• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/installer/util/installation_state.h"
6 
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"
14 
15 namespace installer {
16 
ProductState()17 ProductState::ProductState()
18     : uninstall_command_(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) {
26 }
27 
Initialize(bool system_install,BrowserDistribution::Type type)28 bool ProductState::Initialize(bool system_install,
29                               BrowserDistribution::Type type) {
30   return Initialize(system_install,
31                     BrowserDistribution::GetSpecificDistribution(type));
32 }
33 
34 // Initializes |commands| from the "Commands" subkey of |version_key|.
35 // Returns false if there is no "Commands" subkey or on error.
36 // static
InitializeCommands(const base::win::RegKey & version_key,AppCommands * commands)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;
42 
43   if (commands_key.Open(version_key.Handle(), google_update::kRegCommandsKey,
44                         kAccess) == ERROR_SUCCESS)
45     return commands->Initialize(commands_key);
46   return false;
47 }
48 
Initialize(bool system_install,BrowserDistribution * distribution)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;
56 
57   // Clear the runway.
58   Clear();
59 
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();
68     }
69 
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();
78     }
79 
80     key.ReadValue(google_update::kRegRenameCmdField, &rename_cmd_);
81     if (!InitializeCommands(key, &commands_))
82       commands_.Clear();
83   }
84 
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);
91 
92     // Read in the brand code, it may be absent
93     key.ReadValue(google_update::kRegBrandField, &brand_);
94 
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_);
101 
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);
122   }
123 
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;
130 
131     if (key.ReadValueDW(google_update::kRegUsageStatsField,
132                         &dword_value) == ERROR_SUCCESS) {
133       has_usagestats_ = true;
134       usagestats_ = dword_value;
135     }
136 
137     if (key.ReadValueDW(google_update::kRegEULAAceptedField,
138                         &dword_value) == ERROR_SUCCESS) {
139       has_eula_accepted_ = true;
140       eula_accepted_ = dword_value;
141     }
142   }
143 
144   return version_.get() != NULL;
145 }
146 
GetSetupPath() const147 base::FilePath ProductState::GetSetupPath() const {
148   return uninstall_command_.GetProgram();
149 }
150 
version() const151 const Version& ProductState::version() const {
152   DCHECK(version_.get() != NULL);
153   return *version_;
154 }
155 
CopyFrom(const ProductState & other)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_;
173 
174   return *this;
175 }
176 
Clear()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_ = CommandLine(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;
193 }
194 
GetEulaAccepted(DWORD * eula_accepted) const195 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;
201 }
202 
GetOemInstall(std::wstring * oem_install) const203 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;
209 }
210 
GetUsageStats(DWORD * usagestats) const211 bool ProductState::GetUsageStats(DWORD* usagestats) const {
212   DCHECK(usagestats);
213   if (!has_usagestats_)
214     return false;
215   *usagestats = usagestats_;
216   return true;
217 }
218 
InstallationState()219 InstallationState::InstallationState() {
220 }
221 
222 // static
IndexFromDistType(BrowserDistribution::Type type)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   COMPILE_ASSERT(BrowserDistribution::CHROME_APP_HOST == CHROME_APP_HOST_INDEX,
231                  unexpected_chrome_frame_distribution_value_);
232   DCHECK(type == BrowserDistribution::CHROME_BROWSER ||
233          type == BrowserDistribution::CHROME_FRAME ||
234          type == BrowserDistribution::CHROME_BINARIES ||
235          type == BrowserDistribution::CHROME_APP_HOST);
236   return type;
237 }
238 
Initialize()239 void InstallationState::Initialize() {
240   BrowserDistribution* distribution;
241 
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);
246 
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);
251 
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);
256 
257   distribution = BrowserDistribution::GetSpecificDistribution(
258       BrowserDistribution::CHROME_APP_HOST);
259   user_products_[CHROME_APP_HOST_INDEX].Initialize(false, distribution);
260   system_products_[CHROME_APP_HOST_INDEX].Initialize(true, distribution);
261 }
262 
GetNonVersionedProductState(bool system_install,BrowserDistribution::Type type) const263 const ProductState* InstallationState::GetNonVersionedProductState(
264     bool system_install,
265     BrowserDistribution::Type type) const {
266   const ProductState& product_state = (system_install ? system_products_ :
267       user_products_)[IndexFromDistType(type)];
268   return &product_state;
269 }
270 
GetProductState(bool system_install,BrowserDistribution::Type type) const271 const ProductState* InstallationState::GetProductState(
272     bool system_install,
273     BrowserDistribution::Type type) const {
274   const ProductState* product_state =
275       GetNonVersionedProductState(system_install, type);
276   return product_state->version_.get() == NULL ? NULL : product_state;
277 }
278 }  // namespace installer
279