summaryrefslogtreecommitdiffstats
path: root/chrome/installer
diff options
context:
space:
mode:
authorgrt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-02 15:34:07 +0000
committergrt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-02 15:34:07 +0000
commitf1a761f802d0c1712571d4bca05af620cda5eee6 (patch)
tree00dbe54c53d6563d7b9a60c27dc11adf6d70c047 /chrome/installer
parentd583c3a30db9474b0dcef5128ec6901c8ff23b98 (diff)
downloadchromium_src-f1a761f802d0c1712571d4bca05af620cda5eee6.zip
chromium_src-f1a761f802d0c1712571d4bca05af620cda5eee6.tar.gz
chromium_src-f1a761f802d0c1712571d4bca05af620cda5eee6.tar.bz2
Fix default browser registration for simplified chinese installs.
http://crrev.com/13341 and http://crrev.com/13906, which fixed http://crbug.com/9697, switched from using chrome.exe as the canonical name of Chrome (for purposes of shell registration) to using the localized application name (e.g., "Chromium" or "Google Chrome"). This is problematic since there are differences between the various locales as to what the app name is. This change switches to using a non-localized version of the product name. The right thing to do would really be to switch back to using the executable name (as prescribed by MSDN), except for the case of Chromium builds, where "chromium.exe" could be used. Making that change now would mean potentially re-prompting users to make Chrome their default browser, which would be bad. BUG=92445 TEST=Verify that Google Chrome and Chromium builds can coexist, and that each can be made the default browser. Furthermore, ensure that, for user-level and system-level installs, all of the usual shell registration things work: the Start Menu's "Internet" link (icon and action), running "chrome.exe" (without path) from the Run... dialog, clicking a link in some other program, typeing a URL into the Run... dialog, "Set your default programs" control panel, "Set program access and computer defaults" control panel. Also, verify that if Chrome is installed using zn-CH locale and made the default, that switching to another locale (like en-US) doesn't cause Chrome to prompt to become the default browser. Review URL: http://codereview.chromium.org/8384038 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108297 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/installer')
-rw-r--r--chrome/installer/setup/setup_main.cc10
-rw-r--r--chrome/installer/setup/uninstall.cc98
-rw-r--r--chrome/installer/setup/uninstall.h2
-rw-r--r--chrome/installer/util/browser_distribution.h3
-rw-r--r--chrome/installer/util/chrome_frame_distribution.cc4
-rw-r--r--chrome/installer/util/chrome_frame_distribution.h2
-rw-r--r--chrome/installer/util/chromium_binaries_distribution.cc24
-rw-r--r--chrome/installer/util/google_chrome_distribution.cc7
-rw-r--r--chrome/installer/util/google_chrome_sxs_distribution.cc4
-rw-r--r--chrome/installer/util/google_chrome_sxs_distribution.h15
-rw-r--r--chrome/installer/util/install_util.cc16
-rw-r--r--chrome/installer/util/install_util.h33
-rw-r--r--chrome/installer/util/install_util_unittest.cc55
-rw-r--r--chrome/installer/util/shell_util.cc153
14 files changed, 260 insertions, 166 deletions
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 702893f..be33736 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -717,10 +717,10 @@ installer::InstallStatus InstallProductsHelper(
}
} else if ((install_status == installer::NEW_VERSION_UPDATED) ||
(install_status == installer::IN_USE_UPDATED)) {
- for (size_t i = 0; i < products.size(); ++i) {
- installer::RemoveLegacyRegistryKeys(
- products[i]->distribution());
- }
+ const Product* chrome = installer_state.FindProduct(
+ BrowserDistribution::CHROME_BROWSER);
+ if (chrome != NULL)
+ installer::RemoveChromeLegacyRegistryKeys(chrome->distribution());
}
}
}
@@ -1323,7 +1323,7 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
::MessageBoxW(NULL,
installer::GetLocalizedString(
IDS_UNINSTALL_COMPLETE_BASE).c_str(),
- cf_install->distribution()->GetApplicationName().c_str(),
+ cf_install->distribution()->GetAppShortCutName().c_str(),
MB_OK);
}
}
diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc
index 883c208..b25b03c 100644
--- a/chrome/installer/setup/uninstall.cc
+++ b/chrome/installer/setup/uninstall.cc
@@ -217,26 +217,29 @@ void CloseChromeFrameHelperProcess() {
}
// This method tries to figure out if current user has registered Chrome.
-// It returns true iff:
-// - Software\Clients\StartMenuInternet\Chromium\"" key has a valid value.
-// - The value is same as chrome.exe path for the current installation.
-bool CurrentUserHasDefaultBrowser(const InstallerState& installer_state,
- const Product& product) {
- std::wstring reg_key(ShellUtil::kRegStartMenuInternet);
- reg_key.append(1, L'\\')
- .append(product.distribution()->GetApplicationName())
- .append(ShellUtil::kRegShellOpen);
- RegKey key(HKEY_LOCAL_MACHINE, reg_key.c_str(), KEY_READ);
+// It returns true iff there is a registered browser that will launch the
+// same chrome.exe as the current installation.
+bool CurrentUserHasDefaultBrowser(const InstallerState& installer_state) {
+ using base::win::RegistryKeyIterator;
+ const HKEY root = HKEY_LOCAL_MACHINE;
+ ProgramCompare open_command_pred(
+ installer_state.target_path().Append(kChromeExe));
+ std::wstring client_open_path;
+ RegKey client_open_key;
std::wstring reg_exe;
- if (key.ReadValue(L"", &reg_exe) == ERROR_SUCCESS && reg_exe.length() > 2) {
- FilePath chrome_exe(installer_state.target_path()
- .Append(installer::kChromeExe));
- // The path in the registry will always have quotes.
- reg_exe = reg_exe.substr(1, reg_exe.length() - 2);
- if (FilePath::CompareEqualIgnoreCase(reg_exe, chrome_exe.value()))
+ for (RegistryKeyIterator iter(root, ShellUtil::kRegStartMenuInternet);
+ iter.Valid(); ++iter) {
+ client_open_path.assign(ShellUtil::kRegStartMenuInternet)
+ .append(1, L'\\')
+ .append(iter.Name())
+ .append(ShellUtil::kRegShellOpen);
+ if (client_open_key.Open(root, client_open_path.c_str(),
+ KEY_QUERY_VALUE) == ERROR_SUCCESS &&
+ client_open_key.ReadValue(L"", &reg_exe) == ERROR_SUCCESS &&
+ open_command_pred.Evaluate(reg_exe)) {
return true;
+ }
}
-
return false;
}
@@ -526,24 +529,47 @@ bool DeleteChromeRegistrationKeys(BrowserDistribution* dist, HKEY root,
return true;
}
+ FilePath chrome_exe(target_path.Append(kChromeExe));
+
// Delete Software\Classes\ChromeHTML,
std::wstring html_prog_id(ShellUtil::kRegClasses);
file_util::AppendToPath(&html_prog_id, ShellUtil::kChromeHTMLProgId);
html_prog_id.append(browser_entry_suffix);
InstallUtil::DeleteRegistryKey(root, html_prog_id);
- // Delete Software\Clients\StartMenuInternet\Chromium
- std::wstring set_access_key(ShellUtil::kRegStartMenuInternet);
- file_util::AppendToPath(&set_access_key, dist->GetApplicationName());
- set_access_key.append(browser_entry_suffix);
- InstallUtil::DeleteRegistryKey(root, set_access_key);
-
- // We have renamed the StartMenuInternet\chrome.exe to
- // StartMenuInternet\Chromium so for old users we still need to delete
- // the old key.
- std::wstring old_set_access_key(ShellUtil::kRegStartMenuInternet);
- file_util::AppendToPath(&old_set_access_key, installer::kChromeExe);
- InstallUtil::DeleteRegistryKey(root, old_set_access_key);
+ // Delete all Start Menu Internet registrations that refer to this Chrome.
+ {
+ using base::win::RegistryKeyIterator;
+ ProgramCompare open_command_pred(chrome_exe);
+ std::wstring client_name;
+ std::wstring client_key;
+ std::wstring open_key;
+ for (RegistryKeyIterator iter(root, ShellUtil::kRegStartMenuInternet);
+ iter.Valid(); ++iter) {
+ client_name.assign(iter.Name());
+ client_key.assign(ShellUtil::kRegStartMenuInternet)
+ .append(1, L'\\')
+ .append(client_name);
+ open_key.assign(client_key).append(ShellUtil::kRegShellOpen);
+ if (InstallUtil::DeleteRegistryKeyIf(root, client_key, open_key, L"",
+ open_command_pred) != InstallUtil::NOT_FOUND) {
+ // Delete the default value of SOFTWARE\Clients\StartMenuInternet if it
+ // references this Chrome (i.e., if it was made the default browser).
+ InstallUtil::DeleteRegistryValueIf(
+ root, ShellUtil::kRegStartMenuInternet, L"",
+ InstallUtil::ValueEquals(client_name));
+ // Also delete the value for the default user if we're operating in
+ // HKLM.
+ if (root == HKEY_LOCAL_MACHINE) {
+ InstallUtil::DeleteRegistryValueIf(
+ HKEY_USERS,
+ std::wstring(L".DEFAULT\\").append(
+ ShellUtil::kRegStartMenuInternet).c_str(),
+ L"", InstallUtil::ValueEquals(client_name));
+ }
+ }
+ }
+ }
// Delete Software\RegisteredApplications\Chromium
InstallUtil::DeleteRegistryValue(root, ShellUtil::kRegRegisteredApplications,
@@ -573,14 +599,16 @@ bool DeleteChromeRegistrationKeys(BrowserDistribution* dist, HKEY root,
// Cleanup in case Chrome had been made the default browser.
// Delete the default value of SOFTWARE\Clients\StartMenuInternet if it
- // references this Chrome.
+ // references this Chrome. Do this explicitly here for the case where HKCU is
+ // being processed; the iteration above will have no hits since registration
+ // lives in HKLM.
InstallUtil::DeleteRegistryValueIf(
root, ShellUtil::kRegStartMenuInternet, L"",
InstallUtil::ValueEquals(dist->GetApplicationName() +
browser_entry_suffix));
// Delete each protocol association if it references this Chrome.
- ProgramCompare open_command_pred(target_path.Append(kChromeExe));
+ ProgramCompare open_command_pred(chrome_exe);
std::wstring parent_key(ShellUtil::kRegClasses);
const std::wstring::size_type base_length = parent_key.size();
std::wstring child_key;
@@ -610,7 +638,7 @@ bool DeleteChromeRegistrationKeys(BrowserDistribution* dist, HKEY root,
return true;
}
-void RemoveLegacyRegistryKeys(BrowserDistribution* dist) {
+void RemoveChromeLegacyRegistryKeys(BrowserDistribution* dist) {
// We used to register Chrome to handle crx files, but this turned out
// to be not worth the hassle. Remove these old registry entries if
// they exist. See: http://codereview.chromium.org/210007
@@ -690,8 +718,7 @@ InstallStatus UninstallProduct(const InstallationState& original_state,
// another uninstaller (silent) in elevated mode to do HKLM cleanup.
// And continue uninstalling in the current process also to do HKCU cleanup.
if (remove_all &&
- (!suffix.empty() ||
- CurrentUserHasDefaultBrowser(installer_state, product)) &&
+ (!suffix.empty() || CurrentUserHasDefaultBrowser(installer_state)) &&
!::IsUserAnAdmin() &&
base::win::GetVersion() >= base::win::VERSION_VISTA &&
!cmd_line.HasSwitch(installer::switches::kRunAsAdmin)) {
@@ -747,8 +774,7 @@ InstallStatus UninstallProduct(const InstallationState& original_state,
// Registration data is put in HKLM for system level and possibly user level
// installs (when Chrome is made the default browser at install-time).
if (installer_state.system_install() || remove_all &&
- (!suffix.empty() || CurrentUserHasDefaultBrowser(installer_state,
- product))) {
+ (!suffix.empty() || CurrentUserHasDefaultBrowser(installer_state))) {
DeleteChromeRegistrationKeys(product.distribution(), HKEY_LOCAL_MACHINE,
suffix, installer_state.target_path(), &ret);
}
diff --git a/chrome/installer/setup/uninstall.h b/chrome/installer/setup/uninstall.h
index 49fd352..ef5c4ef 100644
--- a/chrome/installer/setup/uninstall.h
+++ b/chrome/installer/setup/uninstall.h
@@ -37,7 +37,7 @@ bool DeleteChromeRegistrationKeys(BrowserDistribution* dist, HKEY root,
// Removes any legacy registry keys from earlier versions of Chrome that are no
// longer needed. This is used during autoupdate since we don't do full
// uninstalls/reinstalls to update.
-void RemoveLegacyRegistryKeys(BrowserDistribution* dist);
+void RemoveChromeLegacyRegistryKeys(BrowserDistribution* dist);
// This function uninstalls a product. Hence we came up with this awesome
// name for it.
diff --git a/chrome/installer/util/browser_distribution.h b/chrome/installer/util/browser_distribution.h
index 6d92501..58ab51c 100644
--- a/chrome/installer/util/browser_distribution.h
+++ b/chrome/installer/util/browser_distribution.h
@@ -70,8 +70,11 @@ class BrowserDistribution {
virtual std::wstring GetAppGuid();
+ // Returns the name by which the program is registered with Default Programs.
+ // This is not a localized string suitable for presenting to a user.
virtual std::wstring GetApplicationName();
+ // Returns the localized name of the program.
virtual std::wstring GetAppShortCutName();
virtual std::wstring GetAlternateApplicationName();
diff --git a/chrome/installer/util/chrome_frame_distribution.cc b/chrome/installer/util/chrome_frame_distribution.cc
index 7305fdc..f4fa099 100644
--- a/chrome/installer/util/chrome_frame_distribution.cc
+++ b/chrome/installer/util/chrome_frame_distribution.cc
@@ -34,6 +34,10 @@ std::wstring ChromeFrameDistribution::GetAppGuid() {
}
std::wstring ChromeFrameDistribution::GetApplicationName() {
+ return L"Google Chrome Frame";
+}
+
+std::wstring ChromeFrameDistribution::GetAppShortCutName() {
const std::wstring& product_name =
installer::GetLocalizedString(IDS_PRODUCT_FRAME_NAME_BASE);
return product_name;
diff --git a/chrome/installer/util/chrome_frame_distribution.h b/chrome/installer/util/chrome_frame_distribution.h
index f8078d4..e5124a8 100644
--- a/chrome/installer/util/chrome_frame_distribution.h
+++ b/chrome/installer/util/chrome_frame_distribution.h
@@ -25,6 +25,8 @@ class ChromeFrameDistribution : public BrowserDistribution {
virtual std::wstring GetApplicationName() OVERRIDE;
+ virtual std::wstring GetAppShortCutName() OVERRIDE;
+
virtual std::wstring GetAlternateApplicationName() OVERRIDE;
virtual std::wstring GetInstallSubDir() OVERRIDE;
diff --git a/chrome/installer/util/chromium_binaries_distribution.cc b/chrome/installer/util/chromium_binaries_distribution.cc
index 8e39ffb..de57e0d 100644
--- a/chrome/installer/util/chromium_binaries_distribution.cc
+++ b/chrome/installer/util/chromium_binaries_distribution.cc
@@ -25,7 +25,7 @@ std::wstring ChromiumBinariesDistribution::GetAppGuid() {
}
std::wstring ChromiumBinariesDistribution::GetApplicationName() {
- NOTREACHED() << "GetApplicationName unsupported";
+ NOTREACHED();
return std::wstring();
}
@@ -34,12 +34,12 @@ std::wstring ChromiumBinariesDistribution::GetAppShortCutName() {
}
std::wstring ChromiumBinariesDistribution::GetAlternateApplicationName() {
- NOTREACHED() << "GetApplicationName unsupported";
+ NOTREACHED();
return std::wstring();
}
std::wstring ChromiumBinariesDistribution::GetBrowserAppId() {
- NOTREACHED() << "GetApplicationName unsupported";
+ NOTREACHED();
return std::wstring();
}
@@ -48,22 +48,22 @@ std::wstring ChromiumBinariesDistribution::GetInstallSubDir() {
}
std::wstring ChromiumBinariesDistribution::GetPublisherName() {
- NOTREACHED() << "GetApplicationName unsupported";
+ NOTREACHED();
return std::wstring();
}
std::wstring ChromiumBinariesDistribution::GetAppDescription() {
- NOTREACHED() << "GetApplicationName unsupported";
+ NOTREACHED();
return std::wstring();
}
std::wstring ChromiumBinariesDistribution::GetLongAppDescription() {
- NOTREACHED() << "GetApplicationName unsupported";
+ NOTREACHED();
return std::wstring();
}
std::string ChromiumBinariesDistribution::GetSafeBrowsingName() {
- NOTREACHED() << "GetApplicationName unsupported";
+ NOTREACHED();
return std::string();
}
@@ -76,12 +76,12 @@ std::wstring ChromiumBinariesDistribution::GetStateMediumKey() {
}
std::wstring ChromiumBinariesDistribution::GetUninstallLinkName() {
- NOTREACHED() << "GetApplicationName unsupported";
+ NOTREACHED();
return std::wstring();
}
std::wstring ChromiumBinariesDistribution::GetUninstallRegPath() {
- NOTREACHED() << "GetApplicationName unsupported";
+ NOTREACHED();
return std::wstring();
}
@@ -90,16 +90,16 @@ std::wstring ChromiumBinariesDistribution::GetVersionKey() {
}
bool ChromiumBinariesDistribution::CanSetAsDefault() {
- NOTREACHED() << "GetApplicationName unsupported";
+ NOTREACHED();
return false;
}
int ChromiumBinariesDistribution::GetIconIndex() {
- NOTREACHED() << "GetApplicationName unsupported";
+ NOTREACHED();
return 0;
}
bool ChromiumBinariesDistribution::GetChromeChannel(std::wstring* channel) {
- NOTREACHED() << "GetApplicationName unsupported";
+ NOTREACHED();
return false;
}
diff --git a/chrome/installer/util/google_chrome_distribution.cc b/chrome/installer/util/google_chrome_distribution.cc
index 3f9b7db..7a0e89d 100644
--- a/chrome/installer/util/google_chrome_distribution.cc
+++ b/chrome/installer/util/google_chrome_distribution.cc
@@ -403,9 +403,10 @@ std::wstring GoogleChromeDistribution::GetAppGuid() {
}
std::wstring GoogleChromeDistribution::GetApplicationName() {
- const std::wstring& product_name =
- installer::GetLocalizedString(IDS_PRODUCT_NAME_BASE);
- return product_name;
+ // I'd really like to return L ## PRODUCT_FULLNAME_STRING; but that's no good
+ // since it'd be "Chromium" in a non-Chrome build, which isn't at all what I
+ // want. Sigh.
+ return L"Google Chrome";
}
std::wstring GoogleChromeDistribution::GetAlternateApplicationName() {
diff --git a/chrome/installer/util/google_chrome_sxs_distribution.cc b/chrome/installer/util/google_chrome_sxs_distribution.cc
index 416bc67..883994d 100644
--- a/chrome/installer/util/google_chrome_sxs_distribution.cc
+++ b/chrome/installer/util/google_chrome_sxs_distribution.cc
@@ -25,6 +25,10 @@ GoogleChromeSxSDistribution::GoogleChromeSxSDistribution()
GoogleChromeDistribution::set_product_guid(kChromeSxSGuid);
}
+std::wstring GoogleChromeSxSDistribution::GetApplicationName() {
+ return L"Google Chrome Canary";
+}
+
std::wstring GoogleChromeSxSDistribution::GetAppShortCutName() {
const std::wstring& shortcut_name =
installer::GetLocalizedString(IDS_SXS_SHORTCUT_NAME_BASE);
diff --git a/chrome/installer/util/google_chrome_sxs_distribution.h b/chrome/installer/util/google_chrome_sxs_distribution.h
index 10df80a..1e6a6174 100644
--- a/chrome/installer/util/google_chrome_sxs_distribution.h
+++ b/chrome/installer/util/google_chrome_sxs_distribution.h
@@ -23,13 +23,14 @@ class MasterPreferences;
// system level install and setting as default browser.
class GoogleChromeSxSDistribution : public GoogleChromeDistribution {
public:
- virtual std::wstring GetAppShortCutName();
- virtual std::wstring GetBrowserAppId();
- virtual std::wstring GetInstallSubDir();
- virtual std::wstring GetUninstallRegPath();
- virtual bool CanSetAsDefault();
- virtual int GetIconIndex();
- virtual bool GetChromeChannel(std::wstring* channel);
+ virtual std::wstring GetApplicationName() OVERRIDE;
+ virtual std::wstring GetAppShortCutName() OVERRIDE;
+ virtual std::wstring GetBrowserAppId() OVERRIDE;
+ virtual std::wstring GetInstallSubDir() OVERRIDE;
+ virtual std::wstring GetUninstallRegPath() OVERRIDE;
+ virtual bool CanSetAsDefault() OVERRIDE;
+ virtual int GetIconIndex() OVERRIDE;
+ virtual bool GetChromeChannel(std::wstring* channel) OVERRIDE;
// returns the channel name for GoogleChromeSxSDistribution
static std::wstring ChannelName();
private:
diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc
index acd3863..a15ac4e 100644
--- a/chrome/installer/util/install_util.cc
+++ b/chrome/installer/util/install_util.cc
@@ -387,7 +387,7 @@ bool InstallUtil::DeleteRegistryValue(HKEY reg_root,
}
// static
-bool InstallUtil::DeleteRegistryKeyIf(
+InstallUtil::ConditionalDeleteResult InstallUtil::DeleteRegistryKeyIf(
HKEY root_key,
const std::wstring& key_to_delete_path,
const std::wstring& key_to_test_path,
@@ -395,6 +395,7 @@ bool InstallUtil::DeleteRegistryKeyIf(
const RegistryValuePredicate& predicate) {
DCHECK(root_key);
DCHECK(value_name);
+ ConditionalDeleteResult delete_result = NOT_FOUND;
RegKey key;
std::wstring actual_value;
if (key.Open(root_key, key_to_test_path.c_str(),
@@ -402,13 +403,14 @@ bool InstallUtil::DeleteRegistryKeyIf(
key.ReadValue(value_name, &actual_value) == ERROR_SUCCESS &&
predicate.Evaluate(actual_value)) {
key.Close();
- return DeleteRegistryKey(root_key, key_to_delete_path);
+ delete_result = DeleteRegistryKey(root_key, key_to_delete_path)
+ ? DELETED : DELETE_FAILED;
}
- return true;
+ return delete_result;
}
// static
-bool InstallUtil::DeleteRegistryValueIf(
+InstallUtil::ConditionalDeleteResult InstallUtil::DeleteRegistryValueIf(
HKEY root_key,
const wchar_t* key_path,
const wchar_t* value_name,
@@ -416,6 +418,7 @@ bool InstallUtil::DeleteRegistryValueIf(
DCHECK(root_key);
DCHECK(key_path);
DCHECK(value_name);
+ ConditionalDeleteResult delete_result = NOT_FOUND;
RegKey key;
std::wstring actual_value;
if (key.Open(root_key, key_path,
@@ -426,10 +429,11 @@ bool InstallUtil::DeleteRegistryValueIf(
if (result != ERROR_SUCCESS) {
LOG(ERROR) << "Failed to delete registry value: " << value_name
<< " error: " << result;
- return false;
+ delete_result = DELETE_FAILED;
}
+ delete_result = DELETED;
}
- return true;
+ return delete_result;
}
bool InstallUtil::ValueEquals::Evaluate(const std::wstring& value) const {
diff --git a/chrome/installer/util/install_util.h b/chrome/installer/util/install_util.h
index b730cc4..1e47522 100644
--- a/chrome/installer/util/install_util.h
+++ b/chrome/installer/util/install_util.h
@@ -123,25 +123,32 @@ class InstallUtil {
virtual bool Evaluate(const std::wstring& value) const = 0;
};
+ // The result of a conditional delete operation (i.e., DeleteFOOIf).
+ enum ConditionalDeleteResult {
+ NOT_FOUND, // The condition was not satisfied.
+ DELETED, // The condition was satisfied and the delete succeeded.
+ DELETE_FAILED // The condition was satisfied but the delete failed.
+ };
+
// Deletes the key |key_to_delete_path| under |root_key| iff the value
// |value_name| in the key |key_to_test_path| under |root_key| satisfies
// |predicate|. |value_name| must be an empty string to test the key's
- // default value. Returns false if the value satisfied the predicate but
- // could not be deleted, otherwise returns true.
- static bool DeleteRegistryKeyIf(HKEY root_key,
- const std::wstring& key_to_delete_path,
- const std::wstring& key_to_test_path,
- const wchar_t* value_name,
- const RegistryValuePredicate& predicate);
+ // default value.
+ static ConditionalDeleteResult DeleteRegistryKeyIf(
+ HKEY root_key,
+ const std::wstring& key_to_delete_path,
+ const std::wstring& key_to_test_path,
+ const wchar_t* value_name,
+ const RegistryValuePredicate& predicate);
// Deletes the value |value_name| in the key |key_path| under |root_key| iff
// its current value satisfies |predicate|. |value_name| must be an empty
- // string to test the key's default value. Returns false if the value
- // satisfied the predicate but could not be deleted, otherwise returns true.
- static bool DeleteRegistryValueIf(HKEY root_key,
- const wchar_t* key_path,
- const wchar_t* value_name,
- const RegistryValuePredicate& predicate);
+ // string to test the key's default value.
+ static ConditionalDeleteResult DeleteRegistryValueIf(
+ HKEY root_key,
+ const wchar_t* key_path,
+ const wchar_t* value_name,
+ const RegistryValuePredicate& predicate);
// A predicate that performs a case-sensitive string comparison.
class ValueEquals : public RegistryValuePredicate {
diff --git a/chrome/installer/util/install_util_unittest.cc b/chrome/installer/util/install_util_unittest.cc
index 9d5341d..ef0c39b 100644
--- a/chrome/installer/util/install_util_unittest.cc
+++ b/chrome/installer/util/install_util_unittest.cc
@@ -190,8 +190,10 @@ TEST_F(InstallUtilTest, DeleteRegistryKeyIf) {
EXPECT_CALL(pred, Evaluate(_)).Times(0);
ASSERT_FALSE(RegKey(root, parent_key_path.c_str(),
KEY_QUERY_VALUE).Valid());
- EXPECT_TRUE(InstallUtil::DeleteRegistryKeyIf(
- root, parent_key_path, child_key_path, value_name, pred));
+ EXPECT_EQ(InstallUtil::NOT_FOUND,
+ InstallUtil::DeleteRegistryKeyIf(root, parent_key_path,
+ child_key_path, value_name,
+ pred));
EXPECT_FALSE(RegKey(root, parent_key_path.c_str(),
KEY_QUERY_VALUE).Valid());
}
@@ -202,8 +204,10 @@ TEST_F(InstallUtilTest, DeleteRegistryKeyIf) {
EXPECT_CALL(pred, Evaluate(_)).Times(0);
ASSERT_TRUE(RegKey(root, parent_key_path.c_str(), KEY_SET_VALUE).Valid());
- EXPECT_TRUE(InstallUtil::DeleteRegistryKeyIf(
- root, parent_key_path, child_key_path, value_name, pred));
+ EXPECT_EQ(InstallUtil::NOT_FOUND,
+ InstallUtil::DeleteRegistryKeyIf(root, parent_key_path,
+ child_key_path, value_name,
+ pred));
EXPECT_TRUE(RegKey(root, parent_key_path.c_str(),
KEY_QUERY_VALUE).Valid());
}
@@ -214,8 +218,10 @@ TEST_F(InstallUtilTest, DeleteRegistryKeyIf) {
EXPECT_CALL(pred, Evaluate(_)).Times(0);
ASSERT_TRUE(RegKey(root, child_key_path.c_str(), KEY_SET_VALUE).Valid());
- EXPECT_TRUE(InstallUtil::DeleteRegistryKeyIf(
- root, parent_key_path, child_key_path, value_name, pred));
+ EXPECT_EQ(InstallUtil::NOT_FOUND,
+ InstallUtil::DeleteRegistryKeyIf(root, parent_key_path,
+ child_key_path, value_name,
+ pred));
EXPECT_TRUE(RegKey(root, parent_key_path.c_str(),
KEY_QUERY_VALUE).Valid());
}
@@ -228,8 +234,10 @@ TEST_F(InstallUtilTest, DeleteRegistryKeyIf) {
ASSERT_EQ(ERROR_SUCCESS,
RegKey(root, child_key_path.c_str(),
KEY_SET_VALUE).WriteValue(value_name, L"foosball!"));
- EXPECT_TRUE(InstallUtil::DeleteRegistryKeyIf(
- root, parent_key_path, child_key_path, value_name, pred));
+ EXPECT_EQ(InstallUtil::NOT_FOUND,
+ InstallUtil::DeleteRegistryKeyIf(root, parent_key_path,
+ child_key_path, value_name,
+ pred));
EXPECT_TRUE(RegKey(root, parent_key_path.c_str(),
KEY_QUERY_VALUE).Valid());
}
@@ -242,8 +250,10 @@ TEST_F(InstallUtilTest, DeleteRegistryKeyIf) {
ASSERT_EQ(ERROR_SUCCESS,
RegKey(root, child_key_path.c_str(),
KEY_SET_VALUE).WriteValue(value_name, value));
- EXPECT_TRUE(InstallUtil::DeleteRegistryKeyIf(
- root, parent_key_path, child_key_path, value_name, pred));
+ EXPECT_EQ(InstallUtil::DELETED,
+ InstallUtil::DeleteRegistryKeyIf(root, parent_key_path,
+ child_key_path, value_name,
+ pred));
EXPECT_FALSE(RegKey(root, parent_key_path.c_str(),
KEY_QUERY_VALUE).Valid());
}
@@ -265,8 +275,9 @@ TEST_F(InstallUtilTest, DeleteRegistryValueIf) {
EXPECT_CALL(pred, Evaluate(_)).Times(0);
ASSERT_FALSE(RegKey(root, key_path.c_str(), KEY_QUERY_VALUE).Valid());
- EXPECT_TRUE(InstallUtil::DeleteRegistryValueIf(
- root, key_path.c_str(), value_name, pred));
+ EXPECT_EQ(InstallUtil::NOT_FOUND,
+ InstallUtil::DeleteRegistryValueIf(root, key_path.c_str(),
+ value_name, pred));
EXPECT_FALSE(RegKey(root, key_path.c_str(), KEY_QUERY_VALUE).Valid());
}
@@ -276,8 +287,9 @@ TEST_F(InstallUtilTest, DeleteRegistryValueIf) {
EXPECT_CALL(pred, Evaluate(_)).Times(0);
ASSERT_TRUE(RegKey(root, key_path.c_str(), KEY_SET_VALUE).Valid());
- EXPECT_TRUE(InstallUtil::DeleteRegistryValueIf(
- root, key_path.c_str(), value_name, pred));
+ EXPECT_EQ(InstallUtil::NOT_FOUND,
+ InstallUtil::DeleteRegistryValueIf(root, key_path.c_str(),
+ value_name, pred));
EXPECT_TRUE(RegKey(root, key_path.c_str(), KEY_QUERY_VALUE).Valid());
}
@@ -289,8 +301,9 @@ TEST_F(InstallUtilTest, DeleteRegistryValueIf) {
ASSERT_EQ(ERROR_SUCCESS,
RegKey(root, key_path.c_str(),
KEY_SET_VALUE).WriteValue(value_name, L"foosball!"));
- EXPECT_TRUE(InstallUtil::DeleteRegistryValueIf(
- root, key_path.c_str(), value_name, pred));
+ EXPECT_EQ(InstallUtil::NOT_FOUND,
+ InstallUtil::DeleteRegistryValueIf(root, key_path.c_str(),
+ value_name, pred));
EXPECT_TRUE(RegKey(root, key_path.c_str(), KEY_QUERY_VALUE).Valid());
EXPECT_TRUE(RegKey(root, key_path.c_str(),
KEY_QUERY_VALUE).HasValue(value_name));
@@ -304,8 +317,9 @@ TEST_F(InstallUtilTest, DeleteRegistryValueIf) {
ASSERT_EQ(ERROR_SUCCESS,
RegKey(root, key_path.c_str(),
KEY_SET_VALUE).WriteValue(value_name, value));
- EXPECT_TRUE(InstallUtil::DeleteRegistryValueIf(
- root, key_path.c_str(), value_name, pred));
+ EXPECT_EQ(InstallUtil::DELETED,
+ InstallUtil::DeleteRegistryValueIf(root, key_path.c_str(),
+ value_name, pred));
EXPECT_TRUE(RegKey(root, key_path.c_str(), KEY_QUERY_VALUE).Valid());
EXPECT_FALSE(RegKey(root, key_path.c_str(),
KEY_QUERY_VALUE).HasValue(value_name));
@@ -323,8 +337,9 @@ TEST_F(InstallUtilTest, DeleteRegistryValueIf) {
ASSERT_EQ(ERROR_SUCCESS,
RegKey(root, key_path.c_str(),
KEY_SET_VALUE).WriteValue(L"", value));
- EXPECT_TRUE(InstallUtil::DeleteRegistryValueIf(
- root, key_path.c_str(), L"", pred));
+ EXPECT_EQ(InstallUtil::DELETED,
+ InstallUtil::DeleteRegistryValueIf(root, key_path.c_str(), L"",
+ pred));
EXPECT_TRUE(RegKey(root, key_path.c_str(), KEY_QUERY_VALUE).Valid());
EXPECT_FALSE(RegKey(root, key_path.c_str(),
KEY_QUERY_VALUE).HasValue(L""));
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index 7af6a9a..3b56f82 100644
--- a/chrome/installer/util/shell_util.cc
+++ b/chrome/installer/util/shell_util.cc
@@ -39,6 +39,8 @@ using base::win::RegKey;
namespace {
+const wchar_t kReinstallCommand[] = L"ReinstallCommand";
+
// 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
@@ -46,6 +48,30 @@ namespace {
// class.
class RegistryEntry {
public:
+ // Returns the Windows browser client registration key for Chrome. For
+ // example: "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly
+ // speaking, we should use the name of the executable (e.g., "chrome.exe"),
+ // but that ship has sailed. The cost of switching now is re-prompting users
+ // to make Chrome their default browser, which isn't polite. |suffix| is the
+ // user-specific registration suffix; see GetUserSpecificDefaultBrowserSuffix
+ // in shell_util.h for details.
+ static std::wstring GetBrowserClientKey(BrowserDistribution* dist,
+ const std::wstring& suffix) {
+ DCHECK(suffix.empty() || suffix[0] == L'.');
+ return std::wstring(ShellUtil::kRegStartMenuInternet)
+ .append(1, L'\\')
+ .append(dist->GetApplicationName())
+ .append(suffix);
+ }
+
+ // Returns the Windows Default Programs capabilities key for Chrome. For
+ // example:
+ // "Software\Clients\StartMenuInternet\Chromium[.user]\Capabilities".
+ static std::wstring GetCapabilitiesKey(BrowserDistribution* dist,
+ const std::wstring& suffix) {
+ return GetBrowserClientKey(dist, suffix).append(L"\\Capabilities");
+ }
+
// This method returns a list of all the registry entries that
// are needed to register Chromium ProgIds.
static bool GetProgIdEntries(BrowserDistribution* dist,
@@ -74,23 +100,14 @@ class RegistryEntry {
// This method returns a list of the system level registry entries
// needed to declare a capability of handling a protocol.
static bool GetProtocolCapabilityEntries(BrowserDistribution* dist,
- const std::wstring& chrome_exe,
const std::wstring& suffix,
const std::wstring& protocol,
std::list<RegistryEntry*>* entries) {
- std::wstring app_name = dist->GetApplicationName() + suffix;
- std::wstring start_menu_entry(ShellUtil::kRegStartMenuInternet);
- start_menu_entry.append(L"\\" + app_name);
-
- std::wstring capabilities(start_menu_entry + L"\\Capabilities");
-
- std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId);
- html_prog_id.append(suffix);
- entries->push_front(new RegistryEntry(capabilities + L"\\URLAssociations",
- protocol, html_prog_id));
+ entries->push_front(new RegistryEntry(
+ GetCapabilitiesKey(dist, suffix).append(L"\\URLAssociations"),
+ protocol, std::wstring(ShellUtil::kChromeHTMLProgId).append(suffix)));
return true;
-}
-
+ }
// This method returns a list of all the system level registry entries that
// are needed to register Chromium on the machine.
@@ -101,18 +118,25 @@ class RegistryEntry {
std::wstring icon_path = ShellUtil::GetChromeIcon(dist, chrome_exe);
std::wstring quoted_exe_path = L"\"" + chrome_exe + L"\"";
- std::wstring app_name = dist->GetApplicationName() + suffix;
- std::wstring start_menu_entry(ShellUtil::kRegStartMenuInternet);
- start_menu_entry.append(L"\\" + app_name);
- entries->push_front(new RegistryEntry(start_menu_entry, app_name));
+ // Register for the Start Menu "Internet" link (pre-Win7).
+ const std::wstring start_menu_entry(GetBrowserClientKey(dist, suffix));
+ // Register Chrome's display name.
+ // TODO(grt): http://crbug.com/75152 Also set LocalizedString; see
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/cc144109(v=VS.85).aspx#registering_the_display_name
+ entries->push_front(new RegistryEntry(
+ start_menu_entry, dist->GetApplicationName()));
+ // Register the "open" verb for launching Chrome via the "Internet" link.
entries->push_front(new RegistryEntry(
start_menu_entry + ShellUtil::kRegShellOpen, quoted_exe_path));
+ // Register Chrome's icon for the Start Menu "Internet" link.
entries->push_front(new RegistryEntry(
start_menu_entry + ShellUtil::kRegDefaultIcon, icon_path));
+ // Register installation information.
std::wstring install_info(start_menu_entry + L"\\InstallInfo");
- // TODO: use CommandLine API instead of constructing command lines.
- entries->push_front(new RegistryEntry(install_info, L"ReinstallCommand",
+ // Note: not using CommandLine since it has ambiguous rules for quoting
+ // strings.
+ entries->push_front(new RegistryEntry(install_info, kReinstallCommand,
quoted_exe_path + L" --" + ASCIIToWide(switches::kMakeDefaultBrowser)));
entries->push_front(new RegistryEntry(install_info, L"HideIconsCommand",
quoted_exe_path + L" --" + ASCIIToWide(switches::kHideIcons)));
@@ -120,9 +144,15 @@ class RegistryEntry {
quoted_exe_path + L" --" + ASCIIToWide(switches::kShowIcons)));
entries->push_front(new RegistryEntry(install_info, L"IconsVisible", 1));
- std::wstring capabilities(start_menu_entry + L"\\Capabilities");
+ // Register with Default Programs.
+ std::wstring app_name(dist->GetApplicationName().append(suffix));
+ // Tell Windows where to find Chrome's Default Programs info.
+ std::wstring capabilities(GetCapabilitiesKey(dist, suffix));
entries->push_front(new RegistryEntry(ShellUtil::kRegRegisteredApplications,
app_name, capabilities));
+ // Write out Chrome's Default Programs info.
+ // TODO(grt): http://crbug.com/75152 Write a reference to a localized
+ // resource rather than this.
entries->push_front(new RegistryEntry(
capabilities, L"ApplicationDescription",
dist->GetLongAppDescription()));
@@ -131,7 +161,7 @@ class RegistryEntry {
entries->push_front(new RegistryEntry(
capabilities, L"ApplicationName", app_name));
- entries->push_front(new RegistryEntry(capabilities + L"\\StartMenu",
+ entries->push_front(new RegistryEntry(capabilities + L"\\Startmenu",
L"StartMenuInternet", app_name));
std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId);
@@ -148,6 +178,7 @@ class RegistryEntry {
ShellUtil::kPotentialProtocolAssociations[i], html_prog_id));
}
+ // Application Registration.
FilePath chrome_path(chrome_exe);
std::wstring app_path_key(ShellUtil::kAppPathsRegistryKey);
file_util::AppendToPath(&app_path_key, chrome_path.BaseName().value());
@@ -161,10 +192,7 @@ class RegistryEntry {
// This method returns a list of all the user level registry entries that
// are needed to make Chromium the default handler for a protocol.
- static bool GetUserProtocolEntries(BrowserDistribution* dist,
- const std::wstring& chrome_exe,
- const std::wstring& suffix,
- const std::wstring& protocol,
+ static bool GetUserProtocolEntries(const std::wstring& protocol,
const std::wstring& chrome_icon,
const std::wstring& chrome_open,
std::list<RegistryEntry*>* entries) {
@@ -216,8 +244,7 @@ class RegistryEntry {
std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
std::wstring chrome_icon = ShellUtil::GetChromeIcon(dist, chrome_exe);
for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) {
- GetUserProtocolEntries(dist, chrome_exe, suffix,
- ShellUtil::kBrowserProtocolAssociations[i],
+ GetUserProtocolEntries(ShellUtil::kBrowserProtocolAssociations[i],
chrome_icon, chrome_open, entries);
}
@@ -346,14 +373,12 @@ bool IsChromeRegistered(BrowserDistribution* dist,
// This method checks if Chrome is already registered on the local machine
// for the requested protocol. It just checks the one value required for this.
bool IsChromeRegisteredForProtocol(BrowserDistribution* dist,
- const std::wstring& chrome_exe,
const std::wstring& suffix,
const std::wstring& protocol) {
bool registered = true;
std::list<RegistryEntry*> entries;
STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
- RegistryEntry::GetProtocolCapabilityEntries(dist, chrome_exe, suffix,
- protocol, &entries);
+ RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, &entries);
for (std::list<RegistryEntry*>::const_iterator itr = entries.begin();
itr != entries.end() && registered; ++itr) {
// We do not need registered = registered && ... since the loop condition
@@ -426,8 +451,9 @@ bool ElevateAndRegisterChrome(BrowserDistribution* dist,
// of the above key should differ from |chrome_exe| only in user name.
bool AnotherUserHasDefaultBrowser(BrowserDistribution* dist,
const std::wstring& chrome_exe) {
- std::wstring reg_key(ShellUtil::kRegStartMenuInternet);
- reg_key.append(L"\\" + dist->GetApplicationName() + ShellUtil::kRegShellOpen);
+ const std::wstring reg_key(
+ RegistryEntry::GetBrowserClientKey(dist, std::wstring())
+ .append(ShellUtil::kRegShellOpen));
RegKey key(HKEY_LOCAL_MACHINE, reg_key.c_str(), KEY_READ);
std::wstring registry_chrome_exe;
if ((key.ReadValue(L"", &registry_chrome_exe) != ERROR_SUCCESS) ||
@@ -655,28 +681,29 @@ bool ShellUtil::GetQuickLaunchPath(bool system_level, std::wstring* path) {
return true;
}
-void ShellUtil::GetRegisteredBrowsers(BrowserDistribution* dist,
- std::map<std::wstring,
- std::wstring>* browsers) {
- std::wstring base_key(ShellUtil::kRegStartMenuInternet);
- HKEY root = HKEY_LOCAL_MACHINE;
+void ShellUtil::GetRegisteredBrowsers(
+ BrowserDistribution* dist,
+ std::map<std::wstring, std::wstring>* browsers) {
+ const HKEY root = HKEY_LOCAL_MACHINE;
+ const std::wstring base_key(ShellUtil::kRegStartMenuInternet);
+ std::wstring client_path;
+ RegKey key;
+ std::wstring name;
+ std::wstring command;
for (base::win::RegistryKeyIterator iter(root, base_key.c_str());
iter.Valid(); ++iter) {
- std::wstring key = base_key + L"\\" + iter.Name();
- RegKey capabilities(root, (key + L"\\Capabilities").c_str(), KEY_READ);
- std::wstring name;
- if (!capabilities.Valid() ||
- capabilities.ReadValue(L"ApplicationName", &name) != ERROR_SUCCESS) {
- RegKey base_key(root, key.c_str(), KEY_READ);
- if (base_key.ReadValue(L"", &name) != ERROR_SUCCESS)
- continue;
+ client_path.assign(base_key).append(1, L'\\').append(iter.Name());
+ // Read the browser's name (localized according to install language).
+ if (key.Open(root, client_path.c_str(), KEY_QUERY_VALUE) != ERROR_SUCCESS ||
+ key.ReadValue(NULL, &name) != ERROR_SUCCESS) {
+ continue;
}
- RegKey install_info(root, (key + L"\\InstallInfo").c_str(), KEY_READ);
- std::wstring command;
- if (!install_info.Valid() ||
- (install_info.ReadValue(L"ReinstallCommand",
- &command) != ERROR_SUCCESS))
+ // Read the browser's reinstall command.
+ if (key.Open(root, (client_path + L"\\InstallInfo").c_str(),
+ KEY_QUERY_VALUE) != ERROR_SUCCESS ||
+ key.ReadValue(kReinstallCommand, &command) != ERROR_SUCCESS) {
continue;
+ }
if (!name.empty() && !command.empty() &&
name.find(dist->GetApplicationName()) == std::wstring::npos)
(*browsers)[name] = command;
@@ -686,16 +713,16 @@ void ShellUtil::GetRegisteredBrowsers(BrowserDistribution* dist,
bool ShellUtil::GetUserSpecificDefaultBrowserSuffix(BrowserDistribution* dist,
std::wstring* entry) {
wchar_t user_name[256];
- DWORD size = _countof(user_name);
- if (::GetUserName(user_name, &size) == 0)
+ DWORD size = arraysize(user_name);
+ if (::GetUserName(user_name, &size) == 0 || size < 1)
return false;
- entry->assign(L".");
- entry->append(user_name);
+ entry->reserve(size);
+ entry->assign(1, L'.');
+ entry->append(user_name, size - 1);
- std::wstring start_menu_entry(ShellUtil::kRegStartMenuInternet);
- start_menu_entry.append(L"\\" + dist->GetApplicationName() + *entry);
- RegKey key(HKEY_LOCAL_MACHINE, start_menu_entry.c_str(), KEY_READ);
- return key.Valid();
+ return RegKey(HKEY_LOCAL_MACHINE,
+ RegistryEntry::GetBrowserClientKey(dist, *entry).c_str(),
+ KEY_READ).Valid();
}
bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist,
@@ -819,8 +846,8 @@ bool ShellUtil::MakeChromeDefaultProtocolClient(BrowserDistribution* dist,
suffix = L"";
std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
std::wstring chrome_icon = ShellUtil::GetChromeIcon(dist, chrome_exe);
- RegistryEntry::GetUserProtocolEntries(dist, chrome_exe, suffix, protocol,
- chrome_icon, chrome_open, &entries);
+ RegistryEntry::GetUserProtocolEntries(protocol, chrome_icon, chrome_open,
+ &entries);
// Change the default protocol handler for current user.
if (!AddRegistryEntries(HKEY_CURRENT_USER, entries)) {
ret = false;
@@ -895,7 +922,7 @@ bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist,
}
// Check if Chromium is already registered with this suffix.
- if (IsChromeRegisteredForProtocol(dist, chrome_exe, suffix, protocol))
+ if (IsChromeRegisteredForProtocol(dist, suffix, protocol))
return true;
if (IsUserAnAdmin()) {
@@ -910,8 +937,8 @@ bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist,
// Write in the capabillity for the protocol.
std::list<RegistryEntry*> entries;
STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
- RegistryEntry::GetProtocolCapabilityEntries(dist, chrome_exe, suffix,
- protocol, &entries);
+ RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol,
+ &entries);
return AddRegistryEntries(HKEY_LOCAL_MACHINE, entries);
} else if (elevate_if_not_admin &&
base::win::GetVersion() >= base::win::VERSION_VISTA) {