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 26using sync_driver::DeviceInfo; 27namespace extensions { 28 29namespace { 30void 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 42SignedInDevicesChangeObserver::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 52SignedInDevicesChangeObserver::~SignedInDevicesChangeObserver() { 53 ProfileSyncService* pss = ProfileSyncServiceFactory::GetForProfile(profile_); 54 if (pss && pss->GetDeviceInfoTracker()) { 55 pss->GetDeviceInfoTracker()->RemoveObserver(this); 56 } 57} 58 59void 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 88static base::LazyInstance< 89 BrowserContextKeyedAPIFactory<SignedInDevicesManager> > g_factory = 90 LAZY_INSTANCE_INITIALIZER; 91 92// static 93BrowserContextKeyedAPIFactory<SignedInDevicesManager>* 94SignedInDevicesManager::GetFactoryInstance() { 95 return g_factory.Pointer(); 96} 97 98SignedInDevicesManager::SignedInDevicesManager() 99 : profile_(NULL), extension_registry_observer_(this) { 100} 101 102SignedInDevicesManager::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 116SignedInDevicesManager::~SignedInDevicesManager() {} 117 118void 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 135void SignedInDevicesManager::OnListenerRemoved( 136 const EventListenerInfo& details) { 137 RemoveChangeObserverForExtension(details.extension_id); 138} 139 140void 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 153void 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