Home | History | Annotate | Download | only in system_info
      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 "extensions/browser/api/system_info/system_info_api.h"
      6 
      7 #include <set>
      8 
      9 #include "base/bind.h"
     10 #include "base/lazy_instance.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/memory/singleton.h"
     13 #include "base/strings/string_util.h"
     14 #include "base/values.h"
     15 #include "components/storage_monitor/removable_storage_observer.h"
     16 #include "components/storage_monitor/storage_info.h"
     17 #include "components/storage_monitor/storage_monitor.h"
     18 #include "content/public/browser/browser_thread.h"
     19 #include "extensions/browser/api/system_display/display_info_provider.h"
     20 #include "extensions/browser/api/system_storage/storage_info_provider.h"
     21 #include "extensions/browser/extensions_browser_client.h"
     22 #include "extensions/common/api/system_display.h"
     23 #include "extensions/common/api/system_storage.h"
     24 #include "ui/gfx/display_observer.h"
     25 #include "ui/gfx/screen.h"
     26 
     27 namespace extensions {
     28 
     29 using core_api::system_storage::StorageUnitInfo;
     30 using content::BrowserThread;
     31 using storage_monitor::StorageMonitor;
     32 
     33 namespace system_display = core_api::system_display;
     34 namespace system_storage = core_api::system_storage;
     35 
     36 namespace {
     37 
     38 bool IsDisplayChangedEvent(const std::string& event_name) {
     39   return event_name == system_display::OnDisplayChanged::kEventName;
     40 }
     41 
     42 bool IsSystemStorageEvent(const std::string& event_name) {
     43   return (event_name == system_storage::OnAttached::kEventName ||
     44           event_name == system_storage::OnDetached::kEventName);
     45 }
     46 
     47 // Event router for systemInfo API. It is a singleton instance shared by
     48 // multiple profiles.
     49 class SystemInfoEventRouter : public gfx::DisplayObserver,
     50                               public storage_monitor::RemovableStorageObserver {
     51  public:
     52   static SystemInfoEventRouter* GetInstance();
     53 
     54   SystemInfoEventRouter();
     55   virtual ~SystemInfoEventRouter();
     56 
     57   // Add/remove event listener for the |event_name| event.
     58   void AddEventListener(const std::string& event_name);
     59   void RemoveEventListener(const std::string& event_name);
     60 
     61  private:
     62   // gfx::DisplayObserver:
     63   virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE;
     64   virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE;
     65   virtual void OnDisplayMetricsChanged(const gfx::Display& display,
     66                                        uint32_t metrics) OVERRIDE;
     67 
     68   // RemovableStorageObserver implementation.
     69   virtual void OnRemovableStorageAttached(
     70       const storage_monitor::StorageInfo& info) OVERRIDE;
     71   virtual void OnRemovableStorageDetached(
     72       const storage_monitor::StorageInfo& info) OVERRIDE;
     73 
     74   // Called from any thread to dispatch the systemInfo event to all extension
     75   // processes cross multiple profiles.
     76   void DispatchEvent(const std::string& event_name,
     77                      scoped_ptr<base::ListValue> args);
     78 
     79   // Called to dispatch the systemInfo.display.onDisplayChanged event.
     80   void OnDisplayChanged();
     81 
     82   // Used to record the event names being watched.
     83   std::multiset<std::string> watching_event_set_;
     84 
     85   bool has_storage_monitor_observer_;
     86 
     87   DISALLOW_COPY_AND_ASSIGN(SystemInfoEventRouter);
     88 };
     89 
     90 static base::LazyInstance<SystemInfoEventRouter>::Leaky
     91     g_system_info_event_router = LAZY_INSTANCE_INITIALIZER;
     92 
     93 // static
     94 SystemInfoEventRouter* SystemInfoEventRouter::GetInstance() {
     95   return g_system_info_event_router.Pointer();
     96 }
     97 
     98 SystemInfoEventRouter::SystemInfoEventRouter()
     99     : has_storage_monitor_observer_(false) {
    100 }
    101 
    102 SystemInfoEventRouter::~SystemInfoEventRouter() {
    103   if (has_storage_monitor_observer_) {
    104     StorageMonitor* storage_monitor = StorageMonitor::GetInstance();
    105     if (storage_monitor)
    106       storage_monitor->RemoveObserver(this);
    107   }
    108 }
    109 
    110 void SystemInfoEventRouter::AddEventListener(const std::string& event_name) {
    111   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    112 
    113   watching_event_set_.insert(event_name);
    114   if (watching_event_set_.count(event_name) > 1)
    115     return;
    116 
    117   if (IsDisplayChangedEvent(event_name)) {
    118     gfx::Screen* screen = DisplayInfoProvider::Get()->GetActiveScreen();
    119     if (screen)
    120       screen->AddObserver(this);
    121   }
    122 
    123   if (IsSystemStorageEvent(event_name)) {
    124     if (!has_storage_monitor_observer_) {
    125       has_storage_monitor_observer_ = true;
    126       DCHECK(StorageMonitor::GetInstance()->IsInitialized());
    127       StorageMonitor::GetInstance()->AddObserver(this);
    128     }
    129   }
    130 }
    131 
    132 void SystemInfoEventRouter::RemoveEventListener(const std::string& event_name) {
    133   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    134 
    135   std::multiset<std::string>::iterator it =
    136       watching_event_set_.find(event_name);
    137   if (it != watching_event_set_.end()) {
    138     watching_event_set_.erase(it);
    139     if (watching_event_set_.count(event_name) > 0)
    140       return;
    141   }
    142 
    143   if (IsDisplayChangedEvent(event_name)) {
    144     gfx::Screen* screen = DisplayInfoProvider::Get()->GetActiveScreen();
    145     if (screen)
    146       screen->RemoveObserver(this);
    147   }
    148 
    149   if (IsSystemStorageEvent(event_name)) {
    150     const std::string& other_event_name =
    151         (event_name == system_storage::OnDetached::kEventName)
    152             ? system_storage::OnAttached::kEventName
    153             : system_storage::OnDetached::kEventName;
    154     if (watching_event_set_.count(other_event_name) == 0) {
    155       StorageMonitor::GetInstance()->RemoveObserver(this);
    156       has_storage_monitor_observer_ = false;
    157     }
    158   }
    159 }
    160 
    161 void SystemInfoEventRouter::OnRemovableStorageAttached(
    162     const storage_monitor::StorageInfo& info) {
    163   StorageUnitInfo unit;
    164   systeminfo::BuildStorageUnitInfo(info, &unit);
    165   scoped_ptr<base::ListValue> args(new base::ListValue);
    166   args->Append(unit.ToValue().release());
    167   DispatchEvent(system_storage::OnAttached::kEventName, args.Pass());
    168 }
    169 
    170 void SystemInfoEventRouter::OnRemovableStorageDetached(
    171     const storage_monitor::StorageInfo& info) {
    172   scoped_ptr<base::ListValue> args(new base::ListValue);
    173   std::string transient_id =
    174       StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
    175           info.device_id());
    176   args->AppendString(transient_id);
    177 
    178   DispatchEvent(system_storage::OnDetached::kEventName, args.Pass());
    179 }
    180 
    181 void SystemInfoEventRouter::OnDisplayAdded(const gfx::Display& new_display) {
    182   OnDisplayChanged();
    183 }
    184 
    185 void SystemInfoEventRouter::OnDisplayRemoved(const gfx::Display& old_display) {
    186   OnDisplayChanged();
    187 }
    188 
    189 void SystemInfoEventRouter::OnDisplayMetricsChanged(const gfx::Display& display,
    190                                                     uint32_t metrics) {
    191   OnDisplayChanged();
    192 }
    193 
    194 void SystemInfoEventRouter::OnDisplayChanged() {
    195   scoped_ptr<base::ListValue> args(new base::ListValue());
    196   DispatchEvent(system_display::OnDisplayChanged::kEventName, args.Pass());
    197 }
    198 
    199 void SystemInfoEventRouter::DispatchEvent(const std::string& event_name,
    200                                           scoped_ptr<base::ListValue> args) {
    201   ExtensionsBrowserClient::Get()->BroadcastEventToRenderers(event_name,
    202                                                             args.Pass());
    203 }
    204 
    205 void AddEventListener(const std::string& event_name) {
    206   SystemInfoEventRouter::GetInstance()->AddEventListener(event_name);
    207 }
    208 
    209 void RemoveEventListener(const std::string& event_name) {
    210   SystemInfoEventRouter::GetInstance()->RemoveEventListener(event_name);
    211 }
    212 
    213 }  // namespace
    214 
    215 static base::LazyInstance<BrowserContextKeyedAPIFactory<SystemInfoAPI> >
    216     g_factory = LAZY_INSTANCE_INITIALIZER;
    217 
    218 // static
    219 BrowserContextKeyedAPIFactory<SystemInfoAPI>*
    220 SystemInfoAPI::GetFactoryInstance() {
    221   return g_factory.Pointer();
    222 }
    223 
    224 SystemInfoAPI::SystemInfoAPI(content::BrowserContext* context)
    225     : browser_context_(context) {
    226   EventRouter* router = EventRouter::Get(browser_context_);
    227   router->RegisterObserver(this, system_storage::OnAttached::kEventName);
    228   router->RegisterObserver(this, system_storage::OnDetached::kEventName);
    229   router->RegisterObserver(this, system_display::OnDisplayChanged::kEventName);
    230 }
    231 
    232 SystemInfoAPI::~SystemInfoAPI() {
    233 }
    234 
    235 void SystemInfoAPI::Shutdown() {
    236   EventRouter::Get(browser_context_)->UnregisterObserver(this);
    237 }
    238 
    239 void SystemInfoAPI::OnListenerAdded(const EventListenerInfo& details) {
    240   if (IsSystemStorageEvent(details.event_name)) {
    241     StorageMonitor::GetInstance()->EnsureInitialized(
    242         base::Bind(&AddEventListener, details.event_name));
    243   } else {
    244     AddEventListener(details.event_name);
    245   }
    246 }
    247 
    248 void SystemInfoAPI::OnListenerRemoved(const EventListenerInfo& details) {
    249   if (IsSystemStorageEvent(details.event_name)) {
    250     StorageMonitor::GetInstance()->EnsureInitialized(
    251         base::Bind(&RemoveEventListener, details.event_name));
    252   } else {
    253     RemoveEventListener(details.event_name);
    254   }
    255 }
    256 
    257 }  // namespace extensions
    258