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()) |
| 298 return NULL; |
| 299 |
| 300 return GetAppExtension( |
| 301 browser->profile(), |
| 302 web_app::GetExtensionIdFromApplicationName(browser->app_name())); |
| 303 } |
| 304 |
243 // static | 305 // static |
244 void ExtensionAppShimHandler::QuitAppForWindow(AppWindow* app_window) { | 306 void ExtensionAppShimHandler::QuitAppForWindow(AppWindow* app_window) { |
245 ExtensionAppShimHandler* handler = GetInstance(); | 307 ExtensionAppShimHandler* handler = GetInstance(); |
246 Host* host = handler->FindHost( | 308 Host* host = handler->FindHost( |
247 Profile::FromBrowserContext(app_window->browser_context()), | 309 Profile::FromBrowserContext(app_window->browser_context()), |
248 app_window->extension_id()); | 310 app_window->extension_id()); |
249 if (host) { | 311 if (host) { |
250 handler->OnShimQuit(host); | 312 handler->OnShimQuit(host); |
251 } else { | 313 } else { |
252 // App shims might be disabled or the shim is still starting up. | 314 // App shims might be disabled or the shim is still starting up. |
253 AppWindowRegistry::Get( | 315 AppWindowRegistry::Get( |
254 Profile::FromBrowserContext(app_window->browser_context())) | 316 Profile::FromBrowserContext(app_window->browser_context())) |
255 ->CloseAllAppWindowsForApp(app_window->extension_id()); | 317 ->CloseAllAppWindowsForApp(app_window->extension_id()); |
256 } | 318 } |
257 } | 319 } |
258 | 320 |
| 321 // static |
| 322 void ExtensionAppShimHandler::QuitHostedAppForWindow( |
| 323 Profile* profile, |
| 324 const std::string& app_id) { |
| 325 ExtensionAppShimHandler* handler = GetInstance(); |
| 326 Host* host = handler->FindHost(Profile::FromBrowserContext(profile), app_id); |
| 327 if (host) |
| 328 handler->OnShimQuit(host); |
| 329 else |
| 330 handler->CloseBrowsersForApp(app_id); |
| 331 } |
| 332 |
259 void ExtensionAppShimHandler::HideAppForWindow(AppWindow* app_window) { | 333 void ExtensionAppShimHandler::HideAppForWindow(AppWindow* app_window) { |
260 ExtensionAppShimHandler* handler = GetInstance(); | 334 ExtensionAppShimHandler* handler = GetInstance(); |
261 Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); | 335 Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); |
262 Host* host = handler->FindHost(profile, app_window->extension_id()); | 336 Host* host = handler->FindHost(profile, app_window->extension_id()); |
263 if (host) | 337 if (host) |
264 host->OnAppHide(); | 338 host->OnAppHide(); |
265 else | 339 else |
266 SetAppHidden(profile, app_window->extension_id(), true); | 340 SetAppHidden(profile, app_window->extension_id(), true); |
267 } | 341 } |
268 | 342 |
| 343 void ExtensionAppShimHandler::HideHostedApp(Profile* profile, |
| 344 const std::string& app_id) { |
| 345 ExtensionAppShimHandler* handler = GetInstance(); |
| 346 Host* host = handler->FindHost(profile, app_id); |
| 347 if (host) |
| 348 host->OnAppHide(); |
| 349 else |
| 350 handler->SetHostedAppHidden(profile, app_id, true); |
| 351 } |
| 352 |
269 void ExtensionAppShimHandler::FocusAppForWindow(AppWindow* app_window) { | 353 void ExtensionAppShimHandler::FocusAppForWindow(AppWindow* app_window) { |
270 ExtensionAppShimHandler* handler = GetInstance(); | 354 ExtensionAppShimHandler* handler = GetInstance(); |
271 Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); | 355 Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); |
272 const std::string& app_id = app_window->extension_id(); | 356 const std::string& app_id = app_window->extension_id(); |
273 Host* host = handler->FindHost(profile, app_id); | 357 Host* host = handler->FindHost(profile, app_id); |
274 if (host) { | 358 if (host) { |
275 handler->OnShimFocus(host, | 359 handler->OnShimFocus(host, |
276 APP_SHIM_FOCUS_NORMAL, | 360 APP_SHIM_FOCUS_NORMAL, |
277 std::vector<base::FilePath>()); | 361 std::vector<base::FilePath>()); |
278 } else { | 362 } 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. | 445 // Return now. OnAppLaunchComplete will be called when the app is activated. |
362 } | 446 } |
363 | 447 |
364 // static | 448 // static |
365 ExtensionAppShimHandler* ExtensionAppShimHandler::GetInstance() { | 449 ExtensionAppShimHandler* ExtensionAppShimHandler::GetInstance() { |
366 return g_browser_process->platform_part() | 450 return g_browser_process->platform_part() |
367 ->app_shim_host_manager() | 451 ->app_shim_host_manager() |
368 ->extension_app_shim_handler(); | 452 ->extension_app_shim_handler(); |
369 } | 453 } |
370 | 454 |
| 455 void ExtensionAppShimHandler::CloseBrowsersForApp(const std::string& app_id) { |
| 456 AppBrowserMap::iterator it = app_browser_windows_.find(app_id); |
| 457 if (it == app_browser_windows_.end()) |
| 458 return; |
| 459 |
| 460 for (const Browser* browser : it->second) |
| 461 browser->window()->Close(); |
| 462 } |
| 463 |
371 void ExtensionAppShimHandler::OnProfileLoaded( | 464 void ExtensionAppShimHandler::OnProfileLoaded( |
372 Host* host, | 465 Host* host, |
373 AppShimLaunchType launch_type, | 466 AppShimLaunchType launch_type, |
374 const std::vector<base::FilePath>& files, | 467 const std::vector<base::FilePath>& files, |
375 Profile* profile) { | 468 Profile* profile) { |
376 const std::string& app_id = host->GetAppId(); | 469 const std::string& app_id = host->GetAppId(); |
377 | 470 |
378 // The first host to claim this (profile, app_id) becomes the main host. | 471 // The first host to claim this (profile, app_id) becomes the main host. |
379 // For any others, focus or relaunch the app. | 472 // For any others, focus or relaunch the app. |
380 if (!hosts_.insert(make_pair(make_pair(profile, app_id), host)).second) { | 473 if (!hosts_.insert(make_pair(make_pair(profile, app_id), host)).second) { |
(...skipping 11 matching lines...) Expand all Loading... |
392 } | 485 } |
393 | 486 |
394 // TODO(jeremya): Handle the case that launching the app fails. Probably we | 487 // 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 | 488 // 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 | 489 // exists/was created' and time out with failure if we don't see that sign of |
397 // life within a certain window. | 490 // life within a certain window. |
398 const extensions::Extension* extension = | 491 const extensions::Extension* extension = |
399 delegate_->GetAppExtension(profile, app_id); | 492 delegate_->GetAppExtension(profile, app_id); |
400 if (extension) { | 493 if (extension) { |
401 delegate_->LaunchApp(profile, extension, files); | 494 delegate_->LaunchApp(profile, extension, files); |
402 // If it's a hosted app, just kill it immediately after opening for now. | 495 // If it's a hosted app that opens in a tab, let the shim terminate |
403 if (extension->is_hosted_app()) | 496 // immediately. |
| 497 if (extension->is_hosted_app() && |
| 498 extensions::GetLaunchType(extensions::ExtensionPrefs::Get(profile), |
| 499 extension) == |
| 500 extensions::LAUNCH_TYPE_REGULAR) { |
404 host->OnAppLaunchComplete(APP_SHIM_LAUNCH_DUPLICATE_HOST); | 501 host->OnAppLaunchComplete(APP_SHIM_LAUNCH_DUPLICATE_HOST); |
| 502 } |
405 return; | 503 return; |
406 } | 504 } |
407 | 505 |
408 delegate_->EnableExtension( | 506 delegate_->EnableExtension( |
409 profile, app_id, | 507 profile, app_id, |
410 base::Bind(&ExtensionAppShimHandler::OnExtensionEnabled, | 508 base::Bind(&ExtensionAppShimHandler::OnExtensionEnabled, |
411 weak_factory_.GetWeakPtr(), | 509 weak_factory_.GetWeakPtr(), |
412 host->GetProfilePath(), app_id, files)); | 510 host->GetProfilePath(), app_id, files)); |
413 } | 511 } |
414 | 512 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 } | 545 } |
448 } | 546 } |
449 | 547 |
450 void ExtensionAppShimHandler::OnShimFocus( | 548 void ExtensionAppShimHandler::OnShimFocus( |
451 Host* host, | 549 Host* host, |
452 AppShimFocusType focus_type, | 550 AppShimFocusType focus_type, |
453 const std::vector<base::FilePath>& files) { | 551 const std::vector<base::FilePath>& files) { |
454 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); | 552 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); |
455 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); | 553 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); |
456 | 554 |
457 const AppWindowList windows = | 555 bool windows_focused; |
458 delegate_->GetWindows(profile, host->GetAppId()); | 556 const std::string& app_id = host->GetAppId(); |
459 bool windows_focused = FocusWindows(windows); | 557 if (delegate_->GetAppExtension(profile, app_id)->is_hosted_app()) { |
| 558 AppBrowserMap::iterator it = app_browser_windows_.find(app_id); |
| 559 if (it == app_browser_windows_.end()) |
| 560 return; |
| 561 |
| 562 windows_focused = FocusHostedAppWindows(it->second); |
| 563 } else { |
| 564 const AppWindowList windows = |
| 565 delegate_->GetWindows(profile, host->GetAppId()); |
| 566 windows_focused = FocusWindows(windows); |
| 567 } |
460 | 568 |
461 if (focus_type == APP_SHIM_FOCUS_NORMAL || | 569 if (focus_type == APP_SHIM_FOCUS_NORMAL || |
462 (focus_type == APP_SHIM_FOCUS_REOPEN && windows_focused)) { | 570 (focus_type == APP_SHIM_FOCUS_REOPEN && windows_focused)) { |
463 return; | 571 return; |
464 } | 572 } |
465 | 573 |
466 const extensions::Extension* extension = | 574 const extensions::Extension* extension = |
467 delegate_->GetAppExtension(profile, host->GetAppId()); | 575 delegate_->GetAppExtension(profile, host->GetAppId()); |
468 if (extension) { | 576 if (extension) { |
469 delegate_->LaunchApp(profile, extension, files); | 577 delegate_->LaunchApp(profile, extension, files); |
470 } else { | 578 } else { |
471 // Extensions may have been uninstalled or disabled since the shim | 579 // Extensions may have been uninstalled or disabled since the shim |
472 // started. | 580 // started. |
473 host->OnAppClosed(); | 581 host->OnAppClosed(); |
474 } | 582 } |
475 } | 583 } |
476 | 584 |
477 void ExtensionAppShimHandler::OnShimSetHidden(Host* host, bool hidden) { | 585 void ExtensionAppShimHandler::OnShimSetHidden(Host* host, bool hidden) { |
478 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); | 586 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); |
479 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); | 587 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); |
480 | 588 |
481 SetAppHidden(profile, host->GetAppId(), hidden); | 589 const std::string& app_id = host->GetAppId(); |
| 590 if (delegate_->GetAppExtension(profile, app_id)->is_hosted_app()) |
| 591 SetHostedAppHidden(profile, app_id, hidden); |
| 592 else |
| 593 SetAppHidden(profile, app_id, hidden); |
482 } | 594 } |
483 | 595 |
484 void ExtensionAppShimHandler::OnShimQuit(Host* host) { | 596 void ExtensionAppShimHandler::OnShimQuit(Host* host) { |
485 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); | 597 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); |
486 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); | 598 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); |
487 | 599 |
488 const std::string& app_id = host->GetAppId(); | 600 const std::string& app_id = host->GetAppId(); |
489 const AppWindowList windows = delegate_->GetWindows(profile, app_id); | 601 if (delegate_->GetAppExtension(profile, app_id)->is_hosted_app()) |
490 for (AppWindowRegistry::const_iterator it = windows.begin(); | 602 CloseBrowsersForApp(app_id); |
491 it != windows.end(); | 603 else { |
492 ++it) { | 604 const AppWindowList windows = delegate_->GetWindows(profile, app_id); |
493 (*it)->GetBaseWindow()->Close(); | 605 for (AppWindowRegistry::const_iterator it = windows.begin(); |
| 606 it != windows.end(); ++it) { |
| 607 (*it)->GetBaseWindow()->Close(); |
| 608 } |
494 } | 609 } |
495 // Once the last window closes, flow will end up in OnAppDeactivated via | 610 // Once the last window closes, flow will end up in OnAppDeactivated via |
496 // AppLifetimeMonitor. | 611 // AppLifetimeMonitor. |
| 612 // Otherwise, once the last window closes for a hosted app, OnBrowserRemoved |
| 613 // will call OnAppDeactivated. |
497 } | 614 } |
498 | 615 |
499 void ExtensionAppShimHandler::set_delegate(Delegate* delegate) { | 616 void ExtensionAppShimHandler::set_delegate(Delegate* delegate) { |
500 delegate_.reset(delegate); | 617 delegate_.reset(delegate); |
501 } | 618 } |
502 | 619 |
503 void ExtensionAppShimHandler::Observe( | 620 void ExtensionAppShimHandler::Observe( |
504 int type, | 621 int type, |
505 const content::NotificationSource& source, | 622 const content::NotificationSource& source, |
506 const content::NotificationDetails& details) { | 623 const content::NotificationDetails& details) { |
507 Profile* profile = content::Source<Profile>(source).ptr(); | |
508 if (profile->IsOffTheRecord()) | |
509 return; | |
510 | |
511 switch (type) { | 624 switch (type) { |
512 case chrome::NOTIFICATION_PROFILE_CREATED: { | 625 case chrome::NOTIFICATION_PROFILE_CREATED: { |
| 626 Profile* profile = content::Source<Profile>(source).ptr(); |
| 627 if (profile->IsOffTheRecord()) |
| 628 return; |
| 629 |
513 AppLifetimeMonitorFactory::GetForProfile(profile)->AddObserver(this); | 630 AppLifetimeMonitorFactory::GetForProfile(profile)->AddObserver(this); |
514 break; | 631 break; |
515 } | 632 } |
516 case chrome::NOTIFICATION_PROFILE_DESTROYED: { | 633 case chrome::NOTIFICATION_PROFILE_DESTROYED: { |
| 634 Profile* profile = content::Source<Profile>(source).ptr(); |
| 635 if (profile->IsOffTheRecord()) |
| 636 return; |
| 637 |
517 AppLifetimeMonitorFactory::GetForProfile(profile)->RemoveObserver(this); | 638 AppLifetimeMonitorFactory::GetForProfile(profile)->RemoveObserver(this); |
518 // Shut down every shim associated with this profile. | 639 // Shut down every shim associated with this profile. |
519 for (HostMap::iterator it = hosts_.begin(); it != hosts_.end(); ) { | 640 for (HostMap::iterator it = hosts_.begin(); it != hosts_.end(); ) { |
520 // Increment the iterator first as OnAppClosed may call back to | 641 // Increment the iterator first as OnAppClosed may call back to |
521 // OnShimClose and invalidate the iterator. | 642 // OnShimClose and invalidate the iterator. |
522 HostMap::iterator current = it++; | 643 HostMap::iterator current = it++; |
523 if (profile->IsSameProfile(current->first.first)) { | 644 if (profile->IsSameProfile(current->first.first)) { |
524 Host* host = current->second; | 645 Host* host = current->second; |
525 host->OnAppClosed(); | 646 host->OnAppClosed(); |
526 } | 647 } |
527 } | 648 } |
528 break; | 649 break; |
529 } | 650 } |
| 651 case chrome::NOTIFICATION_BROWSER_WINDOW_READY: { |
| 652 Browser* browser = content::Source<Browser>(source).ptr(); |
| 653 // Don't keep track of browsers that are not associated with an app. |
| 654 const extensions::Extension* extension = GetAppForBrowser(browser); |
| 655 if (!extension) |
| 656 return; |
| 657 |
| 658 BrowserSet& browsers = app_browser_windows_[extension->id()]; |
| 659 browsers.insert(browser); |
| 660 if (browsers.size() == 1) |
| 661 OnAppActivated(browser->profile(), extension->id()); |
| 662 |
| 663 break; |
| 664 } |
530 default: { | 665 default: { |
531 NOTREACHED(); // Unexpected notification. | 666 NOTREACHED(); // Unexpected notification. |
532 break; | 667 break; |
533 } | 668 } |
534 } | 669 } |
535 } | 670 } |
536 | 671 |
537 void ExtensionAppShimHandler::OnAppStart(Profile* profile, | 672 void ExtensionAppShimHandler::OnAppStart(Profile* profile, |
538 const std::string& app_id) {} | 673 const std::string& app_id) {} |
539 | 674 |
(...skipping 22 matching lines...) Expand all Loading... |
562 | 697 |
563 if (hosts_.empty()) | 698 if (hosts_.empty()) |
564 delegate_->MaybeTerminate(); | 699 delegate_->MaybeTerminate(); |
565 } | 700 } |
566 | 701 |
567 void ExtensionAppShimHandler::OnAppStop(Profile* profile, | 702 void ExtensionAppShimHandler::OnAppStop(Profile* profile, |
568 const std::string& app_id) {} | 703 const std::string& app_id) {} |
569 | 704 |
570 void ExtensionAppShimHandler::OnChromeTerminating() {} | 705 void ExtensionAppShimHandler::OnChromeTerminating() {} |
571 | 706 |
| 707 // The BrowserWindow may be NULL when this is called. |
| 708 // Therefore we listen for the notification |
| 709 // chrome::NOTIFICATION_BROWSER_WINDOW_READY and then call OnAppActivated. |
| 710 // If this notification is removed, check that OnBrowserAdded is called after |
| 711 // the BrowserWindow is ready. |
| 712 void ExtensionAppShimHandler::OnBrowserAdded(Browser* browser) { |
| 713 } |
| 714 |
| 715 void ExtensionAppShimHandler::OnBrowserRemoved(Browser* browser) { |
| 716 const extensions::Extension* extension = GetAppForBrowser(browser); |
| 717 if (!extension) |
| 718 return; |
| 719 |
| 720 AppBrowserMap::iterator it = app_browser_windows_.find(extension->id()); |
| 721 if (it != app_browser_windows_.end()) { |
| 722 BrowserSet& browsers = it->second; |
| 723 browsers.erase(browser); |
| 724 if (browsers.empty()) |
| 725 OnAppDeactivated(browser->profile(), extension->id()); |
| 726 } |
| 727 } |
| 728 |
572 } // namespace apps | 729 } // namespace apps |
OLD | NEW |