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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 return VerifyVersionInfo(&min_version_info, type_mask, condition_mask) != 0; | 67 return VerifyVersionInfo(&min_version_info, type_mask, condition_mask) != 0; |
68 } | 68 } |
69 | 69 |
70 // This class represents a single registry entry. The objective is to | 70 // This class represents a single registry entry. The objective is to |
71 // encapsulate all the registry entries required for registering Chrome at one | 71 // 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 | 72 // 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 | 73 // of this class type can be obtained only by calling a static method of this |
74 // class. | 74 // class. |
75 class RegistryEntry { | 75 class RegistryEntry { |
76 public: | 76 public: |
| 77 // An enum of places to look for this key in the Windows registry. |
| 78 enum LookForIn { |
| 79 LOOK_IN_HKCU = 0, |
| 80 LOOK_IN_HKLM, |
| 81 LOOK_IN_HKCU_THEN_HKLM, |
| 82 }; |
| 83 |
77 // Returns the Windows browser client registration key for Chrome. For | 84 // Returns the Windows browser client registration key for Chrome. For |
78 // example: "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly | 85 // example: "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly |
79 // speaking, we should use the name of the executable (e.g., "chrome.exe"), | 86 // 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 | 87 // 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 | 88 // to make Chrome their default browser, which isn't polite. |suffix| is the |
82 // user-specific registration suffix; see GetUserSpecificDefaultBrowserSuffix | 89 // user-specific registration suffix; see GetUserSpecificDefaultBrowserSuffix |
83 // in shell_util.h for details. | 90 // in shell_util.h for details. |
84 static string16 GetBrowserClientKey(BrowserDistribution* dist, | 91 static string16 GetBrowserClientKey(BrowserDistribution* dist, |
85 const string16& suffix) { | 92 const string16& suffix) { |
86 DCHECK(suffix.empty() || suffix[0] == L'.'); | 93 DCHECK(suffix.empty() || suffix[0] == L'.'); |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 // strings. | 250 // strings. |
244 entries->push_front(new RegistryEntry(install_info, kReinstallCommand, | 251 entries->push_front(new RegistryEntry(install_info, kReinstallCommand, |
245 quoted_exe_path + L" --" + ASCIIToWide(switches::kMakeDefaultBrowser))); | 252 quoted_exe_path + L" --" + ASCIIToWide(switches::kMakeDefaultBrowser))); |
246 entries->push_front(new RegistryEntry(install_info, L"HideIconsCommand", | 253 entries->push_front(new RegistryEntry(install_info, L"HideIconsCommand", |
247 quoted_exe_path + L" --" + ASCIIToWide(switches::kHideIcons))); | 254 quoted_exe_path + L" --" + ASCIIToWide(switches::kHideIcons))); |
248 entries->push_front(new RegistryEntry(install_info, L"ShowIconsCommand", | 255 entries->push_front(new RegistryEntry(install_info, L"ShowIconsCommand", |
249 quoted_exe_path + L" --" + ASCIIToWide(switches::kShowIcons))); | 256 quoted_exe_path + L" --" + ASCIIToWide(switches::kShowIcons))); |
250 entries->push_front(new RegistryEntry(install_info, L"IconsVisible", 1)); | 257 entries->push_front(new RegistryEntry(install_info, L"IconsVisible", 1)); |
251 | 258 |
252 // Register with Default Programs. | 259 // Register with Default Programs. |
253 string16 app_name(dist->GetApplicationName().append(suffix)); | 260 string16 reg_app_name(dist->GetApplicationName().append(suffix)); |
254 // Tell Windows where to find Chrome's Default Programs info. | 261 // Tell Windows where to find Chrome's Default Programs info. |
255 string16 capabilities(GetCapabilitiesKey(dist, suffix)); | 262 string16 capabilities(GetCapabilitiesKey(dist, suffix)); |
256 entries->push_front(new RegistryEntry(ShellUtil::kRegRegisteredApplications, | 263 entries->push_front(new RegistryEntry(ShellUtil::kRegRegisteredApplications, |
257 app_name, capabilities)); | 264 reg_app_name, capabilities)); |
258 // Write out Chrome's Default Programs info. | 265 // Write out Chrome's Default Programs info. |
259 // TODO(grt): http://crbug.com/75152 Write a reference to a localized | 266 // TODO(grt): http://crbug.com/75152 Write a reference to a localized |
260 // resource rather than this. | 267 // resource rather than this. |
261 entries->push_front(new RegistryEntry( | 268 entries->push_front(new RegistryEntry( |
262 capabilities, ShellUtil::kRegApplicationDescription, | 269 capabilities, ShellUtil::kRegApplicationDescription, |
263 dist->GetLongAppDescription())); | 270 dist->GetLongAppDescription())); |
264 entries->push_front(new RegistryEntry( | 271 entries->push_front(new RegistryEntry( |
265 capabilities, ShellUtil::kRegApplicationIcon, icon_path)); | 272 capabilities, ShellUtil::kRegApplicationIcon, icon_path)); |
266 entries->push_front(new RegistryEntry( | 273 entries->push_front(new RegistryEntry( |
267 capabilities, ShellUtil::kRegApplicationName, app_name)); | 274 capabilities, ShellUtil::kRegApplicationName, |
| 275 dist->GetAppShortCutName())); |
268 | 276 |
269 entries->push_front(new RegistryEntry(capabilities + L"\\Startmenu", | 277 entries->push_front(new RegistryEntry(capabilities + L"\\Startmenu", |
270 L"StartMenuInternet", app_name)); | 278 L"StartMenuInternet", reg_app_name)); |
271 | 279 |
272 string16 html_prog_id(ShellUtil::kChromeHTMLProgId); | 280 string16 html_prog_id(ShellUtil::kChromeHTMLProgId); |
273 html_prog_id.append(suffix); | 281 html_prog_id.append(suffix); |
274 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { | 282 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { |
275 entries->push_front(new RegistryEntry( | 283 entries->push_front(new RegistryEntry( |
276 capabilities + L"\\FileAssociations", | 284 capabilities + L"\\FileAssociations", |
277 ShellUtil::kFileAssociations[i], html_prog_id)); | 285 ShellUtil::kFileAssociations[i], html_prog_id)); |
278 } | 286 } |
279 for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL; | 287 for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL; |
280 i++) { | 288 i++) { |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 if (_is_string) { | 378 if (_is_string) { |
371 items->AddSetRegValueWorkItem(root, _key_path, _name, _value, true); | 379 items->AddSetRegValueWorkItem(root, _key_path, _name, _value, true); |
372 } else { | 380 } else { |
373 items->AddSetRegValueWorkItem(root, _key_path, _name, _int_value, true); | 381 items->AddSetRegValueWorkItem(root, _key_path, _name, _int_value, true); |
374 } | 382 } |
375 } | 383 } |
376 | 384 |
377 // Checks if the current registry entry exists in HKCU\|_key_path|\|_name| | 385 // 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 | 386 // and value is |_value|. If the key does NOT exist in HKCU, checks for |
379 // the correct name and value in HKLM. | 387 // the correct name and value in HKLM. |
380 // This mimics Windows' behavior when searching in HKCR (HKCU takes precedence | 388 // |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 | 389 // 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 | 390 // to exist in them. |
383 // (but harmless) queries into HKCU in that case. Starting with Windows 8, | 391 // If |look_for_in| is LOOK_IN_HKCU_THEN_HKLM, this method mimics Windows' |
384 // Chrome's values go in HKCU for user-level installs, which takes precedence | 392 // behavior when searching in HKCR (HKCU takes precedence over HKLM). For |
385 // over HKLM. | 393 // registrations outside of HKCR on versions of Windows up to Win7, Chrome's |
386 bool ExistsInRegistry() { | 394 // values go in HKLM. This function will make unnecessary (but harmless) |
387 RegistryStatus hkcu_status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER); | 395 // queries into HKCU in that case. |
| 396 bool ExistsInRegistry(LookForIn look_for_in) const { |
| 397 const bool look_in_hkcu = (look_for_in == LOOK_IN_HKCU || |
| 398 look_for_in == LOOK_IN_HKCU_THEN_HKLM); |
| 399 const bool look_in_hklm = (look_for_in == LOOK_IN_HKLM || |
| 400 look_for_in == LOOK_IN_HKCU_THEN_HKLM); |
| 401 |
| 402 RegistryStatus hkcu_status = DOES_NOT_EXIST; |
| 403 if (look_in_hkcu) |
| 404 hkcu_status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER); |
| 405 |
| 406 RegistryStatus hklm_status = DOES_NOT_EXIST; |
| 407 if (hkcu_status == DOES_NOT_EXIST && look_in_hklm) |
| 408 hklm_status = StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE); |
| 409 |
388 return (hkcu_status == SAME_VALUE || | 410 return (hkcu_status == SAME_VALUE || |
389 (hkcu_status == DOES_NOT_EXIST && | 411 (hkcu_status == DOES_NOT_EXIST && hklm_status == SAME_VALUE)); |
390 StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE) == SAME_VALUE)); | |
391 } | 412 } |
392 | 413 |
393 private: | 414 private: |
394 // States this RegistryKey can be in compared to the registry. | 415 // States this RegistryKey can be in compared to the registry. |
395 enum RegistryStatus { | 416 enum RegistryStatus { |
396 // |_name| does not exist in the registry | 417 // |_name| does not exist in the registry |
397 DOES_NOT_EXIST, | 418 DOES_NOT_EXIST, |
398 // |_name| exists, but its value != |_value| | 419 // |_name| exists, but its value != |_value| |
399 DIFFERENT_VALUE, | 420 DIFFERENT_VALUE, |
400 // |_name| exists and its value is |_value| | 421 // |_name| exists and its value is |_value| |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 | 485 |
465 // Apply all the registry changes and if there is a problem, rollback | 486 // Apply all the registry changes and if there is a problem, rollback |
466 if (!items->Do()) { | 487 if (!items->Do()) { |
467 items->Rollback(); | 488 items->Rollback(); |
468 return false; | 489 return false; |
469 } | 490 } |
470 return true; | 491 return true; |
471 } | 492 } |
472 | 493 |
473 // Checks that all |entries| are present on this computer. | 494 // Checks that all |entries| are present on this computer. |
474 bool AreEntriesRegistered(const std::list<RegistryEntry*>& entries) { | 495 // |look_for_in| is passed to RegistryEntry::ExistsInRegistry(). Documentation |
| 496 // for it can be found there. |
| 497 bool AreEntriesRegistered(const std::list<RegistryEntry*>& entries, |
| 498 RegistryEntry::LookForIn look_for_in) { |
475 bool registered = true; | 499 bool registered = true; |
476 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin(); | 500 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin(); |
477 registered && itr != entries.end(); ++itr) { | 501 registered && itr != entries.end(); ++itr) { |
478 // We do not need registered = registered && ... since the loop condition | 502 // We do not need registered = registered && ... since the loop condition |
479 // is set to exit early. | 503 // is set to exit early. |
480 registered = (*itr)->ExistsInRegistry(); | 504 registered = (*itr)->ExistsInRegistry(look_for_in); |
481 } | 505 } |
482 return registered; | 506 return registered; |
483 } | 507 } |
484 | 508 |
485 // Checks that all required registry entries for Chrome are already present | 509 // Checks that all required registry entries for Chrome are already present |
486 // on this computer. | 510 // on this computer. |
487 bool IsChromeRegistered(BrowserDistribution* dist, | 511 bool IsChromeRegistered(BrowserDistribution* dist, |
488 const string16& chrome_exe, | 512 const string16& chrome_exe, |
489 const string16& suffix) { | 513 const string16& suffix) { |
490 std::list<RegistryEntry*> entries; | 514 std::list<RegistryEntry*> entries; |
491 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); | 515 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); |
492 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries); | 516 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries); |
493 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries); | 517 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries); |
494 return AreEntriesRegistered(entries); | 518 return AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU_THEN_HKLM); |
495 } | 519 } |
496 | 520 |
497 // This method checks if Chrome is already registered on the local machine | 521 // 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. | 522 // for the requested protocol. It just checks the one value required for this. |
499 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, | 523 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, |
500 const string16& suffix, | 524 const string16& suffix, |
501 const string16& protocol) { | 525 const string16& protocol) { |
502 std::list<RegistryEntry*> entries; | 526 std::list<RegistryEntry*> entries; |
503 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); | 527 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); |
504 RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); | 528 RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); |
505 return AreEntriesRegistered(entries); | 529 return AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU_THEN_HKLM); |
506 } | 530 } |
507 | 531 |
508 // This method registers Chrome on Vista by launching an elevated setup.exe. | 532 // 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 | 533 // 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 | 534 // accepts it the new process will make the necessary changes and return SUCCESS |
511 // that we capture and return. | 535 // that we capture and return. |
512 // If protocol is non-empty we will also register Chrome as being capable of | 536 // If protocol is non-empty we will also register Chrome as being capable of |
513 // handling the protocol. | 537 // handling the protocol. |
514 bool ElevateAndRegisterChrome(BrowserDistribution* dist, | 538 bool ElevateAndRegisterChrome(BrowserDistribution* dist, |
515 const string16& chrome_exe, | 539 const string16& chrome_exe, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 } | 572 } |
549 | 573 |
550 DWORD ret_val = 0; | 574 DWORD ret_val = 0; |
551 InstallUtil::ExecuteExeAsAdmin(cmd, &ret_val); | 575 InstallUtil::ExecuteExeAsAdmin(cmd, &ret_val); |
552 if (ret_val == 0) | 576 if (ret_val == 0) |
553 return true; | 577 return true; |
554 } | 578 } |
555 return false; | 579 return false; |
556 } | 580 } |
557 | 581 |
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 application association dialog, which | 582 // Launches the Windows 7 and Windows 8 application association dialog, which |
615 // is the only documented way to make a browser the default browser on | 583 // is the only documented way to make a browser the default browser on |
616 // Windows 8. | 584 // Windows 8. |
617 bool LaunchApplicationAssociationDialog(const string16& app_id) { | 585 bool LaunchApplicationAssociationDialog(const string16& app_id) { |
618 base::win::ScopedComPtr<IApplicationAssociationRegistrationUI> aarui; | 586 base::win::ScopedComPtr<IApplicationAssociationRegistrationUI> aarui; |
619 HRESULT hr = aarui.CreateInstance(CLSID_ApplicationAssociationRegistrationUI); | 587 HRESULT hr = aarui.CreateInstance(CLSID_ApplicationAssociationRegistrationUI); |
620 if (FAILED(hr)) | 588 if (FAILED(hr)) |
621 return false; | 589 return false; |
622 hr = aarui->LaunchAdvancedAssociationUI(app_id.c_str()); | 590 hr = aarui->LaunchAdvancedAssociationUI(app_id.c_str()); |
623 return SUCCEEDED(hr); | 591 return SUCCEEDED(hr); |
(...skipping 16 matching lines...) Expand all Loading... |
640 // should be removed after a reasonable time, say 2012-08-01. Anyone on Win8 | 608 // should be removed after a reasonable time, say 2012-08-01. Anyone on Win8 |
641 // dev channel who hasn't been autoupdated or manually updated by then will have | 609 // dev channel who hasn't been autoupdated or manually updated by then will have |
642 // to uninstall and reinstall Chrome to repair. See http://crbug.com/124666 and | 610 // to uninstall and reinstall Chrome to repair. See http://crbug.com/124666 and |
643 // http://crbug.com/123994 for gory details. | 611 // http://crbug.com/123994 for gory details. |
644 // This function is also used to remove DelegateExecute verb handler | 612 // This function is also used to remove DelegateExecute verb handler |
645 // registrations on builds for which Metro is no longer supported. This will | 613 // registrations on builds for which Metro is no longer supported. This will |
646 // also become irrelevant sometime after Windows 8 RC (thus the aforementioned | 614 // also become irrelevant sometime after Windows 8 RC (thus the aforementioned |
647 // removal date remains correct). | 615 // removal date remains correct). |
648 void RemoveBadWindows8RegistrationIfNeeded( | 616 void RemoveBadWindows8RegistrationIfNeeded( |
649 BrowserDistribution* dist, | 617 BrowserDistribution* dist, |
650 const string16& chrome_exe, | 618 const string16& chrome_exe) { |
651 const string16& suffix) { | |
652 string16 handler_guid; | 619 string16 handler_guid; |
653 | 620 |
654 if (dist->GetDelegateExecuteHandlerData(&handler_guid, NULL, NULL, NULL) && | 621 if (dist->GetDelegateExecuteHandlerData(&handler_guid, NULL, NULL, NULL) && |
655 (!InstallUtil::HasDelegateExecuteHandler(dist, chrome_exe) || | 622 (!InstallUtil::HasDelegateExecuteHandler(dist, chrome_exe) || |
656 !IsChromeMetroSupported())) { | 623 !IsChromeMetroSupported())) { |
657 // There's no need to rollback, so forgo the usual work item lists and just | 624 // There's no need to rollback, so forgo the usual work item lists and just |
658 // remove the values from the registry. | 625 // remove the values from the registry. |
659 const HKEY root_key = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? | 626 const HKEY root_key = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? |
660 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; | 627 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; |
| 628 // Use the current installation's suffix, not the about-to-be-installed |
| 629 // suffix. |
| 630 const string16 installation_suffix( |
| 631 ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe)); |
661 const string16 app_id(dist->GetBrowserAppId()); | 632 const string16 app_id(dist->GetBrowserAppId()); |
662 | 633 |
663 // <root hkey>\Software\Classes\<app_id> | 634 // <root hkey>\Software\Classes\<app_id> |
664 string16 key(ShellUtil::kRegClasses); | 635 string16 key(ShellUtil::kRegClasses); |
665 key.push_back(FilePath::kSeparators[0]); | 636 key.push_back(FilePath::kSeparators[0]); |
666 key.append(app_id); | 637 key.append(app_id); |
667 InstallUtil::DeleteRegistryKey(root_key, key); | 638 InstallUtil::DeleteRegistryKey(root_key, key); |
668 | 639 |
669 // <root hkey>\Software\Classes\ChromiumHTML[.user]\shell\open\command | 640 // <root hkey>\Software\Classes\ChromiumHTML[.user]\shell\open\command |
670 key = ShellUtil::kRegClasses; | 641 key = ShellUtil::kRegClasses; |
671 key.push_back(FilePath::kSeparators[0]); | 642 key.push_back(FilePath::kSeparators[0]); |
672 key.append(ShellUtil::kChromeHTMLProgId); | 643 key.append(ShellUtil::kChromeHTMLProgId); |
673 key.append(suffix); | 644 key.append(installation_suffix); |
674 key.append(ShellUtil::kRegShellOpen); | 645 key.append(ShellUtil::kRegShellOpen); |
675 InstallUtil::DeleteRegistryValue(root_key, key, | 646 InstallUtil::DeleteRegistryValue(root_key, key, |
676 ShellUtil::kRegDelegateExecute); | 647 ShellUtil::kRegDelegateExecute); |
677 } | 648 } |
678 } | 649 } |
679 | 650 |
| 651 // Sets |suffix| to this user's username preceded by a dot. This suffix is then |
| 652 // meant to be added to all registration that may conflict with another |
| 653 // user-level Chrome install. |
| 654 // Returns true unless the OS call to retrieve the username fails. |
| 655 bool GetUserSpecificRegistrySuffix(string16* suffix) { |
| 656 wchar_t user_name[256]; |
| 657 DWORD size = arraysize(user_name); |
| 658 if (::GetUserName(user_name, &size) == 0 || size < 1) { |
| 659 PLOG(DFATAL) << "GetUserName failed"; |
| 660 return false; |
| 661 } |
| 662 suffix->reserve(size); |
| 663 suffix->assign(1, L'.'); |
| 664 suffix->append(user_name, size - 1); |
| 665 return true; |
| 666 } |
| 667 |
| 668 // Sets |suffix| to the current user's username, preceded by a dot, on |
| 669 // user-level installs. |
| 670 // To support old-style user-level installs however, |suffix| is cleared if |
| 671 // the user currently owns the non-suffixed HKLM registrations. |
| 672 // |suffix| is also cleared on system-level installs. |
| 673 // |suffix| should then be appended to all Chrome properties that may conflict |
| 674 // with other Chrome user-level installs. |
| 675 // Returns true unless one of the underlying calls fails. |
| 676 bool GetInstallationSpecificSuffix(BrowserDistribution* dist, |
| 677 const string16& chrome_exe, |
| 678 string16* suffix) { |
| 679 if (!InstallUtil::IsPerUserInstall(chrome_exe.c_str()) || |
| 680 ShellUtil::QuickIsChromeRegistered( |
| 681 dist, chrome_exe, string16(), |
| 682 ShellUtil::CONFIRM_SYSTEM_REGISTRATION)) { |
| 683 // No suffix on system-level installs and user-level installs already |
| 684 // registered with no suffix. |
| 685 suffix->clear(); |
| 686 return true; |
| 687 } else { |
| 688 return GetUserSpecificRegistrySuffix(suffix); |
| 689 } |
| 690 } |
| 691 |
680 } // namespace | 692 } // namespace |
681 | 693 |
682 const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon"; | 694 const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon"; |
683 const wchar_t* ShellUtil::kRegShellPath = L"\\shell"; | 695 const wchar_t* ShellUtil::kRegShellPath = L"\\shell"; |
684 const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command"; | 696 const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command"; |
685 const wchar_t* ShellUtil::kRegStartMenuInternet = | 697 const wchar_t* ShellUtil::kRegStartMenuInternet = |
686 L"Software\\Clients\\StartMenuInternet"; | 698 L"Software\\Clients\\StartMenuInternet"; |
687 const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes"; | 699 const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes"; |
688 const wchar_t* ShellUtil::kRegRegisteredApplications = | 700 const wchar_t* ShellUtil::kRegRegisteredApplications = |
689 L"Software\\RegisteredApplications"; | 701 L"Software\\RegisteredApplications"; |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
916 KEY_QUERY_VALUE) != ERROR_SUCCESS || | 928 KEY_QUERY_VALUE) != ERROR_SUCCESS || |
917 key.ReadValue(kReinstallCommand, &command) != ERROR_SUCCESS) { | 929 key.ReadValue(kReinstallCommand, &command) != ERROR_SUCCESS) { |
918 continue; | 930 continue; |
919 } | 931 } |
920 if (!name.empty() && !command.empty() && | 932 if (!name.empty() && !command.empty() && |
921 name.find(dist->GetApplicationName()) == string16::npos) | 933 name.find(dist->GetApplicationName()) == string16::npos) |
922 (*browsers)[name] = command; | 934 (*browsers)[name] = command; |
923 } | 935 } |
924 } | 936 } |
925 | 937 |
926 bool ShellUtil::GetUserSpecificDefaultBrowserSuffix(BrowserDistribution* dist, | 938 string16 ShellUtil::GetCurrentInstallationSuffix(BrowserDistribution* dist, |
927 string16* entry) { | 939 const string16& chrome_exe) { |
928 wchar_t user_name[256]; | 940 string16 tested_suffix; |
929 DWORD size = arraysize(user_name); | 941 if (!InstallUtil::IsPerUserInstall(chrome_exe.c_str()) || |
930 if (::GetUserName(user_name, &size) == 0 || size < 1) | 942 !GetUserSpecificRegistrySuffix(&tested_suffix) || |
931 return false; | 943 !QuickIsChromeRegistered(dist, chrome_exe, tested_suffix, |
932 entry->reserve(size); | 944 CONFIRM_PROGID_REGISTRATION)) { |
933 entry->assign(1, L'.'); | 945 return string16(); |
934 entry->append(user_name, size - 1); | 946 } |
| 947 return tested_suffix; |
| 948 } |
935 | 949 |
936 return RegKey(HKEY_LOCAL_MACHINE, | 950 bool ShellUtil::QuickIsChromeRegistered( |
937 RegistryEntry::GetBrowserClientKey(dist, *entry).c_str(), | 951 BrowserDistribution* dist, |
938 KEY_READ).Valid(); | 952 const string16& chrome_exe, |
| 953 const string16& suffix, |
| 954 RegistrationConfirmationLevel confirmation_level) { |
| 955 // Get the appropriate key to look for based on the level desired. |
| 956 string16 reg_key; |
| 957 switch (confirmation_level) { |
| 958 case CONFIRM_PROGID_REGISTRATION: |
| 959 // Software\Classes\ChromeHTML|suffix| |
| 960 reg_key = ShellUtil::kRegClasses; |
| 961 reg_key.push_back(FilePath::kSeparators[0]); |
| 962 reg_key.append(ShellUtil::kChromeHTMLProgId); |
| 963 reg_key.append(suffix); |
| 964 break; |
| 965 case CONFIRM_SYSTEM_REGISTRATION: |
| 966 case CONFIRM_SYSTEM_REGISTRATION_IN_HKLM: |
| 967 // Software\Clients\StartMenuInternet\Google Chrome|suffix| |
| 968 reg_key = RegistryEntry::GetBrowserClientKey(dist, suffix); |
| 969 break; |
| 970 default: |
| 971 NOTREACHED(); |
| 972 break; |
| 973 } |
| 974 reg_key.append(ShellUtil::kRegShellOpen); |
| 975 |
| 976 // User-level installs ProgId registrations can be found in HKCU (and values |
| 977 // there have priority over HKLM). The same is true for system entries as |
| 978 // of Windows 8. |
| 979 if (confirmation_level == CONFIRM_PROGID_REGISTRATION || |
| 980 (confirmation_level == CONFIRM_SYSTEM_REGISTRATION && |
| 981 base::win::GetVersion() >= base::win::VERSION_WIN8)) { |
| 982 const RegKey key_hkcu(HKEY_CURRENT_USER, reg_key.c_str(), KEY_QUERY_VALUE); |
| 983 string16 hkcu_value; |
| 984 // If |reg_key| is present in HKCU, assert that it points to |chrome_exe|. |
| 985 // Otherwise, fall back on an HKLM lookup below. |
| 986 if (key_hkcu.ReadValue(L"", &hkcu_value) == ERROR_SUCCESS) { |
| 987 return InstallUtil::ProgramCompare( |
| 988 FilePath(chrome_exe)).Evaluate(hkcu_value); |
| 989 } |
| 990 } |
| 991 |
| 992 // Assert that |reg_key| points to |chrome_exe| in HKLM. |
| 993 const RegKey key_hklm(HKEY_LOCAL_MACHINE, reg_key.c_str(), KEY_QUERY_VALUE); |
| 994 string16 hklm_value; |
| 995 if (key_hklm.ReadValue(L"", &hklm_value) == ERROR_SUCCESS) { |
| 996 return InstallUtil::ProgramCompare( |
| 997 FilePath(chrome_exe)).Evaluate(hklm_value); |
| 998 } |
| 999 return false; |
939 } | 1000 } |
940 | 1001 |
941 bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist, | 1002 bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist, |
942 int shell_change, | 1003 int shell_change, |
943 const string16& chrome_exe, | 1004 const string16& chrome_exe, |
944 bool elevate_if_not_admin) { | 1005 bool elevate_if_not_admin) { |
945 if (!dist->CanSetAsDefault()) | 1006 if (!dist->CanSetAsDefault()) |
946 return false; | 1007 return false; |
947 | 1008 |
948 ShellUtil::RegisterChromeBrowser(dist, chrome_exe, L"", elevate_if_not_admin); | 1009 if (!ShellUtil::RegisterChromeBrowser( |
| 1010 dist, chrome_exe, string16(), elevate_if_not_admin)) { |
| 1011 return false; |
| 1012 } |
949 | 1013 |
950 bool ret = true; | 1014 bool ret = true; |
951 // First use the new "recommended" way on Vista to make Chrome default | 1015 // First use the new "recommended" way on Vista to make Chrome default |
952 // browser. | 1016 // browser. |
953 string16 app_name = dist->GetApplicationName(); | 1017 string16 app_name = dist->GetApplicationName(); |
954 string16 app_suffix; | 1018 const string16 app_suffix( |
955 if (ShellUtil::GetUserSpecificDefaultBrowserSuffix(dist, &app_suffix)) | 1019 ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe)); |
956 app_name += app_suffix; | 1020 app_name += app_suffix; |
957 | 1021 |
958 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { | 1022 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { |
959 // On Windows 8, you can't set yourself as the default handler | 1023 // On Windows 8, you can't set yourself as the default handler |
960 // programatically. In other words IApplicationAssociationRegistration | 1024 // programatically. In other words IApplicationAssociationRegistration |
961 // has been rendered useless. What you can do is to launch | 1025 // has been rendered useless. What you can do is to launch |
962 // "Set Program Associations" section of the "Default Programs" | 1026 // "Set Program Associations" section of the "Default Programs" |
963 // control panel. This action does not require elevation and we | 1027 // control panel. This action does not require elevation and we |
964 // don't get to control window activation. More info at: | 1028 // don't get to control window activation. More info at: |
965 // http://msdn.microsoft.com/en-us/library/cc144154(VS.85).aspx | 1029 // http://msdn.microsoft.com/en-us/library/cc144154(VS.85).aspx |
966 return LaunchApplicationAssociationDialog(app_name.c_str()); | 1030 return LaunchApplicationAssociationDialog(app_name.c_str()); |
(...skipping 29 matching lines...) Expand all Loading... |
996 } | 1060 } |
997 } | 1061 } |
998 | 1062 |
999 // Now use the old way to associate Chrome with supported protocols and file | 1063 // Now use the old way to associate Chrome with supported protocols and file |
1000 // associations. This should not be required on Vista but since some | 1064 // associations. This should not be required on Vista but since some |
1001 // applications still read Software\Classes\http key directly, we have to do | 1065 // applications still read Software\Classes\http key directly, we have to do |
1002 // this on Vista also. | 1066 // this on Vista also. |
1003 | 1067 |
1004 std::list<RegistryEntry*> entries; | 1068 std::list<RegistryEntry*> entries; |
1005 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); | 1069 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); |
1006 string16 suffix; | 1070 RegistryEntry::GetUserEntries(dist, chrome_exe, app_suffix, &entries); |
1007 if (!GetUserSpecificDefaultBrowserSuffix(dist, &suffix)) | |
1008 suffix = L""; | |
1009 RegistryEntry::GetUserEntries(dist, chrome_exe, suffix, &entries); | |
1010 // Change the default browser for current user. | 1071 // Change the default browser for current user. |
1011 if ((shell_change & ShellUtil::CURRENT_USER) && | 1072 if ((shell_change & ShellUtil::CURRENT_USER) && |
1012 !AddRegistryEntries(HKEY_CURRENT_USER, entries)) { | 1073 !AddRegistryEntries(HKEY_CURRENT_USER, entries)) { |
1013 ret = false; | 1074 ret = false; |
1014 LOG(ERROR) << "Could not make Chrome default browser (XP/current user)."; | 1075 LOG(ERROR) << "Could not make Chrome default browser (XP/current user)."; |
1015 } | 1076 } |
1016 | 1077 |
1017 // Chrome as default browser at system level. | 1078 // Chrome as default browser at system level. |
1018 if ((shell_change & ShellUtil::SYSTEM_LEVEL) && | 1079 if ((shell_change & ShellUtil::SYSTEM_LEVEL) && |
1019 !AddRegistryEntries(HKEY_LOCAL_MACHINE, entries)) { | 1080 !AddRegistryEntries(HKEY_LOCAL_MACHINE, entries)) { |
(...skipping 19 matching lines...) Expand all Loading... |
1039 // First use the new "recommended" way on Vista to make Chrome default | 1100 // First use the new "recommended" way on Vista to make Chrome default |
1040 // protocol handler. | 1101 // protocol handler. |
1041 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { | 1102 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { |
1042 VLOG(1) << "Registering Chrome as default handler for " << protocol | 1103 VLOG(1) << "Registering Chrome as default handler for " << protocol |
1043 << " on Vista."; | 1104 << " on Vista."; |
1044 base::win::ScopedComPtr<IApplicationAssociationRegistration> pAAR; | 1105 base::win::ScopedComPtr<IApplicationAssociationRegistration> pAAR; |
1045 HRESULT hr = pAAR.CreateInstance(CLSID_ApplicationAssociationRegistration, | 1106 HRESULT hr = pAAR.CreateInstance(CLSID_ApplicationAssociationRegistration, |
1046 NULL, CLSCTX_INPROC); | 1107 NULL, CLSCTX_INPROC); |
1047 if (SUCCEEDED(hr)) { | 1108 if (SUCCEEDED(hr)) { |
1048 string16 app_name = dist->GetApplicationName(); | 1109 string16 app_name = dist->GetApplicationName(); |
1049 string16 suffix; | 1110 app_name += ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe); |
1050 if (ShellUtil::GetUserSpecificDefaultBrowserSuffix(dist, &suffix)) | |
1051 app_name += suffix; | |
1052 | 1111 |
1053 hr = pAAR->SetAppAsDefault(app_name.c_str(), protocol.c_str(), | 1112 hr = pAAR->SetAppAsDefault(app_name.c_str(), protocol.c_str(), |
1054 AT_URLPROTOCOL); | 1113 AT_URLPROTOCOL); |
1055 } | 1114 } |
1056 if (!SUCCEEDED(hr)) { | 1115 if (!SUCCEEDED(hr)) { |
1057 ret = false; | 1116 ret = false; |
1058 LOG(ERROR) << "Could not make Chrome default protocol client (Vista):" | 1117 LOG(ERROR) << "Could not make Chrome default protocol client (Vista):" |
1059 << " HRESULT=" << hr << "."; | 1118 << " HRESULT=" << hr << "."; |
1060 } | 1119 } |
1061 } | 1120 } |
1062 | 1121 |
1063 // Now use the old way to associate Chrome with the desired protocol. This | 1122 // Now use the old way to associate Chrome with the desired protocol. This |
1064 // should not be required on Vista but since some applications still read | 1123 // should not be required on Vista but since some applications still read |
1065 // Software\Classes\http key directly, we have to do this on Vista also. | 1124 // Software\Classes\http key directly, we have to do this on Vista also. |
1066 | 1125 |
1067 std::list<RegistryEntry*> entries; | 1126 std::list<RegistryEntry*> entries; |
1068 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); | 1127 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); |
1069 string16 suffix; | 1128 const string16 suffix(GetCurrentInstallationSuffix(dist, chrome_exe)); |
1070 if (!GetUserSpecificDefaultBrowserSuffix(dist, &suffix)) | 1129 const string16 chrome_open(ShellUtil::GetChromeShellOpenCmd(chrome_exe)); |
1071 suffix = L""; | 1130 const string16 chrome_icon(ShellUtil::GetChromeIcon(dist, chrome_exe)); |
1072 string16 chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe); | |
1073 string16 chrome_icon = ShellUtil::GetChromeIcon(dist, chrome_exe); | |
1074 RegistryEntry::GetUserProtocolEntries(protocol, chrome_icon, chrome_open, | 1131 RegistryEntry::GetUserProtocolEntries(protocol, chrome_icon, chrome_open, |
1075 &entries); | 1132 &entries); |
1076 // Change the default protocol handler for current user. | 1133 // Change the default protocol handler for current user. |
1077 if (!AddRegistryEntries(HKEY_CURRENT_USER, entries)) { | 1134 if (!AddRegistryEntries(HKEY_CURRENT_USER, entries)) { |
1078 ret = false; | 1135 ret = false; |
1079 LOG(ERROR) << "Could not make Chrome default protocol client (XP)."; | 1136 LOG(ERROR) << "Could not make Chrome default protocol client (XP)."; |
1080 } | 1137 } |
1081 | 1138 |
1082 return ret; | 1139 return ret; |
1083 } | 1140 } |
1084 | 1141 |
1085 bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist, | 1142 bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist, |
1086 const string16& chrome_exe, | 1143 const string16& chrome_exe, |
1087 const string16& unique_suffix, | 1144 const string16& unique_suffix, |
1088 bool elevate_if_not_admin) { | 1145 bool elevate_if_not_admin) { |
1089 if (!dist->CanSetAsDefault()) | 1146 if (!dist->CanSetAsDefault()) |
1090 return false; | 1147 return false; |
1091 | 1148 |
1092 // First figure out we need to append a suffix to the registry entries to | |
1093 // make them unique. | |
1094 string16 suffix; | 1149 string16 suffix; |
1095 if (!unique_suffix.empty()) { | 1150 if (!unique_suffix.empty()) { |
1096 suffix = unique_suffix; | 1151 suffix = unique_suffix; |
1097 } else if (InstallUtil::IsPerUserInstall(chrome_exe.c_str()) && | 1152 } else if (!GetInstallationSpecificSuffix(dist, chrome_exe, &suffix)) { |
1098 !GetUserSpecificDefaultBrowserSuffix(dist, &suffix) && | 1153 return false; |
1099 !AnotherUserHasDefaultBrowser(dist, chrome_exe)) { | |
1100 suffix = L""; | |
1101 } | 1154 } |
1102 | 1155 |
1103 // TODO(grt): remove this on or after 2012-08-01; see impl for details. | 1156 // TODO(grt): remove this on or after 2012-08-01; see impl for details. |
1104 RemoveBadWindows8RegistrationIfNeeded(dist, chrome_exe, suffix); | 1157 RemoveBadWindows8RegistrationIfNeeded(dist, chrome_exe); |
1105 | 1158 |
1106 // Check if Chromium is already registered with this suffix. | 1159 // Check if Chromium is already registered with this suffix. |
1107 if (IsChromeRegistered(dist, chrome_exe, suffix)) | 1160 if (IsChromeRegistered(dist, chrome_exe, suffix)) |
1108 return true; | 1161 return true; |
1109 | 1162 |
1110 // If user is an admin try to register and return the status. | 1163 // If user is an admin try to register and return the status. |
1111 if (IsUserAnAdmin()) { | 1164 if (IsUserAnAdmin()) { |
1112 std::list<RegistryEntry*> progids; | 1165 std::list<RegistryEntry*> progids; |
1113 STLElementDeleter<std::list<RegistryEntry*> > progids_deleter(&progids); | 1166 STLElementDeleter<std::list<RegistryEntry*> > progids_deleter(&progids); |
1114 std::list<RegistryEntry*> sys_entries; | 1167 std::list<RegistryEntry*> sys_entries; |
1115 STLElementDeleter<std::list<RegistryEntry*> > sys_deleter(&sys_entries); | 1168 STLElementDeleter<std::list<RegistryEntry*> > sys_deleter(&sys_entries); |
1116 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &progids); | 1169 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &progids); |
1117 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &sys_entries); | 1170 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &sys_entries); |
1118 return AddRegistryEntries( | 1171 return AddRegistryEntries( |
1119 InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? | 1172 InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? |
1120 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, | 1173 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, |
1121 progids) && | 1174 progids) && |
1122 AddRegistryEntries(HKEY_LOCAL_MACHINE, sys_entries); | 1175 AddRegistryEntries(HKEY_LOCAL_MACHINE, sys_entries); |
1123 } | 1176 } |
1124 | 1177 |
1125 // If user is not an admin and OS is Vista, try to elevate and register. | 1178 // If user is not an admin and OS is Vista, try to elevate and register. |
1126 if (elevate_if_not_admin && | 1179 if (elevate_if_not_admin && |
1127 base::win::GetVersion() >= base::win::VERSION_VISTA && | 1180 base::win::GetVersion() >= base::win::VERSION_VISTA && |
1128 ElevateAndRegisterChrome(dist, chrome_exe, suffix, L"")) | 1181 ElevateAndRegisterChrome(dist, chrome_exe, suffix, L"")) |
1129 return true; | 1182 return true; |
1130 | 1183 |
1131 // If we got to this point then all we can do is create ProgIds under HKCU | 1184 // If we got to this point then all we can do is create ProgIds under HKCU. |
1132 // on XP as well as Vista. | |
1133 std::list<RegistryEntry*> entries; | 1185 std::list<RegistryEntry*> entries; |
1134 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); | 1186 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); |
1135 RegistryEntry::GetProgIdEntries(dist, chrome_exe, L"", &entries); | 1187 RegistryEntry::GetProgIdEntries(dist, chrome_exe, L"", &entries); |
1136 return AddRegistryEntries(HKEY_CURRENT_USER, entries); | 1188 // Prefer to use |suffix|; unless Chrome's ProgIds are already registered with |
| 1189 // no suffix (as per the old registration style): in which case some other |
| 1190 // registry entries could refer to them and since we were not able to set our |
| 1191 // HKLM entries above, we are better off not altering these here. |
| 1192 if (!AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU)) { |
| 1193 if (!suffix.empty()) { |
| 1194 STLDeleteElements(&entries); |
| 1195 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries); |
| 1196 } |
| 1197 return AddRegistryEntries(HKEY_CURRENT_USER, entries); |
| 1198 } |
| 1199 return true; |
1137 } | 1200 } |
1138 | 1201 |
1139 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, | 1202 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, |
1140 const string16& chrome_exe, | 1203 const string16& chrome_exe, |
1141 const string16& unique_suffix, | 1204 const string16& unique_suffix, |
1142 const string16& protocol, | 1205 const string16& protocol, |
1143 bool elevate_if_not_admin) { | 1206 bool elevate_if_not_admin) { |
1144 if (!dist->CanSetAsDefault()) | 1207 if (!dist->CanSetAsDefault()) |
1145 return false; | 1208 return false; |
1146 | 1209 |
1147 // Figure out we need to append a suffix to the registry entries to | |
1148 // make them unique. | |
1149 string16 suffix; | 1210 string16 suffix; |
1150 if (!unique_suffix.empty()) { | 1211 if (!unique_suffix.empty()) { |
1151 suffix = unique_suffix; | 1212 suffix = unique_suffix; |
1152 } else if (InstallUtil::IsPerUserInstall(chrome_exe.c_str()) && | 1213 } else if (!GetInstallationSpecificSuffix(dist, chrome_exe, &suffix)) { |
1153 !GetUserSpecificDefaultBrowserSuffix(dist, &suffix) && | 1214 return false; |
1154 !AnotherUserHasDefaultBrowser(dist, chrome_exe)) { | |
1155 suffix = L""; | |
1156 } | 1215 } |
1157 | 1216 |
1158 // Check if Chromium is already registered with this suffix. | 1217 // Check if Chromium is already registered with this suffix. |
1159 if (IsChromeRegisteredForProtocol(dist, suffix, protocol)) | 1218 if (IsChromeRegisteredForProtocol(dist, suffix, protocol)) |
1160 return true; | 1219 return true; |
1161 | 1220 |
1162 if (IsUserAnAdmin()) { | 1221 if (IsUserAnAdmin()) { |
1163 // We can do this operation directly. | 1222 // We can do this operation directly. |
1164 // If we're not registered at all, try to register. If that fails | 1223 // If we're not registered at all, try to register. If that fails |
1165 // we should give up. | 1224 // we should give up. |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1291 chrome_exe.c_str(), | 1350 chrome_exe.c_str(), |
1292 shortcut.c_str(), | 1351 shortcut.c_str(), |
1293 chrome_path.c_str(), | 1352 chrome_path.c_str(), |
1294 arguments.c_str(), | 1353 arguments.c_str(), |
1295 description.c_str(), | 1354 description.c_str(), |
1296 icon_path.c_str(), | 1355 icon_path.c_str(), |
1297 icon_index, | 1356 icon_index, |
1298 dist->GetBrowserAppId().c_str(), | 1357 dist->GetBrowserAppId().c_str(), |
1299 ConvertShellUtilShortcutOptionsToFileUtil(options)); | 1358 ConvertShellUtilShortcutOptionsToFileUtil(options)); |
1300 } | 1359 } |
OLD | NEW |