summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/background_mode_manager.cc59
-rw-r--r--chrome/browser/background_mode_manager.h14
-rw-r--r--chrome/browser/background_mode_manager_unittest.cc61
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());
+}