OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <windows.h> | 5 #include <windows.h> |
6 #include <msi.h> | 6 #include <msi.h> |
7 #include <shellapi.h> | 7 #include <shellapi.h> |
8 #include <shlobj.h> | 8 #include <shlobj.h> |
9 | 9 |
10 #include <string> | 10 #include <string> |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 install_list->Rollback(); | 245 install_list->Rollback(); |
246 ret = installer::RENAME_FAILED; | 246 ret = installer::RENAME_FAILED; |
247 } | 247 } |
248 // temp_path's dtor will take care of deleting or scheduling itself for | 248 // temp_path's dtor will take care of deleting or scheduling itself for |
249 // deletion at reboot when this scope closes. | 249 // deletion at reboot when this scope closes. |
250 VLOG(1) << "Deleting temporary directory " << temp_path.path().value(); | 250 VLOG(1) << "Deleting temporary directory " << temp_path.path().value(); |
251 | 251 |
252 return ret; | 252 return ret; |
253 } | 253 } |
254 | 254 |
| 255 // For each product that is being updated (i.e., already installed at an earlier |
| 256 // version), see if that product has an update policy override that differs from |
| 257 // that for the binaries. If any are found, fail with an error indicating that |
| 258 // the Group Policy settings are in an inconsistent state. Do not do this test |
| 259 // for same-version installs, since it would be unkind to block attempts to |
| 260 // repair a corrupt installation. This function returns false when installation |
| 261 // should be halted, in which case |status| contains the relevant exit code and |
| 262 // the proper installer result has been written to the registry. |
| 263 bool CheckGroupPolicySettings(const InstallationState& original_state, |
| 264 const InstallerState& installer_state, |
| 265 const Version& new_version, |
| 266 installer::InstallStatus* status) { |
| 267 #if !defined(GOOGLE_CHROME_BUILD) |
| 268 // Chromium builds are not updated via Google Update, so there are no |
| 269 // Group Policy settings to consult. |
| 270 return true; |
| 271 #else |
| 272 DCHECK(status); |
| 273 |
| 274 // Single installs are always in good shape. |
| 275 if (!installer_state.is_multi_install()) |
| 276 return true; |
| 277 |
| 278 bool settings_are_valid = true; |
| 279 const bool is_system_install = installer_state.system_install(); |
| 280 BrowserDistribution* const binaries_dist = |
| 281 installer_state.multi_package_binaries_distribution(); |
| 282 |
| 283 // Get the update policy for the binaries. |
| 284 const GoogleUpdateSettings::UpdatePolicy binaries_policy = |
| 285 GoogleUpdateSettings::GetAppUpdatePolicy(binaries_dist->GetAppGuid(), |
| 286 NULL); |
| 287 |
| 288 // Check for differing update policies for all of the products being updated. |
| 289 const Products& products = installer_state.products(); |
| 290 Products::const_iterator scan = products.begin(); |
| 291 for (Products::const_iterator end = products.end(); scan != end; ++scan) { |
| 292 BrowserDistribution* dist = (*scan)->distribution(); |
| 293 const ProductState* product_state = |
| 294 original_state.GetProductState(is_system_install, dist->GetType()); |
| 295 // Is an earlier version of this product already installed? |
| 296 if (product_state != NULL && |
| 297 product_state->version().CompareTo(new_version) < 0) { |
| 298 bool is_overridden = false; |
| 299 GoogleUpdateSettings::UpdatePolicy app_policy = |
| 300 GoogleUpdateSettings::GetAppUpdatePolicy(dist->GetAppGuid(), |
| 301 &is_overridden); |
| 302 if (is_overridden && app_policy != binaries_policy) { |
| 303 LOG(ERROR) << "Found legacy Group Policy setting for " |
| 304 << dist->GetAppShortCutName() << " (value: " << app_policy |
| 305 << ") that does not match the setting for " |
| 306 << binaries_dist->GetAppShortCutName() |
| 307 << " (value: " << binaries_policy << ")."; |
| 308 settings_are_valid = false; |
| 309 } |
| 310 } |
| 311 } |
| 312 |
| 313 if (!settings_are_valid) { |
| 314 // TODO(grt): add " See http://goo.gl/+++ for details." to the end of this |
| 315 // log message and to the IDS_INSTALL_INCONSISTENT_UPDATE_POLICY string once |
| 316 // we have a help center article that explains why this error is being |
| 317 // reported and how to resolve it. |
| 318 LOG(ERROR) << "Cannot apply update on account of inconsistent " |
| 319 "Google Update Group Policy settings. Use the Group Policy " |
| 320 "Editor to set the update policy override for the " |
| 321 << binaries_dist->GetAppShortCutName() |
| 322 << " application and try again."; |
| 323 *status = installer::INCONSISTENT_UPDATE_POLICY; |
| 324 installer_state.WriteInstallerResult( |
| 325 *status, IDS_INSTALL_INCONSISTENT_UPDATE_POLICY_BASE, NULL); |
| 326 } |
| 327 |
| 328 return settings_are_valid; |
| 329 #endif // defined(GOOGLE_CHROME_BUILD) |
| 330 } |
| 331 |
255 // The supported multi-install modes are: | 332 // The supported multi-install modes are: |
256 // --multi-install --chrome --chrome-frame --ready-mode | 333 // --multi-install --chrome --chrome-frame --ready-mode |
257 // - If a non-multi Chrome Frame installation is present, Chrome Frame is | 334 // - If a non-multi Chrome Frame installation is present, Chrome Frame is |
258 // removed from |installer_state|'s list of products (thereby preserving | 335 // removed from |installer_state|'s list of products (thereby preserving |
259 // the existing SxS install). | 336 // the existing SxS install). |
260 // - If a multi Chrome Frame installation is present, its options are | 337 // - If a multi Chrome Frame installation is present, its options are |
261 // preserved (i.e., the --ready-mode command-line option is ignored). | 338 // preserved (i.e., the --ready-mode command-line option is ignored). |
262 // --multi-install --chrome-frame | 339 // --multi-install --chrome-frame |
263 // - If a non-multi Chrome Frame installation is present, fail. | 340 // - If a non-multi Chrome Frame installation is present, fail. |
264 // - If --ready-mode and no Chrome installation is present, fail. | 341 // - If --ready-mode and no Chrome installation is present, fail. |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 install_status = installer::INVALID_ARCHIVE; | 596 install_status = installer::INVALID_ARCHIVE; |
520 installer_state.WriteInstallerResult(install_status, | 597 installer_state.WriteInstallerResult(install_status, |
521 IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); | 598 IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); |
522 } else { | 599 } else { |
523 // TODO(tommi): Move towards having only a single version that is common | 600 // TODO(tommi): Move towards having only a single version that is common |
524 // to all products. Only the package should have a version since it | 601 // to all products. Only the package should have a version since it |
525 // represents all the binaries. When a single product is upgraded, all | 602 // represents all the binaries. When a single product is upgraded, all |
526 // currently installed product for the shared binary installation, should | 603 // currently installed product for the shared binary installation, should |
527 // (or rather must) be upgraded. | 604 // (or rather must) be upgraded. |
528 VLOG(1) << "version to install: " << installer_version->GetString(); | 605 VLOG(1) << "version to install: " << installer_version->GetString(); |
529 bool higher_version_installed = false; | 606 bool proceed_with_installation = true; |
530 for (size_t i = 0; i < installer_state.products().size(); ++i) { | 607 for (size_t i = 0; i < installer_state.products().size(); ++i) { |
531 const Product* product = installer_state.products()[i]; | 608 const Product* product = installer_state.products()[i]; |
532 const ProductState* product_state = | 609 const ProductState* product_state = |
533 original_state.GetProductState(system_install, | 610 original_state.GetProductState(system_install, |
534 product->distribution()->GetType()); | 611 product->distribution()->GetType()); |
535 if (product_state != NULL && | 612 if (product_state != NULL && |
536 (product_state->version().CompareTo(*installer_version) > 0)) { | 613 (product_state->version().CompareTo(*installer_version) > 0)) { |
537 LOG(ERROR) << "Higher version is already installed."; | 614 LOG(ERROR) << "Higher version is already installed."; |
538 higher_version_installed = true; | 615 proceed_with_installation = false; |
539 install_status = installer::HIGHER_VERSION_EXISTS; | 616 install_status = installer::HIGHER_VERSION_EXISTS; |
540 | 617 |
541 if (product->is_chrome()) { | 618 if (product->is_chrome()) { |
542 // TODO(robertshield): We should take the installer result text | 619 // TODO(robertshield): We should take the installer result text |
543 // strings from the Product. | 620 // strings from the Product. |
544 installer_state.WriteInstallerResult(install_status, | 621 installer_state.WriteInstallerResult(install_status, |
545 IDS_INSTALL_HIGHER_VERSION_BASE, NULL); | 622 IDS_INSTALL_HIGHER_VERSION_BASE, NULL); |
546 } else { | 623 } else { |
547 installer_state.WriteInstallerResult(install_status, | 624 installer_state.WriteInstallerResult(install_status, |
548 IDS_INSTALL_HIGHER_VERSION_CF_BASE, NULL); | 625 IDS_INSTALL_HIGHER_VERSION_CF_BASE, NULL); |
549 } | 626 } |
550 } | 627 } |
551 } | 628 } |
552 | 629 |
553 if (!higher_version_installed) { | 630 proceed_with_installation = |
| 631 proceed_with_installation && |
| 632 CheckGroupPolicySettings(original_state, installer_state, |
| 633 *installer_version, &install_status); |
| 634 |
| 635 if (proceed_with_installation) { |
554 // We want to keep uncompressed archive (chrome.7z) that we get after | 636 // We want to keep uncompressed archive (chrome.7z) that we get after |
555 // uncompressing and binary patching. Get the location for this file. | 637 // uncompressing and binary patching. Get the location for this file. |
556 FilePath archive_to_copy( | 638 FilePath archive_to_copy( |
557 temp_path.path().Append(installer::kChromeArchive)); | 639 temp_path.path().Append(installer::kChromeArchive)); |
558 FilePath prefs_source_path(cmd_line.GetSwitchValueNative( | 640 FilePath prefs_source_path(cmd_line.GetSwitchValueNative( |
559 installer::switches::kInstallerData)); | 641 installer::switches::kInstallerData)); |
560 install_status = installer::InstallOrUpdateProduct(original_state, | 642 install_status = installer::InstallOrUpdateProduct(original_state, |
561 installer_state, cmd_line.GetProgram(), archive_to_copy, | 643 installer_state, cmd_line.GetProgram(), archive_to_copy, |
562 temp_path.path(), prefs_source_path, prefs, *installer_version); | 644 temp_path.path(), prefs_source_path, prefs, *installer_version); |
563 | 645 |
(...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1222 if (!(installer_state.is_msi() && is_uninstall)) | 1304 if (!(installer_state.is_msi() && is_uninstall)) |
1223 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT | 1305 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT |
1224 // to pass through, since this is only returned on uninstall which is | 1306 // to pass through, since this is only returned on uninstall which is |
1225 // never invoked directly by Google Update. | 1307 // never invoked directly by Google Update. |
1226 return_code = InstallUtil::GetInstallReturnCode(install_status); | 1308 return_code = InstallUtil::GetInstallReturnCode(install_status); |
1227 | 1309 |
1228 VLOG(1) << "Installation complete, returning: " << return_code; | 1310 VLOG(1) << "Installation complete, returning: " << return_code; |
1229 | 1311 |
1230 return return_code; | 1312 return return_code; |
1231 } | 1313 } |
OLD | NEW |