diff options
-rw-r--r-- | chrome/browser/background_mode_manager.cc | 59 | ||||
-rw-r--r-- | chrome/browser/background_mode_manager.h | 14 | ||||
-rw-r--r-- | chrome/browser/background_mode_manager_unittest.cc | 61 |
3 files changed, 122 insertions, 12 deletions
diff --git a/chrome/browser/background_mode_manager.cc b/chrome/browser/background_mode_manager.cc index 4fe5e2e..7c5a4e2 100644 --- a/chrome/browser/background_mode_manager.cc +++ b/chrome/browser/background_mode_manager.cc @@ -34,6 +34,7 @@ BackgroundModeManager::BackgroundModeManager(Profile* profile) : profile_(profile), background_app_count_(0), + in_background_mode_(false), status_tray_(NULL), status_icon_(NULL) { // If background mode is globally disabled, just exit - don't listen for @@ -73,13 +74,20 @@ BackgroundModeManager::BackgroundModeManager(Profile* profile) registrar_.Add(this, NotificationType::APP_TERMINATING, NotificationService::AllSources()); - + // Listen for changes to the background mode preference. + profile_->GetPrefs()->AddPrefObserver(prefs::kBackgroundModeEnabled, this); } BackgroundModeManager::~BackgroundModeManager() { - // If we're going away, remove our status tray icon so we don't get any events - // from it. - RemoveStatusTrayIcon(); + // We're going away, so exit background mode (does nothing if we aren't in + // background mode currently). This is primarily needed for unit tests, + // because in an actual running system we'd get an APP_TERMINATING + // notification before being destroyed. + EndBackgroundMode(); + // Manually remove our pref observer so we don't get notified for prefs + // changes (have to do it manually because we can't use the registrar for + // prefs notifications). + profile_->GetPrefs()->RemovePrefObserver(prefs::kBackgroundModeEnabled, this); } bool BackgroundModeManager::IsBackgroundModeEnabled() { @@ -125,14 +133,18 @@ void BackgroundModeManager::Observe(NotificationType type, OnBackgroundAppUninstalled(); break; case NotificationType::APP_TERMINATING: - // Performing an explicit shutdown, so exit background mode if we were in - // background mode. - if (background_app_count_ > 0 && IsBackgroundModeEnabled()) - EndBackgroundMode(); + // Performing an explicit shutdown, so exit background mode (does nothing + // if we aren't in background mode currently). + EndBackgroundMode(); // Shutting down, so don't listen for any more notifications so we don't // try to re-enter/exit background mode again. registrar_.RemoveAll(); break; + case NotificationType::PREF_CHANGED: + DCHECK(0 == Details<std::string>(details).ptr()->compare( + prefs::kBackgroundModeEnabled)); + OnBackgroundModePrefChanged(); + break; default: NOTREACHED(); break; @@ -143,6 +155,24 @@ bool BackgroundModeManager::IsBackgroundApp(Extension* extension) { return extension->HasApiPermission(Extension::kBackgroundPermission); } + +void BackgroundModeManager::OnBackgroundModePrefChanged() { + // Background mode has been enabled/disabled in preferences, so update our + // state accordingly. + if (IsBackgroundModeEnabled() && !in_background_mode_ && + background_app_count_ > 0) { + // We should be in background mode, but we're not, so switch to background + // mode. + EnableLaunchOnStartup(true); + StartBackgroundMode(); + } + if (!IsBackgroundModeEnabled() && in_background_mode_) { + // We're in background mode, but we shouldn't be any longer. + EnableLaunchOnStartup(false); + EndBackgroundMode(); + } +} + void BackgroundModeManager::OnBackgroundAppLoaded() { // When a background app loads, increment our count and also enable // KeepAlive mode if the preference is set. @@ -152,6 +182,13 @@ void BackgroundModeManager::OnBackgroundAppLoaded() { } void BackgroundModeManager::StartBackgroundMode() { + // Don't bother putting ourselves in background mode if we're already there. + if (in_background_mode_) + return; + + // Mark ourselves as running in background mode. + in_background_mode_ = true; + // Put ourselves in KeepAlive mode and create a status tray icon. BrowserList::StartKeepAlive(); @@ -163,12 +200,16 @@ void BackgroundModeManager::OnBackgroundAppUnloaded() { // When a background app unloads, decrement our count and also end // KeepAlive mode if appropriate. background_app_count_--; - DCHECK(background_app_count_ == 0); + DCHECK(background_app_count_ >= 0); if (background_app_count_ == 0 && IsBackgroundModeEnabled()) EndBackgroundMode(); } void BackgroundModeManager::EndBackgroundMode() { + if (!in_background_mode_) + return; + in_background_mode_ = false; + // End KeepAlive mode and blow away our status tray icon. BrowserList::EndKeepAlive(); RemoveStatusTrayIcon(); diff --git a/chrome/browser/background_mode_manager.h b/chrome/browser/background_mode_manager.h index 38b010c..9970391 100644 --- a/chrome/browser/background_mode_manager.h +++ b/chrome/browser/background_mode_manager.h @@ -49,6 +49,12 @@ class BackgroundModeManager BackgroundAppLoadUnload); FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest, BackgroundAppInstallUninstall); + FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest, + BackgroundPrefDisabled); + FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest, + BackgroundPrefDynamicDisable); + FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest, + BackgroundPrefDynamicEnable); // NotificationObserver implementation. virtual void Observe(NotificationType type, @@ -76,6 +82,9 @@ class BackgroundModeManager // launch-on-startup is disabled if appropriate. void OnBackgroundAppUninstalled(); + // Invoked when the kBackgroundModeEnabled preference has changed. + void OnBackgroundModePrefChanged(); + // Returns true if the passed extension is a background app. bool IsBackgroundApp(Extension* extension); @@ -121,6 +130,11 @@ class BackgroundModeManager // The number of background apps currently loaded. int background_app_count_; + // Set to true when we are running in background mode. Allows us to track our + // current background state so we can take the appropriate action when the + // user disables/enables background mode via preferences. + bool in_background_mode_; + // Reference to our status tray (owned by our parent profile). If null, the // platform doesn't support status icons. StatusTray* status_tray_; diff --git a/chrome/browser/background_mode_manager_unittest.cc b/chrome/browser/background_mode_manager_unittest.cc index 087b4fe..f028c7c 100644 --- a/chrome/browser/background_mode_manager_unittest.cc +++ b/chrome/browser/background_mode_manager_unittest.cc @@ -4,10 +4,14 @@ #include "chrome/browser/background_mode_manager.h" #include "chrome/browser/browser_list.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/common/pref_names.h" #include "chrome/test/testing_profile.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using testing::InSequence; + class TestBackgroundModeManager : public BackgroundModeManager { public: explicit TestBackgroundModeManager(Profile* profile) @@ -19,28 +23,79 @@ class TestBackgroundModeManager : public BackgroundModeManager { }; TEST(BackgroundModeManagerTest, BackgroundAppLoadUnload) { + InSequence s; TestingProfile profile; TestBackgroundModeManager manager(&profile); + EXPECT_CALL(manager, CreateStatusTrayIcon()); + EXPECT_CALL(manager, RemoveStatusTrayIcon()); EXPECT_FALSE(BrowserList::WillKeepAlive()); // Call to AppLoaded() will cause the status tray to be created, then call to // unloaded will result in call to remove the icon. - EXPECT_CALL(manager, CreateStatusTrayIcon()); manager.OnBackgroundAppLoaded(); EXPECT_TRUE(BrowserList::WillKeepAlive()); - EXPECT_CALL(manager, RemoveStatusTrayIcon()); manager.OnBackgroundAppUnloaded(); EXPECT_FALSE(BrowserList::WillKeepAlive()); } TEST(BackgroundModeManagerTest, BackgroundAppInstallUninstall) { + InSequence s; TestingProfile profile; TestBackgroundModeManager manager(&profile); // Call to AppInstalled() will cause chrome to be set to launch on startup, // and call to AppUninstalling() set chrome to not launch on startup. EXPECT_CALL(manager, EnableLaunchOnStartup(true)); + EXPECT_CALL(manager, CreateStatusTrayIcon()); + EXPECT_CALL(manager, EnableLaunchOnStartup(false)); + EXPECT_CALL(manager, RemoveStatusTrayIcon()); manager.OnBackgroundAppInstalled(); manager.OnBackgroundAppLoaded(); - EXPECT_CALL(manager, EnableLaunchOnStartup(false)); manager.OnBackgroundAppUninstalled(); manager.OnBackgroundAppUnloaded(); } + +TEST(BackgroundModeManagerTest, BackgroundPrefDisabled) { + InSequence s; + TestingProfile profile; + profile.GetPrefs()->SetBoolean(prefs::kBackgroundModeEnabled, false); + TestBackgroundModeManager manager(&profile); + // Should not change launch on startup status when installing/uninstalling + // if background mode is disabled. + EXPECT_CALL(manager, EnableLaunchOnStartup(true)).Times(0); + EXPECT_CALL(manager, CreateStatusTrayIcon()).Times(0); + manager.OnBackgroundAppInstalled(); + manager.OnBackgroundAppLoaded(); + EXPECT_FALSE(BrowserList::WillKeepAlive()); + manager.OnBackgroundAppUninstalled(); + manager.OnBackgroundAppUnloaded(); +} + +TEST(BackgroundModeManagerTest, BackgroundPrefDynamicDisable) { + InSequence s; + TestingProfile profile; + TestBackgroundModeManager manager(&profile); + EXPECT_CALL(manager, EnableLaunchOnStartup(true)); + EXPECT_CALL(manager, CreateStatusTrayIcon()); + EXPECT_CALL(manager, EnableLaunchOnStartup(false)); + EXPECT_CALL(manager, RemoveStatusTrayIcon()); + manager.OnBackgroundAppInstalled(); + manager.OnBackgroundAppLoaded(); + EXPECT_TRUE(BrowserList::WillKeepAlive()); + // Disable status on the fly. + profile.GetPrefs()->SetBoolean(prefs::kBackgroundModeEnabled, false); + EXPECT_FALSE(BrowserList::WillKeepAlive()); +} + +TEST(BackgroundModeManagerTest, BackgroundPrefDynamicEnable) { + InSequence s; + TestingProfile profile; + TestBackgroundModeManager manager(&profile); + profile.GetPrefs()->SetBoolean(prefs::kBackgroundModeEnabled, false); + EXPECT_CALL(manager, EnableLaunchOnStartup(true)); + EXPECT_CALL(manager, CreateStatusTrayIcon()); + manager.OnBackgroundAppInstalled(); + manager.OnBackgroundAppLoaded(); + EXPECT_FALSE(BrowserList::WillKeepAlive()); + // Enable status on the fly. + profile.GetPrefs()->SetBoolean(prefs::kBackgroundModeEnabled, true); + EXPECT_TRUE(BrowserList::WillKeepAlive()); +} |