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

Side by Side Diff: chrome/installer/util/shell_util.cc

Issue 10451074: Always suffix ChromeHTML entries on Windows for user-level installs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase on r142211 Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/installer/util/shell_util.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 22 matching lines...) Expand all
33 #include "chrome/common/chrome_switches.h" 33 #include "chrome/common/chrome_switches.h"
34 #include "chrome/installer/util/browser_distribution.h" 34 #include "chrome/installer/util/browser_distribution.h"
35 #include "chrome/installer/util/install_util.h" 35 #include "chrome/installer/util/install_util.h"
36 #include "chrome/installer/util/master_preferences.h" 36 #include "chrome/installer/util/master_preferences.h"
37 #include "chrome/installer/util/master_preferences_constants.h" 37 #include "chrome/installer/util/master_preferences_constants.h"
38 38
39 using base::win::RegKey; 39 using base::win::RegKey;
40 40
41 namespace { 41 namespace {
42 42
43 // An enum used to tell QuickIsChromeRegistered() which level of registration
44 // the caller wants to confirm.
45 enum RegistrationConfirmationLevel {
46 // Only look for Chrome's ProgIds.
47 // This is sufficient when we are trying to determine the suffix of the
48 // currently running Chrome as system registrations might not be present.
49 CONFIRM_PROGID_REGISTRATION = 0,
50 // Confirm that Chrome is registered on the system (i.e. registered with
51 // Defaut Programs). These registrations can be in HKCU as of Windows 8.
52 CONFIRM_SYSTEM_REGISTRATION,
53 // Same as CONFIRM_SYSTEM_REGISTRATION, but only look in HKLM (used when
54 // uninstalling to know whether elevation is required to clean up the
55 // registry).
56 CONFIRM_SYSTEM_REGISTRATION_IN_HKLM,
57 };
58
43 const wchar_t kReinstallCommand[] = L"ReinstallCommand"; 59 const wchar_t kReinstallCommand[] = L"ReinstallCommand";
44 60
45 // Returns true if Chrome Metro is supported on this OS (Win 8 8370 or greater). 61 // Returns true if Chrome Metro is supported on this OS (Win 8 8370 or greater).
46 // TODO(gab): Change this to a simple check for Win 8 once old Win8 builds 62 // TODO(gab): Change this to a simple check for Win 8 once old Win8 builds
47 // become irrelevant. 63 // become irrelevant.
48 bool IsChromeMetroSupported() { 64 bool IsChromeMetroSupported() {
49 OSVERSIONINFOEX min_version_info = {}; 65 OSVERSIONINFOEX min_version_info = {};
50 min_version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 66 min_version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
51 min_version_info.dwMajorVersion = 6; 67 min_version_info.dwMajorVersion = 6;
52 min_version_info.dwMinorVersion = 2; 68 min_version_info.dwMinorVersion = 2;
(...skipping 14 matching lines...) Expand all
67 return VerifyVersionInfo(&min_version_info, type_mask, condition_mask) != 0; 83 return VerifyVersionInfo(&min_version_info, type_mask, condition_mask) != 0;
68 } 84 }
69 85
70 // This class represents a single registry entry. The objective is to 86 // This class represents a single registry entry. The objective is to
71 // encapsulate all the registry entries required for registering Chrome at one 87 // encapsulate all the registry entries required for registering Chrome at one
72 // place. This class can not be instantiated outside the class and the objects 88 // place. This class can not be instantiated outside the class and the objects
73 // of this class type can be obtained only by calling a static method of this 89 // of this class type can be obtained only by calling a static method of this
74 // class. 90 // class.
75 class RegistryEntry { 91 class RegistryEntry {
76 public: 92 public:
93 // A bit-field enum of places to look for this key in the Windows registry.
94 enum LookForIn {
95 LOOK_IN_HKCU = 1 << 0,
96 LOOK_IN_HKLM = 1 << 1,
97 LOOK_IN_HKCU_THEN_HKLM = LOOK_IN_HKCU | LOOK_IN_HKLM,
98 };
99
77 // Returns the Windows browser client registration key for Chrome. For 100 // Returns the Windows browser client registration key for Chrome. For
78 // example: "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly 101 // example: "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly
79 // speaking, we should use the name of the executable (e.g., "chrome.exe"), 102 // speaking, we should use the name of the executable (e.g., "chrome.exe"),
80 // but that ship has sailed. The cost of switching now is re-prompting users 103 // but that ship has sailed. The cost of switching now is re-prompting users
81 // to make Chrome their default browser, which isn't polite. |suffix| is the 104 // to make Chrome their default browser, which isn't polite. |suffix| is the
82 // user-specific registration suffix; see GetUserSpecificDefaultBrowserSuffix 105 // user-specific registration suffix; see GetUserSpecificDefaultBrowserSuffix
83 // in shell_util.h for details. 106 // in shell_util.h for details.
84 static string16 GetBrowserClientKey(BrowserDistribution* dist, 107 static string16 GetBrowserClientKey(BrowserDistribution* dist,
85 const string16& suffix) { 108 const string16& suffix) {
86 DCHECK(suffix.empty() || suffix[0] == L'.'); 109 DCHECK(suffix.empty() || suffix[0] == L'.');
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 // strings. 266 // strings.
244 entries->push_front(new RegistryEntry(install_info, kReinstallCommand, 267 entries->push_front(new RegistryEntry(install_info, kReinstallCommand,
245 quoted_exe_path + L" --" + ASCIIToWide(switches::kMakeDefaultBrowser))); 268 quoted_exe_path + L" --" + ASCIIToWide(switches::kMakeDefaultBrowser)));
246 entries->push_front(new RegistryEntry(install_info, L"HideIconsCommand", 269 entries->push_front(new RegistryEntry(install_info, L"HideIconsCommand",
247 quoted_exe_path + L" --" + ASCIIToWide(switches::kHideIcons))); 270 quoted_exe_path + L" --" + ASCIIToWide(switches::kHideIcons)));
248 entries->push_front(new RegistryEntry(install_info, L"ShowIconsCommand", 271 entries->push_front(new RegistryEntry(install_info, L"ShowIconsCommand",
249 quoted_exe_path + L" --" + ASCIIToWide(switches::kShowIcons))); 272 quoted_exe_path + L" --" + ASCIIToWide(switches::kShowIcons)));
250 entries->push_front(new RegistryEntry(install_info, L"IconsVisible", 1)); 273 entries->push_front(new RegistryEntry(install_info, L"IconsVisible", 1));
251 274
252 // Register with Default Programs. 275 // Register with Default Programs.
253 string16 app_name(dist->GetApplicationName().append(suffix)); 276 string16 reg_app_name(dist->GetApplicationName().append(suffix));
254 // Tell Windows where to find Chrome's Default Programs info. 277 // Tell Windows where to find Chrome's Default Programs info.
255 string16 capabilities(GetCapabilitiesKey(dist, suffix)); 278 string16 capabilities(GetCapabilitiesKey(dist, suffix));
256 entries->push_front(new RegistryEntry(ShellUtil::kRegRegisteredApplications, 279 entries->push_front(new RegistryEntry(ShellUtil::kRegRegisteredApplications,
257 app_name, capabilities)); 280 reg_app_name, capabilities));
258 // Write out Chrome's Default Programs info. 281 // Write out Chrome's Default Programs info.
259 // TODO(grt): http://crbug.com/75152 Write a reference to a localized 282 // TODO(grt): http://crbug.com/75152 Write a reference to a localized
260 // resource rather than this. 283 // resource rather than this.
261 entries->push_front(new RegistryEntry( 284 entries->push_front(new RegistryEntry(
262 capabilities, ShellUtil::kRegApplicationDescription, 285 capabilities, ShellUtil::kRegApplicationDescription,
263 dist->GetLongAppDescription())); 286 dist->GetLongAppDescription()));
264 entries->push_front(new RegistryEntry( 287 entries->push_front(new RegistryEntry(
265 capabilities, ShellUtil::kRegApplicationIcon, icon_path)); 288 capabilities, ShellUtil::kRegApplicationIcon, icon_path));
266 entries->push_front(new RegistryEntry( 289 entries->push_front(new RegistryEntry(
267 capabilities, ShellUtil::kRegApplicationName, app_name)); 290 capabilities, ShellUtil::kRegApplicationName,
291 dist->GetAppShortCutName()));
268 292
269 entries->push_front(new RegistryEntry(capabilities + L"\\Startmenu", 293 entries->push_front(new RegistryEntry(capabilities + L"\\Startmenu",
270 L"StartMenuInternet", app_name)); 294 L"StartMenuInternet", reg_app_name));
271 295
272 string16 html_prog_id(ShellUtil::kChromeHTMLProgId); 296 string16 html_prog_id(ShellUtil::kChromeHTMLProgId);
273 html_prog_id.append(suffix); 297 html_prog_id.append(suffix);
274 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { 298 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
275 entries->push_front(new RegistryEntry( 299 entries->push_front(new RegistryEntry(
276 capabilities + L"\\FileAssociations", 300 capabilities + L"\\FileAssociations",
277 ShellUtil::kFileAssociations[i], html_prog_id)); 301 ShellUtil::kFileAssociations[i], html_prog_id));
278 } 302 }
279 for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL; 303 for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL;
280 i++) { 304 i++) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 if (_is_string) { 394 if (_is_string) {
371 items->AddSetRegValueWorkItem(root, _key_path, _name, _value, true); 395 items->AddSetRegValueWorkItem(root, _key_path, _name, _value, true);
372 } else { 396 } else {
373 items->AddSetRegValueWorkItem(root, _key_path, _name, _int_value, true); 397 items->AddSetRegValueWorkItem(root, _key_path, _name, _int_value, true);
374 } 398 }
375 } 399 }
376 400
377 // Checks if the current registry entry exists in HKCU\|_key_path|\|_name| 401 // Checks if the current registry entry exists in HKCU\|_key_path|\|_name|
378 // and value is |_value|. If the key does NOT exist in HKCU, checks for 402 // and value is |_value|. If the key does NOT exist in HKCU, checks for
379 // the correct name and value in HKLM. 403 // the correct name and value in HKLM.
380 // This mimics Windows' behavior when searching in HKCR (HKCU takes precedence 404 // |look_for_in| specifies roots (HKCU and/or HKLM) in which to look for the
381 // over HKLM). For registrations outside of HKCR on versions of Windows up 405 // key, unspecified roots are not looked into (i.e. the the key is assumed not
382 // to Win7, Chrome's values go in HKLM. This function will make unnecessary 406 // to exist in them).
383 // (but harmless) queries into HKCU in that case. Starting with Windows 8, 407 // |look_for_in| must at least specify one root to look into.
384 // Chrome's values go in HKCU for user-level installs, which takes precedence 408 // If |look_for_in| is LOOK_IN_HKCU_THEN_HKLM, this method mimics Windows'
385 // over HKLM. 409 // behavior when searching in HKCR (HKCU takes precedence over HKLM). For
386 bool ExistsInRegistry() { 410 // registrations outside of HKCR on versions of Windows prior to Win8,
387 RegistryStatus hkcu_status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER); 411 // Chrome's values go in HKLM. This function will make unnecessary (but
388 return (hkcu_status == SAME_VALUE || 412 // harmless) queries into HKCU in that case.
389 (hkcu_status == DOES_NOT_EXIST && 413 bool ExistsInRegistry(uint32 look_for_in) const {
390 StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE) == SAME_VALUE)); 414 DCHECK(look_for_in);
415
416 RegistryStatus status = DOES_NOT_EXIST;
417 if (look_for_in & LOOK_IN_HKCU)
418 status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER);
419 if (status == DOES_NOT_EXIST && (look_for_in & LOOK_IN_HKLM))
420 status = StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE);
421 return status == SAME_VALUE;
391 } 422 }
392 423
393 private: 424 private:
394 // States this RegistryKey can be in compared to the registry. 425 // States this RegistryKey can be in compared to the registry.
395 enum RegistryStatus { 426 enum RegistryStatus {
396 // |_name| does not exist in the registry 427 // |_name| does not exist in the registry
397 DOES_NOT_EXIST, 428 DOES_NOT_EXIST,
398 // |_name| exists, but its value != |_value| 429 // |_name| exists, but its value != |_value|
399 DIFFERENT_VALUE, 430 DIFFERENT_VALUE,
400 // |_name| exists and its value is |_value| 431 // |_name| exists and its value is |_value|
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 495
465 // Apply all the registry changes and if there is a problem, rollback 496 // Apply all the registry changes and if there is a problem, rollback
466 if (!items->Do()) { 497 if (!items->Do()) {
467 items->Rollback(); 498 items->Rollback();
468 return false; 499 return false;
469 } 500 }
470 return true; 501 return true;
471 } 502 }
472 503
473 // Checks that all |entries| are present on this computer. 504 // Checks that all |entries| are present on this computer.
474 bool AreEntriesRegistered(const std::list<RegistryEntry*>& entries) { 505 // |look_for_in| is passed to RegistryEntry::ExistsInRegistry(). Documentation
506 // for it can be found there.
507 bool AreEntriesRegistered(const std::list<RegistryEntry*>& entries,
508 uint32 look_for_in) {
475 bool registered = true; 509 bool registered = true;
476 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin(); 510 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin();
477 registered && itr != entries.end(); ++itr) { 511 registered && itr != entries.end(); ++itr) {
478 // We do not need registered = registered && ... since the loop condition 512 // We do not need registered = registered && ... since the loop condition
479 // is set to exit early. 513 // is set to exit early.
480 registered = (*itr)->ExistsInRegistry(); 514 registered = (*itr)->ExistsInRegistry(look_for_in);
481 } 515 }
482 return registered; 516 return registered;
483 } 517 }
484 518
485 // Checks that all required registry entries for Chrome are already present 519 // Checks that all required registry entries for Chrome are already present
486 // on this computer. 520 // on this computer.
487 bool IsChromeRegistered(BrowserDistribution* dist, 521 bool IsChromeRegistered(BrowserDistribution* dist,
488 const string16& chrome_exe, 522 const string16& chrome_exe,
489 const string16& suffix) { 523 const string16& suffix) {
490 std::list<RegistryEntry*> entries; 524 std::list<RegistryEntry*> entries;
491 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); 525 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries);
492 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries); 526 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries);
493 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries); 527 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries);
494 return AreEntriesRegistered(entries); 528 return AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU_THEN_HKLM);
495 } 529 }
496 530
497 // This method checks if Chrome is already registered on the local machine 531 // This method checks if Chrome is already registered on the local machine
498 // for the requested protocol. It just checks the one value required for this. 532 // for the requested protocol. It just checks the one value required for this.
499 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, 533 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist,
500 const string16& suffix, 534 const string16& suffix,
501 const string16& protocol) { 535 const string16& protocol) {
502 std::list<RegistryEntry*> entries; 536 std::list<RegistryEntry*> entries;
503 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); 537 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries);
504 RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); 538 RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, &entries);
505 return AreEntriesRegistered(entries); 539 return AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU_THEN_HKLM);
506 } 540 }
507 541
508 // This method registers Chrome on Vista by launching an elevated setup.exe. 542 // This method registers Chrome on Vista by launching an elevated setup.exe.
509 // That will show the user the standard Vista elevation prompt. If the user 543 // That will show the user the standard Vista elevation prompt. If the user
510 // accepts it the new process will make the necessary changes and return SUCCESS 544 // accepts it the new process will make the necessary changes and return SUCCESS
511 // that we capture and return. 545 // that we capture and return.
512 // If protocol is non-empty we will also register Chrome as being capable of 546 // If protocol is non-empty we will also register Chrome as being capable of
513 // handling the protocol. 547 // handling the protocol.
514 bool ElevateAndRegisterChrome(BrowserDistribution* dist, 548 bool ElevateAndRegisterChrome(BrowserDistribution* dist,
515 const string16& chrome_exe, 549 const string16& chrome_exe,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 } 582 }
549 583
550 DWORD ret_val = 0; 584 DWORD ret_val = 0;
551 InstallUtil::ExecuteExeAsAdmin(cmd, &ret_val); 585 InstallUtil::ExecuteExeAsAdmin(cmd, &ret_val);
552 if (ret_val == 0) 586 if (ret_val == 0)
553 return true; 587 return true;
554 } 588 }
555 return false; 589 return false;
556 } 590 }
557 591
558 // This method tries to figure out if another user has already registered her
559 // own copy of Chrome so that we can avoid overwriting it and append current
560 // user's login name to default browser registry entries. This function is
561 // not meant to detect all cases. It just tries to handle the most common case.
562 // All the conditions below have to be true for it to return true:
563 // - Software\Clients\StartMenuInternet\Chromium\"" key should have a valid
564 // value.
565 // - The value should not be same as given value in |chrome_exe|
566 // - Finally to handle the default install path (C:\Document and Settings\
567 // <user>\Local Settings\Application Data\Chromium\Application) the value
568 // of the above key should differ from |chrome_exe| only in user name.
569 bool AnotherUserHasDefaultBrowser(BrowserDistribution* dist,
570 const string16& chrome_exe) {
571 const string16 reg_key(
572 RegistryEntry::GetBrowserClientKey(dist, string16())
573 .append(ShellUtil::kRegShellOpen));
574 RegKey key(HKEY_LOCAL_MACHINE, reg_key.c_str(), KEY_READ);
575 string16 registry_chrome_exe;
576 if ((key.ReadValue(L"", &registry_chrome_exe) != ERROR_SUCCESS) ||
577 registry_chrome_exe.length() < 2)
578 return false;
579
580 registry_chrome_exe = registry_chrome_exe.substr(1,
581 registry_chrome_exe.length() - 2);
582 if ((registry_chrome_exe.size() == chrome_exe.size()) &&
583 (std::equal(chrome_exe.begin(), chrome_exe.end(),
584 registry_chrome_exe.begin(),
585 base::CaseInsensitiveCompare<wchar_t>()))) {
586 return false;
587 }
588
589 std::vector<string16> v1, v2;
590 base::SplitString(registry_chrome_exe, L'\\', &v1);
591 base::SplitString(chrome_exe, L'\\', &v2);
592 if (v1.empty() || v2.empty() || v1.size() != v2.size())
593 return false;
594
595 // Now check that only one of the values within two '\' chars differ.
596 std::vector<string16>::iterator itr1 = v1.begin();
597 std::vector<string16>::iterator itr2 = v2.begin();
598 bool one_mismatch = false;
599 for ( ; itr1 < v1.end() && itr2 < v2.end(); ++itr1, ++itr2) {
600 string16 s1 = *itr1;
601 string16 s2 = *itr2;
602 if ((s1.size() != s2.size()) ||
603 (!std::equal(s1.begin(), s1.end(),
604 s2.begin(), base::CaseInsensitiveCompare<wchar_t>()))) {
605 if (one_mismatch)
606 return false;
607 else
608 one_mismatch = true;
609 }
610 }
611 return true;
612 }
613
614 // Launches the Windows 7 and Windows 8 dialog for picking the application to 592 // Launches the Windows 7 and Windows 8 dialog for picking the application to
615 // handle the given protocol. Most importantly, this is used to set the default 593 // handle the given protocol. Most importantly, this is used to set the default
616 // handler for http (and, implicitly with it, https). In that case it is also 594 // handler for http (and, implicitly with it, https). In that case it is also
617 // known as the 'how do you want to open webpages' dialog. 595 // known as the 'how do you want to open webpages' dialog.
618 // It is required that Chrome be already *registered* for the given protocol. 596 // It is required that Chrome be already *registered* for the given protocol.
619 bool LaunchSelectDefaultProtocolHandlerDialog(const wchar_t* protocol) { 597 bool LaunchSelectDefaultProtocolHandlerDialog(const wchar_t* protocol) {
620 DCHECK(protocol); 598 DCHECK(protocol);
621 OPENASINFO open_as_info = {}; 599 OPENASINFO open_as_info = {};
622 open_as_info.pcszFile = protocol; 600 open_as_info.pcszFile = protocol;
623 open_as_info.oaifInFlags = 601 open_as_info.oaifInFlags =
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 // should be removed after a reasonable time, say 2012-08-01. Anyone on Win8 635 // should be removed after a reasonable time, say 2012-08-01. Anyone on Win8
658 // dev channel who hasn't been autoupdated or manually updated by then will have 636 // dev channel who hasn't been autoupdated or manually updated by then will have
659 // to uninstall and reinstall Chrome to repair. See http://crbug.com/124666 and 637 // to uninstall and reinstall Chrome to repair. See http://crbug.com/124666 and
660 // http://crbug.com/123994 for gory details. 638 // http://crbug.com/123994 for gory details.
661 // This function is also used to remove DelegateExecute verb handler 639 // This function is also used to remove DelegateExecute verb handler
662 // registrations on builds for which Metro is no longer supported. This will 640 // registrations on builds for which Metro is no longer supported. This will
663 // also become irrelevant sometime after Windows 8 RC (thus the aforementioned 641 // also become irrelevant sometime after Windows 8 RC (thus the aforementioned
664 // removal date remains correct). 642 // removal date remains correct).
665 void RemoveBadWindows8RegistrationIfNeeded( 643 void RemoveBadWindows8RegistrationIfNeeded(
666 BrowserDistribution* dist, 644 BrowserDistribution* dist,
667 const string16& chrome_exe, 645 const string16& chrome_exe) {
668 const string16& suffix) {
669 string16 handler_guid; 646 string16 handler_guid;
670 647
671 if (dist->GetDelegateExecuteHandlerData(&handler_guid, NULL, NULL, NULL) && 648 if (dist->GetDelegateExecuteHandlerData(&handler_guid, NULL, NULL, NULL) &&
672 (!InstallUtil::HasDelegateExecuteHandler(dist, chrome_exe) || 649 (!InstallUtil::HasDelegateExecuteHandler(dist, chrome_exe) ||
673 !IsChromeMetroSupported())) { 650 !IsChromeMetroSupported())) {
674 // There's no need to rollback, so forgo the usual work item lists and just 651 // There's no need to rollback, so forgo the usual work item lists and just
675 // remove the values from the registry. 652 // remove the values from the registry.
676 const HKEY root_key = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? 653 const HKEY root_key = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ?
677 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; 654 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
655 // Use the current installation's suffix, not the about-to-be-installed
656 // suffix.
657 const string16 installation_suffix(
658 ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe));
678 const string16 app_id(dist->GetBrowserAppId()); 659 const string16 app_id(dist->GetBrowserAppId());
679 660
680 // <root hkey>\Software\Classes\<app_id> 661 // <root hkey>\Software\Classes\<app_id>
681 string16 key(ShellUtil::kRegClasses); 662 string16 key(ShellUtil::kRegClasses);
682 key.push_back(FilePath::kSeparators[0]); 663 key.push_back(FilePath::kSeparators[0]);
683 key.append(app_id); 664 key.append(app_id);
684 InstallUtil::DeleteRegistryKey(root_key, key); 665 InstallUtil::DeleteRegistryKey(root_key, key);
685 666
686 // <root hkey>\Software\Classes\ChromiumHTML[.user]\shell\open\command 667 // <root hkey>\Software\Classes\ChromiumHTML[.user]\shell\open\command
687 key = ShellUtil::kRegClasses; 668 key = ShellUtil::kRegClasses;
688 key.push_back(FilePath::kSeparators[0]); 669 key.push_back(FilePath::kSeparators[0]);
689 key.append(ShellUtil::kChromeHTMLProgId); 670 key.append(ShellUtil::kChromeHTMLProgId);
690 key.append(suffix); 671 key.append(installation_suffix);
691 key.append(ShellUtil::kRegShellOpen); 672 key.append(ShellUtil::kRegShellOpen);
692 InstallUtil::DeleteRegistryValue(root_key, key, 673 InstallUtil::DeleteRegistryValue(root_key, key,
693 ShellUtil::kRegDelegateExecute); 674 ShellUtil::kRegDelegateExecute);
694 } 675 }
695 } 676 }
696 677
678 // Returns true if the current install's |chrome_exe| has been registered with
679 // |suffix|.
680 // |confirmation_level| is the level of verification desired as described in
681 // the RegistrationConfirmationLevel enum above.
682 // |suffix| can be the empty string (this is used to support old installs
683 // where we used to not suffix user-level installs if they were the first to
684 // request the non-suffixed registry entries on the machine).
685 // NOTE: This a quick check that only validates that a single registry entry
686 // points to |chrome_exe|. This should only be used at run-time to determine
687 // how Chrome is registered, not to know whether the registration is complete
688 // at install-time (IsChromeRegistered() can be used for that).
689 bool QuickIsChromeRegistered(BrowserDistribution* dist,
690 const string16& chrome_exe,
691 const string16& suffix,
692 RegistrationConfirmationLevel confirmation_level) {
693 // Get the appropriate key to look for based on the level desired.
694 string16 reg_key;
695 switch (confirmation_level) {
696 case CONFIRM_PROGID_REGISTRATION:
697 // Software\Classes\ChromeHTML|suffix|
698 reg_key = ShellUtil::kRegClasses;
699 reg_key.push_back(FilePath::kSeparators[0]);
700 reg_key.append(ShellUtil::kChromeHTMLProgId);
701 reg_key.append(suffix);
702 break;
703 case CONFIRM_SYSTEM_REGISTRATION:
704 case CONFIRM_SYSTEM_REGISTRATION_IN_HKLM:
705 // Software\Clients\StartMenuInternet\Google Chrome|suffix|
706 reg_key = RegistryEntry::GetBrowserClientKey(dist, suffix);
707 break;
708 default:
709 NOTREACHED();
710 break;
711 }
712 reg_key.append(ShellUtil::kRegShellOpen);
713
714 // ProgId registrations are allowed to reside in HKCU for user-level installs
715 // (and values there have priority over values in HKLM). The same is true for
716 // system entries as of Windows 8.
717 if (confirmation_level == CONFIRM_PROGID_REGISTRATION ||
718 (confirmation_level == CONFIRM_SYSTEM_REGISTRATION &&
719 base::win::GetVersion() >= base::win::VERSION_WIN8)) {
720 const RegKey key_hkcu(HKEY_CURRENT_USER, reg_key.c_str(), KEY_QUERY_VALUE);
721 string16 hkcu_value;
722 // If |reg_key| is present in HKCU, assert that it points to |chrome_exe|.
723 // Otherwise, fall back on an HKLM lookup below.
724 if (key_hkcu.ReadValue(L"", &hkcu_value) == ERROR_SUCCESS) {
725 return InstallUtil::ProgramCompare(
726 FilePath(chrome_exe)).Evaluate(hkcu_value);
727 }
728 }
729
730 // Assert that |reg_key| points to |chrome_exe| in HKLM.
731 const RegKey key_hklm(HKEY_LOCAL_MACHINE, reg_key.c_str(), KEY_QUERY_VALUE);
732 string16 hklm_value;
733 if (key_hklm.ReadValue(L"", &hklm_value) == ERROR_SUCCESS) {
734 return InstallUtil::ProgramCompare(
735 FilePath(chrome_exe)).Evaluate(hklm_value);
736 }
737 return false;
738 }
739
740 // Sets |suffix| to this user's username preceded by a dot. This suffix is then
741 // meant to be added to all registration that may conflict with another
742 // user-level Chrome install.
743 // Returns true unless the OS call to retrieve the username fails.
744 bool GetUserSpecificRegistrySuffix(string16* suffix) {
745 wchar_t user_name[256];
746 DWORD size = arraysize(user_name);
747 if (::GetUserName(user_name, &size) == 0 || size < 1) {
748 PLOG(DFATAL) << "GetUserName failed";
749 return false;
750 }
751 suffix->reserve(size);
752 suffix->assign(1, L'.');
753 suffix->append(user_name, size - 1);
754 return true;
755 }
756
757 // Sets |suffix| to the current user's username, preceded by a dot, on
758 // user-level installs.
759 // To support old-style user-level installs however, |suffix| is cleared if
760 // the user currently owns the non-suffixed HKLM registrations.
761 // |suffix| is also cleared on system-level installs.
762 // |suffix| should then be appended to all Chrome properties that may conflict
763 // with other Chrome user-level installs.
764 // Returns true unless one of the underlying calls fails.
765 bool GetInstallationSpecificSuffix(BrowserDistribution* dist,
766 const string16& chrome_exe,
767 string16* suffix) {
768 if (!InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ||
769 QuickIsChromeRegistered(dist, chrome_exe, string16(),
770 CONFIRM_SYSTEM_REGISTRATION)) {
771 // No suffix on system-level installs and user-level installs already
772 // registered with no suffix.
773 suffix->clear();
774 return true;
775 } else {
776 return GetUserSpecificRegistrySuffix(suffix);
777 }
778 }
779
697 } // namespace 780 } // namespace
698 781
699 const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon"; 782 const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon";
700 const wchar_t* ShellUtil::kRegShellPath = L"\\shell"; 783 const wchar_t* ShellUtil::kRegShellPath = L"\\shell";
701 const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command"; 784 const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command";
702 const wchar_t* ShellUtil::kRegStartMenuInternet = 785 const wchar_t* ShellUtil::kRegStartMenuInternet =
703 L"Software\\Clients\\StartMenuInternet"; 786 L"Software\\Clients\\StartMenuInternet";
704 const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes"; 787 const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes";
705 const wchar_t* ShellUtil::kRegRegisteredApplications = 788 const wchar_t* ShellUtil::kRegRegisteredApplications =
706 L"Software\\RegisteredApplications"; 789 L"Software\\RegisteredApplications";
(...skipping 26 matching lines...) Expand all
733 L"ApplicationDescription"; 816 L"ApplicationDescription";
734 const wchar_t* ShellUtil::kRegApplicationName = L"ApplicationName"; 817 const wchar_t* ShellUtil::kRegApplicationName = L"ApplicationName";
735 const wchar_t* ShellUtil::kRegApplicationIcon = L"ApplicationIcon"; 818 const wchar_t* ShellUtil::kRegApplicationIcon = L"ApplicationIcon";
736 const wchar_t* ShellUtil::kRegApplicationCompany = L"ApplicationCompany"; 819 const wchar_t* ShellUtil::kRegApplicationCompany = L"ApplicationCompany";
737 const wchar_t* ShellUtil::kRegExePath = L"\\.exe"; 820 const wchar_t* ShellUtil::kRegExePath = L"\\.exe";
738 const wchar_t* ShellUtil::kRegVerbOpen = L"open"; 821 const wchar_t* ShellUtil::kRegVerbOpen = L"open";
739 const wchar_t* ShellUtil::kRegVerbRun = L"run"; 822 const wchar_t* ShellUtil::kRegVerbRun = L"run";
740 const wchar_t* ShellUtil::kRegCommand = L"command"; 823 const wchar_t* ShellUtil::kRegCommand = L"command";
741 const wchar_t* ShellUtil::kRegDelegateExecute = L"DelegateExecute"; 824 const wchar_t* ShellUtil::kRegDelegateExecute = L"DelegateExecute";
742 825
826 bool ShellUtil::QuickIsChromeRegisteredInHKLM(BrowserDistribution* dist,
827 const string16& chrome_exe,
828 const string16& suffix) {
829 return QuickIsChromeRegistered(dist, chrome_exe, suffix,
830 CONFIRM_SYSTEM_REGISTRATION_IN_HKLM);
831 }
832
743 bool ShellUtil::CreateChromeDesktopShortcut(BrowserDistribution* dist, 833 bool ShellUtil::CreateChromeDesktopShortcut(BrowserDistribution* dist,
744 const string16& chrome_exe, 834 const string16& chrome_exe,
745 const string16& description, 835 const string16& description,
746 const string16& appended_name, 836 const string16& appended_name,
747 const string16& arguments, 837 const string16& arguments,
748 const string16& icon_path, 838 const string16& icon_path,
749 int icon_index, 839 int icon_index,
750 ShellChange shell_change, 840 ShellChange shell_change,
751 uint32 options) { 841 uint32 options) {
752 string16 shortcut_name; 842 string16 shortcut_name;
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 if (key.Open(root, (client_path + L"\\InstallInfo").c_str(), 1033 if (key.Open(root, (client_path + L"\\InstallInfo").c_str(),
944 KEY_QUERY_VALUE) == ERROR_SUCCESS && 1034 KEY_QUERY_VALUE) == ERROR_SUCCESS &&
945 key.ReadValue(kReinstallCommand, &command) == ERROR_SUCCESS && 1035 key.ReadValue(kReinstallCommand, &command) == ERROR_SUCCESS &&
946 !command.empty()) { 1036 !command.empty()) {
947 (*browsers)[name] = command; 1037 (*browsers)[name] = command;
948 } 1038 }
949 } 1039 }
950 } 1040 }
951 } 1041 }
952 1042
953 bool ShellUtil::GetUserSpecificDefaultBrowserSuffix(BrowserDistribution* dist, 1043 string16 ShellUtil::GetCurrentInstallationSuffix(BrowserDistribution* dist,
954 string16* entry) { 1044 const string16& chrome_exe) {
955 wchar_t user_name[256]; 1045 string16 tested_suffix;
956 DWORD size = arraysize(user_name); 1046 if (!InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ||
957 if (::GetUserName(user_name, &size) == 0 || size < 1) 1047 !GetUserSpecificRegistrySuffix(&tested_suffix) ||
958 return false; 1048 !QuickIsChromeRegistered(dist, chrome_exe, tested_suffix,
959 entry->reserve(size); 1049 CONFIRM_PROGID_REGISTRATION)) {
960 entry->assign(1, L'.'); 1050 return string16();
961 entry->append(user_name, size - 1); 1051 }
962 1052 return tested_suffix;
963 return RegKey(HKEY_LOCAL_MACHINE,
964 RegistryEntry::GetBrowserClientKey(dist, *entry).c_str(),
965 KEY_READ).Valid();
966 } 1053 }
967 1054
968 bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist, 1055 bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist,
969 int shell_change, 1056 int shell_change,
970 const string16& chrome_exe, 1057 const string16& chrome_exe,
971 bool elevate_if_not_admin) { 1058 bool elevate_if_not_admin) {
972 if (!dist->CanSetAsDefault()) 1059 if (!dist->CanSetAsDefault())
973 return false; 1060 return false;
974 1061
975 // Windows 8 does not permit making a browser default just like that. 1062 // Windows 8 does not permit making a browser default just like that.
976 // This process needs to be routed through the system's UI. Use 1063 // This process needs to be routed through the system's UI. Use
977 // ShowMakeChromeDefaultSystemUI instead (below). 1064 // ShowMakeChromeDefaultSystemUI instead (below).
978 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { 1065 if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
979 NOTREACHED(); 1066 NOTREACHED();
980 return false; 1067 return false;
981 } 1068 }
982 1069
983 ShellUtil::RegisterChromeBrowser(dist, chrome_exe, L"", elevate_if_not_admin); 1070 if (!ShellUtil::RegisterChromeBrowser(
1071 dist, chrome_exe, string16(), elevate_if_not_admin)) {
1072 return false;
1073 }
984 1074
985 bool ret = true; 1075 bool ret = true;
986 // First use the new "recommended" way on Vista to make Chrome default 1076 // First use the new "recommended" way on Vista to make Chrome default
987 // browser. 1077 // browser.
988 string16 app_name = dist->GetApplicationName(); 1078 string16 app_name = dist->GetApplicationName();
989 string16 app_suffix; 1079 const string16 app_suffix(
990 if (ShellUtil::GetUserSpecificDefaultBrowserSuffix(dist, &app_suffix)) 1080 ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe));
991 app_name += app_suffix; 1081 app_name += app_suffix;
992 1082
993 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { 1083 if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
994 // On Windows Vista and Win7 we still can set ourselves via the 1084 // On Windows Vista and Win7 we still can set ourselves via the
995 // the IApplicationAssociationRegistration interface. 1085 // the IApplicationAssociationRegistration interface.
996 VLOG(1) << "Registering Chrome as default browser on Vista."; 1086 VLOG(1) << "Registering Chrome as default browser on Vista.";
997 base::win::ScopedComPtr<IApplicationAssociationRegistration> pAAR; 1087 base::win::ScopedComPtr<IApplicationAssociationRegistration> pAAR;
998 HRESULT hr = pAAR.CreateInstance(CLSID_ApplicationAssociationRegistration, 1088 HRESULT hr = pAAR.CreateInstance(CLSID_ApplicationAssociationRegistration,
999 NULL, CLSCTX_INPROC); 1089 NULL, CLSCTX_INPROC);
1000 if (SUCCEEDED(hr)) { 1090 if (SUCCEEDED(hr)) {
1001 for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) { 1091 for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) {
(...skipping 19 matching lines...) Expand all
1021 } 1111 }
1022 } 1112 }
1023 1113
1024 // Now use the old way to associate Chrome with supported protocols and file 1114 // Now use the old way to associate Chrome with supported protocols and file
1025 // associations. This should not be required on Vista but since some 1115 // associations. This should not be required on Vista but since some
1026 // applications still read Software\Classes\http key directly, we have to do 1116 // applications still read Software\Classes\http key directly, we have to do
1027 // this on Vista also. 1117 // this on Vista also.
1028 1118
1029 std::list<RegistryEntry*> entries; 1119 std::list<RegistryEntry*> entries;
1030 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); 1120 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries);
1031 string16 suffix; 1121 RegistryEntry::GetUserEntries(dist, chrome_exe, app_suffix, &entries);
1032 if (!GetUserSpecificDefaultBrowserSuffix(dist, &suffix))
1033 suffix = L"";
1034 RegistryEntry::GetUserEntries(dist, chrome_exe, suffix, &entries);
1035 // Change the default browser for current user. 1122 // Change the default browser for current user.
1036 if ((shell_change & ShellUtil::CURRENT_USER) && 1123 if ((shell_change & ShellUtil::CURRENT_USER) &&
1037 !AddRegistryEntries(HKEY_CURRENT_USER, entries)) { 1124 !AddRegistryEntries(HKEY_CURRENT_USER, entries)) {
1038 ret = false; 1125 ret = false;
1039 LOG(ERROR) << "Could not make Chrome default browser (XP/current user)."; 1126 LOG(ERROR) << "Could not make Chrome default browser (XP/current user).";
1040 } 1127 }
1041 1128
1042 // Chrome as default browser at system level. 1129 // Chrome as default browser at system level.
1043 if ((shell_change & ShellUtil::SYSTEM_LEVEL) && 1130 if ((shell_change & ShellUtil::SYSTEM_LEVEL) &&
1044 !AddRegistryEntries(HKEY_LOCAL_MACHINE, entries)) { 1131 !AddRegistryEntries(HKEY_LOCAL_MACHINE, entries)) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1082 // First use the new "recommended" way on Vista to make Chrome default 1169 // First use the new "recommended" way on Vista to make Chrome default
1083 // protocol handler. 1170 // protocol handler.
1084 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { 1171 if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
1085 VLOG(1) << "Registering Chrome as default handler for " << protocol 1172 VLOG(1) << "Registering Chrome as default handler for " << protocol
1086 << " on Vista."; 1173 << " on Vista.";
1087 base::win::ScopedComPtr<IApplicationAssociationRegistration> pAAR; 1174 base::win::ScopedComPtr<IApplicationAssociationRegistration> pAAR;
1088 HRESULT hr = pAAR.CreateInstance(CLSID_ApplicationAssociationRegistration, 1175 HRESULT hr = pAAR.CreateInstance(CLSID_ApplicationAssociationRegistration,
1089 NULL, CLSCTX_INPROC); 1176 NULL, CLSCTX_INPROC);
1090 if (SUCCEEDED(hr)) { 1177 if (SUCCEEDED(hr)) {
1091 string16 app_name = dist->GetApplicationName(); 1178 string16 app_name = dist->GetApplicationName();
1092 string16 suffix; 1179 app_name += ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe);
1093 if (ShellUtil::GetUserSpecificDefaultBrowserSuffix(dist, &suffix))
1094 app_name += suffix;
1095 1180
1096 hr = pAAR->SetAppAsDefault(app_name.c_str(), protocol.c_str(), 1181 hr = pAAR->SetAppAsDefault(app_name.c_str(), protocol.c_str(),
1097 AT_URLPROTOCOL); 1182 AT_URLPROTOCOL);
1098 } 1183 }
1099 if (!SUCCEEDED(hr)) { 1184 if (!SUCCEEDED(hr)) {
1100 ret = false; 1185 ret = false;
1101 LOG(ERROR) << "Could not make Chrome default protocol client (Vista):" 1186 LOG(ERROR) << "Could not make Chrome default protocol client (Vista):"
1102 << " HRESULT=" << hr << "."; 1187 << " HRESULT=" << hr << ".";
1103 } 1188 }
1104 } 1189 }
1105 1190
1106 // Now use the old way to associate Chrome with the desired protocol. This 1191 // Now use the old way to associate Chrome with the desired protocol. This
1107 // should not be required on Vista but since some applications still read 1192 // should not be required on Vista but since some applications still read
1108 // Software\Classes\http key directly, we have to do this on Vista also. 1193 // Software\Classes\http key directly, we have to do this on Vista also.
1109 1194
1110 std::list<RegistryEntry*> entries; 1195 std::list<RegistryEntry*> entries;
1111 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); 1196 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries);
1112 string16 suffix; 1197 const string16 suffix(GetCurrentInstallationSuffix(dist, chrome_exe));
1113 if (!GetUserSpecificDefaultBrowserSuffix(dist, &suffix)) 1198 const string16 chrome_open(ShellUtil::GetChromeShellOpenCmd(chrome_exe));
1114 suffix = L""; 1199 const string16 chrome_icon(ShellUtil::GetChromeIcon(dist, chrome_exe));
1115 string16 chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
1116 string16 chrome_icon = ShellUtil::GetChromeIcon(dist, chrome_exe);
1117 RegistryEntry::GetUserProtocolEntries(protocol, chrome_icon, chrome_open, 1200 RegistryEntry::GetUserProtocolEntries(protocol, chrome_icon, chrome_open,
1118 &entries); 1201 &entries);
1119 // Change the default protocol handler for current user. 1202 // Change the default protocol handler for current user.
1120 if (!AddRegistryEntries(HKEY_CURRENT_USER, entries)) { 1203 if (!AddRegistryEntries(HKEY_CURRENT_USER, entries)) {
1121 ret = false; 1204 ret = false;
1122 LOG(ERROR) << "Could not make Chrome default protocol client (XP)."; 1205 LOG(ERROR) << "Could not make Chrome default protocol client (XP).";
1123 } 1206 }
1124 1207
1125 return ret; 1208 return ret;
1126 } 1209 }
1127 1210
1128 bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist, 1211 bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist,
1129 const string16& chrome_exe, 1212 const string16& chrome_exe,
1130 const string16& unique_suffix, 1213 const string16& unique_suffix,
1131 bool elevate_if_not_admin) { 1214 bool elevate_if_not_admin) {
1132 if (!dist->CanSetAsDefault()) 1215 if (!dist->CanSetAsDefault())
1133 return false; 1216 return false;
1134 1217
1135 // First figure out we need to append a suffix to the registry entries to
1136 // make them unique.
1137 string16 suffix; 1218 string16 suffix;
1138 if (!unique_suffix.empty()) { 1219 if (!unique_suffix.empty()) {
1139 suffix = unique_suffix; 1220 suffix = unique_suffix;
1140 } else if (InstallUtil::IsPerUserInstall(chrome_exe.c_str()) && 1221 } else if (!GetInstallationSpecificSuffix(dist, chrome_exe, &suffix)) {
1141 !GetUserSpecificDefaultBrowserSuffix(dist, &suffix) && 1222 return false;
1142 !AnotherUserHasDefaultBrowser(dist, chrome_exe)) {
1143 suffix = L"";
1144 } 1223 }
1145 1224
1146 // TODO(grt): remove this on or after 2012-08-01; see impl for details. 1225 // TODO(grt): remove this on or after 2012-08-01; see impl for details.
1147 RemoveBadWindows8RegistrationIfNeeded(dist, chrome_exe, suffix); 1226 RemoveBadWindows8RegistrationIfNeeded(dist, chrome_exe);
1148 1227
1149 // Check if Chromium is already registered with this suffix. 1228 // Check if Chromium is already registered with this suffix.
1150 if (IsChromeRegistered(dist, chrome_exe, suffix)) 1229 if (IsChromeRegistered(dist, chrome_exe, suffix))
1151 return true; 1230 return true;
1152 1231
1153 // If user is an admin try to register and return the status. 1232 // If user is an admin try to register and return the status.
1154 if (IsUserAnAdmin()) { 1233 if (IsUserAnAdmin()) {
1155 std::list<RegistryEntry*> progids; 1234 std::list<RegistryEntry*> progids;
1156 STLElementDeleter<std::list<RegistryEntry*> > progids_deleter(&progids); 1235 STLElementDeleter<std::list<RegistryEntry*> > progids_deleter(&progids);
1157 std::list<RegistryEntry*> sys_entries; 1236 std::list<RegistryEntry*> sys_entries;
1158 STLElementDeleter<std::list<RegistryEntry*> > sys_deleter(&sys_entries); 1237 STLElementDeleter<std::list<RegistryEntry*> > sys_deleter(&sys_entries);
1159 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &progids); 1238 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &progids);
1160 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &sys_entries); 1239 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &sys_entries);
1161 return AddRegistryEntries( 1240 return AddRegistryEntries(
1162 InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? 1241 InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ?
1163 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, 1242 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
1164 progids) && 1243 progids) &&
1165 AddRegistryEntries(HKEY_LOCAL_MACHINE, sys_entries); 1244 AddRegistryEntries(HKEY_LOCAL_MACHINE, sys_entries);
1166 } 1245 }
1167 1246
1168 // If user is not an admin and OS is Vista, try to elevate and register. 1247 // If user is not an admin and OS is Vista, try to elevate and register.
1169 if (elevate_if_not_admin && 1248 if (elevate_if_not_admin &&
1170 base::win::GetVersion() >= base::win::VERSION_VISTA && 1249 base::win::GetVersion() >= base::win::VERSION_VISTA &&
1171 ElevateAndRegisterChrome(dist, chrome_exe, suffix, L"")) 1250 ElevateAndRegisterChrome(dist, chrome_exe, suffix, L""))
1172 return true; 1251 return true;
1173 1252
1174 // If we got to this point then all we can do is create ProgIds under HKCU 1253 // If we got to this point then all we can do is create ProgIds under HKCU.
1175 // on XP as well as Vista.
1176 std::list<RegistryEntry*> entries; 1254 std::list<RegistryEntry*> entries;
1177 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); 1255 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries);
1178 RegistryEntry::GetProgIdEntries(dist, chrome_exe, L"", &entries); 1256 RegistryEntry::GetProgIdEntries(dist, chrome_exe, L"", &entries);
1179 return AddRegistryEntries(HKEY_CURRENT_USER, entries); 1257 // Prefer to use |suffix|; unless Chrome's ProgIds are already registered with
1258 // no suffix (as per the old registration style): in which case some other
1259 // registry entries could refer to them and since we were not able to set our
1260 // HKLM entries above, we are better off not altering these here.
1261 if (!AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU)) {
1262 if (!suffix.empty()) {
1263 STLDeleteElements(&entries);
1264 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries);
1265 }
1266 return AddRegistryEntries(HKEY_CURRENT_USER, entries);
1267 }
1268 return true;
1180 } 1269 }
1181 1270
1182 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, 1271 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist,
1183 const string16& chrome_exe, 1272 const string16& chrome_exe,
1184 const string16& unique_suffix, 1273 const string16& unique_suffix,
1185 const string16& protocol, 1274 const string16& protocol,
1186 bool elevate_if_not_admin) { 1275 bool elevate_if_not_admin) {
1187 if (!dist->CanSetAsDefault()) 1276 if (!dist->CanSetAsDefault())
1188 return false; 1277 return false;
1189 1278
1190 // Figure out we need to append a suffix to the registry entries to
1191 // make them unique.
1192 string16 suffix; 1279 string16 suffix;
1193 if (!unique_suffix.empty()) { 1280 if (!unique_suffix.empty()) {
1194 suffix = unique_suffix; 1281 suffix = unique_suffix;
1195 } else if (InstallUtil::IsPerUserInstall(chrome_exe.c_str()) && 1282 } else if (!GetInstallationSpecificSuffix(dist, chrome_exe, &suffix)) {
1196 !GetUserSpecificDefaultBrowserSuffix(dist, &suffix) && 1283 return false;
1197 !AnotherUserHasDefaultBrowser(dist, chrome_exe)) {
1198 suffix = L"";
1199 } 1284 }
1200 1285
1201 // Check if Chromium is already registered with this suffix. 1286 // Check if Chromium is already registered with this suffix.
1202 if (IsChromeRegisteredForProtocol(dist, suffix, protocol)) 1287 if (IsChromeRegisteredForProtocol(dist, suffix, protocol))
1203 return true; 1288 return true;
1204 1289
1205 if (IsUserAnAdmin()) { 1290 if (IsUserAnAdmin()) {
1206 // We can do this operation directly. 1291 // We can do this operation directly.
1207 // First, make sure Chrome is fully registered on this machine. 1292 // First, make sure Chrome is fully registered on this machine.
1208 if (!RegisterChromeBrowser(dist, chrome_exe, suffix, false)) 1293 if (!RegisterChromeBrowser(dist, chrome_exe, suffix, false))
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1331 chrome_exe.c_str(), 1416 chrome_exe.c_str(),
1332 shortcut.c_str(), 1417 shortcut.c_str(),
1333 chrome_path.c_str(), 1418 chrome_path.c_str(),
1334 arguments.c_str(), 1419 arguments.c_str(),
1335 description.c_str(), 1420 description.c_str(),
1336 icon_path.c_str(), 1421 icon_path.c_str(),
1337 icon_index, 1422 icon_index,
1338 dist->GetBrowserAppId().c_str(), 1423 dist->GetBrowserAppId().c_str(),
1339 ConvertShellUtilShortcutOptionsToFileUtil(options)); 1424 ConvertShellUtilShortcutOptionsToFileUtil(options));
1340 } 1425 }
OLDNEW
« no previous file with comments | « chrome/installer/util/shell_util.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698