Roll src/third_party/WebKit a3b4a2e:7441784 (svn 202551:202552)
[chromium-blink-merge.git] / extensions / browser / api / system_info / system_info_api.cc
bloba7c7facef0df38de1f75984ad6fdbf8567c565da
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 "extensions/browser/api/system_info/system_info_api.h"
7 #include <set>
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"
27 namespace extensions {
29 using api::system_storage::StorageUnitInfo;
30 using content::BrowserThread;
31 using storage_monitor::StorageMonitor;
33 namespace system_display = api::system_display;
34 namespace system_storage = api::system_storage;
36 namespace {
38 bool IsDisplayChangedEvent(const std::string& event_name) {
39 return event_name == system_display::OnDisplayChanged::kEventName;
42 bool IsSystemStorageEvent(const std::string& event_name) {
43 return (event_name == system_storage::OnAttached::kEventName ||
44 event_name == system_storage::OnDetached::kEventName);
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();
54 SystemInfoEventRouter();
55 ~SystemInfoEventRouter() override;
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);
61 private:
62 // gfx::DisplayObserver:
63 void OnDisplayAdded(const gfx::Display& new_display) override;
64 void OnDisplayRemoved(const gfx::Display& old_display) override;
65 void OnDisplayMetricsChanged(const gfx::Display& display,
66 uint32_t metrics) override;
68 // RemovableStorageObserver implementation.
69 void OnRemovableStorageAttached(
70 const storage_monitor::StorageInfo& info) override;
71 void OnRemovableStorageDetached(
72 const storage_monitor::StorageInfo& info) override;
74 // Called from any thread to dispatch the systemInfo event to all extension
75 // processes cross multiple profiles.
76 void DispatchEvent(events::HistogramValue histogram_value,
77 const std::string& event_name,
78 scoped_ptr<base::ListValue> args);
80 // Called to dispatch the systemInfo.display.onDisplayChanged event.
81 void OnDisplayChanged();
83 // Used to record the event names being watched.
84 std::multiset<std::string> watching_event_set_;
86 bool has_storage_monitor_observer_;
88 DISALLOW_COPY_AND_ASSIGN(SystemInfoEventRouter);
91 static base::LazyInstance<SystemInfoEventRouter>::Leaky
92 g_system_info_event_router = LAZY_INSTANCE_INITIALIZER;
94 // static
95 SystemInfoEventRouter* SystemInfoEventRouter::GetInstance() {
96 return g_system_info_event_router.Pointer();
99 SystemInfoEventRouter::SystemInfoEventRouter()
100 : has_storage_monitor_observer_(false) {
103 SystemInfoEventRouter::~SystemInfoEventRouter() {
104 if (has_storage_monitor_observer_) {
105 StorageMonitor* storage_monitor = StorageMonitor::GetInstance();
106 if (storage_monitor)
107 storage_monitor->RemoveObserver(this);
111 void SystemInfoEventRouter::AddEventListener(const std::string& event_name) {
112 DCHECK_CURRENTLY_ON(BrowserThread::UI);
114 watching_event_set_.insert(event_name);
115 if (watching_event_set_.count(event_name) > 1)
116 return;
118 if (IsDisplayChangedEvent(event_name)) {
119 gfx::Screen* screen = DisplayInfoProvider::Get()->GetActiveScreen();
120 if (screen)
121 screen->AddObserver(this);
124 if (IsSystemStorageEvent(event_name)) {
125 if (!has_storage_monitor_observer_) {
126 has_storage_monitor_observer_ = true;
127 DCHECK(StorageMonitor::GetInstance()->IsInitialized());
128 StorageMonitor::GetInstance()->AddObserver(this);
133 void SystemInfoEventRouter::RemoveEventListener(const std::string& event_name) {
134 DCHECK_CURRENTLY_ON(BrowserThread::UI);
136 std::multiset<std::string>::iterator it =
137 watching_event_set_.find(event_name);
138 if (it != watching_event_set_.end()) {
139 watching_event_set_.erase(it);
140 if (watching_event_set_.count(event_name) > 0)
141 return;
144 if (IsDisplayChangedEvent(event_name)) {
145 gfx::Screen* screen = DisplayInfoProvider::Get()->GetActiveScreen();
146 if (screen)
147 screen->RemoveObserver(this);
150 if (IsSystemStorageEvent(event_name)) {
151 const std::string& other_event_name =
152 (event_name == system_storage::OnDetached::kEventName)
153 ? system_storage::OnAttached::kEventName
154 : system_storage::OnDetached::kEventName;
155 if (watching_event_set_.count(other_event_name) == 0) {
156 StorageMonitor::GetInstance()->RemoveObserver(this);
157 has_storage_monitor_observer_ = false;
162 void SystemInfoEventRouter::OnRemovableStorageAttached(
163 const storage_monitor::StorageInfo& info) {
164 StorageUnitInfo unit;
165 systeminfo::BuildStorageUnitInfo(info, &unit);
166 scoped_ptr<base::ListValue> args(new base::ListValue);
167 args->Append(unit.ToValue().release());
168 DispatchEvent(events::SYSTEM_STORAGE_ON_ATTACHED,
169 system_storage::OnAttached::kEventName, args.Pass());
172 void SystemInfoEventRouter::OnRemovableStorageDetached(
173 const storage_monitor::StorageInfo& info) {
174 scoped_ptr<base::ListValue> args(new base::ListValue);
175 std::string transient_id =
176 StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
177 info.device_id());
178 args->AppendString(transient_id);
180 DispatchEvent(events::SYSTEM_STORAGE_ON_DETACHED,
181 system_storage::OnDetached::kEventName, args.Pass());
184 void SystemInfoEventRouter::OnDisplayAdded(const gfx::Display& new_display) {
185 OnDisplayChanged();
188 void SystemInfoEventRouter::OnDisplayRemoved(const gfx::Display& old_display) {
189 OnDisplayChanged();
192 void SystemInfoEventRouter::OnDisplayMetricsChanged(const gfx::Display& display,
193 uint32_t metrics) {
194 OnDisplayChanged();
197 void SystemInfoEventRouter::OnDisplayChanged() {
198 scoped_ptr<base::ListValue> args(new base::ListValue());
199 DispatchEvent(events::SYSTEM_DISPLAY_ON_DISPLAY_CHANGED,
200 system_display::OnDisplayChanged::kEventName, args.Pass());
203 void SystemInfoEventRouter::DispatchEvent(
204 events::HistogramValue histogram_value,
205 const std::string& event_name,
206 scoped_ptr<base::ListValue> args) {
207 ExtensionsBrowserClient::Get()->BroadcastEventToRenderers(
208 histogram_value, event_name, args.Pass());
211 void AddEventListener(const std::string& event_name) {
212 SystemInfoEventRouter::GetInstance()->AddEventListener(event_name);
215 void RemoveEventListener(const std::string& event_name) {
216 SystemInfoEventRouter::GetInstance()->RemoveEventListener(event_name);
219 } // namespace
221 static base::LazyInstance<BrowserContextKeyedAPIFactory<SystemInfoAPI> >
222 g_factory = LAZY_INSTANCE_INITIALIZER;
224 // static
225 BrowserContextKeyedAPIFactory<SystemInfoAPI>*
226 SystemInfoAPI::GetFactoryInstance() {
227 return g_factory.Pointer();
230 SystemInfoAPI::SystemInfoAPI(content::BrowserContext* context)
231 : browser_context_(context) {
232 EventRouter* router = EventRouter::Get(browser_context_);
233 router->RegisterObserver(this, system_storage::OnAttached::kEventName);
234 router->RegisterObserver(this, system_storage::OnDetached::kEventName);
235 router->RegisterObserver(this, system_display::OnDisplayChanged::kEventName);
238 SystemInfoAPI::~SystemInfoAPI() {
241 void SystemInfoAPI::Shutdown() {
242 EventRouter::Get(browser_context_)->UnregisterObserver(this);
245 void SystemInfoAPI::OnListenerAdded(const EventListenerInfo& details) {
246 if (IsSystemStorageEvent(details.event_name)) {
247 StorageMonitor::GetInstance()->EnsureInitialized(
248 base::Bind(&AddEventListener, details.event_name));
249 } else {
250 AddEventListener(details.event_name);
254 void SystemInfoAPI::OnListenerRemoved(const EventListenerInfo& details) {
255 if (IsSystemStorageEvent(details.event_name)) {
256 StorageMonitor::GetInstance()->EnsureInitialized(
257 base::Bind(&RemoveEventListener, details.event_name));
258 } else {
259 RemoveEventListener(details.event_name);
263 } // namespace extensions