OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 // This file defines functions that integrate Chrome in Windows shell. These | 5 // This file defines functions that integrate Chrome in Windows shell. These |
6 // functions can be used by Chrome as well as Chrome installer. All of the | 6 // functions can be used by Chrome as well as Chrome installer. All of the |
7 // work is done by the local functions defined in anonymous namespace in | 7 // work is done by the local functions defined in anonymous namespace in |
8 // this class. | 8 // this class. |
9 | 9 |
10 #include "chrome/installer/util/shell_util.h" | 10 #include "chrome/installer/util/shell_util.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 #include "chrome/common/chrome_switches.h" | 46 #include "chrome/common/chrome_switches.h" |
47 #include "chrome/installer/util/beacons.h" | 47 #include "chrome/installer/util/beacons.h" |
48 #include "chrome/installer/util/browser_distribution.h" | 48 #include "chrome/installer/util/browser_distribution.h" |
49 #include "chrome/installer/util/install_util.h" | 49 #include "chrome/installer/util/install_util.h" |
50 #include "chrome/installer/util/installer_util_strings.h" | 50 #include "chrome/installer/util/installer_util_strings.h" |
51 #include "chrome/installer/util/l10n_string_util.h" | 51 #include "chrome/installer/util/l10n_string_util.h" |
52 #include "chrome/installer/util/master_preferences.h" | 52 #include "chrome/installer/util/master_preferences.h" |
53 #include "chrome/installer/util/master_preferences_constants.h" | 53 #include "chrome/installer/util/master_preferences_constants.h" |
54 #include "chrome/installer/util/registry_entry.h" | 54 #include "chrome/installer/util/registry_entry.h" |
55 #include "chrome/installer/util/scoped_user_protocol_entry.h" | 55 #include "chrome/installer/util/scoped_user_protocol_entry.h" |
| 56 #include "chrome/installer/util/shell_registry_util.h" |
56 #include "chrome/installer/util/util_constants.h" | 57 #include "chrome/installer/util/util_constants.h" |
57 #include "chrome/installer/util/work_item.h" | 58 #include "chrome/installer/util/work_item.h" |
58 | 59 |
59 using base::win::RegKey; | 60 using base::win::RegKey; |
60 | 61 |
61 namespace { | 62 namespace { |
62 | 63 |
63 // An enum used to tell QuickIsChromeRegistered() which level of registration | 64 // An enum used to tell QuickIsChromeRegistered() which level of registration |
64 // the caller wants to confirm. | 65 // the caller wants to confirm. |
65 enum RegistrationConfirmationLevel { | 66 enum RegistrationConfirmationLevel { |
66 // Only look for Chrome's ProgIds. | 67 // Only look for Chrome's ProgIds. |
67 // This is sufficient when we are trying to determine the suffix of the | 68 // This is sufficient when we are trying to determine the suffix of the |
68 // currently running Chrome as shell integration registrations might not be | 69 // currently running Chrome as shell integration registrations might not be |
69 // present. | 70 // present. |
70 CONFIRM_PROGID_REGISTRATION = 0, | 71 CONFIRM_PROGID_REGISTRATION = 0, |
71 // Confirm that Chrome is fully integrated with Windows (i.e. registered with | 72 // Confirm that Chrome is fully integrated with Windows (i.e. registered with |
72 // Defaut Programs). These registrations can be in HKCU as of Windows 8. | 73 // Defaut Programs). These registrations can be in HKCU as of Windows 8. |
73 // Note: Shell registration implies ProgId registration. | 74 // Note: Shell registration implies ProgId registration. |
74 CONFIRM_SHELL_REGISTRATION, | 75 CONFIRM_SHELL_REGISTRATION, |
75 // Same as CONFIRM_SHELL_REGISTRATION, but only look in HKLM (used when | 76 // Same as CONFIRM_SHELL_REGISTRATION, but only look in HKLM (used when |
76 // uninstalling to know whether elevation is required to clean up the | 77 // uninstalling to know whether elevation is required to clean up the |
77 // registry). | 78 // registry). |
78 CONFIRM_SHELL_REGISTRATION_IN_HKLM, | 79 CONFIRM_SHELL_REGISTRATION_IN_HKLM, |
79 }; | 80 }; |
80 | 81 |
81 const wchar_t kReinstallCommand[] = L"ReinstallCommand"; | |
82 | |
83 // Returns the current (or installed) browser's ProgId (e.g. | |
84 // "ChromeHTML|suffix|"). | |
85 // |suffix| can be the empty string. | |
86 base::string16 GetBrowserProgId(const base::string16& suffix) { | |
87 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | |
88 base::string16 chrome_html(dist->GetBrowserProgIdPrefix()); | |
89 chrome_html.append(suffix); | |
90 | |
91 // ProgIds cannot be longer than 39 characters. | |
92 // Ref: http://msdn.microsoft.com/en-us/library/aa911706.aspx. | |
93 // Make all new registrations comply with this requirement (existing | |
94 // registrations must be preserved). | |
95 base::string16 new_style_suffix; | |
96 if (ShellUtil::GetUserSpecificRegistrySuffix(&new_style_suffix) && | |
97 suffix == new_style_suffix && chrome_html.length() > 39) { | |
98 NOTREACHED(); | |
99 chrome_html.erase(39); | |
100 } | |
101 return chrome_html; | |
102 } | |
103 | |
104 // This class is used to initialize and cache a base 32 encoding of the md5 hash | 82 // This class is used to initialize and cache a base 32 encoding of the md5 hash |
105 // of this user's sid preceded by a dot. | 83 // of this user's sid preceded by a dot. |
106 // This is guaranteed to be unique on the machine and 27 characters long | 84 // This is guaranteed to be unique on the machine and 27 characters long |
107 // (including the '.'). | 85 // (including the '.'). |
108 // This is then meant to be used as a suffix on all registrations that may | 86 // This is then meant to be used as a suffix on all registrations that may |
109 // conflict with another user-level Chrome install. | 87 // conflict with another user-level Chrome install. |
110 class UserSpecificRegistrySuffix { | 88 class UserSpecificRegistrySuffix { |
111 public: | 89 public: |
112 // All the initialization is done in the constructor to be able to build the | 90 // All the initialization is done in the constructor to be able to build the |
113 // suffix in a thread-safe manner when used in conjunction with a | 91 // suffix in a thread-safe manner when used in conjunction with a |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 | 127 |
150 bool UserSpecificRegistrySuffix::GetSuffix(base::string16* suffix) { | 128 bool UserSpecificRegistrySuffix::GetSuffix(base::string16* suffix) { |
151 if (suffix_.empty()) { | 129 if (suffix_.empty()) { |
152 NOTREACHED(); | 130 NOTREACHED(); |
153 return false; | 131 return false; |
154 } | 132 } |
155 suffix->assign(suffix_); | 133 suffix->assign(suffix_); |
156 return true; | 134 return true; |
157 } | 135 } |
158 | 136 |
159 // Details about a Windows application, to be entered into the registry for the | |
160 // purpose of file associations. | |
161 struct ApplicationInfo { | |
162 ApplicationInfo() : file_type_icon_index(0), application_icon_index(0) {} | |
163 | |
164 // The ProgId used by Windows for file associations with this application. | |
165 // Must not be empty or start with a '.'. | |
166 base::string16 prog_id; | |
167 // The friendly name, and the path of the icon that will be used for files of | |
168 // these types when associated with this application by default. (They are NOT | |
169 // the name/icon that will represent the application under the Open With | |
170 // menu.) | |
171 base::string16 file_type_name; | |
172 base::FilePath file_type_icon_path; | |
173 int file_type_icon_index; | |
174 // The command to execute when opening a file via this association. It should | |
175 // contain "%1" (to tell Windows to pass the filename as an argument). | |
176 // TODO(mgiuca): |command_line| should be a base::CommandLine. | |
177 base::string16 command_line; | |
178 // The AppUserModelId used by Windows 8 for this application. Distinct from | |
179 // |prog_id|. | |
180 base::string16 app_id; | |
181 | |
182 // User-visible details about this application. Any of these may be empty. | |
183 base::string16 application_name; | |
184 base::FilePath application_icon_path; | |
185 int application_icon_index; | |
186 base::string16 application_description; | |
187 base::string16 publisher_name; | |
188 | |
189 // The CLSID for the application's DelegateExecute handler. May be empty. | |
190 base::string16 delegate_clsid; | |
191 }; | |
192 | |
193 // Returns the Windows browser client registration key for Chrome. For example: | |
194 // "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly speaking, we | |
195 // should use the name of the executable (e.g., "chrome.exe"), but that ship has | |
196 // sailed. The cost of switching now is re-prompting users to make Chrome their | |
197 // default browser, which isn't polite. |suffix| is the user-specific | |
198 // registration suffix; see GetUserSpecificDefaultBrowserSuffix in shell_util.h | |
199 // for details. | |
200 base::string16 GetBrowserClientKey(BrowserDistribution* dist, | |
201 const base::string16& suffix) { | |
202 DCHECK(suffix.empty() || suffix[0] == L'.'); | |
203 return base::string16(ShellUtil::kRegStartMenuInternet) | |
204 .append(1, L'\\') | |
205 .append(dist->GetBaseAppName()) | |
206 .append(suffix); | |
207 } | |
208 | |
209 // Returns the Windows Default Programs capabilities key for Chrome. For | |
210 // example: | |
211 // "Software\Clients\StartMenuInternet\Chromium[.user]\Capabilities". | |
212 base::string16 GetCapabilitiesKey(BrowserDistribution* dist, | |
213 const base::string16& suffix) { | |
214 return GetBrowserClientKey(dist, suffix).append(L"\\Capabilities"); | |
215 } | |
216 | |
217 // DelegateExecute ProgId. Needed for Chrome Metro in Windows 8. This is only | |
218 // needed for registring a web browser, not for general associations. | |
219 ScopedVector<RegistryEntry> GetChromeDelegateExecuteEntries( | |
220 const base::FilePath& chrome_exe, | |
221 const ApplicationInfo& app_info) { | |
222 ScopedVector<RegistryEntry> entries; | |
223 | |
224 base::string16 app_id_shell_key(ShellUtil::kRegClasses); | |
225 app_id_shell_key.push_back(base::FilePath::kSeparators[0]); | |
226 app_id_shell_key.append(app_info.app_id); | |
227 app_id_shell_key.append(ShellUtil::kRegExePath); | |
228 app_id_shell_key.append(ShellUtil::kRegShellPath); | |
229 | |
230 // <root hkey>\Software\Classes\<app_id>\.exe\shell @=open | |
231 entries.push_back( | |
232 new RegistryEntry(app_id_shell_key, ShellUtil::kRegVerbOpen)); | |
233 | |
234 // The command to execute when opening this application via the Metro UI. | |
235 const base::string16 delegate_command( | |
236 ShellUtil::GetChromeDelegateCommand(chrome_exe)); | |
237 | |
238 // Each of Chrome's shortcuts has an appid; which, as of Windows 8, is | |
239 // registered to handle some verbs. This registration has the side-effect | |
240 // that these verbs now show up in the shortcut's context menu. We | |
241 // mitigate this side-effect by making the context menu entries | |
242 // user readable/localized strings. See relevant MSDN article: | |
243 // http://msdn.microsoft.com/en-US/library/windows/desktop/cc144171.aspx | |
244 static const struct { | |
245 const wchar_t* verb; | |
246 int name_id; | |
247 } verbs[] = { | |
248 {ShellUtil::kRegVerbOpen, -1}, | |
249 {ShellUtil::kRegVerbOpenNewWindow, IDS_SHORTCUT_NEW_WINDOW_BASE}, | |
250 }; | |
251 for (const auto& verb_and_id : verbs) { | |
252 base::string16 sub_path(app_id_shell_key); | |
253 sub_path.push_back(base::FilePath::kSeparators[0]); | |
254 sub_path.append(verb_and_id.verb); | |
255 | |
256 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb> | |
257 if (verb_and_id.name_id != -1) { | |
258 // TODO(grt): http://crbug.com/75152 Write a reference to a localized | |
259 // resource. | |
260 const base::string16 verb_name( | |
261 installer::GetLocalizedString(verb_and_id.name_id)); | |
262 entries.push_back(new RegistryEntry(sub_path, verb_name.c_str())); | |
263 } | |
264 entries.push_back( | |
265 new RegistryEntry(sub_path, L"CommandId", L"Browser.Launch")); | |
266 | |
267 sub_path.push_back(base::FilePath::kSeparators[0]); | |
268 sub_path.append(ShellUtil::kRegCommand); | |
269 | |
270 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>\command | |
271 entries.push_back(new RegistryEntry(sub_path, delegate_command)); | |
272 entries.push_back(new RegistryEntry( | |
273 sub_path, ShellUtil::kRegDelegateExecute, app_info.delegate_clsid)); | |
274 } | |
275 | |
276 return entries; | |
277 } | |
278 | |
279 // Gets the registry entries to register an application in the Windows registry. | |
280 // |app_info| provides all of the information needed. | |
281 void GetProgIdEntries(const ApplicationInfo& app_info, | |
282 ScopedVector<RegistryEntry>* entries) { | |
283 // Basic sanity checks. | |
284 DCHECK(!app_info.prog_id.empty()); | |
285 DCHECK_NE(L'.', app_info.prog_id[0]); | |
286 | |
287 // File association ProgId | |
288 base::string16 prog_id_path(ShellUtil::kRegClasses); | |
289 prog_id_path.push_back(base::FilePath::kSeparators[0]); | |
290 prog_id_path.append(app_info.prog_id); | |
291 entries->push_back(new RegistryEntry(prog_id_path, app_info.file_type_name)); | |
292 entries->push_back(new RegistryEntry( | |
293 prog_id_path + ShellUtil::kRegDefaultIcon, | |
294 ShellUtil::FormatIconLocation(app_info.file_type_icon_path, | |
295 app_info.file_type_icon_index))); | |
296 entries->push_back(new RegistryEntry(prog_id_path + ShellUtil::kRegShellOpen, | |
297 app_info.command_line)); | |
298 if (!app_info.delegate_clsid.empty()) { | |
299 entries->push_back(new RegistryEntry( | |
300 prog_id_path + ShellUtil::kRegShellOpen, ShellUtil::kRegDelegateExecute, | |
301 app_info.delegate_clsid)); | |
302 // TODO(scottmg): Simplify after Metro removal. https://crbug.com/558054. | |
303 entries->back()->set_removal_flag(RegistryEntry::RemovalFlag::VALUE); | |
304 } | |
305 | |
306 // The following entries are required as of Windows 8, but do not | |
307 // depend on the DelegateExecute verb handler being set. | |
308 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { | |
309 if (!app_info.app_id.empty()) { | |
310 entries->push_back(new RegistryEntry( | |
311 prog_id_path, ShellUtil::kRegAppUserModelId, app_info.app_id)); | |
312 } | |
313 | |
314 // Add \Software\Classes\<prog_id>\Application entries | |
315 base::string16 application_path(prog_id_path + ShellUtil::kRegApplication); | |
316 if (!app_info.app_id.empty()) { | |
317 entries->push_back(new RegistryEntry( | |
318 application_path, ShellUtil::kRegAppUserModelId, app_info.app_id)); | |
319 } | |
320 if (!app_info.application_icon_path.empty()) { | |
321 entries->push_back(new RegistryEntry( | |
322 application_path, ShellUtil::kRegApplicationIcon, | |
323 ShellUtil::FormatIconLocation(app_info.application_icon_path, | |
324 app_info.application_icon_index))); | |
325 } | |
326 if (!app_info.application_name.empty()) { | |
327 entries->push_back(new RegistryEntry(application_path, | |
328 ShellUtil::kRegApplicationName, | |
329 app_info.application_name)); | |
330 } | |
331 if (!app_info.application_description.empty()) { | |
332 entries->push_back(new RegistryEntry( | |
333 application_path, ShellUtil::kRegApplicationDescription, | |
334 app_info.application_description)); | |
335 } | |
336 if (!app_info.publisher_name.empty()) { | |
337 entries->push_back(new RegistryEntry(application_path, | |
338 ShellUtil::kRegApplicationCompany, | |
339 app_info.publisher_name)); | |
340 } | |
341 } | |
342 } | |
343 | |
344 // This method returns a list of all the registry entries that are needed to | |
345 // register this installation's ProgId and AppId. These entries need to be | |
346 // registered in HKLM prior to Win8. | |
347 void GetChromeProgIdEntries(BrowserDistribution* dist, | |
348 const base::FilePath& chrome_exe, | |
349 const base::string16& suffix, | |
350 ScopedVector<RegistryEntry>* entries) { | |
351 int chrome_icon_index = | |
352 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME); | |
353 | |
354 ApplicationInfo app_info; | |
355 app_info.prog_id = GetBrowserProgId(suffix); | |
356 app_info.file_type_name = dist->GetBrowserProgIdDesc(); | |
357 // File types associated with Chrome are just given the Chrome icon. | |
358 app_info.file_type_icon_path = chrome_exe; | |
359 app_info.file_type_icon_index = chrome_icon_index; | |
360 app_info.command_line = ShellUtil::GetChromeShellOpenCmd(chrome_exe); | |
361 // For user-level installs: entries for the app id will be in HKCU; thus we | |
362 // do not need a suffix on those entries. | |
363 app_info.app_id = ShellUtil::GetBrowserModelId( | |
364 dist, InstallUtil::IsPerUserInstall(chrome_exe)); | |
365 | |
366 // TODO(grt): http://crbug.com/75152 Write a reference to a localized | |
367 // resource for name, description, and company. | |
368 app_info.application_name = dist->GetDisplayName(); | |
369 app_info.application_icon_path = chrome_exe; | |
370 app_info.application_icon_index = chrome_icon_index; | |
371 app_info.application_description = dist->GetAppDescription(); | |
372 app_info.publisher_name = dist->GetPublisherName(); | |
373 | |
374 app_info.delegate_clsid = dist->GetCommandExecuteImplClsid(); | |
375 | |
376 GetProgIdEntries(app_info, entries); | |
377 | |
378 if (!app_info.delegate_clsid.empty()) { | |
379 ScopedVector<RegistryEntry> delegate_execute_entries = | |
380 GetChromeDelegateExecuteEntries(chrome_exe, app_info); | |
381 // Remove the keys (not only their values) so that Windows will continue | |
382 // to launch Chrome without a pesky association error. | |
383 // TODO(scottmg): Simplify after Metro removal. https://crbug.com/558054. | |
384 for (RegistryEntry* entry : delegate_execute_entries) | |
385 entry->set_removal_flag(RegistryEntry::RemovalFlag::KEY); | |
386 // Move |delegate_execute_entries| to |entries|. | |
387 entries->insert(entries->end(), delegate_execute_entries.begin(), | |
388 delegate_execute_entries.end()); | |
389 delegate_execute_entries.weak_clear(); | |
390 } | |
391 } | |
392 | |
393 // This method returns a list of the registry entries needed to declare a | |
394 // capability of handling a protocol on Windows. | |
395 void GetProtocolCapabilityEntries(BrowserDistribution* dist, | |
396 const base::string16& suffix, | |
397 const base::string16& protocol, | |
398 ScopedVector<RegistryEntry>* entries) { | |
399 entries->push_back(new RegistryEntry( | |
400 GetCapabilitiesKey(dist, suffix).append(L"\\URLAssociations"), protocol, | |
401 GetBrowserProgId(suffix))); | |
402 } | |
403 | |
404 // This method returns a list of the registry entries required to register this | |
405 // installation in "RegisteredApplications" on Windows (to appear in Default | |
406 // Programs, StartMenuInternet, etc.). These entries need to be registered in | |
407 // HKLM prior to Win8. If |suffix| is not empty, these entries are guaranteed to | |
408 // be unique on this machine. | |
409 void GetShellIntegrationEntries(BrowserDistribution* dist, | |
410 const base::FilePath& chrome_exe, | |
411 const base::string16& suffix, | |
412 ScopedVector<RegistryEntry>* entries) { | |
413 const base::string16 icon_path(ShellUtil::FormatIconLocation( | |
414 chrome_exe, dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME))); | |
415 const base::string16 quoted_exe_path(L"\"" + chrome_exe.value() + L"\""); | |
416 | |
417 // Register for the Start Menu "Internet" link (pre-Win7). | |
418 const base::string16 start_menu_entry(GetBrowserClientKey(dist, suffix)); | |
419 // Register Chrome's display name. | |
420 // TODO(grt): http://crbug.com/75152 Also set LocalizedString; see | |
421 // http://msdn.microsoft.com/en-us/library/windows/desktop/cc144109(v=VS.85).a
spx#registering_the_display_name | |
422 entries->push_back( | |
423 new RegistryEntry(start_menu_entry, dist->GetDisplayName())); | |
424 // Register the "open" verb for launching Chrome via the "Internet" link. | |
425 entries->push_back(new RegistryEntry( | |
426 start_menu_entry + ShellUtil::kRegShellOpen, quoted_exe_path)); | |
427 // Register Chrome's icon for the Start Menu "Internet" link. | |
428 entries->push_back(new RegistryEntry( | |
429 start_menu_entry + ShellUtil::kRegDefaultIcon, icon_path)); | |
430 | |
431 // Register installation information. | |
432 base::string16 install_info(start_menu_entry + L"\\InstallInfo"); | |
433 // Note: not using CommandLine since it has ambiguous rules for quoting | |
434 // strings. | |
435 entries->push_back( | |
436 new RegistryEntry(install_info, kReinstallCommand, | |
437 quoted_exe_path + L" --" + | |
438 base::ASCIIToUTF16(switches::kMakeDefaultBrowser))); | |
439 entries->push_back(new RegistryEntry( | |
440 install_info, L"HideIconsCommand", | |
441 quoted_exe_path + L" --" + base::ASCIIToUTF16(switches::kHideIcons))); | |
442 entries->push_back(new RegistryEntry( | |
443 install_info, L"ShowIconsCommand", | |
444 quoted_exe_path + L" --" + base::ASCIIToUTF16(switches::kShowIcons))); | |
445 entries->push_back(new RegistryEntry(install_info, L"IconsVisible", 1)); | |
446 | |
447 // Register with Default Programs. | |
448 const base::string16 reg_app_name(dist->GetBaseAppName().append(suffix)); | |
449 // Tell Windows where to find Chrome's Default Programs info. | |
450 const base::string16 capabilities(GetCapabilitiesKey(dist, suffix)); | |
451 entries->push_back(new RegistryEntry(ShellUtil::kRegRegisteredApplications, | |
452 reg_app_name, capabilities)); | |
453 // Write out Chrome's Default Programs info. | |
454 // TODO(grt): http://crbug.com/75152 Write a reference to a localized | |
455 // resource rather than this. | |
456 entries->push_back(new RegistryEntry(capabilities, | |
457 ShellUtil::kRegApplicationDescription, | |
458 dist->GetLongAppDescription())); | |
459 entries->push_back(new RegistryEntry( | |
460 capabilities, ShellUtil::kRegApplicationIcon, icon_path)); | |
461 entries->push_back(new RegistryEntry( | |
462 capabilities, ShellUtil::kRegApplicationName, dist->GetDisplayName())); | |
463 | |
464 entries->push_back(new RegistryEntry(capabilities + L"\\Startmenu", | |
465 L"StartMenuInternet", reg_app_name)); | |
466 | |
467 const base::string16 html_prog_id(GetBrowserProgId(suffix)); | |
468 for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) { | |
469 entries->push_back(new RegistryEntry( | |
470 capabilities + L"\\FileAssociations", | |
471 ShellUtil::kPotentialFileAssociations[i], html_prog_id)); | |
472 } | |
473 for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL; i++) { | |
474 entries->push_back(new RegistryEntry( | |
475 capabilities + L"\\URLAssociations", | |
476 ShellUtil::kPotentialProtocolAssociations[i], html_prog_id)); | |
477 } | |
478 } | |
479 | |
480 // Gets the registry entries to register an application as a handler for a | |
481 // particular file extension. |prog_id| is the ProgId used by Windows for the | |
482 // application. |ext| is the file extension, which must begin with a '.'. | |
483 void GetAppExtRegistrationEntries(const base::string16& prog_id, | |
484 const base::string16& ext, | |
485 ScopedVector<RegistryEntry>* entries) { | |
486 // In HKEY_CURRENT_USER\Software\Classes\EXT\OpenWithProgids, create an | |
487 // empty value with this class's ProgId. | |
488 base::string16 key_name(ShellUtil::kRegClasses); | |
489 key_name.push_back(base::FilePath::kSeparators[0]); | |
490 key_name.append(ext); | |
491 key_name.push_back(base::FilePath::kSeparators[0]); | |
492 key_name.append(ShellUtil::kRegOpenWithProgids); | |
493 entries->push_back(new RegistryEntry(key_name, prog_id, base::string16())); | |
494 } | |
495 | |
496 // This method returns a list of the registry entries required for this | |
497 // installation to be registered in the Windows shell. | |
498 // In particular: | |
499 // - App Paths | |
500 // http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121 | |
501 // - File Associations | |
502 // http://msdn.microsoft.com/en-us/library/bb166549 | |
503 // These entries need to be registered in HKLM prior to Win8. | |
504 void GetChromeAppRegistrationEntries(const base::FilePath& chrome_exe, | |
505 const base::string16& suffix, | |
506 ScopedVector<RegistryEntry>* entries) { | |
507 base::string16 app_path_key(ShellUtil::kAppPathsRegistryKey); | |
508 app_path_key.push_back(base::FilePath::kSeparators[0]); | |
509 app_path_key.append(chrome_exe.BaseName().value()); | |
510 entries->push_back(new RegistryEntry(app_path_key, chrome_exe.value())); | |
511 entries->push_back(new RegistryEntry(app_path_key, | |
512 ShellUtil::kAppPathsRegistryPathName, | |
513 chrome_exe.DirName().value())); | |
514 | |
515 const base::string16 html_prog_id(GetBrowserProgId(suffix)); | |
516 for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) { | |
517 GetAppExtRegistrationEntries( | |
518 html_prog_id, ShellUtil::kPotentialFileAssociations[i], entries); | |
519 } | |
520 } | |
521 | |
522 // Gets the registry entries to register an application as the default handler | |
523 // for a particular file extension. |prog_id| is the ProgId used by Windows for | |
524 // the application. |ext| is the file extension, which must begin with a '.'. If | |
525 // |overwrite_existing|, always sets the default handler; otherwise only sets if | |
526 // there is no existing default. | |
527 // | |
528 // This has no effect on Windows 8. Windows 8 ignores the default and lets the | |
529 // user choose. If there is only one handler for a file, it will automatically | |
530 // become the default. Otherwise, the first time the user opens a file, they are | |
531 // presented with the dialog to set the default handler. (This is roughly | |
532 // equivalent to being called with |overwrite_existing| false.) | |
533 void GetAppDefaultRegistrationEntries(const base::string16& prog_id, | |
534 const base::string16& ext, | |
535 bool overwrite_existing, | |
536 ScopedVector<RegistryEntry>* entries) { | |
537 // Set the default value of HKEY_CURRENT_USER\Software\Classes\EXT to this | |
538 // class's name. | |
539 base::string16 key_name(ShellUtil::kRegClasses); | |
540 key_name.push_back(base::FilePath::kSeparators[0]); | |
541 key_name.append(ext); | |
542 scoped_ptr<RegistryEntry> default_association( | |
543 new RegistryEntry(key_name, prog_id)); | |
544 if (overwrite_existing || | |
545 !default_association->KeyExistsInRegistry(RegistryEntry::LOOK_IN_HKCU)) { | |
546 entries->push_back(default_association.release()); | |
547 } | |
548 } | |
549 | |
550 // This method returns a list of all the user level registry entries that are | |
551 // needed to make Chromium the default handler for a protocol on XP. | |
552 void GetXPStyleUserProtocolEntries(const base::string16& protocol, | |
553 const base::string16& chrome_icon, | |
554 const base::string16& chrome_open, | |
555 ScopedVector<RegistryEntry>* entries) { | |
556 // Protocols associations. | |
557 base::string16 url_key(ShellUtil::kRegClasses); | |
558 url_key.push_back(base::FilePath::kSeparators[0]); | |
559 url_key.append(protocol); | |
560 | |
561 // This registry value tells Windows that this 'class' is a URL scheme | |
562 // so IE, explorer and other apps will route it to our handler. | |
563 // <root hkey>\Software\Classes\<protocol>\URL Protocol | |
564 entries->push_back( | |
565 new RegistryEntry(url_key, ShellUtil::kRegUrlProtocol, base::string16())); | |
566 | |
567 // <root hkey>\Software\Classes\<protocol>\DefaultIcon | |
568 base::string16 icon_key = url_key + ShellUtil::kRegDefaultIcon; | |
569 entries->push_back(new RegistryEntry(icon_key, chrome_icon)); | |
570 | |
571 // <root hkey>\Software\Classes\<protocol>\shell\open\command | |
572 base::string16 shell_key = url_key + ShellUtil::kRegShellOpen; | |
573 entries->push_back(new RegistryEntry(shell_key, chrome_open)); | |
574 | |
575 // <root hkey>\Software\Classes\<protocol>\shell\open\ddeexec | |
576 base::string16 dde_key = url_key + L"\\shell\\open\\ddeexec"; | |
577 entries->push_back(new RegistryEntry(dde_key, base::string16())); | |
578 | |
579 // <root hkey>\Software\Classes\<protocol>\shell\@ | |
580 base::string16 protocol_shell_key = url_key + ShellUtil::kRegShellPath; | |
581 entries->push_back(new RegistryEntry(protocol_shell_key, L"open")); | |
582 } | |
583 | |
584 // This method returns a list of all the user level registry entries that are | |
585 // needed to make Chromium default browser on XP. Some of these entries are | |
586 // irrelevant in recent versions of Windows, but we register them anyways as | |
587 // some legacy apps are hardcoded to lookup those values. | |
588 void GetXPStyleDefaultBrowserUserEntries(BrowserDistribution* dist, | |
589 const base::FilePath& chrome_exe, | |
590 const base::string16& suffix, | |
591 ScopedVector<RegistryEntry>* entries) { | |
592 // File extension associations. | |
593 base::string16 html_prog_id(GetBrowserProgId(suffix)); | |
594 for (int i = 0; ShellUtil::kDefaultFileAssociations[i] != NULL; i++) { | |
595 GetAppDefaultRegistrationEntries( | |
596 html_prog_id, ShellUtil::kDefaultFileAssociations[i], true, entries); | |
597 } | |
598 | |
599 // Protocols associations. | |
600 base::string16 chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe); | |
601 base::string16 chrome_icon = ShellUtil::FormatIconLocation( | |
602 chrome_exe, dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME)); | |
603 for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) { | |
604 GetXPStyleUserProtocolEntries(ShellUtil::kBrowserProtocolAssociations[i], | |
605 chrome_icon, chrome_open, entries); | |
606 } | |
607 | |
608 // start->Internet shortcut. | |
609 base::string16 start_menu(ShellUtil::kRegStartMenuInternet); | |
610 base::string16 app_name = dist->GetBaseAppName() + suffix; | |
611 entries->push_back(new RegistryEntry(start_menu, app_name)); | |
612 } | |
613 | |
614 // Checks that all |entries| are present on this computer (or absent if their | 137 // Checks that all |entries| are present on this computer (or absent if their |
615 // |removal_flag_| is set). |look_for_in| is passed to | 138 // |removal_flag_| is set). |look_for_in| is passed to |
616 // RegistryEntry::ExistsInRegistry(). Documentation for it can be found there. | 139 // RegistryEntry::ExistsInRegistry(). Documentation for it can be found there. |
617 bool AreEntriesAsDesired(const ScopedVector<RegistryEntry>& entries, | 140 bool AreEntriesAsDesired(const ScopedVector<RegistryEntry>& entries, |
618 uint32_t look_for_in) { | 141 uint32_t look_for_in) { |
619 for (const auto* entry : entries) { | 142 for (const auto* entry : entries) { |
620 if (entry->ExistsInRegistry(look_for_in) != !entry->IsFlaggedForRemoval()) | 143 if (entry->ExistsInRegistry(look_for_in) != !entry->IsFlaggedForRemoval()) |
621 return false; | 144 return false; |
622 } | 145 } |
623 return true; | 146 return true; |
624 } | 147 } |
625 | 148 |
626 // Checks that all required registry entries for Chrome are already present on | 149 // Checks that all required registry entries for Chrome are already present on |
627 // this computer (or absent if their |removal_flag_| is set). | 150 // this computer (or absent if their |removal_flag_| is set). |
628 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. | 151 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. |
629 // Note: between r133333 and r154145 we were registering parts of Chrome in HKCU | 152 // Note: between r133333 and r154145 we were registering parts of Chrome in HKCU |
630 // and parts in HKLM for user-level installs; we now always register everything | 153 // and parts in HKLM for user-level installs; we now always register everything |
631 // under a single registry root. Not doing so caused http://crbug.com/144910 for | 154 // under a single registry root. Not doing so caused http://crbug.com/144910 for |
632 // users who first-installed Chrome in that revision range (those users are | 155 // users who first-installed Chrome in that revision range (those users are |
633 // still impacted by http://crbug.com/144910). This method will keep returning | 156 // still impacted by http://crbug.com/144910). This method will keep returning |
634 // true for affected users (i.e. who have all the registrations, but over both | 157 // true for affected users (i.e. who have all the registrations, but over both |
635 // registry roots). | 158 // registry roots). |
636 bool IsChromeRegistered(BrowserDistribution* dist, | 159 bool IsChromeRegistered(BrowserDistribution* dist, |
637 const base::FilePath& chrome_exe, | 160 const base::FilePath& chrome_exe, |
638 const base::string16& suffix, | 161 const base::string16& suffix, |
639 uint32_t look_for_in) { | 162 uint32_t look_for_in) { |
640 ScopedVector<RegistryEntry> entries; | 163 ScopedVector<RegistryEntry> entries; |
641 GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries); | 164 installer_util::GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries); |
642 GetShellIntegrationEntries(dist, chrome_exe, suffix, &entries); | 165 installer_util::GetShellIntegrationEntries(dist, chrome_exe, suffix, |
643 GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries); | 166 &entries); |
| 167 installer_util::GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries); |
644 return AreEntriesAsDesired(entries, look_for_in); | 168 return AreEntriesAsDesired(entries, look_for_in); |
645 } | 169 } |
646 | 170 |
647 // This method checks if Chrome is already registered on the local machine | 171 // This method checks if Chrome is already registered on the local machine |
648 // for the requested protocol. It just checks the one value required for this. | 172 // for the requested protocol. It just checks the one value required for this. |
649 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. | 173 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. |
650 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, | 174 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, |
651 const base::string16& suffix, | 175 const base::string16& suffix, |
652 const base::string16& protocol, | 176 const base::string16& protocol, |
653 uint32_t look_for_in) { | 177 uint32_t look_for_in) { |
654 ScopedVector<RegistryEntry> entries; | 178 ScopedVector<RegistryEntry> entries; |
655 GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); | 179 installer_util::GetProtocolCapabilityEntries(dist, suffix, protocol, |
| 180 &entries); |
656 return AreEntriesAsDesired(entries, look_for_in); | 181 return AreEntriesAsDesired(entries, look_for_in); |
657 } | 182 } |
658 | 183 |
659 // This method registers Chrome on Vista by launching an elevated setup.exe. | 184 // This method registers Chrome on Vista by launching an elevated setup.exe. |
660 // That will show the user the standard Vista elevation prompt. If the user | 185 // That will show the user the standard Vista elevation prompt. If the user |
661 // accepts it the new process will make the necessary changes and return SUCCESS | 186 // accepts it the new process will make the necessary changes and return SUCCESS |
662 // that we capture and return. | 187 // that we capture and return. |
663 // If protocol is non-empty we will also register Chrome as being capable of | 188 // If protocol is non-empty we will also register Chrome as being capable of |
664 // handling the protocol. | 189 // handling the protocol. |
665 bool ElevateAndRegisterChrome(BrowserDistribution* dist, | 190 bool ElevateAndRegisterChrome(BrowserDistribution* dist, |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
766 case CONFIRM_PROGID_REGISTRATION: | 291 case CONFIRM_PROGID_REGISTRATION: |
767 // Software\Classes\ChromeHTML|suffix| | 292 // Software\Classes\ChromeHTML|suffix| |
768 reg_key = ShellUtil::kRegClasses; | 293 reg_key = ShellUtil::kRegClasses; |
769 reg_key.push_back(base::FilePath::kSeparators[0]); | 294 reg_key.push_back(base::FilePath::kSeparators[0]); |
770 reg_key.append(dist->GetBrowserProgIdPrefix()); | 295 reg_key.append(dist->GetBrowserProgIdPrefix()); |
771 reg_key.append(suffix); | 296 reg_key.append(suffix); |
772 break; | 297 break; |
773 case CONFIRM_SHELL_REGISTRATION: | 298 case CONFIRM_SHELL_REGISTRATION: |
774 case CONFIRM_SHELL_REGISTRATION_IN_HKLM: | 299 case CONFIRM_SHELL_REGISTRATION_IN_HKLM: |
775 // Software\Clients\StartMenuInternet\Google Chrome|suffix| | 300 // Software\Clients\StartMenuInternet\Google Chrome|suffix| |
776 reg_key = GetBrowserClientKey(dist, suffix); | 301 reg_key = installer_util::GetBrowserClientKey(dist, suffix); |
777 break; | 302 break; |
778 default: | 303 default: |
779 NOTREACHED(); | 304 NOTREACHED(); |
780 break; | 305 break; |
781 } | 306 } |
782 reg_key.append(ShellUtil::kRegShellOpen); | 307 reg_key.append(ShellUtil::kRegShellOpen); |
783 | 308 |
784 // ProgId registrations are allowed to reside in HKCU for user-level installs | 309 // ProgId registrations are allowed to reside in HKCU for user-level installs |
785 // (and values there have priority over values in HKLM). The same is true for | 310 // (and values there have priority over values in HKLM). The same is true for |
786 // shell integration entries as of Windows 8. | 311 // shell integration entries as of Windows 8. |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 } | 373 } |
849 | 374 |
850 // Associates Chrome with supported protocols and file associations. This should | 375 // Associates Chrome with supported protocols and file associations. This should |
851 // not be required on Vista+ but since some applications still read | 376 // not be required on Vista+ but since some applications still read |
852 // Software\Classes\http key directly, we have to do this on Vista+ as well. | 377 // Software\Classes\http key directly, we have to do this on Vista+ as well. |
853 bool RegisterChromeAsDefaultXPStyle(BrowserDistribution* dist, | 378 bool RegisterChromeAsDefaultXPStyle(BrowserDistribution* dist, |
854 int shell_change, | 379 int shell_change, |
855 const base::FilePath& chrome_exe) { | 380 const base::FilePath& chrome_exe) { |
856 bool ret = true; | 381 bool ret = true; |
857 ScopedVector<RegistryEntry> entries; | 382 ScopedVector<RegistryEntry> entries; |
858 GetXPStyleDefaultBrowserUserEntries( | 383 installer_util::GetXPStyleDefaultBrowserUserEntries( |
859 dist, chrome_exe, | 384 dist, chrome_exe, |
860 ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe), &entries); | 385 ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe), &entries); |
861 | 386 |
862 // Change the default browser for current user. | 387 // Change the default browser for current user. |
863 if ((shell_change & ShellUtil::CURRENT_USER) && | 388 if ((shell_change & ShellUtil::CURRENT_USER) && |
864 !ShellUtil::AddRegistryEntries(HKEY_CURRENT_USER, entries)) { | 389 !ShellUtil::AddRegistryEntries(HKEY_CURRENT_USER, entries)) { |
865 ret = false; | 390 ret = false; |
866 LOG(ERROR) << "Could not make Chrome default browser (XP/current user)."; | 391 LOG(ERROR) << "Could not make Chrome default browser (XP/current user)."; |
867 } | 392 } |
868 | 393 |
(...skipping 15 matching lines...) Expand all Loading... |
884 BrowserDistribution* dist, | 409 BrowserDistribution* dist, |
885 const base::FilePath& chrome_exe, | 410 const base::FilePath& chrome_exe, |
886 const base::string16& protocol) { | 411 const base::string16& protocol) { |
887 ScopedVector<RegistryEntry> entries; | 412 ScopedVector<RegistryEntry> entries; |
888 const base::string16 chrome_open( | 413 const base::string16 chrome_open( |
889 ShellUtil::GetChromeShellOpenCmd(chrome_exe)); | 414 ShellUtil::GetChromeShellOpenCmd(chrome_exe)); |
890 const base::string16 chrome_icon( | 415 const base::string16 chrome_icon( |
891 ShellUtil::FormatIconLocation( | 416 ShellUtil::FormatIconLocation( |
892 chrome_exe, | 417 chrome_exe, |
893 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME))); | 418 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME))); |
894 GetXPStyleUserProtocolEntries(protocol, chrome_icon, chrome_open, &entries); | 419 installer_util::GetXPStyleUserProtocolEntries(protocol, chrome_icon, |
| 420 chrome_open, &entries); |
895 // Change the default protocol handler for current user. | 421 // Change the default protocol handler for current user. |
896 if (!ShellUtil::AddRegistryEntries(HKEY_CURRENT_USER, entries)) { | 422 if (!ShellUtil::AddRegistryEntries(HKEY_CURRENT_USER, entries)) { |
897 LOG(ERROR) << "Could not make Chrome default protocol client (XP)."; | 423 LOG(ERROR) << "Could not make Chrome default protocol client (XP)."; |
898 return false; | 424 return false; |
899 } | 425 } |
900 | 426 |
901 return true; | 427 return true; |
902 } | 428 } |
903 | 429 |
904 // Returns |properties.shortcut_name| if the property is set, otherwise it | 430 // Returns |properties.shortcut_name| if the property is set, otherwise it |
(...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1625 if (key.Open(root, client_path.c_str(), | 1151 if (key.Open(root, client_path.c_str(), |
1626 KEY_QUERY_VALUE) != ERROR_SUCCESS || | 1152 KEY_QUERY_VALUE) != ERROR_SUCCESS || |
1627 key.ReadValue(NULL, &name) != ERROR_SUCCESS || | 1153 key.ReadValue(NULL, &name) != ERROR_SUCCESS || |
1628 name.empty() || | 1154 name.empty() || |
1629 name.find(dist->GetBaseAppName()) != base::string16::npos) { | 1155 name.find(dist->GetBaseAppName()) != base::string16::npos) { |
1630 continue; | 1156 continue; |
1631 } | 1157 } |
1632 // Read the browser's reinstall command. | 1158 // Read the browser's reinstall command. |
1633 if (key.Open(root, (client_path + L"\\InstallInfo").c_str(), | 1159 if (key.Open(root, (client_path + L"\\InstallInfo").c_str(), |
1634 KEY_QUERY_VALUE) == ERROR_SUCCESS && | 1160 KEY_QUERY_VALUE) == ERROR_SUCCESS && |
1635 key.ReadValue(kReinstallCommand, &command) == ERROR_SUCCESS && | 1161 key.ReadValue(installer_util::kReinstallCommand, &command) == |
| 1162 ERROR_SUCCESS && |
1636 !command.empty()) { | 1163 !command.empty()) { |
1637 (*browsers)[name] = command; | 1164 (*browsers)[name] = command; |
1638 } | 1165 } |
1639 } | 1166 } |
1640 } | 1167 } |
1641 } | 1168 } |
1642 | 1169 |
1643 base::string16 ShellUtil::GetCurrentInstallationSuffix( | 1170 base::string16 ShellUtil::GetCurrentInstallationSuffix( |
1644 BrowserDistribution* dist, | 1171 BrowserDistribution* dist, |
1645 const base::FilePath& chrome_exe) { | 1172 const base::FilePath& chrome_exe) { |
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2032 // Check if chrome is already registered with this suffix. | 1559 // Check if chrome is already registered with this suffix. |
2033 if (IsChromeRegistered(dist, chrome_exe, suffix, look_for_in)) | 1560 if (IsChromeRegistered(dist, chrome_exe, suffix, look_for_in)) |
2034 return true; | 1561 return true; |
2035 | 1562 |
2036 bool result = true; | 1563 bool result = true; |
2037 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { | 1564 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { |
2038 // Do the full registration if we can do it at user-level or if the user is | 1565 // Do the full registration if we can do it at user-level or if the user is |
2039 // an admin. | 1566 // an admin. |
2040 ScopedVector<RegistryEntry> progid_and_appreg_entries; | 1567 ScopedVector<RegistryEntry> progid_and_appreg_entries; |
2041 ScopedVector<RegistryEntry> shell_entries; | 1568 ScopedVector<RegistryEntry> shell_entries; |
2042 GetChromeProgIdEntries(dist, chrome_exe, suffix, | 1569 installer_util::GetChromeProgIdEntries(dist, chrome_exe, suffix, |
2043 &progid_and_appreg_entries); | 1570 &progid_and_appreg_entries); |
2044 GetChromeAppRegistrationEntries(chrome_exe, suffix, | 1571 installer_util::GetChromeAppRegistrationEntries(chrome_exe, suffix, |
2045 &progid_and_appreg_entries); | 1572 &progid_and_appreg_entries); |
2046 GetShellIntegrationEntries(dist, chrome_exe, suffix, &shell_entries); | 1573 installer_util::GetShellIntegrationEntries(dist, chrome_exe, suffix, |
| 1574 &shell_entries); |
2047 result = (AddRegistryEntries(root, progid_and_appreg_entries) && | 1575 result = (AddRegistryEntries(root, progid_and_appreg_entries) && |
2048 AddRegistryEntries(root, shell_entries)); | 1576 AddRegistryEntries(root, shell_entries)); |
2049 } else if (elevate_if_not_admin && | 1577 } else if (elevate_if_not_admin && |
2050 base::win::GetVersion() >= base::win::VERSION_VISTA && | 1578 base::win::GetVersion() >= base::win::VERSION_VISTA && |
2051 ElevateAndRegisterChrome(dist, chrome_exe, suffix, base::string16())) { | 1579 ElevateAndRegisterChrome(dist, chrome_exe, suffix, base::string16())) { |
2052 // If the user is not an admin and OS is between Vista and Windows 7 | 1580 // If the user is not an admin and OS is between Vista and Windows 7 |
2053 // inclusively, try to elevate and register. This is only intended for | 1581 // inclusively, try to elevate and register. This is only intended for |
2054 // user-level installs as system-level installs should always be run with | 1582 // user-level installs as system-level installs should always be run with |
2055 // admin rights. | 1583 // admin rights. |
2056 result = true; | 1584 result = true; |
2057 } else { | 1585 } else { |
2058 // If we got to this point then all we can do is create ProgId and basic app | 1586 // If we got to this point then all we can do is create ProgId and basic app |
2059 // registrations under HKCU. | 1587 // registrations under HKCU. |
2060 ScopedVector<RegistryEntry> entries; | 1588 ScopedVector<RegistryEntry> entries; |
2061 GetChromeProgIdEntries(dist, chrome_exe, base::string16(), &entries); | 1589 installer_util::GetChromeProgIdEntries(dist, chrome_exe, base::string16(), |
| 1590 &entries); |
2062 // Prefer to use |suffix|; unless Chrome's ProgIds are already registered | 1591 // Prefer to use |suffix|; unless Chrome's ProgIds are already registered |
2063 // with no suffix (as per the old registration style): in which case some | 1592 // with no suffix (as per the old registration style): in which case some |
2064 // other registry entries could refer to them and since we were not able to | 1593 // other registry entries could refer to them and since we were not able to |
2065 // set our HKLM entries above, we are better off not altering these here. | 1594 // set our HKLM entries above, we are better off not altering these here. |
2066 if (!AreEntriesAsDesired(entries, RegistryEntry::LOOK_IN_HKCU)) { | 1595 if (!AreEntriesAsDesired(entries, RegistryEntry::LOOK_IN_HKCU)) { |
2067 if (!suffix.empty()) { | 1596 if (!suffix.empty()) { |
2068 entries.clear(); | 1597 entries.clear(); |
2069 GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries); | 1598 installer_util::GetChromeProgIdEntries(dist, chrome_exe, suffix, |
2070 GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries); | 1599 &entries); |
| 1600 installer_util::GetChromeAppRegistrationEntries(chrome_exe, suffix, |
| 1601 &entries); |
2071 } | 1602 } |
2072 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); | 1603 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); |
2073 } else { | 1604 } else { |
2074 // The ProgId is registered unsuffixed in HKCU, also register the app with | 1605 // The ProgId is registered unsuffixed in HKCU, also register the app with |
2075 // Windows in HKCU (this was not done in the old registration style and | 1606 // Windows in HKCU (this was not done in the old registration style and |
2076 // thus needs to be done after the above check for the unsuffixed | 1607 // thus needs to be done after the above check for the unsuffixed |
2077 // registration). | 1608 // registration). |
2078 entries.clear(); | 1609 entries.clear(); |
2079 GetChromeAppRegistrationEntries(chrome_exe, base::string16(), &entries); | 1610 installer_util::GetChromeAppRegistrationEntries( |
| 1611 chrome_exe, base::string16(), &entries); |
2080 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); | 1612 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); |
2081 } | 1613 } |
2082 } | 1614 } |
2083 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); | 1615 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); |
2084 return result; | 1616 return result; |
2085 } | 1617 } |
2086 | 1618 |
2087 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, | 1619 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, |
2088 const base::FilePath& chrome_exe, | 1620 const base::FilePath& chrome_exe, |
2089 const base::string16& unique_suffix, | 1621 const base::string16& unique_suffix, |
(...skipping 26 matching lines...) Expand all Loading... |
2116 return true; | 1648 return true; |
2117 | 1649 |
2118 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { | 1650 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { |
2119 // We can do this operation directly. | 1651 // We can do this operation directly. |
2120 // First, make sure Chrome is fully registered on this machine. | 1652 // First, make sure Chrome is fully registered on this machine. |
2121 if (!RegisterChromeBrowser(dist, chrome_exe, suffix, false)) | 1653 if (!RegisterChromeBrowser(dist, chrome_exe, suffix, false)) |
2122 return false; | 1654 return false; |
2123 | 1655 |
2124 // Write in the capabillity for the protocol. | 1656 // Write in the capabillity for the protocol. |
2125 ScopedVector<RegistryEntry> entries; | 1657 ScopedVector<RegistryEntry> entries; |
2126 GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); | 1658 installer_util::GetProtocolCapabilityEntries(dist, suffix, protocol, |
| 1659 &entries); |
2127 return AddRegistryEntries(root, entries); | 1660 return AddRegistryEntries(root, entries); |
2128 } else if (elevate_if_not_admin && | 1661 } else if (elevate_if_not_admin && |
2129 base::win::GetVersion() >= base::win::VERSION_VISTA) { | 1662 base::win::GetVersion() >= base::win::VERSION_VISTA) { |
2130 // Elevate to do the whole job | 1663 // Elevate to do the whole job |
2131 return ElevateAndRegisterChrome(dist, chrome_exe, suffix, protocol); | 1664 return ElevateAndRegisterChrome(dist, chrome_exe, suffix, protocol); |
2132 } else { | 1665 } else { |
2133 // Admin rights are required to register capabilities before Windows 8. | 1666 // Admin rights are required to register capabilities before Windows 8. |
2134 return false; | 1667 return false; |
2135 } | 1668 } |
2136 } | 1669 } |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2269 // static | 1802 // static |
2270 bool ShellUtil::AddFileAssociations( | 1803 bool ShellUtil::AddFileAssociations( |
2271 const base::string16& prog_id, | 1804 const base::string16& prog_id, |
2272 const base::CommandLine& command_line, | 1805 const base::CommandLine& command_line, |
2273 const base::string16& file_type_name, | 1806 const base::string16& file_type_name, |
2274 const base::FilePath& icon_path, | 1807 const base::FilePath& icon_path, |
2275 const std::set<base::string16>& file_extensions) { | 1808 const std::set<base::string16>& file_extensions) { |
2276 ScopedVector<RegistryEntry> entries; | 1809 ScopedVector<RegistryEntry> entries; |
2277 | 1810 |
2278 // Create a class for this app. | 1811 // Create a class for this app. |
2279 ApplicationInfo app_info; | 1812 installer_util::ApplicationInfo app_info; |
2280 app_info.prog_id = prog_id; | 1813 app_info.prog_id = prog_id; |
2281 app_info.file_type_name = file_type_name; | 1814 app_info.file_type_name = file_type_name; |
2282 app_info.file_type_icon_path = icon_path; | 1815 app_info.file_type_icon_path = icon_path; |
2283 app_info.file_type_icon_index = 0; | 1816 app_info.file_type_icon_index = 0; |
2284 app_info.command_line = command_line.GetCommandLineStringWithPlaceholders(); | 1817 app_info.command_line = command_line.GetCommandLineStringWithPlaceholders(); |
2285 GetProgIdEntries(app_info, &entries); | 1818 installer_util::GetProgIdEntries(app_info, &entries); |
2286 | 1819 |
2287 // Associate each extension that the app can handle with the class. Set this | 1820 // Associate each extension that the app can handle with the class. Set this |
2288 // app as the default handler if and only if there is no existing default. | 1821 // app as the default handler if and only if there is no existing default. |
2289 for (std::set<base::string16>::const_iterator it = file_extensions.begin(); | 1822 for (std::set<base::string16>::const_iterator it = file_extensions.begin(); |
2290 it != file_extensions.end(); | 1823 it != file_extensions.end(); |
2291 ++it) { | 1824 ++it) { |
2292 // Do not allow empty file extensions, or extensions beginning with a '.'. | 1825 // Do not allow empty file extensions, or extensions beginning with a '.'. |
2293 DCHECK(!it->empty()); | 1826 DCHECK(!it->empty()); |
2294 DCHECK_NE(L'.', (*it)[0]); | 1827 DCHECK_NE(L'.', (*it)[0]); |
2295 base::string16 ext(1, L'.'); | 1828 base::string16 ext(1, L'.'); |
2296 ext.append(*it); | 1829 ext.append(*it); |
2297 GetAppExtRegistrationEntries(prog_id, ext, &entries); | 1830 installer_util::GetAppExtRegistrationEntries(prog_id, ext, &entries); |
2298 | 1831 |
2299 // Regstering as the default will have no effect on Windows 8 (see | 1832 // Regstering as the default will have no effect on Windows 8 (see |
2300 // documentation for GetAppDefaultRegistrationEntries). However, if our app | 1833 // documentation for GetAppDefaultRegistrationEntries). However, if our app |
2301 // is the only handler, it will automatically become the default, so the | 1834 // is the only handler, it will automatically become the default, so the |
2302 // same effect is achieved. | 1835 // same effect is achieved. |
2303 GetAppDefaultRegistrationEntries(prog_id, ext, false, &entries); | 1836 installer_util::GetAppDefaultRegistrationEntries(prog_id, ext, false, |
| 1837 &entries); |
2304 } | 1838 } |
2305 | 1839 |
2306 return AddRegistryEntries(HKEY_CURRENT_USER, entries); | 1840 return AddRegistryEntries(HKEY_CURRENT_USER, entries); |
2307 } | 1841 } |
2308 | 1842 |
2309 // static | 1843 // static |
2310 bool ShellUtil::DeleteFileAssociations(const base::string16& prog_id) { | 1844 bool ShellUtil::DeleteFileAssociations(const base::string16& prog_id) { |
2311 // Delete the key HKEY_CURRENT_USER\Software\Classes\PROGID. | 1845 // Delete the key HKEY_CURRENT_USER\Software\Classes\PROGID. |
2312 base::string16 key_path(kRegClasses); | 1846 base::string16 key_path(kRegClasses); |
2313 key_path.push_back(base::FilePath::kSeparators[0]); | 1847 key_path.push_back(base::FilePath::kSeparators[0]); |
(...skipping 15 matching lines...) Expand all Loading... |
2329 itr != entries.end(); ++itr) | 1863 itr != entries.end(); ++itr) |
2330 (*itr)->AddToWorkItemList(root, items.get()); | 1864 (*itr)->AddToWorkItemList(root, items.get()); |
2331 | 1865 |
2332 // Apply all the registry changes and if there is a problem, rollback | 1866 // Apply all the registry changes and if there is a problem, rollback |
2333 if (!items->Do()) { | 1867 if (!items->Do()) { |
2334 items->Rollback(); | 1868 items->Rollback(); |
2335 return false; | 1869 return false; |
2336 } | 1870 } |
2337 return true; | 1871 return true; |
2338 } | 1872 } |
OLD | NEW |