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

Unified Diff: chrome/installer/util/shell_util.cc

Issue 10617002: Use a better registration suffix that will always be unique while respecting the MSDN rules. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 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 side-by-side diff with in-line comments
Download patch
« base/win/win_util.cc ('K') | « chrome/installer/util/shell_util.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/installer/util/shell_util.cc
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index 2dc53ef030a988f9c8045d235cebf828f154de85..f27da4065bed322f4c590d7c8e1245681e20f7bb 100644
--- a/chrome/installer/util/shell_util.cc
+++ b/chrome/installer/util/shell_util.cc
@@ -28,6 +28,7 @@
#include "base/values.h"
#include "base/win/registry.h"
#include "base/win/scoped_comptr.h"
+#include "base/win/win_util.h"
#include "base/win/windows_version.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
@@ -85,6 +86,64 @@ bool IsChromeMetroSupported() {
return VerifyVersionInfo(&min_version_info, type_mask, condition_mask) != 0;
}
+// Sets |suffix| to a base 16 encoding of this user's sid preceded by a dot.
+// This suffix is then meant to be added to all registration that may conflict
+// with another user-level Chrome install.
+// This is guaranteed to be 25 characters (including the dot).
+// Note that prior to Chrome 21, the suffix registered used to be the user's
+// username (see GetOldUserSpecificRegistrySuffix() below). We still honor old
+// installs registered that way, but it was wrong because some of the characters
+// allowed in a username are not allowed in a ProgId.
+// Returns true unless the OS call to retrieve the username fails.
+bool GetNewUserSpecificRegistrySuffix(string16* suffix) {
+ string16 encoded_sid;
+ if (!base::win::GetUserSidBase16Encoded(&encoded_sid)) {
+ PLOG(DFATAL) << "GetUserSidBase16Encoded failed";
+ return false;
+ }
+ suffix->reserve(encoded_sid.length() + 1);
+ suffix->assign(1, L'.');
+ suffix->append(encoded_sid);
+ return true;
+}
+
+// Sets |suffix| to this user's username preceded by a dot. This suffix is then
+// meant to be added to all registration that may conflict with another
+// user-level Chrome install.
+// Returns true unless the OS call to retrieve the username fails.
+bool GetOldUserSpecificRegistrySuffix(string16* suffix) {
gab 2012/06/21 05:55:41 This is not new, simply moved from lower to avoid
+ wchar_t user_name[256];
+ DWORD size = arraysize(user_name);
+ if (::GetUserName(user_name, &size) == 0 || size < 1) {
+ PLOG(DFATAL) << "GetUserName failed";
+ return false;
+ }
+ suffix->reserve(size);
+ suffix->assign(1, L'.');
+ suffix->append(user_name, size - 1);
+ return true;
+}
+
+// Returns Chrome's ProgId as "ChromeHTML|suffix|".
grt (UTC plus 2) 2012/06/22 14:08:24 although there are other funcs in this file with C
gab 2012/06/22 18:24:04 Done.
+// |suffix| can be the empty string.
+string16 GetChromeHTMLProgId(const string16& suffix) {
grt (UTC plus 2) 2012/06/22 14:08:24 i'm not too fond of the fact that this is called a
gab 2012/06/22 18:24:04 Done. Cached it locally as a static variable whic
+ string16 chrome_html(ShellUtil::kChromeHTMLProgId);
+ chrome_html.append(suffix);
+
+ // ProgIds cannot be longer than 39 characters.
+ // Ref: http://msdn.microsoft.com/en-us/library/aa911706.aspx.
+ // We can however only make sure it's compliant with MSDN in the new-style of
grt (UTC plus 2) 2012/06/22 14:08:24 suggest: "Make all new registrations comply with t
gab 2012/06/22 18:24:04 Done.
+ // registrations as we didn't respect this before (and can't go back on what's
+ // currently installed).
+ string16 new_style_suffix;
+ if (GetNewUserSpecificRegistrySuffix(&new_style_suffix) &&
+ suffix.compare(new_style_suffix) == 0 && chrome_html.length() > 39) {
+ LOG(DFATAL) << "The suffixed ProgId is longer than 39 characters.";
grt (UTC plus 2) 2012/06/22 14:08:24 suggest NOTREACHED(); since the log will be meanin
gab 2012/06/22 18:24:04 Done.
+ chrome_html.erase(39, string16::npos);
grt (UTC plus 2) 2012/06/22 14:08:24 chrome_html.erase(39);
gab 2012/06/22 18:24:04 Done.
+ }
+ return chrome_html;
+}
+
// This class represents a single registry entry. The objective is to
// encapsulate all the registry entries required for registering Chrome at one
// place. This class can not be instantiated outside the class and the objects
@@ -181,8 +240,7 @@ class RegistryEntry {
// File association ProgId
string16 chrome_html_prog_id(ShellUtil::kRegClasses);
chrome_html_prog_id.push_back(FilePath::kSeparators[0]);
- chrome_html_prog_id.append(ShellUtil::kChromeHTMLProgId);
- chrome_html_prog_id.append(suffix);
+ chrome_html_prog_id.append(GetChromeHTMLProgId(suffix));
entries->push_front(new RegistryEntry(
chrome_html_prog_id, ShellUtil::kChromeHTMLProgIdDesc));
entries->push_front(new RegistryEntry(
@@ -234,7 +292,7 @@ class RegistryEntry {
std::list<RegistryEntry*>* entries) {
entries->push_front(new RegistryEntry(
GetCapabilitiesKey(dist, suffix).append(L"\\URLAssociations"),
- protocol, string16(ShellUtil::kChromeHTMLProgId).append(suffix)));
+ protocol, GetChromeHTMLProgId(suffix)));
return true;
}
@@ -295,8 +353,7 @@ class RegistryEntry {
entries->push_front(new RegistryEntry(capabilities + L"\\Startmenu",
L"StartMenuInternet", reg_app_name));
- string16 html_prog_id(ShellUtil::kChromeHTMLProgId);
- html_prog_id.append(suffix);
+ string16 html_prog_id(GetChromeHTMLProgId(suffix));
for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
entries->push_front(new RegistryEntry(
capabilities + L"\\FileAssociations",
@@ -365,8 +422,7 @@ class RegistryEntry {
const string16& suffix,
std::list<RegistryEntry*>* entries) {
// File extension associations.
- string16 html_prog_id(ShellUtil::kChromeHTMLProgId);
- html_prog_id.append(suffix);
+ string16 html_prog_id(GetChromeHTMLProgId(suffix));
for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
string16 ext_key(ShellUtil::kRegClasses);
ext_key.push_back(FilePath::kSeparators[0]);
@@ -677,8 +733,7 @@ void RemoveBadWindows8RegistrationIfNeeded(
// <root hkey>\Software\Classes\ChromiumHTML[.user]\shell\open\command
key = ShellUtil::kRegClasses;
key.push_back(FilePath::kSeparators[0]);
- key.append(ShellUtil::kChromeHTMLProgId);
- key.append(installation_suffix);
+ key.append(GetChromeHTMLProgId(installation_suffix));
key.append(ShellUtil::kRegShellOpen);
InstallUtil::DeleteRegistryValue(root_key, key,
ShellUtil::kRegDelegateExecute);
@@ -747,28 +802,13 @@ bool QuickIsChromeRegistered(BrowserDistribution* dist,
return false;
}
-// Sets |suffix| to this user's username preceded by a dot. This suffix is then
-// meant to be added to all registration that may conflict with another
-// user-level Chrome install.
-// Returns true unless the OS call to retrieve the username fails.
-bool GetUserSpecificRegistrySuffix(string16* suffix) {
- wchar_t user_name[256];
- DWORD size = arraysize(user_name);
- if (::GetUserName(user_name, &size) == 0 || size < 1) {
- PLOG(DFATAL) << "GetUserName failed";
- return false;
- }
- suffix->reserve(size);
- suffix->assign(1, L'.');
- suffix->append(user_name, size - 1);
- return true;
-}
-
-// Sets |suffix| to the current user's username, preceded by a dot, on
-// user-level installs.
+// Sets |suffix| to a base 16 encoding of this user's sid preceded by a dot, on
+// user-level installs, preferably.
// To support old-style user-level installs however, |suffix| is cleared if
// the user currently owns the non-suffixed HKLM registrations.
-// |suffix| is also cleared on system-level installs.
+// |suffix| can also be set to the user's username if the current install
+// is suffixed as per the old-style registrations.
+// |suffix| is cleared on system-level installs.
// |suffix| should then be appended to all Chrome properties that may conflict
// with other Chrome user-level installs.
// Returns true unless one of the underlying calls fails.
@@ -782,9 +822,19 @@ bool GetInstallationSpecificSuffix(BrowserDistribution* dist,
// registered with no suffix.
suffix->clear();
return true;
- } else {
- return GetUserSpecificRegistrySuffix(suffix);
}
+
+ string16 old_suffix;
+ if (!GetOldUserSpecificRegistrySuffix(&old_suffix)) {
+ return false;
+ } else if (QuickIsChromeRegistered(dist, chrome_exe, old_suffix,
+ CONFIRM_SHELL_REGISTRATION)) {
+ // Username suffix for installs that are suffixed as per the old-style.
+ suffix->assign(old_suffix);
+ return true;
+ }
+
+ return GetNewUserSpecificRegistrySuffix(suffix);
}
// Returns the root registry key (HKLM or HKCU) into which shell integration
@@ -1060,11 +1110,26 @@ void ShellUtil::GetRegisteredBrowsers(
string16 ShellUtil::GetCurrentInstallationSuffix(BrowserDistribution* dist,
const string16& chrome_exe) {
+ // This method is somewhat the opposite of GetInstallationSpecificSuffix().
+ // In this case we are not trying to determine the current suffix for the
+ // upcoming installation (i.e. not trying to stick to a currently bad
+ // registration style if one is present).
+ // Here we want to determine which suffix we should use at run-time.
+ // In order of preference, we prefer (for user-level installs):
+ // 1) Base 16 encoded sid (new-style).
+ // 2) Username (old-style).
+ // 3) Unsuffixed (even worst).
string16 tested_suffix;
if (!InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ||
- !GetUserSpecificRegistrySuffix(&tested_suffix) ||
+ !GetNewUserSpecificRegistrySuffix(&tested_suffix) ||
grt (UTC plus 2) 2012/06/22 14:08:24 a failure in GetNewUserSpecificRegistrySuffix mean
gab 2012/06/22 18:24:04 Ah yes, good catch, changed it to check old suffix
+ !QuickIsChromeRegistered(dist, chrome_exe, tested_suffix,
+ CONFIRM_PROGID_REGISTRATION) ||
+ !GetOldUserSpecificRegistrySuffix(&tested_suffix) ||
!QuickIsChromeRegistered(dist, chrome_exe, tested_suffix,
CONFIRM_PROGID_REGISTRATION)) {
+ DCHECK(InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ||
grt (UTC plus 2) 2012/06/22 14:08:24 it's not clear to me what this is checking. shoul
gab 2012/06/22 18:24:04 Ah yes, good catch :)! Added a comment to clarify.
+ QuickIsChromeRegistered(dist, chrome_exe, string16(),
+ CONFIRM_PROGID_REGISTRATION));
return string16();
}
return tested_suffix;
@@ -1082,7 +1147,7 @@ string16 ShellUtil::GetBrowserModelId(BrowserDistribution* dist,
string16 app_id(dist->GetBaseAppId());
string16 suffix;
if (InstallUtil::IsPerUserInstall(chrome_exe.c_str()) &&
- !GetUserSpecificRegistrySuffix(&suffix)) {
+ !GetNewUserSpecificRegistrySuffix(&suffix)) {
NOTREACHED();
}
// There is only one component (i.e. the suffixed appid) in this case, but it
« base/win/win_util.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