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

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: 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"
22 #include "chrome/browser/ui/tabs/tab_strip_model.h"
19 #include "chrome/browser/web_applications/web_app_mac.h" 23 #include "chrome/browser/web_applications/web_app_mac.h"
20 #include "chrome/common/extensions/extension_constants.h" 24 #include "chrome/common/extensions/extension_constants.h"
21 #include "chrome/common/extensions/extension_metrics.h" 25 #include "chrome/common/extensions/extension_metrics.h"
22 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 26 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
23 #include "chrome/common/mac/app_shim_messages.h" 27 #include "chrome/common/mac/app_shim_messages.h"
24 #include "components/crx_file/id_util.h" 28 #include "components/crx_file/id_util.h"
25 #include "content/public/browser/notification_details.h" 29 #include "content/public/browser/notification_details.h"
26 #include "content/public/browser/notification_service.h" 30 #include "content/public/browser/notification_service.h"
27 #include "content/public/browser/notification_source.h" 31 #include "content/public/browser/notification_source.h"
28 #include "extensions/browser/app_window/app_window.h" 32 #include "extensions/browser/app_window/app_window.h"
29 #include "extensions/browser/app_window/app_window_registry.h" 33 #include "extensions/browser/app_window/app_window_registry.h"
30 #include "extensions/browser/app_window/native_app_window.h" 34 #include "extensions/browser/app_window/native_app_window.h"
31 #include "extensions/browser/extension_host.h" 35 #include "extensions/browser/extension_host.h"
36 #include "extensions/browser/extension_prefs.h"
32 #include "extensions/browser/extension_registry.h" 37 #include "extensions/browser/extension_registry.h"
33 #include "extensions/common/constants.h" 38 #include "extensions/common/constants.h"
34 #include "ui/base/cocoa/focus_window_set.h" 39 #include "ui/base/cocoa/focus_window_set.h"
35 40
36 using extensions::AppWindow; 41 using extensions::AppWindow;
37 using extensions::AppWindowRegistry; 42 using extensions::AppWindowRegistry;
38 using extensions::ExtensionRegistry; 43 using extensions::ExtensionRegistry;
39 44
40 namespace { 45 namespace {
41 46
(...skipping 17 matching lines...) Expand all
59 for (AppWindowList::const_reverse_iterator it = windows.rbegin(); 64 for (AppWindowList::const_reverse_iterator it = windows.rbegin();
60 it != windows.rend(); 65 it != windows.rend();
61 ++it) { 66 ++it) {
62 if (hidden) 67 if (hidden)
63 (*it)->GetBaseWindow()->HideWithApp(); 68 (*it)->GetBaseWindow()->HideWithApp();
64 else 69 else
65 (*it)->GetBaseWindow()->ShowWithApp(); 70 (*it)->GetBaseWindow()->ShowWithApp();
66 } 71 }
67 } 72 }
68 73
74 void SetHostedAppHidden(Profile* profile,
jackhou1 2014/12/11 02:43:18 Maybe make this a method of ExtensionAppShimHandle
mitchellj 2014/12/12 00:03:45 Done.
75 const std::string& app_id,
76 bool hidden) {
77 const BrowserList* browser_list =
78 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE);
79
80 for (BrowserList::const_iterator it = browser_list->begin();
jackhou1 2014/12/11 02:43:18 You can use C++11's range-based for-loops now: fo
mitchellj 2014/12/12 00:03:45 Done.
81 it != browser_list->end(); ++it) {
82 Browser* browser = *it;
83
84 if (!browser->is_app() ||
85 web_app::GetExtensionIdFromApplicationName(browser->app_name()) !=
86 app_id) {
87 continue;
88 }
89
90 TabStripModel* tab_strip = browser->tab_strip_model();
91 for (int index = 0; index < tab_strip->count(); index++) {
92 if (hidden)
jackhou1 2014/12/11 02:43:18 Do you need this loop? It doesn't look like this b
mitchellj 2014/12/12 00:03:45 Done.
93 browser->window()->Hide();
94 else
95 browser->window()->Show();
96 }
97 }
98 }
99
69 bool FocusWindows(const AppWindowList& windows) { 100 bool FocusWindows(const AppWindowList& windows) {
70 if (windows.empty()) 101 if (windows.empty())
71 return false; 102 return false;
72 103
73 std::set<gfx::NativeWindow> native_windows; 104 std::set<gfx::NativeWindow> native_windows;
74 for (AppWindowList::const_iterator it = windows.begin(); it != windows.end(); 105 for (AppWindowList::const_iterator it = windows.begin(); it != windows.end();
75 ++it) { 106 ++it) {
76 native_windows.insert((*it)->GetNativeWindow()); 107 native_windows.insert((*it)->GetNativeWindow());
77 } 108 }
78 // Allow workspace switching. For the browser process, we can reasonably rely 109 // 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 110 // 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. 111 // don't have windows, so we have to do it ourselves.
81 ui::FocusWindowSet(native_windows); 112 ui::FocusWindowSet(native_windows);
82 return true; 113 return true;
83 } 114 }
84 115
116 bool FocusHostedAppWindows(std::vector<content::WebContents*>& windows) {
jackhou1 2014/12/11 02:43:18 Just pass in the BrowserSet here. You can get the
mitchellj 2014/12/12 00:03:45 Done.
117 if (windows.empty())
118 return false;
119
120 std::set<gfx::NativeWindow> native_windows;
121 for (std::vector<content::WebContents*>::const_iterator it = windows.begin();
122 it != windows.end(); ++it) {
123 native_windows.insert((*it)->GetTopLevelNativeWindow());
124 }
125
126 ui::FocusWindowSet(native_windows);
127 return true;
128 }
129
85 // Attempts to launch a packaged app, prompting the user to enable it if 130 // Attempts to launch a packaged app, prompting the user to enable it if
86 // necessary. The prompt is shown in its own window. 131 // necessary. The prompt is shown in its own window.
87 // This class manages its own lifetime. 132 // This class manages its own lifetime.
88 class EnableViaPrompt : public ExtensionEnableFlowDelegate { 133 class EnableViaPrompt : public ExtensionEnableFlowDelegate {
89 public: 134 public:
90 EnableViaPrompt(Profile* profile, 135 EnableViaPrompt(Profile* profile,
91 const std::string& extension_id, 136 const std::string& extension_id,
92 const base::Callback<void()>& callback) 137 const base::Callback<void()>& callback)
93 : profile_(profile), 138 : profile_(profile),
94 extension_id_(extension_id), 139 extension_id_(extension_id),
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 : delegate_(new Delegate), 267 : delegate_(new Delegate),
223 weak_factory_(this) { 268 weak_factory_(this) {
224 // This is instantiated in BrowserProcessImpl::PreMainMessageLoopRun with 269 // This is instantiated in BrowserProcessImpl::PreMainMessageLoopRun with
225 // AppShimHostManager. Since PROFILE_CREATED is not fired until 270 // AppShimHostManager. Since PROFILE_CREATED is not fired until
226 // ProfileManager::GetLastUsedProfile/GetLastOpenedProfiles, this should catch 271 // ProfileManager::GetLastUsedProfile/GetLastOpenedProfiles, this should catch
227 // notifications for all profiles. 272 // notifications for all profiles.
228 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, 273 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED,
229 content::NotificationService::AllBrowserContextsAndSources()); 274 content::NotificationService::AllBrowserContextsAndSources());
230 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 275 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
231 content::NotificationService::AllBrowserContextsAndSources()); 276 content::NotificationService::AllBrowserContextsAndSources());
277 BrowserList::AddObserver(this);
232 } 278 }
233 279
234 ExtensionAppShimHandler::~ExtensionAppShimHandler() {} 280 ExtensionAppShimHandler::~ExtensionAppShimHandler() {
281 BrowserList::RemoveObserver(this);
282 }
235 283
236 AppShimHandler::Host* ExtensionAppShimHandler::FindHost( 284 AppShimHandler::Host* ExtensionAppShimHandler::FindHost(
237 Profile* profile, 285 Profile* profile,
238 const std::string& app_id) { 286 const std::string& app_id) {
239 HostMap::iterator it = hosts_.find(make_pair(profile, app_id)); 287 HostMap::iterator it = hosts_.find(make_pair(profile, app_id));
240 return it == hosts_.end() ? NULL : it->second; 288 return it == hosts_.end() ? NULL : it->second;
241 } 289 }
242 290
243 // static 291 // static
244 void ExtensionAppShimHandler::QuitAppForWindow(AppWindow* app_window) { 292 void ExtensionAppShimHandler::QuitAppForWindow(AppWindow* app_window) {
245 ExtensionAppShimHandler* handler = GetInstance(); 293 ExtensionAppShimHandler* handler = GetInstance();
246 Host* host = handler->FindHost( 294 Host* host = handler->FindHost(
247 Profile::FromBrowserContext(app_window->browser_context()), 295 Profile::FromBrowserContext(app_window->browser_context()),
248 app_window->extension_id()); 296 app_window->extension_id());
249 if (host) { 297 if (host) {
250 handler->OnShimQuit(host); 298 handler->OnShimQuit(host);
251 } else { 299 } else {
252 // App shims might be disabled or the shim is still starting up. 300 // App shims might be disabled or the shim is still starting up.
253 AppWindowRegistry::Get( 301 AppWindowRegistry::Get(
254 Profile::FromBrowserContext(app_window->browser_context())) 302 Profile::FromBrowserContext(app_window->browser_context()))
255 ->CloseAllAppWindowsForApp(app_window->extension_id()); 303 ->CloseAllAppWindowsForApp(app_window->extension_id());
256 } 304 }
257 } 305 }
258 306
307 // static
308 void ExtensionAppShimHandler::QuitHostedAppForWindow(
309 Browser* browser,
310 const extensions::Extension* extension) {
311 ExtensionAppShimHandler* handler = GetInstance();
312 Host* host = handler->FindHost(
313 Profile::FromBrowserContext(browser->profile()), extension->id());
314 if (host && extension->is_hosted_app()) {
315 handler->OnShimQuit(host);
316 }
317 }
318
259 void ExtensionAppShimHandler::HideAppForWindow(AppWindow* app_window) { 319 void ExtensionAppShimHandler::HideAppForWindow(AppWindow* app_window) {
260 ExtensionAppShimHandler* handler = GetInstance(); 320 ExtensionAppShimHandler* handler = GetInstance();
261 Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); 321 Profile* profile = Profile::FromBrowserContext(app_window->browser_context());
262 Host* host = handler->FindHost(profile, app_window->extension_id()); 322 Host* host = handler->FindHost(profile, app_window->extension_id());
263 if (host) 323 if (host)
264 host->OnAppHide(); 324 host->OnAppHide();
265 else 325 else
266 SetAppHidden(profile, app_window->extension_id(), true); 326 SetAppHidden(profile, app_window->extension_id(), true);
267 } 327 }
268 328
329 void ExtensionAppShimHandler::HideHostedApp(Profile* profile,
330 const std::string& app_id) {
331 ExtensionAppShimHandler* handler = GetInstance();
332 Host* host = handler->FindHost(profile, app_id);
333 if (host)
334 host->OnAppHide();
335 else
336 SetHostedAppHidden(profile, app_id, true);
337 }
338
269 void ExtensionAppShimHandler::FocusAppForWindow(AppWindow* app_window) { 339 void ExtensionAppShimHandler::FocusAppForWindow(AppWindow* app_window) {
270 ExtensionAppShimHandler* handler = GetInstance(); 340 ExtensionAppShimHandler* handler = GetInstance();
271 Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); 341 Profile* profile = Profile::FromBrowserContext(app_window->browser_context());
272 const std::string& app_id = app_window->extension_id(); 342 const std::string& app_id = app_window->extension_id();
273 Host* host = handler->FindHost(profile, app_id); 343 Host* host = handler->FindHost(profile, app_id);
274 if (host) { 344 if (host) {
275 handler->OnShimFocus(host, 345 handler->OnShimFocus(host,
276 APP_SHIM_FOCUS_NORMAL, 346 APP_SHIM_FOCUS_NORMAL,
277 std::vector<base::FilePath>()); 347 std::vector<base::FilePath>());
278 } else { 348 } else {
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 } 462 }
393 463
394 // TODO(jeremya): Handle the case that launching the app fails. Probably we 464 // 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 465 // 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 466 // exists/was created' and time out with failure if we don't see that sign of
397 // life within a certain window. 467 // life within a certain window.
398 const extensions::Extension* extension = 468 const extensions::Extension* extension =
399 delegate_->GetAppExtension(profile, app_id); 469 delegate_->GetAppExtension(profile, app_id);
400 if (extension) { 470 if (extension) {
401 delegate_->LaunchApp(profile, extension, files); 471 delegate_->LaunchApp(profile, extension, files);
402 // If it's a hosted app, just kill it immediately after opening for now. 472 // If it's a hosted app and a tabbed application, kill it immediately.
jackhou1 2014/12/11 02:43:18 s/kill it immediately/let the shim terminate immed
mitchellj 2014/12/12 00:03:45 Acknowledged.
403 if (extension->is_hosted_app()) 473 if (extension->is_hosted_app()) {
404 host->OnAppLaunchComplete(APP_SHIM_LAUNCH_DUPLICATE_HOST); 474 if (extensions::GetLaunchType(extensions::ExtensionPrefs::Get(profile),
475 extension) ==
476 extensions::LAUNCH_TYPE_REGULAR) {
477 host->OnAppLaunchComplete(APP_SHIM_LAUNCH_DUPLICATE_HOST);
478 } else {
479 host->OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS);
jackhou1 2014/12/11 02:43:18 Instead of sending APP_SHIM_LAUNCH_SUCCESS here, h
mitchellj 2014/12/12 00:03:45 Done.
480 }
481 }
405 return; 482 return;
406 } 483 }
407 484
408 delegate_->EnableExtension( 485 delegate_->EnableExtension(
409 profile, app_id, 486 profile, app_id,
410 base::Bind(&ExtensionAppShimHandler::OnExtensionEnabled, 487 base::Bind(&ExtensionAppShimHandler::OnExtensionEnabled,
411 weak_factory_.GetWeakPtr(), 488 weak_factory_.GetWeakPtr(),
412 host->GetProfilePath(), app_id, files)); 489 host->GetProfilePath(), app_id, files));
413 } 490 }
414 491
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 } 524 }
448 } 525 }
449 526
450 void ExtensionAppShimHandler::OnShimFocus( 527 void ExtensionAppShimHandler::OnShimFocus(
451 Host* host, 528 Host* host,
452 AppShimFocusType focus_type, 529 AppShimFocusType focus_type,
453 const std::vector<base::FilePath>& files) { 530 const std::vector<base::FilePath>& files) {
454 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); 531 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath()));
455 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); 532 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath());
456 533
457 const AppWindowList windows = 534 bool windows_focused;
458 delegate_->GetWindows(profile, host->GetAppId()); 535 const std::string& app_id = host->GetAppId();
459 bool windows_focused = FocusWindows(windows); 536 if (delegate_->GetAppExtension(profile, app_id)->is_hosted_app()) {
537 std::vector<content::WebContents*> items;
538 AppBrowserMap::iterator it = app_browser_windows_.find(app_id);
539 if (it == app_browser_windows_.end())
540 return;
541
542 BrowserSet& browsers = it->second;
543 for (BrowserSet::const_iterator it = browsers.begin(); it != browsers.end();
544 ++it) {
545 Browser* browser = *it;
546 TabStripModel* tab_strip = browser->tab_strip_model();
547 for (int index = 0; index < tab_strip->count(); index++) {
548 content::WebContents* web_contents = tab_strip->GetWebContentsAt(index);
549 items.push_back(web_contents);
550 }
551 }
552 windows_focused = FocusHostedAppWindows(items);
553 } else {
554 const AppWindowList windows =
555 delegate_->GetWindows(profile, host->GetAppId());
556 windows_focused = FocusWindows(windows);
557 }
460 558
461 if (focus_type == APP_SHIM_FOCUS_NORMAL || 559 if (focus_type == APP_SHIM_FOCUS_NORMAL ||
462 (focus_type == APP_SHIM_FOCUS_REOPEN && windows_focused)) { 560 (focus_type == APP_SHIM_FOCUS_REOPEN && windows_focused)) {
463 return; 561 return;
464 } 562 }
465 563
466 const extensions::Extension* extension = 564 const extensions::Extension* extension =
467 delegate_->GetAppExtension(profile, host->GetAppId()); 565 delegate_->GetAppExtension(profile, host->GetAppId());
468 if (extension) { 566 if (extension) {
469 delegate_->LaunchApp(profile, extension, files); 567 delegate_->LaunchApp(profile, extension, files);
470 } else { 568 } else {
471 // Extensions may have been uninstalled or disabled since the shim 569 // Extensions may have been uninstalled or disabled since the shim
472 // started. 570 // started.
473 host->OnAppClosed(); 571 host->OnAppClosed();
474 } 572 }
475 } 573 }
476 574
477 void ExtensionAppShimHandler::OnShimSetHidden(Host* host, bool hidden) { 575 void ExtensionAppShimHandler::OnShimSetHidden(Host* host, bool hidden) {
478 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); 576 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath()));
479 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); 577 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath());
480 578
481 SetAppHidden(profile, host->GetAppId(), hidden); 579 const std::string& app_id = host->GetAppId();
580 if (delegate_->GetAppExtension(profile, app_id)->is_hosted_app()) {
581 SetHostedAppHidden(profile, app_id, hidden);
582 } else {
583 SetAppHidden(profile, app_id, hidden);
584 }
482 } 585 }
483 586
484 void ExtensionAppShimHandler::OnShimQuit(Host* host) { 587 void ExtensionAppShimHandler::OnShimQuit(Host* host) {
485 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); 588 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath()));
486 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); 589 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath());
487 590
488 const std::string& app_id = host->GetAppId(); 591 const std::string& app_id = host->GetAppId();
489 const AppWindowList windows = delegate_->GetWindows(profile, app_id); 592 if (delegate_->GetAppExtension(profile, app_id)->is_hosted_app()) {
490 for (AppWindowRegistry::const_iterator it = windows.begin(); 593 std::vector<content::WebContents*> items;
491 it != windows.end(); 594 AppBrowserMap::iterator it = app_browser_windows_.find(app_id);
492 ++it) { 595 if (it == app_browser_windows_.end())
493 (*it)->GetBaseWindow()->Close(); 596 return;
597
598 const BrowserSet& browsers = it->second;
599 for (BrowserSet::const_iterator it = browsers.begin(); it != browsers.end();
600 ++it) {
601 Browser* browser = *it;
602 TabStripModel* tab_strip = browser->tab_strip_model();
jackhou1 2014/12/11 02:43:18 I think you can just call BrowserWindow::Close().
mitchellj 2014/12/12 00:03:45 Done.
603 for (int index = 0; index < tab_strip->count(); index++) {
604 content::WebContents* web_contents = tab_strip->GetWebContentsAt(index);
605 web_contents->Close();
606 }
607 }
608 } else {
609 const AppWindowList windows = delegate_->GetWindows(profile, app_id);
610 for (AppWindowRegistry::const_iterator it = windows.begin();
611 it != windows.end(); ++it) {
612 (*it)->GetBaseWindow()->Close();
613 }
494 } 614 }
495 // Once the last window closes, flow will end up in OnAppDeactivated via 615 // Once the last window closes, flow will end up in OnAppDeactivated via
496 // AppLifetimeMonitor. 616 // AppLifetimeMonitor.
617 // Otherwise, once the last window closes for a hosted app, OnBrowserRevmoed
jackhou1 2014/12/11 02:43:18 s/Revmoed/Removed/
mitchellj 2014/12/12 00:03:45 Done.
618 // will call OnAppDeactivated.
497 } 619 }
498 620
499 void ExtensionAppShimHandler::set_delegate(Delegate* delegate) { 621 void ExtensionAppShimHandler::set_delegate(Delegate* delegate) {
500 delegate_.reset(delegate); 622 delegate_.reset(delegate);
501 } 623 }
502 624
503 void ExtensionAppShimHandler::Observe( 625 void ExtensionAppShimHandler::Observe(
504 int type, 626 int type,
505 const content::NotificationSource& source, 627 const content::NotificationSource& source,
506 const content::NotificationDetails& details) { 628 const content::NotificationDetails& details) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 684
563 if (hosts_.empty()) 685 if (hosts_.empty())
564 delegate_->MaybeTerminate(); 686 delegate_->MaybeTerminate();
565 } 687 }
566 688
567 void ExtensionAppShimHandler::OnAppStop(Profile* profile, 689 void ExtensionAppShimHandler::OnAppStop(Profile* profile,
568 const std::string& app_id) {} 690 const std::string& app_id) {}
569 691
570 void ExtensionAppShimHandler::OnChromeTerminating() {} 692 void ExtensionAppShimHandler::OnChromeTerminating() {}
571 693
694 void ExtensionAppShimHandler::OnBrowserAdded(Browser* browser) {
695 // Don't keep track of browsers that are not associated with an app.
696 if (!browser->is_app())
697 return;
698
699 std::string app_id =
700 web_app::GetExtensionIdFromApplicationName(browser->app_name());
701 BrowserSet& browsers = app_browser_windows_[app_id];
702 browsers.insert(browser);
jackhou1 2014/12/11 02:43:18 You should make this call OnAppActivated if it is
mitchellj 2014/12/12 00:03:45 Done. I ran into a problem where calling OnAppActi
703 }
704
705 void ExtensionAppShimHandler::OnBrowserRemoved(Browser* browser) {
706 if (!browser->is_app())
jackhou1 2014/12/11 02:43:18 I think we should be consistent about checking bot
mitchellj 2014/12/12 00:03:45 Done.
707 return;
708
709 std::string app_id =
710 web_app::GetExtensionIdFromApplicationName(browser->app_name());
711 AppBrowserMap::iterator it = app_browser_windows_.find(app_id);
712 if (it != app_browser_windows_.end()) {
713 BrowserSet& browsers = it->second;
714 browsers.erase(browser);
715 if (browsers.empty())
716 OnAppDeactivated(browser->profile(), app_id);
717 }
718 }
719
572 } // namespace apps 720 } // namespace apps
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698