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/profile_sync_service.h" 19 #include "chrome/browser/sync/profile_sync_service_factory.h" 20 #include "chrome/common/extensions/api/signed_in_devices.h" 21 #include "components/sync_driver/device_info.h" 22 #include "extensions/browser/event_router.h" 23 #include "extensions/browser/extension_registry.h" 24 #include "extensions/common/extension.h" 25 26 using sync_driver::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 && pss->GetDeviceInfoTracker()) { 48 pss->GetDeviceInfoTracker()->AddObserver(this); 49 } 50 } 51 52 SignedInDevicesChangeObserver::~SignedInDevicesChangeObserver() { 53 ProfileSyncService* pss = ProfileSyncServiceFactory::GetForProfile(profile_); 54 if (pss && pss->GetDeviceInfoTracker()) { 55 pss->GetDeviceInfoTracker()->RemoveObserver(this); 56 } 57 } 58 59 void SignedInDevicesChangeObserver::OnDeviceInfoChange() { 60 // There is a change in the list of devices. Get all devices and send them to 61 // the listener. 62 ScopedVector<DeviceInfo> devices = GetAllSignedInDevices(extension_id_, 63 profile_); 64 65 std::vector<linked_ptr<api::signed_in_devices::DeviceInfo> > args; 66 67 for (ScopedVector<DeviceInfo>::const_iterator it = devices.begin(); 68 it != devices.end(); 69 ++it) { 70 linked_ptr<api::signed_in_devices::DeviceInfo> api_device = 71 make_linked_ptr(new api::signed_in_devices::DeviceInfo); 72 FillDeviceInfo(*(*it), api_device.get()); 73 args.push_back(api_device); 74 } 75 76 scoped_ptr<base::ListValue> result = 77 api::signed_in_devices::OnDeviceInfoChange::Create(args); 78 scoped_ptr<Event> event(new Event( 79 api::signed_in_devices::OnDeviceInfoChange::kEventName, 80 result.Pass())); 81 82 event->restrict_to_browser_context = profile_; 83 84 EventRouter::Get(profile_)->DispatchEventToExtension( 85 extension_id_, event.Pass()); 86 } 87 88 static base::LazyInstance< 89 BrowserContextKeyedAPIFactory<SignedInDevicesManager> > g_factory = 90 LAZY_INSTANCE_INITIALIZER; 91 92 // static 93 BrowserContextKeyedAPIFactory<SignedInDevicesManager>* 94 SignedInDevicesManager::GetFactoryInstance() { 95 return g_factory.Pointer(); 96 } 97 98 SignedInDevicesManager::SignedInDevicesManager() 99 : profile_(NULL), extension_registry_observer_(this) { 100 } 101 102 SignedInDevicesManager::SignedInDevicesManager(content::BrowserContext* context) 103 : profile_(Profile::FromBrowserContext(context)), 104 extension_registry_observer_(this) { 105 extensions::EventRouter* router = extensions::EventRouter::Get(profile_); 106 if (router) { 107 router->RegisterObserver( 108 this, api::signed_in_devices::OnDeviceInfoChange::kEventName); 109 } 110 111 // Register for unload event so we could clear all our listeners when 112 // extensions have unloaded. 113 extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); 114 } 115 116 SignedInDevicesManager::~SignedInDevicesManager() {} 117 118 void SignedInDevicesManager::OnListenerAdded( 119 const EventListenerInfo& details) { 120 for (ScopedVector<SignedInDevicesChangeObserver>::const_iterator it = 121 change_observers_.begin(); 122 it != change_observers_.end(); 123 ++it) { 124 if ((*it)->extension_id() == details.extension_id) { 125 DCHECK(false) <<"OnListenerAded fired twice for same extension"; 126 return; 127 } 128 } 129 130 change_observers_.push_back(new SignedInDevicesChangeObserver( 131 details.extension_id, 132 profile_)); 133 } 134 135 void SignedInDevicesManager::OnListenerRemoved( 136 const EventListenerInfo& details) { 137 RemoveChangeObserverForExtension(details.extension_id); 138 } 139 140 void SignedInDevicesManager::RemoveChangeObserverForExtension( 141 const std::string& extension_id) { 142 for (ScopedVector<SignedInDevicesChangeObserver>::iterator it = 143 change_observers_.begin(); 144 it != change_observers_.end(); 145 ++it) { 146 if ((*it)->extension_id() == extension_id) { 147 change_observers_.erase(it); 148 return; 149 } 150 } 151 } 152 153 void SignedInDevicesManager::OnExtensionUnloaded( 154 content::BrowserContext* browser_context, 155 const Extension* extension, 156 UnloadedExtensionInfo::Reason reason) { 157 RemoveChangeObserverForExtension(extension->id()); 158 } 159 160 } // namespace extensions 161