| OLD | NEW |
| (Empty) |
| 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 "apps/apps_client.h" | |
| 6 #include "apps/shell_window.h" | |
| 7 #include "apps/shell_window_registry.h" | |
| 8 #include "apps/ui/native_app_window.h" | |
| 9 #include "components/browser_context_keyed_service/browser_context_dependency_ma
nager.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 ShellWindow 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 ShellWindow'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 ShellWindow, return an empty string. | |
| 27 std::string GetWindowKeyForRenderViewHost( | |
| 28 const apps::ShellWindowRegistry* registry, | |
| 29 content::RenderViewHost* render_view_host) { | |
| 30 apps::ShellWindow* shell_window = | |
| 31 registry->GetShellWindowForRenderViewHost(render_view_host); | |
| 32 if (!shell_window) | |
| 33 return std::string(); // Not a ShellWindow. | |
| 34 | |
| 35 if (shell_window->window_key().empty()) | |
| 36 return shell_window->web_contents()->GetURL().possibly_invalid_spec(); | |
| 37 | |
| 38 std::string key = shell_window->extension()->id(); | |
| 39 key += ':'; | |
| 40 key += shell_window->window_key(); | |
| 41 return key; | |
| 42 } | |
| 43 | |
| 44 } // namespace | |
| 45 | |
| 46 namespace apps { | |
| 47 | |
| 48 ShellWindowRegistry::ShellWindowRegistry(content::BrowserContext* context) | |
| 49 : context_(context), | |
| 50 devtools_callback_(base::Bind( | |
| 51 &ShellWindowRegistry::OnDevToolsStateChanged, | |
| 52 base::Unretained(this))) { | |
| 53 content::DevToolsManager::GetInstance()->AddAgentStateCallback( | |
| 54 devtools_callback_); | |
| 55 } | |
| 56 | |
| 57 ShellWindowRegistry::~ShellWindowRegistry() { | |
| 58 content::DevToolsManager::GetInstance()->RemoveAgentStateCallback( | |
| 59 devtools_callback_); | |
| 60 } | |
| 61 | |
| 62 // static | |
| 63 ShellWindowRegistry* ShellWindowRegistry::Get( | |
| 64 content::BrowserContext* context) { | |
| 65 return Factory::GetForBrowserContext(context, true /* create */); | |
| 66 } | |
| 67 | |
| 68 void ShellWindowRegistry::AddShellWindow(ShellWindow* shell_window) { | |
| 69 BringToFront(shell_window); | |
| 70 FOR_EACH_OBSERVER(Observer, observers_, OnShellWindowAdded(shell_window)); | |
| 71 } | |
| 72 | |
| 73 void ShellWindowRegistry::ShellWindowIconChanged(ShellWindow* shell_window) { | |
| 74 AddShellWindowToList(shell_window); | |
| 75 FOR_EACH_OBSERVER(Observer, observers_, | |
| 76 OnShellWindowIconChanged(shell_window)); | |
| 77 } | |
| 78 | |
| 79 void ShellWindowRegistry::ShellWindowActivated(ShellWindow* shell_window) { | |
| 80 BringToFront(shell_window); | |
| 81 } | |
| 82 | |
| 83 void ShellWindowRegistry::RemoveShellWindow(ShellWindow* shell_window) { | |
| 84 const ShellWindowList::iterator it = std::find(shell_windows_.begin(), | |
| 85 shell_windows_.end(), | |
| 86 shell_window); | |
| 87 if (it != shell_windows_.end()) | |
| 88 shell_windows_.erase(it); | |
| 89 FOR_EACH_OBSERVER(Observer, observers_, OnShellWindowRemoved(shell_window)); | |
| 90 } | |
| 91 | |
| 92 void ShellWindowRegistry::AddObserver(Observer* observer) { | |
| 93 observers_.AddObserver(observer); | |
| 94 } | |
| 95 | |
| 96 void ShellWindowRegistry::RemoveObserver(Observer* observer) { | |
| 97 observers_.RemoveObserver(observer); | |
| 98 } | |
| 99 | |
| 100 ShellWindowRegistry::ShellWindowList ShellWindowRegistry::GetShellWindowsForApp( | |
| 101 const std::string& app_id) const { | |
| 102 ShellWindowList app_windows; | |
| 103 for (ShellWindowList::const_iterator i = shell_windows_.begin(); | |
| 104 i != shell_windows_.end(); ++i) { | |
| 105 if ((*i)->extension_id() == app_id) | |
| 106 app_windows.push_back(*i); | |
| 107 } | |
| 108 return app_windows; | |
| 109 } | |
| 110 | |
| 111 void ShellWindowRegistry::CloseAllShellWindowsForApp( | |
| 112 const std::string& app_id) { | |
| 113 for (ShellWindowList::const_iterator i = shell_windows_.begin(); | |
| 114 i != shell_windows_.end(); ) { | |
| 115 ShellWindow* shell_window = *(i++); | |
| 116 if (shell_window->extension_id() == app_id) | |
| 117 shell_window->GetBaseWindow()->Close(); | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 ShellWindow* ShellWindowRegistry::GetShellWindowForRenderViewHost( | |
| 122 content::RenderViewHost* render_view_host) const { | |
| 123 for (ShellWindowList::const_iterator i = shell_windows_.begin(); | |
| 124 i != shell_windows_.end(); ++i) { | |
| 125 if ((*i)->web_contents()->GetRenderViewHost() == render_view_host) | |
| 126 return *i; | |
| 127 } | |
| 128 | |
| 129 return NULL; | |
| 130 } | |
| 131 | |
| 132 ShellWindow* ShellWindowRegistry::GetShellWindowForNativeWindow( | |
| 133 gfx::NativeWindow window) const { | |
| 134 for (ShellWindowList::const_iterator i = shell_windows_.begin(); | |
| 135 i != shell_windows_.end(); ++i) { | |
| 136 if ((*i)->GetNativeWindow() == window) | |
| 137 return *i; | |
| 138 } | |
| 139 | |
| 140 return NULL; | |
| 141 } | |
| 142 | |
| 143 ShellWindow* ShellWindowRegistry::GetCurrentShellWindowForApp( | |
| 144 const std::string& app_id) const { | |
| 145 ShellWindow* result = NULL; | |
| 146 for (ShellWindowList::const_iterator i = shell_windows_.begin(); | |
| 147 i != shell_windows_.end(); ++i) { | |
| 148 if ((*i)->extension()->id() == app_id) { | |
| 149 result = *i; | |
| 150 if (result->GetBaseWindow()->IsActive()) | |
| 151 return result; | |
| 152 } | |
| 153 } | |
| 154 | |
| 155 return result; | |
| 156 } | |
| 157 | |
| 158 ShellWindow* ShellWindowRegistry::GetShellWindowForAppAndKey( | |
| 159 const std::string& app_id, | |
| 160 const std::string& window_key) const { | |
| 161 ShellWindow* result = NULL; | |
| 162 for (ShellWindowList::const_iterator i = shell_windows_.begin(); | |
| 163 i != shell_windows_.end(); ++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 ShellWindowRegistry::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 ShellWindow* ShellWindowRegistry::GetShellWindowForNativeWindowAnyProfile( | |
| 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(); ++i) { | |
| 187 ShellWindowRegistry* registry = Factory::GetForBrowserContext( | |
| 188 *i, false /* create */); | |
| 189 if (!registry) | |
| 190 continue; | |
| 191 | |
| 192 ShellWindow* shell_window = registry->GetShellWindowForNativeWindow(window); | |
| 193 if (shell_window) | |
| 194 return shell_window; | |
| 195 } | |
| 196 | |
| 197 return NULL; | |
| 198 } | |
| 199 | |
| 200 // static | |
| 201 bool ShellWindowRegistry::IsShellWindowRegisteredInAnyProfile( | |
| 202 int window_type_mask) { | |
| 203 std::vector<content::BrowserContext*> contexts = | |
| 204 AppsClient::Get()->GetLoadedBrowserContexts(); | |
| 205 for (std::vector<content::BrowserContext*>::const_iterator i = | |
| 206 contexts.begin(); | |
| 207 i != contexts.end(); ++i) { | |
| 208 ShellWindowRegistry* registry = Factory::GetForBrowserContext( | |
| 209 *i, false /* create */); | |
| 210 if (!registry) | |
| 211 continue; | |
| 212 | |
| 213 const ShellWindowList& shell_windows = registry->shell_windows(); | |
| 214 if (shell_windows.empty()) | |
| 215 continue; | |
| 216 | |
| 217 if (window_type_mask == 0) | |
| 218 return true; | |
| 219 | |
| 220 for (const_iterator j = shell_windows.begin(); j != shell_windows.end(); | |
| 221 ++j) { | |
| 222 if ((*j)->window_type() & window_type_mask) | |
| 223 return true; | |
| 224 } | |
| 225 } | |
| 226 | |
| 227 return false; | |
| 228 } | |
| 229 | |
| 230 void ShellWindowRegistry::OnDevToolsStateChanged( | |
| 231 content::DevToolsAgentHost* agent_host, bool attached) { | |
| 232 content::RenderViewHost* rvh = agent_host->GetRenderViewHost(); | |
| 233 // Ignore unrelated notifications. | |
| 234 if (!rvh || | |
| 235 rvh->GetSiteInstance()->GetProcess()->GetBrowserContext() != context_) | |
| 236 return; | |
| 237 | |
| 238 std::string key = GetWindowKeyForRenderViewHost(this, rvh); | |
| 239 if (key.empty()) | |
| 240 return; | |
| 241 | |
| 242 if (attached) | |
| 243 inspected_windows_.insert(key); | |
| 244 else | |
| 245 inspected_windows_.erase(key); | |
| 246 } | |
| 247 | |
| 248 void ShellWindowRegistry::AddShellWindowToList(ShellWindow* shell_window) { | |
| 249 const ShellWindowList::iterator it = std::find(shell_windows_.begin(), | |
| 250 shell_windows_.end(), | |
| 251 shell_window); | |
| 252 if (it != shell_windows_.end()) | |
| 253 return; | |
| 254 shell_windows_.push_back(shell_window); | |
| 255 } | |
| 256 | |
| 257 void ShellWindowRegistry::BringToFront(ShellWindow* shell_window) { | |
| 258 const ShellWindowList::iterator it = std::find(shell_windows_.begin(), | |
| 259 shell_windows_.end(), | |
| 260 shell_window); | |
| 261 if (it != shell_windows_.end()) | |
| 262 shell_windows_.erase(it); | |
| 263 shell_windows_.push_front(shell_window); | |
| 264 } | |
| 265 | |
| 266 /////////////////////////////////////////////////////////////////////////////// | |
| 267 // Factory boilerplate | |
| 268 | |
| 269 // static | |
| 270 ShellWindowRegistry* ShellWindowRegistry::Factory::GetForBrowserContext( | |
| 271 content::BrowserContext* context, bool create) { | |
| 272 return static_cast<ShellWindowRegistry*>( | |
| 273 GetInstance()->GetServiceForBrowserContext(context, create)); | |
| 274 } | |
| 275 | |
| 276 ShellWindowRegistry::Factory* ShellWindowRegistry::Factory::GetInstance() { | |
| 277 return Singleton<ShellWindowRegistry::Factory>::get(); | |
| 278 } | |
| 279 | |
| 280 ShellWindowRegistry::Factory::Factory() | |
| 281 : BrowserContextKeyedServiceFactory( | |
| 282 "ShellWindowRegistry", | |
| 283 BrowserContextDependencyManager::GetInstance()) { | |
| 284 } | |
| 285 | |
| 286 ShellWindowRegistry::Factory::~Factory() { | |
| 287 } | |
| 288 | |
| 289 BrowserContextKeyedService* | |
| 290 ShellWindowRegistry::Factory::BuildServiceInstanceFor( | |
| 291 content::BrowserContext* context) const { | |
| 292 return new ShellWindowRegistry(context); | |
| 293 } | |
| 294 | |
| 295 bool ShellWindowRegistry::Factory::ServiceIsCreatedWithBrowserContext() const { | |
| 296 return true; | |
| 297 } | |
| 298 | |
| 299 bool ShellWindowRegistry::Factory::ServiceIsNULLWhileTesting() const { | |
| 300 return false; | |
| 301 } | |
| 302 | |
| 303 content::BrowserContext* ShellWindowRegistry::Factory::GetBrowserContextToUse( | |
| 304 content::BrowserContext* context) const { | |
| 305 return extensions::ExtensionsBrowserClient::Get()-> | |
| 306 GetOriginalContext(context); | |
| 307 } | |
| 308 | |
| 309 } // namespace extensions | |
| OLD | NEW |