Home | History | Annotate | Download | only in signed_in_devices
      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