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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 <string> 5 #include <string>
6 6
7 #include "base/base_paths.h" 7 #include "base/base_paths.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
(...skipping 11 matching lines...) Expand all
22 #include "chrome/common/pref_names.h" 22 #include "chrome/common/pref_names.h"
23 #include "content/browser/user_metrics.h" 23 #include "content/browser/user_metrics.h"
24 #include "content/common/notification_service.h" 24 #include "content/common/notification_service.h"
25 #include "content/common/notification_type.h" 25 #include "content/common/notification_type.h"
26 #include "grit/chromium_strings.h" 26 #include "grit/chromium_strings.h"
27 #include "grit/generated_resources.h" 27 #include "grit/generated_resources.h"
28 #include "grit/theme_resources.h" 28 #include "grit/theme_resources.h"
29 #include "ui/base/l10n/l10n_util.h" 29 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/base/resource/resource_bundle.h" 30 #include "ui/base/resource/resource_bundle.h"
31 31
32 void BackgroundModeManager::OnApplicationDataChanged( 32
33 const Extension* extension) { 33 BackgroundModeManager::BackgroundModeData::BackgroundModeData(
34 UpdateContextMenuEntryIcon(extension); 34 Profile* profile,
35 BackgroundModeManager* background_mode_manager)
36 : applications_(new BackgroundApplicationListModel(profile)),
37 status_icon_(NULL),
38 context_menu_(NULL),
39 context_menu_application_offset_(0),
40 profile_(profile),
41 background_mode_manager_(background_mode_manager) {
35 } 42 }
36 43
37 void BackgroundModeManager::OnApplicationListChanged() { 44 BackgroundModeManager::BackgroundModeData::~BackgroundModeData() {
38 UpdateStatusTrayIconContextMenu();
39 } 45 }
40 46
41 BackgroundModeManager::BackgroundModeManager(Profile* profile, 47 ///////////////////////////////////////////////////////////////////////////////
42 CommandLine* command_line) 48 // BackgroundModeManager::BackgroundModeData, ui::SimpleMenuModel overrides
43 : profile_(profile), 49 bool BackgroundModeManager::BackgroundModeData::IsCommandIdChecked(
44 applications_(profile), 50 int command_id) const {
51 DCHECK(command_id == IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND);
52 return true;
53 }
54
55 bool BackgroundModeManager::BackgroundModeData::IsCommandIdEnabled(
56 int command_id) const {
57 // For now, we do not support disabled items.
58 return true;
59 }
60
61 bool BackgroundModeManager::BackgroundModeData::GetAcceleratorForCommandId(
62 int command_id, ui::Accelerator* accelerator) {
63 // No accelerators for status icon context menus.
64 return false;
65 }
66
67 void BackgroundModeManager::BackgroundModeData::ExecuteCommand(int item) {
68 switch (item) {
69 case IDC_ABOUT:
70 GetBrowserWindow()->OpenAboutChromeDialog();
71 break;
72 case IDC_EXIT:
73 UserMetrics::RecordAction(UserMetricsAction("Exit"));
74 BrowserList::CloseAllBrowsersAndExit();
75 break;
76 case IDC_OPTIONS:
77 GetBrowserWindow()->OpenOptionsDialog();
78 break;
79 case IDC_TASK_MANAGER:
80 GetBrowserWindow()->OpenTaskManager(true);
81 break;
82 case IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND: {
83 // Background mode must already be enabled (as otherwise this menu would
84 // not be visible).
85 DCHECK(background_mode_manager_->IsBackgroundModePrefEnabled());
86 DCHECK(BrowserList::WillKeepAlive());
87
88 // Set the background mode pref to "disabled" - the resulting notification
89 // will result in a call to DisableBackgroundMode().
90 PrefService* service = g_browser_process->local_state();
91 DCHECK(service);
92 service->SetBoolean(prefs::kBackgroundModeEnabled, false);
93 break;
94 }
95 default:
96 ExecuteApplication(item);
97 break;
98 }
99 }
100
101 void BackgroundModeManager::BackgroundModeData::ExecuteApplication(
102 int item) {
103 Browser* browser = GetBrowserWindow();
104 const Extension* extension = applications_->GetExtension(item);
105 browser->OpenApplicationTab(profile_, extension, NEW_FOREGROUND_TAB);
106 }
107
108 Browser* BackgroundModeManager::BackgroundModeData::GetBrowserWindow() {
109 Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
110 if (!browser) {
111 Browser::OpenEmptyWindow(profile_);
112 browser = BrowserList::GetLastActiveWithProfile(profile_);
113 }
114 return browser;
115 }
116
117 void BackgroundModeManager::BackgroundModeData::UpdateContextMenuEntryIcon(
118 const Extension* extension) {
119 if (!context_menu_)
120 return;
121 context_menu_->SetIcon(
122 context_menu_application_offset_ +
123 applications_->GetPosition(extension),
124 *(applications_->GetIcon(extension)));
125
126 status_icon_->SetContextMenu(context_menu_); // for Update effect
127 }
128
129 bool BackgroundModeManager::BackgroundModeData::HasBackgroundApp() {
130 return (applications_->size() > 0);
131 }
132
133 ///////////////////////////////////////////////////////////////////////////////
134 // BackgroundModeManager, public
135 BackgroundModeManager::BackgroundModeManager(CommandLine* command_line)
136 : status_tray_(NULL),
45 background_app_count_(0), 137 background_app_count_(0),
46 context_menu_(NULL),
47 context_menu_application_offset_(0),
48 in_background_mode_(false), 138 in_background_mode_(false),
49 keep_alive_for_startup_(false), 139 keep_alive_for_startup_(false) {
50 status_tray_(NULL),
51 status_icon_(NULL) {
52 // If background mode is currently disabled, just exit - don't listen for any 140 // If background mode is currently disabled, just exit - don't listen for any
53 // notifications. 141 // notifications.
54 if (IsBackgroundModePermanentlyDisabled(command_line)) 142 if (IsBackgroundModePermanentlyDisabled(command_line))
55 return; 143 return;
56 144
57 // Listen for the background mode preference changing. 145 // Listen for the background mode preference changing.
58 if (g_browser_process->local_state()) { // Skip for unit tests 146 if (g_browser_process->local_state()) { // Skip for unit tests
59 pref_registrar_.Init(g_browser_process->local_state()); 147 pref_registrar_.Init(g_browser_process->local_state());
60 pref_registrar_.Add(prefs::kBackgroundModeEnabled, this); 148 pref_registrar_.Add(prefs::kBackgroundModeEnabled, this);
61 } 149 }
62 150
63 // Keep the browser alive until extensions are done loading - this is needed 151 // Keep the browser alive until extensions are done loading - this is needed
64 // by the --no-startup-window flag. We want to stay alive until we load 152 // by the --no-startup-window flag. We want to stay alive until we load
65 // extensions, at which point we should either run in background mode (if 153 // extensions, at which point we should either run in background mode (if
66 // there are background apps) or exit if there are none. 154 // there are background apps) or exit if there are none.
67 if (command_line->HasSwitch(switches::kNoStartupWindow)) { 155 if (command_line->HasSwitch(switches::kNoStartupWindow)) {
68 keep_alive_for_startup_ = true; 156 keep_alive_for_startup_ = true;
69 BrowserList::StartKeepAlive(); 157 BrowserList::StartKeepAlive();
70 } 158 }
71 159
72 // If the -keep-alive-for-test flag is passed, then always keep chrome running 160 // If the -keep-alive-for-test flag is passed, then always keep chrome running
73 // in the background until the user explicitly terminates it, by acting as if 161 // in the background until the user explicitly terminates it, by acting as if
74 // we loaded a background app. 162 // we loaded a background app.
75 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKeepAliveForTest)) 163 if (command_line->HasSwitch(switches::kKeepAliveForTest))
76 OnBackgroundAppLoaded(); 164 OnBackgroundAppLoaded();
77 165
166 // Listen for the application shutting down so we can decrement our KeepAlive
167 // count.
168 registrar_.Add(this, NotificationType::APP_TERMINATING,
169 NotificationService::AllSources());
170 }
171
172 BackgroundModeManager::~BackgroundModeManager() {
173 for (std::map<Profile*, BackgroundModeInfo>::iterator it =
174 background_mode_data_.begin();
175 it != background_mode_data_.end();
176 ++it) {
177 it->second->applications_->RemoveObserver(this);
178 }
179
180 // We're going away, so exit background mode (does nothing if we aren't in
181 // background mode currently). This is primarily needed for unit tests,
182 // because in an actual running system we'd get an APP_TERMINATING
183 // notification before being destroyed.
184 EndBackgroundMode();
185 }
186
187 // static
188 void BackgroundModeManager::RegisterPrefs(PrefService* prefs) {
189 prefs->RegisterBooleanPref(prefs::kUserCreatedLoginItem, false);
190 prefs->RegisterBooleanPref(prefs::kBackgroundModeEnabled, true);
191 }
192
193
194 void BackgroundModeManager::RegisterProfile(Profile* profile) {
195 // We don't want to register multiple times for one profile.
196 DCHECK(background_mode_data_.find(profile) == background_mode_data_.end());
197 BackgroundModeInfo bmd(new BackgroundModeData(profile, this));
198 background_mode_data_[profile] = bmd;
199
78 // Listen for when extensions are loaded/unloaded so we can track the 200 // Listen for when extensions are loaded/unloaded so we can track the
79 // number of background apps and modify our keep-alive and launch-on-startup 201 // number of background apps and modify our keep-alive and launch-on-startup
80 // state appropriately. 202 // state appropriately.
81 registrar_.Add(this, NotificationType::EXTENSION_LOADED, 203 registrar_.Add(this, NotificationType::EXTENSION_LOADED,
82 Source<Profile>(profile)); 204 Source<Profile>(profile));
83 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, 205 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
84 Source<Profile>(profile)); 206 Source<Profile>(profile));
85 207
86 // Check for the presence of background apps after all extensions have been 208 // Check for the presence of background apps after all extensions have been
87 // loaded, to handle the case where an extension has been manually removed 209 // loaded, to handle the case where an extension has been manually removed
88 // while Chrome was not running. 210 // while Chrome was not running.
89 registrar_.Add(this, NotificationType::EXTENSIONS_READY, 211 registrar_.Add(this, NotificationType::EXTENSIONS_READY,
90 Source<Profile>(profile)); 212 Source<Profile>(profile));
91 213
92 // Listen for the application shutting down so we can decrement our KeepAlive 214 background_mode_data_[profile]->applications_->AddObserver(this);
93 // count.
94 registrar_.Add(this, NotificationType::APP_TERMINATING,
95 NotificationService::AllSources());
96
97 applications_.AddObserver(this);
98 } 215 }
99 216
100 BackgroundModeManager::~BackgroundModeManager() { 217 ///////////////////////////////////////////////////////////////////////////////
101 applications_.RemoveObserver(this); 218 // BackgroundModeManager, NotificationObserver overrides
102
103 // We're going away, so exit background mode (does nothing if we aren't in
104 // background mode currently). This is primarily needed for unit tests,
105 // because in an actual running system we'd get an APP_TERMINATING
106 // notification before being destroyed.
107 EndBackgroundMode();
108 }
109
110 void BackgroundModeManager::Observe(NotificationType type, 219 void BackgroundModeManager::Observe(NotificationType type,
111 const NotificationSource& source, 220 const NotificationSource& source,
112 const NotificationDetails& details) { 221 const NotificationDetails& details) {
113 switch (type.value) { 222 switch (type.value) {
114 case NotificationType::PREF_CHANGED: 223 case NotificationType::PREF_CHANGED:
115 DCHECK(*Details<std::string>(details).ptr() == 224 DCHECK(*Details<std::string>(details).ptr() ==
116 prefs::kBackgroundModeEnabled); 225 prefs::kBackgroundModeEnabled);
117 if (IsBackgroundModePrefEnabled()) 226 if (IsBackgroundModePrefEnabled())
118 EnableBackgroundMode(); 227 EnableBackgroundMode();
119 else 228 else
(...skipping 12 matching lines...) Expand all
132 // launch on startup even after the user removes the LoginItem manually. 241 // launch on startup even after the user removes the LoginItem manually.
133 #if !defined(OS_MACOSX) 242 #if !defined(OS_MACOSX)
134 EnableLaunchOnStartup(background_app_count_ > 0); 243 EnableLaunchOnStartup(background_app_count_ > 0);
135 #endif 244 #endif
136 break; 245 break;
137 case NotificationType::EXTENSION_LOADED: { 246 case NotificationType::EXTENSION_LOADED: {
138 Extension* extension = Details<Extension>(details).ptr(); 247 Extension* extension = Details<Extension>(details).ptr();
139 if (BackgroundApplicationListModel::IsBackgroundApp(*extension)) { 248 if (BackgroundApplicationListModel::IsBackgroundApp(*extension)) {
140 // Extensions loaded after the ExtensionsService is ready should be 249 // Extensions loaded after the ExtensionsService is ready should be
141 // treated as new installs. 250 // treated as new installs.
142 if (profile_->GetExtensionService()->is_ready()) 251 Profile* profile = Source<Profile>(source).ptr();
143 OnBackgroundAppInstalled(extension); 252 if (profile->GetExtensionService()->is_ready())
253 OnBackgroundAppInstalled(extension, profile);
144 OnBackgroundAppLoaded(); 254 OnBackgroundAppLoaded();
145 } 255 }
146 } 256 }
147 break; 257 break;
148 case NotificationType::EXTENSION_UNLOADED: 258 case NotificationType::EXTENSION_UNLOADED:
149 if (BackgroundApplicationListModel::IsBackgroundApp( 259 if (BackgroundApplicationListModel::IsBackgroundApp(
150 *Details<UnloadedExtensionInfo>(details)->extension)) { 260 *Details<UnloadedExtensionInfo>(details)->extension)) {
151 Details<UnloadedExtensionInfo> info = 261 Details<UnloadedExtensionInfo> info =
152 Details<UnloadedExtensionInfo>(details); 262 Details<UnloadedExtensionInfo>(details);
153 // If we already got an unload notification when it was disabled, ignore 263 // If we already got an unload notification when it was disabled, ignore
154 // this one. 264 // this one.
155 // TODO(atwilson): Change BackgroundModeManager to use 265 // TODO(atwilson): Change BackgroundModeManager to use
156 // BackgroundApplicationListModel instead of tracking the count here. 266 // BackgroundApplicationListModel instead of tracking the count here.
157 if (info->already_disabled) 267 if (info->already_disabled)
158 return; 268 return;
159 OnBackgroundAppUnloaded(); 269 OnBackgroundAppUnloaded();
160 OnBackgroundAppUninstalled(); 270 Profile* profile = Source<Profile>(source).ptr();
271 OnBackgroundAppUninstalled(profile);
161 } 272 }
162 break; 273 break;
163 case NotificationType::APP_TERMINATING: 274 case NotificationType::APP_TERMINATING:
164 // Make sure we aren't still keeping the app alive (only happens if we 275 // Make sure we aren't still keeping the app alive (only happens if we
165 // don't receive an EXTENSIONS_READY notification for some reason). 276 // don't receive an EXTENSIONS_READY notification for some reason).
166 EndKeepAliveForStartup(); 277 EndKeepAliveForStartup();
167 // Performing an explicit shutdown, so exit background mode (does nothing 278 // Performing an explicit shutdown, so exit background mode (does nothing
168 // if we aren't in background mode currently). 279 // if we aren't in background mode currently).
169 EndBackgroundMode(); 280 EndBackgroundMode();
170 // Shutting down, so don't listen for any more notifications so we don't 281 // Shutting down, so don't listen for any more notifications so we don't
171 // try to re-enter/exit background mode again. 282 // try to re-enter/exit background mode again.
172 registrar_.RemoveAll(); 283 registrar_.RemoveAll();
173 break; 284 break;
174 default: 285 default:
175 NOTREACHED(); 286 NOTREACHED();
176 break; 287 break;
177 } 288 }
178 } 289 }
179 290
291 ///////////////////////////////////////////////////////////////////////////////
292 // BackgroundModeManager, BackgroundApplicationListModel::Observer overrides
293 void BackgroundModeManager::OnApplicationDataChanged(
294 const Extension* extension, Profile* profile) {
295 UpdateContextMenuEntryIcon(extension, profile);
296 }
297
298 void BackgroundModeManager::OnApplicationListChanged(Profile* profile) {
299 UpdateStatusTrayIconContextMenu(profile);
300 }
301
302
303 ///////////////////////////////////////////////////////////////////////////////
304 // BackgroundModeManager, private
180 void BackgroundModeManager::EndKeepAliveForStartup() { 305 void BackgroundModeManager::EndKeepAliveForStartup() {
181 if (keep_alive_for_startup_) { 306 if (keep_alive_for_startup_) {
182 keep_alive_for_startup_ = false; 307 keep_alive_for_startup_ = false;
183 // We call this via the message queue to make sure we don't try to end 308 // We call this via the message queue to make sure we don't try to end
184 // keep-alive (which can shutdown Chrome) before the message loop has 309 // keep-alive (which can shutdown Chrome) before the message loop has
185 // started. 310 // started.
186 MessageLoop::current()->PostTask( 311 MessageLoop::current()->PostTask(
187 FROM_HERE, NewRunnableFunction(BrowserList::EndKeepAlive)); 312 FROM_HERE, NewRunnableFunction(BrowserList::EndKeepAlive));
188 } 313 }
189 } 314 }
190 315
191 void BackgroundModeManager::OnBackgroundAppLoaded() { 316 void BackgroundModeManager::OnBackgroundAppLoaded() {
192 // When a background app loads, increment our count and also enable 317 // When a background app loads, increment our count and also enable
193 // KeepAlive mode if the preference is set. 318 // KeepAlive mode if the preference is set.
319 // The count here is across all profiles since we must have background
320 // mode if there is even one.
194 background_app_count_++; 321 background_app_count_++;
195 if (background_app_count_ == 1) 322 if (background_app_count_ == 1)
196 StartBackgroundMode(); 323 StartBackgroundMode();
197 } 324 }
198 325
199 void BackgroundModeManager::StartBackgroundMode() { 326 void BackgroundModeManager::StartBackgroundMode() {
200 // Don't bother putting ourselves in background mode if we're already there 327 // Don't bother putting ourselves in background mode if we're already there
201 // or if background mode is disabled. 328 // or if background mode is disabled.
202 if (in_background_mode_ || !IsBackgroundModePrefEnabled()) 329 if (in_background_mode_ || !IsBackgroundModePrefEnabled())
203 return; 330 return;
204 331
205 // Mark ourselves as running in background mode. 332 // Mark ourselves as running in background mode.
206 in_background_mode_ = true; 333 in_background_mode_ = true;
207 334
208 // Put ourselves in KeepAlive mode and create a status tray icon. 335 // Put ourselves in KeepAlive mode and create a status tray icon.
209 BrowserList::StartKeepAlive(); 336 BrowserList::StartKeepAlive();
210 337
211 // Display a status icon to exit Chrome. 338 // Display a status icon to exit Chrome.
212 CreateStatusTrayIcon(); 339 InitStatusTrayIcons();
340 }
341
342 void BackgroundModeManager::InitStatusTrayIcons() {
343 // Only initialize status tray icons for those profiles which actually
344 // have a background app running.
345 for (std::map<Profile*, BackgroundModeInfo>::iterator it =
346 background_mode_data_.begin();
347 it != background_mode_data_.end();
348 ++it) {
349 if (it->second->HasBackgroundApp())
350 CreateStatusTrayIcon(it->first);
351 }
213 } 352 }
214 353
215 void BackgroundModeManager::OnBackgroundAppUnloaded() { 354 void BackgroundModeManager::OnBackgroundAppUnloaded() {
216 // When a background app unloads, decrement our count and also end 355 // When a background app unloads, decrement our count and also end
217 // KeepAlive mode if appropriate. 356 // KeepAlive mode if appropriate.
218 background_app_count_--; 357 background_app_count_--;
219 DCHECK_GE(background_app_count_, 0); 358 DCHECK_GE(background_app_count_, 0);
220 if (background_app_count_ == 0) 359 if (background_app_count_ == 0)
221 EndBackgroundMode(); 360 EndBackgroundMode();
222 } 361 }
223 362
224 void BackgroundModeManager::EndBackgroundMode() { 363 void BackgroundModeManager::EndBackgroundMode() {
225 if (!in_background_mode_) 364 if (!in_background_mode_)
226 return; 365 return;
227 in_background_mode_ = false; 366 in_background_mode_ = false;
228 367
229 // End KeepAlive mode and blow away our status tray icon. 368 // End KeepAlive mode and blow away our status tray icon.
230 BrowserList::EndKeepAlive(); 369 BrowserList::EndKeepAlive();
231 RemoveStatusTrayIcon(); 370 // There is a status tray icon for each profile. Blow them all away.
371 for (std::map<Profile*, BackgroundModeInfo>::iterator it =
372 background_mode_data_.begin();
373 it != background_mode_data_.end();
374 ++it) {
375 RemoveStatusTrayIcon(it->first);
376 }
232 } 377 }
233 378
234 void BackgroundModeManager::EnableBackgroundMode() { 379 void BackgroundModeManager::EnableBackgroundMode() {
235 DCHECK(IsBackgroundModePrefEnabled()); 380 DCHECK(IsBackgroundModePrefEnabled());
236 // If background mode should be enabled, but isn't, turn it on. 381 // If background mode should be enabled, but isn't, turn it on.
237 if (background_app_count_ > 0 && !in_background_mode_) { 382 if (background_app_count_ > 0 && !in_background_mode_) {
238 StartBackgroundMode(); 383 StartBackgroundMode();
239 EnableLaunchOnStartup(true); 384 EnableLaunchOnStartup(true);
240 } 385 }
241 } 386 }
242 387
243 void BackgroundModeManager::DisableBackgroundMode() { 388 void BackgroundModeManager::DisableBackgroundMode() {
244 DCHECK(!IsBackgroundModePrefEnabled()); 389 DCHECK(!IsBackgroundModePrefEnabled());
245 // If background mode is currently enabled, turn it off. 390 // If background mode is currently enabled, turn it off.
246 if (in_background_mode_) { 391 if (in_background_mode_) {
247 EndBackgroundMode(); 392 EndBackgroundMode();
248 EnableLaunchOnStartup(false); 393 EnableLaunchOnStartup(false);
249 } 394 }
250 } 395 }
251 396
252 void BackgroundModeManager::OnBackgroundAppInstalled( 397 void BackgroundModeManager::OnBackgroundAppInstalled(
253 const Extension* extension) { 398 const Extension* extension, Profile* profile) {
254 // Background mode is disabled - don't do anything. 399 // Background mode is disabled - don't do anything.
255 if (!IsBackgroundModePrefEnabled()) 400 if (!IsBackgroundModePrefEnabled())
256 return; 401 return;
257 402
258 // We're installing a background app. If this is the first background app 403 // We're installing a background app. If this is the first background app
259 // being installed, make sure we are set to launch on startup. 404 // being installed, make sure we are set to launch on startup.
260 if (background_app_count_ == 0) 405 if (background_app_count_ == 0)
261 EnableLaunchOnStartup(true); 406 EnableLaunchOnStartup(true);
262 407
408 // Check if we need a status tray icon and make one if we do.
409 CreateStatusTrayIcon(profile);
410
263 // Notify the user that a background app has been installed. 411 // Notify the user that a background app has been installed.
264 if (extension) // NULL when called by unit tests. 412 if (extension) // NULL when called by unit tests.
265 DisplayAppInstalledNotification(extension); 413 DisplayAppInstalledNotification(extension, profile);
266 } 414 }
267 415
268 void BackgroundModeManager::OnBackgroundAppUninstalled() { 416 void BackgroundModeManager::OnBackgroundAppUninstalled(Profile* profile) {
417 // Check if we need to remove the status tray icon if there are no
418 // more background apps.
419 BackgroundModeInfo bmd = GetBackgroundModeInfo(profile);
420 DCHECK(bmd.get());
421 // If there are still background apps for this profile, don't remove
422 // the status tray icon.
423 if (!bmd->HasBackgroundApp())
424 RemoveStatusTrayIcon(profile);
425
269 // When uninstalling a background app, disable launch on startup if 426 // When uninstalling a background app, disable launch on startup if
270 // we have no more background apps. 427 // we have no more background apps.
271 if (background_app_count_ == 0) 428 if (background_app_count_ == 0)
272 EnableLaunchOnStartup(false); 429 EnableLaunchOnStartup(false);
273 } 430 }
274 431
275 void BackgroundModeManager::CreateStatusTrayIcon() { 432 void BackgroundModeManager::CreateStatusTrayIcon(Profile* profile) {
276 // Only need status icons on windows/linux. ChromeOS doesn't allow exiting 433 // Only need status icons on windows/linux. ChromeOS doesn't allow exiting
277 // Chrome and Mac can use the dock icon instead. 434 // Chrome and Mac can use the dock icon instead.
435
436 // Since there are multiple profiles which share the status tray, we now
437 // use the browser process to keep track of it.
278 #if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) 438 #if !defined(OS_MACOSX) && !defined(OS_CHROMEOS)
279 if (!status_tray_) 439 if (!status_tray_)
280 status_tray_ = profile_->GetStatusTray(); 440 status_tray_ = g_browser_process->status_tray();
281 #endif 441 #endif
282 442
283 // If the platform doesn't support status icons, or we've already created 443 // If the platform doesn't support status icons, or we've already created
284 // our status icon, just return. 444 // our status icon, just return.
285 if (!status_tray_ || status_icon_) 445 BackgroundModeInfo bmd = GetBackgroundModeInfo(profile);
286 return; 446 if (!status_tray_ || bmd->status_icon_)
287 status_icon_ = status_tray_->CreateStatusIcon();
288 if (!status_icon_)
289 return; 447 return;
290 448
291 // Set the image and add ourselves as a click observer on it 449 bmd->status_icon_ = status_tray_->CreateStatusIcon();
450 if (!bmd->status_icon_)
451 return;
452
453 // Set the image and add ourselves as a click observer on it.
454 // TODO(rlp): Status tray icon should have submenus for each profile.
292 SkBitmap* bitmap = ResourceBundle::GetSharedInstance().GetBitmapNamed( 455 SkBitmap* bitmap = ResourceBundle::GetSharedInstance().GetBitmapNamed(
293 IDR_STATUS_TRAY_ICON); 456 IDR_STATUS_TRAY_ICON);
294 status_icon_->SetImage(*bitmap); 457 bmd->status_icon_->SetImage(*bitmap);
295 status_icon_->SetToolTip(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); 458 bmd->status_icon_->SetToolTip(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
296 UpdateStatusTrayIconContextMenu(); 459 UpdateStatusTrayIconContextMenu(profile);
297 } 460 }
298 461
299 void BackgroundModeManager::UpdateContextMenuEntryIcon( 462 void BackgroundModeManager::UpdateContextMenuEntryIcon(
300 const Extension* extension) { 463 const Extension* extension, Profile* profile) {
301 if (!context_menu_) 464 BackgroundModeInfo bmd = GetBackgroundModeInfo(profile);
302 return; 465 DCHECK(bmd.get());
303 context_menu_->SetIcon( 466 bmd->UpdateContextMenuEntryIcon(extension);
304 context_menu_application_offset_ + applications_.GetPosition(extension),
305 *(applications_.GetIcon(extension)));
306 status_icon_->SetContextMenu(context_menu_); // for Update effect
307 } 467 }
308 468
309 void BackgroundModeManager::UpdateStatusTrayIconContextMenu() { 469 void BackgroundModeManager::UpdateStatusTrayIconContextMenu(Profile* profile) {
310 if (!status_icon_) 470 BackgroundModeInfo bmd = GetBackgroundModeInfo(profile);
311 return; 471 DCHECK(bmd.get());
472 if (!bmd->status_icon_) {
473 // If no status icon exists, it's either because one wasn't created when
474 // it should have been which can happen when extensions load after the
475 // profile has already been registered with the background mode manager.
476 // The other case is if we aren't in background mode.
477 if (in_background_mode_)
478 CreateStatusTrayIcon(profile);
479 else
480 return;
481 }
312 482
483 // TODO(rlp): Add current profile color.
313 // Create a context menu item for Chrome. 484 // Create a context menu item for Chrome.
314 ui::SimpleMenuModel* menu = new ui::SimpleMenuModel(this); 485 ui::SimpleMenuModel* menu = new ui::SimpleMenuModel(bmd.get());
315 // Add About item 486 // Add About item
316 menu->AddItem(IDC_ABOUT, l10n_util::GetStringFUTF16(IDS_ABOUT, 487 menu->AddItem(IDC_ABOUT, l10n_util::GetStringFUTF16(IDS_ABOUT,
317 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))); 488 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
318 menu->AddItem(IDC_OPTIONS, GetPreferencesMenuLabel()); 489 menu->AddItem(IDC_OPTIONS, GetPreferencesMenuLabel());
319 menu->AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER); 490 menu->AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER);
320 menu->AddSeparator(); 491 menu->AddSeparator();
321 int position = 0; 492 int position = 0;
322 context_menu_application_offset_ = menu->GetItemCount(); 493 bmd->context_menu_application_offset_ = menu->GetItemCount();
323 for (ExtensionList::const_iterator cursor = applications_.begin(); 494 for (ExtensionList::const_iterator cursor = bmd->applications_->begin();
324 cursor != applications_.end(); 495 cursor != bmd->applications_->end();
325 ++cursor, ++position) { 496 ++cursor, ++position) {
326 const SkBitmap* icon = applications_.GetIcon(*cursor); 497 const SkBitmap* icon = bmd->applications_->GetIcon(*cursor);
327 DCHECK(position == applications_.GetPosition(*cursor)); 498 DCHECK(position == bmd->applications_->GetPosition(*cursor));
328 const std::string& name = (*cursor)->name(); 499 const std::string& name = (*cursor)->name();
329 menu->AddItem(position, UTF8ToUTF16(name)); 500 menu->AddItem(position, UTF8ToUTF16(name));
330 if (icon) 501 if (icon)
331 menu->SetIcon(menu->GetItemCount() - 1, *icon); 502 menu->SetIcon(menu->GetItemCount() - 1, *icon);
332 } 503 }
333 if (applications_.size() > 0) 504 if (bmd->applications_->size() > 0)
334 menu->AddSeparator(); 505 menu->AddSeparator();
335 menu->AddCheckItemWithStringId( 506 menu->AddCheckItemWithStringId(
336 IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND, 507 IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND,
337 IDS_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND); 508 IDS_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND);
338 menu->AddItemWithStringId(IDC_EXIT, IDS_EXIT); 509 menu->AddItemWithStringId(IDC_EXIT, IDS_EXIT);
339 context_menu_ = menu; 510 bmd->context_menu_ = menu;
340 status_icon_->SetContextMenu(menu); 511 bmd->status_icon_->SetContextMenu(menu);
341 } 512 }
342 513
343 bool BackgroundModeManager::IsCommandIdChecked(int command_id) const { 514 void BackgroundModeManager::RemoveStatusTrayIcon(Profile* profile) {
344 DCHECK(command_id == IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND); 515 BackgroundModeInfo bmd = GetBackgroundModeInfo(profile);
345 return true; 516 DCHECK(bmd.get());
517
518 if (bmd->status_icon_)
519 status_tray_->RemoveStatusIcon(bmd->status_icon_);
520 bmd->status_icon_ = NULL;
521 bmd->context_menu_ = NULL; // Do not delete, points within |status_icon_|.
346 } 522 }
347 523
348 bool BackgroundModeManager::IsCommandIdEnabled(int command_id) const { 524 BackgroundModeManager::BackgroundModeInfo
349 // For now, we do not support disabled items. 525 BackgroundModeManager::GetBackgroundModeInfo(Profile* profile) {
350 return true; 526 DCHECK(background_mode_data_.find(profile) != background_mode_data_.end());
351 } 527 return background_mode_data_[profile];
352
353 bool BackgroundModeManager::GetAcceleratorForCommandId(
354 int command_id,
355 ui::Accelerator* accelerator) {
356 // No accelerators for status icon context menus.
357 return false;
358 }
359
360 void BackgroundModeManager::RemoveStatusTrayIcon() {
361 if (status_icon_)
362 status_tray_->RemoveStatusIcon(status_icon_);
363 status_icon_ = NULL;
364 context_menu_ = NULL; // Do not delete, points within |status_icon_|.
365 }
366
367 void BackgroundModeManager::ExecuteApplication(int item) {
368 DCHECK(item >= 0 && item < static_cast<int>(applications_.size()));
369 Browser* browser = BrowserList::GetLastActive();
370 if (!browser) {
371 Browser::OpenEmptyWindow(profile_);
372 browser = BrowserList::GetLastActive();
373 }
374 const Extension* extension = applications_.GetExtension(item);
375 browser->OpenApplicationTab(profile_, extension, NEW_FOREGROUND_TAB);
376 }
377
378 void BackgroundModeManager::ExecuteCommand(int item) {
379 switch (item) {
380 case IDC_ABOUT:
381 GetBrowserWindow()->OpenAboutChromeDialog();
382 break;
383 case IDC_EXIT:
384 UserMetrics::RecordAction(UserMetricsAction("Exit"));
385 BrowserList::CloseAllBrowsersAndExit();
386 break;
387 case IDC_OPTIONS:
388 GetBrowserWindow()->OpenOptionsDialog();
389 break;
390 case IDC_TASK_MANAGER:
391 GetBrowserWindow()->OpenTaskManager(true);
392 break;
393 case IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND: {
394 // Background mode must already be enabled (as otherwise this menu would
395 // not be visible).
396 DCHECK(IsBackgroundModePrefEnabled());
397 DCHECK(BrowserList::WillKeepAlive());
398
399 // Set the background mode pref to "disabled" - the resulting notification
400 // will result in a call to DisableBackgroundMode().
401 PrefService* service = g_browser_process->local_state();
402 DCHECK(service);
403 service->SetBoolean(prefs::kBackgroundModeEnabled, false);
404 break;
405 }
406 default:
407 ExecuteApplication(item);
408 break;
409 }
410 }
411
412 Browser* BackgroundModeManager::GetBrowserWindow() {
413 Browser* browser = BrowserList::GetLastActive();
414 if (!browser) {
415 Browser::OpenEmptyWindow(profile_);
416 browser = BrowserList::GetLastActive();
417 }
418 return browser;
419 } 528 }
420 529
421 // static 530 // static
422 bool BackgroundModeManager::IsBackgroundModePermanentlyDisabled( 531 bool BackgroundModeManager::IsBackgroundModePermanentlyDisabled(
423 const CommandLine* command_line) { 532 const CommandLine* command_line) {
424 533
425 // Background mode is disabled if the appropriate flag is passed, or if 534 // Background mode is disabled if the appropriate flag is passed, or if
426 // extensions are disabled, or if the associated preference is unset. It's 535 // extensions are disabled, or if the associated preference is unset. It's
427 // always disabled on chromeos since chrome is always running on that 536 // always disabled on chromeos since chrome is always running on that
428 // platform, making it superfluous. 537 // platform, making it superfluous.
429 #if defined(OS_CHROMEOS) 538 #if defined(OS_CHROMEOS)
430 return true; 539 return true;
431 #else 540 #else
432 bool background_mode_disabled = 541 bool background_mode_disabled =
433 command_line->HasSwitch(switches::kDisableBackgroundMode) || 542 command_line->HasSwitch(switches::kDisableBackgroundMode) ||
434 command_line->HasSwitch(switches::kDisableExtensions); 543 command_line->HasSwitch(switches::kDisableExtensions);
435 return background_mode_disabled; 544 return background_mode_disabled;
436 #endif 545 #endif
437 } 546 }
438 547
439 bool BackgroundModeManager::IsBackgroundModePrefEnabled() { 548 bool BackgroundModeManager::IsBackgroundModePrefEnabled() {
440 PrefService* service = g_browser_process->local_state(); 549 PrefService* service = g_browser_process->local_state();
441 DCHECK(service); 550 DCHECK(service);
442 return service->GetBoolean(prefs::kBackgroundModeEnabled); 551 return service->GetBoolean(prefs::kBackgroundModeEnabled);
443 } 552 }
444
445 // static
446 void BackgroundModeManager::RegisterPrefs(PrefService* prefs) {
447 prefs->RegisterBooleanPref(prefs::kUserCreatedLoginItem, false);
448 prefs->RegisterBooleanPref(prefs::kBackgroundModeEnabled, true);
449 }
OLDNEW
« 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