- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / installer / util / installation_state.cc
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/version.h"
10 #include "base/win/registry.h"
11 #include "chrome/installer/util/google_update_constants.h"
12 #include "chrome/installer/util/install_util.h"
13
14 namespace installer {
15
16 ProductState::ProductState()
17     : uninstall_command_(CommandLine::NO_PROGRAM),
18       eula_accepted_(0),
19       usagestats_(0),
20       msi_(false),
21       multi_install_(false),
22       has_eula_accepted_(false),
23       has_oem_install_(false),
24       has_usagestats_(false) {
25 }
26
27 bool ProductState::Initialize(bool system_install,
28                               BrowserDistribution::Type type) {
29   return Initialize(system_install,
30                     BrowserDistribution::GetSpecificDistribution(type));
31 }
32
33 // Initializes |commands| from the "Commands" subkey of |version_key|.
34 // Returns false if there is no "Commands" subkey or on error.
35 // static
36 bool ProductState::InitializeCommands(const base::win::RegKey& version_key,
37                                       AppCommands* commands) {
38   static const DWORD kAccess = KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE;
39   base::win::RegKey commands_key;
40
41   if (commands_key.Open(version_key.Handle(), google_update::kRegCommandsKey,
42                         kAccess) == ERROR_SUCCESS)
43     return commands->Initialize(commands_key);
44   return false;
45 }
46
47 bool ProductState::Initialize(bool system_install,
48                               BrowserDistribution* distribution) {
49   const std::wstring version_key(distribution->GetVersionKey());
50   const std::wstring state_key(distribution->GetStateKey());
51   const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
52   base::win::RegKey key;
53
54   // Clear the runway.
55   Clear();
56
57   // Read from the Clients key.
58   if (key.Open(root_key, version_key.c_str(),
59                KEY_QUERY_VALUE) == ERROR_SUCCESS) {
60     std::wstring version_str;
61     if (key.ReadValue(google_update::kRegVersionField,
62                       &version_str) == ERROR_SUCCESS) {
63       version_.reset(new Version(WideToASCII(version_str)));
64       if (!version_->IsValid())
65         version_.reset();
66     }
67
68     // Attempt to read the other values even if the "pv" version value was
69     // absent. Note that ProductState instances containing these values will
70     // only be accessible via InstallationState::GetNonVersionedProductState.
71     if (key.ReadValue(google_update::kRegOldVersionField,
72                       &version_str) == ERROR_SUCCESS) {
73       old_version_.reset(new Version(WideToASCII(version_str)));
74       if (!old_version_->IsValid())
75         old_version_.reset();
76     }
77
78     key.ReadValue(google_update::kRegRenameCmdField, &rename_cmd_);
79     if (!InitializeCommands(key, &commands_))
80       commands_.Clear();
81   }
82
83   // Read from the ClientState key.
84   if (key.Open(root_key, state_key.c_str(),
85                KEY_QUERY_VALUE) == ERROR_SUCCESS) {
86     std::wstring setup_path;
87     std::wstring uninstall_arguments;
88     // "ap" will be absent if not managed by Google Update.
89     channel_.Initialize(key);
90
91     // Read in the brand code, it may be absent
92     key.ReadValue(google_update::kRegBrandField, &brand_);
93
94     // "UninstallString" will be absent for the multi-installer package.
95     key.ReadValue(kUninstallStringField, &setup_path);
96     // "UninstallArguments" will be absent for the multi-installer package.
97     key.ReadValue(kUninstallArgumentsField, &uninstall_arguments);
98     InstallUtil::MakeUninstallCommand(setup_path, uninstall_arguments,
99                                       &uninstall_command_);
100
101     // "usagestats" may be absent, 0 (false), or 1 (true).  On the chance that
102     // different values are permitted in the future, we'll simply hold whatever
103     // we find.
104     has_usagestats_ = (key.ReadValueDW(google_update::kRegUsageStatsField,
105                                        &usagestats_) == ERROR_SUCCESS);
106     // "oeminstall" may be present with any value or absent.
107     has_oem_install_ = (key.ReadValue(google_update::kRegOemInstallField,
108                                       &oem_install_) == ERROR_SUCCESS);
109     // "eulaaccepted" may be absent, 0 or 1.
110     has_eula_accepted_ = (key.ReadValueDW(google_update::kRegEULAAceptedField,
111                                           &eula_accepted_) == ERROR_SUCCESS);
112     // "msi" may be absent, 0 or 1
113     DWORD dw_value = 0;
114     msi_ = (key.ReadValueDW(google_update::kRegMSIField,
115                             &dw_value) == ERROR_SUCCESS) && (dw_value != 0);
116     // Multi-install is implied or is derived from the command-line.
117     if (distribution->GetType() == BrowserDistribution::CHROME_BINARIES)
118       multi_install_ = true;
119     else
120       multi_install_ = uninstall_command_.HasSwitch(switches::kMultiInstall);
121   }
122
123   // Read from the ClientStateMedium key.  Values here override those in
124   // ClientState.
125   if (system_install &&
126       key.Open(root_key, distribution->GetStateMediumKey().c_str(),
127                KEY_QUERY_VALUE) == ERROR_SUCCESS) {
128     DWORD dword_value = 0;
129
130     if (key.ReadValueDW(google_update::kRegUsageStatsField,
131                         &dword_value) == ERROR_SUCCESS) {
132       has_usagestats_ = true;
133       usagestats_ = dword_value;
134     }
135
136     if (key.ReadValueDW(google_update::kRegEULAAceptedField,
137                         &dword_value) == ERROR_SUCCESS) {
138       has_eula_accepted_ = true;
139       eula_accepted_ = dword_value;
140     }
141   }
142
143   return version_.get() != NULL;
144 }
145
146 base::FilePath ProductState::GetSetupPath() const {
147   return uninstall_command_.GetProgram();
148 }
149
150 const Version& ProductState::version() const {
151   DCHECK(version_.get() != NULL);
152   return *version_;
153 }
154
155 ProductState& ProductState::CopyFrom(const ProductState& other) {
156   channel_.set_value(other.channel_.value());
157   version_.reset(other.version_.get() ? new Version(*other.version_) : NULL);
158   old_version_.reset(
159       other.old_version_.get() ? new Version(*other.old_version_) : NULL);
160   brand_ = other.brand_;
161   rename_cmd_ = other.rename_cmd_;
162   uninstall_command_ = other.uninstall_command_;
163   oem_install_ = other.oem_install_;
164   commands_.CopyFrom(other.commands_);
165   eula_accepted_ = other.eula_accepted_;
166   usagestats_ = other.usagestats_;
167   msi_ = other.msi_;
168   multi_install_ = other.multi_install_;
169   has_eula_accepted_ = other.has_eula_accepted_;
170   has_oem_install_ = other.has_oem_install_;
171   has_usagestats_ = other.has_usagestats_;
172
173   return *this;
174 }
175
176 void ProductState::Clear() {
177   channel_.set_value(std::wstring());
178   version_.reset();
179   old_version_.reset();
180   brand_.clear();
181   rename_cmd_.clear();
182   oem_install_.clear();
183   uninstall_command_ = CommandLine(CommandLine::NO_PROGRAM);
184   commands_.Clear();
185   eula_accepted_ = 0;
186   usagestats_ = 0;
187   msi_ = false;
188   multi_install_ = false;
189   has_eula_accepted_ = false;
190   has_oem_install_ = false;
191   has_usagestats_ = false;
192 }
193
194 bool ProductState::GetEulaAccepted(DWORD* eula_accepted) const {
195   DCHECK(eula_accepted);
196   if (!has_eula_accepted_)
197     return false;
198   *eula_accepted = eula_accepted_;
199   return true;
200 }
201
202 bool ProductState::GetOemInstall(std::wstring* oem_install) const {
203   DCHECK(oem_install);
204   if (!has_oem_install_)
205     return false;
206   *oem_install = oem_install_;
207   return true;
208 }
209
210 bool ProductState::GetUsageStats(DWORD* usagestats) const {
211   DCHECK(usagestats);
212   if (!has_usagestats_)
213     return false;
214   *usagestats = usagestats_;
215   return true;
216 }
217
218 InstallationState::InstallationState() {
219 }
220
221 // static
222 int InstallationState::IndexFromDistType(BrowserDistribution::Type type) {
223   COMPILE_ASSERT(BrowserDistribution::CHROME_BROWSER == CHROME_BROWSER_INDEX,
224                  unexpected_chrome_browser_distribution_value_);
225   COMPILE_ASSERT(BrowserDistribution::CHROME_FRAME == CHROME_FRAME_INDEX,
226                  unexpected_chrome_frame_distribution_value_);
227   COMPILE_ASSERT(BrowserDistribution::CHROME_BINARIES == CHROME_BINARIES_INDEX,
228                  unexpected_chrome_frame_distribution_value_);
229   COMPILE_ASSERT(BrowserDistribution::CHROME_APP_HOST == CHROME_APP_HOST_INDEX,
230                  unexpected_chrome_frame_distribution_value_);
231   DCHECK(type == BrowserDistribution::CHROME_BROWSER ||
232          type == BrowserDistribution::CHROME_FRAME ||
233          type == BrowserDistribution::CHROME_BINARIES ||
234          type == BrowserDistribution::CHROME_APP_HOST);
235   return type;
236 }
237
238 void InstallationState::Initialize() {
239   BrowserDistribution* distribution;
240
241   distribution = BrowserDistribution::GetSpecificDistribution(
242       BrowserDistribution::CHROME_BROWSER);
243   user_products_[CHROME_BROWSER_INDEX].Initialize(false, distribution);
244   system_products_[CHROME_BROWSER_INDEX].Initialize(true, distribution);
245
246   distribution = BrowserDistribution::GetSpecificDistribution(
247       BrowserDistribution::CHROME_FRAME);
248   user_products_[CHROME_FRAME_INDEX].Initialize(false, distribution);
249   system_products_[CHROME_FRAME_INDEX].Initialize(true, distribution);
250
251   distribution = BrowserDistribution::GetSpecificDistribution(
252       BrowserDistribution::CHROME_BINARIES);
253   user_products_[CHROME_BINARIES_INDEX].Initialize(false, distribution);
254   system_products_[CHROME_BINARIES_INDEX].Initialize(true, distribution);
255
256   distribution = BrowserDistribution::GetSpecificDistribution(
257       BrowserDistribution::CHROME_APP_HOST);
258   user_products_[CHROME_APP_HOST_INDEX].Initialize(false, distribution);
259   system_products_[CHROME_APP_HOST_INDEX].Initialize(true, distribution);
260 }
261
262 const ProductState* InstallationState::GetNonVersionedProductState(
263     bool system_install,
264     BrowserDistribution::Type type) const {
265   const ProductState& product_state = (system_install ? system_products_ :
266       user_products_)[IndexFromDistType(type)];
267   return &product_state;
268 }
269
270 const ProductState* InstallationState::GetProductState(
271     bool system_install,
272     BrowserDistribution::Type type) const {
273   const ProductState* product_state =
274       GetNonVersionedProductState(system_install, type);
275   return product_state->version_.get() == NULL ? NULL : product_state;
276 }
277 }  // namespace installer