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 "chrome/browser/background/background_mode_manager.h" | 5 #include "chrome/browser/background/background_mode_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "base/strings/utf_string_conversions.h" | 21 #include "base/strings/utf_string_conversions.h" |
22 #include "base/thread_task_runner_handle.h" | 22 #include "base/thread_task_runner_handle.h" |
23 #include "chrome/app/chrome_command_ids.h" | 23 #include "chrome/app/chrome_command_ids.h" |
24 #include "chrome/browser/background/background_application_list_model.h" | 24 #include "chrome/browser/background/background_application_list_model.h" |
25 #include "chrome/browser/background/background_trigger.h" | 25 #include "chrome/browser/background/background_trigger.h" |
26 #include "chrome/browser/browser_process.h" | 26 #include "chrome/browser/browser_process.h" |
27 #include "chrome/browser/browser_shutdown.h" | 27 #include "chrome/browser/browser_shutdown.h" |
28 #include "chrome/browser/chrome_notification_types.h" | 28 #include "chrome/browser/chrome_notification_types.h" |
29 #include "chrome/browser/extensions/extension_service.h" | 29 #include "chrome/browser/extensions/extension_service.h" |
30 #include "chrome/browser/lifetime/application_lifetime.h" | 30 #include "chrome/browser/lifetime/application_lifetime.h" |
| 31 #include "chrome/browser/lifetime/browser_keep_alive.h" |
31 #include "chrome/browser/profiles/profile.h" | 32 #include "chrome/browser/profiles/profile.h" |
32 #include "chrome/browser/profiles/profile_info_cache.h" | 33 #include "chrome/browser/profiles/profile_info_cache.h" |
33 #include "chrome/browser/profiles/profile_manager.h" | 34 #include "chrome/browser/profiles/profile_manager.h" |
34 #include "chrome/browser/status_icons/status_icon.h" | 35 #include "chrome/browser/status_icons/status_icon.h" |
35 #include "chrome/browser/status_icons/status_tray.h" | 36 #include "chrome/browser/status_icons/status_tray.h" |
36 #include "chrome/browser/ui/browser.h" | 37 #include "chrome/browser/ui/browser.h" |
37 #include "chrome/browser/ui/browser_commands.h" | 38 #include "chrome/browser/ui/browser_commands.h" |
38 #include "chrome/browser/ui/browser_dialogs.h" | 39 #include "chrome/browser/ui/browser_dialogs.h" |
39 #include "chrome/browser/ui/browser_finder.h" | 40 #include "chrome/browser/ui/browser_finder.h" |
40 #include "chrome/browser/ui/browser_list.h" | 41 #include "chrome/browser/ui/browser_list.h" |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 MENU_ITEM_BACKGROUND_CLIENT = 2, | 115 MENU_ITEM_BACKGROUND_CLIENT = 2, |
115 MENU_ITEM_KEEP_RUNNING = 3, | 116 MENU_ITEM_KEEP_RUNNING = 3, |
116 MENU_ITEM_EXIT = 4, | 117 MENU_ITEM_EXIT = 4, |
117 MENU_ITEM_NUM_STATES | 118 MENU_ITEM_NUM_STATES |
118 }; | 119 }; |
119 | 120 |
120 void RecordMenuItemClick(MenuItem item) { | 121 void RecordMenuItemClick(MenuItem item) { |
121 UMA_HISTOGRAM_ENUMERATION("BackgroundMode.MenuItemClick", item, | 122 UMA_HISTOGRAM_ENUMERATION("BackgroundMode.MenuItemClick", item, |
122 MENU_ITEM_NUM_STATES); | 123 MENU_ITEM_NUM_STATES); |
123 } | 124 } |
| 125 |
| 126 // Helper function for DecrementKeepAliveCountForStartup() to actually decrement |
| 127 // the keep alive. |
| 128 void DoDecrementKeepAliveCountForStartup( |
| 129 scoped_ptr<browser_lifetime::ScopedKeepAlive> keep_alive) { |
| 130 keep_alive.reset(); // Explicitly reset(). |
| 131 } |
| 132 |
124 } // namespace | 133 } // namespace |
125 | 134 |
126 BackgroundModeManager::BackgroundModeData::BackgroundModeData( | 135 BackgroundModeManager::BackgroundModeData::BackgroundModeData( |
127 Profile* profile, | 136 Profile* profile, |
128 CommandIdHandlerVector* command_id_handler_vector) | 137 CommandIdHandlerVector* command_id_handler_vector) |
129 : applications_(new BackgroundApplicationListModel(profile)), | 138 : applications_(new BackgroundApplicationListModel(profile)), |
130 profile_(profile), | 139 profile_(profile), |
131 command_id_handler_vector_(command_id_handler_vector) { | 140 command_id_handler_vector_(command_id_handler_vector) { |
132 } | 141 } |
133 | 142 |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 /////////////////////////////////////////////////////////////////////////////// | 312 /////////////////////////////////////////////////////////////////////////////// |
304 // BackgroundModeManager, public | 313 // BackgroundModeManager, public |
305 BackgroundModeManager::BackgroundModeManager( | 314 BackgroundModeManager::BackgroundModeManager( |
306 const base::CommandLine& command_line, | 315 const base::CommandLine& command_line, |
307 ProfileInfoCache* profile_cache) | 316 ProfileInfoCache* profile_cache) |
308 : profile_cache_(profile_cache), | 317 : profile_cache_(profile_cache), |
309 status_tray_(NULL), | 318 status_tray_(NULL), |
310 status_icon_(NULL), | 319 status_icon_(NULL), |
311 context_menu_(NULL), | 320 context_menu_(NULL), |
312 in_background_mode_(false), | 321 in_background_mode_(false), |
313 keep_alive_for_startup_(false), | |
314 keep_alive_for_test_(false), | 322 keep_alive_for_test_(false), |
315 background_mode_suspended_(false), | 323 background_mode_suspended_(false), |
316 keeping_alive_(false), | |
317 weak_factory_(this) { | 324 weak_factory_(this) { |
318 // We should never start up if there is no browser process or if we are | 325 // We should never start up if there is no browser process or if we are |
319 // currently quitting. | 326 // currently quitting. |
320 CHECK(g_browser_process != NULL); | 327 CHECK(g_browser_process != NULL); |
321 CHECK(!browser_shutdown::IsTryingToQuit()); | 328 CHECK(!browser_shutdown::IsTryingToQuit()); |
322 | 329 |
323 // Add self as an observer for the profile info cache so we know when profiles | 330 // Add self as an observer for the profile info cache so we know when profiles |
324 // are deleted and their names change. | 331 // are deleted and their names change. |
325 profile_cache_->AddObserver(this); | 332 profile_cache_->AddObserver(this); |
326 | 333 |
327 RecordAutoLaunchState(command_line); | 334 RecordAutoLaunchState(command_line); |
328 UMA_HISTOGRAM_BOOLEAN("BackgroundMode.OnStartup.IsBackgroundModePrefEnabled", | 335 UMA_HISTOGRAM_BOOLEAN("BackgroundMode.OnStartup.IsBackgroundModePrefEnabled", |
329 IsBackgroundModePrefEnabled()); | 336 IsBackgroundModePrefEnabled()); |
330 | 337 |
331 // Listen for the background mode preference changing. | 338 // Listen for the background mode preference changing. |
332 if (g_browser_process->local_state()) { // Skip for unit tests | 339 if (g_browser_process->local_state()) { // Skip for unit tests |
333 pref_registrar_.Init(g_browser_process->local_state()); | 340 pref_registrar_.Init(g_browser_process->local_state()); |
334 pref_registrar_.Add( | 341 pref_registrar_.Add( |
335 prefs::kBackgroundModeEnabled, | 342 prefs::kBackgroundModeEnabled, |
336 base::Bind(&BackgroundModeManager::OnBackgroundModeEnabledPrefChanged, | 343 base::Bind(&BackgroundModeManager::OnBackgroundModeEnabledPrefChanged, |
337 base::Unretained(this))); | 344 base::Unretained(this))); |
338 } | 345 } |
339 | 346 |
340 // Keep the browser alive until extensions are done loading - this is needed | 347 // Keep the browser alive until extensions are done loading - this is needed |
341 // by the --no-startup-window flag. We want to stay alive until we load | 348 // by the --no-startup-window flag. We want to stay alive until we load |
342 // extensions, at which point we should either run in background mode (if | 349 // extensions, at which point we should either run in background mode (if |
343 // there are background apps) or exit if there are none. | 350 // there are background apps) or exit if there are none. |
344 if (command_line.HasSwitch(switches::kNoStartupWindow)) { | 351 if (command_line.HasSwitch(switches::kNoStartupWindow)) { |
345 keep_alive_for_startup_ = true; | 352 keep_alive_for_startup_.reset(new browser_lifetime::ScopedKeepAlive); |
346 chrome::IncrementKeepAliveCount(); | |
347 } else { | 353 } else { |
348 // Otherwise, start with background mode suspended in case we're launching | 354 // Otherwise, start with background mode suspended in case we're launching |
349 // in a mode that doesn't open a browser window. It will be resumed when the | 355 // in a mode that doesn't open a browser window. It will be resumed when the |
350 // first browser window is opened. | 356 // first browser window is opened. |
351 SuspendBackgroundMode(); | 357 SuspendBackgroundMode(); |
352 } | 358 } |
353 | 359 |
354 // If the -keep-alive-for-test flag is passed, then always keep chrome running | 360 // If the -keep-alive-for-test flag is passed, then always keep chrome running |
355 // in the background until the user explicitly terminates it. | 361 // in the background until the user explicitly terminates it. |
356 if (command_line.HasSwitch(switches::kKeepAliveForTest)) | 362 if (command_line.HasSwitch(switches::kKeepAliveForTest)) |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 browser_watcher::ExitFunnel::RecordSingleEvent( | 679 browser_watcher::ExitFunnel::RecordSingleEvent( |
674 chrome::kBrowserExitCodesRegistryPath, L"TraybarExit"); | 680 chrome::kBrowserExitCodesRegistryPath, L"TraybarExit"); |
675 #endif | 681 #endif |
676 content::RecordAction(UserMetricsAction("Exit")); | 682 content::RecordAction(UserMetricsAction("Exit")); |
677 chrome::CloseAllBrowsers(); | 683 chrome::CloseAllBrowsers(); |
678 break; | 684 break; |
679 case IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND: { | 685 case IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND: { |
680 // Background mode must already be enabled (as otherwise this menu would | 686 // Background mode must already be enabled (as otherwise this menu would |
681 // not be visible). | 687 // not be visible). |
682 DCHECK(IsBackgroundModePrefEnabled()); | 688 DCHECK(IsBackgroundModePrefEnabled()); |
683 DCHECK(chrome::WillKeepAlive()); | 689 DCHECK(browser_lifetime::WillKeepAlive()); |
684 | 690 |
685 RecordMenuItemClick(MENU_ITEM_KEEP_RUNNING); | 691 RecordMenuItemClick(MENU_ITEM_KEEP_RUNNING); |
686 | 692 |
687 // Set the background mode pref to "disabled" - the resulting notification | 693 // Set the background mode pref to "disabled" - the resulting notification |
688 // will result in a call to DisableBackgroundMode(). | 694 // will result in a call to DisableBackgroundMode(). |
689 PrefService* service = g_browser_process->local_state(); | 695 PrefService* service = g_browser_process->local_state(); |
690 DCHECK(service); | 696 DCHECK(service); |
691 service->SetBoolean(prefs::kBackgroundModeEnabled, false); | 697 service->SetBoolean(prefs::kBackgroundModeEnabled, false); |
692 break; | 698 break; |
693 } | 699 } |
694 default: | 700 default: |
695 if (bmd) { | 701 if (bmd) { |
696 bmd->ExecuteCommand(command_id, event_flags); | 702 bmd->ExecuteCommand(command_id, event_flags); |
697 } else { | 703 } else { |
698 UserManager::Show(base::FilePath(), | 704 UserManager::Show(base::FilePath(), |
699 profiles::USER_MANAGER_NO_TUTORIAL, | 705 profiles::USER_MANAGER_NO_TUTORIAL, |
700 profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION); | 706 profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION); |
701 } | 707 } |
702 break; | 708 break; |
703 } | 709 } |
704 } | 710 } |
705 | 711 |
706 | 712 |
707 /////////////////////////////////////////////////////////////////////////////// | 713 /////////////////////////////////////////////////////////////////////////////// |
708 // BackgroundModeManager, private | 714 // BackgroundModeManager, private |
709 void BackgroundModeManager::DecrementKeepAliveCountForStartup() { | 715 void BackgroundModeManager::DecrementKeepAliveCountForStartup() { |
710 if (keep_alive_for_startup_) { | 716 if (keep_alive_for_startup_) { |
711 keep_alive_for_startup_ = false; | |
712 // We call this via the message queue to make sure we don't try to end | 717 // We call this via the message queue to make sure we don't try to end |
713 // keep-alive (which can shutdown Chrome) before the message loop has | 718 // keep-alive (which can shutdown Chrome) before the message loop has |
714 // started. | 719 // started. |
715 base::ThreadTaskRunnerHandle::Get()->PostTask( | 720 base::ThreadTaskRunnerHandle::Get()->PostTask( |
716 FROM_HERE, base::Bind(&chrome::DecrementKeepAliveCount)); | 721 FROM_HERE, |
| 722 base::Bind(&DoDecrementKeepAliveCountForStartup, |
| 723 base::Passed(&keep_alive_for_startup_))); |
717 } | 724 } |
718 } | 725 } |
719 | 726 |
720 void BackgroundModeManager::StartBackgroundMode() { | 727 void BackgroundModeManager::StartBackgroundMode() { |
721 DCHECK(ShouldBeInBackgroundMode()); | 728 DCHECK(ShouldBeInBackgroundMode()); |
722 // Don't bother putting ourselves in background mode if we're already there | 729 // Don't bother putting ourselves in background mode if we're already there |
723 // or if background mode is disabled. | 730 // or if background mode is disabled. |
724 if (in_background_mode_) | 731 if (in_background_mode_) |
725 return; | 732 return; |
726 | 733 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
785 UpdateKeepAliveAndTrayIcon(); | 792 UpdateKeepAliveAndTrayIcon(); |
786 } | 793 } |
787 | 794 |
788 void BackgroundModeManager::ResumeBackgroundMode() { | 795 void BackgroundModeManager::ResumeBackgroundMode() { |
789 background_mode_suspended_ = false; | 796 background_mode_suspended_ = false; |
790 UpdateKeepAliveAndTrayIcon(); | 797 UpdateKeepAliveAndTrayIcon(); |
791 } | 798 } |
792 | 799 |
793 void BackgroundModeManager::UpdateKeepAliveAndTrayIcon() { | 800 void BackgroundModeManager::UpdateKeepAliveAndTrayIcon() { |
794 if (in_background_mode_ && !background_mode_suspended_) { | 801 if (in_background_mode_ && !background_mode_suspended_) { |
795 if (!keeping_alive_) { | 802 if (!keep_alive_for_background_mode_) { |
796 keeping_alive_ = true; | 803 keep_alive_for_background_mode_.reset( |
797 chrome::IncrementKeepAliveCount(); | 804 new browser_lifetime::ScopedKeepAlive); |
798 | 805 |
799 #if defined(OS_WIN) | 806 #if defined(OS_WIN) |
800 browser_watcher::ExitFunnel::RecordSingleEvent( | 807 browser_watcher::ExitFunnel::RecordSingleEvent( |
801 chrome::kBrowserExitCodesRegistryPath, L"BackgroundOn"); | 808 chrome::kBrowserExitCodesRegistryPath, L"BackgroundOn"); |
802 #endif | 809 #endif |
803 } | 810 } |
804 CreateStatusTrayIcon(); | 811 CreateStatusTrayIcon(); |
805 return; | 812 return; |
806 } | 813 } |
807 | 814 |
808 RemoveStatusTrayIcon(); | 815 RemoveStatusTrayIcon(); |
809 if (keeping_alive_) { | 816 if (keep_alive_for_background_mode_) { |
810 keeping_alive_ = false; | 817 keep_alive_for_background_mode_.reset(); |
811 chrome::DecrementKeepAliveCount(); | |
812 | 818 |
813 #if defined(OS_WIN) | 819 #if defined(OS_WIN) |
814 browser_watcher::ExitFunnel::RecordSingleEvent( | 820 browser_watcher::ExitFunnel::RecordSingleEvent( |
815 chrome::kBrowserExitCodesRegistryPath, L"BackgroundOff"); | 821 chrome::kBrowserExitCodesRegistryPath, L"BackgroundOff"); |
816 #endif | 822 #endif |
817 } | 823 } |
818 } | 824 } |
819 | 825 |
820 void BackgroundModeManager::OnBrowserAdded(Browser* browser) { | 826 void BackgroundModeManager::OnBrowserAdded(Browser* browser) { |
821 ResumeBackgroundMode(); | 827 ResumeBackgroundMode(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 OnBackgroundClientInstalled(name); | 866 OnBackgroundClientInstalled(name); |
861 } | 867 } |
862 } | 868 } |
863 | 869 |
864 int BackgroundModeManager::GetBackgroundClientCount() const { | 870 int BackgroundModeManager::GetBackgroundClientCount() const { |
865 int count = 0; | 871 int count = 0; |
866 // Walk the BackgroundModeData for all profiles and count the number of | 872 // Walk the BackgroundModeData for all profiles and count the number of |
867 // clients. | 873 // clients. |
868 for (const auto& it : background_mode_data_) | 874 for (const auto& it : background_mode_data_) |
869 count += it.second->GetBackgroundClientCount(); | 875 count += it.second->GetBackgroundClientCount(); |
870 DCHECK(count >= 0); | 876 DCHECK_GE(count, 0); |
871 return count; | 877 return count; |
872 } | 878 } |
873 | 879 |
874 int BackgroundModeManager::GetBackgroundClientCountForProfile( | 880 int BackgroundModeManager::GetBackgroundClientCountForProfile( |
875 Profile* const profile) const { | 881 Profile* const profile) const { |
876 BackgroundModeManager::BackgroundModeData* bmd = | 882 BackgroundModeManager::BackgroundModeData* bmd = |
877 GetBackgroundModeData(profile); | 883 GetBackgroundModeData(profile); |
878 if (!bmd) | 884 if (!bmd) |
879 return 0; | 885 return 0; |
880 return bmd->GetBackgroundClientCount(); | 886 return bmd->GetBackgroundClientCount(); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1043 } | 1049 } |
1044 } | 1050 } |
1045 return profile_it; | 1051 return profile_it; |
1046 } | 1052 } |
1047 | 1053 |
1048 bool BackgroundModeManager::IsBackgroundModePrefEnabled() const { | 1054 bool BackgroundModeManager::IsBackgroundModePrefEnabled() const { |
1049 PrefService* service = g_browser_process->local_state(); | 1055 PrefService* service = g_browser_process->local_state(); |
1050 DCHECK(service); | 1056 DCHECK(service); |
1051 return service->GetBoolean(prefs::kBackgroundModeEnabled); | 1057 return service->GetBoolean(prefs::kBackgroundModeEnabled); |
1052 } | 1058 } |
OLD | NEW |