Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1278)

Side by Side Diff: chrome/installer/setup/installer_state.cc

Issue 2589753002: Remove multi-install from chrome/installer/setup. (Closed)
Patch Set: revert util/product changes for now Created 3 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/installer/setup/installer_state.h" 5 #include "chrome/installer/setup/installer_state.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm>
10 #include <functional>
11 #include <memory>
12 #include <string> 9 #include <string>
13 #include <utility> 10 #include <utility>
14 11
15 #include "base/command_line.h" 12 #include "base/command_line.h"
16 #include "base/files/file_util.h" 13 #include "base/files/file_util.h"
17 #include "base/logging.h" 14 #include "base/logging.h"
18 #include "base/macros.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/win/registry.h" 15 #include "base/win/registry.h"
21 #include "base/win/scoped_handle.h"
22 #include "chrome/installer/util/delete_tree_work_item.h"
23 #include "chrome/installer/util/google_update_settings.h" 16 #include "chrome/installer/util/google_update_settings.h"
24 #include "chrome/installer/util/helper.h" 17 #include "chrome/installer/util/helper.h"
25 #include "chrome/installer/util/install_util.h" 18 #include "chrome/installer/util/install_util.h"
26 #include "chrome/installer/util/installation_state.h" 19 #include "chrome/installer/util/installation_state.h"
27 #include "chrome/installer/util/master_preferences.h" 20 #include "chrome/installer/util/master_preferences.h"
28 #include "chrome/installer/util/master_preferences_constants.h" 21 #include "chrome/installer/util/master_preferences_constants.h"
29 #include "chrome/installer/util/product.h" 22 #include "chrome/installer/util/product.h"
30 #include "chrome/installer/util/work_item.h" 23 #include "chrome/installer/util/work_item.h"
31 #include "chrome/installer/util/work_item_list.h" 24 #include "chrome/installer/util/work_item_list.h"
32 25
33 namespace installer { 26 namespace installer {
34 27
35 bool InstallerState::IsMultiInstallUpdate(
36 const MasterPreferences& prefs,
37 const InstallationState& machine_state) {
38 // First, are the binaries present?
39 const ProductState* binaries =
40 machine_state.GetProductState(level_ == SYSTEM_LEVEL,
41 BrowserDistribution::CHROME_BINARIES);
42 if (binaries == NULL) {
43 // The multi-install binaries have not been installed, so they certainly
44 // aren't being updated.
45 return false;
46 }
47
48 if (prefs.install_chrome()) {
49 const ProductState* product =
50 machine_state.GetProductState(level_ == SYSTEM_LEVEL,
51 BrowserDistribution::CHROME_BROWSER);
52 if (product == NULL) {
53 VLOG(2) << "It seems that chrome is being installed for the first time.";
54 return false;
55 }
56 if (!product->channel().Equals(binaries->channel())) {
57 VLOG(2) << "It seems that chrome is being over installed.";
58 return false;
59 }
60 }
61
62 VLOG(2) << "It seems that the binaries are being updated.";
63
64 return true;
65 }
66
67 InstallerState::InstallerState() 28 InstallerState::InstallerState()
68 : operation_(UNINITIALIZED), 29 : operation_(UNINITIALIZED),
69 state_type_(BrowserDistribution::CHROME_BROWSER), 30 state_type_(BrowserDistribution::CHROME_BROWSER),
70 multi_package_distribution_(NULL),
71 level_(UNKNOWN_LEVEL), 31 level_(UNKNOWN_LEVEL),
72 package_type_(UNKNOWN_PACKAGE_TYPE),
73 root_key_(NULL), 32 root_key_(NULL),
74 msi_(false), 33 msi_(false),
75 background_mode_(false), 34 background_mode_(false),
76 verbose_logging_(false), 35 verbose_logging_(false),
77 is_migrating_to_single_(false) {} 36 is_migrating_to_single_(false) {}
78 37
79 InstallerState::InstallerState(Level level) 38 InstallerState::InstallerState(Level level)
80 : operation_(UNINITIALIZED), 39 : operation_(UNINITIALIZED),
81 state_type_(BrowserDistribution::CHROME_BROWSER), 40 state_type_(BrowserDistribution::CHROME_BROWSER),
82 multi_package_distribution_(NULL),
83 level_(UNKNOWN_LEVEL), 41 level_(UNKNOWN_LEVEL),
84 package_type_(UNKNOWN_PACKAGE_TYPE),
85 root_key_(NULL), 42 root_key_(NULL),
86 msi_(false), 43 msi_(false),
87 background_mode_(false), 44 background_mode_(false),
88 verbose_logging_(false), 45 verbose_logging_(false),
89 is_migrating_to_single_(false) { 46 is_migrating_to_single_(false) {
90 // Use set_level() so that root_key_ is updated properly. 47 // Use set_level() so that root_key_ is updated properly.
91 set_level(level); 48 set_level(level);
92 } 49 }
93 50
94 InstallerState::~InstallerState() { 51 InstallerState::~InstallerState() {
95 } 52 }
96 53
97 void InstallerState::Initialize(const base::CommandLine& command_line, 54 void InstallerState::Initialize(const base::CommandLine& command_line,
98 const MasterPreferences& prefs, 55 const MasterPreferences& prefs,
99 const InstallationState& machine_state) { 56 const InstallationState& machine_state) {
100 Clear(); 57 Clear();
101 58
102 bool pref_bool; 59 bool pref_bool;
103 if (!prefs.GetBool(master_preferences::kSystemLevel, &pref_bool)) 60 if (!prefs.GetBool(master_preferences::kSystemLevel, &pref_bool))
104 pref_bool = false; 61 pref_bool = false;
105 set_level(pref_bool ? SYSTEM_LEVEL : USER_LEVEL); 62 set_level(pref_bool ? SYSTEM_LEVEL : USER_LEVEL);
106 63
107 if (!prefs.GetBool(master_preferences::kVerboseLogging, &verbose_logging_)) 64 if (!prefs.GetBool(master_preferences::kVerboseLogging, &verbose_logging_))
108 verbose_logging_ = false; 65 verbose_logging_ = false;
109 66
110 if (!prefs.GetBool(master_preferences::kMultiInstall, &pref_bool))
111 pref_bool = false;
112 set_package_type(pref_bool ? MULTI_PACKAGE : SINGLE_PACKAGE);
113
114 if (!prefs.GetBool(master_preferences::kMsi, &msi_)) 67 if (!prefs.GetBool(master_preferences::kMsi, &msi_))
115 msi_ = false; 68 msi_ = false;
116 69
117 const bool is_uninstall = command_line.HasSwitch(switches::kUninstall); 70 const bool is_uninstall = command_line.HasSwitch(switches::kUninstall);
118 71
119 if (prefs.install_chrome()) { 72 Product* p = AddProductFromPreferences(BrowserDistribution::CHROME_BROWSER,
120 Product* p = AddProductFromPreferences( 73 prefs, machine_state);
121 BrowserDistribution::CHROME_BROWSER, prefs, machine_state); 74 VLOG(1) << (is_uninstall ? "Uninstall" : "Install")
122 VLOG(1) << (is_uninstall ? "Uninstall" : "Install") 75 << " distribution: " << p->distribution()->GetDisplayName();
123 << " distribution: " << p->distribution()->GetDisplayName();
124 }
125 76
126 // Binaries are only used by Chrome. 77 // For a single-install, the current browser dist is the operand.
gab 2016/12/22 19:05:10 Comment no longer relevant given we're always in s
grt (UTC plus 2) 2017/01/02 10:45:03 Done.
127 if (is_multi_install() && 78 BrowserDistribution* operand = BrowserDistribution::GetDistribution();
gab 2016/12/22 19:05:10 Along similar thoughts, s/operand/dist ?
grt (UTC plus 2) 2017/01/02 10:45:03 Good point. Done.
128 FindProduct(BrowserDistribution::CHROME_BROWSER)) { 79 state_key_ = operand->GetStateKey();
129 Product* p = AddProductFromPreferences( 80 state_type_ = operand->GetType();
130 BrowserDistribution::CHROME_BINARIES, prefs, machine_state);
131 VLOG(1) << (is_uninstall ? "Uninstall" : "Install")
132 << " distribution: " << p->distribution()->GetDisplayName();
133 }
134
135 BrowserDistribution* operand = NULL;
136 81
137 if (is_uninstall) { 82 if (is_uninstall) {
138 operation_ = UNINSTALL; 83 operation_ = UNINSTALL;
139 } else if (!prefs.is_multi_install()) { 84 } else {
140 // For a single-install, the current browser dist is the operand.
141 operand = BrowserDistribution::GetDistribution();
142 operation_ = SINGLE_INSTALL_OR_UPDATE; 85 operation_ = SINGLE_INSTALL_OR_UPDATE;
143 // Is this a migration from multi-install to single-install? 86 // Is this a migration from multi-install to single-install?
144 const ProductState* state = 87 const ProductState* state =
145 machine_state.GetProductState(system_install(), operand->GetType()); 88 machine_state.GetProductState(system_install(), operand->GetType());
146 is_migrating_to_single_ = state && state->is_multi_install(); 89 is_migrating_to_single_ = state && state->is_multi_install();
147 } else if (IsMultiInstallUpdate(prefs, machine_state)) {
148 // Updates driven by Google Update take place under the multi-installer's
149 // app guid.
150 operand = multi_package_distribution_;
151 operation_ = MULTI_UPDATE;
152 } else {
153 operation_ = MULTI_INSTALL;
154 } 90 }
155 91
156 // Initial, over, and un-installs will take place under Chrome or Binaries
157 // app guid.
158 if (operand == NULL) {
159 operand = BrowserDistribution::GetSpecificDistribution(
160 prefs.install_chrome() ?
161 BrowserDistribution::CHROME_BROWSER :
162 BrowserDistribution::CHROME_BINARIES);
163 }
164
165 state_key_ = operand->GetStateKey();
166 state_type_ = operand->GetType();
167
168 // Parse --critical-update-version=W.X.Y.Z 92 // Parse --critical-update-version=W.X.Y.Z
169 std::string critical_version_value( 93 std::string critical_version_value(
170 command_line.GetSwitchValueASCII(switches::kCriticalUpdateVersion)); 94 command_line.GetSwitchValueASCII(switches::kCriticalUpdateVersion));
171 critical_update_version_ = base::Version(critical_version_value); 95 critical_update_version_ = base::Version(critical_version_value);
172 } 96 }
173 97
174 void InstallerState::set_level(Level level) { 98 void InstallerState::set_level(Level level) {
175 level_ = level; 99 level_ = level;
176 switch (level) { 100 switch (level) {
177 case USER_LEVEL: 101 case USER_LEVEL:
178 root_key_ = HKEY_CURRENT_USER; 102 root_key_ = HKEY_CURRENT_USER;
179 break; 103 break;
180 case SYSTEM_LEVEL: 104 case SYSTEM_LEVEL:
181 root_key_ = HKEY_LOCAL_MACHINE; 105 root_key_ = HKEY_LOCAL_MACHINE;
182 break; 106 break;
183 default: 107 default:
184 DCHECK(level == UNKNOWN_LEVEL); 108 DCHECK(level == UNKNOWN_LEVEL);
185 level_ = UNKNOWN_LEVEL; 109 level_ = UNKNOWN_LEVEL;
186 root_key_ = NULL; 110 root_key_ = NULL;
187 break; 111 break;
188 } 112 }
189 } 113 }
190 114
191 void InstallerState::set_package_type(PackageType type) { 115 // Returns |dist|'s install directory.
192 package_type_ = type;
193 switch (type) {
194 case SINGLE_PACKAGE:
195 multi_package_distribution_ = NULL;
196 break;
197 case MULTI_PACKAGE:
198 multi_package_distribution_ =
199 BrowserDistribution::GetSpecificDistribution(
200 BrowserDistribution::CHROME_BINARIES);
201 break;
202 default:
203 DCHECK(type == UNKNOWN_PACKAGE_TYPE);
204 package_type_ = UNKNOWN_PACKAGE_TYPE;
205 multi_package_distribution_ = NULL;
206 break;
207 }
208 }
209
210 // Returns the Chrome binaries directory for multi-install or |dist|'s directory
211 // otherwise.
212 base::FilePath InstallerState::GetDefaultProductInstallPath( 116 base::FilePath InstallerState::GetDefaultProductInstallPath(
gab 2016/12/22 19:05:10 This is now so simple it should probably be inline
grt (UTC plus 2) 2017/01/02 10:45:03 Done.
213 BrowserDistribution* dist) const { 117 BrowserDistribution* dist) const {
214 DCHECK(dist); 118 DCHECK(dist);
215 DCHECK(package_type_ != UNKNOWN_PACKAGE_TYPE);
216 119
217 if (package_type_ == SINGLE_PACKAGE) { 120 return GetChromeInstallPath(system_install(), dist);
218 return GetChromeInstallPath(system_install(), dist);
219 } else {
220 return GetChromeInstallPath(system_install(),
221 BrowserDistribution::GetSpecificDistribution(
222 BrowserDistribution::CHROME_BINARIES));
223 }
224 } 121 }
225 122
226 // Evaluates a product's eligibility for participation in this operation. 123 // Evaluates a product's eligibility for participation in this operation.
227 // We never expect these checks to fail, hence they all terminate the process in 124 // We never expect these checks to fail, hence they all terminate the process in
228 // debug builds. See the log messages for details. 125 // debug builds. See the log messages for details.
229 bool InstallerState::CanAddProduct(const Product& product, 126 bool InstallerState::CanAddProduct(const Product& product,
gab 2016/12/22 19:05:10 Now that the only product is chrome, will this go
grt (UTC plus 2) 2017/01/02 10:45:03 During the cleanups that will be unlocked when thi
230 const base::FilePath* product_dir) const { 127 const base::FilePath* product_dir) const {
231 switch (package_type_) { 128 if (product_) {
232 case SINGLE_PACKAGE: 129 LOG(DFATAL) << "Cannot process more than one single-install product.";
233 if (!products_.empty()) { 130 return false;
234 LOG(DFATAL) << "Cannot process more than one single-install product.";
235 return false;
236 }
237 break;
238 case MULTI_PACKAGE:
239 if (!product.HasOption(kOptionMultiInstall)) {
240 LOG(DFATAL) << "Cannot process a single-install product with a "
241 "multi-install state.";
242 return false;
243 }
244 if (FindProduct(product.distribution()->GetType()) != NULL) {
245 LOG(DFATAL) << "Cannot process more than one product of the same type.";
246 return false;
247 }
248 if (!target_path_.empty()) {
249 base::FilePath default_dir;
250 if (product_dir == NULL)
251 default_dir = GetDefaultProductInstallPath(product.distribution());
252 if (!base::FilePath::CompareEqualIgnoreCase(
253 (product_dir == NULL ? default_dir : *product_dir).value(),
254 target_path_.value())) {
255 LOG(DFATAL) << "Cannot process products in different directories.";
256 return false;
257 }
258 }
259 break;
260 default:
261 DCHECK_EQ(UNKNOWN_PACKAGE_TYPE, package_type_);
262 break;
263 } 131 }
264 return true; 132 return true;
265 } 133 }
266 134
267 // Adds |product|, installed in |product_dir| to this object's collection. If 135 // Adds |product|, installed in |product_dir| to this object's collection. If
268 // |product_dir| is NULL, the product's default install location is used. 136 // |product_dir| is NULL, the product's default install location is used.
269 // Returns NULL if |product| is incompatible with this object. Otherwise, 137 // Returns NULL if |product| is incompatible with this object. Otherwise,
270 // returns a pointer to the product (ownership is held by this object). 138 // returns a pointer to the product (ownership is held by this object).
271 Product* InstallerState::AddProductInDirectory( 139 Product* InstallerState::AddProductInDirectory(
272 const base::FilePath* product_dir, 140 const base::FilePath* product_dir,
273 std::unique_ptr<Product>* product) { 141 std::unique_ptr<Product>* product) {
gab 2016/12/22 19:05:10 If |product| can be moved out, the caller can alre
grt (UTC plus 2) 2017/01/02 10:45:03 Hmm. As-is, the caller retains ownership of the in
gab 2017/01/05 22:08:01 It doesn't seem weird to me. It says: "here's the
grt (UTC plus 2) 2017/01/06 10:25:53 Done.
274 DCHECK(product != NULL); 142 DCHECK(product != NULL);
275 DCHECK(product->get() != NULL); 143 DCHECK(product->get() != NULL);
276 const Product& the_product = *product->get(); 144 const Product& the_product = *product->get();
145 DCHECK(!the_product.HasOption(kOptionMultiInstall));
277 146
278 if (!CanAddProduct(the_product, product_dir)) 147 if (!CanAddProduct(the_product, product_dir))
279 return NULL; 148 return NULL;
280 149
281 if (package_type_ == UNKNOWN_PACKAGE_TYPE) {
282 set_package_type(the_product.HasOption(kOptionMultiInstall) ?
283 MULTI_PACKAGE : SINGLE_PACKAGE);
284 }
285
286 if (target_path_.empty()) { 150 if (target_path_.empty()) {
287 target_path_ = product_dir ? *product_dir : GetDefaultProductInstallPath( 151 target_path_ = product_dir ? *product_dir : GetDefaultProductInstallPath(
288 the_product.distribution()); 152 the_product.distribution());
289 } 153 }
290 154
291 if (state_key_.empty()) 155 if (state_key_.empty())
292 state_key_ = the_product.distribution()->GetStateKey(); 156 state_key_ = the_product.distribution()->GetStateKey();
293 157
294 products_.push_back(product->release()); 158 product_ = std::move(*product);
295 return products_.back(); 159 return product_.get();
296 } 160 }
297 161
298 Product* InstallerState::AddProduct(std::unique_ptr<Product>* product) { 162 Product* InstallerState::AddProduct(std::unique_ptr<Product>* product) {
299 return AddProductInDirectory(NULL, product); 163 return AddProductInDirectory(NULL, product);
300 } 164 }
301 165
302 // Adds a product of type |distribution_type| constructed on the basis of 166 // Adds a product of type |distribution_type| constructed on the basis of
303 // |prefs|, setting this object's msi flag if the product is represented in 167 // |prefs|, setting this object's msi flag if the product is represented in
304 // |machine_state| and is msi-installed. Returns the product that was added, 168 // |machine_state| and is msi-installed. Returns the product that was added,
305 // or NULL if |state| is incompatible with this object. Ownership is not passed 169 // or NULL if |state| is incompatible with this object. Ownership is not passed
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 msi_ |= state.is_msi(); 205 msi_ |= state.is_msi();
342 206
343 return product; 207 return product;
344 } 208 }
345 209
346 bool InstallerState::system_install() const { 210 bool InstallerState::system_install() const {
347 DCHECK(level_ == USER_LEVEL || level_ == SYSTEM_LEVEL); 211 DCHECK(level_ == USER_LEVEL || level_ == SYSTEM_LEVEL);
348 return level_ == SYSTEM_LEVEL; 212 return level_ == SYSTEM_LEVEL;
349 } 213 }
350 214
351 bool InstallerState::is_multi_install() const {
352 DCHECK(package_type_ == SINGLE_PACKAGE || package_type_ == MULTI_PACKAGE);
353 return package_type_ != SINGLE_PACKAGE;
354 }
355
356 bool InstallerState::RemoveProduct(const Product* product) {
357 ScopedVector<Product>::iterator it =
358 std::find(products_.begin(), products_.end(), product);
359 if (it != products_.end()) {
360 products_.weak_erase(it);
361 return true;
362 }
363 return false;
364 }
365
366 const Product* InstallerState::FindProduct(
367 BrowserDistribution::Type distribution_type) const {
368 for (Products::const_iterator scan = products_.begin(), end = products_.end();
369 scan != end; ++scan) {
370 if ((*scan)->is_type(distribution_type))
371 return *scan;
372 }
373 return NULL;
374 }
375
376 base::Version* InstallerState::GetCurrentVersion( 215 base::Version* InstallerState::GetCurrentVersion(
377 const InstallationState& machine_state) const { 216 const InstallationState& machine_state) const {
378 DCHECK(!products_.empty()); 217 DCHECK(product_);
379 std::unique_ptr<base::Version> current_version; 218 std::unique_ptr<base::Version> current_version;
380 // If we're doing a multi-install, the current version may be either an
381 // existing multi or an existing single product that is being migrated
382 // in place (i.e., Chrome). In the latter case, there is no existing
383 // CHROME_BINARIES installation so we need to search for the product.
384 BrowserDistribution::Type prod_type; 219 BrowserDistribution::Type prod_type;
385 if (package_type_ == MULTI_PACKAGE) { 220 prod_type = product_->distribution()->GetType();
386 prod_type = BrowserDistribution::CHROME_BINARIES;
387 if (machine_state.GetProductState(level_ == SYSTEM_LEVEL,
388 prod_type) == NULL) {
389 // Search for a product on which we're operating that is installed in our
390 // target directory.
391 Products::const_iterator end = products().end();
392 for (Products::const_iterator scan = products().begin(); scan != end;
393 ++scan) {
394 BrowserDistribution::Type product_type =
395 (*scan)->distribution()->GetType();
396 const ProductState* state =
397 machine_state.GetProductState(level_ == SYSTEM_LEVEL, product_type);
398 if (state != NULL && target_path_.IsParent(state->GetSetupPath())) {
399 prod_type = product_type;
400 break;
401 }
402 }
403 }
404 } else {
405 prod_type = products_[0]->distribution()->GetType();
406 }
407 const ProductState* product_state = 221 const ProductState* product_state =
408 machine_state.GetProductState(level_ == SYSTEM_LEVEL, prod_type); 222 machine_state.GetProductState(level_ == SYSTEM_LEVEL, prod_type);
409 223
410 if (product_state != NULL) { 224 if (product_state != NULL) {
411 const base::Version* version = NULL; 225 const base::Version* version = NULL;
412 226
413 // Be aware that there might be a pending "new_chrome.exe" already in the 227 // Be aware that there might be a pending "new_chrome.exe" already in the
414 // installation path. If so, we use old_version, which holds the version of 228 // installation path. If so, we use old_version, which holds the version of
415 // "chrome.exe" itself. 229 // "chrome.exe" itself.
416 if (base::PathExists(target_path().Append(kChromeNewExe))) 230 if (base::PathExists(target_path().Append(kChromeNewExe)))
(...skipping 15 matching lines...) Expand all
432 DCHECK(new_version.IsValid()); 246 DCHECK(new_version.IsValid());
433 if (critical_update_version_.IsValid() && 247 if (critical_update_version_.IsValid() &&
434 (current_version == NULL || 248 (current_version == NULL ||
435 (current_version->CompareTo(critical_update_version_) < 0)) && 249 (current_version->CompareTo(critical_update_version_) < 0)) &&
436 new_version.CompareTo(critical_update_version_) >= 0) { 250 new_version.CompareTo(critical_update_version_) >= 0) {
437 return critical_update_version_; 251 return critical_update_version_;
438 } 252 }
439 return base::Version(); 253 return base::Version();
440 } 254 }
441 255
442 bool InstallerState::IsChromeFrameRunning(
443 const InstallationState& machine_state) const {
444 return AnyExistsAndIsInUse(machine_state, CHROME_FRAME_DLL);
445 }
446
447 bool InstallerState::AreBinariesInUse(
448 const InstallationState& machine_state) const {
449 return AnyExistsAndIsInUse(
450 machine_state,
451 (CHROME_FRAME_HELPER_EXE | CHROME_FRAME_HELPER_DLL |
452 CHROME_FRAME_DLL | CHROME_DLL));
453 }
454
455 base::FilePath InstallerState::GetInstallerDirectory( 256 base::FilePath InstallerState::GetInstallerDirectory(
456 const base::Version& version) const { 257 const base::Version& version) const {
457 return target_path().AppendASCII(version.GetString()).Append(kInstallerDir); 258 return target_path().AppendASCII(version.GetString()).Append(kInstallerDir);
458 } 259 }
459 260
460 // static
461 bool InstallerState::IsFileInUse(const base::FilePath& file) {
462 // Call CreateFile with a share mode of 0 which should cause this to fail
463 // with ERROR_SHARING_VIOLATION if the file exists and is in-use.
464 return !base::win::ScopedHandle(CreateFile(file.value().c_str(),
465 GENERIC_WRITE, 0, NULL,
466 OPEN_EXISTING, 0, 0)).IsValid();
467 }
468
469 void InstallerState::Clear() { 261 void InstallerState::Clear() {
470 operation_ = UNINITIALIZED; 262 operation_ = UNINITIALIZED;
471 target_path_.clear(); 263 target_path_.clear();
472 state_key_.clear(); 264 state_key_.clear();
473 state_type_ = BrowserDistribution::CHROME_BROWSER; 265 state_type_ = BrowserDistribution::CHROME_BROWSER;
474 products_.clear(); 266 product_.reset();
475 multi_package_distribution_ = NULL;
476 critical_update_version_ = base::Version(); 267 critical_update_version_ = base::Version();
477 level_ = UNKNOWN_LEVEL; 268 level_ = UNKNOWN_LEVEL;
478 package_type_ = UNKNOWN_PACKAGE_TYPE;
479 root_key_ = NULL; 269 root_key_ = NULL;
480 msi_ = false; 270 msi_ = false;
481 verbose_logging_ = false; 271 verbose_logging_ = false;
482 is_migrating_to_single_ = false; 272 is_migrating_to_single_ = false;
483 } 273 }
484 274
485 bool InstallerState::AnyExistsAndIsInUse(const InstallationState& machine_state,
486 uint32_t file_bits) const {
487 static const wchar_t* const kBinaryFileNames[] = {
488 kChromeDll,
489 kChromeFrameDll,
490 kChromeFrameHelperDll,
491 kChromeFrameHelperExe,
492 };
493 DCHECK_NE(file_bits, 0U);
494 DCHECK_LT(file_bits, 1U << NUM_BINARIES);
495 static_assert(CHROME_DLL == 1, "binary file names and values must match");
496 static_assert(CHROME_FRAME_DLL == 2,
497 "binary file names and values must match");
498 static_assert(CHROME_FRAME_HELPER_DLL == 4,
499 "binary file names and values must match");
500 static_assert(CHROME_FRAME_HELPER_EXE == 8,
501 "binary file names and values must match");
502
503 // Check only for the current version (i.e., the version we are upgrading
504 // _from_). Later versions from pending in-use updates need not be checked
505 // since the current version is guaranteed to be in use if any such are.
506 std::unique_ptr<base::Version> current_version(
507 GetCurrentVersion(machine_state));
508 if (!current_version)
509 return false;
510 base::FilePath directory(
511 target_path().AppendASCII(current_version->GetString()));
512 for (int i = 0; i < NUM_BINARIES; ++i) {
513 if (!(file_bits & (1U << i)))
514 continue;
515 base::FilePath file(directory.Append(kBinaryFileNames[i]));
516 if (base::PathExists(file) && IsFileInUse(file))
517 return true;
518 }
519 return false;
520 }
521
522 void InstallerState::AddComDllList(
523 std::vector<base::FilePath>* com_dll_list) const {
524 for (auto* product : products_)
525 product->AddComDllList(com_dll_list);
526 }
527
528 void InstallerState::SetStage(InstallerStage stage) const { 275 void InstallerState::SetStage(InstallerStage stage) const {
529 GoogleUpdateSettings::SetProgress(system_install(), state_key_, 276 GoogleUpdateSettings::SetProgress(system_install(), state_key_,
530 progress_calculator_.Calculate(stage)); 277 progress_calculator_.Calculate(stage));
531 } 278 }
532 279
533 void InstallerState::UpdateChannels() const { 280 void InstallerState::UpdateChannels() const {
534 DCHECK_NE(UNINSTALL, operation_); 281 DCHECK_NE(UNINSTALL, operation_);
535 // Update the "ap" value for the product being installed/updated. Use the 282 // Update the "ap" value for the product being installed/updated. Use the
536 // current value in the registry since the InstallationState instance used by 283 // current value in the registry since the InstallationState instance used by
537 // the bulk of the installer does not track changes made by UpdateStage. 284 // the bulk of the installer does not track changes made by UpdateStage.
538 // Create the app's ClientState key if it doesn't exist. 285 // Create the app's ClientState key if it doesn't exist.
539 ChannelInfo channel_info; 286 ChannelInfo channel_info;
540 base::win::RegKey state_key; 287 base::win::RegKey state_key;
541 LONG result = 288 LONG result =
542 state_key.Create(root_key_, 289 state_key.Create(root_key_,
543 state_key_.c_str(), 290 state_key_.c_str(),
544 KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_WOW64_32KEY); 291 KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_WOW64_32KEY);
545 if (result == ERROR_SUCCESS) { 292 if (result == ERROR_SUCCESS) {
546 channel_info.Initialize(state_key); 293 channel_info.Initialize(state_key);
547 294
548 // This is a multi-install product. 295 // This is not a multi-install product.
549 bool modified = channel_info.SetMultiInstall(is_multi_install()); 296 bool modified = channel_info.SetMultiInstall(false);
550 297
551 if (is_multi_install()) { 298 // Remove all multi-install products from the channel name.
552 // Add the appropriate modifiers for all products and their options. 299 modified |= channel_info.SetChrome(false);
553 for (auto* product : products_) 300 modified |= channel_info.SetChromeFrame(false);
554 modified |= product->SetChannelFlags(true, &channel_info); 301 modified |= channel_info.SetAppLauncher(false);
555 } else {
556 // Remove all multi-install products from the channel name.
557 modified |= channel_info.SetChrome(false);
558 modified |= channel_info.SetChromeFrame(false);
559 modified |= channel_info.SetAppLauncher(false);
560 }
561 302
562 VLOG(1) << "ap: " << channel_info.value(); 303 VLOG(1) << "ap: " << channel_info.value();
563 304
564 // Write the results if needed. 305 // Write the results if needed.
565 if (modified) 306 if (modified)
566 channel_info.Write(&state_key); 307 channel_info.Write(&state_key);
567
568 if (is_multi_install()) {
569 // Remove the -stage: modifier since we don't want to propagate that to
570 // the other app_guids.
571 channel_info.ClearStage();
572
573 // Synchronize the other products and the package with this one.
574 ChannelInfo other_info;
575 for (int i = 0; i < BrowserDistribution::NUM_TYPES; ++i) {
576 BrowserDistribution::Type type =
577 static_cast<BrowserDistribution::Type>(i);
578 // Skip the app_guid we started with.
579 if (type == state_type_)
580 continue;
581 BrowserDistribution* dist = NULL;
582 // Always operate on the binaries.
583 if (i == BrowserDistribution::CHROME_BINARIES) {
584 dist = multi_package_distribution_;
585 } else {
586 const Product* product = FindProduct(type);
587 // Skip this one if it's for a product we're not operating on.
588 if (product == NULL)
589 continue;
590 dist = product->distribution();
591 }
592 result =
593 state_key.Create(root_key_,
594 dist->GetStateKey().c_str(),
595 KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_WOW64_32KEY);
596 if (result == ERROR_SUCCESS) {
597 other_info.Initialize(state_key);
598 if (!other_info.Equals(channel_info))
599 channel_info.Write(&state_key);
600 } else {
601 LOG(ERROR) << "Failed opening key " << dist->GetStateKey()
602 << " to update app channels; result: " << result;
603 }
604 }
605 }
606 } else { 308 } else {
607 LOG(ERROR) << "Failed opening key " << state_key_ 309 LOG(ERROR) << "Failed opening key " << state_key_
608 << " to update app channels; result: " << result; 310 << " to update app channels; result: " << result;
609 } 311 }
610 } 312 }
611 313
612 void InstallerState::WriteInstallerResult( 314 void InstallerState::WriteInstallerResult(
613 InstallStatus status, 315 InstallStatus status,
614 int string_resource_id, 316 int string_resource_id,
615 const base::string16* const launch_cmd) const { 317 const base::string16* const launch_cmd) const {
616 // Use a no-rollback list since this is a best-effort deal. 318 // Use a no-rollback list since this is a best-effort deal.
617 std::unique_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); 319 std::unique_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList());
618 install_list->set_log_message("Write Installer Result"); 320 install_list->set_log_message("Write Installer Result");
619 install_list->set_best_effort(true); 321 install_list->set_best_effort(true);
620 install_list->set_rollback_enabled(false); 322 install_list->set_rollback_enabled(false);
621 const bool system_install = this->system_install(); 323 const bool system_install = this->system_install();
622 // Write the value for all products upon which we're operating. 324 // Write the value for the product upon which we're operating.
623 Products::const_iterator end = products().end(); 325 InstallUtil::AddInstallerResultItems(
624 for (Products::const_iterator scan = products().begin(); scan != end; 326 system_install, product_->distribution()->GetStateKey(), status,
625 ++scan) { 327 string_resource_id, launch_cmd, install_list.get());
626 InstallUtil::AddInstallerResultItems( 328 if (is_migrating_to_single() && InstallUtil::GetInstallReturnCode(status)) {
627 system_install, (*scan)->distribution()->GetStateKey(), status,
628 string_resource_id, launch_cmd, install_list.get());
629 }
630 // And for the binaries if this is a multi-install.
631 if (is_multi_install()) {
632 InstallUtil::AddInstallerResultItems(
633 system_install, multi_package_binaries_distribution()->GetStateKey(),
634 status, string_resource_id, launch_cmd, install_list.get());
635 } else if (is_migrating_to_single() &&
636 InstallUtil::GetInstallReturnCode(status)) {
637 #if defined(GOOGLE_CHROME_BUILD) 329 #if defined(GOOGLE_CHROME_BUILD)
638 // Also write to the binaries on error if this is a migration back to 330 // Write to the binaries on error if this is a migration back to
639 // single-install for Google Chrome builds. Skip this for Chromium builds 331 // single-install for Google Chrome builds. Skip this for Chromium builds
640 // because they lump the "ClientState" and "Clients" keys into a single 332 // because they lump the "ClientState" and "Clients" keys into a single
641 // key. As a consequence, writing this value causes Software\Chromium to be 333 // key. As a consequence, writing this value causes Software\Chromium to be
642 // re-created after it was deleted during the migration to single-install. 334 // re-created after it was deleted during the migration to single-install.
643 // Google Chrome builds don't suffer this since the two keys are distinct 335 // Google Chrome builds don't suffer this since the two keys are distinct
644 // and have different lifetimes. The result is only written on failure since 336 // and have different lifetimes. The result is only written on failure since
645 // for success, the binaries have been uninstalled and therefore the result 337 // for success, the binaries have been uninstalled and therefore the result
646 // will not be read by Google Update. 338 // will not be read by Google Update.
647 InstallUtil::AddInstallerResultItems( 339 InstallUtil::AddInstallerResultItems(
648 system_install, BrowserDistribution::GetSpecificDistribution( 340 system_install, BrowserDistribution::GetSpecificDistribution(
649 BrowserDistribution::CHROME_BINARIES) 341 BrowserDistribution::CHROME_BINARIES)
650 ->GetStateKey(), 342 ->GetStateKey(),
651 status, string_resource_id, launch_cmd, install_list.get()); 343 status, string_resource_id, launch_cmd, install_list.get());
652 #endif 344 #endif
653 } 345 }
654 install_list->Do(); 346 install_list->Do();
655 } 347 }
656 348
657 bool InstallerState::RequiresActiveSetup() const { 349 bool InstallerState::RequiresActiveSetup() const {
658 return system_install() && FindProduct(BrowserDistribution::CHROME_BROWSER); 350 return system_install();
659 } 351 }
660 352
661 } // namespace installer 353 } // namespace installer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698