MacViews: Get c/b/ui/views/tabs to build on Mac
[chromium-blink-merge.git] / chrome / installer / util / auto_launch_util.cc
blob7ad231536e2c82d04f93072cbeff8966ca0c5e17
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/installer/util/auto_launch_util.h"
7 #include "base/command_line.h"
8 #include "base/files/file_path.h"
9 #include "base/logging.h"
10 #include "base/path_service.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/win/win_util.h"
14 #include "chrome/common/chrome_constants.h"
15 #include "chrome/common/chrome_paths.h"
16 #include "chrome/common/chrome_switches.h"
17 #include "chrome/common/chrome_version_info.h"
18 #include "chrome/installer/util/util_constants.h"
19 #include "crypto/sha2.h"
21 using base::ASCIIToUTF16;
22 using base::ASCIIToWide;
24 namespace auto_launch_util {
26 // The prefix of the Chrome Auto-launch key under the Run key.
27 const wchar_t kAutolaunchKeyValue[] = L"GoogleChromeAutoLaunch";
29 // We use one Run key with flags specifying which feature we want to start up.
30 // When we change our Run key we need to specify what we want to do with each
31 // flag. This lists the possible actions we can take with the flags.
32 enum FlagSetting {
33 FLAG_DISABLE, // Disable the flag.
34 FLAG_ENABLE, // Enable the flag.
35 FLAG_PRESERVE, // Preserve the value that the flag has currently.
38 // A helper function that takes a |profile_directory| and builds a registry key
39 // name to use when deciding where to read/write the auto-launch value
40 // to/from. It takes into account the name of the profile (so that different
41 // installations of Chrome don't conflict, and so the in the future different
42 // profiles can be auto-launched (or not) separately).
43 base::string16 ProfileToKeyName(const base::string16& profile_directory) {
44 base::FilePath path;
45 const bool success = PathService::Get(chrome::DIR_USER_DATA, &path);
46 DCHECK(success);
47 path = path.Append(profile_directory);
49 std::string input(path.AsUTF8Unsafe());
50 uint8 hash[16];
51 crypto::SHA256HashString(input, hash, sizeof(hash));
52 std::string hash_string = base::HexEncode(hash, sizeof(hash));
53 return base::string16(kAutolaunchKeyValue) + ASCIIToWide("_") +
54 ASCIIToWide(hash_string);
57 // Returns whether the Chrome executable specified in |application_path| is set
58 // to auto-launch at computer startup with a given |command_line_switch|.
59 // NOTE: |application_path| is optional and should be blank in most cases (as
60 // it will default to the application path of the current executable).
61 // |profile_directory| is the name of the directory (leaf, not the full path)
62 // that contains the profile that should be opened at computer startup.
63 // |command_line_switch| is the switch we are optionally interested in and, if
64 // not blank, must be present for the function to return true. If blank, it acts
65 // like a wildcard.
66 bool WillLaunchAtLoginWithSwitch(const base::FilePath& application_path,
67 const base::string16& profile_directory,
68 const std::string& command_line_switch) {
69 base::string16 key_name(ProfileToKeyName(profile_directory));
70 base::string16 autolaunch;
71 if (!base::win::ReadCommandFromAutoRun(
72 HKEY_CURRENT_USER, key_name, &autolaunch)) {
73 return false;
76 base::FilePath chrome_exe(application_path);
77 if (chrome_exe.empty()) {
78 if (!PathService::Get(base::DIR_EXE, &chrome_exe)) {
79 NOTREACHED();
80 return false;
83 chrome_exe = chrome_exe.Append(installer::kChromeExe);
85 if (autolaunch.find(chrome_exe.value()) == base::string16::npos)
86 return false;
88 return command_line_switch.empty() ||
89 autolaunch.find(ASCIIToUTF16(command_line_switch)) !=
90 base::string16::npos;
93 bool AutoStartRequested(const base::string16& profile_directory,
94 bool window_requested,
95 const base::FilePath& application_path) {
96 if (window_requested) {
97 return WillLaunchAtLoginWithSwitch(application_path,
98 profile_directory,
99 switches::kAutoLaunchAtStartup);
100 } else {
101 // Background mode isn't profile specific, but is attached to the Run key
102 // for the Default profile.
103 return WillLaunchAtLoginWithSwitch(application_path,
104 ASCIIToUTF16(chrome::kInitialProfile),
105 switches::kNoStartupWindow);
109 bool CheckAndRemoveDeprecatedBackgroundModeSwitch() {
110 // For backwards compatibility we need to provide a migration path from the
111 // previously used key "chromium" that the BackgroundMode used to set, as it
112 // is incompatible with the new key (can't have two Run keys with
113 // conflicting switches).
114 base::string16 chromium = ASCIIToUTF16("chromium");
115 base::string16 value;
116 if (base::win::ReadCommandFromAutoRun(HKEY_CURRENT_USER, chromium, &value)) {
117 if (value.find(ASCIIToUTF16(switches::kNoStartupWindow)) !=
118 base::string16::npos) {
119 base::win::RemoveCommandFromAutoRun(HKEY_CURRENT_USER, chromium);
120 return true;
124 return false;
127 void SetWillLaunchAtLogin(const base::FilePath& application_path,
128 const base::string16& profile_directory,
129 FlagSetting foreground_mode,
130 FlagSetting background_mode) {
131 if (CheckAndRemoveDeprecatedBackgroundModeSwitch()) {
132 // We've found the deprecated switch, we must migrate it (unless background
133 // mode is being turned off).
134 if (profile_directory == ASCIIToUTF16(chrome::kInitialProfile) &&
135 background_mode == FLAG_PRESERVE) {
136 // Preserve in this case also covers the deprecated value, so we must
137 // explicitly turn the flag on and the rest will be taken care of below.
138 background_mode = FLAG_ENABLE;
139 } else {
140 // When we add support for multiple profiles for foreground mode we need
141 // to think about where to store the background mode switch. I think we
142 // need to store it with the Default profile (call SetWillLaunchAtLogin
143 // again specifying the Default profile), but concerns were raised in
144 // review.
145 NOTREACHED();
148 base::string16 key_name(ProfileToKeyName(profile_directory));
150 // Check which feature should be enabled.
151 bool in_foreground =
152 foreground_mode == FLAG_ENABLE ||
153 (foreground_mode == FLAG_PRESERVE &&
154 WillLaunchAtLoginWithSwitch(application_path,
155 profile_directory,
156 switches::kAutoLaunchAtStartup));
157 bool in_background =
158 background_mode == FLAG_ENABLE ||
159 (background_mode == FLAG_PRESERVE &&
160 WillLaunchAtLoginWithSwitch(application_path,
161 profile_directory,
162 switches::kNoStartupWindow));
164 // TODO(finnur): Convert this into a shortcut, instead of using the Run key.
165 if (in_foreground || in_background) {
166 base::FilePath path(application_path);
167 if (path.empty()) {
168 if (!PathService::Get(base::DIR_EXE, &path)) {
169 NOTREACHED();
170 return;
173 base::string16 cmd_line = ASCIIToUTF16("\"");
174 cmd_line += path.value();
175 cmd_line += ASCIIToUTF16("\\");
176 cmd_line += installer::kChromeExe;
177 cmd_line += ASCIIToUTF16("\"");
179 if (in_background) {
180 cmd_line += ASCIIToUTF16(" --");
181 cmd_line += ASCIIToUTF16(switches::kNoStartupWindow);
183 if (in_foreground) {
184 cmd_line += ASCIIToUTF16(" --");
185 cmd_line += ASCIIToUTF16(switches::kAutoLaunchAtStartup);
187 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
188 if (command_line.HasSwitch(switches::kUserDataDir)) {
189 cmd_line += ASCIIToUTF16(" --");
190 cmd_line += ASCIIToUTF16(switches::kUserDataDir);
191 cmd_line += ASCIIToUTF16("=\"");
192 cmd_line +=
193 command_line.GetSwitchValuePath(switches::kUserDataDir).value();
194 cmd_line += ASCIIToUTF16("\"");
197 cmd_line += ASCIIToUTF16(" --");
198 cmd_line += ASCIIToUTF16(switches::kProfileDirectory);
199 cmd_line += ASCIIToUTF16("=\"");
200 cmd_line += profile_directory;
201 cmd_line += ASCIIToUTF16("\"");
204 base::win::AddCommandToAutoRun(HKEY_CURRENT_USER, key_name, cmd_line);
205 } else {
206 base::win::RemoveCommandFromAutoRun(HKEY_CURRENT_USER, key_name);
210 void DisableAllAutoStartFeatures(const base::string16& profile_directory) {
211 DisableForegroundStartAtLogin(profile_directory);
212 DisableBackgroundStartAtLogin();
215 void EnableForegroundStartAtLogin(const base::string16& profile_directory,
216 const base::FilePath& application_path) {
217 SetWillLaunchAtLogin(
218 application_path, profile_directory, FLAG_ENABLE, FLAG_PRESERVE);
221 void DisableForegroundStartAtLogin(const base::string16& profile_directory) {
222 SetWillLaunchAtLogin(
223 base::FilePath(), profile_directory, FLAG_DISABLE, FLAG_PRESERVE);
226 void EnableBackgroundStartAtLogin() {
227 // Background mode isn't profile specific, but we specify the Default profile
228 // just to have a unique Run key to attach it to. FilePath is blank because
229 // this function is not called from the installer (see comments for
230 // EnableAutoStartAtLogin).
231 SetWillLaunchAtLogin(base::FilePath(),
232 ASCIIToUTF16(chrome::kInitialProfile),
233 FLAG_PRESERVE,
234 FLAG_ENABLE);
237 void DisableBackgroundStartAtLogin() {
238 SetWillLaunchAtLogin(base::FilePath(),
239 ASCIIToUTF16(chrome::kInitialProfile),
240 FLAG_PRESERVE,
241 FLAG_DISABLE);
244 } // namespace auto_launch_util