Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / 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 "chrome/browser/extensions/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 "chrome/browser/browser_process.h"
16 #include "chrome/browser/extensions/api/system_storage/storage_info_provider.h"
17 #include "chrome/browser/extensions/event_router_forwarder.h"
18 #include "chrome/browser/storage_monitor/removable_storage_observer.h"
19 #include "chrome/browser/storage_monitor/storage_info.h"
20 #include "chrome/browser/storage_monitor/storage_monitor.h"
21 #include "chrome/common/extensions/api/system_display.h"
22 #include "chrome/common/extensions/api/system_storage.h"
23 #include "ui/gfx/display_observer.h"
24
25 #if defined(USE_ASH)
26 #include "ash/shell.h"
27 #include "ui/gfx/screen.h"
28 #endif
29
30 namespace extensions {
31
32 using api::system_storage::StorageUnitInfo;
33 using content::BrowserThread;
34
35 namespace system_display = api::system_display;
36 namespace system_storage = api::system_storage;
37
38 namespace {
39
40 #if defined(USE_ASH)
41 bool IsDisplayChangedEvent(const std::string& event_name) {
42   return event_name == system_display::OnDisplayChanged::kEventName;
43 }
44 #endif
45
46 bool IsSystemStorageEvent(const std::string& event_name) {
47   return (event_name == system_storage::OnAttached::kEventName ||
48           event_name == system_storage::OnDetached::kEventName);
49 }
50
51 // Event router for systemInfo API. It is a singleton instance shared by
52 // multiple profiles.
53 class SystemInfoEventRouter : public gfx::DisplayObserver,
54                               public RemovableStorageObserver {
55  public:
56   static SystemInfoEventRouter* GetInstance();
57
58   SystemInfoEventRouter();
59   virtual ~SystemInfoEventRouter();
60
61   // Add/remove event listener for the |event_name| event.
62   void AddEventListener(const std::string& event_name);
63   void RemoveEventListener(const std::string& event_name);
64
65  private:
66   // gfx::DisplayObserver:
67   virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE;
68   virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE;
69   virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE;
70
71   // RemovableStorageObserver implementation.
72   virtual void OnRemovableStorageAttached(const StorageInfo& info) OVERRIDE;
73   virtual void OnRemovableStorageDetached(const StorageInfo& info) OVERRIDE;
74
75   // Called from any thread to dispatch the systemInfo event to all extension
76   // processes cross multiple profiles.
77   void DispatchEvent(const std::string& event_name,
78                      scoped_ptr<base::ListValue> args);
79
80   // Called to dispatch the systemInfo.display.onDisplayChanged event.
81   void OnDisplayChanged();
82
83   // Used to record the event names being watched.
84   std::multiset<std::string> watching_event_set_;
85
86   bool has_storage_monitor_observer_;
87
88   DISALLOW_COPY_AND_ASSIGN(SystemInfoEventRouter);
89 };
90
91 static base::LazyInstance<SystemInfoEventRouter>::Leaky
92     g_system_info_event_router = LAZY_INSTANCE_INITIALIZER;
93
94 // static
95 SystemInfoEventRouter* SystemInfoEventRouter::GetInstance() {
96   return g_system_info_event_router.Pointer();
97 }
98
99 SystemInfoEventRouter::SystemInfoEventRouter()
100     : has_storage_monitor_observer_(false) {
101 }
102
103 SystemInfoEventRouter::~SystemInfoEventRouter() {
104   if (has_storage_monitor_observer_) {
105     StorageMonitor* storage_monitor = StorageMonitor::GetInstance();
106     if (storage_monitor)
107       storage_monitor->RemoveObserver(this);
108   }
109 }
110
111 void SystemInfoEventRouter::AddEventListener(const std::string& event_name) {
112   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
113
114   watching_event_set_.insert(event_name);
115   if (watching_event_set_.count(event_name) > 1)
116     return;
117
118   // For systemInfo.display event.
119 #if defined(USE_ASH)
120   if (IsDisplayChangedEvent(event_name))
121     ash::Shell::GetScreen()->AddObserver(this);
122 #endif
123
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);
129     }
130   }
131 }
132
133 void SystemInfoEventRouter::RemoveEventListener(const std::string& event_name) {
134   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
135
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;
142   }
143
144 #if defined(USE_ASH)
145   if (IsDisplayChangedEvent(event_name))
146     ash::Shell::GetScreen()->RemoveObserver(this);
147 #endif
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 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 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::OnDisplayBoundsChanged(
182     const gfx::Display& display) {
183   OnDisplayChanged();
184 }
185
186 void SystemInfoEventRouter::OnDisplayAdded(const gfx::Display& new_display) {
187   OnDisplayChanged();
188 }
189
190 void SystemInfoEventRouter::OnDisplayRemoved(const gfx::Display& old_display) {
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   g_browser_process->extension_event_router_forwarder()->
202       BroadcastEventToRenderers(event_name, args.Pass(), GURL());
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<ProfileKeyedAPIFactory<SystemInfoAPI> >
216     g_factory = LAZY_INSTANCE_INITIALIZER;
217
218 // static
219 ProfileKeyedAPIFactory<SystemInfoAPI>* SystemInfoAPI::GetFactoryInstance() {
220   return g_factory.Pointer();
221 }
222
223 SystemInfoAPI::SystemInfoAPI(Profile* profile) : profile_(profile) {
224   EventRouter* router = ExtensionSystem::Get(profile_)->event_router();
225   router->RegisterObserver(this, system_storage::OnAttached::kEventName);
226   router->RegisterObserver(this, system_storage::OnDetached::kEventName);
227   router->RegisterObserver(this, system_display::OnDisplayChanged::kEventName);
228 }
229
230 SystemInfoAPI::~SystemInfoAPI() {
231 }
232
233 void SystemInfoAPI::Shutdown() {
234   ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this);
235 }
236
237 void SystemInfoAPI::OnListenerAdded(const EventListenerInfo& details) {
238   if (IsSystemStorageEvent(details.event_name)) {
239     StorageMonitor::GetInstance()->EnsureInitialized(
240         base::Bind(&AddEventListener, details.event_name));
241   } else {
242     AddEventListener(details.event_name);
243   }
244 }
245
246 void SystemInfoAPI::OnListenerRemoved(const EventListenerInfo& details) {
247   if (IsSystemStorageEvent(details.event_name)) {
248     StorageMonitor::GetInstance()->EnsureInitialized(
249         base::Bind(&RemoveEventListener, details.event_name));
250   } else {
251     RemoveEventListener(details.event_name);
252   }
253 }
254
255 }  // namespace extensions