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

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, 1 month 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
161 // Listen for the background mode preference changing. 164 // Listen for the background mode preference changing.
162 if (g_browser_process->local_state()) { // Skip for unit tests 165 if (g_browser_process->local_state()) { // Skip for unit tests
163 pref_registrar_.Init(g_browser_process->local_state()); 166 pref_registrar_.Init(g_browser_process->local_state());
164 pref_registrar_.Add( 167 pref_registrar_.Add(
165 prefs::kBackgroundModeEnabled, 168 prefs::kBackgroundModeEnabled,
166 base::Bind(&BackgroundModeManager::OnBackgroundModeEnabledPrefChanged, 169 base::Bind(&BackgroundModeManager::OnBackgroundModeEnabledPrefChanged,
167 base::Unretained(this))); 170 base::Unretained(this)));
168 } 171 }
169 172
170 // Keep the browser alive until extensions are done loading - this is needed 173 // Keep the browser alive until extensions are done loading - this is needed
171 // by the --no-startup-window flag. We want to stay alive until we load 174 // by the --no-startup-window flag. We want to stay alive until we load
172 // extensions, at which point we should either run in background mode (if 175 // extensions, at which point we should either run in background mode (if
173 // there are background apps) or exit if there are none. 176 // there are background apps) or exit if there are none.
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();
180 } else {
181 // Otherwise, start with background mode suspended in case we're launching
182 // in a mode that doesn't open a browser window. It will be resumed when the
183 // first browser window is opened.
184 SuspendBackgroundMode();
177 } 185 }
178 186
179 // If the -keep-alive-for-test flag is passed, then always keep chrome running 187 // If the -keep-alive-for-test flag is passed, then always keep chrome running
180 // in the background until the user explicitly terminates it. 188 // in the background until the user explicitly terminates it.
181 if (command_line->HasSwitch(switches::kKeepAliveForTest)) 189 if (command_line->HasSwitch(switches::kKeepAliveForTest))
182 keep_alive_for_test_ = true; 190 keep_alive_for_test_ = true;
183 191
184 if (ShouldBeInBackgroundMode()) 192 if (ShouldBeInBackgroundMode())
185 StartBackgroundMode(); 193 StartBackgroundMode();
186 194
187 // Listen for the application shutting down so we can decrement our KeepAlive 195 // Listen for the application shutting down so we can decrement our KeepAlive
188 // count. 196 // count.
189 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, 197 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
190 content::NotificationService::AllSources()); 198 content::NotificationService::AllSources());
199 BrowserList::AddObserver(this);
191 } 200 }
192 201
193 BackgroundModeManager::~BackgroundModeManager() { 202 BackgroundModeManager::~BackgroundModeManager() {
194 // Remove ourselves from the application observer list (only needed by unit 203 // 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). 204 // tests since APP_TERMINATING is what does this in a real running system).
196 for (BackgroundModeInfoMap::iterator it = 205 for (BackgroundModeInfoMap::iterator it =
197 background_mode_data_.begin(); 206 background_mode_data_.begin();
198 it != background_mode_data_.end(); 207 it != background_mode_data_.end();
199 ++it) { 208 ++it) {
200 it->second->applications_->RemoveObserver(this); 209 it->second->applications_->RemoveObserver(this);
201 } 210 }
211 BrowserList::RemoveObserver(this);
202 212
203 // We're going away, so exit background mode (does nothing if we aren't in 213 // 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, 214 // background mode currently). This is primarily needed for unit tests,
205 // because in an actual running system we'd get an APP_TERMINATING 215 // because in an actual running system we'd get an APP_TERMINATING
206 // notification before being destroyed. 216 // notification before being destroyed.
207 EndBackgroundMode(); 217 EndBackgroundMode();
208 } 218 }
209 219
210 // static 220 // static
211 void BackgroundModeManager::RegisterPrefs(PrefRegistrySimple* registry) { 221 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(); 460 BackgroundModeData* bmd = background_mode_data_.begin()->second.get();
451 switch (command_id) { 461 switch (command_id) {
452 case IDC_ABOUT: 462 case IDC_ABOUT:
453 chrome::ShowAboutChrome(bmd->GetBrowserWindow()); 463 chrome::ShowAboutChrome(bmd->GetBrowserWindow());
454 break; 464 break;
455 case IDC_TASK_MANAGER: 465 case IDC_TASK_MANAGER:
456 chrome::OpenTaskManager(bmd->GetBrowserWindow()); 466 chrome::OpenTaskManager(bmd->GetBrowserWindow());
457 break; 467 break;
458 case IDC_EXIT: 468 case IDC_EXIT:
459 content::RecordAction(UserMetricsAction("Exit")); 469 content::RecordAction(UserMetricsAction("Exit"));
460 chrome::AttemptExit(); 470 chrome::CloseAllBrowsers();
461 break; 471 break;
462 case IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND: { 472 case IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND: {
463 // Background mode must already be enabled (as otherwise this menu would 473 // Background mode must already be enabled (as otherwise this menu would
464 // not be visible). 474 // not be visible).
465 DCHECK(IsBackgroundModePrefEnabled()); 475 DCHECK(IsBackgroundModePrefEnabled());
466 DCHECK(chrome::WillKeepAlive()); 476 DCHECK(chrome::WillKeepAlive());
467 477
468 // Set the background mode pref to "disabled" - the resulting notification 478 // Set the background mode pref to "disabled" - the resulting notification
469 // will result in a call to DisableBackgroundMode(). 479 // will result in a call to DisableBackgroundMode().
470 PrefService* service = g_browser_process->local_state(); 480 PrefService* service = g_browser_process->local_state();
(...skipping 24 matching lines...) Expand all
495 void BackgroundModeManager::StartBackgroundMode() { 505 void BackgroundModeManager::StartBackgroundMode() {
496 DCHECK(ShouldBeInBackgroundMode()); 506 DCHECK(ShouldBeInBackgroundMode());
497 // Don't bother putting ourselves in background mode if we're already there 507 // Don't bother putting ourselves in background mode if we're already there
498 // or if background mode is disabled. 508 // or if background mode is disabled.
499 if (in_background_mode_) 509 if (in_background_mode_)
500 return; 510 return;
501 511
502 // Mark ourselves as running in background mode. 512 // Mark ourselves as running in background mode.
503 in_background_mode_ = true; 513 in_background_mode_ = true;
504 514
505 // Put ourselves in KeepAlive mode and create a status tray icon. 515 UpdateKeepAliveAndTrayIcon();
506 chrome::StartKeepAlive();
507
508 // Display a status icon to exit Chrome.
509 InitStatusTrayIcon();
510 516
511 content::NotificationService::current()->Notify( 517 content::NotificationService::current()->Notify(
512 chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED, 518 chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED,
513 content::Source<BackgroundModeManager>(this), 519 content::Source<BackgroundModeManager>(this),
514 content::Details<bool>(&in_background_mode_)); 520 content::Details<bool>(&in_background_mode_));
515 } 521 }
516 522
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() { 523 void BackgroundModeManager::EndBackgroundMode() {
525 if (!in_background_mode_) 524 if (!in_background_mode_)
526 return; 525 return;
527 in_background_mode_ = false; 526 in_background_mode_ = false;
528 527
529 // End KeepAlive mode and blow away our status tray icon. 528 UpdateKeepAliveAndTrayIcon();
530 chrome::EndKeepAlive();
531 529
532 RemoveStatusTrayIcon();
533 content::NotificationService::current()->Notify( 530 content::NotificationService::current()->Notify(
534 chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED, 531 chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED,
535 content::Source<BackgroundModeManager>(this), 532 content::Source<BackgroundModeManager>(this),
536 content::Details<bool>(&in_background_mode_)); 533 content::Details<bool>(&in_background_mode_));
537 } 534 }
538 535
539 void BackgroundModeManager::EnableBackgroundMode() { 536 void BackgroundModeManager::EnableBackgroundMode() {
540 DCHECK(IsBackgroundModePrefEnabled()); 537 DCHECK(IsBackgroundModePrefEnabled());
541 // If background mode should be enabled, but isn't, turn it on. 538 // If background mode should be enabled, but isn't, turn it on.
542 if (!in_background_mode_ && ShouldBeInBackgroundMode()) { 539 if (!in_background_mode_ && ShouldBeInBackgroundMode()) {
543 StartBackgroundMode(); 540 StartBackgroundMode();
544 EnableLaunchOnStartup(true); 541 EnableLaunchOnStartup(true);
545 } 542 }
546 } 543 }
547 544
548 void BackgroundModeManager::DisableBackgroundMode() { 545 void BackgroundModeManager::DisableBackgroundMode() {
549 DCHECK(!IsBackgroundModePrefEnabled()); 546 DCHECK(!IsBackgroundModePrefEnabled());
550 // If background mode is currently enabled, turn it off. 547 // If background mode is currently enabled, turn it off.
551 if (in_background_mode_) { 548 if (in_background_mode_) {
552 EndBackgroundMode(); 549 EndBackgroundMode();
553 EnableLaunchOnStartup(false); 550 EnableLaunchOnStartup(false);
554 } 551 }
555 } 552 }
556 553
554 void BackgroundModeManager::SuspendBackgroundMode() {
555 background_mode_suspended_ = true;
556 UpdateKeepAliveAndTrayIcon();
557 }
558
559 void BackgroundModeManager::ResumeBackgroundMode() {
560 background_mode_suspended_ = false;
561 UpdateKeepAliveAndTrayIcon();
562 }
563
564 void BackgroundModeManager::UpdateKeepAliveAndTrayIcon() {
565 if (in_background_mode_ && !background_mode_suspended_) {
566 if (!keeping_alive_) {
567 keeping_alive_ = true;
568 chrome::StartKeepAlive();
569 }
570 CreateStatusTrayIcon();
571 return;
572 }
573
574 RemoveStatusTrayIcon();
575 if (keeping_alive_) {
576 keeping_alive_ = false;
577 chrome::EndKeepAlive();
578 }
579 }
580
581 void BackgroundModeManager::OnBrowserAdded(Browser* browser) {
582 ResumeBackgroundMode();
583 }
584
557 int BackgroundModeManager::GetBackgroundAppCount() const { 585 int BackgroundModeManager::GetBackgroundAppCount() const {
558 int count = 0; 586 int count = 0;
559 // Walk the BackgroundModeData for all profiles and count the number of apps. 587 // Walk the BackgroundModeData for all profiles and count the number of apps.
560 for (BackgroundModeInfoMap::const_iterator it = 588 for (BackgroundModeInfoMap::const_iterator it =
561 background_mode_data_.begin(); 589 background_mode_data_.begin();
562 it != background_mode_data_.end(); 590 it != background_mode_data_.end();
563 ++it) { 591 ++it) {
564 count += it->second->GetBackgroundAppCount(); 592 count += it->second->GetBackgroundAppCount();
565 } 593 }
566 DCHECK(count >= 0); 594 DCHECK(count >= 0);
(...skipping 10 matching lines...) Expand all
577 return IsBackgroundModePrefEnabled() && 605 return IsBackgroundModePrefEnabled() &&
578 (GetBackgroundAppCount() > 0 || keep_alive_for_test_); 606 (GetBackgroundAppCount() > 0 || keep_alive_for_test_);
579 } 607 }
580 608
581 void BackgroundModeManager::OnBackgroundAppInstalled( 609 void BackgroundModeManager::OnBackgroundAppInstalled(
582 const Extension* extension) { 610 const Extension* extension) {
583 // Background mode is disabled - don't do anything. 611 // Background mode is disabled - don't do anything.
584 if (!IsBackgroundModePrefEnabled()) 612 if (!IsBackgroundModePrefEnabled())
585 return; 613 return;
586 614
587 // Check if we need a status tray icon and make one if we do (needed so we 615 // Ensure we have a tray icon (needed so we can display the app-installed
588 // can display the app-installed notification below). 616 // notification below).
589 CreateStatusTrayIcon(); 617 EnableBackgroundMode();
618 ResumeBackgroundMode();
590 619
591 // Notify the user that a background app has been installed. 620 // Notify the user that a background app has been installed.
592 if (extension) { // NULL when called by unit tests. 621 if (extension) { // NULL when called by unit tests.
593 DisplayAppInstalledNotification(extension); 622 DisplayAppInstalledNotification(extension);
594 } 623 }
595 } 624 }
596 625
597 void BackgroundModeManager::CheckReloadStatus( 626 void BackgroundModeManager::CheckReloadStatus(
598 const Extension* extension, 627 const Extension* extension,
599 bool* is_being_reloaded) { 628 bool* is_being_reloaded) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 status_icon_ = status_tray_->CreateStatusIcon( 662 status_icon_ = status_tray_->CreateStatusIcon(
634 StatusTray::BACKGROUND_MODE_ICON, 663 StatusTray::BACKGROUND_MODE_ICON,
635 *image_skia, 664 *image_skia,
636 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); 665 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
637 if (!status_icon_) 666 if (!status_icon_)
638 return; 667 return;
639 UpdateStatusTrayIconContextMenu(); 668 UpdateStatusTrayIconContextMenu();
640 } 669 }
641 670
642 void BackgroundModeManager::UpdateStatusTrayIconContextMenu() { 671 void BackgroundModeManager::UpdateStatusTrayIconContextMenu() {
643 // If no status icon exists, it's either because one wasn't created when 672 // Ensure we have a tray icon if appropriate.
644 // it should have been which can happen when extensions load after the 673 UpdateKeepAliveAndTrayIcon();
645 // profile has already been registered with the background mode manager.
646 if (in_background_mode_ && !status_icon_)
647 CreateStatusTrayIcon();
648 674
649 // If we don't have a status icon or one could not be created succesfully, 675 // If we don't have a status icon or one could not be created succesfully,
650 // then no need to continue the update. 676 // then no need to continue the update.
651 if (!status_icon_) 677 if (!status_icon_)
652 return; 678 return;
653 679
654 // We should only get here if we have a profile loaded, or if we're running 680 // We should only get here if we have a profile loaded, or if we're running
655 // in test mode. 681 // in test mode.
656 if (background_mode_data_.empty()) { 682 if (background_mode_data_.empty()) {
657 DCHECK(keep_alive_for_test_); 683 DCHECK(keep_alive_for_test_);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 } 775 }
750 } 776 }
751 return profile_it; 777 return profile_it;
752 } 778 }
753 779
754 bool BackgroundModeManager::IsBackgroundModePrefEnabled() const { 780 bool BackgroundModeManager::IsBackgroundModePrefEnabled() const {
755 PrefService* service = g_browser_process->local_state(); 781 PrefService* service = g_browser_process->local_state();
756 DCHECK(service); 782 DCHECK(service);
757 return service->GetBoolean(prefs::kBackgroundModeEnabled); 783 return service->GetBoolean(prefs::kBackgroundModeEnabled);
758 } 784 }
OLDNEW
« no previous file with comments | « chrome/browser/background/background_mode_manager.h ('k') | chrome/browser/background/background_mode_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698