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 "extensions/browser/app_window/app_window_registry.h"
10 #include "base/strings/stringprintf.h"
11 #include "components/keyed_service/content/browser_context_dependency_manager.h"
12 #include "content/public/browser/browser_context.h"
13 #include "content/public/browser/devtools_agent_host.h"
14 #include "content/public/browser/render_process_host.h"
15 #include "content/public/browser/site_instance.h"
16 #include "content/public/browser/web_contents.h"
17 #include "extensions/browser/app_window/app_window.h"
18 #include "extensions/browser/app_window/native_app_window.h"
19 #include "extensions/browser/extensions_browser_client.h"
20 #include "extensions/common/extension.h"
22 namespace extensions
{
24 void AppWindowRegistry::Observer::OnAppWindowAdded(AppWindow
* app_window
) {
27 void AppWindowRegistry::Observer::OnAppWindowIconChanged(
28 AppWindow
* app_window
) {
31 void AppWindowRegistry::Observer::OnAppWindowRemoved(AppWindow
* app_window
) {
34 void AppWindowRegistry::Observer::OnAppWindowHidden(AppWindow
* app_window
) {
37 void AppWindowRegistry::Observer::OnAppWindowShown(AppWindow
* app_window
,
41 void AppWindowRegistry::Observer::OnAppWindowActivated(AppWindow
* app_window
) {
44 AppWindowRegistry::Observer::~Observer() {
47 AppWindowRegistry::AppWindowRegistry(content::BrowserContext
* context
)
49 devtools_callback_(base::Bind(&AppWindowRegistry::OnDevToolsStateChanged
,
50 base::Unretained(this))) {
51 content::DevToolsAgentHost::AddAgentStateCallback(devtools_callback_
);
54 AppWindowRegistry::~AppWindowRegistry() {
55 content::DevToolsAgentHost::RemoveAgentStateCallback(devtools_callback_
);
59 AppWindowRegistry
* AppWindowRegistry::Get(content::BrowserContext
* context
) {
60 return Factory::GetForBrowserContext(context
, true /* create */);
63 void AppWindowRegistry::AddAppWindow(AppWindow
* app_window
) {
64 BringToFront(app_window
);
65 FOR_EACH_OBSERVER(Observer
, observers_
, OnAppWindowAdded(app_window
));
68 void AppWindowRegistry::AppWindowIconChanged(AppWindow
* app_window
) {
69 AddAppWindowToList(app_window
);
70 FOR_EACH_OBSERVER(Observer
, observers_
, OnAppWindowIconChanged(app_window
));
73 void AppWindowRegistry::AppWindowActivated(AppWindow
* app_window
) {
74 BringToFront(app_window
);
75 FOR_EACH_OBSERVER(Observer
, observers_
, OnAppWindowActivated(app_window
));
78 void AppWindowRegistry::AppWindowHidden(AppWindow
* app_window
) {
79 FOR_EACH_OBSERVER(Observer
, observers_
, OnAppWindowHidden(app_window
));
82 void AppWindowRegistry::AppWindowShown(AppWindow
* app_window
, bool was_hidden
) {
83 FOR_EACH_OBSERVER(Observer
, observers_
,
84 OnAppWindowShown(app_window
, was_hidden
));
87 void AppWindowRegistry::RemoveAppWindow(AppWindow
* app_window
) {
88 const AppWindowList::iterator it
=
89 std::find(app_windows_
.begin(), app_windows_
.end(), app_window
);
90 if (it
!= app_windows_
.end())
91 app_windows_
.erase(it
);
92 FOR_EACH_OBSERVER(Observer
, observers_
, OnAppWindowRemoved(app_window
));
95 void AppWindowRegistry::AddObserver(Observer
* observer
) {
96 observers_
.AddObserver(observer
);
99 void AppWindowRegistry::RemoveObserver(Observer
* observer
) {
100 observers_
.RemoveObserver(observer
);
103 AppWindowRegistry::AppWindowList
AppWindowRegistry::GetAppWindowsForApp(
104 const std::string
& app_id
) const {
105 AppWindowList app_windows
;
106 for (AppWindowList::const_iterator i
= app_windows_
.begin();
107 i
!= app_windows_
.end();
109 if ((*i
)->extension_id() == app_id
)
110 app_windows
.push_back(*i
);
115 void AppWindowRegistry::CloseAllAppWindowsForApp(const std::string
& app_id
) {
116 const AppWindowList windows
= GetAppWindowsForApp(app_id
);
117 for (AppWindowRegistry::const_iterator it
= windows
.begin();
120 (*it
)->GetBaseWindow()->Close();
124 AppWindow
* AppWindowRegistry::GetAppWindowForWebContents(
125 const content::WebContents
* web_contents
) const {
126 for (AppWindow
* window
: app_windows_
) {
127 if (window
->web_contents() == web_contents
)
133 AppWindow
* AppWindowRegistry::GetAppWindowForNativeWindow(
134 gfx::NativeWindow window
) const {
135 for (AppWindowList::const_iterator i
= app_windows_
.begin();
136 i
!= app_windows_
.end();
138 if ((*i
)->GetNativeWindow() == window
)
145 AppWindow
* AppWindowRegistry::GetCurrentAppWindowForApp(
146 const std::string
& app_id
) const {
147 AppWindow
* result
= NULL
;
148 for (AppWindowList::const_iterator i
= app_windows_
.begin();
149 i
!= app_windows_
.end();
151 if ((*i
)->extension_id() == app_id
) {
153 if (result
->GetBaseWindow()->IsActive())
161 AppWindow
* AppWindowRegistry::GetAppWindowForAppAndKey(
162 const std::string
& app_id
,
163 const std::string
& window_key
) const {
164 AppWindow
* result
= NULL
;
165 for (AppWindowList::const_iterator i
= app_windows_
.begin();
166 i
!= app_windows_
.end();
168 if ((*i
)->extension_id() == app_id
&& (*i
)->window_key() == window_key
) {
170 if (result
->GetBaseWindow()->IsActive())
177 bool AppWindowRegistry::HadDevToolsAttached(
178 content::WebContents
* web_contents
) const {
179 std::string key
= GetWindowKeyForWebContents(web_contents
);
180 return key
.empty() ? false : inspected_windows_
.count(key
) != 0;
183 void AppWindowRegistry::OnDevToolsStateChanged(
184 content::DevToolsAgentHost
* agent_host
,
186 content::WebContents
* web_contents
= agent_host
->GetWebContents();
187 // Ignore unrelated notifications.
188 if (!web_contents
|| web_contents
->GetBrowserContext() != context_
)
191 std::string key
= GetWindowKeyForWebContents(web_contents
);
196 inspected_windows_
.insert(key
);
198 inspected_windows_
.erase(key
);
201 void AppWindowRegistry::AddAppWindowToList(AppWindow
* app_window
) {
202 const AppWindowList::iterator it
=
203 std::find(app_windows_
.begin(), app_windows_
.end(), app_window
);
204 if (it
!= app_windows_
.end())
206 app_windows_
.push_back(app_window
);
209 void AppWindowRegistry::BringToFront(AppWindow
* app_window
) {
210 const AppWindowList::iterator it
=
211 std::find(app_windows_
.begin(), app_windows_
.end(), app_window
);
212 if (it
!= app_windows_
.end())
213 app_windows_
.erase(it
);
214 app_windows_
.push_front(app_window
);
217 std::string
AppWindowRegistry::GetWindowKeyForWebContents(
218 content::WebContents
* web_contents
) const {
219 AppWindow
* app_window
= GetAppWindowForWebContents(web_contents
);
221 return std::string(); // Not an AppWindow.
223 if (app_window
->window_key().empty())
224 return web_contents
->GetURL().possibly_invalid_spec();
226 return base::StringPrintf("%s:%s", app_window
->extension_id().c_str(),
227 app_window
->window_key().c_str());
230 ///////////////////////////////////////////////////////////////////////////////
231 // Factory boilerplate
234 AppWindowRegistry
* AppWindowRegistry::Factory::GetForBrowserContext(
235 content::BrowserContext
* context
,
237 return static_cast<AppWindowRegistry
*>(
238 GetInstance()->GetServiceForBrowserContext(context
, create
));
241 AppWindowRegistry::Factory
* AppWindowRegistry::Factory::GetInstance() {
242 return Singleton
<AppWindowRegistry::Factory
>::get();
245 AppWindowRegistry::Factory::Factory()
246 : BrowserContextKeyedServiceFactory(
248 BrowserContextDependencyManager::GetInstance()) {}
250 AppWindowRegistry::Factory::~Factory() {}
252 KeyedService
* AppWindowRegistry::Factory::BuildServiceInstanceFor(
253 content::BrowserContext
* context
) const {
254 return new AppWindowRegistry(context
);
257 bool AppWindowRegistry::Factory::ServiceIsCreatedWithBrowserContext() const {
261 bool AppWindowRegistry::Factory::ServiceIsNULLWhileTesting() const {
265 content::BrowserContext
* AppWindowRegistry::Factory::GetBrowserContextToUse(
266 content::BrowserContext
* context
) const {
267 return ExtensionsBrowserClient::Get()->GetOriginalContext(context
);
270 } // namespace extensions