- add sources.
[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/screen_ash.h"
27 #include "ash/shell.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 bool IsDisplayChangedEvent(const std::string& event_name) {
41   return event_name == system_display::OnDisplayChanged::kEventName;
42 }
43
44 // Event router for systemInfo API. It is a singleton instance shared by
45 // multiple profiles.
46 class SystemInfoEventRouter : public gfx::DisplayObserver,
47                               public RemovableStorageObserver {
48  public:
49   static SystemInfoEventRouter* GetInstance();
50
51   SystemInfoEventRouter();
52   virtual ~SystemInfoEventRouter();
53
54   // Add/remove event listener for the |event_name| event.
55   void AddEventListener(const std::string& event_name);
56   void RemoveEventListener(const std::string& event_name);
57
58  private:
59   // gfx::DisplayObserver:
60   virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE;
61   virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE;
62   virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE;
63
64   // RemovableStorageObserver implementation.
65   virtual void OnRemovableStorageAttached(const StorageInfo& info) OVERRIDE;
66   virtual void OnRemovableStorageDetached(const StorageInfo& info) OVERRIDE;
67
68   // Called from any thread to dispatch the systemInfo event to all extension
69   // processes cross multiple profiles.
70   void DispatchEvent(const std::string& event_name,
71       scoped_ptr<base::ListValue> args);
72
73   // Called to dispatch the systemInfo.display.onDisplayChanged event.
74   void OnDisplayChanged();
75
76   // Used to record the event names being watched.
77   std::multiset<std::string> watching_event_set_;
78
79   DISALLOW_COPY_AND_ASSIGN(SystemInfoEventRouter);
80 };
81
82 static base::LazyInstance<SystemInfoEventRouter>::Leaky
83   g_system_info_event_router = LAZY_INSTANCE_INITIALIZER;
84
85 // static
86 SystemInfoEventRouter* SystemInfoEventRouter::GetInstance() {
87   return g_system_info_event_router.Pointer();
88 }
89
90 SystemInfoEventRouter::SystemInfoEventRouter() {
91   StorageMonitor::GetInstance()->AddObserver(this);
92 }
93
94 SystemInfoEventRouter::~SystemInfoEventRouter() {
95   if (StorageMonitor* storage_monitor = StorageMonitor::GetInstance())
96     storage_monitor->RemoveObserver(this);
97 }
98
99 void SystemInfoEventRouter::AddEventListener(const std::string& event_name) {
100   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
101
102   watching_event_set_.insert(event_name);
103   if (watching_event_set_.count(event_name) > 1)
104     return;
105
106   // For systemInfo.display event.
107   if (IsDisplayChangedEvent(event_name)) {
108 #if defined(USE_ASH)
109     ash::Shell::GetScreen()->AddObserver(this);
110 #endif
111   }
112 }
113
114 void SystemInfoEventRouter::RemoveEventListener(
115     const std::string& event_name) {
116   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
117
118   std::multiset<std::string>::iterator it =
119       watching_event_set_.find(event_name);
120   if (it != watching_event_set_.end())
121     watching_event_set_.erase(it);
122
123   if (watching_event_set_.count(event_name) > 0)
124     return;
125
126   if (IsDisplayChangedEvent(event_name)) {
127 #if defined(USE_ASH)
128     ash::Shell::GetScreen()->RemoveObserver(this);
129 #endif
130   }
131 }
132
133 void SystemInfoEventRouter::OnRemovableStorageAttached(
134     const StorageInfo& info) {
135   StorageUnitInfo unit;
136   systeminfo::BuildStorageUnitInfo(info, &unit);
137   scoped_ptr<base::ListValue> args(new base::ListValue);
138   args->Append(unit.ToValue().release());
139   DispatchEvent(system_storage::OnAttached::kEventName, args.Pass());
140 }
141
142 void SystemInfoEventRouter::OnRemovableStorageDetached(
143     const StorageInfo& info) {
144   scoped_ptr<base::ListValue> args(new base::ListValue);
145   args->Append(new base::StringValue(StorageMonitor::GetInstance()->
146                    GetTransientIdForDeviceId(info.device_id())));
147
148   DispatchEvent(system_storage::OnDetached::kEventName, args.Pass());
149 }
150
151 void SystemInfoEventRouter::OnDisplayBoundsChanged(
152     const gfx::Display& display) {
153   OnDisplayChanged();
154 }
155
156 void SystemInfoEventRouter::OnDisplayAdded(const gfx::Display& new_display) {
157   OnDisplayChanged();
158 }
159
160 void SystemInfoEventRouter::OnDisplayRemoved(const gfx::Display& old_display) {
161   OnDisplayChanged();
162 }
163
164 void SystemInfoEventRouter::OnDisplayChanged() {
165   scoped_ptr<base::ListValue> args(new base::ListValue());
166   DispatchEvent(system_display::OnDisplayChanged::kEventName, args.Pass());
167 }
168
169 void SystemInfoEventRouter::DispatchEvent(const std::string& event_name,
170                                           scoped_ptr<base::ListValue> args) {
171   g_browser_process->extension_event_router_forwarder()->
172       BroadcastEventToRenderers(event_name, args.Pass(), GURL());
173 }
174
175 }  // namespace
176
177 static base::LazyInstance<ProfileKeyedAPIFactory<SystemInfoAPI> >
178     g_factory = LAZY_INSTANCE_INITIALIZER;
179
180 // static
181 ProfileKeyedAPIFactory<SystemInfoAPI>* SystemInfoAPI::GetFactoryInstance() {
182   return &g_factory.Get();
183 }
184
185 SystemInfoAPI::SystemInfoAPI(Profile* profile) : profile_(profile) {
186   ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
187       this, system_storage::OnAttached::kEventName);
188   ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
189       this, system_storage::OnDetached::kEventName);
190   ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
191       this, system_display::OnDisplayChanged::kEventName);
192 }
193
194 SystemInfoAPI::~SystemInfoAPI() {
195 }
196
197 void SystemInfoAPI::Shutdown() {
198   ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this);
199 }
200
201 void SystemInfoAPI::OnListenerAdded(const EventListenerInfo& details) {
202   SystemInfoEventRouter::GetInstance()->AddEventListener(details.event_name);
203 }
204
205 void SystemInfoAPI::OnListenerRemoved(const EventListenerInfo& details) {
206   SystemInfoEventRouter::GetInstance()->RemoveEventListener(details.event_name);
207 }
208
209 }  // namespace extensions