Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc

Issue 790043002: Hosted apps on OS X now act more like a native app. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@creating-app-shims-2
Patch Set: Moved functions, cleaned up code and created CloseBrowsersForApp function Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698