OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 if appropriate (needed so we can display the |
588 // can display the app-installed notification below). | 616 // app-installed notification below). |
589 CreateStatusTrayIcon(); | 617 UpdateKeepAliveAndTrayIcon(); |
618 | |
619 // If we don't have a status icon or one could not be created succesfully, | |
620 // then we won't notify the user. | |
Andrew T Wilson (Slow)
2013/10/23 10:00:21
This means that platforms without status trays wil
Sam McNally
2013/10/24 02:01:37
Done.
| |
621 if (!status_icon_) | |
622 return; | |
590 | 623 |
591 // Notify the user that a background app has been installed. | 624 // Notify the user that a background app has been installed. |
592 if (extension) { // NULL when called by unit tests. | 625 if (extension) { // NULL when called by unit tests. |
593 DisplayAppInstalledNotification(extension); | 626 DisplayAppInstalledNotification(extension); |
594 } | 627 } |
595 } | 628 } |
596 | 629 |
597 void BackgroundModeManager::CheckReloadStatus( | 630 void BackgroundModeManager::CheckReloadStatus( |
598 const Extension* extension, | 631 const Extension* extension, |
599 bool* is_being_reloaded) { | 632 bool* is_being_reloaded) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
633 status_icon_ = status_tray_->CreateStatusIcon( | 666 status_icon_ = status_tray_->CreateStatusIcon( |
634 StatusTray::BACKGROUND_MODE_ICON, | 667 StatusTray::BACKGROUND_MODE_ICON, |
635 *image_skia, | 668 *image_skia, |
636 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); | 669 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); |
637 if (!status_icon_) | 670 if (!status_icon_) |
638 return; | 671 return; |
639 UpdateStatusTrayIconContextMenu(); | 672 UpdateStatusTrayIconContextMenu(); |
640 } | 673 } |
641 | 674 |
642 void BackgroundModeManager::UpdateStatusTrayIconContextMenu() { | 675 void BackgroundModeManager::UpdateStatusTrayIconContextMenu() { |
643 // If no status icon exists, it's either because one wasn't created when | 676 // Ensure we have a tray icon if appropriate. |
644 // it should have been which can happen when extensions load after the | 677 UpdateKeepAliveAndTrayIcon(); |
645 // profile has already been registered with the background mode manager. | |
646 if (in_background_mode_ && !status_icon_) | |
647 CreateStatusTrayIcon(); | |
648 | 678 |
649 // If we don't have a status icon or one could not be created succesfully, | 679 // If we don't have a status icon or one could not be created succesfully, |
650 // then no need to continue the update. | 680 // then no need to continue the update. |
651 if (!status_icon_) | 681 if (!status_icon_) |
652 return; | 682 return; |
653 | 683 |
654 // We should only get here if we have a profile loaded, or if we're running | 684 // We should only get here if we have a profile loaded, or if we're running |
655 // in test mode. | 685 // in test mode. |
656 if (background_mode_data_.empty()) { | 686 if (background_mode_data_.empty()) { |
657 DCHECK(keep_alive_for_test_); | 687 DCHECK(keep_alive_for_test_); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
749 } | 779 } |
750 } | 780 } |
751 return profile_it; | 781 return profile_it; |
752 } | 782 } |
753 | 783 |
754 bool BackgroundModeManager::IsBackgroundModePrefEnabled() const { | 784 bool BackgroundModeManager::IsBackgroundModePrefEnabled() const { |
755 PrefService* service = g_browser_process->local_state(); | 785 PrefService* service = g_browser_process->local_state(); |
756 DCHECK(service); | 786 DCHECK(service); |
757 return service->GetBoolean(prefs::kBackgroundModeEnabled); | 787 return service->GetBoolean(prefs::kBackgroundModeEnabled); |
758 } | 788 } |
OLD | NEW |