Android: Get rid of extra dup()s on launching child processes
[chromium-blink-merge.git] / chrome / installer / util / installation_state.cc
blob645738d923882c0488ad21b776651bf1548bc867
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 bool ProductState::Initialize(bool system_install,
29 BrowserDistribution::Type type) {
30 return Initialize(system_install,
31 BrowserDistribution::GetSpecificDistribution(type));
34 // Initializes |commands| from the "Commands" subkey of |version_key|.
35 // Returns false if there is no "Commands" subkey or on error.
36 // static
37 bool ProductState::InitializeCommands(const base::win::RegKey& version_key,
38 AppCommands* commands) {
39 static const DWORD kAccess =
40 KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_WOW64_32KEY;
41 base::win::RegKey commands_key;
43 if (commands_key.Open(version_key.Handle(), google_update::kRegCommandsKey,
44 kAccess) == ERROR_SUCCESS)
45 return commands->Initialize(commands_key, KEY_WOW64_32KEY);
46 return false;
49 bool ProductState::Initialize(bool system_install,
50 BrowserDistribution* distribution) {
51 static const DWORD kAccess = KEY_QUERY_VALUE | KEY_WOW64_32KEY;
52 const std::wstring version_key(distribution->GetVersionKey());
53 const std::wstring state_key(distribution->GetStateKey());
54 const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
55 base::win::RegKey key;
57 // Clear the runway.
58 Clear();
60 // Read from the Clients key.
61 if (key.Open(root_key, version_key.c_str(), kAccess) == ERROR_SUCCESS) {
62 base::string16 version_str;
63 if (key.ReadValue(google_update::kRegVersionField,
64 &version_str) == ERROR_SUCCESS) {
65 version_.reset(new Version(base::UTF16ToASCII(version_str)));
66 if (!version_->IsValid())
67 version_.reset();
70 // Attempt to read the other values even if the "pv" version value was
71 // absent. Note that ProductState instances containing these values will
72 // only be accessible via InstallationState::GetNonVersionedProductState.
73 if (key.ReadValue(google_update::kRegOldVersionField,
74 &version_str) == ERROR_SUCCESS) {
75 old_version_.reset(new Version(base::UTF16ToASCII(version_str)));
76 if (!old_version_->IsValid())
77 old_version_.reset();
80 key.ReadValue(google_update::kRegRenameCmdField, &rename_cmd_);
81 if (!InitializeCommands(key, &commands_))
82 commands_.Clear();
85 // Read from the ClientState key.
86 if (key.Open(root_key, state_key.c_str(), kAccess) == ERROR_SUCCESS) {
87 std::wstring setup_path;
88 std::wstring uninstall_arguments;
89 // "ap" will be absent if not managed by Google Update.
90 channel_.Initialize(key);
92 // Read in the brand code, it may be absent
93 key.ReadValue(google_update::kRegBrandField, &brand_);
95 // "UninstallString" will be absent for the multi-installer package.
96 key.ReadValue(kUninstallStringField, &setup_path);
97 // "UninstallArguments" will be absent for the multi-installer package.
98 key.ReadValue(kUninstallArgumentsField, &uninstall_arguments);
99 InstallUtil::MakeUninstallCommand(setup_path, uninstall_arguments,
100 &uninstall_command_);
102 // "usagestats" may be absent, 0 (false), or 1 (true). On the chance that
103 // different values are permitted in the future, we'll simply hold whatever
104 // we find.
105 has_usagestats_ = (key.ReadValueDW(google_update::kRegUsageStatsField,
106 &usagestats_) == ERROR_SUCCESS);
107 // "oeminstall" may be present with any value or absent.
108 has_oem_install_ = (key.ReadValue(google_update::kRegOemInstallField,
109 &oem_install_) == ERROR_SUCCESS);
110 // "eulaaccepted" may be absent, 0 or 1.
111 has_eula_accepted_ = (key.ReadValueDW(google_update::kRegEULAAceptedField,
112 &eula_accepted_) == ERROR_SUCCESS);
113 // "msi" may be absent, 0 or 1
114 DWORD dw_value = 0;
115 msi_ = (key.ReadValueDW(google_update::kRegMSIField,
116 &dw_value) == ERROR_SUCCESS) && (dw_value != 0);
117 // Multi-install is implied or is derived from the command-line.
118 if (distribution->GetType() == BrowserDistribution::CHROME_BINARIES)
119 multi_install_ = true;
120 else
121 multi_install_ = uninstall_command_.HasSwitch(switches::kMultiInstall);
124 // Read from the ClientStateMedium key. Values here override those in
125 // ClientState.
126 if (system_install &&
127 key.Open(root_key, distribution->GetStateMediumKey().c_str(), kAccess) ==
128 ERROR_SUCCESS) {
129 DWORD dword_value = 0;
131 if (key.ReadValueDW(google_update::kRegUsageStatsField,
132 &dword_value) == ERROR_SUCCESS) {
133 has_usagestats_ = true;
134 usagestats_ = dword_value;
137 if (key.ReadValueDW(google_update::kRegEULAAceptedField,
138 &dword_value) == ERROR_SUCCESS) {
139 has_eula_accepted_ = true;
140 eula_accepted_ = dword_value;
144 return version_.get() != NULL;
147 base::FilePath ProductState::GetSetupPath() const {
148 return uninstall_command_.GetProgram();
151 const Version& ProductState::version() const {
152 DCHECK(version_.get() != NULL);
153 return *version_;
156 ProductState& ProductState::CopyFrom(const ProductState& other) {
157 channel_.set_value(other.channel_.value());
158 version_.reset(other.version_.get() ? new Version(*other.version_) : NULL);
159 old_version_.reset(
160 other.old_version_.get() ? new Version(*other.old_version_) : NULL);
161 brand_ = other.brand_;
162 rename_cmd_ = other.rename_cmd_;
163 uninstall_command_ = other.uninstall_command_;
164 oem_install_ = other.oem_install_;
165 commands_.CopyFrom(other.commands_);
166 eula_accepted_ = other.eula_accepted_;
167 usagestats_ = other.usagestats_;
168 msi_ = other.msi_;
169 multi_install_ = other.multi_install_;
170 has_eula_accepted_ = other.has_eula_accepted_;
171 has_oem_install_ = other.has_oem_install_;
172 has_usagestats_ = other.has_usagestats_;
174 return *this;
177 void ProductState::Clear() {
178 channel_.set_value(std::wstring());
179 version_.reset();
180 old_version_.reset();
181 brand_.clear();
182 rename_cmd_.clear();
183 oem_install_.clear();
184 uninstall_command_ = base::CommandLine(base::CommandLine::NO_PROGRAM);
185 commands_.Clear();
186 eula_accepted_ = 0;
187 usagestats_ = 0;
188 msi_ = false;
189 multi_install_ = false;
190 has_eula_accepted_ = false;
191 has_oem_install_ = false;
192 has_usagestats_ = false;
195 bool ProductState::GetEulaAccepted(DWORD* eula_accepted) const {
196 DCHECK(eula_accepted);
197 if (!has_eula_accepted_)
198 return false;
199 *eula_accepted = eula_accepted_;
200 return true;
203 bool ProductState::GetOemInstall(std::wstring* oem_install) const {
204 DCHECK(oem_install);
205 if (!has_oem_install_)
206 return false;
207 *oem_install = oem_install_;
208 return true;
211 bool ProductState::GetUsageStats(DWORD* usagestats) const {
212 DCHECK(usagestats);
213 if (!has_usagestats_)
214 return false;
215 *usagestats = usagestats_;
216 return true;
219 InstallationState::InstallationState() {
222 // static
223 int InstallationState::IndexFromDistType(BrowserDistribution::Type type) {
224 COMPILE_ASSERT(BrowserDistribution::CHROME_BROWSER == CHROME_BROWSER_INDEX,
225 unexpected_chrome_browser_distribution_value_);
226 COMPILE_ASSERT(BrowserDistribution::CHROME_FRAME == CHROME_FRAME_INDEX,
227 unexpected_chrome_frame_distribution_value_);
228 COMPILE_ASSERT(BrowserDistribution::CHROME_BINARIES == CHROME_BINARIES_INDEX,
229 unexpected_chrome_frame_distribution_value_);
230 DCHECK(type == BrowserDistribution::CHROME_BROWSER ||
231 type == BrowserDistribution::CHROME_FRAME ||
232 type == BrowserDistribution::CHROME_BINARIES);
233 return type;
236 void InstallationState::Initialize() {
237 BrowserDistribution* distribution;
239 distribution = BrowserDistribution::GetSpecificDistribution(
240 BrowserDistribution::CHROME_BROWSER);
241 user_products_[CHROME_BROWSER_INDEX].Initialize(false, distribution);
242 system_products_[CHROME_BROWSER_INDEX].Initialize(true, distribution);
244 distribution = BrowserDistribution::GetSpecificDistribution(
245 BrowserDistribution::CHROME_FRAME);
246 user_products_[CHROME_FRAME_INDEX].Initialize(false, distribution);
247 system_products_[CHROME_FRAME_INDEX].Initialize(true, distribution);
249 distribution = BrowserDistribution::GetSpecificDistribution(
250 BrowserDistribution::CHROME_BINARIES);
251 user_products_[CHROME_BINARIES_INDEX].Initialize(false, distribution);
252 system_products_[CHROME_BINARIES_INDEX].Initialize(true, distribution);
255 const ProductState* InstallationState::GetNonVersionedProductState(
256 bool system_install,
257 BrowserDistribution::Type type) const {
258 const ProductState& product_state = (system_install ? system_products_ :
259 user_products_)[IndexFromDistType(type)];
260 return &product_state;
263 const ProductState* InstallationState::GetProductState(
264 bool system_install,
265 BrowserDistribution::Type type) const {
266 const ProductState* product_state =
267 GetNonVersionedProductState(system_install, type);
268 return product_state->version_.get() == NULL ? NULL : product_state;
270 } // namespace installer