| // 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. |
| |
| #include "chrome/installer/setup/installer_state.h" |
| |
| #include <stddef.h> |
| |
| #include <string> |
| |
| #include "base/command_line.h" |
| #include "base/files/file_util.h" |
| #include "base/win/registry.h" |
| #include "build/branding_buildflags.h" |
| #include "chrome/install_static/install_util.h" |
| #include "chrome/installer/setup/setup_util.h" |
| #include "chrome/installer/util/google_update_settings.h" |
| #include "chrome/installer/util/helper.h" |
| #include "chrome/installer/util/install_util.h" |
| #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/work_item.h" |
| #include "chrome/installer/util/work_item_list.h" |
| |
| namespace installer { |
| |
| namespace { |
| |
| // Returns the boolean value of the distribution preference in |prefs| named |
| // |pref_name|, or |default_value| if not set. |
| bool GetMasterPreference(const MasterPreferences& prefs, |
| const char* pref_name, |
| bool default_value) { |
| bool value; |
| return prefs.GetBool(pref_name, &value) ? value : default_value; |
| } |
| |
| } // namespace |
| |
| InstallerState::InstallerState() |
| : operation_(UNINITIALIZED), |
| level_(UNKNOWN_LEVEL), |
| root_key_(nullptr), |
| msi_(false), |
| verbose_logging_(false) {} |
| |
| InstallerState::InstallerState(Level level) |
| : operation_(UNINITIALIZED), |
| level_(UNKNOWN_LEVEL), |
| root_key_(nullptr), |
| msi_(false), |
| verbose_logging_(false) { |
| // Use set_level() so that root_key_ is updated properly. |
| set_level(level); |
| } |
| |
| InstallerState::~InstallerState() {} |
| |
| void InstallerState::Initialize(const base::CommandLine& command_line, |
| const MasterPreferences& prefs, |
| const InstallationState& machine_state) { |
| Clear(); |
| |
| set_level(GetMasterPreference(prefs, master_preferences::kSystemLevel, false) |
| ? SYSTEM_LEVEL |
| : USER_LEVEL); |
| |
| verbose_logging_ = |
| GetMasterPreference(prefs, master_preferences::kVerboseLogging, false); |
| |
| msi_ = GetMasterPreference(prefs, master_preferences::kMsi, false); |
| if (!msi_) { |
| const ProductState* product_state = |
| machine_state.GetProductState(system_install()); |
| if (product_state != nullptr) |
| msi_ = product_state->is_msi(); |
| } |
| |
| const bool is_uninstall = command_line.HasSwitch(switches::kUninstall); |
| |
| // TODO(grt): Infer target_path_ from an existing install in support of |
| // varying install locations; see https://crbug.com/380177. |
| target_path_ = GetChromeInstallPath(system_install()); |
| state_key_ = install_static::GetClientStateKeyPath(); |
| |
| VLOG(1) << (is_uninstall ? "Uninstall Chrome" : "Install Chrome"); |
| |
| operation_ = is_uninstall ? UNINSTALL : SINGLE_INSTALL_OR_UPDATE; |
| |
| // Parse --critical-update-version=W.X.Y.Z |
| std::string critical_version_value( |
| command_line.GetSwitchValueASCII(switches::kCriticalUpdateVersion)); |
| critical_update_version_ = base::Version(critical_version_value); |
| } |
| |
| void InstallerState::set_level(Level level) { |
| level_ = level; |
| switch (level) { |
| case UNKNOWN_LEVEL: |
| root_key_ = nullptr; |
| return; |
| case USER_LEVEL: |
| root_key_ = HKEY_CURRENT_USER; |
| return; |
| case SYSTEM_LEVEL: |
| root_key_ = HKEY_LOCAL_MACHINE; |
| return; |
| } |
| NOTREACHED() << level; |
| } |
| |
| bool InstallerState::system_install() const { |
| DCHECK(level_ == USER_LEVEL || level_ == SYSTEM_LEVEL); |
| return level_ == SYSTEM_LEVEL; |
| } |
| |
| base::Version InstallerState::GetCurrentVersion( |
| const InstallationState& machine_state) const { |
| base::Version current_version; |
| const ProductState* product_state = |
| machine_state.GetProductState(level_ == SYSTEM_LEVEL); |
| |
| if (product_state) { |
| // Be aware that there might be a pending "new_chrome.exe" already in the |
| // installation path. If so, we use old_version, which holds the version of |
| // "chrome.exe" itself. |
| if (base::PathExists(target_path().Append(kChromeNewExe)) && |
| product_state->old_version()) { |
| current_version = *(product_state->old_version()); |
| } else { |
| current_version = product_state->version(); |
| } |
| } |
| |
| return current_version; |
| } |
| |
| base::Version InstallerState::DetermineCriticalVersion( |
| const base::Version& current_version, |
| const base::Version& new_version) const { |
| DCHECK(new_version.IsValid()); |
| if (critical_update_version_.IsValid() && |
| (!current_version.IsValid() || |
| (current_version.CompareTo(critical_update_version_) < 0)) && |
| new_version.CompareTo(critical_update_version_) >= 0) { |
| return critical_update_version_; |
| } |
| return base::Version(); |
| } |
| |
| base::FilePath InstallerState::GetInstallerDirectory( |
| const base::Version& version) const { |
| return target_path().AppendASCII(version.GetString()).Append(kInstallerDir); |
| } |
| |
| void InstallerState::Clear() { |
| operation_ = UNINITIALIZED; |
| target_path_.clear(); |
| state_key_.clear(); |
| critical_update_version_ = base::Version(); |
| level_ = UNKNOWN_LEVEL; |
| root_key_ = nullptr; |
| msi_ = false; |
| verbose_logging_ = false; |
| } |
| |
| void InstallerState::SetStage(InstallerStage stage) const { |
| GoogleUpdateSettings::SetProgress(system_install(), state_key_, |
| progress_calculator_.Calculate(stage)); |
| } |
| |
| void InstallerState::WriteInstallerResult( |
| InstallStatus status, |
| int string_resource_id, |
| const base::string16* const launch_cmd) const { |
| // Use a no-rollback list since this is a best-effort deal. |
| std::unique_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); |
| install_list->set_log_message("Write Installer Result"); |
| install_list->set_best_effort(true); |
| install_list->set_rollback_enabled(false); |
| const bool system_install = this->system_install(); |
| // Write the value for the product upon which we're operating. |
| InstallUtil::AddInstallerResultItems( |
| system_install, install_static::GetClientStateKeyPath(), status, |
| string_resource_id, launch_cmd, install_list.get()); |
| install_list->Do(); |
| } |
| |
| bool InstallerState::RequiresActiveSetup() const { |
| return system_install(); |
| } |
| |
| } // namespace installer |