Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / apps / app_window_registry.cc
1 // Copyright 2014 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 "apps/app_window.h"
6 #include "apps/app_window_registry.h"
7 #include "apps/apps_client.h"
8 #include "apps/ui/native_app_window.h"
9 #include "components/keyed_service/content/browser_context_dependency_manager.h"
10 #include "content/public/browser/browser_context.h"
11 #include "content/public/browser/devtools_agent_host.h"
12 #include "content/public/browser/devtools_manager.h"
13 #include "content/public/browser/render_process_host.h"
14 #include "content/public/browser/render_view_host.h"
15 #include "content/public/browser/site_instance.h"
16 #include "content/public/browser/web_contents.h"
17 #include "extensions/browser/extensions_browser_client.h"
18 #include "extensions/common/extension.h"
19
20 namespace {
21
22 // Create a key that identifies a AppWindow in a RenderViewHost across App
23 // reloads. If the window was given an id in CreateParams, the key is the
24 // extension id, a colon separator, and the AppWindow's |id|. If there is no
25 // |id|, the chrome-extension://extension-id/page.html URL will be used. If the
26 // RenderViewHost is not for a AppWindow, return an empty string.
27 std::string GetWindowKeyForRenderViewHost(
28     const apps::AppWindowRegistry* registry,
29     content::RenderViewHost* render_view_host) {
30   apps::AppWindow* app_window =
31       registry->GetAppWindowForRenderViewHost(render_view_host);
32   if (!app_window)
33     return std::string();  // Not a AppWindow.
34
35   if (app_window->window_key().empty())
36     return app_window->web_contents()->GetURL().possibly_invalid_spec();
37
38   std::string key = app_window->extension()->id();
39   key += ':';
40   key += app_window->window_key();
41   return key;
42 }
43
44 }  // namespace
45
46 namespace apps {
47
48 AppWindowRegistry::AppWindowRegistry(content::BrowserContext* context)
49     : context_(context),
50       devtools_callback_(base::Bind(&AppWindowRegistry::OnDevToolsStateChanged,
51                                     base::Unretained(this))) {
52   content::DevToolsManager::GetInstance()->AddAgentStateCallback(
53       devtools_callback_);
54 }
55
56 AppWindowRegistry::~AppWindowRegistry() {
57   content::DevToolsManager::GetInstance()->RemoveAgentStateCallback(
58       devtools_callback_);
59 }
60
61 // static
62 AppWindowRegistry* AppWindowRegistry::Get(content::BrowserContext* context) {
63   return Factory::GetForBrowserContext(context, true /* create */);
64 }
65
66 void AppWindowRegistry::AddAppWindow(AppWindow* app_window) {
67   BringToFront(app_window);
68   FOR_EACH_OBSERVER(Observer, observers_, OnAppWindowAdded(app_window));
69 }
70
71 void AppWindowRegistry::AppWindowIconChanged(AppWindow* app_window) {
72   AddAppWindowToList(app_window);
73   FOR_EACH_OBSERVER(Observer, observers_, OnAppWindowIconChanged(app_window));
74 }
75
76 void AppWindowRegistry::AppWindowActivated(AppWindow* app_window) {
77   BringToFront(app_window);
78 }
79
80 void AppWindowRegistry::RemoveAppWindow(AppWindow* app_window) {
81   const AppWindowList::iterator it =
82       std::find(app_windows_.begin(), app_windows_.end(), app_window);
83   if (it != app_windows_.end())
84     app_windows_.erase(it);
85   FOR_EACH_OBSERVER(Observer, observers_, OnAppWindowRemoved(app_window));
86 }
87
88 void AppWindowRegistry::AddObserver(Observer* observer) {
89   observers_.AddObserver(observer);
90 }
91
92 void AppWindowRegistry::RemoveObserver(Observer* observer) {
93   observers_.RemoveObserver(observer);
94 }
95
96 AppWindowRegistry::AppWindowList AppWindowRegistry::GetAppWindowsForApp(
97     const std::string& app_id) const {
98   AppWindowList app_windows;
99   for (AppWindowList::const_iterator i = app_windows_.begin();
100        i != app_windows_.end();
101        ++i) {
102     if ((*i)->extension_id() == app_id)
103       app_windows.push_back(*i);
104   }
105   return app_windows;
106 }
107
108 void AppWindowRegistry::CloseAllAppWindowsForApp(const std::string& app_id) {
109   for (AppWindowList::const_iterator i = app_windows_.begin();
110        i != app_windows_.end();) {
111     AppWindow* app_window = *(i++);
112     if (app_window->extension_id() == app_id)
113       app_window->GetBaseWindow()->Close();
114   }
115 }
116
117 AppWindow* AppWindowRegistry::GetAppWindowForRenderViewHost(
118     content::RenderViewHost* render_view_host) const {
119   for (AppWindowList::const_iterator i = app_windows_.begin();
120        i != app_windows_.end();
121        ++i) {
122     if ((*i)->web_contents()->GetRenderViewHost() == render_view_host)
123       return *i;
124   }
125
126   return NULL;
127 }
128
129 AppWindow* AppWindowRegistry::GetAppWindowForNativeWindow(
130     gfx::NativeWindow window) const {
131   for (AppWindowList::const_iterator i = app_windows_.begin();
132        i != app_windows_.end();
133        ++i) {
134     if ((*i)->GetNativeWindow() == window)
135       return *i;
136   }
137
138   return NULL;
139 }
140
141 AppWindow* AppWindowRegistry::GetCurrentAppWindowForApp(
142     const std::string& app_id) const {
143   AppWindow* result = NULL;
144   for (AppWindowList::const_iterator i = app_windows_.begin();
145        i != app_windows_.end();
146        ++i) {
147     if ((*i)->extension()->id() == app_id) {
148       result = *i;
149       if (result->GetBaseWindow()->IsActive())
150         return result;
151     }
152   }
153
154   return result;
155 }
156
157 AppWindow* AppWindowRegistry::GetAppWindowForAppAndKey(
158     const std::string& app_id,
159     const std::string& window_key) const {
160   AppWindow* result = NULL;
161   for (AppWindowList::const_iterator i = app_windows_.begin();
162        i != app_windows_.end();
163        ++i) {
164     if ((*i)->extension()->id() == app_id && (*i)->window_key() == window_key) {
165       result = *i;
166       if (result->GetBaseWindow()->IsActive())
167         return result;
168     }
169   }
170   return result;
171 }
172
173 bool AppWindowRegistry::HadDevToolsAttached(
174     content::RenderViewHost* render_view_host) const {
175   std::string key = GetWindowKeyForRenderViewHost(this, render_view_host);
176   return key.empty() ? false : inspected_windows_.count(key) != 0;
177 }
178
179 // static
180 AppWindow* AppWindowRegistry::GetAppWindowForNativeWindowAnyProfile(
181     gfx::NativeWindow window) {
182   std::vector<content::BrowserContext*> contexts =
183       AppsClient::Get()->GetLoadedBrowserContexts();
184   for (std::vector<content::BrowserContext*>::const_iterator i =
185            contexts.begin();
186        i != contexts.end();
187        ++i) {
188     AppWindowRegistry* registry =
189         Factory::GetForBrowserContext(*i, false /* create */);
190     if (!registry)
191       continue;
192
193     AppWindow* app_window = registry->GetAppWindowForNativeWindow(window);
194     if (app_window)
195       return app_window;
196   }
197
198   return NULL;
199 }
200
201 // static
202 bool AppWindowRegistry::IsAppWindowRegisteredInAnyProfile(
203     int window_type_mask) {
204   std::vector<content::BrowserContext*> contexts =
205       AppsClient::Get()->GetLoadedBrowserContexts();
206   for (std::vector<content::BrowserContext*>::const_iterator i =
207            contexts.begin();
208        i != contexts.end();
209        ++i) {
210     AppWindowRegistry* registry =
211         Factory::GetForBrowserContext(*i, false /* create */);
212     if (!registry)
213       continue;
214
215     const AppWindowList& app_windows = registry->app_windows();
216     if (app_windows.empty())
217       continue;
218
219     if (window_type_mask == 0)
220       return true;
221
222     for (const_iterator j = app_windows.begin(); j != app_windows.end(); ++j) {
223       if ((*j)->window_type() & window_type_mask)
224         return true;
225     }
226   }
227
228   return false;
229 }
230
231 void AppWindowRegistry::OnDevToolsStateChanged(
232     content::DevToolsAgentHost* agent_host,
233     bool attached) {
234   content::RenderViewHost* rvh = agent_host->GetRenderViewHost();
235   // Ignore unrelated notifications.
236   if (!rvh ||
237       rvh->GetSiteInstance()->GetProcess()->GetBrowserContext() != context_)
238     return;
239
240   std::string key = GetWindowKeyForRenderViewHost(this, rvh);
241   if (key.empty())
242     return;
243
244   if (attached)
245     inspected_windows_.insert(key);
246   else
247     inspected_windows_.erase(key);
248 }
249
250 void AppWindowRegistry::AddAppWindowToList(AppWindow* app_window) {
251   const AppWindowList::iterator it =
252       std::find(app_windows_.begin(), app_windows_.end(), app_window);
253   if (it != app_windows_.end())
254     return;
255   app_windows_.push_back(app_window);
256 }
257
258 void AppWindowRegistry::BringToFront(AppWindow* app_window) {
259   const AppWindowList::iterator it =
260       std::find(app_windows_.begin(), app_windows_.end(), app_window);
261   if (it != app_windows_.end())
262     app_windows_.erase(it);
263   app_windows_.push_front(app_window);
264 }
265
266 ///////////////////////////////////////////////////////////////////////////////
267 // Factory boilerplate
268
269 // static
270 AppWindowRegistry* AppWindowRegistry::Factory::GetForBrowserContext(
271     content::BrowserContext* context,
272     bool create) {
273   return static_cast<AppWindowRegistry*>(
274       GetInstance()->GetServiceForBrowserContext(context, create));
275 }
276
277 AppWindowRegistry::Factory* AppWindowRegistry::Factory::GetInstance() {
278   return Singleton<AppWindowRegistry::Factory>::get();
279 }
280
281 AppWindowRegistry::Factory::Factory()
282     : BrowserContextKeyedServiceFactory(
283           "AppWindowRegistry",
284           BrowserContextDependencyManager::GetInstance()) {}
285
286 AppWindowRegistry::Factory::~Factory() {}
287
288 KeyedService* AppWindowRegistry::Factory::BuildServiceInstanceFor(
289     content::BrowserContext* context) const {
290   return new AppWindowRegistry(context);
291 }
292
293 bool AppWindowRegistry::Factory::ServiceIsCreatedWithBrowserContext() const {
294   return true;
295 }
296
297 bool AppWindowRegistry::Factory::ServiceIsNULLWhileTesting() const {
298   return false;
299 }
300
301 content::BrowserContext* AppWindowRegistry::Factory::GetBrowserContextToUse(
302     content::BrowserContext* context) const {
303   return extensions::ExtensionsBrowserClient::Get()->GetOriginalContext(
304       context);
305 }
306
307 }  // namespace extensions