Chromium Code Reviews| 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 // A bit-field enum of places to look for this key in the Windows registry. | |
| 78 enum LookForIn { | |
| 79 LOOK_IN_HKCU = 1 << 0, | |
| 80 LOOK_IN_HKLM = 1 << 1, | |
| 81 }; | |
| 82 | |
| 77 // Returns the Windows browser client registration key for Chrome. For | 83 // Returns the Windows browser client registration key for Chrome. For |
| 78 // example: "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly | 84 // example: "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly |
| 79 // speaking, we should use the name of the executable (e.g., "chrome.exe"), | 85 // 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 | 86 // 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 | 87 // to make Chrome their default browser, which isn't polite. |suffix| is the |
| 82 // user-specific registration suffix; see GetUserSpecificDefaultBrowserSuffix | 88 // user-specific registration suffix; see GetUserSpecificDefaultBrowserSuffix |
| 83 // in shell_util.h for details. | 89 // in shell_util.h for details. |
| 84 static string16 GetBrowserClientKey(BrowserDistribution* dist, | 90 static string16 GetBrowserClientKey(BrowserDistribution* dist, |
| 85 const string16& suffix) { | 91 const string16& suffix) { |
| 86 DCHECK(suffix.empty() || suffix[0] == L'.'); | 92 DCHECK(suffix.empty() || suffix[0] == L'.'); |
| 87 return string16(ShellUtil::kRegStartMenuInternet) | 93 return string16(ShellUtil::kRegStartMenuInternet) |
| 88 .append(1, L'\\') | 94 .append(1, L'\\') |
| 89 .append(dist->GetApplicationName()) | 95 .append(dist->GetApplicationName()) |
| 90 .append(suffix); | 96 .append(suffix); |
| 91 } | 97 } |
| 92 | 98 |
| 93 // Returns the Windows Default Programs capabilities key for Chrome. For | 99 // Returns the Windows Default Programs capabilities key for Chrome. For |
| 94 // example: | 100 // example: |
| 95 // "Software\Clients\StartMenuInternet\Chromium[.user]\Capabilities". | 101 // "Software\Clients\StartMenuInternet\Chromium[.user]\Capabilities". |
| 96 static string16 GetCapabilitiesKey(BrowserDistribution* dist, | 102 static string16 GetCapabilitiesKey(BrowserDistribution* dist, |
| 97 const string16& suffix) { | 103 const string16& suffix) { |
| 98 return GetBrowserClientKey(dist, suffix).append(L"\\Capabilities"); | 104 return GetBrowserClientKey(dist, suffix).append(L"\\Capabilities"); |
| 99 } | 105 } |
| 100 | 106 |
| 107 // Returns true if Chrome is registered with the given |suffix| either in HKCU | |
| 108 // or HKLM. | |
| 109 // This function only checks for the existence of | |
| 110 // Software\Classes\ChromeHTML|suffix| and doesn't otherwise validate the | |
| 111 // registration of Chrome. | |
| 112 static bool IsChromeRegisteredWithSuffix(const string16& suffix) { | |
| 113 DCHECK(!suffix.empty()); | |
| 114 string16 chrome_html_prog_id(ShellUtil::kRegClasses); | |
| 115 chrome_html_prog_id.push_back(FilePath::kSeparators[0]); | |
| 116 chrome_html_prog_id.append(ShellUtil::kChromeHTMLProgId); | |
| 117 chrome_html_prog_id.append(suffix); | |
| 118 return RegistryEntry(chrome_html_prog_id, | |
| 119 ShellUtil::kChromeHTMLProgIdDesc).ExistsInRegistry( | |
| 120 LOOK_IN_HKCU | LOOK_IN_HKLM); | |
| 121 } | |
| 122 | |
| 101 // This method returns a list of all the registry entries that | 123 // This method returns a list of all the registry entries that |
| 102 // are needed to register Chromium ProgIds. | 124 // are needed to register Chromium ProgIds. |
| 103 // These entries should be registered in HKCU for user-level installs and in | 125 // These entries should be registered in HKCU for user-level installs and in |
| 104 // HKLM for system-level installs. | 126 // HKLM for system-level installs. |
| 105 // TODO (gab): Extract the Windows 8 only registrations out of this function. | 127 // TODO (gab): Extract the Windows 8 only registrations out of this function. |
| 106 static bool GetProgIdEntries(BrowserDistribution* dist, | 128 static bool GetProgIdEntries(BrowserDistribution* dist, |
| 107 const string16& chrome_exe, | 129 const string16& chrome_exe, |
| 108 const string16& suffix, | 130 const string16& suffix, |
| 109 std::list<RegistryEntry*>* entries) { | 131 std::list<RegistryEntry*>* entries) { |
| 110 string16 icon_path(ShellUtil::GetChromeIcon(dist, chrome_exe)); | 132 string16 icon_path(ShellUtil::GetChromeIcon(dist, chrome_exe)); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 243 // strings. | 265 // strings. |
| 244 entries->push_front(new RegistryEntry(install_info, kReinstallCommand, | 266 entries->push_front(new RegistryEntry(install_info, kReinstallCommand, |
| 245 quoted_exe_path + L" --" + ASCIIToWide(switches::kMakeDefaultBrowser))); | 267 quoted_exe_path + L" --" + ASCIIToWide(switches::kMakeDefaultBrowser))); |
| 246 entries->push_front(new RegistryEntry(install_info, L"HideIconsCommand", | 268 entries->push_front(new RegistryEntry(install_info, L"HideIconsCommand", |
| 247 quoted_exe_path + L" --" + ASCIIToWide(switches::kHideIcons))); | 269 quoted_exe_path + L" --" + ASCIIToWide(switches::kHideIcons))); |
| 248 entries->push_front(new RegistryEntry(install_info, L"ShowIconsCommand", | 270 entries->push_front(new RegistryEntry(install_info, L"ShowIconsCommand", |
| 249 quoted_exe_path + L" --" + ASCIIToWide(switches::kShowIcons))); | 271 quoted_exe_path + L" --" + ASCIIToWide(switches::kShowIcons))); |
| 250 entries->push_front(new RegistryEntry(install_info, L"IconsVisible", 1)); | 272 entries->push_front(new RegistryEntry(install_info, L"IconsVisible", 1)); |
| 251 | 273 |
| 252 // Register with Default Programs. | 274 // Register with Default Programs. |
| 253 string16 app_name(dist->GetApplicationName().append(suffix)); | 275 string16 reg_app_name(dist->GetApplicationName().append(suffix)); |
| 254 // Tell Windows where to find Chrome's Default Programs info. | 276 // Tell Windows where to find Chrome's Default Programs info. |
| 255 string16 capabilities(GetCapabilitiesKey(dist, suffix)); | 277 string16 capabilities(GetCapabilitiesKey(dist, suffix)); |
| 256 entries->push_front(new RegistryEntry(ShellUtil::kRegRegisteredApplications, | 278 entries->push_front(new RegistryEntry(ShellUtil::kRegRegisteredApplications, |
| 257 app_name, capabilities)); | 279 reg_app_name, capabilities)); |
| 258 // Write out Chrome's Default Programs info. | 280 // Write out Chrome's Default Programs info. |
| 259 // TODO(grt): http://crbug.com/75152 Write a reference to a localized | 281 // TODO(grt): http://crbug.com/75152 Write a reference to a localized |
| 260 // resource rather than this. | 282 // resource rather than this. |
| 261 entries->push_front(new RegistryEntry( | 283 entries->push_front(new RegistryEntry( |
| 262 capabilities, ShellUtil::kRegApplicationDescription, | 284 capabilities, ShellUtil::kRegApplicationDescription, |
| 263 dist->GetLongAppDescription())); | 285 dist->GetLongAppDescription())); |
| 264 entries->push_front(new RegistryEntry( | 286 entries->push_front(new RegistryEntry( |
| 265 capabilities, ShellUtil::kRegApplicationIcon, icon_path)); | 287 capabilities, ShellUtil::kRegApplicationIcon, icon_path)); |
| 266 entries->push_front(new RegistryEntry( | 288 entries->push_front(new RegistryEntry( |
| 267 capabilities, ShellUtil::kRegApplicationName, app_name)); | 289 capabilities, ShellUtil::kRegApplicationName, |
| 290 dist->GetApplicationName())); | |
| 268 | 291 |
| 269 entries->push_front(new RegistryEntry(capabilities + L"\\Startmenu", | 292 entries->push_front(new RegistryEntry(capabilities + L"\\Startmenu", |
| 270 L"StartMenuInternet", app_name)); | 293 L"StartMenuInternet", reg_app_name)); |
| 271 | 294 |
| 272 string16 html_prog_id(ShellUtil::kChromeHTMLProgId); | 295 string16 html_prog_id(ShellUtil::kChromeHTMLProgId); |
| 273 html_prog_id.append(suffix); | 296 html_prog_id.append(suffix); |
| 274 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { | 297 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { |
| 275 entries->push_front(new RegistryEntry( | 298 entries->push_front(new RegistryEntry( |
| 276 capabilities + L"\\FileAssociations", | 299 capabilities + L"\\FileAssociations", |
| 277 ShellUtil::kFileAssociations[i], html_prog_id)); | 300 ShellUtil::kFileAssociations[i], html_prog_id)); |
| 278 } | 301 } |
| 279 for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL; | 302 for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL; |
| 280 i++) { | 303 i++) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 370 if (_is_string) { | 393 if (_is_string) { |
| 371 items->AddSetRegValueWorkItem(root, _key_path, _name, _value, true); | 394 items->AddSetRegValueWorkItem(root, _key_path, _name, _value, true); |
| 372 } else { | 395 } else { |
| 373 items->AddSetRegValueWorkItem(root, _key_path, _name, _int_value, true); | 396 items->AddSetRegValueWorkItem(root, _key_path, _name, _int_value, true); |
| 374 } | 397 } |
| 375 } | 398 } |
| 376 | 399 |
| 377 // Checks if the current registry entry exists in HKCU\|_key_path|\|_name| | 400 // 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 | 401 // and value is |_value|. If the key does NOT exist in HKCU, checks for |
| 379 // the correct name and value in HKLM. | 402 // the correct name and value in HKLM. |
| 380 // This mimics Windows' behavior when searching in HKCR (HKCU takes precedence | 403 // |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 | 404 // key, unspecified roots are not looked in and the key is assumed not to |
| 382 // to Win7, Chrome's values go in HKLM. This function will make unnecessary | 405 // exist in them. |
| 383 // (but harmless) queries into HKCU in that case. Starting with Windows 8, | 406 // |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 | 407 // If |look_for_in| specifies both HKCU and HKLM, this method mimics Windows' |
| 385 // over HKLM. | 408 // behavior when searching in HKCR (HKCU takes precedence over HKLM). For |
| 386 bool ExistsInRegistry() { | 409 // registrations outside of HKCR on versions of Windows up to Win7, Chrome's |
| 387 RegistryStatus hkcu_status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER); | 410 // values go in HKLM. This function will make unnecessary (but harmless) |
| 411 // queries into HKCU in that case. Starting with Windows 8, Chrome's values go | |
|
grt (UTC plus 2)
2012/05/30 20:37:40
Is this statement about where Chrome's values go i
gab
2012/05/31 06:36:01
Yes, in fact it was already checked in somehow, I
| |
| 412 // in HKCU for user-level installs, which takes precedence over HKLM. | |
| 413 bool ExistsInRegistry(uint32 look_for_in) const { | |
| 414 DCHECK(look_for_in); | |
| 415 | |
| 416 RegistryStatus hkcu_status = DOES_NOT_EXIST; | |
| 417 if (look_for_in & LOOK_IN_HKCU) | |
| 418 hkcu_status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER); | |
| 419 | |
| 420 RegistryStatus hklm_status = DOES_NOT_EXIST; | |
| 421 if (hkcu_status == DOES_NOT_EXIST && (look_for_in & LOOK_IN_HKLM)) | |
| 422 hklm_status = StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE); | |
| 423 | |
| 388 return (hkcu_status == SAME_VALUE || | 424 return (hkcu_status == SAME_VALUE || |
| 389 (hkcu_status == DOES_NOT_EXIST && | 425 (hkcu_status == DOES_NOT_EXIST && hklm_status == SAME_VALUE)); |
| 390 StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE) == SAME_VALUE)); | |
| 391 } | 426 } |
| 392 | 427 |
| 393 private: | 428 private: |
| 394 // States this RegistryKey can be in compared to the registry. | 429 // States this RegistryKey can be in compared to the registry. |
| 395 enum RegistryStatus { | 430 enum RegistryStatus { |
| 396 // |_name| does not exist in the registry | 431 // |_name| does not exist in the registry |
| 397 DOES_NOT_EXIST, | 432 DOES_NOT_EXIST, |
| 398 // |_name| exists, but its value != |_value| | 433 // |_name| exists, but its value != |_value| |
| 399 DIFFERENT_VALUE, | 434 DIFFERENT_VALUE, |
| 400 // |_name| exists and its value is |_value| | 435 // |_name| exists and its value is |_value| |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 464 | 499 |
| 465 // Apply all the registry changes and if there is a problem, rollback | 500 // Apply all the registry changes and if there is a problem, rollback |
| 466 if (!items->Do()) { | 501 if (!items->Do()) { |
| 467 items->Rollback(); | 502 items->Rollback(); |
| 468 return false; | 503 return false; |
| 469 } | 504 } |
| 470 return true; | 505 return true; |
| 471 } | 506 } |
| 472 | 507 |
| 473 // Checks that all |entries| are present on this computer. | 508 // Checks that all |entries| are present on this computer. |
| 474 bool AreEntriesRegistered(const std::list<RegistryEntry*>& entries) { | 509 // |look_for_in| is passed to RegistryEntry::ExistsInRegistry(). Documentation |
| 510 // for it can be found there. | |
| 511 bool AreEntriesRegistered(const std::list<RegistryEntry*>& entries, | |
| 512 uint32 look_for_in) { | |
| 475 bool registered = true; | 513 bool registered = true; |
| 476 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin(); | 514 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin(); |
| 477 registered && itr != entries.end(); ++itr) { | 515 registered && itr != entries.end(); ++itr) { |
| 478 // We do not need registered = registered && ... since the loop condition | 516 // We do not need registered = registered && ... since the loop condition |
| 479 // is set to exit early. | 517 // is set to exit early. |
| 480 registered = (*itr)->ExistsInRegistry(); | 518 registered = (*itr)->ExistsInRegistry(look_for_in); |
| 481 } | 519 } |
| 482 return registered; | 520 return registered; |
| 483 } | 521 } |
| 484 | 522 |
| 485 // Checks that all required registry entries for Chrome are already present | 523 // Checks that all required registry entries for Chrome are already present |
| 486 // on this computer. | 524 // on this computer. |
| 487 bool IsChromeRegistered(BrowserDistribution* dist, | 525 bool IsChromeRegistered(BrowserDistribution* dist, |
| 488 const string16& chrome_exe, | 526 const string16& chrome_exe, |
| 489 const string16& suffix) { | 527 const string16& suffix) { |
| 490 std::list<RegistryEntry*> entries; | 528 std::list<RegistryEntry*> entries; |
| 491 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); | 529 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); |
| 492 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries); | 530 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries); |
| 493 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries); | 531 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries); |
| 494 return AreEntriesRegistered(entries); | 532 return AreEntriesRegistered( |
| 533 entries, RegistryEntry::LOOK_IN_HKCU | RegistryEntry::LOOK_IN_HKLM); | |
| 495 } | 534 } |
| 496 | 535 |
| 497 // This method checks if Chrome is already registered on the local machine | 536 // 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. | 537 // for the requested protocol. It just checks the one value required for this. |
| 499 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, | 538 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, |
| 500 const string16& suffix, | 539 const string16& suffix, |
| 501 const string16& protocol) { | 540 const string16& protocol) { |
| 502 std::list<RegistryEntry*> entries; | 541 std::list<RegistryEntry*> entries; |
| 503 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); | 542 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); |
| 504 RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); | 543 RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); |
| 505 return AreEntriesRegistered(entries); | 544 return AreEntriesRegistered( |
| 545 entries, RegistryEntry::LOOK_IN_HKCU | RegistryEntry::LOOK_IN_HKLM); | |
| 506 } | 546 } |
| 507 | 547 |
| 508 // This method registers Chrome on Vista by launching an elevated setup.exe. | 548 // 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 | 549 // 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 | 550 // accepts it the new process will make the necessary changes and return SUCCESS |
| 511 // that we capture and return. | 551 // that we capture and return. |
| 512 // If protocol is non-empty we will also register Chrome as being capable of | 552 // If protocol is non-empty we will also register Chrome as being capable of |
| 513 // handling the protocol. | 553 // handling the protocol. |
| 514 bool ElevateAndRegisterChrome(BrowserDistribution* dist, | 554 bool ElevateAndRegisterChrome(BrowserDistribution* dist, |
| 515 const string16& chrome_exe, | 555 const string16& chrome_exe, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 548 } | 588 } |
| 549 | 589 |
| 550 DWORD ret_val = 0; | 590 DWORD ret_val = 0; |
| 551 InstallUtil::ExecuteExeAsAdmin(cmd, &ret_val); | 591 InstallUtil::ExecuteExeAsAdmin(cmd, &ret_val); |
| 552 if (ret_val == 0) | 592 if (ret_val == 0) |
| 553 return true; | 593 return true; |
| 554 } | 594 } |
| 555 return false; | 595 return false; |
| 556 } | 596 } |
| 557 | 597 |
| 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 | 598 // 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 | 599 // is the only documented way to make a browser the default browser on |
| 616 // Windows 8. | 600 // Windows 8. |
| 617 bool LaunchApplicationAssociationDialog(const string16& app_id) { | 601 bool LaunchApplicationAssociationDialog(const string16& app_id) { |
| 618 base::win::ScopedComPtr<IApplicationAssociationRegistrationUI> aarui; | 602 base::win::ScopedComPtr<IApplicationAssociationRegistrationUI> aarui; |
| 619 HRESULT hr = aarui.CreateInstance(CLSID_ApplicationAssociationRegistrationUI); | 603 HRESULT hr = aarui.CreateInstance(CLSID_ApplicationAssociationRegistrationUI); |
| 620 if (FAILED(hr)) | 604 if (FAILED(hr)) |
| 621 return false; | 605 return false; |
| 622 hr = aarui->LaunchAdvancedAssociationUI(app_id.c_str()); | 606 hr = aarui->LaunchAdvancedAssociationUI(app_id.c_str()); |
| 623 return SUCCEEDED(hr); | 607 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 | 624 // 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 | 625 // 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 | 626 // to uninstall and reinstall Chrome to repair. See http://crbug.com/124666 and |
| 643 // http://crbug.com/123994 for gory details. | 627 // http://crbug.com/123994 for gory details. |
| 644 // This function is also used to remove DelegateExecute verb handler | 628 // This function is also used to remove DelegateExecute verb handler |
| 645 // registrations on builds for which Metro is no longer supported. This will | 629 // registrations on builds for which Metro is no longer supported. This will |
| 646 // also become irrelevant sometime after Windows 8 RC (thus the aforementioned | 630 // also become irrelevant sometime after Windows 8 RC (thus the aforementioned |
| 647 // removal date remains correct). | 631 // removal date remains correct). |
| 648 void RemoveBadWindows8RegistrationIfNeeded( | 632 void RemoveBadWindows8RegistrationIfNeeded( |
| 649 BrowserDistribution* dist, | 633 BrowserDistribution* dist, |
| 650 const string16& chrome_exe, | 634 const string16& chrome_exe) { |
| 651 const string16& suffix) { | |
| 652 string16 handler_guid; | 635 string16 handler_guid; |
| 653 | 636 |
| 654 if (dist->GetDelegateExecuteHandlerData(&handler_guid, NULL, NULL, NULL) && | 637 if (dist->GetDelegateExecuteHandlerData(&handler_guid, NULL, NULL, NULL) && |
| 655 (!InstallUtil::HasDelegateExecuteHandler(dist, chrome_exe) || | 638 (!InstallUtil::HasDelegateExecuteHandler(dist, chrome_exe) || |
| 656 !IsChromeMetroSupported())) { | 639 !IsChromeMetroSupported())) { |
| 657 // There's no need to rollback, so forgo the usual work item lists and just | 640 // There's no need to rollback, so forgo the usual work item lists and just |
| 658 // remove the values from the registry. | 641 // remove the values from the registry. |
| 659 const HKEY root_key = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? | 642 const HKEY root_key = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? |
| 660 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; | 643 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; |
| 644 // Use the current installation's suffix, not the about-to-be-installed | |
| 645 // suffix. | |
| 646 const string16 installation_suffix = | |
| 647 ShellUtil::GetCurrentInstallationSuffix(); | |
| 661 const string16 app_id(dist->GetBrowserAppId()); | 648 const string16 app_id(dist->GetBrowserAppId()); |
| 662 | 649 |
| 663 // <root hkey>\Software\Classes\<app_id> | 650 // <root hkey>\Software\Classes\<app_id> |
| 664 string16 key(ShellUtil::kRegClasses); | 651 string16 key(ShellUtil::kRegClasses); |
| 665 key.push_back(FilePath::kSeparators[0]); | 652 key.push_back(FilePath::kSeparators[0]); |
| 666 key.append(app_id); | 653 key.append(app_id); |
| 667 InstallUtil::DeleteRegistryKey(root_key, key); | 654 InstallUtil::DeleteRegistryKey(root_key, key); |
| 668 | 655 |
| 669 // <root hkey>\Software\Classes\ChromiumHTML[.user]\shell\open\command | 656 // <root hkey>\Software\Classes\ChromiumHTML[.user]\shell\open\command |
| 670 key = ShellUtil::kRegClasses; | 657 key = ShellUtil::kRegClasses; |
| 671 key.push_back(FilePath::kSeparators[0]); | 658 key.push_back(FilePath::kSeparators[0]); |
| 672 key.append(ShellUtil::kChromeHTMLProgId); | 659 key.append(ShellUtil::kChromeHTMLProgId); |
| 673 key.append(suffix); | 660 key.append(installation_suffix); |
| 674 key.append(ShellUtil::kRegShellOpen); | 661 key.append(ShellUtil::kRegShellOpen); |
| 675 InstallUtil::DeleteRegistryValue(root_key, key, | 662 InstallUtil::DeleteRegistryValue(root_key, key, |
| 676 ShellUtil::kRegDelegateExecute); | 663 ShellUtil::kRegDelegateExecute); |
| 677 } | 664 } |
| 678 } | 665 } |
| 679 | 666 |
| 667 // Returns true if the current user-level install has been registered without | |
| 668 // a suffix. This is used to support old installs where we used to not suffix | |
| 669 // user-level installs if they were the first to request the non-suffixed | |
| 670 // registry entries on the machine. This however created clashes with | |
| 671 // system-level installs when updating user-level installs to system-level | |
| 672 // installs. There is no downside to suffixing anyways (the name registered is | |
| 673 // not user visible). | |
| 674 // All the conditions below have to be true for it to return true: | |
| 675 // - Software\Clients\StartMenuInternet\Chromium\"" key should have a valid | |
| 676 // value. | |
| 677 // - The value should be same as given value in |chrome_exe|. | |
| 678 bool CurrentUserIsRegisteredWithNoSuffix(BrowserDistribution* dist, | |
| 679 const string16& chrome_exe) { | |
|
grt (UTC plus 2)
2012/05/30 20:37:40
nit: indentation
gab
2012/05/31 06:36:01
Done.
| |
| 680 // Assert that a Chrome is registered under | |
| 681 // HKLM\Software\Clients\StartMenuInternet\Google Chrome | |
| 682 const string16 reg_key( | |
| 683 RegistryEntry::GetBrowserClientKey(dist, string16()) | |
| 684 .append(ShellUtil::kRegShellOpen)); | |
| 685 RegKey key(HKEY_LOCAL_MACHINE, reg_key.c_str(), KEY_READ); | |
| 686 string16 registry_chrome_exe; | |
| 687 if ((key.ReadValue(L"", ®istry_chrome_exe) != ERROR_SUCCESS) || | |
| 688 registry_chrome_exe.length() < 2) { | |
| 689 return false; | |
| 690 } | |
| 691 | |
| 692 // Assert that the Chrome registered there is |chrome_exe| (i.e. this user's | |
|
grt (UTC plus 2)
2012/05/30 20:37:40
String comparisons of paths make me uncomfortable.
gab
2012/05/31 06:36:01
This code was copied from the old AnotherUserHasDe
| |
| 693 // Chrome). | |
| 694 registry_chrome_exe = registry_chrome_exe.substr(1, | |
| 695 registry_chrome_exe.length() - 2); | |
| 696 if (registry_chrome_exe.size() != chrome_exe.size() || | |
| 697 !std::equal(chrome_exe.begin(), chrome_exe.end(), | |
| 698 registry_chrome_exe.begin(), | |
| 699 base::CaseInsensitiveCompare<wchar_t>())) { | |
| 700 return false; | |
| 701 } | |
| 702 | |
| 703 return true; | |
| 704 } | |
| 705 | |
| 706 // Sets |suffix| to this user's username preceded by a dot. This suffix is then | |
| 707 // meant to be added to all registration that may conflict with another | |
| 708 // user-level Chrome install. | |
| 709 // Returns true unless the OS call to retrieve the username fails. | |
| 710 bool GetUserSpecificRegistrySuffix(string16* suffix) { | |
| 711 wchar_t user_name[256]; | |
| 712 DWORD size = arraysize(user_name); | |
| 713 if (::GetUserName(user_name, &size) == 0 || size < 1) { | |
| 714 LOG(DFATAL) << "Failed to get username in " << __FUNCTION__ << "."; | |
|
grt (UTC plus 2)
2012/05/30 20:37:40
I think you can remove __FUNCTION__ since it doesn
gab
2012/05/31 06:36:01
Ok, my thinking was that it's quite a generic stri
grt (UTC plus 2)
2012/06/04 02:18:26
I find __FUNCTION__ can be really helpful in tests
gab
2012/06/05 19:50:02
Ah ok, hadn't realized file and line were logged,
| |
| 715 return false; | |
| 716 } | |
| 717 suffix->reserve(size); | |
| 718 suffix->assign(1, L'.'); | |
| 719 suffix->append(user_name, size - 1); | |
| 720 return true; | |
| 721 } | |
| 722 | |
| 723 // Sets |suffix| to the current user's username on user-level installs. | |
|
grt (UTC plus 2)
2012/05/30 20:37:40
Regarding "to the current user's username": please
gab
2012/05/31 06:36:01
Done.
| |
| 724 // To support old-style user-level installs however, |suffix| is cleared if | |
| 725 // the user currently owns the non-suffixed HKLM registrations. | |
| 726 // |suffix| is also cleared on system-level installs. | |
| 727 // |suffix| should then be appended to all Chrome properties that may conflict | |
| 728 // with other Chrome user-level installs. | |
| 729 // Returns true unless one of the underlying calls fails. | |
| 730 bool GetInstallationSpecificSuffix(BrowserDistribution* dist, | |
| 731 const string16& chrome_exe, | |
| 732 string16* suffix) { | |
| 733 if (!InstallUtil::IsPerUserInstall(chrome_exe.c_str()) || | |
| 734 CurrentUserIsRegisteredWithNoSuffix(dist, chrome_exe)) { | |
| 735 // No suffix on system-level installs and user-level installs already | |
| 736 // registered with no suffix. | |
| 737 *suffix = L""; | |
| 738 return true; | |
| 739 } else { | |
| 740 return GetUserSpecificRegistrySuffix(suffix); | |
| 741 } | |
| 742 } | |
| 743 | |
| 680 } // namespace | 744 } // namespace |
| 681 | 745 |
| 682 const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon"; | 746 const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon"; |
| 683 const wchar_t* ShellUtil::kRegShellPath = L"\\shell"; | 747 const wchar_t* ShellUtil::kRegShellPath = L"\\shell"; |
| 684 const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command"; | 748 const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command"; |
| 685 const wchar_t* ShellUtil::kRegStartMenuInternet = | 749 const wchar_t* ShellUtil::kRegStartMenuInternet = |
| 686 L"Software\\Clients\\StartMenuInternet"; | 750 L"Software\\Clients\\StartMenuInternet"; |
| 687 const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes"; | 751 const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes"; |
| 688 const wchar_t* ShellUtil::kRegRegisteredApplications = | 752 const wchar_t* ShellUtil::kRegRegisteredApplications = |
| 689 L"Software\\RegisteredApplications"; | 753 L"Software\\RegisteredApplications"; |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 916 KEY_QUERY_VALUE) != ERROR_SUCCESS || | 980 KEY_QUERY_VALUE) != ERROR_SUCCESS || |
| 917 key.ReadValue(kReinstallCommand, &command) != ERROR_SUCCESS) { | 981 key.ReadValue(kReinstallCommand, &command) != ERROR_SUCCESS) { |
| 918 continue; | 982 continue; |
| 919 } | 983 } |
| 920 if (!name.empty() && !command.empty() && | 984 if (!name.empty() && !command.empty() && |
| 921 name.find(dist->GetApplicationName()) == string16::npos) | 985 name.find(dist->GetApplicationName()) == string16::npos) |
| 922 (*browsers)[name] = command; | 986 (*browsers)[name] = command; |
| 923 } | 987 } |
| 924 } | 988 } |
| 925 | 989 |
| 926 bool ShellUtil::GetUserSpecificDefaultBrowserSuffix(BrowserDistribution* dist, | 990 string16 ShellUtil::GetCurrentInstallationSuffix() { |
| 927 string16* entry) { | 991 // Make sure we return an empty suffix if this is a system-level install. |
| 928 wchar_t user_name[256]; | 992 // This check is needed because it is technically possible for a system-level |
| 929 DWORD size = arraysize(user_name); | 993 // install to run when a suffixed user-level is present (if the user never |
| 930 if (::GetUserName(user_name, &size) == 0 || size < 1) | 994 // runs his user-level install after a system-level Chrome is installed and |
| 931 return false; | 995 // instead runs the system-level chrome himself from Program Files...). In the |
| 932 entry->reserve(size); | 996 // unlikely event that we cannot get the path to chrome exe however, skip |
| 933 entry->assign(1, L'.'); | 997 // this check as it is already checking for a corner case... |
| 934 entry->append(user_name, size - 1); | 998 FilePath chrome_exe; |
| 999 bool skip_system_install_check = false; | |
| 1000 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { | |
|
grt (UTC plus 2)
2012/05/30 20:37:40
In general, we should strive to not do this PathSe
gab
2012/05/31 06:36:01
Right, I don't like it either, the problem though
grt (UTC plus 2)
2012/06/04 02:18:26
My suggestion was to change the function signature
gab
2012/06/05 19:50:02
Ah ok yes, makes sense.
Done.
| |
| 1001 LOG(DFATAL) << "Failed to get the path to chrome exe in " << __FUNCTION__; | |
| 1002 skip_system_install_check = true; | |
| 1003 } | |
| 935 | 1004 |
| 936 return RegKey(HKEY_LOCAL_MACHINE, | 1005 string16 tested_suffix; |
| 937 RegistryEntry::GetBrowserClientKey(dist, *entry).c_str(), | 1006 if ((!skip_system_install_check && |
| 938 KEY_READ).Valid(); | 1007 !InstallUtil::IsPerUserInstall(chrome_exe.value().c_str())) || |
| 1008 !GetUserSpecificRegistrySuffix(&tested_suffix) || | |
| 1009 !RegistryEntry::IsChromeRegisteredWithSuffix(tested_suffix)) { | |
|
grt (UTC plus 2)
2012/05/30 20:37:40
What's the motivation for looking at the ProgID ra
gab
2012/05/31 06:36:01
Chrome can have only its ProgIds registered (if th
| |
| 1010 return L""; | |
| 1011 } | |
| 1012 return tested_suffix; | |
| 1013 } | |
| 1014 | |
| 1015 bool ShellUtil::IsInstallationPresentInHKLM(BrowserDistribution* dist, | |
| 1016 const string16& chrome_exe, | |
| 1017 const string16& suffix) { | |
| 1018 std::list<RegistryEntry*> entries; | |
| 1019 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); | |
| 1020 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries); | |
| 1021 return AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKLM); | |
| 939 } | 1022 } |
| 940 | 1023 |
| 941 bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist, | 1024 bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist, |
| 942 int shell_change, | 1025 int shell_change, |
| 943 const string16& chrome_exe, | 1026 const string16& chrome_exe, |
| 944 bool elevate_if_not_admin) { | 1027 bool elevate_if_not_admin) { |
| 945 if (!dist->CanSetAsDefault()) | 1028 if (!dist->CanSetAsDefault()) |
| 946 return false; | 1029 return false; |
| 947 | 1030 |
| 948 ShellUtil::RegisterChromeBrowser(dist, chrome_exe, L"", elevate_if_not_admin); | 1031 ShellUtil::RegisterChromeBrowser(dist, chrome_exe, L"", elevate_if_not_admin); |
|
grt (UTC plus 2)
2012/05/30 20:37:40
Can anything good happen in MakeChromeDefault if R
gab
2012/05/31 06:36:01
Done.
| |
| 949 | 1032 |
| 950 bool ret = true; | 1033 bool ret = true; |
| 951 // First use the new "recommended" way on Vista to make Chrome default | 1034 // First use the new "recommended" way on Vista to make Chrome default |
| 952 // browser. | 1035 // browser. |
| 953 string16 app_name = dist->GetApplicationName(); | 1036 string16 app_name = dist->GetApplicationName(); |
| 954 string16 app_suffix; | 1037 const string16 app_suffix(ShellUtil::GetCurrentInstallationSuffix()); |
| 955 if (ShellUtil::GetUserSpecificDefaultBrowserSuffix(dist, &app_suffix)) | 1038 app_name += app_suffix; |
| 956 app_name += app_suffix; | |
| 957 | 1039 |
| 958 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { | 1040 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { |
| 959 // On Windows 8, you can't set yourself as the default handler | 1041 // On Windows 8, you can't set yourself as the default handler |
| 960 // programatically. In other words IApplicationAssociationRegistration | 1042 // programatically. In other words IApplicationAssociationRegistration |
| 961 // has been rendered useless. What you can do is to launch | 1043 // has been rendered useless. What you can do is to launch |
| 962 // "Set Program Associations" section of the "Default Programs" | 1044 // "Set Program Associations" section of the "Default Programs" |
| 963 // control panel. This action does not require elevation and we | 1045 // control panel. This action does not require elevation and we |
| 964 // don't get to control window activation. More info at: | 1046 // don't get to control window activation. More info at: |
| 965 // http://msdn.microsoft.com/en-us/library/cc144154(VS.85).aspx | 1047 // http://msdn.microsoft.com/en-us/library/cc144154(VS.85).aspx |
| 966 return LaunchApplicationAssociationDialog(app_name.c_str()); | 1048 return LaunchApplicationAssociationDialog(app_name.c_str()); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 996 } | 1078 } |
| 997 } | 1079 } |
| 998 | 1080 |
| 999 // Now use the old way to associate Chrome with supported protocols and file | 1081 // 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 | 1082 // associations. This should not be required on Vista but since some |
| 1001 // applications still read Software\Classes\http key directly, we have to do | 1083 // applications still read Software\Classes\http key directly, we have to do |
| 1002 // this on Vista also. | 1084 // this on Vista also. |
| 1003 | 1085 |
| 1004 std::list<RegistryEntry*> entries; | 1086 std::list<RegistryEntry*> entries; |
| 1005 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); | 1087 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); |
| 1006 string16 suffix; | 1088 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. | 1089 // Change the default browser for current user. |
| 1011 if ((shell_change & ShellUtil::CURRENT_USER) && | 1090 if ((shell_change & ShellUtil::CURRENT_USER) && |
| 1012 !AddRegistryEntries(HKEY_CURRENT_USER, entries)) { | 1091 !AddRegistryEntries(HKEY_CURRENT_USER, entries)) { |
| 1013 ret = false; | 1092 ret = false; |
| 1014 LOG(ERROR) << "Could not make Chrome default browser (XP/current user)."; | 1093 LOG(ERROR) << "Could not make Chrome default browser (XP/current user)."; |
| 1015 } | 1094 } |
| 1016 | 1095 |
| 1017 // Chrome as default browser at system level. | 1096 // Chrome as default browser at system level. |
| 1018 if ((shell_change & ShellUtil::SYSTEM_LEVEL) && | 1097 if ((shell_change & ShellUtil::SYSTEM_LEVEL) && |
| 1019 !AddRegistryEntries(HKEY_LOCAL_MACHINE, entries)) { | 1098 !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 | 1118 // First use the new "recommended" way on Vista to make Chrome default |
| 1040 // protocol handler. | 1119 // protocol handler. |
| 1041 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { | 1120 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { |
| 1042 VLOG(1) << "Registering Chrome as default handler for " << protocol | 1121 VLOG(1) << "Registering Chrome as default handler for " << protocol |
| 1043 << " on Vista."; | 1122 << " on Vista."; |
| 1044 base::win::ScopedComPtr<IApplicationAssociationRegistration> pAAR; | 1123 base::win::ScopedComPtr<IApplicationAssociationRegistration> pAAR; |
| 1045 HRESULT hr = pAAR.CreateInstance(CLSID_ApplicationAssociationRegistration, | 1124 HRESULT hr = pAAR.CreateInstance(CLSID_ApplicationAssociationRegistration, |
| 1046 NULL, CLSCTX_INPROC); | 1125 NULL, CLSCTX_INPROC); |
| 1047 if (SUCCEEDED(hr)) { | 1126 if (SUCCEEDED(hr)) { |
| 1048 string16 app_name = dist->GetApplicationName(); | 1127 string16 app_name = dist->GetApplicationName(); |
| 1049 string16 suffix; | 1128 app_name += ShellUtil::GetCurrentInstallationSuffix(); |
| 1050 if (ShellUtil::GetUserSpecificDefaultBrowserSuffix(dist, &suffix)) | |
| 1051 app_name += suffix; | |
| 1052 | 1129 |
| 1053 hr = pAAR->SetAppAsDefault(app_name.c_str(), protocol.c_str(), | 1130 hr = pAAR->SetAppAsDefault(app_name.c_str(), protocol.c_str(), |
| 1054 AT_URLPROTOCOL); | 1131 AT_URLPROTOCOL); |
| 1055 } | 1132 } |
| 1056 if (!SUCCEEDED(hr)) { | 1133 if (!SUCCEEDED(hr)) { |
| 1057 ret = false; | 1134 ret = false; |
| 1058 LOG(ERROR) << "Could not make Chrome default protocol client (Vista):" | 1135 LOG(ERROR) << "Could not make Chrome default protocol client (Vista):" |
| 1059 << " HRESULT=" << hr << "."; | 1136 << " HRESULT=" << hr << "."; |
| 1060 } | 1137 } |
| 1061 } | 1138 } |
| 1062 | 1139 |
| 1063 // Now use the old way to associate Chrome with the desired protocol. This | 1140 // 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 | 1141 // 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. | 1142 // Software\Classes\http key directly, we have to do this on Vista also. |
| 1066 | 1143 |
| 1067 std::list<RegistryEntry*> entries; | 1144 std::list<RegistryEntry*> entries; |
| 1068 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); | 1145 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); |
| 1069 string16 suffix; | 1146 const string16 suffix(ShellUtil::GetCurrentInstallationSuffix()); |
| 1070 if (!GetUserSpecificDefaultBrowserSuffix(dist, &suffix)) | 1147 const string16 chrome_open(ShellUtil::GetChromeShellOpenCmd(chrome_exe)); |
| 1071 suffix = L""; | 1148 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, | 1149 RegistryEntry::GetUserProtocolEntries(protocol, chrome_icon, chrome_open, |
| 1075 &entries); | 1150 &entries); |
| 1076 // Change the default protocol handler for current user. | 1151 // Change the default protocol handler for current user. |
| 1077 if (!AddRegistryEntries(HKEY_CURRENT_USER, entries)) { | 1152 if (!AddRegistryEntries(HKEY_CURRENT_USER, entries)) { |
| 1078 ret = false; | 1153 ret = false; |
| 1079 LOG(ERROR) << "Could not make Chrome default protocol client (XP)."; | 1154 LOG(ERROR) << "Could not make Chrome default protocol client (XP)."; |
| 1080 } | 1155 } |
| 1081 | 1156 |
| 1082 return ret; | 1157 return ret; |
| 1083 } | 1158 } |
| 1084 | 1159 |
| 1085 bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist, | 1160 bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist, |
| 1086 const string16& chrome_exe, | 1161 const string16& chrome_exe, |
| 1087 const string16& unique_suffix, | 1162 const string16& unique_suffix, |
| 1088 bool elevate_if_not_admin) { | 1163 bool elevate_if_not_admin) { |
| 1089 if (!dist->CanSetAsDefault()) | 1164 if (!dist->CanSetAsDefault()) |
| 1090 return false; | 1165 return false; |
| 1091 | 1166 |
| 1092 // First figure out we need to append a suffix to the registry entries to | |
| 1093 // make them unique. | |
| 1094 string16 suffix; | 1167 string16 suffix; |
| 1095 if (!unique_suffix.empty()) { | 1168 if (!unique_suffix.empty()) { |
| 1096 suffix = unique_suffix; | 1169 suffix = unique_suffix; |
| 1097 } else if (InstallUtil::IsPerUserInstall(chrome_exe.c_str()) && | 1170 } else if (!GetInstallationSpecificSuffix(dist, chrome_exe, &suffix)) { |
| 1098 !GetUserSpecificDefaultBrowserSuffix(dist, &suffix) && | 1171 return false; |
| 1099 !AnotherUserHasDefaultBrowser(dist, chrome_exe)) { | |
| 1100 suffix = L""; | |
| 1101 } | 1172 } |
| 1102 | 1173 |
| 1103 // TODO(grt): remove this on or after 2012-08-01; see impl for details. | 1174 // TODO(grt): remove this on or after 2012-08-01; see impl for details. |
| 1104 RemoveBadWindows8RegistrationIfNeeded(dist, chrome_exe, suffix); | 1175 RemoveBadWindows8RegistrationIfNeeded(dist, chrome_exe); |
| 1105 | 1176 |
| 1106 // Check if Chromium is already registered with this suffix. | 1177 // Check if Chromium is already registered with this suffix. |
| 1107 if (IsChromeRegistered(dist, chrome_exe, suffix)) | 1178 if (IsChromeRegistered(dist, chrome_exe, suffix)) |
| 1108 return true; | 1179 return true; |
| 1109 | 1180 |
| 1110 // If user is an admin try to register and return the status. | 1181 // If user is an admin try to register and return the status. |
| 1111 if (IsUserAnAdmin()) { | 1182 if (IsUserAnAdmin()) { |
| 1112 std::list<RegistryEntry*> progids; | 1183 std::list<RegistryEntry*> progids; |
| 1113 STLElementDeleter<std::list<RegistryEntry*> > progids_deleter(&progids); | 1184 STLElementDeleter<std::list<RegistryEntry*> > progids_deleter(&progids); |
| 1114 std::list<RegistryEntry*> sys_entries; | 1185 std::list<RegistryEntry*> sys_entries; |
| 1115 STLElementDeleter<std::list<RegistryEntry*> > sys_deleter(&sys_entries); | 1186 STLElementDeleter<std::list<RegistryEntry*> > sys_deleter(&sys_entries); |
| 1116 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &progids); | 1187 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &progids); |
| 1117 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &sys_entries); | 1188 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &sys_entries); |
| 1118 return AddRegistryEntries( | 1189 return AddRegistryEntries( |
| 1119 InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? | 1190 InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? |
| 1120 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, | 1191 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, |
| 1121 progids) && | 1192 progids) && |
| 1122 AddRegistryEntries(HKEY_LOCAL_MACHINE, sys_entries); | 1193 AddRegistryEntries(HKEY_LOCAL_MACHINE, sys_entries); |
| 1123 } | 1194 } |
| 1124 | 1195 |
| 1125 // If user is not an admin and OS is Vista, try to elevate and register. | 1196 // If user is not an admin and OS is Vista, try to elevate and register. |
| 1126 if (elevate_if_not_admin && | 1197 if (elevate_if_not_admin && |
| 1127 base::win::GetVersion() >= base::win::VERSION_VISTA && | 1198 base::win::GetVersion() >= base::win::VERSION_VISTA && |
| 1128 ElevateAndRegisterChrome(dist, chrome_exe, suffix, L"")) | 1199 ElevateAndRegisterChrome(dist, chrome_exe, suffix, L"")) |
| 1129 return true; | 1200 return true; |
| 1130 | 1201 |
| 1131 // If we got to this point then all we can do is create ProgIds under HKCU | 1202 // 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; | 1203 std::list<RegistryEntry*> entries; |
| 1134 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); | 1204 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); |
| 1135 RegistryEntry::GetProgIdEntries(dist, chrome_exe, L"", &entries); | 1205 RegistryEntry::GetProgIdEntries(dist, chrome_exe, L"", &entries); |
| 1206 // Prefer to use |suffix|; unless Chrome's ProgIds are already registered with | |
| 1207 // no suffix (as per the old registration style): in which case some other | |
| 1208 // registry entries could refer to them and since we were not able to set our | |
| 1209 // HKLM entries above, we are better off not altering these here. | |
| 1210 if (!suffix.empty() && | |
| 1211 !AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU)) { | |
| 1212 entries.clear(); | |
| 1213 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries); | |
| 1214 } | |
| 1136 return AddRegistryEntries(HKEY_CURRENT_USER, entries); | 1215 return AddRegistryEntries(HKEY_CURRENT_USER, entries); |
| 1137 } | 1216 } |
| 1138 | 1217 |
| 1139 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, | 1218 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, |
| 1140 const string16& chrome_exe, | 1219 const string16& chrome_exe, |
| 1141 const string16& unique_suffix, | 1220 const string16& unique_suffix, |
| 1142 const string16& protocol, | 1221 const string16& protocol, |
| 1143 bool elevate_if_not_admin) { | 1222 bool elevate_if_not_admin) { |
| 1144 if (!dist->CanSetAsDefault()) | 1223 if (!dist->CanSetAsDefault()) |
| 1145 return false; | 1224 return false; |
| 1146 | 1225 |
| 1147 // Figure out we need to append a suffix to the registry entries to | |
| 1148 // make them unique. | |
| 1149 string16 suffix; | 1226 string16 suffix; |
| 1150 if (!unique_suffix.empty()) { | 1227 if (!unique_suffix.empty()) { |
| 1151 suffix = unique_suffix; | 1228 suffix = unique_suffix; |
| 1152 } else if (InstallUtil::IsPerUserInstall(chrome_exe.c_str()) && | 1229 } else if (!GetInstallationSpecificSuffix(dist, chrome_exe, &suffix)) { |
| 1153 !GetUserSpecificDefaultBrowserSuffix(dist, &suffix) && | 1230 return false; |
| 1154 !AnotherUserHasDefaultBrowser(dist, chrome_exe)) { | |
| 1155 suffix = L""; | |
| 1156 } | 1231 } |
| 1157 | 1232 |
| 1158 // Check if Chromium is already registered with this suffix. | 1233 // Check if Chromium is already registered with this suffix. |
| 1159 if (IsChromeRegisteredForProtocol(dist, suffix, protocol)) | 1234 if (IsChromeRegisteredForProtocol(dist, suffix, protocol)) |
| 1160 return true; | 1235 return true; |
| 1161 | 1236 |
| 1162 if (IsUserAnAdmin()) { | 1237 if (IsUserAnAdmin()) { |
| 1163 // We can do this operation directly. | 1238 // We can do this operation directly. |
| 1164 // If we're not registered at all, try to register. If that fails | 1239 // If we're not registered at all, try to register. If that fails |
| 1165 // we should give up. | 1240 // we should give up. |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1291 chrome_exe.c_str(), | 1366 chrome_exe.c_str(), |
| 1292 shortcut.c_str(), | 1367 shortcut.c_str(), |
| 1293 chrome_path.c_str(), | 1368 chrome_path.c_str(), |
| 1294 arguments.c_str(), | 1369 arguments.c_str(), |
| 1295 description.c_str(), | 1370 description.c_str(), |
| 1296 icon_path.c_str(), | 1371 icon_path.c_str(), |
| 1297 icon_index, | 1372 icon_index, |
| 1298 dist->GetBrowserAppId().c_str(), | 1373 dist->GetBrowserAppId().c_str(), |
| 1299 ConvertShellUtilShortcutOptionsToFileUtil(options)); | 1374 ConvertShellUtilShortcutOptionsToFileUtil(options)); |
| 1300 } | 1375 } |
| OLD | NEW |