diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/installer/setup/setup_main.cc | 10 | ||||
-rw-r--r-- | chrome/installer/setup/uninstall.cc | 98 | ||||
-rw-r--r-- | chrome/installer/setup/uninstall.h | 2 | ||||
-rw-r--r-- | chrome/installer/util/browser_distribution.h | 3 | ||||
-rw-r--r-- | chrome/installer/util/chrome_frame_distribution.cc | 4 | ||||
-rw-r--r-- | chrome/installer/util/chrome_frame_distribution.h | 2 | ||||
-rw-r--r-- | chrome/installer/util/chromium_binaries_distribution.cc | 24 | ||||
-rw-r--r-- | chrome/installer/util/google_chrome_distribution.cc | 7 | ||||
-rw-r--r-- | chrome/installer/util/google_chrome_sxs_distribution.cc | 4 | ||||
-rw-r--r-- | chrome/installer/util/google_chrome_sxs_distribution.h | 15 | ||||
-rw-r--r-- | chrome/installer/util/install_util.cc | 16 | ||||
-rw-r--r-- | chrome/installer/util/install_util.h | 33 | ||||
-rw-r--r-- | chrome/installer/util/install_util_unittest.cc | 55 | ||||
-rw-r--r-- | chrome/installer/util/shell_util.cc | 153 |
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"", ®_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"", ®_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"", ®istry_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) { |