| 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/setup_main.h" | 5 #include "chrome/installer/setup/setup_main.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <msi.h> | 8 #include <msi.h> |
| 9 #include <shellapi.h> | 9 #include <shellapi.h> |
| 10 #include <shlobj.h> | 10 #include <shlobj.h> |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 #include "chrome/installer/setup/archive_patch_helper.h" | 40 #include "chrome/installer/setup/archive_patch_helper.h" |
| 41 #include "chrome/installer/setup/install.h" | 41 #include "chrome/installer/setup/install.h" |
| 42 #include "chrome/installer/setup/install_worker.h" | 42 #include "chrome/installer/setup/install_worker.h" |
| 43 #include "chrome/installer/setup/setup_constants.h" | 43 #include "chrome/installer/setup/setup_constants.h" |
| 44 #include "chrome/installer/setup/setup_util.h" | 44 #include "chrome/installer/setup/setup_util.h" |
| 45 #include "chrome/installer/setup/uninstall.h" | 45 #include "chrome/installer/setup/uninstall.h" |
| 46 #include "chrome/installer/util/browser_distribution.h" | 46 #include "chrome/installer/util/browser_distribution.h" |
| 47 #include "chrome/installer/util/channel_info.h" | 47 #include "chrome/installer/util/channel_info.h" |
| 48 #include "chrome/installer/util/delete_after_reboot_helper.h" | 48 #include "chrome/installer/util/delete_after_reboot_helper.h" |
| 49 #include "chrome/installer/util/delete_tree_work_item.h" | 49 #include "chrome/installer/util/delete_tree_work_item.h" |
| 50 #include "chrome/installer/util/eula_util.h" | |
| 51 #include "chrome/installer/util/google_update_constants.h" | 50 #include "chrome/installer/util/google_update_constants.h" |
| 52 #include "chrome/installer/util/google_update_settings.h" | 51 #include "chrome/installer/util/google_update_settings.h" |
| 53 #include "chrome/installer/util/google_update_util.h" | 52 #include "chrome/installer/util/google_update_util.h" |
| 54 #include "chrome/installer/util/helper.h" | 53 #include "chrome/installer/util/helper.h" |
| 55 #include "chrome/installer/util/html_dialog.h" | 54 #include "chrome/installer/util/html_dialog.h" |
| 56 #include "chrome/installer/util/install_util.h" | 55 #include "chrome/installer/util/install_util.h" |
| 57 #include "chrome/installer/util/installation_state.h" | 56 #include "chrome/installer/util/installation_state.h" |
| 58 #include "chrome/installer/util/installation_validator.h" | 57 #include "chrome/installer/util/installation_validator.h" |
| 59 #include "chrome/installer/util/installer_state.h" | 58 #include "chrome/installer/util/installer_state.h" |
| 60 #include "chrome/installer/util/l10n_string_util.h" | 59 #include "chrome/installer/util/l10n_string_util.h" |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 InstallerState* installer_state, | 373 InstallerState* installer_state, |
| 375 installer::InstallStatus* status) { | 374 installer::InstallStatus* status) { |
| 376 const Products& products = installer_state->products(); | 375 const Products& products = installer_state->products(); |
| 377 DCHECK(products.size()); | 376 DCHECK(products.size()); |
| 378 | 377 |
| 379 const bool system_level = installer_state->system_install(); | 378 const bool system_level = installer_state->system_install(); |
| 380 | 379 |
| 381 if (installer_state->is_multi_install()) { | 380 if (installer_state->is_multi_install()) { |
| 382 const Product* chrome = | 381 const Product* chrome = |
| 383 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); | 382 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); |
| 384 const Product* app_host = | |
| 385 installer_state->FindProduct(BrowserDistribution::CHROME_APP_HOST); | |
| 386 const Product* binaries = | 383 const Product* binaries = |
| 387 installer_state->FindProduct(BrowserDistribution::CHROME_BINARIES); | 384 installer_state->FindProduct(BrowserDistribution::CHROME_BINARIES); |
| 388 const ProductState* chrome_state = | 385 const ProductState* chrome_state = |
| 389 original_state.GetProductState(system_level, | 386 original_state.GetProductState(system_level, |
| 390 BrowserDistribution::CHROME_BROWSER); | 387 BrowserDistribution::CHROME_BROWSER); |
| 391 | 388 |
| 392 if (binaries) { | 389 if (binaries) { |
| 393 if (products.size() == 1) { | 390 if (products.size() == 1) { |
| 394 // There are no products aside from the binaries, so there is no update | 391 // There are no products aside from the binaries, so there is no update |
| 395 // to be applied. This can happen after multi-install Chrome Frame is | 392 // to be applied. This can happen after multi-install Chrome Frame is |
| 396 // migrated to single-install. This is treated as an update failure | 393 // migrated to single-install. This is treated as an update failure |
| 397 // unless the binaries are not in-use, in which case they will be | 394 // unless the binaries are not in-use, in which case they will be |
| 398 // uninstalled and success will be reported (see handling in wWinMain). | 395 // uninstalled and success will be reported (see handling in wWinMain). |
| 399 VLOG(1) << "No products to be updated."; | 396 VLOG(1) << "No products to be updated."; |
| 400 *status = installer::UNUSED_BINARIES; | 397 *status = installer::UNUSED_BINARIES; |
| 401 installer_state->WriteInstallerResult(*status, 0, NULL); | 398 installer_state->WriteInstallerResult(*status, 0, NULL); |
| 402 return false; | 399 return false; |
| 403 } | 400 } |
| 404 } else { | 401 } else { |
| 405 // This will only be hit if --multi-install is given with no products, or | 402 // This will only be hit if --multi-install is given with no products. |
| 406 // if the app host is being installed and doesn't need the binaries at | |
| 407 // user-level. | |
| 408 // The former case might be due to a request by an orphaned Application | |
| 409 // Host to re-install the binaries. Thus we add them to the installation. | |
| 410 // The latter case is fine and we let it be. | |
| 411 // If this is not an app host install and the binaries are not already | |
| 412 // present, the installation will fail later due to a lack of products to | |
| 413 // install. | |
| 414 if (app_host && !chrome && !chrome_state) { | |
| 415 DCHECK(!system_level); | |
| 416 // App Host may use Chrome/Chrome binaries at system-level. | |
| 417 if (original_state.GetProductState( | |
| 418 true, // system | |
| 419 BrowserDistribution::CHROME_BROWSER) || | |
| 420 original_state.GetProductState( | |
| 421 true, // system | |
| 422 BrowserDistribution::CHROME_BINARIES)) { | |
| 423 VLOG(1) << "Installing/updating App Launcher without binaries."; | |
| 424 } else { | |
| 425 // Somehow the binaries were present when the quick-enable app host | |
| 426 // command was run, but now they appear to be missing. | |
| 427 // Force binaries to be installed/updated. | |
| 428 scoped_ptr<Product> binaries_to_add(new Product( | |
| 429 BrowserDistribution::GetSpecificDistribution( | |
| 430 BrowserDistribution::CHROME_BINARIES))); | |
| 431 binaries_to_add->SetOption(installer::kOptionMultiInstall, true); | |
| 432 binaries = installer_state->AddProduct(&binaries_to_add); | |
| 433 VLOG(1) << | |
| 434 "Adding binaries for pre-existing App Launcher installation."; | |
| 435 } | |
| 436 } | |
| 437 | |
| 438 return true; | 403 return true; |
| 439 } | 404 } |
| 440 | 405 |
| 441 if (!chrome && chrome_state) { | 406 if (!chrome && chrome_state) { |
| 442 // A product other than Chrome is being installed in multi-install mode, | 407 // A product other than Chrome is being installed in multi-install mode, |
| 443 // and Chrome is already present. Add Chrome to the set of products | 408 // and Chrome is already present. Add Chrome to the set of products |
| 444 // (making it multi-install in the process) so that it is updated, too. | 409 // (making it multi-install in the process) so that it is updated, too. |
| 445 scoped_ptr<Product> multi_chrome(new Product( | 410 scoped_ptr<Product> multi_chrome(new Product( |
| 446 BrowserDistribution::GetSpecificDistribution( | 411 BrowserDistribution::GetSpecificDistribution( |
| 447 BrowserDistribution::CHROME_BROWSER))); | 412 BrowserDistribution::CHROME_BROWSER))); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 465 installer_state->WriteInstallerResult(*status, | 430 installer_state->WriteInstallerResult(*status, |
| 466 IDS_INSTALL_MULTI_INSTALLATION_EXISTS_BASE, NULL); | 431 IDS_INSTALL_MULTI_INSTALLATION_EXISTS_BASE, NULL); |
| 467 return false; | 432 return false; |
| 468 } | 433 } |
| 469 } | 434 } |
| 470 } | 435 } |
| 471 | 436 |
| 472 return true; | 437 return true; |
| 473 } | 438 } |
| 474 | 439 |
| 475 // Checks app host pre-install conditions, specifically that this is a | |
| 476 // user-level multi-install. When the pre-install conditions are not | |
| 477 // satisfied, the result is written to the registry (via WriteInstallerResult), | |
| 478 // |status| is set appropriately, and false is returned. | |
| 479 bool CheckAppHostPreconditions(const InstallationState& original_state, | |
| 480 InstallerState* installer_state, | |
| 481 installer::InstallStatus* status) { | |
| 482 if (installer_state->FindProduct(BrowserDistribution::CHROME_APP_HOST)) { | |
| 483 if (!installer_state->is_multi_install()) { | |
| 484 LOG(DFATAL) << "App Launcher requires multi install"; | |
| 485 *status = installer::APP_HOST_REQUIRES_MULTI_INSTALL; | |
| 486 // No message string since there is nothing a user can do. | |
| 487 installer_state->WriteInstallerResult(*status, 0, NULL); | |
| 488 return false; | |
| 489 } | |
| 490 | |
| 491 if (installer_state->system_install()) { | |
| 492 LOG(DFATAL) << "App Launcher may only be installed at user-level."; | |
| 493 *status = installer::APP_HOST_REQUIRES_USER_LEVEL; | |
| 494 // No message string since there is nothing a user can do. | |
| 495 installer_state->WriteInstallerResult(*status, 0, NULL); | |
| 496 return false; | |
| 497 } | |
| 498 } | |
| 499 | |
| 500 return true; | |
| 501 } | |
| 502 | |
| 503 // Checks for compatibility between the current state of the system and the | 440 // Checks for compatibility between the current state of the system and the |
| 504 // desired operation. Also applies policy that mutates the desired operation; | 441 // desired operation. Also applies policy that mutates the desired operation; |
| 505 // specifically, the |installer_state| object. | 442 // specifically, the |installer_state| object. |
| 506 // Also blocks simultaneous user-level and system-level installs. In the case | 443 // Also blocks simultaneous user-level and system-level installs. In the case |
| 507 // of trying to install user-level Chrome when system-level exists, the | 444 // of trying to install user-level Chrome when system-level exists, the |
| 508 // existing system-level Chrome is launched. | 445 // existing system-level Chrome is launched. |
| 509 // When the pre-install conditions are not satisfied, the result is written to | 446 // When the pre-install conditions are not satisfied, the result is written to |
| 510 // the registry (via WriteInstallerResult), |status| is set appropriately, and | 447 // the registry (via WriteInstallerResult), |status| is set appropriately, and |
| 511 // false is returned. | 448 // false is returned. |
| 512 bool CheckPreInstallConditions(const InstallationState& original_state, | 449 bool CheckPreInstallConditions(const InstallationState& original_state, |
| 513 InstallerState* installer_state, | 450 InstallerState* installer_state, |
| 514 installer::InstallStatus* status) { | 451 installer::InstallStatus* status) { |
| 515 if (!CheckAppHostPreconditions(original_state, installer_state, status)) { | |
| 516 DCHECK_NE(*status, installer::UNKNOWN_STATUS); | |
| 517 return false; | |
| 518 } | |
| 519 | |
| 520 // See what products are already installed in multi mode. When we do multi | 452 // See what products are already installed in multi mode. When we do multi |
| 521 // installs, we must upgrade all installations since they share the binaries. | 453 // installs, we must upgrade all installations since they share the binaries. |
| 522 AddExistingMultiInstalls(original_state, installer_state); | 454 AddExistingMultiInstalls(original_state, installer_state); |
| 523 | 455 |
| 524 if (!CheckMultiInstallConditions(original_state, installer_state, status)) { | 456 if (!CheckMultiInstallConditions(original_state, installer_state, status)) { |
| 525 DCHECK_NE(*status, installer::UNKNOWN_STATUS); | 457 DCHECK_NE(*status, installer::UNKNOWN_STATUS); |
| 526 return false; | 458 return false; |
| 527 } | 459 } |
| 528 | 460 |
| 529 const Products& products = installer_state->products(); | 461 const Products& products = installer_state->products(); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 base::LaunchProcess(cmd, base::LaunchOptions()); | 522 base::LaunchProcess(cmd, base::LaunchOptions()); |
| 591 } | 523 } |
| 592 } else { | 524 } else { |
| 593 // It's no longer possible for |product| to be anything other than | 525 // It's no longer possible for |product| to be anything other than |
| 594 // Chrome. | 526 // Chrome. |
| 595 NOTREACHED(); | 527 NOTREACHED(); |
| 596 } | 528 } |
| 597 return false; | 529 return false; |
| 598 } | 530 } |
| 599 } | 531 } |
| 600 | |
| 601 } else { // System-level install. | |
| 602 // --ensure-google-update-present is supported for user-level only. | |
| 603 // The flag is generic, but its primary use case involves App Host. | |
| 604 if (installer_state->ensure_google_update_present()) { | |
| 605 LOG(DFATAL) << "--" << installer::switches::kEnsureGoogleUpdatePresent | |
| 606 << " is supported for user-level only."; | |
| 607 *status = installer::APP_HOST_REQUIRES_USER_LEVEL; | |
| 608 // No message string since there is nothing a user can do. | |
| 609 installer_state->WriteInstallerResult(*status, 0, NULL); | |
| 610 return false; | |
| 611 } | |
| 612 } | 532 } |
| 613 | 533 |
| 614 return true; | 534 return true; |
| 615 } | 535 } |
| 616 | 536 |
| 617 // Initializes |temp_path| to "Temp" within the target directory, and | 537 // Initializes |temp_path| to "Temp" within the target directory, and |
| 618 // |unpack_path| to a random directory beginning with "source" within | 538 // |unpack_path| to a random directory beginning with "source" within |
| 619 // |temp_path|. Returns false on error. | 539 // |temp_path|. Returns false on error. |
| 620 bool CreateTemporaryAndUnpackDirectories( | 540 bool CreateTemporaryAndUnpackDirectories( |
| 621 const InstallerState& installer_state, | 541 const InstallerState& installer_state, |
| (...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1134 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); | 1054 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); |
| 1135 installer::InstallStatus status = installer::INVALID_STATE_FOR_OPTION; | 1055 installer::InstallStatus status = installer::INVALID_STATE_FOR_OPTION; |
| 1136 if (chrome_install) { | 1056 if (chrome_install) { |
| 1137 installer::HandleOsUpgradeForBrowser(*installer_state, | 1057 installer::HandleOsUpgradeForBrowser(*installer_state, |
| 1138 *chrome_install); | 1058 *chrome_install); |
| 1139 status = installer::INSTALL_REPAIRED; | 1059 status = installer::INSTALL_REPAIRED; |
| 1140 } else { | 1060 } else { |
| 1141 LOG(DFATAL) << "Chrome product not found."; | 1061 LOG(DFATAL) << "Chrome product not found."; |
| 1142 } | 1062 } |
| 1143 *exit_code = InstallUtil::GetInstallReturnCode(status); | 1063 *exit_code = InstallUtil::GetInstallReturnCode(status); |
| 1144 } else if (cmd_line.HasSwitch(installer::switches::kQueryEULAAcceptance)) { | |
| 1145 *exit_code = installer::IsEULAAccepted(installer_state->system_install()); | |
| 1146 } else if (cmd_line.HasSwitch(installer::switches::kInactiveUserToast)) { | 1064 } else if (cmd_line.HasSwitch(installer::switches::kInactiveUserToast)) { |
| 1147 // Launch the inactive user toast experiment. | 1065 // Launch the inactive user toast experiment. |
| 1148 int flavor = -1; | 1066 int flavor = -1; |
| 1149 base::StringToInt(cmd_line.GetSwitchValueNative( | 1067 base::StringToInt(cmd_line.GetSwitchValueNative( |
| 1150 installer::switches::kInactiveUserToast), &flavor); | 1068 installer::switches::kInactiveUserToast), &flavor); |
| 1151 std::string experiment_group = | 1069 std::string experiment_group = |
| 1152 cmd_line.GetSwitchValueASCII(installer::switches::kExperimentGroup); | 1070 cmd_line.GetSwitchValueASCII(installer::switches::kExperimentGroup); |
| 1153 DCHECK_NE(-1, flavor); | 1071 DCHECK_NE(-1, flavor); |
| 1154 if (flavor == -1) { | 1072 if (flavor == -1) { |
| 1155 *exit_code = installer::UNKNOWN_STATUS; | 1073 *exit_code = installer::UNKNOWN_STATUS; |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1513 if (product_state != NULL && | 1431 if (product_state != NULL && |
| 1514 (product_state->version().CompareTo(*installer_version) > 0)) { | 1432 (product_state->version().CompareTo(*installer_version) > 0)) { |
| 1515 LOG(ERROR) << "Higher version of " | 1433 LOG(ERROR) << "Higher version of " |
| 1516 << product.distribution()->GetDisplayName() | 1434 << product.distribution()->GetDisplayName() |
| 1517 << " is already installed."; | 1435 << " is already installed."; |
| 1518 higher_products |= (1 << product.distribution()->GetType()); | 1436 higher_products |= (1 << product.distribution()->GetType()); |
| 1519 } | 1437 } |
| 1520 } | 1438 } |
| 1521 | 1439 |
| 1522 if (higher_products != 0) { | 1440 if (higher_products != 0) { |
| 1523 COMPILE_ASSERT(BrowserDistribution::NUM_TYPES == 4, | 1441 COMPILE_ASSERT(BrowserDistribution::NUM_TYPES == 3, |
| 1524 add_support_for_new_products_here_); | 1442 add_support_for_new_products_here_); |
| 1525 const uint32 kBrowserBit = 1 << BrowserDistribution::CHROME_BROWSER; | 1443 int message_id = IDS_INSTALL_HIGHER_VERSION_BASE; |
| 1526 int message_id = 0; | |
| 1527 | |
| 1528 proceed_with_installation = false; | 1444 proceed_with_installation = false; |
| 1529 install_status = HIGHER_VERSION_EXISTS; | 1445 install_status = HIGHER_VERSION_EXISTS; |
| 1530 switch (higher_products) { | |
| 1531 case kBrowserBit: | |
| 1532 message_id = IDS_INSTALL_HIGHER_VERSION_BASE; | |
| 1533 break; | |
| 1534 default: | |
| 1535 message_id = IDS_INSTALL_HIGHER_VERSION_APP_LAUNCHER_BASE; | |
| 1536 break; | |
| 1537 } | |
| 1538 | |
| 1539 installer_state.WriteInstallerResult(install_status, message_id, NULL); | 1446 installer_state.WriteInstallerResult(install_status, message_id, NULL); |
| 1540 } | 1447 } |
| 1541 | 1448 |
| 1542 proceed_with_installation = | 1449 proceed_with_installation = |
| 1543 proceed_with_installation && | 1450 proceed_with_installation && |
| 1544 CheckGroupPolicySettings(original_state, installer_state, | 1451 CheckGroupPolicySettings(original_state, installer_state, |
| 1545 *installer_version, &install_status); | 1452 *installer_version, &install_status); |
| 1546 | 1453 |
| 1547 if (proceed_with_installation) { | 1454 if (proceed_with_installation) { |
| 1548 // If Google Update is absent at user-level, install it using the | |
| 1549 // Google Update installer from an existing system-level installation. | |
| 1550 // This is for quick-enable App Host install from a system-level | |
| 1551 // Chrome Binaries installation. | |
| 1552 if (!system_install && installer_state.ensure_google_update_present()) { | |
| 1553 if (!google_update::EnsureUserLevelGoogleUpdatePresent()) { | |
| 1554 LOG(ERROR) << "Failed to install Google Update"; | |
| 1555 proceed_with_installation = false; | |
| 1556 install_status = INSTALL_OF_GOOGLE_UPDATE_FAILED; | |
| 1557 installer_state.WriteInstallerResult(install_status, 0, NULL); | |
| 1558 } | |
| 1559 } | |
| 1560 | |
| 1561 } | |
| 1562 | |
| 1563 if (proceed_with_installation) { | |
| 1564 base::FilePath prefs_source_path(cmd_line.GetSwitchValueNative( | 1455 base::FilePath prefs_source_path(cmd_line.GetSwitchValueNative( |
| 1565 switches::kInstallerData)); | 1456 switches::kInstallerData)); |
| 1566 install_status = InstallOrUpdateProduct( | 1457 install_status = InstallOrUpdateProduct( |
| 1567 original_state, installer_state, setup_exe, uncompressed_archive, | 1458 original_state, installer_state, setup_exe, uncompressed_archive, |
| 1568 temp_path.path(), src_path, prefs_source_path, prefs, | 1459 temp_path.path(), src_path, prefs_source_path, prefs, |
| 1569 *installer_version); | 1460 *installer_version); |
| 1570 | 1461 |
| 1571 int install_msg_base = IDS_INSTALL_FAILED_BASE; | 1462 int install_msg_base = IDS_INSTALL_FAILED_BASE; |
| 1572 base::FilePath chrome_exe; | 1463 base::FilePath chrome_exe; |
| 1573 base::string16 quoted_chrome_exe; | 1464 base::string16 quoted_chrome_exe; |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1819 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT | 1710 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT |
| 1820 // to pass through, since this is only returned on uninstall which is | 1711 // to pass through, since this is only returned on uninstall which is |
| 1821 // never invoked directly by Google Update. | 1712 // never invoked directly by Google Update. |
| 1822 return_code = InstallUtil::GetInstallReturnCode(install_status); | 1713 return_code = InstallUtil::GetInstallReturnCode(install_status); |
| 1823 } | 1714 } |
| 1824 | 1715 |
| 1825 VLOG(1) << "Installation complete, returning: " << return_code; | 1716 VLOG(1) << "Installation complete, returning: " << return_code; |
| 1826 | 1717 |
| 1827 return return_code; | 1718 return return_code; |
| 1828 } | 1719 } |
| OLD | NEW |