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

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

Issue 10451074: Always suffix ChromeHTML entries on Windows for user-level installs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: nit Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // This file defines functions that integrate Chrome in Windows shell. These 5 // This file defines functions that integrate Chrome in Windows shell. These
6 // functions can be used by Chrome as well as Chrome installer. All of the 6 // functions can be used by Chrome as well as Chrome installer. All of the
7 // work is done by the local functions defined in anonymous namespace in 7 // work is done by the local functions defined in anonymous namespace in
8 // this class. 8 // this class.
9 9
10 #include "chrome/installer/util/shell_util.h" 10 #include "chrome/installer/util/shell_util.h"
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
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,
grt (UTC plus 2) 2012/06/04 02:18:26 consider adding LOOK_IN_HKCU_THEN_HKLM or somethin
gab 2012/06/05 19:50:02 Done.
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.
grt (UTC plus 2) 2012/06/04 02:18:26 Please explain in the comment why checking only th
gab 2012/06/05 19:50:02 Done in the new enum RegistrationConfirmationLevel
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(
grt (UTC plus 2) 2012/06/04 02:18:26 Checking that the description matches seems fragil
gab 2012/06/05 19:50:02 Done and merged in QuickChromeIsRegistered().
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
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
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.
412 bool ExistsInRegistry(uint32 look_for_in) const {
413 DCHECK(look_for_in);
414
415 RegistryStatus hkcu_status = DOES_NOT_EXIST;
416 if (look_for_in & LOOK_IN_HKCU)
417 hkcu_status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER);
418
419 RegistryStatus hklm_status = DOES_NOT_EXIST;
420 if (hkcu_status == DOES_NOT_EXIST && (look_for_in & LOOK_IN_HKLM))
421 hklm_status = StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE);
422
388 return (hkcu_status == SAME_VALUE || 423 return (hkcu_status == SAME_VALUE ||
389 (hkcu_status == DOES_NOT_EXIST && 424 (hkcu_status == DOES_NOT_EXIST && hklm_status == SAME_VALUE));
390 StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE) == SAME_VALUE));
391 } 425 }
392 426
393 private: 427 private:
394 // States this RegistryKey can be in compared to the registry. 428 // States this RegistryKey can be in compared to the registry.
395 enum RegistryStatus { 429 enum RegistryStatus {
396 // |_name| does not exist in the registry 430 // |_name| does not exist in the registry
397 DOES_NOT_EXIST, 431 DOES_NOT_EXIST,
398 // |_name| exists, but its value != |_value| 432 // |_name| exists, but its value != |_value|
399 DIFFERENT_VALUE, 433 DIFFERENT_VALUE,
400 // |_name| exists and its value is |_value| 434 // |_name| exists and its value is |_value|
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 (*itr)->AddToWorkItemList(root, items.get()); 497 (*itr)->AddToWorkItemList(root, items.get());
464 498
465 // Apply all the registry changes and if there is a problem, rollback 499 // Apply all the registry changes and if there is a problem, rollback
466 if (!items->Do()) { 500 if (!items->Do()) {
467 items->Rollback(); 501 items->Rollback();
468 return false; 502 return false;
469 } 503 }
470 return true; 504 return true;
471 } 505 }
472 506
507 // Returns true if any of the entries in |entries| are present on this computer.
508 // |look_for_in| is passed to RegistryEntry::ExistsInRegistry(). Documentation
509 // for it can be found there.
510 bool AreAnyEntriesRegistered(const std::list<RegistryEntry*>& entries,
511 uint32 look_for_in) {
grt (UTC plus 2) 2012/06/04 02:18:26 nit: indentation
gab 2012/06/05 19:50:02 Done.
512 bool any = false;
513 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin();
514 !any && itr != entries.end(); ++itr) {
515 // We do not need any = any && ... since the loop condition is set to exit
516 // early.
517 any = (*itr)->ExistsInRegistry(look_for_in);
518 }
519 return any;
520 }
521
473 // Checks that all |entries| are present on this computer. 522 // Checks that all |entries| are present on this computer.
474 bool AreEntriesRegistered(const std::list<RegistryEntry*>& entries) { 523 // |look_for_in| is passed to RegistryEntry::ExistsInRegistry(). Documentation
524 // for it can be found there.
525 bool AreEntriesRegistered(const std::list<RegistryEntry*>& entries,
526 uint32 look_for_in) {
475 bool registered = true; 527 bool registered = true;
476 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin(); 528 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin();
477 registered && itr != entries.end(); ++itr) { 529 registered && itr != entries.end(); ++itr) {
478 // We do not need registered = registered && ... since the loop condition 530 // We do not need registered = registered && ... since the loop condition
479 // is set to exit early. 531 // is set to exit early.
480 registered = (*itr)->ExistsInRegistry(); 532 registered = (*itr)->ExistsInRegistry(look_for_in);
481 } 533 }
482 return registered; 534 return registered;
483 } 535 }
484 536
485 // Checks that all required registry entries for Chrome are already present 537 // Checks that all required registry entries for Chrome are already present
486 // on this computer. 538 // on this computer.
487 bool IsChromeRegistered(BrowserDistribution* dist, 539 bool IsChromeRegistered(BrowserDistribution* dist,
488 const string16& chrome_exe, 540 const string16& chrome_exe,
489 const string16& suffix) { 541 const string16& suffix) {
490 std::list<RegistryEntry*> entries; 542 std::list<RegistryEntry*> entries;
491 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); 543 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries);
492 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries); 544 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries);
493 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries); 545 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries);
494 return AreEntriesRegistered(entries); 546 return AreEntriesRegistered(
547 entries, RegistryEntry::LOOK_IN_HKCU | RegistryEntry::LOOK_IN_HKLM);
495 } 548 }
496 549
497 // This method checks if Chrome is already registered on the local machine 550 // 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. 551 // for the requested protocol. It just checks the one value required for this.
499 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, 552 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist,
500 const string16& suffix, 553 const string16& suffix,
501 const string16& protocol) { 554 const string16& protocol) {
502 std::list<RegistryEntry*> entries; 555 std::list<RegistryEntry*> entries;
503 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries); 556 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries);
504 RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); 557 RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, &entries);
505 return AreEntriesRegistered(entries); 558 return AreEntriesRegistered(
559 entries, RegistryEntry::LOOK_IN_HKCU | RegistryEntry::LOOK_IN_HKLM);
506 } 560 }
507 561
508 // This method registers Chrome on Vista by launching an elevated setup.exe. 562 // 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 563 // 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 564 // accepts it the new process will make the necessary changes and return SUCCESS
511 // that we capture and return. 565 // that we capture and return.
512 // If protocol is non-empty we will also register Chrome as being capable of 566 // If protocol is non-empty we will also register Chrome as being capable of
513 // handling the protocol. 567 // handling the protocol.
514 bool ElevateAndRegisterChrome(BrowserDistribution* dist, 568 bool ElevateAndRegisterChrome(BrowserDistribution* dist,
515 const string16& chrome_exe, 569 const string16& chrome_exe,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 } 602 }
549 603
550 DWORD ret_val = 0; 604 DWORD ret_val = 0;
551 InstallUtil::ExecuteExeAsAdmin(cmd, &ret_val); 605 InstallUtil::ExecuteExeAsAdmin(cmd, &ret_val);
552 if (ret_val == 0) 606 if (ret_val == 0)
553 return true; 607 return true;
554 } 608 }
555 return false; 609 return false;
556 } 610 }
557 611
558 // This method tries to figure out if another user has already registered her
559 // own copy of Chrome so that we can avoid overwriting it and append current
560 // user's login name to default browser registry entries. This function is
561 // not meant to detect all cases. It just tries to handle the most common case.
562 // All the conditions below have to be true for it to return true:
563 // - Software\Clients\StartMenuInternet\Chromium\"" key should have a valid
564 // value.
565 // - The value should not be same as given value in |chrome_exe|
566 // - Finally to handle the default install path (C:\Document and Settings\
567 // <user>\Local Settings\Application Data\Chromium\Application) the value
568 // of the above key should differ from |chrome_exe| only in user name.
569 bool AnotherUserHasDefaultBrowser(BrowserDistribution* dist,
570 const string16& chrome_exe) {
571 const string16 reg_key(
572 RegistryEntry::GetBrowserClientKey(dist, string16())
573 .append(ShellUtil::kRegShellOpen));
574 RegKey key(HKEY_LOCAL_MACHINE, reg_key.c_str(), KEY_READ);
575 string16 registry_chrome_exe;
576 if ((key.ReadValue(L"", &registry_chrome_exe) != ERROR_SUCCESS) ||
577 registry_chrome_exe.length() < 2)
578 return false;
579
580 registry_chrome_exe = registry_chrome_exe.substr(1,
581 registry_chrome_exe.length() - 2);
582 if ((registry_chrome_exe.size() == chrome_exe.size()) &&
583 (std::equal(chrome_exe.begin(), chrome_exe.end(),
584 registry_chrome_exe.begin(),
585 base::CaseInsensitiveCompare<wchar_t>()))) {
586 return false;
587 }
588
589 std::vector<string16> v1, v2;
590 base::SplitString(registry_chrome_exe, L'\\', &v1);
591 base::SplitString(chrome_exe, L'\\', &v2);
592 if (v1.empty() || v2.empty() || v1.size() != v2.size())
593 return false;
594
595 // Now check that only one of the values within two '\' chars differ.
596 std::vector<string16>::iterator itr1 = v1.begin();
597 std::vector<string16>::iterator itr2 = v2.begin();
598 bool one_mismatch = false;
599 for ( ; itr1 < v1.end() && itr2 < v2.end(); ++itr1, ++itr2) {
600 string16 s1 = *itr1;
601 string16 s2 = *itr2;
602 if ((s1.size() != s2.size()) ||
603 (!std::equal(s1.begin(), s1.end(),
604 s2.begin(), base::CaseInsensitiveCompare<wchar_t>()))) {
605 if (one_mismatch)
606 return false;
607 else
608 one_mismatch = true;
609 }
610 }
611 return true;
612 }
613
614 // Launches the Windows 7 and Windows 8 application association dialog, which 612 // 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 613 // is the only documented way to make a browser the default browser on
616 // Windows 8. 614 // Windows 8.
617 bool LaunchApplicationAssociationDialog(const string16& app_id) { 615 bool LaunchApplicationAssociationDialog(const string16& app_id) {
618 base::win::ScopedComPtr<IApplicationAssociationRegistrationUI> aarui; 616 base::win::ScopedComPtr<IApplicationAssociationRegistrationUI> aarui;
619 HRESULT hr = aarui.CreateInstance(CLSID_ApplicationAssociationRegistrationUI); 617 HRESULT hr = aarui.CreateInstance(CLSID_ApplicationAssociationRegistrationUI);
620 if (FAILED(hr)) 618 if (FAILED(hr))
621 return false; 619 return false;
622 hr = aarui->LaunchAdvancedAssociationUI(app_id.c_str()); 620 hr = aarui->LaunchAdvancedAssociationUI(app_id.c_str());
623 return SUCCEEDED(hr); 621 return SUCCEEDED(hr);
(...skipping 16 matching lines...) Expand all
640 // should be removed after a reasonable time, say 2012-08-01. Anyone on Win8 638 // 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 639 // 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 640 // to uninstall and reinstall Chrome to repair. See http://crbug.com/124666 and
643 // http://crbug.com/123994 for gory details. 641 // http://crbug.com/123994 for gory details.
644 // This function is also used to remove DelegateExecute verb handler 642 // This function is also used to remove DelegateExecute verb handler
645 // registrations on builds for which Metro is no longer supported. This will 643 // registrations on builds for which Metro is no longer supported. This will
646 // also become irrelevant sometime after Windows 8 RC (thus the aforementioned 644 // also become irrelevant sometime after Windows 8 RC (thus the aforementioned
647 // removal date remains correct). 645 // removal date remains correct).
648 void RemoveBadWindows8RegistrationIfNeeded( 646 void RemoveBadWindows8RegistrationIfNeeded(
649 BrowserDistribution* dist, 647 BrowserDistribution* dist,
650 const string16& chrome_exe, 648 const string16& chrome_exe) {
651 const string16& suffix) {
652 string16 handler_guid; 649 string16 handler_guid;
653 650
654 if (dist->GetDelegateExecuteHandlerData(&handler_guid, NULL, NULL, NULL) && 651 if (dist->GetDelegateExecuteHandlerData(&handler_guid, NULL, NULL, NULL) &&
655 (!InstallUtil::HasDelegateExecuteHandler(dist, chrome_exe) || 652 (!InstallUtil::HasDelegateExecuteHandler(dist, chrome_exe) ||
656 !IsChromeMetroSupported())) { 653 !IsChromeMetroSupported())) {
657 // There's no need to rollback, so forgo the usual work item lists and just 654 // There's no need to rollback, so forgo the usual work item lists and just
658 // remove the values from the registry. 655 // remove the values from the registry.
659 const HKEY root_key = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? 656 const HKEY root_key = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ?
660 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; 657 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
658 // Use the current installation's suffix, not the about-to-be-installed
659 // suffix.
660 const string16 installation_suffix =
grt (UTC plus 2) 2012/06/04 02:18:26 nit: use () rather than =
gab 2012/06/05 19:50:02 Done.
661 ShellUtil::GetCurrentInstallationSuffix();
661 const string16 app_id(dist->GetBrowserAppId()); 662 const string16 app_id(dist->GetBrowserAppId());
662 663
663 // <root hkey>\Software\Classes\<app_id> 664 // <root hkey>\Software\Classes\<app_id>
664 string16 key(ShellUtil::kRegClasses); 665 string16 key(ShellUtil::kRegClasses);
665 key.push_back(FilePath::kSeparators[0]); 666 key.push_back(FilePath::kSeparators[0]);
666 key.append(app_id); 667 key.append(app_id);
667 InstallUtil::DeleteRegistryKey(root_key, key); 668 InstallUtil::DeleteRegistryKey(root_key, key);
668 669
669 // <root hkey>\Software\Classes\ChromiumHTML[.user]\shell\open\command 670 // <root hkey>\Software\Classes\ChromiumHTML[.user]\shell\open\command
670 key = ShellUtil::kRegClasses; 671 key = ShellUtil::kRegClasses;
671 key.push_back(FilePath::kSeparators[0]); 672 key.push_back(FilePath::kSeparators[0]);
672 key.append(ShellUtil::kChromeHTMLProgId); 673 key.append(ShellUtil::kChromeHTMLProgId);
673 key.append(suffix); 674 key.append(installation_suffix);
674 key.append(ShellUtil::kRegShellOpen); 675 key.append(ShellUtil::kRegShellOpen);
675 InstallUtil::DeleteRegistryValue(root_key, key, 676 InstallUtil::DeleteRegistryValue(root_key, key,
676 ShellUtil::kRegDelegateExecute); 677 ShellUtil::kRegDelegateExecute);
677 } 678 }
678 } 679 }
679 680
681 // Sets |suffix| to this user's username preceded by a dot. This suffix is then
682 // meant to be added to all registration that may conflict with another
683 // user-level Chrome install.
684 // Returns true unless the OS call to retrieve the username fails.
685 bool GetUserSpecificRegistrySuffix(string16* suffix) {
686 wchar_t user_name[256];
687 DWORD size = arraysize(user_name);
688 if (::GetUserName(user_name, &size) == 0 || size < 1) {
689 PLOG(DFATAL) << "Failed to get username from Windows.";
grt (UTC plus 2) 2012/06/04 02:18:26 nit: since this log string ends up in the binary,
gab 2012/06/05 19:50:02 Done.
690 return false;
691 }
692 suffix->reserve(size);
693 suffix->assign(1, L'.');
694 suffix->append(user_name, size - 1);
695 return true;
696 }
697
698 // Sets |suffix| to the current user's username, preceded by a dot, on
699 // user-level installs.
700 // To support old-style user-level installs however, |suffix| is cleared if
701 // the user currently owns the non-suffixed HKLM registrations.
702 // |suffix| is also cleared on system-level installs.
703 // |suffix| should then be appended to all Chrome properties that may conflict
704 // with other Chrome user-level installs.
705 // Returns true unless one of the underlying calls fails.
706 bool GetInstallationSpecificSuffix(BrowserDistribution* dist,
707 const string16& chrome_exe,
708 string16* suffix) {
709 if (!InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ||
710 ShellUtil::CurrentUserIsRegisteredWithNoSuffix(dist, chrome_exe)) {
711 // No suffix on system-level installs and user-level installs already
712 // registered with no suffix.
713 *suffix = L"";
grt (UTC plus 2) 2012/06/04 02:18:26 suffix->clear();
gab 2012/06/05 19:50:02 Done.
714 return true;
715 } else {
716 return GetUserSpecificRegistrySuffix(suffix);
717 }
718 }
719
680 } // namespace 720 } // namespace
681 721
682 const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon"; 722 const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon";
683 const wchar_t* ShellUtil::kRegShellPath = L"\\shell"; 723 const wchar_t* ShellUtil::kRegShellPath = L"\\shell";
684 const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command"; 724 const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command";
685 const wchar_t* ShellUtil::kRegStartMenuInternet = 725 const wchar_t* ShellUtil::kRegStartMenuInternet =
686 L"Software\\Clients\\StartMenuInternet"; 726 L"Software\\Clients\\StartMenuInternet";
687 const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes"; 727 const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes";
688 const wchar_t* ShellUtil::kRegRegisteredApplications = 728 const wchar_t* ShellUtil::kRegRegisteredApplications =
689 L"Software\\RegisteredApplications"; 729 L"Software\\RegisteredApplications";
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
916 KEY_QUERY_VALUE) != ERROR_SUCCESS || 956 KEY_QUERY_VALUE) != ERROR_SUCCESS ||
917 key.ReadValue(kReinstallCommand, &command) != ERROR_SUCCESS) { 957 key.ReadValue(kReinstallCommand, &command) != ERROR_SUCCESS) {
918 continue; 958 continue;
919 } 959 }
920 if (!name.empty() && !command.empty() && 960 if (!name.empty() && !command.empty() &&
921 name.find(dist->GetApplicationName()) == string16::npos) 961 name.find(dist->GetApplicationName()) == string16::npos)
922 (*browsers)[name] = command; 962 (*browsers)[name] = command;
923 } 963 }
924 } 964 }
925 965
926 bool ShellUtil::GetUserSpecificDefaultBrowserSuffix(BrowserDistribution* dist, 966 string16 ShellUtil::GetCurrentInstallationSuffix() {
927 string16* entry) { 967 // Make sure we return an empty suffix if this is a system-level install.
928 wchar_t user_name[256]; 968 // This check is needed because it is technically possible for a system-level
929 DWORD size = arraysize(user_name); 969 // install to run when a suffixed user-level is present (if the user never
930 if (::GetUserName(user_name, &size) == 0 || size < 1) 970 // runs his user-level install after a system-level Chrome is installed and
971 // instead runs the system-level chrome himself from Program Files...). In the
972 // unlikely event that we cannot get the path to chrome exe however, skip
973 // this check as it is already checking for a corner case...
974 FilePath chrome_exe;
975 bool skip_system_install_check = false;
976 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
977 LOG(DFATAL) << "Failed to get the path to chrome exe in " << __FUNCTION__;
978 skip_system_install_check = true;
979 }
980
981 string16 tested_suffix;
982 if ((!skip_system_install_check &&
983 !InstallUtil::IsPerUserInstall(chrome_exe.value().c_str())) ||
984 !GetUserSpecificRegistrySuffix(&tested_suffix) ||
985 !RegistryEntry::IsChromeRegisteredWithSuffix(tested_suffix)) {
986 return L"";
grt (UTC plus 2) 2012/06/04 02:18:26 L"" -> string16()
gab 2012/06/05 19:50:02 Done.
987 }
988 return tested_suffix;
989 }
990
991 bool ShellUtil::CurrentUserIsRegisteredWithNoSuffix(
992 BrowserDistribution* dist, const string16& chrome_exe) {
993 // Assert that a Chrome is registered under
994 // HKLM\Software\Clients\StartMenuInternet\Google Chrome
995 const string16 reg_key(
996 RegistryEntry::GetBrowserClientKey(dist, string16())
997 .append(ShellUtil::kRegShellOpen));
998 RegKey key(HKEY_LOCAL_MACHINE, reg_key.c_str(), KEY_READ);
999 string16 registry_chrome_exe;
1000 if ((key.ReadValue(L"", &registry_chrome_exe) != ERROR_SUCCESS) ||
1001 registry_chrome_exe.length() < 2) {
931 return false; 1002 return false;
932 entry->reserve(size); 1003 }
933 entry->assign(1, L'.');
934 entry->append(user_name, size - 1);
935 1004
936 return RegKey(HKEY_LOCAL_MACHINE, 1005 // Assert that the Chrome registered there is |chrome_exe| (i.e. this user's
937 RegistryEntry::GetBrowserClientKey(dist, *entry).c_str(), 1006 // Chrome).
938 KEY_READ).Valid(); 1007 FilePath registry_chrome_exe_path(registry_chrome_exe);
1008 InstallUtil::ProgramCompare comparator(registry_chrome_exe_path);
grt (UTC plus 2) 2012/06/04 02:18:26 PC's ctor takes chrome_exe and Evaluate takes a re
gab 2012/06/05 19:50:02 Changed to QuickIsChromeRegistered() and added log
1009 return comparator.Evaluate(chrome_exe);
1010 }
1011
1012 bool ShellUtil::IsInstallationPresentInHKLM(BrowserDistribution* dist,
1013 const string16& chrome_exe,
1014 const string16& suffix) {
1015 std::list<RegistryEntry*> entries;
1016 STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries);
1017 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries);
1018 return AreAnyEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKLM);
grt (UTC plus 2) 2012/06/04 02:18:26 This will return true for an unsuffixed user-level
gab 2012/06/05 19:50:02 Removed.
939 } 1019 }
940 1020
941 bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist, 1021 bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist,
942 int shell_change, 1022 int shell_change,
943 const string16& chrome_exe, 1023 const string16& chrome_exe,
944 bool elevate_if_not_admin) { 1024 bool elevate_if_not_admin) {
945 if (!dist->CanSetAsDefault()) 1025 if (!dist->CanSetAsDefault())
946 return false; 1026 return false;
947 1027
948 ShellUtil::RegisterChromeBrowser(dist, chrome_exe, L"", elevate_if_not_admin); 1028 if (!ShellUtil::RegisterChromeBrowser(
1029 dist, chrome_exe, L"", elevate_if_not_admin)) {
grt (UTC plus 2) 2012/06/04 02:18:26 L"" -> string16()
gab 2012/06/05 19:50:02 Done.
1030 return false;
1031 }
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
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
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(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)) {
grt (UTC plus 2) 2012/06/04 02:18:26 there's no need to AddRegistryEntries if AreEntrie
gab 2012/06/05 19:50:02 Indeed :), the one nice thing with the previous lo
1212 entries.clear();
grt (UTC plus 2) 2012/06/04 02:18:26 entries.clear() -> STLDeleteElements(entries)
gab 2012/06/05 19:50:02 Done.
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
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 }
OLDNEW
« chrome/installer/setup/uninstall.cc ('K') | « chrome/installer/util/shell_util.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698