Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h" | 5 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h" |
| 6 | 6 |
| 7 #include "apps/app_lifetime_monitor_factory.h" | 7 #include "apps/app_lifetime_monitor_factory.h" |
| 8 #include "apps/launcher.h" | 8 #include "apps/launcher.h" |
| 9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "chrome/browser/apps/app_shim/app_shim_host_manager_mac.h" | 11 #include "chrome/browser/apps/app_shim/app_shim_host_manager_mac.h" |
| 12 #include "chrome/browser/browser_process.h" | 12 #include "chrome/browser/browser_process.h" |
| 13 #include "chrome/browser/chrome_notification_types.h" | 13 #include "chrome/browser/chrome_notification_types.h" |
| 14 #include "chrome/browser/extensions/launch_util.h" | |
| 14 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
| 15 #include "chrome/browser/profiles/profile_manager.h" | 16 #include "chrome/browser/profiles/profile_manager.h" |
| 17 #include "chrome/browser/ui/browser_list.h" | |
| 18 #include "chrome/browser/ui/browser_window.h" | |
| 16 #include "chrome/browser/ui/extensions/application_launch.h" | 19 #include "chrome/browser/ui/extensions/application_launch.h" |
| 17 #include "chrome/browser/ui/extensions/extension_enable_flow.h" | 20 #include "chrome/browser/ui/extensions/extension_enable_flow.h" |
| 18 #include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h" | 21 #include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h" |
| 19 #include "chrome/browser/web_applications/web_app_mac.h" | 22 #include "chrome/browser/web_applications/web_app_mac.h" |
| 20 #include "chrome/common/extensions/extension_constants.h" | 23 #include "chrome/common/extensions/extension_constants.h" |
| 21 #include "chrome/common/extensions/extension_metrics.h" | 24 #include "chrome/common/extensions/extension_metrics.h" |
| 22 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" | 25 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" |
| 23 #include "chrome/common/mac/app_shim_messages.h" | 26 #include "chrome/common/mac/app_shim_messages.h" |
| 24 #include "components/crx_file/id_util.h" | 27 #include "components/crx_file/id_util.h" |
| 25 #include "content/public/browser/notification_details.h" | 28 #include "content/public/browser/notification_details.h" |
| 26 #include "content/public/browser/notification_service.h" | 29 #include "content/public/browser/notification_service.h" |
| 27 #include "content/public/browser/notification_source.h" | 30 #include "content/public/browser/notification_source.h" |
| 28 #include "extensions/browser/app_window/app_window.h" | 31 #include "extensions/browser/app_window/app_window.h" |
| 29 #include "extensions/browser/app_window/app_window_registry.h" | 32 #include "extensions/browser/app_window/app_window_registry.h" |
| 30 #include "extensions/browser/app_window/native_app_window.h" | 33 #include "extensions/browser/app_window/native_app_window.h" |
| 31 #include "extensions/browser/extension_host.h" | 34 #include "extensions/browser/extension_host.h" |
| 35 #include "extensions/browser/extension_prefs.h" | |
| 32 #include "extensions/browser/extension_registry.h" | 36 #include "extensions/browser/extension_registry.h" |
| 33 #include "extensions/common/constants.h" | 37 #include "extensions/common/constants.h" |
| 34 #include "ui/base/cocoa/focus_window_set.h" | 38 #include "ui/base/cocoa/focus_window_set.h" |
| 35 | 39 |
| 36 using extensions::AppWindow; | 40 using extensions::AppWindow; |
| 37 using extensions::AppWindowRegistry; | 41 using extensions::AppWindowRegistry; |
| 38 using extensions::ExtensionRegistry; | 42 using extensions::ExtensionRegistry; |
| 39 | 43 |
| 40 namespace { | 44 namespace { |
| 41 | 45 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 75 ++it) { | 79 ++it) { |
| 76 native_windows.insert((*it)->GetNativeWindow()); | 80 native_windows.insert((*it)->GetNativeWindow()); |
| 77 } | 81 } |
| 78 // Allow workspace switching. For the browser process, we can reasonably rely | 82 // Allow workspace switching. For the browser process, we can reasonably rely |
| 79 // on OS X to switch spaces for us and honor relevant user settings. But shims | 83 // on OS X to switch spaces for us and honor relevant user settings. But shims |
| 80 // don't have windows, so we have to do it ourselves. | 84 // don't have windows, so we have to do it ourselves. |
| 81 ui::FocusWindowSet(native_windows); | 85 ui::FocusWindowSet(native_windows); |
| 82 return true; | 86 return true; |
| 83 } | 87 } |
| 84 | 88 |
| 89 bool FocusHostedAppWindows(std::set<Browser*>& browsers) { | |
| 90 if (browsers.empty()) | |
| 91 return false; | |
| 92 | |
| 93 std::set<gfx::NativeWindow> native_windows; | |
| 94 for (const Browser* browser : browsers) | |
| 95 native_windows.insert(browser->window()->GetNativeWindow()); | |
| 96 | |
| 97 ui::FocusWindowSet(native_windows); | |
| 98 return true; | |
| 99 } | |
| 100 | |
| 85 // Attempts to launch a packaged app, prompting the user to enable it if | 101 // Attempts to launch a packaged app, prompting the user to enable it if |
| 86 // necessary. The prompt is shown in its own window. | 102 // necessary. The prompt is shown in its own window. |
| 87 // This class manages its own lifetime. | 103 // This class manages its own lifetime. |
| 88 class EnableViaPrompt : public ExtensionEnableFlowDelegate { | 104 class EnableViaPrompt : public ExtensionEnableFlowDelegate { |
| 89 public: | 105 public: |
| 90 EnableViaPrompt(Profile* profile, | 106 EnableViaPrompt(Profile* profile, |
| 91 const std::string& extension_id, | 107 const std::string& extension_id, |
| 92 const base::Callback<void()>& callback) | 108 const base::Callback<void()>& callback) |
| 93 : profile_(profile), | 109 : profile_(profile), |
| 94 extension_id_(extension_id), | 110 extension_id_(extension_id), |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 161 AppWindowList ExtensionAppShimHandler::Delegate::GetWindows( | 177 AppWindowList ExtensionAppShimHandler::Delegate::GetWindows( |
| 162 Profile* profile, | 178 Profile* profile, |
| 163 const std::string& extension_id) { | 179 const std::string& extension_id) { |
| 164 return AppWindowRegistry::Get(profile)->GetAppWindowsForApp(extension_id); | 180 return AppWindowRegistry::Get(profile)->GetAppWindowsForApp(extension_id); |
| 165 } | 181 } |
| 166 | 182 |
| 167 const extensions::Extension* | 183 const extensions::Extension* |
| 168 ExtensionAppShimHandler::Delegate::GetAppExtension( | 184 ExtensionAppShimHandler::Delegate::GetAppExtension( |
| 169 Profile* profile, | 185 Profile* profile, |
| 170 const std::string& extension_id) { | 186 const std::string& extension_id) { |
| 171 ExtensionRegistry* registry = ExtensionRegistry::Get(profile); | 187 return ExtensionAppShimHandler::GetAppExtension(profile, extension_id); |
| 172 const extensions::Extension* extension = | |
| 173 registry->GetExtensionById(extension_id, ExtensionRegistry::ENABLED); | |
| 174 return extension && | |
| 175 (extension->is_platform_app() || extension->is_hosted_app()) | |
| 176 ? extension | |
| 177 : NULL; | |
| 178 } | 188 } |
| 179 | 189 |
| 180 void ExtensionAppShimHandler::Delegate::EnableExtension( | 190 void ExtensionAppShimHandler::Delegate::EnableExtension( |
| 181 Profile* profile, | 191 Profile* profile, |
| 182 const std::string& extension_id, | 192 const std::string& extension_id, |
| 183 const base::Callback<void()>& callback) { | 193 const base::Callback<void()>& callback) { |
| 184 (new EnableViaPrompt(profile, extension_id, callback))->Run(); | 194 (new EnableViaPrompt(profile, extension_id, callback))->Run(); |
| 185 } | 195 } |
| 186 | 196 |
| 187 void ExtensionAppShimHandler::Delegate::LaunchApp( | 197 void ExtensionAppShimHandler::Delegate::LaunchApp( |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 222 : delegate_(new Delegate), | 232 : delegate_(new Delegate), |
| 223 weak_factory_(this) { | 233 weak_factory_(this) { |
| 224 // This is instantiated in BrowserProcessImpl::PreMainMessageLoopRun with | 234 // This is instantiated in BrowserProcessImpl::PreMainMessageLoopRun with |
| 225 // AppShimHostManager. Since PROFILE_CREATED is not fired until | 235 // AppShimHostManager. Since PROFILE_CREATED is not fired until |
| 226 // ProfileManager::GetLastUsedProfile/GetLastOpenedProfiles, this should catch | 236 // ProfileManager::GetLastUsedProfile/GetLastOpenedProfiles, this should catch |
| 227 // notifications for all profiles. | 237 // notifications for all profiles. |
| 228 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, | 238 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, |
| 229 content::NotificationService::AllBrowserContextsAndSources()); | 239 content::NotificationService::AllBrowserContextsAndSources()); |
| 230 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, | 240 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, |
| 231 content::NotificationService::AllBrowserContextsAndSources()); | 241 content::NotificationService::AllBrowserContextsAndSources()); |
| 242 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_WINDOW_READY, | |
| 243 content::NotificationService::AllBrowserContextsAndSources()); | |
| 244 BrowserList::AddObserver(this); | |
| 232 } | 245 } |
| 233 | 246 |
| 234 ExtensionAppShimHandler::~ExtensionAppShimHandler() {} | 247 ExtensionAppShimHandler::~ExtensionAppShimHandler() { |
| 248 BrowserList::RemoveObserver(this); | |
| 249 } | |
| 235 | 250 |
| 236 AppShimHandler::Host* ExtensionAppShimHandler::FindHost( | 251 AppShimHandler::Host* ExtensionAppShimHandler::FindHost( |
| 237 Profile* profile, | 252 Profile* profile, |
| 238 const std::string& app_id) { | 253 const std::string& app_id) { |
| 239 HostMap::iterator it = hosts_.find(make_pair(profile, app_id)); | 254 HostMap::iterator it = hosts_.find(make_pair(profile, app_id)); |
| 240 return it == hosts_.end() ? NULL : it->second; | 255 return it == hosts_.end() ? NULL : it->second; |
| 241 } | 256 } |
| 242 | 257 |
| 258 void ExtensionAppShimHandler::SetHostedAppHidden(Profile* profile, | |
| 259 const std::string& app_id, | |
| 260 bool hidden) { | |
| 261 const AppBrowserMap::iterator it = app_browser_windows_.find(app_id); | |
| 262 if (it == app_browser_windows_.end()) | |
| 263 return; | |
| 264 | |
| 265 for (const Browser* browser : it->second) { | |
| 266 if (web_app::GetExtensionIdFromApplicationName(browser->app_name()) != | |
| 267 app_id) { | |
| 268 continue; | |
| 269 } | |
| 270 | |
| 271 if (hidden) | |
| 272 browser->window()->Hide(); | |
| 273 else | |
| 274 browser->window()->Show(); | |
| 275 } | |
| 276 } | |
| 277 | |
| 278 // static | |
| 279 const extensions::Extension* ExtensionAppShimHandler::GetAppExtension( | |
| 280 Profile* profile, | |
| 281 const std::string& extension_id) { | |
| 282 if (!profile) | |
| 283 return NULL; | |
| 284 | |
| 285 ExtensionRegistry* registry = ExtensionRegistry::Get(profile); | |
| 286 const extensions::Extension* extension = | |
| 287 registry->GetExtensionById(extension_id, ExtensionRegistry::ENABLED); | |
| 288 return extension && | |
| 289 (extension->is_platform_app() || extension->is_hosted_app()) | |
| 290 ? extension | |
| 291 : NULL; | |
| 292 } | |
| 293 | |
| 294 // static | |
| 295 const extensions::Extension* ExtensionAppShimHandler::GetAppForBrowser( | |
| 296 Browser* browser) { | |
| 297 if (!browser || !browser->is_app()) | |
|
jackhou1
2014/12/12 04:42:49
Blank line after return.
mitchellj
2014/12/14 22:28:57
Done.
| |
| 298 return NULL; | |
| 299 return GetAppExtension( | |
| 300 browser->profile(), | |
| 301 web_app::GetExtensionIdFromApplicationName(browser->app_name())); | |
| 302 } | |
| 303 | |
| 243 // static | 304 // static |
| 244 void ExtensionAppShimHandler::QuitAppForWindow(AppWindow* app_window) { | 305 void ExtensionAppShimHandler::QuitAppForWindow(AppWindow* app_window) { |
| 245 ExtensionAppShimHandler* handler = GetInstance(); | 306 ExtensionAppShimHandler* handler = GetInstance(); |
| 246 Host* host = handler->FindHost( | 307 Host* host = handler->FindHost( |
| 247 Profile::FromBrowserContext(app_window->browser_context()), | 308 Profile::FromBrowserContext(app_window->browser_context()), |
| 248 app_window->extension_id()); | 309 app_window->extension_id()); |
| 249 if (host) { | 310 if (host) { |
| 250 handler->OnShimQuit(host); | 311 handler->OnShimQuit(host); |
| 251 } else { | 312 } else { |
| 252 // App shims might be disabled or the shim is still starting up. | 313 // App shims might be disabled or the shim is still starting up. |
| 253 AppWindowRegistry::Get( | 314 AppWindowRegistry::Get( |
| 254 Profile::FromBrowserContext(app_window->browser_context())) | 315 Profile::FromBrowserContext(app_window->browser_context())) |
| 255 ->CloseAllAppWindowsForApp(app_window->extension_id()); | 316 ->CloseAllAppWindowsForApp(app_window->extension_id()); |
| 256 } | 317 } |
| 257 } | 318 } |
| 258 | 319 |
| 320 // static | |
| 321 void ExtensionAppShimHandler::QuitHostedAppForWindow( | |
| 322 Profile* profile, | |
| 323 const std::string& app_id) { | |
| 324 ExtensionAppShimHandler* handler = GetInstance(); | |
| 325 Host* host = handler->FindHost(Profile::FromBrowserContext(profile), app_id); | |
| 326 if (host) | |
| 327 handler->OnShimQuit(host); | |
| 328 else | |
| 329 handler->CloseBrowsersForApp(app_id); | |
| 330 } | |
| 331 | |
| 259 void ExtensionAppShimHandler::HideAppForWindow(AppWindow* app_window) { | 332 void ExtensionAppShimHandler::HideAppForWindow(AppWindow* app_window) { |
| 260 ExtensionAppShimHandler* handler = GetInstance(); | 333 ExtensionAppShimHandler* handler = GetInstance(); |
| 261 Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); | 334 Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); |
| 262 Host* host = handler->FindHost(profile, app_window->extension_id()); | 335 Host* host = handler->FindHost(profile, app_window->extension_id()); |
| 263 if (host) | 336 if (host) |
| 264 host->OnAppHide(); | 337 host->OnAppHide(); |
| 265 else | 338 else |
| 266 SetAppHidden(profile, app_window->extension_id(), true); | 339 SetAppHidden(profile, app_window->extension_id(), true); |
| 267 } | 340 } |
| 268 | 341 |
| 342 void ExtensionAppShimHandler::HideHostedApp(Profile* profile, | |
| 343 const std::string& app_id) { | |
| 344 ExtensionAppShimHandler* handler = GetInstance(); | |
| 345 Host* host = handler->FindHost(profile, app_id); | |
| 346 if (host) | |
| 347 host->OnAppHide(); | |
| 348 else | |
| 349 handler->SetHostedAppHidden(profile, app_id, true); | |
| 350 } | |
| 351 | |
| 269 void ExtensionAppShimHandler::FocusAppForWindow(AppWindow* app_window) { | 352 void ExtensionAppShimHandler::FocusAppForWindow(AppWindow* app_window) { |
| 270 ExtensionAppShimHandler* handler = GetInstance(); | 353 ExtensionAppShimHandler* handler = GetInstance(); |
| 271 Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); | 354 Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); |
| 272 const std::string& app_id = app_window->extension_id(); | 355 const std::string& app_id = app_window->extension_id(); |
| 273 Host* host = handler->FindHost(profile, app_id); | 356 Host* host = handler->FindHost(profile, app_id); |
| 274 if (host) { | 357 if (host) { |
| 275 handler->OnShimFocus(host, | 358 handler->OnShimFocus(host, |
| 276 APP_SHIM_FOCUS_NORMAL, | 359 APP_SHIM_FOCUS_NORMAL, |
| 277 std::vector<base::FilePath>()); | 360 std::vector<base::FilePath>()); |
| 278 } else { | 361 } else { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 361 // Return now. OnAppLaunchComplete will be called when the app is activated. | 444 // Return now. OnAppLaunchComplete will be called when the app is activated. |
| 362 } | 445 } |
| 363 | 446 |
| 364 // static | 447 // static |
| 365 ExtensionAppShimHandler* ExtensionAppShimHandler::GetInstance() { | 448 ExtensionAppShimHandler* ExtensionAppShimHandler::GetInstance() { |
| 366 return g_browser_process->platform_part() | 449 return g_browser_process->platform_part() |
| 367 ->app_shim_host_manager() | 450 ->app_shim_host_manager() |
| 368 ->extension_app_shim_handler(); | 451 ->extension_app_shim_handler(); |
| 369 } | 452 } |
| 370 | 453 |
| 454 void ExtensionAppShimHandler::CloseBrowsersForApp(const std::string& app_id) { | |
| 455 AppBrowserMap::iterator it = app_browser_windows_.find(app_id); | |
| 456 if (it == app_browser_windows_.end()) | |
| 457 return; | |
| 458 | |
| 459 for (const Browser* browser : it->second) | |
| 460 browser->window()->Close(); | |
| 461 } | |
| 462 | |
| 371 void ExtensionAppShimHandler::OnProfileLoaded( | 463 void ExtensionAppShimHandler::OnProfileLoaded( |
| 372 Host* host, | 464 Host* host, |
| 373 AppShimLaunchType launch_type, | 465 AppShimLaunchType launch_type, |
| 374 const std::vector<base::FilePath>& files, | 466 const std::vector<base::FilePath>& files, |
| 375 Profile* profile) { | 467 Profile* profile) { |
| 376 const std::string& app_id = host->GetAppId(); | 468 const std::string& app_id = host->GetAppId(); |
| 377 | 469 |
| 378 // The first host to claim this (profile, app_id) becomes the main host. | 470 // The first host to claim this (profile, app_id) becomes the main host. |
| 379 // For any others, focus or relaunch the app. | 471 // For any others, focus or relaunch the app. |
| 380 if (!hosts_.insert(make_pair(make_pair(profile, app_id), host)).second) { | 472 if (!hosts_.insert(make_pair(make_pair(profile, app_id), host)).second) { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 392 } | 484 } |
| 393 | 485 |
| 394 // TODO(jeremya): Handle the case that launching the app fails. Probably we | 486 // TODO(jeremya): Handle the case that launching the app fails. Probably we |
| 395 // need to watch for 'app successfully launched' or at least 'background page | 487 // need to watch for 'app successfully launched' or at least 'background page |
| 396 // exists/was created' and time out with failure if we don't see that sign of | 488 // exists/was created' and time out with failure if we don't see that sign of |
| 397 // life within a certain window. | 489 // life within a certain window. |
| 398 const extensions::Extension* extension = | 490 const extensions::Extension* extension = |
| 399 delegate_->GetAppExtension(profile, app_id); | 491 delegate_->GetAppExtension(profile, app_id); |
| 400 if (extension) { | 492 if (extension) { |
| 401 delegate_->LaunchApp(profile, extension, files); | 493 delegate_->LaunchApp(profile, extension, files); |
| 402 // If it's a hosted app, just kill it immediately after opening for now. | 494 // If it's a hosted app that opens in a tab, let the shim terminate |
| 403 if (extension->is_hosted_app()) | 495 // immediately. |
| 496 if (extension->is_hosted_app() && | |
| 497 extensions::GetLaunchType(extensions::ExtensionPrefs::Get(profile), | |
| 498 extension) == | |
| 499 extensions::LAUNCH_TYPE_REGULAR) { | |
| 404 host->OnAppLaunchComplete(APP_SHIM_LAUNCH_DUPLICATE_HOST); | 500 host->OnAppLaunchComplete(APP_SHIM_LAUNCH_DUPLICATE_HOST); |
| 501 } | |
| 405 return; | 502 return; |
| 406 } | 503 } |
| 407 | 504 |
| 408 delegate_->EnableExtension( | 505 delegate_->EnableExtension( |
| 409 profile, app_id, | 506 profile, app_id, |
| 410 base::Bind(&ExtensionAppShimHandler::OnExtensionEnabled, | 507 base::Bind(&ExtensionAppShimHandler::OnExtensionEnabled, |
| 411 weak_factory_.GetWeakPtr(), | 508 weak_factory_.GetWeakPtr(), |
| 412 host->GetProfilePath(), app_id, files)); | 509 host->GetProfilePath(), app_id, files)); |
| 413 } | 510 } |
| 414 | 511 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 447 } | 544 } |
| 448 } | 545 } |
| 449 | 546 |
| 450 void ExtensionAppShimHandler::OnShimFocus( | 547 void ExtensionAppShimHandler::OnShimFocus( |
| 451 Host* host, | 548 Host* host, |
| 452 AppShimFocusType focus_type, | 549 AppShimFocusType focus_type, |
| 453 const std::vector<base::FilePath>& files) { | 550 const std::vector<base::FilePath>& files) { |
| 454 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); | 551 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); |
| 455 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); | 552 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); |
| 456 | 553 |
| 457 const AppWindowList windows = | 554 bool windows_focused; |
| 458 delegate_->GetWindows(profile, host->GetAppId()); | 555 const std::string& app_id = host->GetAppId(); |
| 459 bool windows_focused = FocusWindows(windows); | 556 if (delegate_->GetAppExtension(profile, app_id)->is_hosted_app()) { |
| 557 AppBrowserMap::iterator it = app_browser_windows_.find(app_id); | |
| 558 if (it == app_browser_windows_.end()) | |
| 559 return; | |
| 560 | |
| 561 windows_focused = FocusHostedAppWindows(it->second); | |
| 562 } else { | |
| 563 const AppWindowList windows = | |
| 564 delegate_->GetWindows(profile, host->GetAppId()); | |
| 565 windows_focused = FocusWindows(windows); | |
| 566 } | |
| 460 | 567 |
| 461 if (focus_type == APP_SHIM_FOCUS_NORMAL || | 568 if (focus_type == APP_SHIM_FOCUS_NORMAL || |
| 462 (focus_type == APP_SHIM_FOCUS_REOPEN && windows_focused)) { | 569 (focus_type == APP_SHIM_FOCUS_REOPEN && windows_focused)) { |
| 463 return; | 570 return; |
| 464 } | 571 } |
| 465 | 572 |
| 466 const extensions::Extension* extension = | 573 const extensions::Extension* extension = |
| 467 delegate_->GetAppExtension(profile, host->GetAppId()); | 574 delegate_->GetAppExtension(profile, host->GetAppId()); |
| 468 if (extension) { | 575 if (extension) { |
| 469 delegate_->LaunchApp(profile, extension, files); | 576 delegate_->LaunchApp(profile, extension, files); |
| 470 } else { | 577 } else { |
| 471 // Extensions may have been uninstalled or disabled since the shim | 578 // Extensions may have been uninstalled or disabled since the shim |
| 472 // started. | 579 // started. |
| 473 host->OnAppClosed(); | 580 host->OnAppClosed(); |
| 474 } | 581 } |
| 475 } | 582 } |
| 476 | 583 |
| 477 void ExtensionAppShimHandler::OnShimSetHidden(Host* host, bool hidden) { | 584 void ExtensionAppShimHandler::OnShimSetHidden(Host* host, bool hidden) { |
| 478 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); | 585 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); |
| 479 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); | 586 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); |
| 480 | 587 |
| 481 SetAppHidden(profile, host->GetAppId(), hidden); | 588 const std::string& app_id = host->GetAppId(); |
| 589 if (delegate_->GetAppExtension(profile, app_id)->is_hosted_app()) | |
| 590 SetHostedAppHidden(profile, app_id, hidden); | |
| 591 else | |
| 592 SetAppHidden(profile, app_id, hidden); | |
| 482 } | 593 } |
| 483 | 594 |
| 484 void ExtensionAppShimHandler::OnShimQuit(Host* host) { | 595 void ExtensionAppShimHandler::OnShimQuit(Host* host) { |
| 485 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); | 596 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); |
| 486 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); | 597 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); |
| 487 | 598 |
| 488 const std::string& app_id = host->GetAppId(); | 599 const std::string& app_id = host->GetAppId(); |
| 489 const AppWindowList windows = delegate_->GetWindows(profile, app_id); | 600 if (delegate_->GetAppExtension(profile, app_id)->is_hosted_app()) |
| 490 for (AppWindowRegistry::const_iterator it = windows.begin(); | 601 CloseBrowsersForApp(app_id); |
| 491 it != windows.end(); | 602 else { |
| 492 ++it) { | 603 const AppWindowList windows = delegate_->GetWindows(profile, app_id); |
| 493 (*it)->GetBaseWindow()->Close(); | 604 for (AppWindowRegistry::const_iterator it = windows.begin(); |
| 605 it != windows.end(); ++it) { | |
| 606 (*it)->GetBaseWindow()->Close(); | |
| 607 } | |
| 494 } | 608 } |
| 495 // Once the last window closes, flow will end up in OnAppDeactivated via | 609 // Once the last window closes, flow will end up in OnAppDeactivated via |
| 496 // AppLifetimeMonitor. | 610 // AppLifetimeMonitor. |
| 611 // Otherwise, once the last window closes for a hosted app, OnBrowserRemoved | |
| 612 // will call OnAppDeactivated. | |
| 497 } | 613 } |
| 498 | 614 |
| 499 void ExtensionAppShimHandler::set_delegate(Delegate* delegate) { | 615 void ExtensionAppShimHandler::set_delegate(Delegate* delegate) { |
| 500 delegate_.reset(delegate); | 616 delegate_.reset(delegate); |
| 501 } | 617 } |
| 502 | 618 |
| 503 void ExtensionAppShimHandler::Observe( | 619 void ExtensionAppShimHandler::Observe( |
| 504 int type, | 620 int type, |
| 505 const content::NotificationSource& source, | 621 const content::NotificationSource& source, |
| 506 const content::NotificationDetails& details) { | 622 const content::NotificationDetails& details) { |
| 507 Profile* profile = content::Source<Profile>(source).ptr(); | |
| 508 if (profile->IsOffTheRecord()) | |
| 509 return; | |
| 510 | |
| 511 switch (type) { | 623 switch (type) { |
| 512 case chrome::NOTIFICATION_PROFILE_CREATED: { | 624 case chrome::NOTIFICATION_PROFILE_CREATED: { |
| 625 Profile* profile = content::Source<Profile>(source).ptr(); | |
| 626 if (profile->IsOffTheRecord()) | |
| 627 return; | |
| 628 | |
| 513 AppLifetimeMonitorFactory::GetForProfile(profile)->AddObserver(this); | 629 AppLifetimeMonitorFactory::GetForProfile(profile)->AddObserver(this); |
| 514 break; | 630 break; |
| 515 } | 631 } |
| 516 case chrome::NOTIFICATION_PROFILE_DESTROYED: { | 632 case chrome::NOTIFICATION_PROFILE_DESTROYED: { |
| 633 Profile* profile = content::Source<Profile>(source).ptr(); | |
| 634 if (profile->IsOffTheRecord()) | |
| 635 return; | |
| 636 | |
| 517 AppLifetimeMonitorFactory::GetForProfile(profile)->RemoveObserver(this); | 637 AppLifetimeMonitorFactory::GetForProfile(profile)->RemoveObserver(this); |
| 518 // Shut down every shim associated with this profile. | 638 // Shut down every shim associated with this profile. |
| 519 for (HostMap::iterator it = hosts_.begin(); it != hosts_.end(); ) { | 639 for (HostMap::iterator it = hosts_.begin(); it != hosts_.end(); ) { |
| 520 // Increment the iterator first as OnAppClosed may call back to | 640 // Increment the iterator first as OnAppClosed may call back to |
| 521 // OnShimClose and invalidate the iterator. | 641 // OnShimClose and invalidate the iterator. |
| 522 HostMap::iterator current = it++; | 642 HostMap::iterator current = it++; |
| 523 if (profile->IsSameProfile(current->first.first)) { | 643 if (profile->IsSameProfile(current->first.first)) { |
| 524 Host* host = current->second; | 644 Host* host = current->second; |
| 525 host->OnAppClosed(); | 645 host->OnAppClosed(); |
| 526 } | 646 } |
| 527 } | 647 } |
| 528 break; | 648 break; |
| 529 } | 649 } |
| 650 case chrome::NOTIFICATION_BROWSER_WINDOW_READY: { | |
| 651 Browser* browser = content::Source<Browser>(source).ptr(); | |
| 652 // Don't keep track of browsers that are not associated with an app. | |
| 653 std::string app_id = | |
|
jackhou1
2014/12/12 04:42:49
No need for this, you can use extension->id() belo
mitchellj
2014/12/14 22:28:57
Done.
| |
| 654 web_app::GetExtensionIdFromApplicationName(browser->app_name()); | |
| 655 const extensions::Extension* extension = GetAppForBrowser(browser); | |
| 656 if (!extension) | |
| 657 return; | |
| 658 | |
| 659 BrowserSet& browsers = app_browser_windows_[app_id]; | |
| 660 browsers.insert(browser); | |
| 661 if (browsers.size() == 1) | |
| 662 OnAppActivated(browser->profile(), app_id); | |
| 663 | |
| 664 break; | |
| 665 } | |
| 530 default: { | 666 default: { |
| 531 NOTREACHED(); // Unexpected notification. | 667 NOTREACHED(); // Unexpected notification. |
| 532 break; | 668 break; |
| 533 } | 669 } |
| 534 } | 670 } |
| 535 } | 671 } |
| 536 | 672 |
| 537 void ExtensionAppShimHandler::OnAppStart(Profile* profile, | 673 void ExtensionAppShimHandler::OnAppStart(Profile* profile, |
| 538 const std::string& app_id) {} | 674 const std::string& app_id) {} |
| 539 | 675 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 562 | 698 |
| 563 if (hosts_.empty()) | 699 if (hosts_.empty()) |
| 564 delegate_->MaybeTerminate(); | 700 delegate_->MaybeTerminate(); |
| 565 } | 701 } |
| 566 | 702 |
| 567 void ExtensionAppShimHandler::OnAppStop(Profile* profile, | 703 void ExtensionAppShimHandler::OnAppStop(Profile* profile, |
| 568 const std::string& app_id) {} | 704 const std::string& app_id) {} |
| 569 | 705 |
| 570 void ExtensionAppShimHandler::OnChromeTerminating() {} | 706 void ExtensionAppShimHandler::OnChromeTerminating() {} |
| 571 | 707 |
| 708 // The BrowserWindow may be NULL when this is called. | |
| 709 // Therefore we listen for the notification | |
| 710 // chrome::NOTIFICATION_BROWSER_WINDOW_READY and then call OnAppActivated. | |
| 711 // If this notification is removed, check that OnBrowserAdded is called after | |
| 712 // the BrowserWindow is ready. | |
| 713 void ExtensionAppShimHandler::OnBrowserAdded(Browser* browser) { | |
| 714 } | |
| 715 | |
| 716 void ExtensionAppShimHandler::OnBrowserRemoved(Browser* browser) { | |
| 717 std::string app_id = | |
|
jackhou1
2014/12/12 04:42:49
Same here.
mitchellj
2014/12/14 22:28:57
Done.
| |
| 718 web_app::GetExtensionIdFromApplicationName(browser->app_name()); | |
| 719 const extensions::Extension* extension = GetAppForBrowser(browser); | |
| 720 if (!extension) | |
| 721 return; | |
| 722 | |
| 723 AppBrowserMap::iterator it = app_browser_windows_.find(app_id); | |
| 724 if (it != app_browser_windows_.end()) { | |
| 725 BrowserSet& browsers = it->second; | |
| 726 browsers.erase(browser); | |
| 727 if (browsers.empty()) | |
| 728 OnAppDeactivated(browser->profile(), app_id); | |
| 729 } | |
| 730 } | |
| 731 | |
| 572 } // namespace apps | 732 } // namespace apps |
| OLD | NEW |