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

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

Issue 2589753002: Remove multi-install from chrome/installer/setup. (Closed)
Patch Set: gab and robertshield comments Created 3 years, 11 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"
18 #include "base/macros.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/win/registry.h" 14 #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" 15 #include "chrome/installer/util/google_update_settings.h"
24 #include "chrome/installer/util/helper.h" 16 #include "chrome/installer/util/helper.h"
25 #include "chrome/installer/util/install_util.h" 17 #include "chrome/installer/util/install_util.h"
26 #include "chrome/installer/util/installation_state.h" 18 #include "chrome/installer/util/installation_state.h"
27 #include "chrome/installer/util/master_preferences.h" 19 #include "chrome/installer/util/master_preferences.h"
28 #include "chrome/installer/util/master_preferences_constants.h" 20 #include "chrome/installer/util/master_preferences_constants.h"
29 #include "chrome/installer/util/product.h" 21 #include "chrome/installer/util/product.h"
30 #include "chrome/installer/util/work_item.h" 22 #include "chrome/installer/util/work_item.h"
31 #include "chrome/installer/util/work_item_list.h" 23 #include "chrome/installer/util/work_item_list.h"
32 24
33 namespace installer { 25 namespace installer {
34 26
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() 27 InstallerState::InstallerState()
68 : operation_(UNINITIALIZED), 28 : operation_(UNINITIALIZED),
69 state_type_(BrowserDistribution::CHROME_BROWSER), 29 state_type_(BrowserDistribution::CHROME_BROWSER),
70 multi_package_distribution_(NULL),
71 level_(UNKNOWN_LEVEL), 30 level_(UNKNOWN_LEVEL),
72 package_type_(UNKNOWN_PACKAGE_TYPE),
73 root_key_(NULL), 31 root_key_(NULL),
74 msi_(false), 32 msi_(false),
75 background_mode_(false), 33 background_mode_(false),
76 verbose_logging_(false), 34 verbose_logging_(false),
77 is_migrating_to_single_(false) {} 35 is_migrating_to_single_(false) {}
78 36
79 InstallerState::InstallerState(Level level) 37 InstallerState::InstallerState(Level level)
80 : operation_(UNINITIALIZED), 38 : operation_(UNINITIALIZED),
81 state_type_(BrowserDistribution::CHROME_BROWSER), 39 state_type_(BrowserDistribution::CHROME_BROWSER),
82 multi_package_distribution_(NULL),
83 level_(UNKNOWN_LEVEL), 40 level_(UNKNOWN_LEVEL),
84 package_type_(UNKNOWN_PACKAGE_TYPE),
85 root_key_(NULL), 41 root_key_(NULL),
86 msi_(false), 42 msi_(false),
87 background_mode_(false), 43 background_mode_(false),
88 verbose_logging_(false), 44 verbose_logging_(false),
89 is_migrating_to_single_(false) { 45 is_migrating_to_single_(false) {
90 // Use set_level() so that root_key_ is updated properly. 46 // Use set_level() so that root_key_ is updated properly.
91 set_level(level); 47 set_level(level);
92 } 48 }
93 49
94 InstallerState::~InstallerState() { 50 InstallerState::~InstallerState() {
95 } 51 }
96 52
97 void InstallerState::Initialize(const base::CommandLine& command_line, 53 void InstallerState::Initialize(const base::CommandLine& command_line,
98 const MasterPreferences& prefs, 54 const MasterPreferences& prefs,
99 const InstallationState& machine_state) { 55 const InstallationState& machine_state) {
100 Clear(); 56 Clear();
101 57
102 bool pref_bool; 58 bool pref_bool;
103 if (!prefs.GetBool(master_preferences::kSystemLevel, &pref_bool)) 59 if (!prefs.GetBool(master_preferences::kSystemLevel, &pref_bool))
104 pref_bool = false; 60 pref_bool = false;
105 set_level(pref_bool ? SYSTEM_LEVEL : USER_LEVEL); 61 set_level(pref_bool ? SYSTEM_LEVEL : USER_LEVEL);
106 62
107 if (!prefs.GetBool(master_preferences::kVerboseLogging, &verbose_logging_)) 63 if (!prefs.GetBool(master_preferences::kVerboseLogging, &verbose_logging_))
108 verbose_logging_ = false; 64 verbose_logging_ = false;
109 65
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_)) 66 if (!prefs.GetBool(master_preferences::kMsi, &msi_))
115 msi_ = false; 67 msi_ = false;
116 68
117 const bool is_uninstall = command_line.HasSwitch(switches::kUninstall); 69 const bool is_uninstall = command_line.HasSwitch(switches::kUninstall);
118 70
119 if (prefs.install_chrome()) { 71 Product* p = AddProductFromPreferences(BrowserDistribution::CHROME_BROWSER,
120 Product* p = AddProductFromPreferences( 72 prefs, machine_state);
121 BrowserDistribution::CHROME_BROWSER, prefs, machine_state); 73 VLOG(1) << (is_uninstall ? "Uninstall" : "Install")
122 VLOG(1) << (is_uninstall ? "Uninstall" : "Install") 74 << " distribution: " << p->distribution()->GetDisplayName();
123 << " distribution: " << p->distribution()->GetDisplayName();
124 }
125 75
126 // Binaries are only used by Chrome. 76 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
127 if (is_multi_install() && 77 state_key_ = dist->GetStateKey();
128 FindProduct(BrowserDistribution::CHROME_BROWSER)) { 78 state_type_ = dist->GetType();
129 Product* p = AddProductFromPreferences(
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 79
137 if (is_uninstall) { 80 if (is_uninstall) {
138 operation_ = UNINSTALL; 81 operation_ = UNINSTALL;
139 } else if (!prefs.is_multi_install()) { 82 } else {
140 // For a single-install, the current browser dist is the operand.
141 operand = BrowserDistribution::GetDistribution();
142 operation_ = SINGLE_INSTALL_OR_UPDATE; 83 operation_ = SINGLE_INSTALL_OR_UPDATE;
143 // Is this a migration from multi-install to single-install? 84 // Is this a migration from multi-install to single-install?
144 const ProductState* state = 85 const ProductState* state =
145 machine_state.GetProductState(system_install(), operand->GetType()); 86 machine_state.GetProductState(system_install(), state_type_);
146 is_migrating_to_single_ = state && state->is_multi_install(); 87 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 } 88 }
155 89
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 90 // Parse --critical-update-version=W.X.Y.Z
169 std::string critical_version_value( 91 std::string critical_version_value(
170 command_line.GetSwitchValueASCII(switches::kCriticalUpdateVersion)); 92 command_line.GetSwitchValueASCII(switches::kCriticalUpdateVersion));
171 critical_update_version_ = base::Version(critical_version_value); 93 critical_update_version_ = base::Version(critical_version_value);
172 } 94 }
173 95
174 void InstallerState::set_level(Level level) { 96 void InstallerState::set_level(Level level) {
175 level_ = level; 97 level_ = level;
176 switch (level) { 98 switch (level) {
177 case USER_LEVEL: 99 case USER_LEVEL:
178 root_key_ = HKEY_CURRENT_USER; 100 root_key_ = HKEY_CURRENT_USER;
179 break; 101 break;
180 case SYSTEM_LEVEL: 102 case SYSTEM_LEVEL:
181 root_key_ = HKEY_LOCAL_MACHINE; 103 root_key_ = HKEY_LOCAL_MACHINE;
182 break; 104 break;
183 default: 105 default:
184 DCHECK(level == UNKNOWN_LEVEL); 106 DCHECK(level == UNKNOWN_LEVEL);
185 level_ = UNKNOWN_LEVEL; 107 level_ = UNKNOWN_LEVEL;
186 root_key_ = NULL; 108 root_key_ = NULL;
187 break; 109 break;
188 } 110 }
189 } 111 }
190 112
191 void InstallerState::set_package_type(PackageType type) {
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(
213 BrowserDistribution* dist) const {
214 DCHECK(dist);
215 DCHECK(package_type_ != UNKNOWN_PACKAGE_TYPE);
216
217 if (package_type_ == SINGLE_PACKAGE) {
218 return GetChromeInstallPath(system_install(), dist);
219 } else {
220 return GetChromeInstallPath(system_install(),
221 BrowserDistribution::GetSpecificDistribution(
222 BrowserDistribution::CHROME_BINARIES));
223 }
224 }
225
226 // Evaluates a product's eligibility for participation in this operation. 113 // 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 114 // We never expect these checks to fail, hence they all terminate the process in
228 // debug builds. See the log messages for details. 115 // debug builds. See the log messages for details.
229 bool InstallerState::CanAddProduct(const Product& product, 116 bool InstallerState::CanAddProduct(const Product& product,
huangs 2017/01/06 17:57:18 Note that |product| is no longer used. Would code
grt (UTC plus 2) 2017/01/06 21:15:46 Done.
230 const base::FilePath* product_dir) const { 117 const base::FilePath* product_dir) const {
231 switch (package_type_) { 118 if (product_) {
232 case SINGLE_PACKAGE: 119 LOG(DFATAL) << "Cannot process more than one single-install product.";
233 if (!products_.empty()) { 120 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 } 121 }
264 return true; 122 return true;
265 } 123 }
266 124
267 // Adds |product|, installed in |product_dir| to this object's collection. If 125 // 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. 126 // |product_dir| is NULL, the product's default install location is used.
269 // Returns NULL if |product| is incompatible with this object. Otherwise, 127 // Returns NULL if |product| is incompatible with this object. Otherwise,
270 // returns a pointer to the product (ownership is held by this object). 128 // returns a pointer to the product (ownership is held by this object).
271 Product* InstallerState::AddProductInDirectory( 129 Product* InstallerState::AddProductInDirectory(
272 const base::FilePath* product_dir, 130 const base::FilePath* product_dir,
273 std::unique_ptr<Product>* product) { 131 std::unique_ptr<Product> product) {
274 DCHECK(product != NULL); 132 DCHECK(product);
275 DCHECK(product->get() != NULL); 133 const Product& the_product = *product;
276 const Product& the_product = *product->get(); 134 DCHECK(!the_product.HasOption(kOptionMultiInstall));
277 135
278 if (!CanAddProduct(the_product, product_dir)) 136 if (!CanAddProduct(the_product, product_dir))
279 return NULL; 137 return nullptr;
280
281 if (package_type_ == UNKNOWN_PACKAGE_TYPE) {
282 set_package_type(the_product.HasOption(kOptionMultiInstall) ?
283 MULTI_PACKAGE : SINGLE_PACKAGE);
284 }
285 138
286 if (target_path_.empty()) { 139 if (target_path_.empty()) {
287 target_path_ = product_dir ? *product_dir : GetDefaultProductInstallPath( 140 target_path_ = product_dir ? *product_dir : GetChromeInstallPath(
141 system_install(),
288 the_product.distribution()); 142 the_product.distribution());
289 } 143 }
290 144
291 if (state_key_.empty()) 145 if (state_key_.empty())
292 state_key_ = the_product.distribution()->GetStateKey(); 146 state_key_ = the_product.distribution()->GetStateKey();
293 147
294 products_.push_back(product->release()); 148 product_ = std::move(product);
295 return products_.back(); 149 return product_.get();
296 } 150 }
297 151
298 Product* InstallerState::AddProduct(std::unique_ptr<Product>* product) { 152 Product* InstallerState::AddProduct(std::unique_ptr<Product> product) {
299 return AddProductInDirectory(NULL, product); 153 return AddProductInDirectory(nullptr, std::move(product));
300 } 154 }
301 155
302 // Adds a product of type |distribution_type| constructed on the basis of 156 // 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 157 // |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, 158 // |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 159 // or NULL if |state| is incompatible with this object. Ownership is not passed
306 // to the caller. 160 // to the caller.
307 Product* InstallerState::AddProductFromPreferences( 161 Product* InstallerState::AddProductFromPreferences(
308 BrowserDistribution::Type distribution_type, 162 BrowserDistribution::Type distribution_type,
309 const MasterPreferences& prefs, 163 const MasterPreferences& prefs,
310 const InstallationState& machine_state) { 164 const InstallationState& machine_state) {
311 std::unique_ptr<Product> product_ptr(new Product( 165 std::unique_ptr<Product> product_ptr(new Product(
312 BrowserDistribution::GetSpecificDistribution(distribution_type))); 166 BrowserDistribution::GetSpecificDistribution(distribution_type)));
313 product_ptr->InitializeFromPreferences(prefs); 167 product_ptr->InitializeFromPreferences(prefs);
314 168
315 Product* product = AddProductInDirectory(NULL, &product_ptr); 169 Product* product = AddProductInDirectory(nullptr, std::move(product_ptr));
316 170
317 if (product != NULL && !msi_) { 171 if (product != NULL && !msi_) {
318 const ProductState* product_state = machine_state.GetProductState( 172 const ProductState* product_state = machine_state.GetProductState(
319 system_install(), distribution_type); 173 system_install(), distribution_type);
320 if (product_state != NULL) 174 if (product_state != NULL)
321 msi_ = product_state->is_msi(); 175 msi_ = product_state->is_msi();
322 } 176 }
323 177
324 return product; 178 return product;
325 } 179 }
326 180
327 Product* InstallerState::AddProductFromState( 181 Product* InstallerState::AddProductFromState(
328 BrowserDistribution::Type type, 182 BrowserDistribution::Type type,
329 const ProductState& state) { 183 const ProductState& state) {
330 std::unique_ptr<Product> product_ptr( 184 std::unique_ptr<Product> product_ptr(
331 new Product(BrowserDistribution::GetSpecificDistribution(type))); 185 new Product(BrowserDistribution::GetSpecificDistribution(type)));
332 product_ptr->InitializeFromUninstallCommand(state.uninstall_command()); 186 product_ptr->InitializeFromUninstallCommand(state.uninstall_command());
333 187
334 // Strip off <version>/Installer/setup.exe; see GetInstallerDirectory(). 188 // Strip off <version>/Installer/setup.exe; see GetInstallerDirectory().
335 base::FilePath product_dir = 189 base::FilePath product_dir =
336 state.GetSetupPath().DirName().DirName().DirName(); 190 state.GetSetupPath().DirName().DirName().DirName();
337 191
338 Product* product = AddProductInDirectory(&product_dir, &product_ptr); 192 Product* product =
193 AddProductInDirectory(&product_dir, std::move(product_ptr));
339 194
340 if (product != NULL) 195 if (product != NULL)
341 msi_ |= state.is_msi(); 196 msi_ |= state.is_msi();
342 197
343 return product; 198 return product;
344 } 199 }
345 200
346 bool InstallerState::system_install() const { 201 bool InstallerState::system_install() const {
347 DCHECK(level_ == USER_LEVEL || level_ == SYSTEM_LEVEL); 202 DCHECK(level_ == USER_LEVEL || level_ == SYSTEM_LEVEL);
348 return level_ == SYSTEM_LEVEL; 203 return level_ == SYSTEM_LEVEL;
349 } 204 }
350 205
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( 206 base::Version* InstallerState::GetCurrentVersion(
377 const InstallationState& machine_state) const { 207 const InstallationState& machine_state) const {
378 DCHECK(!products_.empty()); 208 DCHECK(product_);
379 std::unique_ptr<base::Version> current_version; 209 std::unique_ptr<base::Version> current_version;
380 // If we're doing a multi-install, the current version may be either an 210 const ProductState* product_state = machine_state.GetProductState(
381 // existing multi or an existing single product that is being migrated 211 level_ == SYSTEM_LEVEL, product_->distribution()->GetType());
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;
385 if (package_type_ == MULTI_PACKAGE) {
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 =
408 machine_state.GetProductState(level_ == SYSTEM_LEVEL, prod_type);
409 212
410 if (product_state != NULL) { 213 if (product_state != NULL) {
411 const base::Version* version = NULL; 214 const base::Version* version = NULL;
412 215
413 // Be aware that there might be a pending "new_chrome.exe" already in the 216 // 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 217 // installation path. If so, we use old_version, which holds the version of
415 // "chrome.exe" itself. 218 // "chrome.exe" itself.
416 if (base::PathExists(target_path().Append(kChromeNewExe))) 219 if (base::PathExists(target_path().Append(kChromeNewExe)))
417 version = product_state->old_version(); 220 version = product_state->old_version();
418 221
(...skipping 13 matching lines...) Expand all
432 DCHECK(new_version.IsValid()); 235 DCHECK(new_version.IsValid());
433 if (critical_update_version_.IsValid() && 236 if (critical_update_version_.IsValid() &&
434 (current_version == NULL || 237 (current_version == NULL ||
435 (current_version->CompareTo(critical_update_version_) < 0)) && 238 (current_version->CompareTo(critical_update_version_) < 0)) &&
436 new_version.CompareTo(critical_update_version_) >= 0) { 239 new_version.CompareTo(critical_update_version_) >= 0) {
437 return critical_update_version_; 240 return critical_update_version_;
438 } 241 }
439 return base::Version(); 242 return base::Version();
440 } 243 }
441 244
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( 245 base::FilePath InstallerState::GetInstallerDirectory(
456 const base::Version& version) const { 246 const base::Version& version) const {
457 return target_path().AppendASCII(version.GetString()).Append(kInstallerDir); 247 return target_path().AppendASCII(version.GetString()).Append(kInstallerDir);
458 } 248 }
459 249
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() { 250 void InstallerState::Clear() {
470 operation_ = UNINITIALIZED; 251 operation_ = UNINITIALIZED;
471 target_path_.clear(); 252 target_path_.clear();
472 state_key_.clear(); 253 state_key_.clear();
473 state_type_ = BrowserDistribution::CHROME_BROWSER; 254 state_type_ = BrowserDistribution::CHROME_BROWSER;
474 products_.clear(); 255 product_.reset();
475 multi_package_distribution_ = NULL;
476 critical_update_version_ = base::Version(); 256 critical_update_version_ = base::Version();
477 level_ = UNKNOWN_LEVEL; 257 level_ = UNKNOWN_LEVEL;
478 package_type_ = UNKNOWN_PACKAGE_TYPE;
479 root_key_ = NULL; 258 root_key_ = NULL;
480 msi_ = false; 259 msi_ = false;
481 verbose_logging_ = false; 260 verbose_logging_ = false;
482 is_migrating_to_single_ = false; 261 is_migrating_to_single_ = false;
483 } 262 }
484 263
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 { 264 void InstallerState::SetStage(InstallerStage stage) const {
529 GoogleUpdateSettings::SetProgress(system_install(), state_key_, 265 GoogleUpdateSettings::SetProgress(system_install(), state_key_,
530 progress_calculator_.Calculate(stage)); 266 progress_calculator_.Calculate(stage));
531 } 267 }
532 268
533 void InstallerState::UpdateChannels() const { 269 void InstallerState::UpdateChannels() const {
534 DCHECK_NE(UNINSTALL, operation_); 270 DCHECK_NE(UNINSTALL, operation_);
535 // Update the "ap" value for the product being installed/updated. Use the 271 // Update the "ap" value for the product being installed/updated. Use the
536 // current value in the registry since the InstallationState instance used by 272 // current value in the registry since the InstallationState instance used by
537 // the bulk of the installer does not track changes made by UpdateStage. 273 // the bulk of the installer does not track changes made by UpdateStage.
538 // Create the app's ClientState key if it doesn't exist. 274 // Create the app's ClientState key if it doesn't exist.
539 ChannelInfo channel_info; 275 ChannelInfo channel_info;
540 base::win::RegKey state_key; 276 base::win::RegKey state_key;
541 LONG result = 277 LONG result =
542 state_key.Create(root_key_, 278 state_key.Create(root_key_,
543 state_key_.c_str(), 279 state_key_.c_str(),
544 KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_WOW64_32KEY); 280 KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_WOW64_32KEY);
545 if (result == ERROR_SUCCESS) { 281 if (result == ERROR_SUCCESS) {
546 channel_info.Initialize(state_key); 282 channel_info.Initialize(state_key);
547 283
548 // This is a multi-install product. 284 // Multi-install has been deprecated. All installs and updates are single.
549 bool modified = channel_info.SetMultiInstall(is_multi_install()); 285 bool modified = channel_info.SetMultiInstall(false);
550 286
551 if (is_multi_install()) { 287 // Remove all multi-install products from the channel name.
552 // Add the appropriate modifiers for all products and their options. 288 modified |= channel_info.SetChrome(false);
553 for (auto* product : products_) 289 modified |= channel_info.SetChromeFrame(false);
554 modified |= product->SetChannelFlags(true, &channel_info); 290 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 291
562 VLOG(1) << "ap: " << channel_info.value(); 292 VLOG(1) << "ap: " << channel_info.value();
563 293
564 // Write the results if needed. 294 // Write the results if needed.
565 if (modified) 295 if (modified)
566 channel_info.Write(&state_key); 296 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 { 297 } else {
607 LOG(ERROR) << "Failed opening key " << state_key_ 298 LOG(ERROR) << "Failed opening key " << state_key_
608 << " to update app channels; result: " << result; 299 << " to update app channels; result: " << result;
609 } 300 }
610 } 301 }
611 302
612 void InstallerState::WriteInstallerResult( 303 void InstallerState::WriteInstallerResult(
613 InstallStatus status, 304 InstallStatus status,
614 int string_resource_id, 305 int string_resource_id,
615 const base::string16* const launch_cmd) const { 306 const base::string16* const launch_cmd) const {
616 // Use a no-rollback list since this is a best-effort deal. 307 // Use a no-rollback list since this is a best-effort deal.
617 std::unique_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); 308 std::unique_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList());
618 install_list->set_log_message("Write Installer Result"); 309 install_list->set_log_message("Write Installer Result");
619 install_list->set_best_effort(true); 310 install_list->set_best_effort(true);
620 install_list->set_rollback_enabled(false); 311 install_list->set_rollback_enabled(false);
621 const bool system_install = this->system_install(); 312 const bool system_install = this->system_install();
622 // Write the value for all products upon which we're operating. 313 // Write the value for the product upon which we're operating.
623 Products::const_iterator end = products().end(); 314 InstallUtil::AddInstallerResultItems(
624 for (Products::const_iterator scan = products().begin(); scan != end; 315 system_install, product_->distribution()->GetStateKey(), status,
625 ++scan) { 316 string_resource_id, launch_cmd, install_list.get());
626 InstallUtil::AddInstallerResultItems( 317 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) 318 #if defined(GOOGLE_CHROME_BUILD)
638 // Also write to the binaries on error if this is a migration back to 319 // 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 320 // single-install for Google Chrome builds. Skip this for Chromium builds
640 // because they lump the "ClientState" and "Clients" keys into a single 321 // because they lump the "ClientState" and "Clients" keys into a single
641 // key. As a consequence, writing this value causes Software\Chromium to be 322 // 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. 323 // 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 324 // 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 325 // and have different lifetimes. The result is only written on failure since
645 // for success, the binaries have been uninstalled and therefore the result 326 // for success, the binaries have been uninstalled and therefore the result
646 // will not be read by Google Update. 327 // will not be read by Google Update.
647 InstallUtil::AddInstallerResultItems( 328 InstallUtil::AddInstallerResultItems(
648 system_install, BrowserDistribution::GetSpecificDistribution( 329 system_install, BrowserDistribution::GetSpecificDistribution(
649 BrowserDistribution::CHROME_BINARIES) 330 BrowserDistribution::CHROME_BINARIES)
650 ->GetStateKey(), 331 ->GetStateKey(),
651 status, string_resource_id, launch_cmd, install_list.get()); 332 status, string_resource_id, launch_cmd, install_list.get());
652 #endif 333 #endif
653 } 334 }
654 install_list->Do(); 335 install_list->Do();
655 } 336 }
656 337
657 bool InstallerState::RequiresActiveSetup() const { 338 bool InstallerState::RequiresActiveSetup() const {
658 return system_install() && FindProduct(BrowserDistribution::CHROME_BROWSER); 339 return system_install();
659 } 340 }
660 341
661 } // namespace installer 342 } // namespace installer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698