// 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 "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" #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/profile_sync_service_factory.h" #include "chrome/common/extensions/api/signed_in_devices.h" #include "components/browser_sync/browser/profile_sync_service.h" #include "components/sync_driver/device_info_tracker.h" #include "components/sync_driver/local_device_info_provider.h" #include "extensions/browser/extension_prefs.h" using base::DictionaryValue; using sync_driver::DeviceInfo; using sync_driver::DeviceInfoTracker; using sync_driver::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|. scoped_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue()); out_value = dictionary.get(); extension_prefs->UpdateExtensionPref( extension_id, kPrefStringForIdMapping, dictionary.release()); } 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. ScopedVector<DeviceInfo> GetAllSignedInDevices( const std::string& extension_id, DeviceInfoTracker* device_tracker, ExtensionPrefs* extension_prefs) { DCHECK(device_tracker); ScopedVector<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. scoped_ptr<base::DictionaryValue> editable_mapping_dictionary( mapping_dictionary->DeepCopy()); CreateMappingForUnmappedDevices(&(devices.get()), editable_mapping_dictionary.get()); // Write into |ExtensionPrefs| which will get persisted in disk. extension_prefs->UpdateExtensionPref(extension_id, kPrefStringForIdMapping, editable_mapping_dictionary.release()); return devices; } ScopedVector<DeviceInfo> GetAllSignedInDevices( const std::string& extension_id, Profile* profile) { // Get the device tracker and extension prefs pointers // and call the helper. DeviceInfoTracker* device_tracker = ProfileSyncServiceFactory::GetForProfile(profile)->GetDeviceInfoTracker(); DCHECK(device_tracker); if (!device_tracker->IsSyncing()) { // Devices are not sync'ing. return ScopedVector<DeviceInfo>(); } ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile); return GetAllSignedInDevices(extension_id, device_tracker, extension_prefs); } scoped_ptr<DeviceInfo> GetLocalDeviceInfo(const std::string& extension_id, Profile* profile) { ProfileSyncService* pss = ProfileSyncServiceFactory::GetForProfile(profile); if (!pss) { return scoped_ptr<DeviceInfo>(); } LocalDeviceInfoProvider* local_device = pss->GetLocalDeviceInfoProvider(); DCHECK(local_device); std::string guid = local_device->GetLocalSyncCacheGUID(); scoped_ptr<DeviceInfo> device = GetDeviceInfoForClientId(guid, extension_id, profile); return device; } bool SignedInDevicesGetFunction::RunSync() { scoped_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; if (is_local) { scoped_ptr<DeviceInfo> device = GetLocalDeviceInfo(extension_id(), GetProfile()); base::ListValue* result = new base::ListValue(); if (device.get()) { result->Append(device->ToValue()); } SetResult(result); return true; } ScopedVector<DeviceInfo> devices = GetAllSignedInDevices(extension_id(), GetProfile()); scoped_ptr<base::ListValue> result(new base::ListValue()); for (ScopedVector<DeviceInfo>::const_iterator it = devices.begin(); it != devices.end(); ++it) { result->Append((*it)->ToValue()); } SetResult(result.release()); return true; } } // namespace extensions