Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / extensions / browser / api / system_info / system_info_api.cc
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