1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.h" 6 7 #include <string> 8 #include <vector> 9 10 #include "base/lazy_instance.h" 11 #include "base/memory/linked_ptr.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_vector.h" 14 #include "base/values.h" 15 #include "chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h" 16 #include "chrome/browser/extensions/extension_service.h" 17 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/sync/glue/device_info.h" 19 #include "chrome/browser/sync/profile_sync_service.h" 20 #include "chrome/browser/sync/profile_sync_service_factory.h" 21 #include "chrome/common/extensions/api/signed_in_devices.h" 22 #include "extensions/browser/event_router.h" 23 #include "extensions/browser/extension_registry.h" 24 #include "extensions/common/extension.h" 25 26 using browser_sync::DeviceInfo; 27 namespace extensions { 28 29 namespace { 30 void FillDeviceInfo(const DeviceInfo& device_info, 31 api::signed_in_devices::DeviceInfo* api_device_info) { 32 api_device_info->id = device_info.public_id(); 33 api_device_info->name = device_info.client_name(); 34 api_device_info->os = api::signed_in_devices::ParseOS( 35 device_info.GetOSString()); 36 api_device_info->type = api::signed_in_devices::ParseDeviceType( 37 device_info.GetDeviceTypeString()); 38 api_device_info->chrome_version = device_info.chrome_version(); 39 } 40 } // namespace 41 42 SignedInDevicesChangeObserver::SignedInDevicesChangeObserver( 43 const std::string& extension_id, 44 Profile* profile) : extension_id_(extension_id), 45 profile_(profile) { 46 ProfileSyncService* pss = ProfileSyncServiceFactory::GetForProfile(profile_); 47 if (pss) { 48 pss->AddObserverForDeviceInfoChange(this); 49 } 50 } 51 52 SignedInDevicesChangeObserver::~SignedInDevicesChangeObserver() { 53 ProfileSyncService* pss = ProfileSyncServiceFactory::GetForProfile(profile_); 54 if (pss) { 55 pss->RemoveObserverForDeviceInfoChange(this); 56 } 57 58 } 59 60 void SignedInDevicesChangeObserver::OnDeviceInfoChange() { 61 // There is a change in the list of devices. Get all devices and send them to 62 // the listener. 63 ScopedVector<DeviceInfo> devices = GetAllSignedInDevices(extension_id_, 64 profile_); 65 66 std::vector<linked_ptr<api::signed_in_devices::DeviceInfo> > args; 67 68 for (ScopedVector<DeviceInfo>::const_iterator it = devices.begin(); 69 it != devices.end(); 70 ++it) { 71 linked_ptr<api::signed_in_devices::DeviceInfo> api_device = 72 make_linked_ptr(new api::signed_in_devices::DeviceInfo); 73 FillDeviceInfo(*(*it), api_device.get()); 74 args.push_back(api_device); 75 } 76 77 scoped_ptr<base::ListValue> result = 78 api::signed_in_devices::OnDeviceInfoChange::Create(args); 79 scoped_ptr<Event> event(new Event( 80 api::signed_in_devices::OnDeviceInfoChange::kEventName, 81 result.Pass())); 82 83 event->restrict_to_browser_context = profile_; 84 85 EventRouter::Get(profile_)->DispatchEventToExtension( 86 extension_id_, event.Pass()); 87 } 88 89 static base::LazyInstance< 90 BrowserContextKeyedAPIFactory<SignedInDevicesManager> > g_factory = 91 LAZY_INSTANCE_INITIALIZER; 92 93 // static 94 BrowserContextKeyedAPIFactory<SignedInDevicesManager>* 95 SignedInDevicesManager::GetFactoryInstance() { 96 return g_factory.Pointer(); 97 } 98 99 SignedInDevicesManager::SignedInDevicesManager() 100 : profile_(NULL), extension_registry_observer_(this) { 101 } 102 103 SignedInDevicesManager::SignedInDevicesManager(content::BrowserContext* context) 104 : profile_(Profile::FromBrowserContext(context)), 105 extension_registry_observer_(this) { 106 extensions::EventRouter* router = extensions::EventRouter::Get(profile_); 107 if (router) { 108 router->RegisterObserver( 109 this, api::signed_in_devices::OnDeviceInfoChange::kEventName); 110 } 111 112 // Register for unload event so we could clear all our listeners when 113 // extensions have unloaded. 114 extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); 115 } 116 117 SignedInDevicesManager::~SignedInDevicesManager() {} 118 119 void SignedInDevicesManager::OnListenerAdded( 120 const EventListenerInfo& details) { 121 for (ScopedVector<SignedInDevicesChangeObserver>::const_iterator it = 122 change_observers_.begin(); 123 it != change_observers_.end(); 124 ++it) { 125 if ((*it)->extension_id() == details.extension_id) { 126 DCHECK(false) <<"OnListenerAded fired twice for same extension"; 127 return; 128 } 129 } 130 131 change_observers_.push_back(new SignedInDevicesChangeObserver( 132 details.extension_id, 133 profile_)); 134 } 135 136 void SignedInDevicesManager::OnListenerRemoved( 137 const EventListenerInfo& details) { 138 RemoveChangeObserverForExtension(details.extension_id); 139 } 140 141 void SignedInDevicesManager::RemoveChangeObserverForExtension( 142 const std::string& extension_id) { 143 for (ScopedVector<SignedInDevicesChangeObserver>::iterator it = 144 change_observers_.begin(); 145 it != change_observers_.end(); 146 ++it) { 147 if ((*it)->extension_id() == extension_id) { 148 change_observers_.erase(it); 149 return; 150 } 151 } 152 } 153 154 void SignedInDevicesManager::OnExtensionUnloaded( 155 content::BrowserContext* browser_context, 156 const Extension* extension, 157 UnloadedExtensionInfo::Reason reason) { 158 RemoveChangeObserverForExtension(extension->id()); 159 } 160 161 } // namespace extensions 162