Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / installer / util / auto_launch_util.cc
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.
4
5 #include "chrome/installer/util/auto_launch_util.h"
6
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"
20
21 using base::ASCIIToUTF16;
22 using base::ASCIIToWide;
23
24 namespace auto_launch_util {
25
26 // The prefix of the Chrome Auto-launch key under the Run key.
27 const wchar_t kAutolaunchKeyValue[] = L"GoogleChromeAutoLaunch";
28
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.
36 };
37
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);
48
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);
55 }
56
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;
74   }
75
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;
81     }
82   }
83   chrome_exe = chrome_exe.Append(installer::kChromeExe);
84
85   if (autolaunch.find(chrome_exe.value()) == base::string16::npos)
86     return false;
87
88   return command_line_switch.empty() ||
89          autolaunch.find(ASCIIToUTF16(command_line_switch)) !=
90              base::string16::npos;
91 }
92
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);
106   }
107 }
108
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;
121     }
122   }
123
124   return false;
125 }
126
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();
146     }
147   }
148   base::string16 key_name(ProfileToKeyName(profile_directory));
149
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));
163
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;
171       }
172     }
173     base::string16 cmd_line = ASCIIToUTF16("\"");
174     cmd_line += path.value();
175     cmd_line += ASCIIToUTF16("\\");
176     cmd_line += installer::kChromeExe;
177     cmd_line += ASCIIToUTF16("\"");
178
179     if (in_background) {
180       cmd_line += ASCIIToUTF16(" --");
181       cmd_line += ASCIIToUTF16(switches::kNoStartupWindow);
182     }
183     if (in_foreground) {
184       cmd_line += ASCIIToUTF16(" --");
185       cmd_line += ASCIIToUTF16(switches::kAutoLaunchAtStartup);
186
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("\"");
195       }
196
197       cmd_line += ASCIIToUTF16(" --");
198       cmd_line += ASCIIToUTF16(switches::kProfileDirectory);
199       cmd_line += ASCIIToUTF16("=\"");
200       cmd_line += profile_directory;
201       cmd_line += ASCIIToUTF16("\"");
202     }
203
204     base::win::AddCommandToAutoRun(HKEY_CURRENT_USER, key_name, cmd_line);
205   } else {
206     base::win::RemoveCommandFromAutoRun(HKEY_CURRENT_USER, key_name);
207   }
208 }
209
210 void DisableAllAutoStartFeatures(const base::string16& profile_directory) {
211   DisableForegroundStartAtLogin(profile_directory);
212   DisableBackgroundStartAtLogin();
213 }
214
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);
219 }
220
221 void DisableForegroundStartAtLogin(const base::string16& profile_directory) {
222   SetWillLaunchAtLogin(
223       base::FilePath(), profile_directory, FLAG_DISABLE, FLAG_PRESERVE);
224 }
225
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);
235 }
236
237 void DisableBackgroundStartAtLogin() {
238   SetWillLaunchAtLogin(base::FilePath(),
239                        ASCIIToUTF16(chrome::kInitialProfile),
240                        FLAG_PRESERVE,
241                        FLAG_DISABLE);
242 }
243
244 }  // namespace auto_launch_util