Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / installer / util / installation_state.cc
bloba926435daf1adb68031c689877059f4be5ae5de6
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/installer/util/installation_state.h"
7 #include "base/logging.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/version.h"
11 #include "base/win/registry.h"
12 #include "chrome/installer/util/google_update_constants.h"
13 #include "chrome/installer/util/install_util.h"
15 namespace installer {
17 ProductState::ProductState()
18 : uninstall_command_(base::CommandLine::NO_PROGRAM),
19 eula_accepted_(0),
20 usagestats_(0),
21 msi_(false),
22 multi_install_(false),
23 has_eula_accepted_(false),
24 has_oem_install_(false),
25 has_usagestats_(false) {
28 ProductState::~ProductState() {
31 bool ProductState::Initialize(bool system_install,
32 BrowserDistribution::Type type) {
33 return Initialize(system_install,
34 BrowserDistribution::GetSpecificDistribution(type));
37 // Initializes |commands| from the "Commands" subkey of |version_key|.
38 // Returns false if there is no "Commands" subkey or on error.
39 // static
40 bool ProductState::InitializeCommands(const base::win::RegKey& version_key,
41 AppCommands* commands) {
42 static const DWORD kAccess =
43 KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_WOW64_32KEY;
44 base::win::RegKey commands_key;
46 if (commands_key.Open(version_key.Handle(), google_update::kRegCommandsKey,
47 kAccess) == ERROR_SUCCESS)
48 return commands->Initialize(commands_key, KEY_WOW64_32KEY);
49 return false;
52 bool ProductState::Initialize(bool system_install,
53 BrowserDistribution* distribution) {
54 static const DWORD kAccess = KEY_QUERY_VALUE | KEY_WOW64_32KEY;
55 const std::wstring version_key(distribution->GetVersionKey());
56 const std::wstring state_key(distribution->GetStateKey());
57 const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
58 base::win::RegKey key;
60 // Clear the runway.
61 Clear();
63 // Read from the Clients key.
64 if (key.Open(root_key, version_key.c_str(), kAccess) == ERROR_SUCCESS) {
65 base::string16 version_str;
66 if (key.ReadValue(google_update::kRegVersionField,
67 &version_str) == ERROR_SUCCESS) {
68 version_.reset(new Version(base::UTF16ToASCII(version_str)));
69 if (!version_->IsValid())
70 version_.reset();
73 // Attempt to read the other values even if the "pv" version value was
74 // absent. Note that ProductState instances containing these values will
75 // only be accessible via InstallationState::GetNonVersionedProductState.
76 if (key.ReadValue(google_update::kRegOldVersionField,
77 &version_str) == ERROR_SUCCESS) {
78 old_version_.reset(new Version(base::UTF16ToASCII(version_str)));
79 if (!old_version_->IsValid())
80 old_version_.reset();
83 key.ReadValue(google_update::kRegRenameCmdField, &rename_cmd_);
84 if (!InitializeCommands(key, &commands_))
85 commands_.Clear();
88 // Read from the ClientState key.
89 if (key.Open(root_key, state_key.c_str(), kAccess) == ERROR_SUCCESS) {
90 std::wstring setup_path;
91 std::wstring uninstall_arguments;
92 // "ap" will be absent if not managed by Google Update.
93 channel_.Initialize(key);
95 // Read in the brand code, it may be absent
96 key.ReadValue(google_update::kRegBrandField, &brand_);
98 // "UninstallString" will be absent for the multi-installer package.
99 key.ReadValue(kUninstallStringField, &setup_path);
100 // "UninstallArguments" will be absent for the multi-installer package.
101 key.ReadValue(kUninstallArgumentsField, &uninstall_arguments);
102 InstallUtil::ComposeCommandLine(setup_path, uninstall_arguments,
103 &uninstall_command_);
105 // "usagestats" may be absent, 0 (false), or 1 (true). On the chance that
106 // different values are permitted in the future, we'll simply hold whatever
107 // we find.
108 has_usagestats_ = (key.ReadValueDW(google_update::kRegUsageStatsField,
109 &usagestats_) == ERROR_SUCCESS);
110 // "oeminstall" may be present with any value or absent.
111 has_oem_install_ = (key.ReadValue(google_update::kRegOemInstallField,
112 &oem_install_) == ERROR_SUCCESS);
113 // "eulaaccepted" may be absent, 0 or 1.
114 has_eula_accepted_ = (key.ReadValueDW(google_update::kRegEULAAceptedField,
115 &eula_accepted_) == ERROR_SUCCESS);
116 // "msi" may be absent, 0 or 1
117 DWORD dw_value = 0;
118 msi_ = (key.ReadValueDW(google_update::kRegMSIField,
119 &dw_value) == ERROR_SUCCESS) && (dw_value != 0);
120 // Multi-install is implied or is derived from the command-line.
121 if (distribution->GetType() == BrowserDistribution::CHROME_BINARIES)
122 multi_install_ = true;
123 else
124 multi_install_ = uninstall_command_.HasSwitch(switches::kMultiInstall);
127 // Read from the ClientStateMedium key. Values here override those in
128 // ClientState.
129 if (system_install &&
130 key.Open(root_key, distribution->GetStateMediumKey().c_str(), kAccess) ==
131 ERROR_SUCCESS) {
132 DWORD dword_value = 0;
134 if (key.ReadValueDW(google_update::kRegUsageStatsField,
135 &dword_value) == ERROR_SUCCESS) {
136 has_usagestats_ = true;
137 usagestats_ = dword_value;
140 if (key.ReadValueDW(google_update::kRegEULAAceptedField,
141 &dword_value) == ERROR_SUCCESS) {
142 has_eula_accepted_ = true;
143 eula_accepted_ = dword_value;
147 return version_.get() != NULL;
150 base::FilePath ProductState::GetSetupPath() const {
151 return uninstall_command_.GetProgram();
154 const Version& ProductState::version() const {
155 DCHECK(version_.get() != NULL);
156 return *version_;
159 ProductState& ProductState::CopyFrom(const ProductState& other) {
160 channel_.set_value(other.channel_.value());
161 version_.reset(other.version_.get() ? new Version(*other.version_) : NULL);
162 old_version_.reset(
163 other.old_version_.get() ? new Version(*other.old_version_) : NULL);
164 brand_ = other.brand_;
165 rename_cmd_ = other.rename_cmd_;
166 uninstall_command_ = other.uninstall_command_;
167 oem_install_ = other.oem_install_;
168 commands_.CopyFrom(other.commands_);
169 eula_accepted_ = other.eula_accepted_;
170 usagestats_ = other.usagestats_;
171 msi_ = other.msi_;
172 multi_install_ = other.multi_install_;
173 has_eula_accepted_ = other.has_eula_accepted_;
174 has_oem_install_ = other.has_oem_install_;
175 has_usagestats_ = other.has_usagestats_;
177 return *this;
180 void ProductState::Clear() {
181 channel_.set_value(std::wstring());
182 version_.reset();
183 old_version_.reset();
184 brand_.clear();
185 rename_cmd_.clear();
186 oem_install_.clear();
187 uninstall_command_ = base::CommandLine(base::CommandLine::NO_PROGRAM);
188 commands_.Clear();
189 eula_accepted_ = 0;
190 usagestats_ = 0;
191 msi_ = false;
192 multi_install_ = false;
193 has_eula_accepted_ = false;
194 has_oem_install_ = false;
195 has_usagestats_ = false;
198 bool ProductState::GetEulaAccepted(DWORD* eula_accepted) const {
199 DCHECK(eula_accepted);
200 if (!has_eula_accepted_)
201 return false;
202 *eula_accepted = eula_accepted_;
203 return true;
206 bool ProductState::GetOemInstall(std::wstring* oem_install) const {
207 DCHECK(oem_install);
208 if (!has_oem_install_)
209 return false;
210 *oem_install = oem_install_;
211 return true;
214 bool ProductState::GetUsageStats(DWORD* usagestats) const {
215 DCHECK(usagestats);
216 if (!has_usagestats_)
217 return false;
218 *usagestats = usagestats_;
219 return true;
222 InstallationState::InstallationState() {
225 // static
226 int InstallationState::IndexFromDistType(BrowserDistribution::Type type) {
227 COMPILE_ASSERT(BrowserDistribution::CHROME_BROWSER == CHROME_BROWSER_INDEX,
228 unexpected_chrome_browser_distribution_value_);
229 COMPILE_ASSERT(BrowserDistribution::CHROME_FRAME == CHROME_FRAME_INDEX,
230 unexpected_chrome_frame_distribution_value_);
231 COMPILE_ASSERT(BrowserDistribution::CHROME_BINARIES == CHROME_BINARIES_INDEX,
232 unexpected_chrome_frame_distribution_value_);
233 DCHECK(type == BrowserDistribution::CHROME_BROWSER ||
234 type == BrowserDistribution::CHROME_FRAME ||
235 type == BrowserDistribution::CHROME_BINARIES);
236 return type;
239 void InstallationState::Initialize() {
240 BrowserDistribution* distribution;
242 distribution = BrowserDistribution::GetSpecificDistribution(
243 BrowserDistribution::CHROME_BROWSER);
244 user_products_[CHROME_BROWSER_INDEX].Initialize(false, distribution);
245 system_products_[CHROME_BROWSER_INDEX].Initialize(true, distribution);
247 distribution = BrowserDistribution::GetSpecificDistribution(
248 BrowserDistribution::CHROME_FRAME);
249 user_products_[CHROME_FRAME_INDEX].Initialize(false, distribution);
250 system_products_[CHROME_FRAME_INDEX].Initialize(true, distribution);
252 distribution = BrowserDistribution::GetSpecificDistribution(
253 BrowserDistribution::CHROME_BINARIES);
254 user_products_[CHROME_BINARIES_INDEX].Initialize(false, distribution);
255 system_products_[CHROME_BINARIES_INDEX].Initialize(true, distribution);
258 const ProductState* InstallationState::GetNonVersionedProductState(
259 bool system_install,
260 BrowserDistribution::Type type) const {
261 const ProductState& product_state = (system_install ? system_products_ :
262 user_products_)[IndexFromDistType(type)];
263 return &product_state;
266 const ProductState* InstallationState::GetProductState(
267 bool system_install,
268 BrowserDistribution::Type type) const {
269 const ProductState* product_state =
270 GetNonVersionedProductState(system_install, type);
271 return product_state->version_.get() == NULL ? NULL : product_state;
273 } // namespace installer