summaryrefslogtreecommitdiffstats
path: root/chrome/installer
diff options
context:
space:
mode:
authorgrt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-15 12:00:30 +0000
committergrt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-15 12:00:30 +0000
commit2614ed923300f66bd8f9bd2d109f0be5eed69a0d (patch)
treeef38fcb7c9765d886b97d9c13e2eef7e54d7f8eb /chrome/installer
parent1b3f6b7b95f4534eab79c01cb46c209003a3a890 (diff)
downloadchromium_src-2614ed923300f66bd8f9bd2d109f0be5eed69a0d.zip
chromium_src-2614ed923300f66bd8f9bd2d109f0be5eed69a0d.tar.gz
chromium_src-2614ed923300f66bd8f9bd2d109f0be5eed69a0d.tar.bz2
Launch Google Update on uninstall.
So it can self-destruct if Chrome (or Chrome Frame) was the last Omaha-managed product on the system. BUG=114786 TEST=Install Google Update 1.3.21.105 or later and Chrome w/ --verbose-logging. Uninstall Chrome and see that Google Update vanishes immediately. Take a look at chrome_installer.log and look for messages related to Launching Google Update's uninstaller. Review URL: http://codereview.chromium.org/9693055 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@126888 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/installer')
-rw-r--r--chrome/installer/setup/setup_main.cc38
-rw-r--r--chrome/installer/util/google_update_constants.cc4
-rw-r--r--chrome/installer/util/google_update_constants.h10
-rw-r--r--chrome/installer/util/google_update_settings.cc13
-rw-r--r--chrome/installer/util/google_update_settings.h4
-rw-r--r--chrome/installer/util/google_update_settings_unittest.cc101
6 files changed, 128 insertions, 42 deletions
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 4d0c845..c99d3e6 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -68,6 +68,7 @@ using installer::MasterPreferences;
const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices";
const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\";
const wchar_t kSystemPrincipalSid[] = L"S-1-5-18";
+const int kGoogleUpdateTimeoutMs = 20 * 1000;
const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>(
MiniDumpWithProcessThreadData | // Get PEB and TEB.
@@ -834,6 +835,41 @@ installer::InstallStatus UninstallProduct(
cmd_line.GetProgram(), product, remove_all, force_uninstall, cmd_line);
}
+// Tell Google Update that an uninstall has taken place. This gives it a chance
+// to uninstall itself straight away if no more products are installed on the
+// system rather than waiting for the next time the scheduled task runs.
+// Success or failure of Google Update has no bearing on the success or failure
+// of Chrome's uninstallation.
+void UninstallGoogleUpdate(bool system_install) {
+ string16 uninstall_cmd(
+ GoogleUpdateSettings::GetUninstallCommandLine(system_install));
+ if (!uninstall_cmd.empty()) {
+ base::win::ScopedHandle process;
+ LOG(INFO) << "Launching Google Update's uninstaller: " << uninstall_cmd;
+ if (base::LaunchProcess(uninstall_cmd, base::LaunchOptions(),
+ process.Receive())) {
+ int exit_code = 0;
+ if (base::WaitForExitCodeWithTimeout(process, &exit_code,
+ kGoogleUpdateTimeoutMs)) {
+ if (exit_code == 0) {
+ LOG(INFO) << " normal exit.";
+ } else {
+ LOG(ERROR) << "Google Update uninstaller (" << uninstall_cmd
+ << ") exited with code " << exit_code << ".";
+ }
+ } else {
+ // The process didn't finish in time, or GetExitCodeProcess failed.
+ LOG(ERROR) << "Google Update uninstaller (" << uninstall_cmd
+ << ") is taking more than " << kGoogleUpdateTimeoutMs
+ << " milliseconds to complete.";
+ }
+ } else {
+ PLOG(ERROR) << "Failed to launch Google Update uninstaller ("
+ << uninstall_cmd << ")";
+ }
+ }
+}
+
installer::InstallStatus UninstallProducts(
const InstallationState& original_state,
const InstallerState& installer_state,
@@ -860,6 +896,8 @@ installer::InstallStatus UninstallProducts(
install_status = prod_status;
}
+ UninstallGoogleUpdate(installer_state.system_install());
+
return install_status;
}
diff --git a/chrome/installer/util/google_update_constants.cc b/chrome/installer/util/google_update_constants.cc
index 4e4126d..761cb61 100644
--- a/chrome/installer/util/google_update_constants.cc
+++ b/chrome/installer/util/google_update_constants.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -12,6 +12,7 @@ const wchar_t kRegPathClients[] = L"Software\\Google\\Update\\Clients";
const wchar_t kRegPathClientState[] = L"Software\\Google\\Update\\ClientState";
const wchar_t kRegPathClientStateMedium[]
= L"Software\\Google\\Update\\ClientStateMedium";
+const wchar_t kRegPathGoogleUpdate[] = L"Software\\Google\\Update";
const wchar_t kRegCommandsKey[] = L"Commands";
@@ -41,6 +42,7 @@ const wchar_t kRegRLZReactivationBrandField[] = L"reactivationbrand";
const wchar_t kRegReferralField[] = L"referral";
const wchar_t kRegRenameCmdField[] = L"cmd";
const wchar_t kRegSendsPingsField[] = L"SendsPings";
+const wchar_t kRegUninstallCmdLine[] = L"UninstallCmdLine";
const wchar_t kRegUsageStatsField[] = L"usagestats";
const wchar_t kRegVersionField[] = L"pv";
const wchar_t kRegWebAccessibleField[] = L"WebAccessible";
diff --git a/chrome/installer/util/google_update_constants.h b/chrome/installer/util/google_update_constants.h
index eb27910..e7fc369 100644
--- a/chrome/installer/util/google_update_constants.h
+++ b/chrome/installer/util/google_update_constants.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -16,11 +16,14 @@ extern const wchar_t kChromeUpgradeCode[];
extern const wchar_t kRegPathClients[];
// The difference between ClientState and ClientStateMedium is that the former
-// lives on HKCU or HKLM and the later always lives in HKLM. The only use of
-// the ClientStateMedium is for the EULA consent. See bug 1594565.
+// lives on HKCU or HKLM and the later always lives in HKLM. ClientStateMedium
+// is primarily used for consent of the EULA and stats collection. See bug
+// 1594565.
extern const wchar_t kRegPathClientState[];
extern const wchar_t kRegPathClientStateMedium[];
+extern const wchar_t kRegPathGoogleUpdate[];
+
// The name of the "Commands" key that lives in an app's Clients key
// (a.k.a. "Version" key).
extern const wchar_t kRegCommandsKey[];
@@ -50,6 +53,7 @@ extern const wchar_t kRegRLZReactivationBrandField[];
extern const wchar_t kRegReferralField[];
extern const wchar_t kRegRenameCmdField[];
extern const wchar_t kRegSendsPingsField[];
+extern const wchar_t kRegUninstallCmdLine[];
extern const wchar_t kRegUsageStatsField[];
extern const wchar_t kRegVersionField[];
extern const wchar_t kRegWebAccessibleField[];
diff --git a/chrome/installer/util/google_update_settings.cc b/chrome/installer/util/google_update_settings.cc
index 13d6185..1278c76 100644
--- a/chrome/installer/util/google_update_settings.cc
+++ b/chrome/installer/util/google_update_settings.cc
@@ -531,3 +531,16 @@ GoogleUpdateSettings::UpdatePolicy GoogleUpdateSettings::GetAppUpdatePolicy(
return update_policy;
}
+
+string16 GoogleUpdateSettings::GetUninstallCommandLine(bool system_install) {
+ const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ string16 cmd_line;
+ RegKey update_key;
+
+ if (update_key.Open(root_key, google_update::kRegPathGoogleUpdate,
+ KEY_QUERY_VALUE) == ERROR_SUCCESS) {
+ update_key.ReadValue(google_update::kRegUninstallCmdLine, &cmd_line);
+ }
+
+ return cmd_line;
+}
diff --git a/chrome/installer/util/google_update_settings.h b/chrome/installer/util/google_update_settings.h
index a21e81c..2485502 100644
--- a/chrome/installer/util/google_update_settings.h
+++ b/chrome/installer/util/google_update_settings.h
@@ -196,6 +196,10 @@ class GoogleUpdateSettings {
static UpdatePolicy GetAppUpdatePolicy(const std::wstring& app_guid,
bool* is_overridden);
+ // Returns Google Update's uninstall command line, or an empty string if none
+ // is found.
+ static string16 GetUninstallCommandLine(bool system_install);
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(GoogleUpdateSettings);
};
diff --git a/chrome/installer/util/google_update_settings_unittest.cc b/chrome/installer/util/google_update_settings_unittest.cc
index 59c414c..4eb5d11 100644
--- a/chrome/installer/util/google_update_settings_unittest.cc
+++ b/chrome/installer/util/google_update_settings_unittest.cc
@@ -23,10 +23,6 @@ using installer::ChannelInfo;
namespace {
-const wchar_t kHKCUReplacement[] =
- L"Software\\Google\\InstallUtilUnittest\\HKCU";
-const wchar_t kHKLMReplacement[] =
- L"Software\\Google\\InstallUtilUnittest\\HKLM";
const wchar_t kGoogleUpdatePoliciesKey[] =
L"SOFTWARE\\Policies\\Google\\Update";
const wchar_t kGoogleUpdateUpdateDefault[] = L"UpdateDefault";
@@ -45,38 +41,9 @@ const wchar_t kTestProductGuid[] = L"{89F1B351-B15D-48D4-8F10-1298721CF13D}";
// and user settings.
class GoogleUpdateSettingsTest: public testing::Test {
protected:
- virtual void SetUp() {
- // Wipe the keys we redirect to.
- // This gives us a stable run, even in the presence of previous
- // crashes or failures.
- LSTATUS err = SHDeleteKey(HKEY_CURRENT_USER, kHKCUReplacement);
- EXPECT_TRUE(err == ERROR_SUCCESS || err == ERROR_FILE_NOT_FOUND);
- err = SHDeleteKey(HKEY_CURRENT_USER, kHKLMReplacement);
- EXPECT_TRUE(err == ERROR_SUCCESS || err == ERROR_FILE_NOT_FOUND);
-
- // Create the keys we're redirecting HKCU and HKLM to.
- ASSERT_EQ(ERROR_SUCCESS,
- hkcu_.Create(HKEY_CURRENT_USER, kHKCUReplacement, KEY_READ));
- ASSERT_EQ(ERROR_SUCCESS,
- hklm_.Create(HKEY_CURRENT_USER, kHKLMReplacement, KEY_READ));
-
- // And do the switcharoo.
- ASSERT_EQ(ERROR_SUCCESS,
- ::RegOverridePredefKey(HKEY_CURRENT_USER, hkcu_.Handle()));
- ASSERT_EQ(ERROR_SUCCESS,
- ::RegOverridePredefKey(HKEY_LOCAL_MACHINE, hklm_.Handle()));
- }
-
- virtual void TearDown() {
- // Undo the redirection.
- EXPECT_EQ(ERROR_SUCCESS, ::RegOverridePredefKey(HKEY_CURRENT_USER, NULL));
- EXPECT_EQ(ERROR_SUCCESS, ::RegOverridePredefKey(HKEY_LOCAL_MACHINE, NULL));
-
- // Close our handles and delete the temp keys we redirected to.
- hkcu_.Close();
- hklm_.Close();
- EXPECT_EQ(ERROR_SUCCESS, SHDeleteKey(HKEY_CURRENT_USER, kHKCUReplacement));
- EXPECT_EQ(ERROR_SUCCESS, SHDeleteKey(HKEY_CURRENT_USER, kHKLMReplacement));
+ virtual void SetUp() OVERRIDE {
+ registry_overrides_.OverrideRegistry(HKEY_LOCAL_MACHINE, L"HKLM_pit");
+ registry_overrides_.OverrideRegistry(HKEY_CURRENT_USER, L"HKCU_pit");
}
enum SystemUserInstall {
@@ -181,8 +148,7 @@ class GoogleUpdateSettingsTest: public testing::Test {
return ap_key_value;
}
- RegKey hkcu_;
- RegKey hklm_;
+ registry_util::RegistryOverrideManager registry_overrides_;
};
} // namespace
@@ -590,6 +556,65 @@ TEST_F(GoogleUpdateSettingsTest, GetAppUpdatePolicyAppOverride) {
#endif // defined(GOOGLE_CHROME_BUILD)
+// Test GoogleUpdateSettings::GetUninstallCommandLine at system- or user-level,
+// according to the param.
+class GetUninstallCommandLine : public GoogleUpdateSettingsTest,
+ public testing::WithParamInterface<bool> {
+ protected:
+ static const wchar_t kDummyCommand[];
+
+ virtual void SetUp() OVERRIDE {
+ GoogleUpdateSettingsTest::SetUp();
+ system_install_ = GetParam();
+ root_key_ = system_install_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ }
+
+ HKEY root_key_;
+ bool system_install_;
+};
+
+const wchar_t GetUninstallCommandLine::kDummyCommand[] =
+ L"\"goopdate.exe\" /spam";
+
+// Tests that GetUninstallCommandLine returns an empty string if there's no
+// Software\Google\Update key.
+TEST_P(GetUninstallCommandLine, TestNoKey) {
+ EXPECT_EQ(string16(),
+ GoogleUpdateSettings::GetUninstallCommandLine(system_install_));
+}
+
+// Tests that GetUninstallCommandLine returns an empty string if there's no
+// UninstallCmdLine value in the Software\Google\Update key.
+TEST_P(GetUninstallCommandLine, TestNoValue) {
+ RegKey(root_key_, google_update::kRegPathGoogleUpdate, KEY_SET_VALUE);
+ EXPECT_EQ(string16(),
+ GoogleUpdateSettings::GetUninstallCommandLine(system_install_));
+}
+
+// Tests that GetUninstallCommandLine returns an empty string if there's an
+// empty UninstallCmdLine value in the Software\Google\Update key.
+TEST_P(GetUninstallCommandLine, TestEmptyValue) {
+ RegKey(root_key_, google_update::kRegPathGoogleUpdate, KEY_SET_VALUE)
+ .WriteValue(google_update::kRegUninstallCmdLine, L"");
+ EXPECT_EQ(string16(),
+ GoogleUpdateSettings::GetUninstallCommandLine(system_install_));
+}
+
+// Tests that GetUninstallCommandLine returns the correct string if there's an
+// UninstallCmdLine value in the Software\Google\Update key.
+TEST_P(GetUninstallCommandLine, TestRealValue) {
+ RegKey(root_key_, google_update::kRegPathGoogleUpdate, KEY_SET_VALUE)
+ .WriteValue(google_update::kRegUninstallCmdLine, kDummyCommand);
+ EXPECT_EQ(string16(kDummyCommand),
+ GoogleUpdateSettings::GetUninstallCommandLine(system_install_));
+ // Make sure that there's no value in the other level (user or system).
+ EXPECT_EQ(string16(),
+ GoogleUpdateSettings::GetUninstallCommandLine(!system_install_));
+}
+
+INSTANTIATE_TEST_CASE_P(GetUninstallCommandLineAtLevel, GetUninstallCommandLine,
+ testing::Bool());
+
// Test values for use by the CollectStatsConsent test fixture.
class StatsState {
public: