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

Side by Side Diff: chrome/browser/background/background_mode_manager.cc

Issue 25603004: Leave apps running on Windows and Linux when quitting Chrome from the wrench menu. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 2 months 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <algorithm> 5 #include <algorithm>
6 #include <string> 6 #include <string>
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/base_paths.h" 9 #include "base/base_paths.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 12 matching lines...) Expand all
23 #include "chrome/browser/extensions/extension_system.h" 23 #include "chrome/browser/extensions/extension_system.h"
24 #include "chrome/browser/lifetime/application_lifetime.h" 24 #include "chrome/browser/lifetime/application_lifetime.h"
25 #include "chrome/browser/profiles/profile.h" 25 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/browser/profiles/profile_info_cache.h" 26 #include "chrome/browser/profiles/profile_info_cache.h"
27 #include "chrome/browser/profiles/profile_manager.h" 27 #include "chrome/browser/profiles/profile_manager.h"
28 #include "chrome/browser/status_icons/status_icon.h" 28 #include "chrome/browser/status_icons/status_icon.h"
29 #include "chrome/browser/status_icons/status_tray.h" 29 #include "chrome/browser/status_icons/status_tray.h"
30 #include "chrome/browser/ui/browser.h" 30 #include "chrome/browser/ui/browser.h"
31 #include "chrome/browser/ui/browser_commands.h" 31 #include "chrome/browser/ui/browser_commands.h"
32 #include "chrome/browser/ui/browser_finder.h" 32 #include "chrome/browser/ui/browser_finder.h"
33 #include "chrome/browser/ui/browser_list.h"
33 #include "chrome/browser/ui/chrome_pages.h" 34 #include "chrome/browser/ui/chrome_pages.h"
34 #include "chrome/browser/ui/extensions/application_launch.h" 35 #include "chrome/browser/ui/extensions/application_launch.h"
35 #include "chrome/browser/ui/host_desktop.h" 36 #include "chrome/browser/ui/host_desktop.h"
36 #include "chrome/common/chrome_constants.h" 37 #include "chrome/common/chrome_constants.h"
37 #include "chrome/common/chrome_switches.h" 38 #include "chrome/common/chrome_switches.h"
38 #include "chrome/common/extensions/extension.h" 39 #include "chrome/common/extensions/extension.h"
39 #include "chrome/common/extensions/extension_constants.h" 40 #include "chrome/common/extensions/extension_constants.h"
40 #include "chrome/common/extensions/permissions/permission_set.h" 41 #include "chrome/common/extensions/permissions/permission_set.h"
41 #include "chrome/common/pref_names.h" 42 #include "chrome/common/pref_names.h"
42 #include "content/public/browser/notification_service.h" 43 #include "content/public/browser/notification_service.h"
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 BackgroundModeManager::BackgroundModeManager( 142 BackgroundModeManager::BackgroundModeManager(
142 CommandLine* command_line, 143 CommandLine* command_line,
143 ProfileInfoCache* profile_cache) 144 ProfileInfoCache* profile_cache)
144 : profile_cache_(profile_cache), 145 : profile_cache_(profile_cache),
145 status_tray_(NULL), 146 status_tray_(NULL),
146 status_icon_(NULL), 147 status_icon_(NULL),
147 context_menu_(NULL), 148 context_menu_(NULL),
148 in_background_mode_(false), 149 in_background_mode_(false),
149 keep_alive_for_startup_(false), 150 keep_alive_for_startup_(false),
150 keep_alive_for_test_(false), 151 keep_alive_for_test_(false),
152 background_mode_suspended_(false),
153 keeping_alive_(false),
151 current_command_id_(0) { 154 current_command_id_(0) {
152 // We should never start up if there is no browser process or if we are 155 // We should never start up if there is no browser process or if we are
153 // currently quitting. 156 // currently quitting.
154 CHECK(g_browser_process != NULL); 157 CHECK(g_browser_process != NULL);
155 CHECK(!browser_shutdown::IsTryingToQuit()); 158 CHECK(!browser_shutdown::IsTryingToQuit());
156 159
157 // Add self as an observer for the profile info cache so we know when profiles 160 // Add self as an observer for the profile info cache so we know when profiles
158 // are deleted and their names change. 161 // are deleted and their names change.
159 profile_cache_->AddObserver(this); 162 profile_cache_->AddObserver(this);
160 163
(...skipping 13 matching lines...) Expand all
174 if (command_line->HasSwitch(switches::kNoStartupWindow)) { 177 if (command_line->HasSwitch(switches::kNoStartupWindow)) {
175 keep_alive_for_startup_ = true; 178 keep_alive_for_startup_ = true;
176 chrome::StartKeepAlive(); 179 chrome::StartKeepAlive();
177 } 180 }
178 181
179 // If the -keep-alive-for-test flag is passed, then always keep chrome running 182 // If the -keep-alive-for-test flag is passed, then always keep chrome running
180 // in the background until the user explicitly terminates it. 183 // in the background until the user explicitly terminates it.
181 if (command_line->HasSwitch(switches::kKeepAliveForTest)) 184 if (command_line->HasSwitch(switches::kKeepAliveForTest))
182 keep_alive_for_test_ = true; 185 keep_alive_for_test_ = true;
183 186
187 // If the --app-id or the --show-app-list flag is passed, then start with
188 // background mode suspended. It will be resumed when the first browser window
189 // is opened.
190 if (command_line->HasSwitch(switches::kAppId) ||
191 command_line->HasSwitch(switches::kShowAppList)) {
192 SuspendBackgroundMode();
benwells 2013/10/21 05:57:22 Relying on these two flags feels fragile. E.g. --l
Sam McNally 2013/10/21 06:45:35 Done.
193 }
194
184 if (ShouldBeInBackgroundMode()) 195 if (ShouldBeInBackgroundMode())
185 StartBackgroundMode(); 196 StartBackgroundMode();
186 197
187 // Listen for the application shutting down so we can decrement our KeepAlive 198 // Listen for the application shutting down so we can decrement our KeepAlive
188 // count. 199 // count.
189 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, 200 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
190 content::NotificationService::AllSources()); 201 content::NotificationService::AllSources());
202 BrowserList::AddObserver(this);
191 } 203 }
192 204
193 BackgroundModeManager::~BackgroundModeManager() { 205 BackgroundModeManager::~BackgroundModeManager() {
194 // Remove ourselves from the application observer list (only needed by unit 206 // Remove ourselves from the application observer list (only needed by unit
195 // tests since APP_TERMINATING is what does this in a real running system). 207 // tests since APP_TERMINATING is what does this in a real running system).
196 for (BackgroundModeInfoMap::iterator it = 208 for (BackgroundModeInfoMap::iterator it =
197 background_mode_data_.begin(); 209 background_mode_data_.begin();
198 it != background_mode_data_.end(); 210 it != background_mode_data_.end();
199 ++it) { 211 ++it) {
200 it->second->applications_->RemoveObserver(this); 212 it->second->applications_->RemoveObserver(this);
201 } 213 }
214 BrowserList::RemoveObserver(this);
202 215
203 // We're going away, so exit background mode (does nothing if we aren't in 216 // We're going away, so exit background mode (does nothing if we aren't in
204 // background mode currently). This is primarily needed for unit tests, 217 // background mode currently). This is primarily needed for unit tests,
205 // because in an actual running system we'd get an APP_TERMINATING 218 // because in an actual running system we'd get an APP_TERMINATING
206 // notification before being destroyed. 219 // notification before being destroyed.
207 EndBackgroundMode(); 220 EndBackgroundMode();
208 } 221 }
209 222
210 // static 223 // static
211 void BackgroundModeManager::RegisterPrefs(PrefRegistrySimple* registry) { 224 void BackgroundModeManager::RegisterPrefs(PrefRegistrySimple* registry) {
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 BackgroundModeData* bmd = background_mode_data_.begin()->second.get(); 463 BackgroundModeData* bmd = background_mode_data_.begin()->second.get();
451 switch (command_id) { 464 switch (command_id) {
452 case IDC_ABOUT: 465 case IDC_ABOUT:
453 chrome::ShowAboutChrome(bmd->GetBrowserWindow()); 466 chrome::ShowAboutChrome(bmd->GetBrowserWindow());
454 break; 467 break;
455 case IDC_TASK_MANAGER: 468 case IDC_TASK_MANAGER:
456 chrome::OpenTaskManager(bmd->GetBrowserWindow()); 469 chrome::OpenTaskManager(bmd->GetBrowserWindow());
457 break; 470 break;
458 case IDC_EXIT: 471 case IDC_EXIT:
459 content::RecordAction(UserMetricsAction("Exit")); 472 content::RecordAction(UserMetricsAction("Exit"));
460 chrome::AttemptExit(); 473 chrome::CloseAllBrowsers();
461 break; 474 break;
462 case IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND: { 475 case IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND: {
463 // Background mode must already be enabled (as otherwise this menu would 476 // Background mode must already be enabled (as otherwise this menu would
464 // not be visible). 477 // not be visible).
465 DCHECK(IsBackgroundModePrefEnabled()); 478 DCHECK(IsBackgroundModePrefEnabled());
466 DCHECK(chrome::WillKeepAlive()); 479 DCHECK(chrome::WillKeepAlive());
467 480
468 // Set the background mode pref to "disabled" - the resulting notification 481 // Set the background mode pref to "disabled" - the resulting notification
469 // will result in a call to DisableBackgroundMode(). 482 // will result in a call to DisableBackgroundMode().
470 PrefService* service = g_browser_process->local_state(); 483 PrefService* service = g_browser_process->local_state();
(...skipping 24 matching lines...) Expand all
495 void BackgroundModeManager::StartBackgroundMode() { 508 void BackgroundModeManager::StartBackgroundMode() {
496 DCHECK(ShouldBeInBackgroundMode()); 509 DCHECK(ShouldBeInBackgroundMode());
497 // Don't bother putting ourselves in background mode if we're already there 510 // Don't bother putting ourselves in background mode if we're already there
498 // or if background mode is disabled. 511 // or if background mode is disabled.
499 if (in_background_mode_) 512 if (in_background_mode_)
500 return; 513 return;
501 514
502 // Mark ourselves as running in background mode. 515 // Mark ourselves as running in background mode.
503 in_background_mode_ = true; 516 in_background_mode_ = true;
504 517
505 // Put ourselves in KeepAlive mode and create a status tray icon. 518 UpdateKeepAliveAndTrayIcon();
506 chrome::StartKeepAlive();
507
508 // Display a status icon to exit Chrome.
509 InitStatusTrayIcon();
510 519
511 content::NotificationService::current()->Notify( 520 content::NotificationService::current()->Notify(
512 chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED, 521 chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED,
513 content::Source<BackgroundModeManager>(this), 522 content::Source<BackgroundModeManager>(this),
514 content::Details<bool>(&in_background_mode_)); 523 content::Details<bool>(&in_background_mode_));
515 } 524 }
516 525
517 void BackgroundModeManager::InitStatusTrayIcon() {
518 // Only initialize status tray icons for those profiles which actually
519 // have a background app running.
520 if (ShouldBeInBackgroundMode())
521 CreateStatusTrayIcon();
522 }
523
524 void BackgroundModeManager::EndBackgroundMode() { 526 void BackgroundModeManager::EndBackgroundMode() {
525 if (!in_background_mode_) 527 if (!in_background_mode_)
526 return; 528 return;
527 in_background_mode_ = false; 529 in_background_mode_ = false;
528 530
529 // End KeepAlive mode and blow away our status tray icon. 531 UpdateKeepAliveAndTrayIcon();
530 chrome::EndKeepAlive();
531 532
532 RemoveStatusTrayIcon();
533 content::NotificationService::current()->Notify( 533 content::NotificationService::current()->Notify(
534 chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED, 534 chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED,
535 content::Source<BackgroundModeManager>(this), 535 content::Source<BackgroundModeManager>(this),
536 content::Details<bool>(&in_background_mode_)); 536 content::Details<bool>(&in_background_mode_));
537 } 537 }
538 538
539 void BackgroundModeManager::EnableBackgroundMode() { 539 void BackgroundModeManager::EnableBackgroundMode() {
540 DCHECK(IsBackgroundModePrefEnabled()); 540 DCHECK(IsBackgroundModePrefEnabled());
541 // If background mode should be enabled, but isn't, turn it on. 541 // If background mode should be enabled, but isn't, turn it on.
542 if (!in_background_mode_ && ShouldBeInBackgroundMode()) { 542 if (!in_background_mode_ && ShouldBeInBackgroundMode()) {
543 StartBackgroundMode(); 543 StartBackgroundMode();
544 EnableLaunchOnStartup(true); 544 EnableLaunchOnStartup(true);
545 } 545 }
546 } 546 }
547 547
548 void BackgroundModeManager::DisableBackgroundMode() { 548 void BackgroundModeManager::DisableBackgroundMode() {
549 DCHECK(!IsBackgroundModePrefEnabled()); 549 DCHECK(!IsBackgroundModePrefEnabled());
550 // If background mode is currently enabled, turn it off. 550 // If background mode is currently enabled, turn it off.
551 if (in_background_mode_) { 551 if (in_background_mode_) {
552 EndBackgroundMode(); 552 EndBackgroundMode();
553 EnableLaunchOnStartup(false); 553 EnableLaunchOnStartup(false);
554 } 554 }
555 } 555 }
556 556
557 void BackgroundModeManager::SuspendBackgroundMode() {
558 background_mode_suspended_ = true;
559 UpdateKeepAliveAndTrayIcon();
560 }
561
562 void BackgroundModeManager::ResumeBackgroundMode() {
563 background_mode_suspended_ = false;
564 UpdateKeepAliveAndTrayIcon();
565 }
566
567 void BackgroundModeManager::UpdateKeepAliveAndTrayIcon() {
568 if (in_background_mode_ && !background_mode_suspended_) {
569 if (!keeping_alive_) {
570 keeping_alive_ = true;
571 chrome::StartKeepAlive();
572 }
573 CreateStatusTrayIcon();
benwells 2013/10/21 05:57:22 Nit: early return instead of else.
Sam McNally 2013/10/21 06:45:35 Done.
574 } else {
575 RemoveStatusTrayIcon();
576 if (keeping_alive_) {
577 keeping_alive_ = false;
578 chrome::EndKeepAlive();
579 }
580 }
581 }
582
583 void BackgroundModeManager::OnBrowserAdded(Browser* browser) {
584 ResumeBackgroundMode();
585 }
586
557 int BackgroundModeManager::GetBackgroundAppCount() const { 587 int BackgroundModeManager::GetBackgroundAppCount() const {
558 int count = 0; 588 int count = 0;
559 // Walk the BackgroundModeData for all profiles and count the number of apps. 589 // Walk the BackgroundModeData for all profiles and count the number of apps.
560 for (BackgroundModeInfoMap::const_iterator it = 590 for (BackgroundModeInfoMap::const_iterator it =
561 background_mode_data_.begin(); 591 background_mode_data_.begin();
562 it != background_mode_data_.end(); 592 it != background_mode_data_.end();
563 ++it) { 593 ++it) {
564 count += it->second->GetBackgroundAppCount(); 594 count += it->second->GetBackgroundAppCount();
565 } 595 }
566 DCHECK(count >= 0); 596 DCHECK(count >= 0);
(...skipping 10 matching lines...) Expand all
577 return IsBackgroundModePrefEnabled() && 607 return IsBackgroundModePrefEnabled() &&
578 (GetBackgroundAppCount() > 0 || keep_alive_for_test_); 608 (GetBackgroundAppCount() > 0 || keep_alive_for_test_);
579 } 609 }
580 610
581 void BackgroundModeManager::OnBackgroundAppInstalled( 611 void BackgroundModeManager::OnBackgroundAppInstalled(
582 const Extension* extension) { 612 const Extension* extension) {
583 // Background mode is disabled - don't do anything. 613 // Background mode is disabled - don't do anything.
584 if (!IsBackgroundModePrefEnabled()) 614 if (!IsBackgroundModePrefEnabled())
585 return; 615 return;
586 616
587 // Check if we need a status tray icon and make one if we do (needed so we 617 // Ensure we have a tray icon if appropriate (needed so we can display the
588 // can display the app-installed notification below). 618 // app-installed notification below).
589 CreateStatusTrayIcon(); 619 UpdateKeepAliveAndTrayIcon();
620
621 // If we don't have a status icon or one could not be created succesfully,
622 // then we won't notify the user.
623 if (!status_icon_)
624 return;
590 625
591 // Notify the user that a background app has been installed. 626 // Notify the user that a background app has been installed.
592 if (extension) { // NULL when called by unit tests. 627 if (extension) { // NULL when called by unit tests.
593 DisplayAppInstalledNotification(extension); 628 DisplayAppInstalledNotification(extension);
594 } 629 }
595 } 630 }
596 631
597 void BackgroundModeManager::CheckReloadStatus( 632 void BackgroundModeManager::CheckReloadStatus(
598 const Extension* extension, 633 const Extension* extension,
599 bool* is_being_reloaded) { 634 bool* is_being_reloaded) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); 671 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
637 if (!status_icon_) 672 if (!status_icon_)
638 return; 673 return;
639 UpdateStatusTrayIconContextMenu(); 674 UpdateStatusTrayIconContextMenu();
640 } 675 }
641 676
642 void BackgroundModeManager::UpdateStatusTrayIconContextMenu() { 677 void BackgroundModeManager::UpdateStatusTrayIconContextMenu() {
643 // If no status icon exists, it's either because one wasn't created when 678 // If no status icon exists, it's either because one wasn't created when
644 // it should have been which can happen when extensions load after the 679 // it should have been which can happen when extensions load after the
645 // profile has already been registered with the background mode manager. 680 // profile has already been registered with the background mode manager.
646 if (in_background_mode_ && !status_icon_) 681 UpdateKeepAliveAndTrayIcon();
benwells 2013/10/21 05:57:22 This only happened before if !status_icon, and the
Sam McNally 2013/10/21 06:45:35 Done.
647 CreateStatusTrayIcon();
648 682
649 // If we don't have a status icon or one could not be created succesfully, 683 // If we don't have a status icon or one could not be created succesfully,
650 // then no need to continue the update. 684 // then no need to continue the update.
651 if (!status_icon_) 685 if (!status_icon_)
652 return; 686 return;
653 687
654 // We should only get here if we have a profile loaded, or if we're running 688 // We should only get here if we have a profile loaded, or if we're running
655 // in test mode. 689 // in test mode.
656 if (background_mode_data_.empty()) { 690 if (background_mode_data_.empty()) {
657 DCHECK(keep_alive_for_test_); 691 DCHECK(keep_alive_for_test_);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 } 783 }
750 } 784 }
751 return profile_it; 785 return profile_it;
752 } 786 }
753 787
754 bool BackgroundModeManager::IsBackgroundModePrefEnabled() const { 788 bool BackgroundModeManager::IsBackgroundModePrefEnabled() const {
755 PrefService* service = g_browser_process->local_state(); 789 PrefService* service = g_browser_process->local_state();
756 DCHECK(service); 790 DCHECK(service);
757 return service->GetBoolean(prefs::kBackgroundModeEnabled); 791 return service->GetBoolean(prefs::kBackgroundModeEnabled);
758 } 792 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698