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 22 matching lines...) Expand all Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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"", ®istry_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |