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

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

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