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

Side by Side Diff: chrome/browser/background_mode_manager.cc

Issue 6954001: Add "Keep chrome running in background" preference. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review feedback + added tests. 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"
11 #include "chrome/app/chrome_command_ids.h" 11 #include "chrome/app/chrome_command_ids.h"
12 #include "chrome/browser/background_application_list_model.h" 12 #include "chrome/browser/background_application_list_model.h"
13 #include "chrome/browser/background_mode_manager.h" 13 #include "chrome/browser/background_mode_manager.h"
14 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/extensions/extension_service.h" 15 #include "chrome/browser/extensions/extension_service.h"
16 #include "chrome/browser/platform_util.h"
15 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/status_icons/status_icon.h" 18 #include "chrome/browser/status_icons/status_icon.h"
17 #include "chrome/browser/status_icons/status_tray.h" 19 #include "chrome/browser/status_icons/status_tray.h"
18 #include "chrome/browser/ui/browser_list.h" 20 #include "chrome/browser/ui/browser_list.h"
19 #include "chrome/common/chrome_switches.h" 21 #include "chrome/common/chrome_switches.h"
20 #include "chrome/common/extensions/extension.h" 22 #include "chrome/common/extensions/extension.h"
21 #include "chrome/common/pref_names.h" 23 #include "chrome/common/pref_names.h"
22 #include "content/browser/user_metrics.h" 24 #include "content/browser/user_metrics.h"
23 #include "content/common/notification_service.h" 25 #include "content/common/notification_service.h"
24 #include "content/common/notification_type.h" 26 #include "content/common/notification_type.h"
(...skipping 16 matching lines...) Expand all
41 CommandLine* command_line) 43 CommandLine* command_line)
42 : profile_(profile), 44 : profile_(profile),
43 applications_(profile), 45 applications_(profile),
44 background_app_count_(0), 46 background_app_count_(0),
45 context_menu_(NULL), 47 context_menu_(NULL),
46 context_menu_application_offset_(0), 48 context_menu_application_offset_(0),
47 in_background_mode_(false), 49 in_background_mode_(false),
48 keep_alive_for_startup_(false), 50 keep_alive_for_startup_(false),
49 status_tray_(NULL), 51 status_tray_(NULL),
50 status_icon_(NULL) { 52 status_icon_(NULL) {
51 // If background mode is disabled, just exit - don't listen for any 53 // If background mode is currently disabled, just exit - don't listen for any
52 // notifications. 54 // notifications.
53 if (!IsBackgroundModeEnabled(command_line)) 55 if (IsBackgroundModePermanentlyDisabled(command_line))
54 return; 56 return;
55 57
58 // Listen for the background mode preference changing.
59 if (g_browser_process->local_state()) { // Skip for unit tests
60 pref_registrar_.Init(g_browser_process->local_state());
61 pref_registrar_.Add(prefs::kBackgroundModeEnabled, this);
62 }
63
56 // Keep the browser alive until extensions are done loading - this is needed 64 // Keep the browser alive until extensions are done loading - this is needed
57 // by the --no-startup-window flag. We want to stay alive until we load 65 // by the --no-startup-window flag. We want to stay alive until we load
58 // extensions, at which point we should either run in background mode (if 66 // extensions, at which point we should either run in background mode (if
59 // there are background apps) or exit if there are none. 67 // there are background apps) or exit if there are none.
60 if (command_line->HasSwitch(switches::kNoStartupWindow)) { 68 if (command_line->HasSwitch(switches::kNoStartupWindow)) {
61 keep_alive_for_startup_ = true; 69 keep_alive_for_startup_ = true;
62 BrowserList::StartKeepAlive(); 70 BrowserList::StartKeepAlive();
63 } 71 }
64 72
65 // If the -keep-alive-for-test flag is passed, then always keep chrome running 73 // If the -keep-alive-for-test flag is passed, then always keep chrome running
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 // background mode currently). This is primarily needed for unit tests, 105 // background mode currently). This is primarily needed for unit tests,
98 // because in an actual running system we'd get an APP_TERMINATING 106 // because in an actual running system we'd get an APP_TERMINATING
99 // notification before being destroyed. 107 // notification before being destroyed.
100 EndBackgroundMode(); 108 EndBackgroundMode();
101 } 109 }
102 110
103 void BackgroundModeManager::Observe(NotificationType type, 111 void BackgroundModeManager::Observe(NotificationType type,
104 const NotificationSource& source, 112 const NotificationSource& source,
105 const NotificationDetails& details) { 113 const NotificationDetails& details) {
106 switch (type.value) { 114 switch (type.value) {
115 case NotificationType::PREF_CHANGED:
116 DCHECK(*Details<std::string>(details).ptr() ==
117 prefs::kBackgroundModeEnabled);
118 if (IsBackgroundModePrefEnabled())
119 EnableBackgroundMode();
120 else
121 DisableBackgroundMode();
122 break;
107 case NotificationType::EXTENSIONS_READY: 123 case NotificationType::EXTENSIONS_READY:
108 // Extensions are loaded, so we don't need to manually keep the browser 124 // Extensions are loaded, so we don't need to manually keep the browser
109 // process alive any more when running in no-startup-window mode. 125 // process alive any more when running in no-startup-window mode.
110 EndKeepAliveForStartup(); 126 EndKeepAliveForStartup();
111 127
112 // On a Mac, we use 'login items' mechanism which has user-facing UI so we 128 // On a Mac, we use 'login items' mechanism which has user-facing UI so we
113 // don't want to stomp on user choice every time we start and load 129 // don't want to stomp on user choice every time we start and load
114 // registered extensions. This means that if a background app is removed 130 // registered extensions. This means that if a background app is removed
115 // or added while Chrome is not running, we could leave Chrome in the 131 // or added while Chrome is not running, we could leave Chrome in the
116 // wrong state, but this is better than constantly forcing Chrome to 132 // wrong state, but this is better than constantly forcing Chrome to
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 191
176 void BackgroundModeManager::OnBackgroundAppLoaded() { 192 void BackgroundModeManager::OnBackgroundAppLoaded() {
177 // When a background app loads, increment our count and also enable 193 // When a background app loads, increment our count and also enable
178 // KeepAlive mode if the preference is set. 194 // KeepAlive mode if the preference is set.
179 background_app_count_++; 195 background_app_count_++;
180 if (background_app_count_ == 1) 196 if (background_app_count_ == 1)
181 StartBackgroundMode(); 197 StartBackgroundMode();
182 } 198 }
183 199
184 void BackgroundModeManager::StartBackgroundMode() { 200 void BackgroundModeManager::StartBackgroundMode() {
185 // Don't bother putting ourselves in background mode if we're already there. 201 // Don't bother putting ourselves in background mode if we're already there
186 if (in_background_mode_) 202 // or if background mode is disabled.
203 if (in_background_mode_ || !IsBackgroundModePrefEnabled())
187 return; 204 return;
188 205
189 // Mark ourselves as running in background mode. 206 // Mark ourselves as running in background mode.
190 in_background_mode_ = true; 207 in_background_mode_ = true;
191 208
192 // Put ourselves in KeepAlive mode and create a status tray icon. 209 // Put ourselves in KeepAlive mode and create a status tray icon.
193 BrowserList::StartKeepAlive(); 210 BrowserList::StartKeepAlive();
194 211
195 // Display a status icon to exit Chrome. 212 // Display a status icon to exit Chrome.
196 CreateStatusTrayIcon(); 213 CreateStatusTrayIcon();
(...skipping 11 matching lines...) Expand all
208 void BackgroundModeManager::EndBackgroundMode() { 225 void BackgroundModeManager::EndBackgroundMode() {
209 if (!in_background_mode_) 226 if (!in_background_mode_)
210 return; 227 return;
211 in_background_mode_ = false; 228 in_background_mode_ = false;
212 229
213 // End KeepAlive mode and blow away our status tray icon. 230 // End KeepAlive mode and blow away our status tray icon.
214 BrowserList::EndKeepAlive(); 231 BrowserList::EndKeepAlive();
215 RemoveStatusTrayIcon(); 232 RemoveStatusTrayIcon();
216 } 233 }
217 234
235 void BackgroundModeManager::EnableBackgroundMode() {
236 // If background mode should be enabled, but isn't, turn it on.
Rick Campbell 2011/05/12 05:42:42 Consider adding DCHECK(IsBackgroundModePrefEnabled
Andrew T Wilson (Slow) 2011/05/12 23:34:31 Done.
237 if (background_app_count_ > 0 && !in_background_mode_) {
238 StartBackgroundMode();
239 EnableLaunchOnStartup(true);
240 }
241 }
242
243 void BackgroundModeManager::DisableBackgroundMode() {
244 // If background mode is currently enabled, turn it off.
245 if (in_background_mode_) {
246 EndBackgroundMode();
247 EnableLaunchOnStartup(false);
248 }
249 }
250
218 void BackgroundModeManager::OnBackgroundAppInstalled( 251 void BackgroundModeManager::OnBackgroundAppInstalled(
219 const Extension* extension) { 252 const Extension* extension) {
253 // Background mode is disabled - don't do anything.
254 if (!IsBackgroundModePrefEnabled())
255 return;
256
220 // We're installing a background app. If this is the first background app 257 // We're installing a background app. If this is the first background app
221 // being installed, make sure we are set to launch on startup. 258 // being installed, make sure we are set to launch on startup.
222 if (background_app_count_ == 0) 259 if (background_app_count_ == 0)
223 EnableLaunchOnStartup(true); 260 EnableLaunchOnStartup(true);
224 261
225 // Notify the user that a background app has been installed. 262 // Notify the user that a background app has been installed.
226 if (extension) // NULL when called by unit tests. 263 if (extension) // NULL when called by unit tests.
227 DisplayAppInstalledNotification(extension); 264 DisplayAppInstalledNotification(extension);
228 } 265 }
229 266
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 ++cursor, ++position) { 324 ++cursor, ++position) {
288 const SkBitmap* icon = applications_.GetIcon(*cursor); 325 const SkBitmap* icon = applications_.GetIcon(*cursor);
289 DCHECK(position == applications_.GetPosition(*cursor)); 326 DCHECK(position == applications_.GetPosition(*cursor));
290 const std::string& name = (*cursor)->name(); 327 const std::string& name = (*cursor)->name();
291 menu->AddItem(position, UTF8ToUTF16(name)); 328 menu->AddItem(position, UTF8ToUTF16(name));
292 if (icon) 329 if (icon)
293 menu->SetIcon(menu->GetItemCount() - 1, *icon); 330 menu->SetIcon(menu->GetItemCount() - 1, *icon);
294 } 331 }
295 if (applications_.size() > 0) 332 if (applications_.size() > 0)
296 menu->AddSeparator(); 333 menu->AddSeparator();
334 menu->AddCheckItemWithStringId(
335 IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND,
336 IDS_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND);
297 menu->AddItemWithStringId(IDC_EXIT, IDS_EXIT); 337 menu->AddItemWithStringId(IDC_EXIT, IDS_EXIT);
298 context_menu_ = menu; 338 context_menu_ = menu;
299 status_icon_->SetContextMenu(menu); 339 status_icon_->SetContextMenu(menu);
300 } 340 }
301 341
302 bool BackgroundModeManager::IsCommandIdChecked(int command_id) const { 342 bool BackgroundModeManager::IsCommandIdChecked(int command_id) const {
303 return false; 343 DCHECK(command_id == IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND);
344 return true;
304 } 345 }
305 346
306 bool BackgroundModeManager::IsCommandIdEnabled(int command_id) const { 347 bool BackgroundModeManager::IsCommandIdEnabled(int command_id) const {
307 // For now, we do not support disabled items. 348 // For now, we do not support disabled items.
308 return true; 349 return true;
309 } 350 }
310 351
311 bool BackgroundModeManager::GetAcceleratorForCommandId( 352 bool BackgroundModeManager::GetAcceleratorForCommandId(
312 int command_id, 353 int command_id,
313 ui::Accelerator* accelerator) { 354 ui::Accelerator* accelerator) {
(...skipping 27 matching lines...) Expand all
341 case IDC_EXIT: 382 case IDC_EXIT:
342 UserMetrics::RecordAction(UserMetricsAction("Exit")); 383 UserMetrics::RecordAction(UserMetricsAction("Exit"));
343 BrowserList::CloseAllBrowsersAndExit(); 384 BrowserList::CloseAllBrowsersAndExit();
344 break; 385 break;
345 case IDC_OPTIONS: 386 case IDC_OPTIONS:
346 GetBrowserWindow()->OpenOptionsDialog(); 387 GetBrowserWindow()->OpenOptionsDialog();
347 break; 388 break;
348 case IDC_TASK_MANAGER: 389 case IDC_TASK_MANAGER:
349 GetBrowserWindow()->OpenTaskManager(true); 390 GetBrowserWindow()->OpenTaskManager(true);
350 break; 391 break;
392 case IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND: {
393 // Background mode must already be enabled (as otherwise this menu would
394 // not be visible).
395 DCHECK(IsBackgroundModePrefEnabled());
396 DCHECK(BrowserList::WillKeepAlive());
397 if (BrowserList::size() == 0) {
398 // There are no windows open - unchecking this will exit Chrome. Warn
399 // the user.
400 if (!platform_util::SimpleYesNoBox(
401 NULL,
402 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
403 l10n_util::GetStringFUTF16(
404 IDS_CONFIRM_EXIT_BACKGROUND_MODE_BODY,
405 GetPreferencesMenuLabel()))) {
406 return;
407 }
408 }
409
410 // Set the background mode pref to "disabled" - the resulting notification
411 // will result in a call to DisableBackgroundMode().
412 PrefService* service = g_browser_process->local_state();
413 DCHECK(service);
414 service->SetBoolean(prefs::kBackgroundModeEnabled, false);
415 break;
416 }
351 default: 417 default:
352 ExecuteApplication(item); 418 ExecuteApplication(item);
353 break; 419 break;
354 } 420 }
355 } 421 }
356 422
357 Browser* BackgroundModeManager::GetBrowserWindow() { 423 Browser* BackgroundModeManager::GetBrowserWindow() {
358 Browser* browser = BrowserList::GetLastActive(); 424 Browser* browser = BrowserList::GetLastActive();
359 if (!browser) { 425 if (!browser) {
360 Browser::OpenEmptyWindow(profile_); 426 Browser::OpenEmptyWindow(profile_);
361 browser = BrowserList::GetLastActive(); 427 browser = BrowserList::GetLastActive();
362 } 428 }
363 return browser; 429 return browser;
364 } 430 }
365 431
366 // static 432 // static
367 bool BackgroundModeManager::IsBackgroundModeEnabled( 433 bool BackgroundModeManager::IsBackgroundModePermanentlyDisabled(
368 const CommandLine* command_line) { 434 const CommandLine* command_line) {
369 435
370 // Background mode is disabled if the appropriate flag is passed, or if 436 // Background mode is disabled if the appropriate flag is passed, or if
371 // extensions are disabled. It's always disabled on chromeos since chrome 437 // extensions are disabled, or if the associated preference is unset. It's
372 // is always running on that platform, making it superfluous. 438 // always disabled on chromeos since chrome is always running on that
439 // platform, making it superfluous.
373 #if defined(OS_CHROMEOS) 440 #if defined(OS_CHROMEOS)
374 return false; 441 return true;
375 #else 442 #else
376 bool background_mode_enabled = 443 bool background_mode_disabled =
377 !command_line->HasSwitch(switches::kDisableBackgroundMode) && 444 command_line->HasSwitch(switches::kDisableBackgroundMode) ||
378 !command_line->HasSwitch(switches::kDisableExtensions); 445 command_line->HasSwitch(switches::kDisableExtensions);
379 return background_mode_enabled; 446 return background_mode_disabled;
380 #endif 447 #endif
381 } 448 }
382 449
450 bool BackgroundModeManager::IsBackgroundModePrefEnabled() {
451 PrefService* service = g_browser_process->local_state();
452 DCHECK(service);
453 return service->GetBoolean(prefs::kBackgroundModeEnabled);
454 }
455
383 // static 456 // static
384 void BackgroundModeManager::RegisterPrefs(PrefService* prefs) { 457 void BackgroundModeManager::RegisterPrefs(PrefService* prefs) {
385 prefs->RegisterBooleanPref(prefs::kUserCreatedLoginItem, false); 458 prefs->RegisterBooleanPref(prefs::kUserCreatedLoginItem, false);
459 prefs->RegisterBooleanPref(prefs::kBackgroundModeEnabled, true);
386 } 460 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698