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

Unified Diff: chrome/browser/background_mode_manager.cc

Issue 6914021: Modifying the BackgroundModeManager to handle multiple profiles. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 7 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/background_mode_manager.h ('k') | chrome/browser/background_mode_manager_linux.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/background_mode_manager.cc
===================================================================
--- chrome/browser/background_mode_manager.cc (revision 86624)
+++ chrome/browser/background_mode_manager.cc (working copy)
@@ -29,26 +29,114 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
-void BackgroundModeManager::OnApplicationDataChanged(
+
+BackgroundModeManager::BackgroundModeData::BackgroundModeData(
+ Profile* profile,
+ BackgroundModeManager* background_mode_manager)
+ : applications_(new BackgroundApplicationListModel(profile)),
+ status_icon_(NULL),
+ context_menu_(NULL),
+ context_menu_application_offset_(0),
+ profile_(profile),
+ background_mode_manager_(background_mode_manager) {
+}
+
+BackgroundModeManager::BackgroundModeData::~BackgroundModeData() {
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// BackgroundModeManager::BackgroundModeData, ui::SimpleMenuModel overrides
+bool BackgroundModeManager::BackgroundModeData::IsCommandIdChecked(
+ int command_id) const {
+ DCHECK(command_id == IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND);
+ return true;
+}
+
+bool BackgroundModeManager::BackgroundModeData::IsCommandIdEnabled(
+ int command_id) const {
+ // For now, we do not support disabled items.
+ return true;
+}
+
+bool BackgroundModeManager::BackgroundModeData::GetAcceleratorForCommandId(
+ int command_id, ui::Accelerator* accelerator) {
+ // No accelerators for status icon context menus.
+ return false;
+}
+
+void BackgroundModeManager::BackgroundModeData::ExecuteCommand(int item) {
+ switch (item) {
+ case IDC_ABOUT:
+ GetBrowserWindow()->OpenAboutChromeDialog();
+ break;
+ case IDC_EXIT:
+ UserMetrics::RecordAction(UserMetricsAction("Exit"));
+ BrowserList::CloseAllBrowsersAndExit();
+ break;
+ case IDC_OPTIONS:
+ GetBrowserWindow()->OpenOptionsDialog();
+ break;
+ case IDC_TASK_MANAGER:
+ GetBrowserWindow()->OpenTaskManager(true);
+ break;
+ case IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND: {
+ // Background mode must already be enabled (as otherwise this menu would
+ // not be visible).
+ DCHECK(background_mode_manager_->IsBackgroundModePrefEnabled());
+ DCHECK(BrowserList::WillKeepAlive());
+
+ // Set the background mode pref to "disabled" - the resulting notification
+ // will result in a call to DisableBackgroundMode().
+ PrefService* service = g_browser_process->local_state();
+ DCHECK(service);
+ service->SetBoolean(prefs::kBackgroundModeEnabled, false);
+ break;
+ }
+ default:
+ ExecuteApplication(item);
+ break;
+ }
+}
+
+void BackgroundModeManager::BackgroundModeData::ExecuteApplication(
+ int item) {
+ Browser* browser = GetBrowserWindow();
+ const Extension* extension = applications_->GetExtension(item);
+ browser->OpenApplicationTab(profile_, extension, NEW_FOREGROUND_TAB);
+}
+
+Browser* BackgroundModeManager::BackgroundModeData::GetBrowserWindow() {
+ Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
+ if (!browser) {
+ Browser::OpenEmptyWindow(profile_);
+ browser = BrowserList::GetLastActiveWithProfile(profile_);
+ }
+ return browser;
+}
+
+void BackgroundModeManager::BackgroundModeData::UpdateContextMenuEntryIcon(
const Extension* extension) {
- UpdateContextMenuEntryIcon(extension);
+ if (!context_menu_)
+ return;
+ context_menu_->SetIcon(
+ context_menu_application_offset_ +
+ applications_->GetPosition(extension),
+ *(applications_->GetIcon(extension)));
+
+ status_icon_->SetContextMenu(context_menu_); // for Update effect
}
-void BackgroundModeManager::OnApplicationListChanged() {
- UpdateStatusTrayIconContextMenu();
+bool BackgroundModeManager::BackgroundModeData::HasBackgroundApp() {
+ return (applications_->size() > 0);
}
-BackgroundModeManager::BackgroundModeManager(Profile* profile,
- CommandLine* command_line)
- : profile_(profile),
- applications_(profile),
+///////////////////////////////////////////////////////////////////////////////
+// BackgroundModeManager, public
+BackgroundModeManager::BackgroundModeManager(CommandLine* command_line)
+ : status_tray_(NULL),
background_app_count_(0),
- context_menu_(NULL),
- context_menu_application_offset_(0),
in_background_mode_(false),
- keep_alive_for_startup_(false),
- status_tray_(NULL),
- status_icon_(NULL) {
+ keep_alive_for_startup_(false) {
// If background mode is currently disabled, just exit - don't listen for any
// notifications.
if (IsBackgroundModePermanentlyDisabled(command_line))
@@ -72,9 +160,43 @@
// If the -keep-alive-for-test flag is passed, then always keep chrome running
// in the background until the user explicitly terminates it, by acting as if
// we loaded a background app.
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKeepAliveForTest))
+ if (command_line->HasSwitch(switches::kKeepAliveForTest))
OnBackgroundAppLoaded();
+ // Listen for the application shutting down so we can decrement our KeepAlive
+ // count.
+ registrar_.Add(this, NotificationType::APP_TERMINATING,
+ NotificationService::AllSources());
+}
+
+BackgroundModeManager::~BackgroundModeManager() {
+ for (std::map<Profile*, BackgroundModeInfo>::iterator it =
+ background_mode_data_.begin();
+ it != background_mode_data_.end();
+ ++it) {
+ it->second->applications_->RemoveObserver(this);
+ }
+
+ // 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();
+}
+
+// static
+void BackgroundModeManager::RegisterPrefs(PrefService* prefs) {
+ prefs->RegisterBooleanPref(prefs::kUserCreatedLoginItem, false);
+ prefs->RegisterBooleanPref(prefs::kBackgroundModeEnabled, true);
+}
+
+
+void BackgroundModeManager::RegisterProfile(Profile* profile) {
+ // We don't want to register multiple times for one profile.
+ DCHECK(background_mode_data_.find(profile) == background_mode_data_.end());
+ BackgroundModeInfo bmd(new BackgroundModeData(profile, this));
+ background_mode_data_[profile] = bmd;
+
// Listen for when extensions are loaded/unloaded so we can track the
// number of background apps and modify our keep-alive and launch-on-startup
// state appropriately.
@@ -89,24 +211,11 @@
registrar_.Add(this, NotificationType::EXTENSIONS_READY,
Source<Profile>(profile));
- // Listen for the application shutting down so we can decrement our KeepAlive
- // count.
- registrar_.Add(this, NotificationType::APP_TERMINATING,
- NotificationService::AllSources());
-
- applications_.AddObserver(this);
+ background_mode_data_[profile]->applications_->AddObserver(this);
}
-BackgroundModeManager::~BackgroundModeManager() {
- applications_.RemoveObserver(this);
-
- // 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();
-}
-
+///////////////////////////////////////////////////////////////////////////////
+// BackgroundModeManager, NotificationObserver overrides
void BackgroundModeManager::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
@@ -139,8 +248,9 @@
if (BackgroundApplicationListModel::IsBackgroundApp(*extension)) {
// Extensions loaded after the ExtensionsService is ready should be
// treated as new installs.
- if (profile_->GetExtensionService()->is_ready())
- OnBackgroundAppInstalled(extension);
+ Profile* profile = Source<Profile>(source).ptr();
+ if (profile->GetExtensionService()->is_ready())
+ OnBackgroundAppInstalled(extension, profile);
OnBackgroundAppLoaded();
}
}
@@ -157,7 +267,8 @@
if (info->already_disabled)
return;
OnBackgroundAppUnloaded();
- OnBackgroundAppUninstalled();
+ Profile* profile = Source<Profile>(source).ptr();
+ OnBackgroundAppUninstalled(profile);
}
break;
case NotificationType::APP_TERMINATING:
@@ -177,6 +288,20 @@
}
}
+///////////////////////////////////////////////////////////////////////////////
+// BackgroundModeManager, BackgroundApplicationListModel::Observer overrides
+void BackgroundModeManager::OnApplicationDataChanged(
+ const Extension* extension, Profile* profile) {
+ UpdateContextMenuEntryIcon(extension, profile);
+}
+
+void BackgroundModeManager::OnApplicationListChanged(Profile* profile) {
+ UpdateStatusTrayIconContextMenu(profile);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// BackgroundModeManager, private
void BackgroundModeManager::EndKeepAliveForStartup() {
if (keep_alive_for_startup_) {
keep_alive_for_startup_ = false;
@@ -191,6 +316,8 @@
void BackgroundModeManager::OnBackgroundAppLoaded() {
// When a background app loads, increment our count and also enable
// KeepAlive mode if the preference is set.
+ // The count here is across all profiles since we must have background
+ // mode if there is even one.
background_app_count_++;
if (background_app_count_ == 1)
StartBackgroundMode();
@@ -209,9 +336,21 @@
BrowserList::StartKeepAlive();
// Display a status icon to exit Chrome.
- CreateStatusTrayIcon();
+ InitStatusTrayIcons();
}
+void BackgroundModeManager::InitStatusTrayIcons() {
+ // Only initialize status tray icons for those profiles which actually
+ // have a background app running.
+ for (std::map<Profile*, BackgroundModeInfo>::iterator it =
+ background_mode_data_.begin();
+ it != background_mode_data_.end();
+ ++it) {
+ if (it->second->HasBackgroundApp())
+ CreateStatusTrayIcon(it->first);
+ }
+}
+
void BackgroundModeManager::OnBackgroundAppUnloaded() {
// When a background app unloads, decrement our count and also end
// KeepAlive mode if appropriate.
@@ -228,7 +367,13 @@
// End KeepAlive mode and blow away our status tray icon.
BrowserList::EndKeepAlive();
- RemoveStatusTrayIcon();
+ // There is a status tray icon for each profile. Blow them all away.
+ for (std::map<Profile*, BackgroundModeInfo>::iterator it =
+ background_mode_data_.begin();
+ it != background_mode_data_.end();
+ ++it) {
+ RemoveStatusTrayIcon(it->first);
+ }
}
void BackgroundModeManager::EnableBackgroundMode() {
@@ -250,7 +395,7 @@
}
void BackgroundModeManager::OnBackgroundAppInstalled(
- const Extension* extension) {
+ const Extension* extension, Profile* profile) {
// Background mode is disabled - don't do anything.
if (!IsBackgroundModePrefEnabled())
return;
@@ -260,58 +405,84 @@
if (background_app_count_ == 0)
EnableLaunchOnStartup(true);
+ // Check if we need a status tray icon and make one if we do.
+ CreateStatusTrayIcon(profile);
+
// Notify the user that a background app has been installed.
if (extension) // NULL when called by unit tests.
- DisplayAppInstalledNotification(extension);
+ DisplayAppInstalledNotification(extension, profile);
}
-void BackgroundModeManager::OnBackgroundAppUninstalled() {
+void BackgroundModeManager::OnBackgroundAppUninstalled(Profile* profile) {
+ // Check if we need to remove the status tray icon if there are no
+ // more background apps.
+ BackgroundModeInfo bmd = GetBackgroundModeInfo(profile);
+ DCHECK(bmd.get());
+ // If there are still background apps for this profile, don't remove
+ // the status tray icon.
+ if (!bmd->HasBackgroundApp())
+ RemoveStatusTrayIcon(profile);
+
// When uninstalling a background app, disable launch on startup if
// we have no more background apps.
if (background_app_count_ == 0)
EnableLaunchOnStartup(false);
}
-void BackgroundModeManager::CreateStatusTrayIcon() {
+void BackgroundModeManager::CreateStatusTrayIcon(Profile* profile) {
// Only need status icons on windows/linux. ChromeOS doesn't allow exiting
// Chrome and Mac can use the dock icon instead.
+
+ // Since there are multiple profiles which share the status tray, we now
+ // use the browser process to keep track of it.
#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS)
if (!status_tray_)
- status_tray_ = profile_->GetStatusTray();
+ status_tray_ = g_browser_process->status_tray();
#endif
// If the platform doesn't support status icons, or we've already created
// our status icon, just return.
- if (!status_tray_ || status_icon_)
+ BackgroundModeInfo bmd = GetBackgroundModeInfo(profile);
+ if (!status_tray_ || bmd->status_icon_)
return;
- status_icon_ = status_tray_->CreateStatusIcon();
- if (!status_icon_)
+
+ bmd->status_icon_ = status_tray_->CreateStatusIcon();
+ if (!bmd->status_icon_)
return;
- // Set the image and add ourselves as a click observer on it
+ // Set the image and add ourselves as a click observer on it.
+ // TODO(rlp): Status tray icon should have submenus for each profile.
SkBitmap* bitmap = ResourceBundle::GetSharedInstance().GetBitmapNamed(
IDR_STATUS_TRAY_ICON);
- status_icon_->SetImage(*bitmap);
- status_icon_->SetToolTip(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
- UpdateStatusTrayIconContextMenu();
+ bmd->status_icon_->SetImage(*bitmap);
+ bmd->status_icon_->SetToolTip(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
+ UpdateStatusTrayIconContextMenu(profile);
}
void BackgroundModeManager::UpdateContextMenuEntryIcon(
- const Extension* extension) {
- if (!context_menu_)
- return;
- context_menu_->SetIcon(
- context_menu_application_offset_ + applications_.GetPosition(extension),
- *(applications_.GetIcon(extension)));
- status_icon_->SetContextMenu(context_menu_); // for Update effect
+ const Extension* extension, Profile* profile) {
+ BackgroundModeInfo bmd = GetBackgroundModeInfo(profile);
+ DCHECK(bmd.get());
+ bmd->UpdateContextMenuEntryIcon(extension);
}
-void BackgroundModeManager::UpdateStatusTrayIconContextMenu() {
- if (!status_icon_)
- return;
+void BackgroundModeManager::UpdateStatusTrayIconContextMenu(Profile* profile) {
+ BackgroundModeInfo bmd = GetBackgroundModeInfo(profile);
+ DCHECK(bmd.get());
+ if (!bmd->status_icon_) {
+ // If no status icon exists, it's either because one wasn't created when
+ // it should have been which can happen when extensions load after the
+ // profile has already been registered with the background mode manager.
+ // The other case is if we aren't in background mode.
+ if (in_background_mode_)
+ CreateStatusTrayIcon(profile);
+ else
+ return;
+ }
+ // TODO(rlp): Add current profile color.
// Create a context menu item for Chrome.
- ui::SimpleMenuModel* menu = new ui::SimpleMenuModel(this);
+ ui::SimpleMenuModel* menu = new ui::SimpleMenuModel(bmd.get());
// Add About item
menu->AddItem(IDC_ABOUT, l10n_util::GetStringFUTF16(IDS_ABOUT,
l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
@@ -319,105 +490,43 @@
menu->AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER);
menu->AddSeparator();
int position = 0;
- context_menu_application_offset_ = menu->GetItemCount();
- for (ExtensionList::const_iterator cursor = applications_.begin();
- cursor != applications_.end();
+ bmd->context_menu_application_offset_ = menu->GetItemCount();
+ for (ExtensionList::const_iterator cursor = bmd->applications_->begin();
+ cursor != bmd->applications_->end();
++cursor, ++position) {
- const SkBitmap* icon = applications_.GetIcon(*cursor);
- DCHECK(position == applications_.GetPosition(*cursor));
+ const SkBitmap* icon = bmd->applications_->GetIcon(*cursor);
+ DCHECK(position == bmd->applications_->GetPosition(*cursor));
const std::string& name = (*cursor)->name();
menu->AddItem(position, UTF8ToUTF16(name));
if (icon)
menu->SetIcon(menu->GetItemCount() - 1, *icon);
}
- if (applications_.size() > 0)
+ if (bmd->applications_->size() > 0)
menu->AddSeparator();
menu->AddCheckItemWithStringId(
IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND,
IDS_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND);
menu->AddItemWithStringId(IDC_EXIT, IDS_EXIT);
- context_menu_ = menu;
- status_icon_->SetContextMenu(menu);
+ bmd->context_menu_ = menu;
+ bmd->status_icon_->SetContextMenu(menu);
}
-bool BackgroundModeManager::IsCommandIdChecked(int command_id) const {
- DCHECK(command_id == IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND);
- return true;
-}
+void BackgroundModeManager::RemoveStatusTrayIcon(Profile* profile) {
+ BackgroundModeInfo bmd = GetBackgroundModeInfo(profile);
+ DCHECK(bmd.get());
-bool BackgroundModeManager::IsCommandIdEnabled(int command_id) const {
- // For now, we do not support disabled items.
- return true;
+ if (bmd->status_icon_)
+ status_tray_->RemoveStatusIcon(bmd->status_icon_);
+ bmd->status_icon_ = NULL;
+ bmd->context_menu_ = NULL; // Do not delete, points within |status_icon_|.
}
-bool BackgroundModeManager::GetAcceleratorForCommandId(
- int command_id,
- ui::Accelerator* accelerator) {
- // No accelerators for status icon context menus.
- return false;
+BackgroundModeManager::BackgroundModeInfo
+BackgroundModeManager::GetBackgroundModeInfo(Profile* profile) {
+ DCHECK(background_mode_data_.find(profile) != background_mode_data_.end());
+ return background_mode_data_[profile];
}
-void BackgroundModeManager::RemoveStatusTrayIcon() {
- if (status_icon_)
- status_tray_->RemoveStatusIcon(status_icon_);
- status_icon_ = NULL;
- context_menu_ = NULL; // Do not delete, points within |status_icon_|.
-}
-
-void BackgroundModeManager::ExecuteApplication(int item) {
- DCHECK(item >= 0 && item < static_cast<int>(applications_.size()));
- Browser* browser = BrowserList::GetLastActive();
- if (!browser) {
- Browser::OpenEmptyWindow(profile_);
- browser = BrowserList::GetLastActive();
- }
- const Extension* extension = applications_.GetExtension(item);
- browser->OpenApplicationTab(profile_, extension, NEW_FOREGROUND_TAB);
-}
-
-void BackgroundModeManager::ExecuteCommand(int item) {
- switch (item) {
- case IDC_ABOUT:
- GetBrowserWindow()->OpenAboutChromeDialog();
- break;
- case IDC_EXIT:
- UserMetrics::RecordAction(UserMetricsAction("Exit"));
- BrowserList::CloseAllBrowsersAndExit();
- break;
- case IDC_OPTIONS:
- GetBrowserWindow()->OpenOptionsDialog();
- break;
- case IDC_TASK_MANAGER:
- GetBrowserWindow()->OpenTaskManager(true);
- break;
- case IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND: {
- // Background mode must already be enabled (as otherwise this menu would
- // not be visible).
- DCHECK(IsBackgroundModePrefEnabled());
- DCHECK(BrowserList::WillKeepAlive());
-
- // Set the background mode pref to "disabled" - the resulting notification
- // will result in a call to DisableBackgroundMode().
- PrefService* service = g_browser_process->local_state();
- DCHECK(service);
- service->SetBoolean(prefs::kBackgroundModeEnabled, false);
- break;
- }
- default:
- ExecuteApplication(item);
- break;
- }
-}
-
-Browser* BackgroundModeManager::GetBrowserWindow() {
- Browser* browser = BrowserList::GetLastActive();
- if (!browser) {
- Browser::OpenEmptyWindow(profile_);
- browser = BrowserList::GetLastActive();
- }
- return browser;
-}
-
// static
bool BackgroundModeManager::IsBackgroundModePermanentlyDisabled(
const CommandLine* command_line) {
@@ -440,10 +549,4 @@
PrefService* service = g_browser_process->local_state();
DCHECK(service);
return service->GetBoolean(prefs::kBackgroundModeEnabled);
-}
-
-// static
-void BackgroundModeManager::RegisterPrefs(PrefService* prefs) {
- prefs->RegisterBooleanPref(prefs::kUserCreatedLoginItem, false);
- prefs->RegisterBooleanPref(prefs::kBackgroundModeEnabled, true);
-}
+}
« no previous file with comments | « chrome/browser/background_mode_manager.h ('k') | chrome/browser/background_mode_manager_linux.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698