• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
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 && pss->GetDeviceInfoTracker()) {
48     pss->GetDeviceInfoTracker()->AddObserver(this);
49   }
50 }
51 
~SignedInDevicesChangeObserver()52 SignedInDevicesChangeObserver::~SignedInDevicesChangeObserver() {
53   ProfileSyncService* pss = ProfileSyncServiceFactory::GetForProfile(profile_);
54   if (pss && pss->GetDeviceInfoTracker()) {
55     pss->GetDeviceInfoTracker()->RemoveObserver(this);
56   }
57 }
58 
OnDeviceInfoChange()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>*
GetFactoryInstance()94 SignedInDevicesManager::GetFactoryInstance() {
95   return g_factory.Pointer();
96 }
97 
SignedInDevicesManager()98 SignedInDevicesManager::SignedInDevicesManager()
99     : profile_(NULL), extension_registry_observer_(this) {
100 }
101 
SignedInDevicesManager(content::BrowserContext * context)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 
~SignedInDevicesManager()116 SignedInDevicesManager::~SignedInDevicesManager() {}
117 
OnListenerAdded(const EventListenerInfo & details)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 
OnListenerRemoved(const EventListenerInfo & details)135 void SignedInDevicesManager::OnListenerRemoved(
136     const EventListenerInfo& details) {
137   RemoveChangeObserverForExtension(details.extension_id);
138 }
139 
RemoveChangeObserverForExtension(const std::string & extension_id)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 
OnExtensionUnloaded(content::BrowserContext * browser_context,const Extension * extension,UnloadedExtensionInfo::Reason reason)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