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

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

Issue 10662052: Use a better registration suffix that will always be unique while respecting the MSDN rules (2nd tr… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: uninstall logic and thread-safe suffix caching Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/installer/util/shell_util.h ('k') | chrome/installer/util/shell_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // This file defines functions that integrate Chrome in Windows shell. These 5 // This file defines functions that integrate Chrome in Windows shell. These
6 // functions can be used by Chrome as well as Chrome installer. All of the 6 // functions can be used by Chrome as well as Chrome installer. All of the
7 // work is done by the local functions defined in anonymous namespace in 7 // work is done by the local functions defined in anonymous namespace in
8 // this class. 8 // this class.
9 9
10 #include "chrome/installer/util/shell_util.h" 10 #include "chrome/installer/util/shell_util.h"
11 11
12 #include <windows.h> 12 #include <windows.h>
13 #include <shlobj.h> 13 #include <shlobj.h>
14 14
15 #include <limits>
15 #include <list> 16 #include <list>
16 17
17 #include "base/command_line.h" 18 #include "base/command_line.h"
18 #include "base/file_path.h" 19 #include "base/file_path.h"
19 #include "base/file_util.h" 20 #include "base/file_util.h"
21 #include "base/lazy_instance.h"
20 #include "base/logging.h" 22 #include "base/logging.h"
23 #include "base/md5.h"
21 #include "base/memory/scoped_ptr.h" 24 #include "base/memory/scoped_ptr.h"
22 #include "base/path_service.h" 25 #include "base/path_service.h"
23 #include "base/stl_util.h" 26 #include "base/stl_util.h"
24 #include "base/string_number_conversions.h" 27 #include "base/string_number_conversions.h"
25 #include "base/string_split.h" 28 #include "base/string_split.h"
26 #include "base/string_util.h" 29 #include "base/string_util.h"
27 #include "base/utf_string_conversions.h" 30 #include "base/utf_string_conversions.h"
28 #include "base/values.h" 31 #include "base/values.h"
29 #include "base/win/registry.h" 32 #include "base/win/registry.h"
30 #include "base/win/scoped_comptr.h" 33 #include "base/win/scoped_comptr.h"
34 #include "base/win/win_util.h"
31 #include "base/win/windows_version.h" 35 #include "base/win/windows_version.h"
32 #include "chrome/common/chrome_constants.h" 36 #include "chrome/common/chrome_constants.h"
33 #include "chrome/common/chrome_switches.h" 37 #include "chrome/common/chrome_switches.h"
34 #include "chrome/installer/util/browser_distribution.h" 38 #include "chrome/installer/util/browser_distribution.h"
35 #include "chrome/installer/util/install_util.h" 39 #include "chrome/installer/util/install_util.h"
36 #include "chrome/installer/util/master_preferences.h" 40 #include "chrome/installer/util/master_preferences.h"
37 #include "chrome/installer/util/master_preferences_constants.h" 41 #include "chrome/installer/util/master_preferences_constants.h"
38 42
39 using base::win::RegKey; 43 using base::win::RegKey;
40 44
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 VER_SET_CONDITION(condition_mask, VER_BUILDNUMBER, VER_GREATER_EQUAL); 82 VER_SET_CONDITION(condition_mask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
79 VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); 83 VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
80 VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL); 84 VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
81 85
82 DWORD type_mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER | 86 DWORD type_mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER |
83 VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR; 87 VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR;
84 88
85 return VerifyVersionInfo(&min_version_info, type_mask, condition_mask) != 0; 89 return VerifyVersionInfo(&min_version_info, type_mask, condition_mask) != 0;
86 } 90 }
87 91
92 // Returns the current (or installed) browser's ProgId (e.g.
93 // "ChromeHTML|suffix|").
94 // |suffix| can be the empty string.
95 string16 GetBrowserProgId(const string16& suffix) {
96 string16 chrome_html(ShellUtil::kChromeHTMLProgId);
97 chrome_html.append(suffix);
98
99 // ProgIds cannot be longer than 39 characters.
100 // Ref: http://msdn.microsoft.com/en-us/library/aa911706.aspx.
101 // Make all new registrations comply with this requirement (existing
102 // registrations must be preserved).
103 string16 new_style_suffix;
104 if (ShellUtil::GetUserSpecificRegistrySuffix(&new_style_suffix) &&
105 suffix == new_style_suffix && chrome_html.length() > 39) {
106 NOTREACHED();
107 chrome_html.erase(39);
108 }
109 return chrome_html;
110 }
111
112 // This class is used to initialize and cache a base 32 encoding of the md5 hash
113 // of this user's username preceded by a dot.
114 // This is guaranteed to be unique on the machine and 27 characters long
115 // (including the '.').
116 // This is then meant to be used as a suffix on all registrations that may
117 // conflict with another user-level Chrome install.
118 class UserSpecificRegistrySuffix {
119 public:
120 UserSpecificRegistrySuffix() {
grt (UTC plus 2) 2012/07/05 20:00:19 style dictates not inlining like this even though
gab 2012/07/05 21:19:53 Oh interesting, I didn't know the compiler interpr
121 // Do all the initialization in the constructor to be able to build the
122 // suffix in a thread-safe manner when used in conjunction with a
123 // LazyInstance.
124 wchar_t user_name[256];
125 DWORD size = arraysize(user_name);
126 if (::GetUserName(user_name, &size) == 0 || size < 1) {
127 NOTREACHED();
128 return;
129 }
130 COMPILE_ASSERT(sizeof(base::MD5Digest) == 16, size_of_MD5_not_as_expected_);
131 base::MD5Digest md5_digest;
132 base::MD5Sum(user_name, size, &md5_digest);
grt (UTC plus 2) 2012/07/05 20:00:19 this includes the string terminator in the hash.
gab 2012/07/05 21:19:53 Changed to sid string.
133 const string16 base32_md5(
134 ShellUtil::ByteArrayToBase32(md5_digest.a, arraysize(md5_digest.a)));
135 // The value returned by the base32 algorithm above must never change and
136 // must always be 26 characters long (i.e. if someone ever moves this to
137 // base and implements the full base32 algorithm (i.e. with appended '='
138 // signs in the output), they must provide a flag to allow this method to
139 // still request the output with no appended '=' signs).
140 DCHECK_EQ(base32_md5.length(), 26U);
141 suffix_.reserve(base32_md5.length() + 1);
142 suffix_.assign(1, L'.');
143 suffix_.append(base32_md5);
144 }
145
146 bool GetSuffix(string16* suffix) {
147 if (suffix_.empty()) {
148 NOTREACHED();
149 return false;
150 }
151 suffix->assign(suffix_);
152 return true;
153 }
154
155 private:
156 string16 suffix_;
157
158 DISALLOW_COPY_AND_ASSIGN(UserSpecificRegistrySuffix);
159 }; // class UserSpecificRegistrySuffix
160
88 // This class represents a single registry entry. The objective is to 161 // This class represents a single registry entry. The objective is to
89 // encapsulate all the registry entries required for registering Chrome at one 162 // encapsulate all the registry entries required for registering Chrome at one
90 // place. This class can not be instantiated outside the class and the objects 163 // place. This class can not be instantiated outside the class and the objects
91 // of this class type can be obtained only by calling a static method of this 164 // of this class type can be obtained only by calling a static method of this
92 // class. 165 // class.
93 class RegistryEntry { 166 class RegistryEntry {
94 public: 167 public:
95 // A bit-field enum of places to look for this key in the Windows registry. 168 // A bit-field enum of places to look for this key in the Windows registry.
96 enum LookForIn { 169 enum LookForIn {
97 LOOK_IN_HKCU = 1 << 0, 170 LOOK_IN_HKCU = 1 << 0,
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>\command 247 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>\command
175 entries->push_front(new RegistryEntry(sub_path, delegate_command)); 248 entries->push_front(new RegistryEntry(sub_path, delegate_command));
176 entries->push_front(new RegistryEntry( 249 entries->push_front(new RegistryEntry(
177 sub_path, ShellUtil::kRegDelegateExecute, delegate_guid)); 250 sub_path, ShellUtil::kRegDelegateExecute, delegate_guid));
178 } 251 }
179 } 252 }
180 253
181 // File association ProgId 254 // File association ProgId
182 string16 chrome_html_prog_id(ShellUtil::kRegClasses); 255 string16 chrome_html_prog_id(ShellUtil::kRegClasses);
183 chrome_html_prog_id.push_back(FilePath::kSeparators[0]); 256 chrome_html_prog_id.push_back(FilePath::kSeparators[0]);
184 chrome_html_prog_id.append(ShellUtil::kChromeHTMLProgId); 257 chrome_html_prog_id.append(GetBrowserProgId(suffix));
185 chrome_html_prog_id.append(suffix);
186 entries->push_front(new RegistryEntry( 258 entries->push_front(new RegistryEntry(
187 chrome_html_prog_id, ShellUtil::kChromeHTMLProgIdDesc)); 259 chrome_html_prog_id, ShellUtil::kChromeHTMLProgIdDesc));
188 entries->push_front(new RegistryEntry( 260 entries->push_front(new RegistryEntry(
189 chrome_html_prog_id, ShellUtil::kRegUrlProtocol, L"")); 261 chrome_html_prog_id, ShellUtil::kRegUrlProtocol, L""));
190 entries->push_front(new RegistryEntry( 262 entries->push_front(new RegistryEntry(
191 chrome_html_prog_id + ShellUtil::kRegDefaultIcon, icon_path)); 263 chrome_html_prog_id + ShellUtil::kRegDefaultIcon, icon_path));
192 entries->push_front(new RegistryEntry( 264 entries->push_front(new RegistryEntry(
193 chrome_html_prog_id + ShellUtil::kRegShellOpen, open_cmd)); 265 chrome_html_prog_id + ShellUtil::kRegShellOpen, open_cmd));
194 if (set_delegate_execute) { 266 if (set_delegate_execute) {
195 entries->push_front(new RegistryEntry( 267 entries->push_front(new RegistryEntry(
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 } 299 }
228 300
229 // This method returns a list of the registry entries needed to declare a 301 // This method returns a list of the registry entries needed to declare a
230 // capability of handling a protocol on Windows. 302 // capability of handling a protocol on Windows.
231 static bool GetProtocolCapabilityEntries(BrowserDistribution* dist, 303 static bool GetProtocolCapabilityEntries(BrowserDistribution* dist,
232 const string16& suffix, 304 const string16& suffix,
233 const string16& protocol, 305 const string16& protocol,
234 std::list<RegistryEntry*>* entries) { 306 std::list<RegistryEntry*>* entries) {
235 entries->push_front(new RegistryEntry( 307 entries->push_front(new RegistryEntry(
236 GetCapabilitiesKey(dist, suffix).append(L"\\URLAssociations"), 308 GetCapabilitiesKey(dist, suffix).append(L"\\URLAssociations"),
237 protocol, string16(ShellUtil::kChromeHTMLProgId).append(suffix))); 309 protocol, GetBrowserProgId(suffix)));
238 return true; 310 return true;
239 } 311 }
240 312
241 // This method returns a list of all the registry entries required to fully 313 // This method returns a list of all the registry entries required to fully
242 // integrate Chrome with Windows (i.e. StartMenuInternet, Default Programs, 314 // integrate Chrome with Windows (i.e. StartMenuInternet, Default Programs,
243 // AppPaths, etc.). This entries need to be registered in HKLM prior to Win8. 315 // AppPaths, etc.). This entries need to be registered in HKLM prior to Win8.
244 static bool GetShellIntegrationEntries(BrowserDistribution* dist, 316 static bool GetShellIntegrationEntries(BrowserDistribution* dist,
245 const string16& chrome_exe, 317 const string16& chrome_exe,
246 const string16& suffix, 318 const string16& suffix,
247 std::list<RegistryEntry*>* entries) { 319 std::list<RegistryEntry*>* entries) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 dist->GetLongAppDescription())); 360 dist->GetLongAppDescription()));
289 entries->push_front(new RegistryEntry( 361 entries->push_front(new RegistryEntry(
290 capabilities, ShellUtil::kRegApplicationIcon, icon_path)); 362 capabilities, ShellUtil::kRegApplicationIcon, icon_path));
291 entries->push_front(new RegistryEntry( 363 entries->push_front(new RegistryEntry(
292 capabilities, ShellUtil::kRegApplicationName, 364 capabilities, ShellUtil::kRegApplicationName,
293 dist->GetAppShortCutName())); 365 dist->GetAppShortCutName()));
294 366
295 entries->push_front(new RegistryEntry(capabilities + L"\\Startmenu", 367 entries->push_front(new RegistryEntry(capabilities + L"\\Startmenu",
296 L"StartMenuInternet", reg_app_name)); 368 L"StartMenuInternet", reg_app_name));
297 369
298 string16 html_prog_id(ShellUtil::kChromeHTMLProgId); 370 string16 html_prog_id(GetBrowserProgId(suffix));
299 html_prog_id.append(suffix);
300 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { 371 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
301 entries->push_front(new RegistryEntry( 372 entries->push_front(new RegistryEntry(
302 capabilities + L"\\FileAssociations", 373 capabilities + L"\\FileAssociations",
303 ShellUtil::kFileAssociations[i], html_prog_id)); 374 ShellUtil::kFileAssociations[i], html_prog_id));
304 } 375 }
305 for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL; 376 for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL;
306 i++) { 377 i++) {
307 entries->push_front(new RegistryEntry( 378 entries->push_front(new RegistryEntry(
308 capabilities + L"\\URLAssociations", 379 capabilities + L"\\URLAssociations",
309 ShellUtil::kPotentialProtocolAssociations[i], html_prog_id)); 380 ShellUtil::kPotentialProtocolAssociations[i], html_prog_id));
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 return true; 429 return true;
359 } 430 }
360 431
361 // This method returns a list of all the user level registry entries that 432 // This method returns a list of all the user level registry entries that
362 // are needed to make Chromium default browser. 433 // are needed to make Chromium default browser.
363 static bool GetUserEntries(BrowserDistribution* dist, 434 static bool GetUserEntries(BrowserDistribution* dist,
364 const string16& chrome_exe, 435 const string16& chrome_exe,
365 const string16& suffix, 436 const string16& suffix,
366 std::list<RegistryEntry*>* entries) { 437 std::list<RegistryEntry*>* entries) {
367 // File extension associations. 438 // File extension associations.
368 string16 html_prog_id(ShellUtil::kChromeHTMLProgId); 439 string16 html_prog_id(GetBrowserProgId(suffix));
369 html_prog_id.append(suffix);
370 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { 440 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
371 string16 ext_key(ShellUtil::kRegClasses); 441 string16 ext_key(ShellUtil::kRegClasses);
372 ext_key.push_back(FilePath::kSeparators[0]); 442 ext_key.push_back(FilePath::kSeparators[0]);
373 ext_key.append(ShellUtil::kFileAssociations[i]); 443 ext_key.append(ShellUtil::kFileAssociations[i]);
374 entries->push_front(new RegistryEntry(ext_key, html_prog_id)); 444 entries->push_front(new RegistryEntry(ext_key, html_prog_id));
375 } 445 }
376 446
377 // Protocols associations. 447 // Protocols associations.
378 string16 chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe); 448 string16 chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
379 string16 chrome_icon = ShellUtil::GetChromeIcon(dist, chrome_exe); 449 string16 chrome_icon = ShellUtil::GetChromeIcon(dist, chrome_exe);
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 740
671 // <root hkey>\Software\Classes\<app_id> 741 // <root hkey>\Software\Classes\<app_id>
672 string16 key(ShellUtil::kRegClasses); 742 string16 key(ShellUtil::kRegClasses);
673 key.push_back(FilePath::kSeparators[0]); 743 key.push_back(FilePath::kSeparators[0]);
674 key.append(app_id); 744 key.append(app_id);
675 InstallUtil::DeleteRegistryKey(root_key, key); 745 InstallUtil::DeleteRegistryKey(root_key, key);
676 746
677 // <root hkey>\Software\Classes\ChromiumHTML[.user]\shell\open\command 747 // <root hkey>\Software\Classes\ChromiumHTML[.user]\shell\open\command
678 key = ShellUtil::kRegClasses; 748 key = ShellUtil::kRegClasses;
679 key.push_back(FilePath::kSeparators[0]); 749 key.push_back(FilePath::kSeparators[0]);
680 key.append(ShellUtil::kChromeHTMLProgId); 750 key.append(GetBrowserProgId(installation_suffix));
681 key.append(installation_suffix);
682 key.append(ShellUtil::kRegShellOpen); 751 key.append(ShellUtil::kRegShellOpen);
683 InstallUtil::DeleteRegistryValue(root_key, key, 752 InstallUtil::DeleteRegistryValue(root_key, key,
684 ShellUtil::kRegDelegateExecute); 753 ShellUtil::kRegDelegateExecute);
685 } 754 }
686 } 755 }
687 756
688 // Returns true if the current install's |chrome_exe| has been registered with 757 // Returns true if the current install's |chrome_exe| has been registered with
689 // |suffix|. 758 // |suffix|.
690 // |confirmation_level| is the level of verification desired as described in 759 // |confirmation_level| is the level of verification desired as described in
691 // the RegistrationConfirmationLevel enum above. 760 // the RegistrationConfirmationLevel enum above.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 // Assert that |reg_key| points to |chrome_exe| in HKLM. 809 // Assert that |reg_key| points to |chrome_exe| in HKLM.
741 const RegKey key_hklm(HKEY_LOCAL_MACHINE, reg_key.c_str(), KEY_QUERY_VALUE); 810 const RegKey key_hklm(HKEY_LOCAL_MACHINE, reg_key.c_str(), KEY_QUERY_VALUE);
742 string16 hklm_value; 811 string16 hklm_value;
743 if (key_hklm.ReadValue(L"", &hklm_value) == ERROR_SUCCESS) { 812 if (key_hklm.ReadValue(L"", &hklm_value) == ERROR_SUCCESS) {
744 return InstallUtil::ProgramCompare( 813 return InstallUtil::ProgramCompare(
745 FilePath(chrome_exe)).Evaluate(hklm_value); 814 FilePath(chrome_exe)).Evaluate(hklm_value);
746 } 815 }
747 return false; 816 return false;
748 } 817 }
749 818
750 // Sets |suffix| to this user's username preceded by a dot. This suffix is then 819 // Sets |suffix| to a 27 character string that is specific to this user on this
751 // meant to be added to all registration that may conflict with another 820 // machine (on user-level installs only).
752 // user-level Chrome install. 821 // To support old-style user-level installs however, |suffix| is cleared if the
753 // Returns true unless the OS call to retrieve the username fails. 822 // user currently owns the non-suffixed HKLM registrations.
754 bool GetUserSpecificRegistrySuffix(string16* suffix) { 823 // |suffix| can also be set to the user's username if the current install is
755 wchar_t user_name[256]; 824 // suffixed as per the old-style registrations.
756 DWORD size = arraysize(user_name); 825 // |suffix| is cleared on system-level installs.
757 if (::GetUserName(user_name, &size) == 0 || size < 1) {
758 PLOG(DFATAL) << "GetUserName failed";
759 return false;
760 }
761 suffix->reserve(size);
762 suffix->assign(1, L'.');
763 suffix->append(user_name, size - 1);
764 return true;
765 }
766
767 // Sets |suffix| to the current user's username, preceded by a dot, on
768 // user-level installs.
769 // To support old-style user-level installs however, |suffix| is cleared if
770 // the user currently owns the non-suffixed HKLM registrations.
771 // |suffix| is also cleared on system-level installs.
772 // |suffix| should then be appended to all Chrome properties that may conflict 826 // |suffix| should then be appended to all Chrome properties that may conflict
773 // with other Chrome user-level installs. 827 // with other Chrome user-level installs.
774 // Returns true unless one of the underlying calls fails. 828 // Returns true unless one of the underlying calls fails.
775 bool GetInstallationSpecificSuffix(BrowserDistribution* dist, 829 bool GetInstallationSpecificSuffix(BrowserDistribution* dist,
776 const string16& chrome_exe, 830 const string16& chrome_exe,
777 string16* suffix) { 831 string16* suffix) {
778 if (!InstallUtil::IsPerUserInstall(chrome_exe.c_str()) || 832 if (!InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ||
779 QuickIsChromeRegistered(dist, chrome_exe, string16(), 833 QuickIsChromeRegistered(dist, chrome_exe, string16(),
780 CONFIRM_SHELL_REGISTRATION)) { 834 CONFIRM_SHELL_REGISTRATION)) {
781 // No suffix on system-level installs and user-level installs already 835 // No suffix on system-level installs and user-level installs already
782 // registered with no suffix. 836 // registered with no suffix.
783 suffix->clear(); 837 suffix->clear();
784 return true; 838 return true;
785 } else {
786 return GetUserSpecificRegistrySuffix(suffix);
787 } 839 }
840
841 // Get the old suffix for the check below.
842 if (!ShellUtil::GetOldUserSpecificRegistrySuffix(suffix)) {
843 NOTREACHED();
844 return false;
845 }
846 if (QuickIsChromeRegistered(dist, chrome_exe, *suffix,
847 CONFIRM_SHELL_REGISTRATION)) {
848 // Username suffix for installs that are suffixed as per the old-style.
849 return true;
850 }
851
852 return ShellUtil::GetUserSpecificRegistrySuffix(suffix);
788 } 853 }
789 854
790 // Returns the root registry key (HKLM or HKCU) into which shell integration 855 // Returns the root registry key (HKLM or HKCU) into which shell integration
791 // registration for default protocols must be placed. As of Windows 8 everything 856 // registration for default protocols must be placed. As of Windows 8 everything
792 // can go in HKCU for per-user installs. 857 // can go in HKCU for per-user installs.
793 HKEY DetermineShellIntegrationRoot(bool is_per_user) { 858 HKEY DetermineShellIntegrationRoot(bool is_per_user) {
794 return is_per_user && base::win::GetVersion() >= base::win::VERSION_WIN8 ? 859 return is_per_user && base::win::GetVersion() >= base::win::VERSION_WIN8 ?
795 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; 860 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
796 } 861 }
797 862
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
1053 key.ReadValue(kReinstallCommand, &command) == ERROR_SUCCESS && 1118 key.ReadValue(kReinstallCommand, &command) == ERROR_SUCCESS &&
1054 !command.empty()) { 1119 !command.empty()) {
1055 (*browsers)[name] = command; 1120 (*browsers)[name] = command;
1056 } 1121 }
1057 } 1122 }
1058 } 1123 }
1059 } 1124 }
1060 1125
1061 string16 ShellUtil::GetCurrentInstallationSuffix(BrowserDistribution* dist, 1126 string16 ShellUtil::GetCurrentInstallationSuffix(BrowserDistribution* dist,
1062 const string16& chrome_exe) { 1127 const string16& chrome_exe) {
1128 // This method is somewhat the opposite of GetInstallationSpecificSuffix().
1129 // In this case we are not trying to determine the current suffix for the
1130 // upcoming installation (i.e. not trying to stick to a currently bad
1131 // registration style if one is present).
1132 // Here we want to determine which suffix we should use at run-time.
1133 // In order of preference, we prefer (for user-level installs):
1134 // 1) Base 32 encoding of the md5 hash of the username (new-style).
1135 // 2) Username (old-style).
1136 // 3) Unsuffixed (even worse).
1063 string16 tested_suffix; 1137 string16 tested_suffix;
1064 if (!InstallUtil::IsPerUserInstall(chrome_exe.c_str()) || 1138 if (InstallUtil::IsPerUserInstall(chrome_exe.c_str()) &&
1065 !GetUserSpecificRegistrySuffix(&tested_suffix) || 1139 (!GetUserSpecificRegistrySuffix(&tested_suffix) ||
1066 !QuickIsChromeRegistered(dist, chrome_exe, tested_suffix, 1140 !QuickIsChromeRegistered(dist, chrome_exe, tested_suffix,
1141 CONFIRM_PROGID_REGISTRATION)) &&
1142 (!GetOldUserSpecificRegistrySuffix(&tested_suffix) ||
1143 !QuickIsChromeRegistered(dist, chrome_exe, tested_suffix,
1144 CONFIRM_PROGID_REGISTRATION)) &&
1145 !QuickIsChromeRegistered(dist, chrome_exe, tested_suffix.erase(),
1067 CONFIRM_PROGID_REGISTRATION)) { 1146 CONFIRM_PROGID_REGISTRATION)) {
1068 return string16(); 1147 // If Chrome is not registered under any of the possible suffixes (e.g.
1148 // tests, Canary, etc.): use the new-style suffix at run-time.
1149 if (!GetUserSpecificRegistrySuffix(&tested_suffix))
1150 NOTREACHED();
1069 } 1151 }
1070 return tested_suffix; 1152 return tested_suffix;
1071 } 1153 }
1072 1154
1073 string16 ShellUtil::GetApplicationName(BrowserDistribution* dist, 1155 string16 ShellUtil::GetApplicationName(BrowserDistribution* dist,
1074 const string16& chrome_exe) { 1156 const string16& chrome_exe) {
1075 string16 app_name = dist->GetBaseAppName(); 1157 string16 app_name = dist->GetBaseAppName();
1076 app_name += GetCurrentInstallationSuffix(dist, chrome_exe); 1158 app_name += GetCurrentInstallationSuffix(dist, chrome_exe);
1077 return app_name; 1159 return app_name;
1078 } 1160 }
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after
1514 chrome_exe.c_str(), 1596 chrome_exe.c_str(),
1515 shortcut.c_str(), 1597 shortcut.c_str(),
1516 chrome_path.value().c_str(), 1598 chrome_path.value().c_str(),
1517 arguments.c_str(), 1599 arguments.c_str(),
1518 description.c_str(), 1600 description.c_str(),
1519 icon_path.c_str(), 1601 icon_path.c_str(),
1520 icon_index, 1602 icon_index,
1521 app_id.c_str(), 1603 app_id.c_str(),
1522 ConvertShellUtilShortcutOptionsToFileUtil(options)); 1604 ConvertShellUtilShortcutOptionsToFileUtil(options));
1523 } 1605 }
1606
1607 bool ShellUtil::GetUserSpecificRegistrySuffix(string16* suffix) {
1608 // Use a thread-safe cache for the user's suffix.
1609 static base::LazyInstance<UserSpecificRegistrySuffix>::Leaky suffix_instance =
1610 LAZY_INSTANCE_INITIALIZER;
1611 return suffix_instance.Get().GetSuffix(suffix);
1612 }
1613
1614 bool ShellUtil::GetOldUserSpecificRegistrySuffix(string16* suffix) {
gab 2012/07/03 22:36:07 I thought of also caching this one in the UserSpec
grt (UTC plus 2) 2012/07/05 20:00:19 It could be done with a single class/instance owne
gab 2012/07/05 21:19:53 Right, GetUserName is probably very low-height (an
1615 wchar_t user_name[256];
1616 DWORD size = arraysize(user_name);
1617 if (::GetUserName(user_name, &size) == 0 || size < 1) {
1618 NOTREACHED();
1619 return false;
1620 }
1621 suffix->reserve(size);
1622 suffix->assign(1, L'.');
1623 suffix->append(user_name, size - 1);
1624 return true;
1625 }
1626
1627 string16 ShellUtil::ByteArrayToBase32(const uint8* bytes, size_t size) {
1628 static const char kEncoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
1629
1630 // Eliminate special cases first.
1631 if (size == 0) {
1632 return string16();
1633 } else if (size == 1) {
1634 string16 ret;
1635 ret.push_back(kEncoding[(bytes[0] & 0xf8) >> 3]);
1636 ret.push_back(kEncoding[(bytes[0] & 0x07) << 2]);
1637 return ret;
1638 } else if (size >= std::numeric_limits<size_t>::max() / 8) {
1639 // If |size| is too big, the calculation of |encoded_length| below will
1640 // overflow.
1641 NOTREACHED();
1642 return string16();
1643 }
1644
1645 // Overestimate the number of bits in the string by 4 so that dividing by 5
1646 // is the equivalent of rounding up the actual number of bits divided by 5.
1647 const size_t encoded_length = (size * 8 + 4) / 5;
1648
1649 string16 ret;
1650 ret.reserve(encoded_length);
1651
1652 // A bit stream which will be read from the left and appended to from the
1653 // right as it's emptied.
1654 uint16 bit_stream = (bytes[0] << 8) + bytes[1];
1655 size_t next_byte_index = 2;
1656 int free_bits = 0;
1657 while (free_bits < 16) {
1658 // Extract the 5 leftmost bits in the stream
1659 ret.push_back(kEncoding[(bit_stream & 0xf800) >> 11]);
1660 bit_stream <<= 5;
1661 free_bits += 5;
1662
1663 // If there is enough room in the bit stream, inject another byte (if there
1664 // are any left...).
1665 if (free_bits >= 8 && next_byte_index < size) {
1666 free_bits -= 8;
1667 bit_stream += bytes[next_byte_index++] << free_bits;
1668 }
1669 }
1670
1671 DCHECK_EQ(ret.length(), encoded_length);
1672 return ret;
1673 }
OLDNEW
« no previous file with comments | « chrome/installer/util/shell_util.h ('k') | chrome/installer/util/shell_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698