blob: 222f50c01505d5c5a862c8e84359f1aca15a1d1c [file] [log] [blame]
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h"
#include <memory>
#include <utility>
#include "base/values.h"
#include "chrome/browser/extensions/api/signed_in_devices/id_mapping_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/device_info_sync_service_factory.h"
#include "chrome/common/extensions/api/signed_in_devices.h"
#include "components/sync_device_info/device_info_sync_service.h"
#include "components/sync_device_info/device_info_tracker.h"
#include "components/sync_device_info/local_device_info_provider.h"
#include "extensions/browser/extension_prefs.h"
using base::DictionaryValue;
using syncer::DeviceInfo;
using syncer::DeviceInfoTracker;
using syncer::LocalDeviceInfoProvider;
namespace extensions {
static const char kPrefStringForIdMapping[] = "id_mapping_dictioanry";
// Gets the dictionary that stores the id mapping. The dictionary is stored
// in the |ExtensionPrefs|.
const base::DictionaryValue* GetIdMappingDictionary(
ExtensionPrefs* extension_prefs,
const std::string& extension_id) {
const base::DictionaryValue* out_value = NULL;
if (!extension_prefs->ReadPrefAsDictionary(
extension_id,
kPrefStringForIdMapping,
&out_value) || out_value == NULL) {
// Looks like this is the first call to get the dictionary. Let us create
// a dictionary and set it in to |extension_prefs|.
std::unique_ptr<base::DictionaryValue> dictionary(
new base::DictionaryValue());
out_value = dictionary.get();
extension_prefs->UpdateExtensionPref(extension_id, kPrefStringForIdMapping,
std::move(dictionary));
}
return out_value;
}
// Helper routine to get all signed in devices. The helper takes in
// the pointers for |DeviceInfoTracker| and |Extensionprefs|. This
// makes it easier to test by passing mock values for these pointers.
std::vector<std::unique_ptr<DeviceInfo>> GetAllSignedInDevices(
const std::string& extension_id,
DeviceInfoTracker* device_tracker,
ExtensionPrefs* extension_prefs) {
DCHECK(device_tracker);
std::vector<std::unique_ptr<DeviceInfo>> devices =
device_tracker->GetAllDeviceInfo();
const base::DictionaryValue* mapping_dictionary = GetIdMappingDictionary(
extension_prefs,
extension_id);
CHECK(mapping_dictionary);
// |mapping_dictionary| is const. So make an editable copy.
std::unique_ptr<base::DictionaryValue> editable_mapping_dictionary(
mapping_dictionary->DeepCopy());
CreateMappingForUnmappedDevices(devices, editable_mapping_dictionary.get());
// Write into |ExtensionPrefs| which will get persisted in disk.
extension_prefs->UpdateExtensionPref(extension_id, kPrefStringForIdMapping,
std::move(editable_mapping_dictionary));
return devices;
}
std::vector<std::unique_ptr<DeviceInfo>> GetAllSignedInDevices(
const std::string& extension_id,
Profile* profile) {
// Get the device tracker and extension prefs pointers
// and call the helper.
DeviceInfoTracker* device_tracker =
DeviceInfoSyncServiceFactory::GetForProfile(profile)
->GetDeviceInfoTracker();
DCHECK(device_tracker);
if (!device_tracker->IsSyncing()) {
// Devices are not sync'ing.
return std::vector<std::unique_ptr<DeviceInfo>>();
}
ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile);
return GetAllSignedInDevices(extension_id, device_tracker, extension_prefs);
}
std::unique_ptr<DeviceInfo> GetLocalDeviceInfo(const std::string& extension_id,
Profile* profile) {
syncer::DeviceInfoSyncService* service =
DeviceInfoSyncServiceFactory::GetForProfile(profile);
if (!service) {
return nullptr;
}
const LocalDeviceInfoProvider* local_device_info_provider =
service->GetLocalDeviceInfoProvider();
DCHECK(local_device_info_provider);
const DeviceInfo* local_device =
local_device_info_provider->GetLocalDeviceInfo();
if (!local_device)
return nullptr;
// TODO(karandeepb): Can't we just return a copy of |local_device|, without
// having to look it up by GUID?
return GetDeviceInfoForClientId(local_device->guid(), extension_id, profile);
}
ExtensionFunction::ResponseAction SignedInDevicesGetFunction::Run() {
std::unique_ptr<api::signed_in_devices::Get::Params> params(
api::signed_in_devices::Get::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
bool is_local = params->is_local.get() ? *params->is_local : false;
Profile* profile = Profile::FromBrowserContext(browser_context());
if (is_local) {
std::unique_ptr<DeviceInfo> device =
GetLocalDeviceInfo(extension_id(), profile);
std::unique_ptr<base::ListValue> result(new base::ListValue());
if (device.get()) {
result->Append(device->ToValue());
}
return RespondNow(OneArgument(std::move(result)));
}
std::vector<std::unique_ptr<DeviceInfo>> devices =
GetAllSignedInDevices(extension_id(), profile);
std::unique_ptr<base::ListValue> result(new base::ListValue());
for (const std::unique_ptr<DeviceInfo>& device : devices)
result->Append(device->ToValue());
return RespondNow(OneArgument(std::move(result)));
}
} // namespace extensions