Fix leaking Mock WebContentsDelegate in WebViewTest.MediaAccessAPIAllow* and Download...
[chromium-blink-merge.git] / apps / app_window_registry.cc
blob82d8293f08c6c4a492f0f5e62f4a7dfb64423e60
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.
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"
20 namespace {
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.
35 if (app_window->window_key().empty())
36 return app_window->web_contents()->GetURL().possibly_invalid_spec();
38 std::string key = app_window->extension()->id();
39 key += ':';
40 key += app_window->window_key();
41 return key;
44 } // namespace
46 namespace apps {
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_);
56 AppWindowRegistry::~AppWindowRegistry() {
57 content::DevToolsManager::GetInstance()->RemoveAgentStateCallback(
58 devtools_callback_);
61 // static
62 AppWindowRegistry* AppWindowRegistry::Get(content::BrowserContext* context) {
63 return Factory::GetForBrowserContext(context, true /* create */);
66 void AppWindowRegistry::AddAppWindow(AppWindow* app_window) {
67 BringToFront(app_window);
68 FOR_EACH_OBSERVER(Observer, observers_, OnAppWindowAdded(app_window));
71 void AppWindowRegistry::AppWindowIconChanged(AppWindow* app_window) {
72 AddAppWindowToList(app_window);
73 FOR_EACH_OBSERVER(Observer, observers_, OnAppWindowIconChanged(app_window));
76 void AppWindowRegistry::AppWindowActivated(AppWindow* app_window) {
77 BringToFront(app_window);
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));
88 void AppWindowRegistry::AddObserver(Observer* observer) {
89 observers_.AddObserver(observer);
92 void AppWindowRegistry::RemoveObserver(Observer* observer) {
93 observers_.RemoveObserver(observer);
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);
105 return app_windows;
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();
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;
126 return NULL;
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;
138 return NULL;
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;
154 return result;
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;
170 return result;
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;
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;
193 AppWindow* app_window = registry->GetAppWindowForNativeWindow(window);
194 if (app_window)
195 return app_window;
198 return NULL;
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;
215 const AppWindowList& app_windows = registry->app_windows();
216 if (app_windows.empty())
217 continue;
219 if (window_type_mask == 0)
220 return true;
222 for (const_iterator j = app_windows.begin(); j != app_windows.end(); ++j) {
223 if ((*j)->window_type() & window_type_mask)
224 return true;
228 return false;
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;
240 std::string key = GetWindowKeyForRenderViewHost(this, rvh);
241 if (key.empty())
242 return;
244 if (attached)
245 inspected_windows_.insert(key);
246 else
247 inspected_windows_.erase(key);
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);
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);
266 ///////////////////////////////////////////////////////////////////////////////
267 // Factory boilerplate
269 // static
270 AppWindowRegistry* AppWindowRegistry::Factory::GetForBrowserContext(
271 content::BrowserContext* context,
272 bool create) {
273 return static_cast<AppWindowRegistry*>(
274 GetInstance()->GetServiceForBrowserContext(context, create));
277 AppWindowRegistry::Factory* AppWindowRegistry::Factory::GetInstance() {
278 return Singleton<AppWindowRegistry::Factory>::get();
281 AppWindowRegistry::Factory::Factory()
282 : BrowserContextKeyedServiceFactory(
283 "AppWindowRegistry",
284 BrowserContextDependencyManager::GetInstance()) {}
286 AppWindowRegistry::Factory::~Factory() {}
288 KeyedService* AppWindowRegistry::Factory::BuildServiceInstanceFor(
289 content::BrowserContext* context) const {
290 return new AppWindowRegistry(context);
293 bool AppWindowRegistry::Factory::ServiceIsCreatedWithBrowserContext() const {
294 return true;
297 bool AppWindowRegistry::Factory::ServiceIsNULLWhileTesting() const {
298 return false;
301 content::BrowserContext* AppWindowRegistry::Factory::GetBrowserContextToUse(
302 content::BrowserContext* context) const {
303 return extensions::ExtensionsBrowserClient::Get()->GetOriginalContext(
304 context);
307 } // namespace extensions