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.
5 #include "chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.h"
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/chrome_notification_types.h"
16 #include "chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h"
17 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/sync/glue/device_info.h"
20 #include "chrome/browser/sync/profile_sync_service.h"
21 #include "chrome/browser/sync/profile_sync_service_factory.h"
22 #include "chrome/common/extensions/api/signed_in_devices.h"
23 #include "content/public/browser/notification_details.h"
24 #include "content/public/browser/notification_observer.h"
25 #include "content/public/browser/notification_registrar.h"
26 #include "content/public/browser/notification_service.h"
27 #include "content/public/browser/notification_source.h"
28 #include "extensions/browser/event_router.h"
29 #include "extensions/common/extension.h"
31 using browser_sync::DeviceInfo
;
32 namespace extensions
{
35 void FillDeviceInfo(const DeviceInfo
& device_info
,
36 api::signed_in_devices::DeviceInfo
* api_device_info
) {
37 api_device_info
->id
= device_info
.public_id();
38 api_device_info
->name
= device_info
.client_name();
39 api_device_info
->os
= api::signed_in_devices::ParseOS(
40 device_info
.GetOSString());
41 api_device_info
->type
= api::signed_in_devices::ParseDeviceType(
42 device_info
.GetDeviceTypeString());
43 api_device_info
->chrome_version
= device_info
.chrome_version();
47 SignedInDevicesChangeObserver::SignedInDevicesChangeObserver(
48 const std::string
& extension_id
,
49 Profile
* profile
) : extension_id_(extension_id
),
51 ProfileSyncService
* pss
= ProfileSyncServiceFactory::GetForProfile(profile_
);
53 pss
->AddObserverForDeviceInfoChange(this);
57 SignedInDevicesChangeObserver::~SignedInDevicesChangeObserver() {
58 ProfileSyncService
* pss
= ProfileSyncServiceFactory::GetForProfile(profile_
);
60 pss
->RemoveObserverForDeviceInfoChange(this);
65 void SignedInDevicesChangeObserver::OnDeviceInfoChange() {
66 // There is a change in the list of devices. Get all devices and send them to
68 ScopedVector
<DeviceInfo
> devices
= GetAllSignedInDevices(extension_id_
,
71 std::vector
<linked_ptr
<api::signed_in_devices::DeviceInfo
> > args
;
73 for (ScopedVector
<DeviceInfo
>::const_iterator it
= devices
.begin();
76 linked_ptr
<api::signed_in_devices::DeviceInfo
> api_device
=
77 make_linked_ptr(new api::signed_in_devices::DeviceInfo
);
78 FillDeviceInfo(*(*it
), api_device
.get());
79 args
.push_back(api_device
);
82 scoped_ptr
<base::ListValue
> result
=
83 api::signed_in_devices::OnDeviceInfoChange::Create(args
);
84 scoped_ptr
<Event
> event(new Event(
85 api::signed_in_devices::OnDeviceInfoChange::kEventName
,
88 event
->restrict_to_browser_context
= profile_
;
90 EventRouter::Get(profile_
)->DispatchEventToExtension(
91 extension_id_
, event
.Pass());
94 static base::LazyInstance
<
95 BrowserContextKeyedAPIFactory
<SignedInDevicesManager
> > g_factory
=
96 LAZY_INSTANCE_INITIALIZER
;
99 BrowserContextKeyedAPIFactory
<SignedInDevicesManager
>*
100 SignedInDevicesManager::GetFactoryInstance() {
101 return g_factory
.Pointer();
104 SignedInDevicesManager::SignedInDevicesManager()
107 SignedInDevicesManager::SignedInDevicesManager(content::BrowserContext
* context
)
108 : profile_(Profile::FromBrowserContext(context
)) {
109 extensions::EventRouter
* router
= extensions::EventRouter::Get(profile_
);
111 router
->RegisterObserver(
112 this, api::signed_in_devices::OnDeviceInfoChange::kEventName
);
115 // Register for unload event so we could clear all our listeners when
116 // extensions have unloaded.
117 registrar_
.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED
,
118 content::Source
<Profile
>(profile_
->GetOriginalProfile()));
121 SignedInDevicesManager::~SignedInDevicesManager() {}
123 void SignedInDevicesManager::OnListenerAdded(
124 const EventListenerInfo
& details
) {
125 for (ScopedVector
<SignedInDevicesChangeObserver
>::const_iterator it
=
126 change_observers_
.begin();
127 it
!= change_observers_
.end();
129 if ((*it
)->extension_id() == details
.extension_id
) {
130 DCHECK(false) <<"OnListenerAded fired twice for same extension";
135 change_observers_
.push_back(new SignedInDevicesChangeObserver(
136 details
.extension_id
,
140 void SignedInDevicesManager::OnListenerRemoved(
141 const EventListenerInfo
& details
) {
142 RemoveChangeObserverForExtension(details
.extension_id
);
146 void SignedInDevicesManager::RemoveChangeObserverForExtension(
147 const std::string
& extension_id
) {
148 for (ScopedVector
<SignedInDevicesChangeObserver
>::iterator it
=
149 change_observers_
.begin();
150 it
!= change_observers_
.end();
152 if ((*it
)->extension_id() == extension_id
) {
153 change_observers_
.erase(it
);
159 void SignedInDevicesManager::Observe(
161 const content::NotificationSource
& source
,
162 const content::NotificationDetails
& details
) {
163 DCHECK_EQ(type
, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED
);
164 UnloadedExtensionInfo
* reason
=
165 content::Details
<UnloadedExtensionInfo
>(details
).ptr();
166 RemoveChangeObserverForExtension(reason
->extension
->id());
169 } // namespace extensions