| Index: chrome/installer/setup/setup_util.cc
|
| diff --git a/chrome/installer/setup/setup_util.cc b/chrome/installer/setup/setup_util.cc
|
| index 2d03e8c119e4a7f420b7b1ea09f8f8d9e019393d..f4b88069a76c3d6a92c02ea3bc7b49d37689613a 100644
|
| --- a/chrome/installer/setup/setup_util.cc
|
| +++ b/chrome/installer/setup/setup_util.cc
|
| @@ -42,6 +42,8 @@
|
| #include "chrome/installer/util/installation_state.h"
|
| #include "chrome/installer/util/master_preferences.h"
|
| #include "chrome/installer/util/master_preferences_constants.h"
|
| +#include "chrome/installer/util/non_updating_app_registration_data.h"
|
| +#include "chrome/installer/util/updating_app_registration_data.h"
|
| #include "chrome/installer/util/util_constants.h"
|
| #include "courgette/courgette.h"
|
| #include "courgette/third_party/bsdiff/bsdiff.h"
|
| @@ -67,13 +69,6 @@ base::string16 InstallFullName() {
|
| #endif
|
| }
|
|
|
| -// Returns true if product |type| cam be meaningfully installed without the
|
| -// --multi-install flag.
|
| -bool SupportsSingleInstall(BrowserDistribution::Type type) {
|
| - return (type == BrowserDistribution::CHROME_BROWSER ||
|
| - type == BrowserDistribution::CHROME_FRAME);
|
| -}
|
| -
|
| // Returns true if the "lastrun" value in |root|\|key_path| (a path to Chrome's
|
| // ClientState key for a user) indicates that Chrome has been used within the
|
| // last 28 days.
|
| @@ -132,6 +127,160 @@ bool OnUserHive(const base::string16& client_state_path,
|
| return false;
|
| }
|
|
|
| +// "The binaries" once referred to the on-disk footprint of Chrome and/or Chrome
|
| +// Frame when the products were configured to share such on-disk bits. Support
|
| +// for this mode of install was dropped from ToT in December 2016. Remove any
|
| +// stray bits in the registry leftover from such installs.
|
| +void RemoveBinariesVersionKey(const InstallerState& installer_state) {
|
| +#if defined(GOOGLE_CHROME_BUILD)
|
| + UpdatingAppRegistrationData reg_data(
|
| + L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}");
|
| +#else
|
| + NonUpdatingAppRegistrationData reg_data(L"Software\\Chromium Binaries");
|
| +#endif
|
| +
|
| + base::string16 path(reg_data.GetVersionKey());
|
| + if (base::win::RegKey(installer_state.root_key(), path.c_str(),
|
| + KEY_QUERY_VALUE | KEY_WOW64_32KEY)
|
| + .Valid()) {
|
| + const bool success = InstallUtil::DeleteRegistryKey(
|
| + installer_state.root_key(), path, KEY_WOW64_32KEY);
|
| + UMA_HISTOGRAM_BOOLEAN("Setup.Install.DeleteBinariesClientsKey", success);
|
| + }
|
| +}
|
| +
|
| +// Remove leftover traces of multi-install Chrome Frame, if present. Once upon a
|
| +// time, Google Chrome Frame could be co-installed with Chrome such that they
|
| +// shared the same binaries on disk. Support for new installs of GCF was dropped
|
| +// from ToT in December 2013. Remove any stray bits in the registry leftover
|
| +// from an old multi-install GCF.
|
| +void RemoveMultiChromeFrame(const InstallerState& installer_state) {
|
| +// There never was a "Chromium Frame".
|
| +#if defined(GOOGLE_CHROME_BUILD)
|
| + // To maximize cleanup, unconditionally delete GCF's Clients and ClientState
|
| + // keys unless single-install GCF is present. This condition is satisfied if
|
| + // both keys exist, Clients\pv contains a value, and
|
| + // ClientState\UninstallString contains a path including "\Chrome Frame\".
|
| + // Multi-install GCF would have had "\Chrome\", and anything else is garbage.
|
| +
|
| + UpdatingAppRegistrationData gcf_data(
|
| + L"{8BA986DA-5100-405E-AA35-86F34A02ACBF}");
|
| + base::win::RegKey clients_key;
|
| + base::win::RegKey client_state_key;
|
| +
|
| + const bool has_clients_key =
|
| + clients_key.Open(installer_state.root_key(),
|
| + gcf_data.GetVersionKey().c_str(),
|
| + KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS;
|
| + const bool has_client_state_key =
|
| + client_state_key.Open(installer_state.root_key(),
|
| + gcf_data.GetStateKey().c_str(),
|
| + KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS;
|
| + if (!has_clients_key && !has_client_state_key)
|
| + return; // Nothing to check or to clean.
|
| +
|
| + base::string16 value;
|
| + if (has_clients_key && has_client_state_key &&
|
| + clients_key.ReadValue(google_update::kRegVersionField, &value) ==
|
| + ERROR_SUCCESS &&
|
| + !value.empty() &&
|
| + client_state_key.ReadValue(kUninstallStringField, &value) ==
|
| + ERROR_SUCCESS &&
|
| + value.find(L"\\Chrome Frame\\") != base::string16::npos) {
|
| + return; // Single-install Chrome Frame found.
|
| + }
|
| + client_state_key.Close();
|
| + clients_key.Close();
|
| +
|
| + // Remnants of multi-install GCF or of a malformed GCF are present. Remove the
|
| + // Clients and ClientState keys so that Google Update ceases to check for
|
| + // updates, and the Programs and Features control panel entry to reduce user
|
| + // confusion.
|
| + constexpr int kOperations = 3;
|
| + int success_count = 0;
|
| +
|
| + if (InstallUtil::DeleteRegistryKey(installer_state.root_key(),
|
| + gcf_data.GetVersionKey(),
|
| + KEY_WOW64_32KEY)) {
|
| + ++success_count;
|
| + }
|
| + if (InstallUtil::DeleteRegistryKey(installer_state.root_key(),
|
| + gcf_data.GetStateKey(), KEY_WOW64_32KEY)) {
|
| + ++success_count;
|
| + }
|
| + if (InstallUtil::DeleteRegistryKey(
|
| + installer_state.root_key(),
|
| + L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"
|
| + L"Google Chrome Frame",
|
| + KEY_WOW64_32KEY)) {
|
| + ++success_count;
|
| + }
|
| + DCHECK_LE(success_count, kOperations);
|
| +
|
| + // Used for a histogram; do not reorder.
|
| + enum MultiChromeFrameRemovalResult {
|
| + ALL_FAILED = 0,
|
| + PARTIAL_SUCCESS = 1,
|
| + SUCCESS = 2,
|
| + NUM_RESULTS
|
| + };
|
| + MultiChromeFrameRemovalResult result =
|
| + (success_count == kOperations ? SUCCESS : (success_count ? PARTIAL_SUCCESS
|
| + : ALL_FAILED));
|
| + UMA_HISTOGRAM_ENUMERATION("Setup.Install.MultiChromeFrameRemoved", result,
|
| + NUM_RESULTS);
|
| +#endif // GOOGLE_CHROME_BUILD
|
| +}
|
| +
|
| +void RemoveAppLauncherVersionKey(const InstallerState& installer_state) {
|
| +// The app launcher was only registered for Google Chrome.
|
| +#if defined(GOOGLE_CHROME_BUILD)
|
| + UpdatingAppRegistrationData reg_data(
|
| + L"{FDA71E6F-AC4C-4a00-8B70-9958A68906BF}");
|
| +
|
| + base::string16 path(reg_data.GetVersionKey());
|
| + if (base::win::RegKey(installer_state.root_key(), path.c_str(),
|
| + KEY_QUERY_VALUE | KEY_WOW64_32KEY)
|
| + .Valid()) {
|
| + const bool succeeded = InstallUtil::DeleteRegistryKey(
|
| + installer_state.root_key(), path, KEY_WOW64_32KEY);
|
| + UMA_HISTOGRAM_BOOLEAN("Setup.Install.DeleteAppLauncherClientsKey",
|
| + succeeded);
|
| + }
|
| +#endif // GOOGLE_CHROME_BUILD
|
| +}
|
| +
|
| +void RemoveAppHostExe(const InstallerState& installer_state) {
|
| +// The app host was only installed for Google Chrome.
|
| +#if defined(GOOGLE_CHROME_BUILD)
|
| + base::FilePath app_host(
|
| + installer_state.target_path().Append(FILE_PATH_LITERAL("app_host.exe")));
|
| +
|
| + if (base::PathExists(app_host)) {
|
| + const bool succeeded = base::DeleteFile(app_host, false);
|
| + UMA_HISTOGRAM_BOOLEAN("Setup.Install.DeleteAppHost", succeeded);
|
| + }
|
| +#endif // GOOGLE_CHROME_BUILD
|
| +}
|
| +
|
| +void RemoveLegacyChromeAppCommands(const InstallerState& installer_state) {
|
| +// These app commands were only registered for Google Chrome.
|
| +#if defined(GOOGLE_CHROME_BUILD)
|
| + base::string16 path(GetRegistrationDataCommandKey(
|
| + installer_state.product().distribution()->GetAppRegistrationData(),
|
| + L"install-extension"));
|
| +
|
| + if (base::win::RegKey(installer_state.root_key(), path.c_str(),
|
| + KEY_QUERY_VALUE | KEY_WOW64_32KEY)
|
| + .Valid()) {
|
| + const bool succeeded = InstallUtil::DeleteRegistryKey(
|
| + installer_state.root_key(), path, KEY_WOW64_32KEY);
|
| + UMA_HISTOGRAM_BOOLEAN("Setup.Install.DeleteInstallExtensionCommand",
|
| + succeeded);
|
| + }
|
| +#endif // GOOGLE_CHROME_BUILD
|
| +}
|
| +
|
| } // namespace
|
|
|
| const char kUnPackStatusMetricsName[] = "Setup.Install.LzmaUnPackStatus";
|
| @@ -302,32 +451,6 @@ bool DeleteFileFromTempProcess(const base::FilePath& path,
|
| return ok != FALSE;
|
| }
|
|
|
| -// There are 4 disjoint cases => return values {false,true}:
|
| -// (1) Product is being uninstalled => false.
|
| -// (2) Product is being installed => true.
|
| -// (3) Current operation ignores product, product is absent => false.
|
| -// (4) Current operation ignores product, product is present => true.
|
| -bool WillProductBePresentAfterSetup(
|
| - const installer::InstallerState& installer_state,
|
| - const installer::InstallationState& machine_state,
|
| - BrowserDistribution::Type type) {
|
| - DCHECK(SupportsSingleInstall(type) || installer_state.is_multi_install());
|
| -
|
| - const ProductState* product_state =
|
| - machine_state.GetProductState(installer_state.system_install(), type);
|
| -
|
| - // Determine if the product is present prior to the current operation.
|
| - bool is_present = (product_state != NULL);
|
| - bool is_uninstall = installer_state.operation() == InstallerState::UNINSTALL;
|
| -
|
| - // Determine if current operation affects the product.
|
| - const Product* product = installer_state.FindProduct(type);
|
| - bool is_affected = (product != NULL);
|
| -
|
| - // Decide among {(1),(2),(3),(4)}.
|
| - return is_affected ? !is_uninstall : is_present;
|
| -}
|
| -
|
| bool AdjustProcessPriority() {
|
| if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
|
| DWORD priority_class = ::GetPriorityClass(::GetCurrentProcess());
|
| @@ -732,6 +855,23 @@ void DeRegisterEventLogProvider() {
|
| WorkItem::kWow64Default);
|
| }
|
|
|
| +void DoLegacyCleanups(const InstallerState& installer_state,
|
| + InstallStatus install_status) {
|
| + // Do no harm if the install didn't succeed.
|
| + if (InstallUtil::GetInstallReturnCode(install_status))
|
| + return;
|
| +
|
| + // The cleanups below only apply to normal Chrome, not side-by-side (canary).
|
| + if (InstallUtil::IsChromeSxSProcess())
|
| + return;
|
| +
|
| + RemoveBinariesVersionKey(installer_state);
|
| + RemoveMultiChromeFrame(installer_state);
|
| + RemoveAppLauncherVersionKey(installer_state);
|
| + RemoveAppHostExe(installer_state);
|
| + RemoveLegacyChromeAppCommands(installer_state);
|
| +}
|
| +
|
| ScopedTokenPrivilege::ScopedTokenPrivilege(const wchar_t* privilege_name)
|
| : is_enabled_(false) {
|
| HANDLE temp_handle;
|
|
|