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 {
FillDeviceInfo(const DeviceInfo & device_info,api::signed_in_devices::DeviceInfo * api_device_info)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
SignedInDevicesChangeObserver(const std::string & extension_id,Profile * profile)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
~SignedInDevicesChangeObserver()52 SignedInDevicesChangeObserver::~SignedInDevicesChangeObserver() {
53 ProfileSyncService* pss = ProfileSyncServiceFactory::GetForProfile(profile_);
54 if (pss) {
55 pss->RemoveObserverForDeviceInfoChange(this);
56 }
57
58 }
59
OnDeviceInfoChange()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>*
GetFactoryInstance()95 SignedInDevicesManager::GetFactoryInstance() {
96 return g_factory.Pointer();
97 }
98
SignedInDevicesManager()99 SignedInDevicesManager::SignedInDevicesManager()
100 : profile_(NULL), extension_registry_observer_(this) {
101 }
102
SignedInDevicesManager(content::BrowserContext * context)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
~SignedInDevicesManager()117 SignedInDevicesManager::~SignedInDevicesManager() {}
118
OnListenerAdded(const EventListenerInfo & details)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
OnListenerRemoved(const EventListenerInfo & details)136 void SignedInDevicesManager::OnListenerRemoved(
137 const EventListenerInfo& details) {
138 RemoveChangeObserverForExtension(details.extension_id);
139 }
140
RemoveChangeObserverForExtension(const std::string & extension_id)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
OnExtensionUnloaded(content::BrowserContext * browser_context,const Extension * extension,UnloadedExtensionInfo::Reason reason)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