Chromium Code Reviews| OLD | NEW |
|---|---|
| 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" |
|
huangs
2017/01/03 07:26:05
logging.h is already included in .h file.
grt (UTC plus 2)
2017/01/03 13:04:30
Done.
| |
| 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 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
| 127 if (is_multi_install() && | 78 state_key_ = dist->GetStateKey(); |
| 128 FindProduct(BrowserDistribution::CHROME_BROWSER)) { | 79 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 | 80 |
| 137 if (is_uninstall) { | 81 if (is_uninstall) { |
| 138 operation_ = UNINSTALL; | 82 operation_ = UNINSTALL; |
| 139 } else if (!prefs.is_multi_install()) { | 83 } else { |
| 140 // For a single-install, the current browser dist is the operand. | |
| 141 operand = BrowserDistribution::GetDistribution(); | |
| 142 operation_ = SINGLE_INSTALL_OR_UPDATE; | 84 operation_ = SINGLE_INSTALL_OR_UPDATE; |
| 143 // Is this a migration from multi-install to single-install? | 85 // Is this a migration from multi-install to single-install? |
| 144 const ProductState* state = | 86 const ProductState* state = |
| 145 machine_state.GetProductState(system_install(), operand->GetType()); | 87 machine_state.GetProductState(system_install(), dist->GetType()); |
|
huangs
2017/01/03 07:26:05
Just reminder that |state_type_| == dist->GetType(
grt (UTC plus 2)
2017/01/03 13:04:30
Done.
| |
| 146 is_migrating_to_single_ = state && state->is_multi_install(); | 88 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 } | 89 } |
| 155 | 90 |
| 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 | 91 // Parse --critical-update-version=W.X.Y.Z |
| 169 std::string critical_version_value( | 92 std::string critical_version_value( |
| 170 command_line.GetSwitchValueASCII(switches::kCriticalUpdateVersion)); | 93 command_line.GetSwitchValueASCII(switches::kCriticalUpdateVersion)); |
| 171 critical_update_version_ = base::Version(critical_version_value); | 94 critical_update_version_ = base::Version(critical_version_value); |
| 172 } | 95 } |
| 173 | 96 |
| 174 void InstallerState::set_level(Level level) { | 97 void InstallerState::set_level(Level level) { |
| 175 level_ = level; | 98 level_ = level; |
| 176 switch (level) { | 99 switch (level) { |
| 177 case USER_LEVEL: | 100 case USER_LEVEL: |
| 178 root_key_ = HKEY_CURRENT_USER; | 101 root_key_ = HKEY_CURRENT_USER; |
| 179 break; | 102 break; |
| 180 case SYSTEM_LEVEL: | 103 case SYSTEM_LEVEL: |
| 181 root_key_ = HKEY_LOCAL_MACHINE; | 104 root_key_ = HKEY_LOCAL_MACHINE; |
| 182 break; | 105 break; |
| 183 default: | 106 default: |
| 184 DCHECK(level == UNKNOWN_LEVEL); | 107 DCHECK(level == UNKNOWN_LEVEL); |
| 185 level_ = UNKNOWN_LEVEL; | 108 level_ = UNKNOWN_LEVEL; |
| 186 root_key_ = NULL; | 109 root_key_ = NULL; |
| 187 break; | 110 break; |
| 188 } | 111 } |
| 189 } | 112 } |
| 190 | 113 |
| 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. | 114 // 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 | 115 // We never expect these checks to fail, hence they all terminate the process in |
| 228 // debug builds. See the log messages for details. | 116 // debug builds. See the log messages for details. |
| 229 bool InstallerState::CanAddProduct(const Product& product, | 117 bool InstallerState::CanAddProduct(const Product& product, |
| 230 const base::FilePath* product_dir) const { | 118 const base::FilePath* product_dir) const { |
| 231 switch (package_type_) { | 119 if (product_) { |
| 232 case SINGLE_PACKAGE: | 120 LOG(DFATAL) << "Cannot process more than one single-install product."; |
| 233 if (!products_.empty()) { | 121 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 } | 122 } |
| 264 return true; | 123 return true; |
| 265 } | 124 } |
| 266 | 125 |
| 267 // Adds |product|, installed in |product_dir| to this object's collection. If | 126 // 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. | 127 // |product_dir| is NULL, the product's default install location is used. |
| 269 // Returns NULL if |product| is incompatible with this object. Otherwise, | 128 // Returns NULL if |product| is incompatible with this object. Otherwise, |
| 270 // returns a pointer to the product (ownership is held by this object). | 129 // returns a pointer to the product (ownership is held by this object). |
| 271 Product* InstallerState::AddProductInDirectory( | 130 Product* InstallerState::AddProductInDirectory( |
| 272 const base::FilePath* product_dir, | 131 const base::FilePath* product_dir, |
| 273 std::unique_ptr<Product>* product) { | 132 std::unique_ptr<Product>* product) { |
| 274 DCHECK(product != NULL); | 133 DCHECK(product != NULL); |
| 275 DCHECK(product->get() != NULL); | 134 DCHECK(product->get() != NULL); |
| 276 const Product& the_product = *product->get(); | 135 const Product& the_product = *product->get(); |
| 136 DCHECK(!the_product.HasOption(kOptionMultiInstall)); | |
| 277 | 137 |
| 278 if (!CanAddProduct(the_product, product_dir)) | 138 if (!CanAddProduct(the_product, product_dir)) |
| 279 return NULL; | 139 return NULL; |
| 280 | 140 |
| 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()) { | 141 if (target_path_.empty()) { |
| 287 target_path_ = product_dir ? *product_dir : GetDefaultProductInstallPath( | 142 target_path_ = product_dir ? *product_dir : GetChromeInstallPath( |
| 143 system_install(), | |
| 288 the_product.distribution()); | 144 the_product.distribution()); |
| 289 } | 145 } |
| 290 | 146 |
| 291 if (state_key_.empty()) | 147 if (state_key_.empty()) |
| 292 state_key_ = the_product.distribution()->GetStateKey(); | 148 state_key_ = the_product.distribution()->GetStateKey(); |
| 293 | 149 |
| 294 products_.push_back(product->release()); | 150 product_ = std::move(*product); |
| 295 return products_.back(); | 151 return product_.get(); |
| 296 } | 152 } |
| 297 | 153 |
| 298 Product* InstallerState::AddProduct(std::unique_ptr<Product>* product) { | 154 Product* InstallerState::AddProduct(std::unique_ptr<Product>* product) { |
| 299 return AddProductInDirectory(NULL, product); | 155 return AddProductInDirectory(NULL, product); |
| 300 } | 156 } |
| 301 | 157 |
| 302 // Adds a product of type |distribution_type| constructed on the basis of | 158 // 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 | 159 // |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, | 160 // |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 | 161 // 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 Loading... | |
| 341 msi_ |= state.is_msi(); | 197 msi_ |= state.is_msi(); |
| 342 | 198 |
| 343 return product; | 199 return product; |
| 344 } | 200 } |
| 345 | 201 |
| 346 bool InstallerState::system_install() const { | 202 bool InstallerState::system_install() const { |
| 347 DCHECK(level_ == USER_LEVEL || level_ == SYSTEM_LEVEL); | 203 DCHECK(level_ == USER_LEVEL || level_ == SYSTEM_LEVEL); |
| 348 return level_ == SYSTEM_LEVEL; | 204 return level_ == SYSTEM_LEVEL; |
| 349 } | 205 } |
| 350 | 206 |
| 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( | 207 base::Version* InstallerState::GetCurrentVersion( |
| 377 const InstallationState& machine_state) const { | 208 const InstallationState& machine_state) const { |
| 378 DCHECK(!products_.empty()); | 209 DCHECK(product_); |
| 379 std::unique_ptr<base::Version> current_version; | 210 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; | 211 BrowserDistribution::Type prod_type; |
| 385 if (package_type_ == MULTI_PACKAGE) { | 212 prod_type = product_->distribution()->GetType(); |
|
huangs
2017/01/03 07:26:05
Can combine these 2 lines, or even 4 lines.
grt (UTC plus 2)
2017/01/03 13:04:30
Done.
| |
| 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 = | 213 const ProductState* product_state = |
| 408 machine_state.GetProductState(level_ == SYSTEM_LEVEL, prod_type); | 214 machine_state.GetProductState(level_ == SYSTEM_LEVEL, prod_type); |
| 409 | 215 |
| 410 if (product_state != NULL) { | 216 if (product_state != NULL) { |
| 411 const base::Version* version = NULL; | 217 const base::Version* version = NULL; |
| 412 | 218 |
| 413 // Be aware that there might be a pending "new_chrome.exe" already in the | 219 // 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 | 220 // installation path. If so, we use old_version, which holds the version of |
| 415 // "chrome.exe" itself. | 221 // "chrome.exe" itself. |
| 416 if (base::PathExists(target_path().Append(kChromeNewExe))) | 222 if (base::PathExists(target_path().Append(kChromeNewExe))) |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 432 DCHECK(new_version.IsValid()); | 238 DCHECK(new_version.IsValid()); |
| 433 if (critical_update_version_.IsValid() && | 239 if (critical_update_version_.IsValid() && |
| 434 (current_version == NULL || | 240 (current_version == NULL || |
| 435 (current_version->CompareTo(critical_update_version_) < 0)) && | 241 (current_version->CompareTo(critical_update_version_) < 0)) && |
| 436 new_version.CompareTo(critical_update_version_) >= 0) { | 242 new_version.CompareTo(critical_update_version_) >= 0) { |
| 437 return critical_update_version_; | 243 return critical_update_version_; |
| 438 } | 244 } |
| 439 return base::Version(); | 245 return base::Version(); |
| 440 } | 246 } |
| 441 | 247 |
| 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( | 248 base::FilePath InstallerState::GetInstallerDirectory( |
| 456 const base::Version& version) const { | 249 const base::Version& version) const { |
| 457 return target_path().AppendASCII(version.GetString()).Append(kInstallerDir); | 250 return target_path().AppendASCII(version.GetString()).Append(kInstallerDir); |
| 458 } | 251 } |
| 459 | 252 |
| 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() { | 253 void InstallerState::Clear() { |
| 470 operation_ = UNINITIALIZED; | 254 operation_ = UNINITIALIZED; |
| 471 target_path_.clear(); | 255 target_path_.clear(); |
| 472 state_key_.clear(); | 256 state_key_.clear(); |
| 473 state_type_ = BrowserDistribution::CHROME_BROWSER; | 257 state_type_ = BrowserDistribution::CHROME_BROWSER; |
| 474 products_.clear(); | 258 product_.reset(); |
| 475 multi_package_distribution_ = NULL; | |
| 476 critical_update_version_ = base::Version(); | 259 critical_update_version_ = base::Version(); |
| 477 level_ = UNKNOWN_LEVEL; | 260 level_ = UNKNOWN_LEVEL; |
| 478 package_type_ = UNKNOWN_PACKAGE_TYPE; | |
| 479 root_key_ = NULL; | 261 root_key_ = NULL; |
| 480 msi_ = false; | 262 msi_ = false; |
| 481 verbose_logging_ = false; | 263 verbose_logging_ = false; |
| 482 is_migrating_to_single_ = false; | 264 is_migrating_to_single_ = false; |
| 483 } | 265 } |
| 484 | 266 |
| 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 { | 267 void InstallerState::SetStage(InstallerStage stage) const { |
| 529 GoogleUpdateSettings::SetProgress(system_install(), state_key_, | 268 GoogleUpdateSettings::SetProgress(system_install(), state_key_, |
| 530 progress_calculator_.Calculate(stage)); | 269 progress_calculator_.Calculate(stage)); |
| 531 } | 270 } |
| 532 | 271 |
| 533 void InstallerState::UpdateChannels() const { | 272 void InstallerState::UpdateChannels() const { |
| 534 DCHECK_NE(UNINSTALL, operation_); | 273 DCHECK_NE(UNINSTALL, operation_); |
| 535 // Update the "ap" value for the product being installed/updated. Use the | 274 // Update the "ap" value for the product being installed/updated. Use the |
| 536 // current value in the registry since the InstallationState instance used by | 275 // current value in the registry since the InstallationState instance used by |
| 537 // the bulk of the installer does not track changes made by UpdateStage. | 276 // the bulk of the installer does not track changes made by UpdateStage. |
| 538 // Create the app's ClientState key if it doesn't exist. | 277 // Create the app's ClientState key if it doesn't exist. |
| 539 ChannelInfo channel_info; | 278 ChannelInfo channel_info; |
| 540 base::win::RegKey state_key; | 279 base::win::RegKey state_key; |
| 541 LONG result = | 280 LONG result = |
| 542 state_key.Create(root_key_, | 281 state_key.Create(root_key_, |
| 543 state_key_.c_str(), | 282 state_key_.c_str(), |
| 544 KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_WOW64_32KEY); | 283 KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_WOW64_32KEY); |
| 545 if (result == ERROR_SUCCESS) { | 284 if (result == ERROR_SUCCESS) { |
| 546 channel_info.Initialize(state_key); | 285 channel_info.Initialize(state_key); |
| 547 | 286 |
| 548 // This is a multi-install product. | 287 // This is not a multi-install product. |
| 549 bool modified = channel_info.SetMultiInstall(is_multi_install()); | 288 bool modified = channel_info.SetMultiInstall(false); |
| 550 | 289 |
| 551 if (is_multi_install()) { | 290 // Remove all multi-install products from the channel name. |
|
huangs
2017/01/03 07:26:05
Mention that this is handling legacy?
Also, shoul
grt (UTC plus 2)
2017/01/03 13:04:30
Done.
| |
| 552 // Add the appropriate modifiers for all products and their options. | 291 modified |= channel_info.SetChrome(false); |
| 553 for (auto* product : products_) | 292 modified |= channel_info.SetChromeFrame(false); |
| 554 modified |= product->SetChannelFlags(true, &channel_info); | 293 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 | 294 |
| 562 VLOG(1) << "ap: " << channel_info.value(); | 295 VLOG(1) << "ap: " << channel_info.value(); |
| 563 | 296 |
| 564 // Write the results if needed. | 297 // Write the results if needed. |
| 565 if (modified) | 298 if (modified) |
| 566 channel_info.Write(&state_key); | 299 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 { | 300 } else { |
| 607 LOG(ERROR) << "Failed opening key " << state_key_ | 301 LOG(ERROR) << "Failed opening key " << state_key_ |
| 608 << " to update app channels; result: " << result; | 302 << " to update app channels; result: " << result; |
| 609 } | 303 } |
| 610 } | 304 } |
| 611 | 305 |
| 612 void InstallerState::WriteInstallerResult( | 306 void InstallerState::WriteInstallerResult( |
| 613 InstallStatus status, | 307 InstallStatus status, |
| 614 int string_resource_id, | 308 int string_resource_id, |
| 615 const base::string16* const launch_cmd) const { | 309 const base::string16* const launch_cmd) const { |
| 616 // Use a no-rollback list since this is a best-effort deal. | 310 // Use a no-rollback list since this is a best-effort deal. |
| 617 std::unique_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); | 311 std::unique_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); |
| 618 install_list->set_log_message("Write Installer Result"); | 312 install_list->set_log_message("Write Installer Result"); |
| 619 install_list->set_best_effort(true); | 313 install_list->set_best_effort(true); |
| 620 install_list->set_rollback_enabled(false); | 314 install_list->set_rollback_enabled(false); |
| 621 const bool system_install = this->system_install(); | 315 const bool system_install = this->system_install(); |
| 622 // Write the value for all products upon which we're operating. | 316 // Write the value for the product upon which we're operating. |
| 623 Products::const_iterator end = products().end(); | 317 InstallUtil::AddInstallerResultItems( |
| 624 for (Products::const_iterator scan = products().begin(); scan != end; | 318 system_install, product_->distribution()->GetStateKey(), status, |
| 625 ++scan) { | 319 string_resource_id, launch_cmd, install_list.get()); |
| 626 InstallUtil::AddInstallerResultItems( | 320 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) | 321 #if defined(GOOGLE_CHROME_BUILD) |
| 638 // Also write to the binaries on error if this is a migration back to | 322 // 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 | 323 // single-install for Google Chrome builds. Skip this for Chromium builds |
| 640 // because they lump the "ClientState" and "Clients" keys into a single | 324 // because they lump the "ClientState" and "Clients" keys into a single |
| 641 // key. As a consequence, writing this value causes Software\Chromium to be | 325 // 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. | 326 // 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 | 327 // 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 | 328 // and have different lifetimes. The result is only written on failure since |
| 645 // for success, the binaries have been uninstalled and therefore the result | 329 // for success, the binaries have been uninstalled and therefore the result |
| 646 // will not be read by Google Update. | 330 // will not be read by Google Update. |
| 647 InstallUtil::AddInstallerResultItems( | 331 InstallUtil::AddInstallerResultItems( |
| 648 system_install, BrowserDistribution::GetSpecificDistribution( | 332 system_install, BrowserDistribution::GetSpecificDistribution( |
| 649 BrowserDistribution::CHROME_BINARIES) | 333 BrowserDistribution::CHROME_BINARIES) |
| 650 ->GetStateKey(), | 334 ->GetStateKey(), |
| 651 status, string_resource_id, launch_cmd, install_list.get()); | 335 status, string_resource_id, launch_cmd, install_list.get()); |
| 652 #endif | 336 #endif |
| 653 } | 337 } |
| 654 install_list->Do(); | 338 install_list->Do(); |
| 655 } | 339 } |
| 656 | 340 |
| 657 bool InstallerState::RequiresActiveSetup() const { | 341 bool InstallerState::RequiresActiveSetup() const { |
| 658 return system_install() && FindProduct(BrowserDistribution::CHROME_BROWSER); | 342 return system_install(); |
| 659 } | 343 } |
| 660 | 344 |
| 661 } // namespace installer | 345 } // namespace installer |
| OLD | NEW |