background_mode_manager.cc revision 4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7
13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 23345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Use of this source code is governed by a BSD-style license that can be 33345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// found in the LICENSE file. 43345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 53345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "app/l10n_util.h" 63345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "app/resource_bundle.h" 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/base_paths.h" 83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/command_line.h" 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/file_path.h" 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/logging.h" 113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/path_service.h" 12513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/utf_string_conversions.h" 13513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/app/chrome_command_ids.h" 14513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/background_application_list_model.h" 153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/background_mode_manager.h" 163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/browser_list.h" 17513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/extensions/extensions_service.h" 183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/metrics/user_metrics.h" 193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h" 203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/profile.h" 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/shell_integration.h" 223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/status_icons/status_icon.h" 233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/status_icons/status_tray.h" 243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/chrome_switches.h" 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/extensions/extension.h" 263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/notification_service.h" 273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/notification_type.h" 283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/pref_names.h" 293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "grit/browser_resources.h" 303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "grit/chromium_strings.h" 313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "grit/generated_resources.h" 323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "grit/theme_resources.h" 333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(OS_LINUX) 353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <unistd.h> 363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/environment.h" 373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/file_util.h" 38513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/nix/xdg_util.h" 393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/task.h" 403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h" 413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/chrome_version_info.h" 423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif 433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(OS_MACOSX) 453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/mac_util.h" 463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif 473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(TOOLKIT_GTK) 493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/gtk/gtk_util.h" 503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif 513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(OS_LINUX) 533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic const FilePath::CharType kAutostart[] = "autostart"; 543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic const FilePath::CharType kConfig[] = ".config"; 553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic const char kXdgConfigHome[] = "XDG_CONFIG_HOME"; 563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif 573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(OS_WIN) 59731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/win/registry.h" 603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst HKEY kBackgroundModeRegistryRootKey = HKEY_CURRENT_USER; 613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst wchar_t* kBackgroundModeRegistrySubkey = 623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick L"Software\\Microsoft\\Windows\\CurrentVersion\\Run"; 633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst wchar_t* kBackgroundModeRegistryKeyName = L"chromium"; 643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif 653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(OS_LINUX) 673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace { 683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickFilePath GetAutostartDirectory(base::Environment* environment) { 70731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FilePath result = 72731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::nix::GetXDGDirectory(environment, kXdgConfigHome, kConfig); 733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick result = result.Append(kAutostart); 743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return result; 753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 773345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickFilePath GetAutostartFilename(base::Environment* environment) { 783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FilePath directory = GetAutostartDirectory(environment); 793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return directory.Append(ShellIntegration::GetDesktopName(environment)); 803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} // namespace 833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass DisableLaunchOnStartupTask : public Task { 853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public: 863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void Run() { 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_ptr<base::Environment> environment(base::Environment::Create()); 883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!file_util::Delete(GetAutostartFilename(environment.get()), false)) { 893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG(WARNING) << "Failed to deregister launch on login."; 903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}; 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// TODO(rickcam): Bug 56280: Share implementation with ShellIntegration 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass EnableLaunchOnStartupTask : public Task { 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public: 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void Run() { 983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_ptr<base::Environment> environment(base::Environment::Create()); 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_ptr<chrome::VersionInfo> version_info(new chrome::VersionInfo()); 1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FilePath autostart_directory = GetAutostartDirectory(environment.get()); 1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FilePath autostart_file = GetAutostartFilename(environment.get()); 1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!file_util::DirectoryExists(autostart_directory) && 1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick !file_util::CreateDirectory(autostart_directory)) { 104731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LOG(WARNING) 105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << "Failed to register launch on login. No autostart directory."; 1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string wrapper_script; 1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!environment->GetVar("CHROME_WRAPPER", &wrapper_script)) { 110731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LOG(WARNING) 111731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << "Failed to register launch on login. CHROME_WRAPPER not set."; 1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string autostart_file_contents = 1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "[Desktop Entry]\n" 1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "Type=Application\n" 1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "Terminal=false\n" 118731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick "Exec=" + wrapper_script + 119731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick " --enable-background-mode --no-startup-window\n" 1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "Name=" + version_info->Name() + "\n"; 121731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string::size_type content_length = autostart_file_contents.length(); 1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (file_util::WriteFile(autostart_file, autostart_file_contents.c_str(), 123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick content_length) != 124731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick static_cast<int>(content_length)) { 125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LOG(WARNING) << "Failed to register launch on login. Failed to write " 126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << autostart_file.value(); 127731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick file_util::Delete(GetAutostartFilename(environment.get()), false); 128731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}; 1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif // defined(OS_LINUX) 1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 133513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BackgroundModeManager::OnApplicationDataChanged( 134513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension) { 135513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UpdateContextMenuEntryIcon(extension); 136513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 137513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 138513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BackgroundModeManager::OnApplicationListChanged() { 139513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UpdateStatusTrayIconContextMenu(); 140513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 141513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1423345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickBackgroundModeManager::BackgroundModeManager(Profile* profile, 1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CommandLine* command_line) 1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick : profile_(profile), 145513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch applications_(profile), 1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick background_app_count_(0), 147513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch context_menu_(NULL), 148513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch context_menu_application_offset_(0), 1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick in_background_mode_(false), 150731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick keep_alive_for_startup_(false), 1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick status_tray_(NULL), 1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick status_icon_(NULL) { 153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If background mode or apps are disabled, just exit - don't listen for 1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // any notifications. 155731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!command_line->HasSwitch(switches::kEnableBackgroundMode) || 156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick command_line->HasSwitch(switches::kDisableExtensions)) 1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Keep the browser alive until extensions are done loading - this is needed 160731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // by the --no-startup-window flag. We want to stay alive until we load 161731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // extensions, at which point we should either run in background mode (if 162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // there are background apps) or exit if there are none. 163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (command_line->HasSwitch(switches::kNoStartupWindow)) { 164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick keep_alive_for_startup_ = true; 165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserList::StartKeepAlive(); 166731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 167731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If the -keep-alive-for-test flag is passed, then always keep chrome running 1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // in the background until the user explicitly terminates it, by acting as if 1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // we loaded a background app. 1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKeepAliveForTest)) 1723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OnBackgroundAppLoaded(); 1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // When an extension is installed, make sure launch on startup is properly 1753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // set if appropriate. Likewise, turn off launch on startup when the last 1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // background app is uninstalled. 1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick registrar_.Add(this, NotificationType::EXTENSION_INSTALLED, 1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Source<Profile>(profile)); 1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick registrar_.Add(this, NotificationType::EXTENSION_UNINSTALLED, 1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Source<Profile>(profile)); 1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Listen for when extensions are loaded/unloaded so we can track the 1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // number of background apps. 1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick registrar_.Add(this, NotificationType::EXTENSION_LOADED, 1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Source<Profile>(profile)); 1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, 1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Source<Profile>(profile)); 1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Check for the presence of background apps after all extensions have been 1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // loaded, to handle the case where an extension has been manually removed 1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // while Chrome was not running. 1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick registrar_.Add(this, NotificationType::EXTENSIONS_READY, 1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Source<Profile>(profile)); 1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Listen for the application shutting down so we can decrement our KeepAlive 1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // count. 1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick registrar_.Add(this, NotificationType::APP_TERMINATING, 1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NotificationService::AllSources()); 1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Listen for changes to the background mode preference. 2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pref_registrar_.Init(profile_->GetPrefs()); 2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pref_registrar_.Add(prefs::kBackgroundModeEnabled, this); 202513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 203513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch applications_.AddObserver(this); 2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickBackgroundModeManager::~BackgroundModeManager() { 207513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch applications_.RemoveObserver(this); 208513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We're going away, so exit background mode (does nothing if we aren't in 2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // background mode currently). This is primarily needed for unit tests, 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // because in an actual running system we'd get an APP_TERMINATING 2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // notification before being destroyed. 2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EndBackgroundMode(); 2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool BackgroundModeManager::IsBackgroundModeEnabled() { 2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return profile_->GetPrefs()->GetBoolean(prefs::kBackgroundModeEnabled); 2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool BackgroundModeManager::IsLaunchOnStartupResetAllowed() { 2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return profile_->GetPrefs()->GetBoolean(prefs::kLaunchOnStartupResetAllowed); 2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackgroundModeManager::SetLaunchOnStartupResetAllowed(bool allowed) { 2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick profile_->GetPrefs()->SetBoolean(prefs::kLaunchOnStartupResetAllowed, 2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick allowed); 2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackgroundModeManager::Observe(NotificationType type, 2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const NotificationSource& source, 2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const NotificationDetails& details) { 2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick switch (type.value) { 2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case NotificationType::EXTENSIONS_READY: 234731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Extensions are loaded, so we don't need to manually keep the browser 235731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // process alive any more when running in no-startup-window mode. 236731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick EndKeepAliveForStartup(); 237731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 238731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // On a Mac, we use 'login items' mechanism which has user-facing UI so we 239731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // don't want to stomp on user choice every time we start and load 240731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // registered extensions. 2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if !defined(OS_MACOSX) 2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EnableLaunchOnStartup(IsBackgroundModeEnabled() && 2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick background_app_count_ > 0); 2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif 2453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case NotificationType::EXTENSION_LOADED: 247513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (BackgroundApplicationListModel::IsBackgroundApp( 248513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch *Details<Extension>(details).ptr())) { 2493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OnBackgroundAppLoaded(); 250513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 2513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case NotificationType::EXTENSION_UNLOADED: 253513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (BackgroundApplicationListModel::IsBackgroundApp( 254513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch *Details<Extension>(details).ptr())) { 2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OnBackgroundAppUnloaded(); 256513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case NotificationType::EXTENSION_INSTALLED: 259513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (BackgroundApplicationListModel::IsBackgroundApp( 260513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch *Details<Extension>(details).ptr())) { 2613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OnBackgroundAppInstalled(); 262513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 2643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case NotificationType::EXTENSION_UNINSTALLED: 265513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (Extension::HasApiPermission( 266513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Details<UninstalledExtensionInfo>(details).ptr()-> 267513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch extension_api_permissions, 268513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Extension::kBackgroundPermission)) { 2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OnBackgroundAppUninstalled(); 270513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case NotificationType::APP_TERMINATING: 273731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Make sure we aren't still keeping the app alive (only happens if we 274731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // don't receive an EXTENSIONS_READY notification for some reason). 275731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick EndKeepAliveForStartup(); 2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Performing an explicit shutdown, so exit background mode (does nothing 2773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // if we aren't in background mode currently). 2783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EndBackgroundMode(); 2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Shutting down, so don't listen for any more notifications so we don't 2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // try to re-enter/exit background mode again. 2813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick registrar_.RemoveAll(); 2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case NotificationType::PREF_CHANGED: 2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(0 == Details<std::string>(details).ptr()->compare( 2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs::kBackgroundModeEnabled)); 2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OnBackgroundModePrefChanged(); 2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 2883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick default: 2893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 2903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 2913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 294731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid BackgroundModeManager::EndKeepAliveForStartup() { 295731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (keep_alive_for_startup_) { 296731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick keep_alive_for_startup_ = false; 297731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // We call this via the message queue to make sure we don't try to end 298731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // keep-alive (which can shutdown Chrome) before the message loop has 299731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // started. 300731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick MessageLoop::current()->PostTask( 301731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick FROM_HERE, NewRunnableFunction(BrowserList::EndKeepAlive)); 302731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 3033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 3043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackgroundModeManager::OnBackgroundModePrefChanged() { 3063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Background mode has been enabled/disabled in preferences, so update our 3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // state accordingly. 3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (IsBackgroundModeEnabled() && !in_background_mode_ && 3093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick background_app_count_ > 0) { 3103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We should be in background mode, but we're not, so switch to background 3113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // mode. 3123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EnableLaunchOnStartup(true); 3133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick StartBackgroundMode(); 3143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!IsBackgroundModeEnabled() && in_background_mode_) { 3163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We're in background mode, but we shouldn't be any longer. 3173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EnableLaunchOnStartup(false); 3183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EndBackgroundMode(); 3193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 3213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackgroundModeManager::OnBackgroundAppLoaded() { 3233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // When a background app loads, increment our count and also enable 3243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // KeepAlive mode if the preference is set. 3253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick background_app_count_++; 3263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (background_app_count_ == 1 && IsBackgroundModeEnabled()) 3273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick StartBackgroundMode(); 3283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 3293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackgroundModeManager::StartBackgroundMode() { 3313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Don't bother putting ourselves in background mode if we're already there. 3323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (in_background_mode_) 3333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 3343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Mark ourselves as running in background mode. 3363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick in_background_mode_ = true; 3373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Put ourselves in KeepAlive mode and create a status tray icon. 3393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick BrowserList::StartKeepAlive(); 3403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Display a status icon to exit Chrome. 3423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CreateStatusTrayIcon(); 3433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 3443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackgroundModeManager::OnBackgroundAppUnloaded() { 3463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // When a background app unloads, decrement our count and also end 3473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // KeepAlive mode if appropriate. 3483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick background_app_count_--; 3493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(background_app_count_ >= 0); 3503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (background_app_count_ == 0 && IsBackgroundModeEnabled()) 3513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EndBackgroundMode(); 3523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 3533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackgroundModeManager::EndBackgroundMode() { 3553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!in_background_mode_) 3563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 3573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick in_background_mode_ = false; 3583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // End KeepAlive mode and blow away our status tray icon. 3603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick BrowserList::EndKeepAlive(); 3613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick RemoveStatusTrayIcon(); 3623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 3633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackgroundModeManager::OnBackgroundAppInstalled() { 3653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We're installing a background app. If this is the first background app 3663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // being installed, make sure we are set to launch on startup. 3673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (IsBackgroundModeEnabled() && background_app_count_ == 0) 3683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EnableLaunchOnStartup(true); 3693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 3703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackgroundModeManager::OnBackgroundAppUninstalled() { 372731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // When uninstalling a background app, disable launch on startup if 373731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // we have no more background apps. 374731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (IsBackgroundModeEnabled() && background_app_count_ == 0) 3753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EnableLaunchOnStartup(false); 3763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 3773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackgroundModeManager::EnableLaunchOnStartup(bool should_launch) { 3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // This functionality is only defined for default profile, currently. 3803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUserDataDir)) 3813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 3823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(OS_LINUX) 3833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (should_launch) 384731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 385731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new EnableLaunchOnStartupTask()); 3863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick else 387731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 388731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new DisableLaunchOnStartupTask()); 3893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#elif defined(OS_MACOSX) 3903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (should_launch) { 3913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Return if Chrome is already a Login Item (avoid overriding user choice). 3923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (mac_util::CheckLoginItemStatus(NULL)) 3933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 3943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick mac_util::AddToLoginItems(true); // Hide on startup. 3963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Remember we set Login Item, not the user - so we can reset it later. 3983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SetLaunchOnStartupResetAllowed(true); 3993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 4003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If we didn't set Login Item, don't mess with it. 4013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!IsLaunchOnStartupResetAllowed()) 4023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 4033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SetLaunchOnStartupResetAllowed(false); 4043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Check if Chrome is not a login Item, or is a Login Item but w/o 'hidden' 4063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // flag - most likely user has modified the setting, don't override it. 4073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool is_hidden = false; 4083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!mac_util::CheckLoginItemStatus(&is_hidden) || !is_hidden) 4093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 4103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick mac_util::RemoveFromLoginItems(); 4123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 4133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#elif defined(OS_WIN) 4143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(rickcam): Bug 53597: Make RegKey mockable. 4153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(rickcam): Bug 53600: Use distinct registry keys per flavor+profile. 4163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const wchar_t* key_name = kBackgroundModeRegistryKeyName; 417731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::win::RegKey read_key(kBackgroundModeRegistryRootKey, 418731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick kBackgroundModeRegistrySubkey, KEY_READ); 419731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::win::RegKey write_key(kBackgroundModeRegistryRootKey, 420731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick kBackgroundModeRegistrySubkey, KEY_WRITE); 4213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (should_launch) { 4223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FilePath executable; 4233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!PathService::Get(base::FILE_EXE, &executable)) 4243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 425731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::wstring new_value = executable.value() + 426731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick L" --enable-background-mode --no-startup-window"; 4273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (read_key.ValueExists(key_name)) { 4283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::wstring current_value; 4293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (read_key.ReadValue(key_name, ¤t_value) && 430731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick (current_value == new_value)) 4313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 4323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 433731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!write_key.WriteValue(key_name, new_value.c_str())) 4343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG(WARNING) << "Failed to register launch on login."; 4353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 4363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (read_key.ValueExists(key_name) && !write_key.DeleteValue(key_name)) 4373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG(WARNING) << "Failed to deregister launch on login."; 4383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 4393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif 4403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 4413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackgroundModeManager::CreateStatusTrayIcon() { 4433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Only need status icons on windows/linux. ChromeOS doesn't allow exiting 4443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Chrome and Mac can use the dock icon instead. 4453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) 4463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!status_tray_) 4473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick status_tray_ = profile_->GetStatusTray(); 4483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif 4493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If the platform doesn't support status icons, or we've already created 4513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // our status icon, just return. 4523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!status_tray_ || status_icon_) 4533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 4543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick status_icon_ = status_tray_->CreateStatusIcon(); 4553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!status_icon_) 4563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 4573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Set the image and add ourselves as a click observer on it 4593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SkBitmap* bitmap = ResourceBundle::GetSharedInstance().GetBitmapNamed( 4603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick IDR_STATUS_TRAY_ICON); 4613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick status_icon_->SetImage(*bitmap); 4623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick status_icon_->SetToolTip(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); 463513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UpdateStatusTrayIconContextMenu(); 464513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 465513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 466513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BackgroundModeManager::UpdateContextMenuEntryIcon( 467513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension) { 468513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!context_menu_) 469513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 470513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch context_menu_->SetIcon( 471513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch context_menu_application_offset_ + applications_.GetPosition(extension), 472513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch *(applications_.GetIcon(extension))); 473513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch status_icon_->SetContextMenu(context_menu_); // for Update effect 474513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 475513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 476513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BackgroundModeManager::UpdateStatusTrayIconContextMenu() { 477513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!status_icon_) 478513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 4793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Create a context menu item for Chrome. 4813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick menus::SimpleMenuModel* menu = new menus::SimpleMenuModel(this); 482513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Add About item 483513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch menu->AddItem(IDC_ABOUT, l10n_util::GetStringFUTF16(IDS_ABOUT, 484513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))); 485513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 486513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Add Preferences item 487731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (CommandLine::ForCurrentProcess()->HasSwitch( 488731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick switches::kEnableTabbedOptions)) { 489731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick menu->AddItemWithStringId(IDC_OPTIONS, IDS_SETTINGS); 490731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 4913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(TOOLKIT_GTK) 492731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick string16 preferences = gtk_util::GetStockPreferencesMenuLabel(); 493731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (preferences.empty()) 494731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick menu->AddItemWithStringId(IDC_OPTIONS, IDS_OPTIONS); 495731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick else 496731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick menu->AddItem(IDC_OPTIONS, preferences); 4973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#else 498731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick menu->AddItemWithStringId(IDC_OPTIONS, IDS_OPTIONS); 4993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif 500731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 501513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch menu->AddSeparator(); 502513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int application_position = 0; 503513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch context_menu_application_offset_ = menu->GetItemCount(); 504513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (ExtensionList::const_iterator cursor = applications_.begin(); 505513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch cursor != applications_.end(); 506513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ++cursor, ++application_position) { 507513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const SkBitmap* icon = applications_.GetIcon(*cursor); 508513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int sort_position = applications_.GetPosition(*cursor); 509513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(sort_position == application_position); 510513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& name = (*cursor)->name(); 511513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch menu->AddItem(sort_position, ASCIIToUTF16(name)); 512513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (icon) 513513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch menu->SetIcon(menu->GetItemCount() - 1, *icon); 514513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 5153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick menu->AddSeparator(); 5163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick menu->AddItemWithStringId(IDC_EXIT, IDS_EXIT); 517513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch context_menu_ = menu; 5183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick status_icon_->SetContextMenu(menu); 5193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 5213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool BackgroundModeManager::IsCommandIdChecked(int command_id) const { 5223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 5233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 5253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool BackgroundModeManager::IsCommandIdEnabled(int command_id) const { 5263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // For now, we do not support disabled items. 5273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 5283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 5303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool BackgroundModeManager::GetAcceleratorForCommandId( 5313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int command_id, 5323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick menus::Accelerator* accelerator) { 5333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // No accelerators for status icon context menus. 5343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 5353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 5373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackgroundModeManager::RemoveStatusTrayIcon() { 5383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (status_icon_) 5393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick status_tray_->RemoveStatusIcon(status_icon_); 5403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick status_icon_ = NULL; 5413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 543513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BackgroundModeManager::ExecuteApplication(int item) { 5444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch DCHECK(item >= 0 && item < static_cast<int>(applications_.size())); 545513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Browser* browser = BrowserList::GetLastActive(); 546513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!browser) { 547513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Browser::OpenEmptyWindow(profile_); 548513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch browser = BrowserList::GetLastActive(); 549513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 550513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension = applications_.GetExtension(item); 551513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch browser->OpenApplicationTab(profile_, extension, NULL); 552513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 5533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 5543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackgroundModeManager::ExecuteCommand(int item) { 5553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick switch (item) { 5563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case IDC_EXIT: 5573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UserMetrics::RecordAction(UserMetricsAction("Exit"), profile_); 5583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick BrowserList::CloseAllBrowsersAndExit(); 5593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 5603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case IDC_ABOUT: 5613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GetBrowserWindow()->OpenAboutChromeDialog(); 5623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 5633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case IDC_OPTIONS: 5643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GetBrowserWindow()->OpenOptionsDialog(); 5653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 5663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick default: 567513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ExecuteApplication(item); 5683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 5693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 5703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 5723345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickBrowser* BackgroundModeManager::GetBrowserWindow() { 5733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Browser* browser = BrowserList::GetLastActive(); 5743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!browser) { 5753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Browser::OpenEmptyWindow(profile_); 5763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick browser = BrowserList::GetLastActive(); 5773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 5783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return browser; 5793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 5813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static 5823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackgroundModeManager::RegisterUserPrefs(PrefService* prefs) { 5833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs->RegisterBooleanPref(prefs::kBackgroundModeEnabled, true); 5843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs->RegisterBooleanPref(prefs::kLaunchOnStartupResetAllowed, false); 5853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 586