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/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 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 694 if (!file_util::CreateTemporaryDirInDir(temp_path->path(), | 694 if (!file_util::CreateTemporaryDirInDir(temp_path->path(), |
| 695 installer::kInstallSourceDir, | 695 installer::kInstallSourceDir, |
| 696 unpack_path)) { | 696 unpack_path)) { |
| 697 PLOG(ERROR) << "Could not create temporary path for unpacked archive."; | 697 PLOG(ERROR) << "Could not create temporary path for unpacked archive."; |
| 698 return false; | 698 return false; |
| 699 } | 699 } |
| 700 | 700 |
| 701 return true; | 701 return true; |
| 702 } | 702 } |
| 703 | 703 |
| 704 installer::InstallStatus InstallProducts( | |
|
grt (UTC plus 2)
2013/11/29 04:23:03
code motion only except for what is now line 902.
| |
| 705 const InstallationState& original_state, | |
| 706 const CommandLine& cmd_line, | |
| 707 const MasterPreferences& prefs, | |
| 708 InstallerState* installer_state, | |
| 709 base::FilePath* installer_directory) { | |
| 710 DCHECK(installer_state); | |
| 711 const bool system_install = installer_state->system_install(); | |
| 712 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; | |
| 713 installer::ArchiveType archive_type = installer::UNKNOWN_ARCHIVE_TYPE; | |
| 714 bool delegated_to_existing = false; | |
| 715 installer_state->UpdateStage(installer::PRECONDITIONS); | |
| 716 // The stage provides more fine-grained information than -multifail, so remove | |
| 717 // the -multifail suffix from the Google Update "ap" value. | |
| 718 BrowserDistribution::GetSpecificDistribution(installer_state->state_type())-> | |
| 719 UpdateInstallStatus(system_install, archive_type, install_status); | |
| 720 if (CheckPreInstallConditions(original_state, installer_state, | |
| 721 &install_status)) { | |
| 722 VLOG(1) << "Installing to " << installer_state->target_path().value(); | |
| 723 install_status = InstallProductsHelper( | |
| 724 original_state, cmd_line, prefs, *installer_state, | |
| 725 installer_directory, &archive_type, &delegated_to_existing); | |
| 726 } else { | |
| 727 // CheckPreInstallConditions must set the status on failure. | |
| 728 DCHECK_NE(install_status, installer::UNKNOWN_STATUS); | |
| 729 } | |
| 730 | |
| 731 // Delete the master preferences file if present. Note that we do not care | |
| 732 // about rollback here and we schedule for deletion on reboot if the delete | |
| 733 // fails. As such, we do not use DeleteTreeWorkItem. | |
| 734 if (cmd_line.HasSwitch(installer::switches::kInstallerData)) { | |
| 735 base::FilePath prefs_path(cmd_line.GetSwitchValuePath( | |
| 736 installer::switches::kInstallerData)); | |
| 737 if (!base::DeleteFile(prefs_path, false)) { | |
| 738 LOG(ERROR) << "Failed deleting master preferences file " | |
| 739 << prefs_path.value() | |
| 740 << ", scheduling for deletion after reboot."; | |
| 741 ScheduleFileSystemEntityForDeletion(prefs_path); | |
| 742 } | |
| 743 } | |
| 744 | |
| 745 // Early exit if this setup.exe delegated to another, since that one would | |
| 746 // have taken care of UpdateInstallStatus and UpdateStage. | |
| 747 if (delegated_to_existing) | |
| 748 return install_status; | |
| 749 | |
| 750 const Products& products = installer_state->products(); | |
| 751 for (Products::const_iterator it = products.begin(); it < products.end(); | |
| 752 ++it) { | |
| 753 (*it)->distribution()->UpdateInstallStatus( | |
| 754 system_install, archive_type, install_status); | |
| 755 } | |
| 756 | |
| 757 installer_state->UpdateStage(installer::NO_STAGE); | |
| 758 return install_status; | |
| 759 } | |
| 760 | |
| 761 installer::InstallStatus UninstallProduct( | 704 installer::InstallStatus UninstallProduct( |
| 762 const InstallationState& original_state, | 705 const InstallationState& original_state, |
| 763 const InstallerState& installer_state, | 706 const InstallerState& installer_state, |
| 764 const CommandLine& cmd_line, | 707 const CommandLine& cmd_line, |
| 765 bool remove_all, | 708 bool remove_all, |
| 766 bool force_uninstall, | 709 bool force_uninstall, |
| 767 const Product& product) { | 710 const Product& product) { |
| 768 const ProductState* product_state = | 711 const ProductState* product_state = |
| 769 original_state.GetProductState(installer_state.system_install(), | 712 original_state.GetProductState(installer_state.system_install(), |
| 770 product.distribution()->GetType()); | 713 product.distribution()->GetType()); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 861 base::LaunchProcess(system_level_cmd, base::LaunchOptions(), NULL); | 804 base::LaunchProcess(system_level_cmd, base::LaunchOptions(), NULL); |
| 862 | 805 |
| 863 // Tell Google Update that an uninstall has taken place. | 806 // Tell Google Update that an uninstall has taken place. |
| 864 // Ignore the return value: success or failure of Google Update | 807 // Ignore the return value: success or failure of Google Update |
| 865 // has no bearing on the success or failure of Chrome's uninstallation. | 808 // has no bearing on the success or failure of Chrome's uninstallation. |
| 866 google_update::UninstallGoogleUpdate(installer_state.system_install()); | 809 google_update::UninstallGoogleUpdate(installer_state.system_install()); |
| 867 | 810 |
| 868 return install_status; | 811 return install_status; |
| 869 } | 812 } |
| 870 | 813 |
| 814 // Uninstall the binaries if they are the only product present and they're not | |
| 815 // in-use. | |
| 816 void UninstallBinariesIfUnused( | |
|
grt (UTC plus 2)
2013/11/29 04:23:03
this is more or less what used to be on line 1788,
| |
| 817 const InstallationState& original_state, | |
| 818 const InstallerState& installer_state, | |
| 819 installer::InstallStatus* install_status) { | |
| 820 // Early exit if the binaries are still in use. | |
| 821 if (*install_status != installer::UNUSED_BINARIES || | |
| 822 installer_state.AreBinariesInUse(original_state)) { | |
| 823 return; | |
| 824 } | |
| 825 | |
| 826 LOG(INFO) << "Uninstalling unused binaries"; | |
| 827 installer_state.UpdateStage(installer::UNINSTALLING_BINARIES); | |
| 828 | |
| 829 // Simulate the uninstall as coming from the installed version. | |
| 830 const ProductState* binaries_state = | |
| 831 original_state.GetProductState(installer_state.system_install(), | |
| 832 BrowserDistribution::CHROME_BINARIES); | |
| 833 const CommandLine& uninstall_cmd(binaries_state->uninstall_command()); | |
| 834 MasterPreferences uninstall_prefs(uninstall_cmd); | |
| 835 InstallerState uninstall_state; | |
| 836 uninstall_state.Initialize(uninstall_cmd, uninstall_prefs, original_state); | |
| 837 | |
| 838 *install_status = | |
| 839 UninstallProducts(original_state, uninstall_state, uninstall_cmd); | |
| 840 | |
| 841 // Report that the binaries were uninstalled if they were. This translates | |
| 842 // into a successful install return code. | |
| 843 if (IsUninstallSuccess(*install_status)) { | |
| 844 *install_status = installer::UNUSED_BINARIES_UNINSTALLED; | |
| 845 installer_state.WriteInstallerResult(*install_status, 0, NULL); | |
| 846 } | |
| 847 } | |
| 848 | |
| 849 installer::InstallStatus InstallProducts( | |
| 850 const InstallationState& original_state, | |
| 851 const CommandLine& cmd_line, | |
| 852 const MasterPreferences& prefs, | |
| 853 InstallerState* installer_state, | |
| 854 base::FilePath* installer_directory) { | |
| 855 DCHECK(installer_state); | |
| 856 const bool system_install = installer_state->system_install(); | |
| 857 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; | |
| 858 installer::ArchiveType archive_type = installer::UNKNOWN_ARCHIVE_TYPE; | |
| 859 bool delegated_to_existing = false; | |
| 860 installer_state->UpdateStage(installer::PRECONDITIONS); | |
| 861 // The stage provides more fine-grained information than -multifail, so remove | |
| 862 // the -multifail suffix from the Google Update "ap" value. | |
| 863 BrowserDistribution::GetSpecificDistribution(installer_state->state_type())-> | |
| 864 UpdateInstallStatus(system_install, archive_type, install_status); | |
| 865 if (CheckPreInstallConditions(original_state, installer_state, | |
| 866 &install_status)) { | |
| 867 VLOG(1) << "Installing to " << installer_state->target_path().value(); | |
| 868 install_status = InstallProductsHelper( | |
| 869 original_state, cmd_line, prefs, *installer_state, | |
| 870 installer_directory, &archive_type, &delegated_to_existing); | |
| 871 } else { | |
| 872 // CheckPreInstallConditions must set the status on failure. | |
| 873 DCHECK_NE(install_status, installer::UNKNOWN_STATUS); | |
| 874 } | |
| 875 | |
| 876 // Delete the master preferences file if present. Note that we do not care | |
| 877 // about rollback here and we schedule for deletion on reboot if the delete | |
| 878 // fails. As such, we do not use DeleteTreeWorkItem. | |
| 879 if (cmd_line.HasSwitch(installer::switches::kInstallerData)) { | |
| 880 base::FilePath prefs_path(cmd_line.GetSwitchValuePath( | |
| 881 installer::switches::kInstallerData)); | |
| 882 if (!base::DeleteFile(prefs_path, false)) { | |
| 883 LOG(ERROR) << "Failed deleting master preferences file " | |
| 884 << prefs_path.value() | |
| 885 << ", scheduling for deletion after reboot."; | |
| 886 ScheduleFileSystemEntityForDeletion(prefs_path); | |
| 887 } | |
| 888 } | |
| 889 | |
| 890 // Early exit if this setup.exe delegated to another, since that one would | |
| 891 // have taken care of UpdateInstallStatus and UpdateStage. | |
| 892 if (delegated_to_existing) | |
| 893 return install_status; | |
| 894 | |
| 895 const Products& products = installer_state->products(); | |
| 896 for (Products::const_iterator it = products.begin(); it < products.end(); | |
| 897 ++it) { | |
| 898 (*it)->distribution()->UpdateInstallStatus( | |
| 899 system_install, archive_type, install_status); | |
| 900 } | |
| 901 | |
| 902 UninstallBinariesIfUnused(original_state, *installer_state, &install_status); | |
|
grt (UTC plus 2)
2013/11/29 04:23:03
this line is the only change between the old Insta
| |
| 903 | |
| 904 installer_state->UpdateStage(installer::NO_STAGE); | |
| 905 return install_status; | |
| 906 } | |
| 907 | |
| 871 installer::InstallStatus ShowEULADialog(const string16& inner_frame) { | 908 installer::InstallStatus ShowEULADialog(const string16& inner_frame) { |
| 872 VLOG(1) << "About to show EULA"; | 909 VLOG(1) << "About to show EULA"; |
| 873 string16 eula_path = installer::GetLocalizedEulaResource(); | 910 string16 eula_path = installer::GetLocalizedEulaResource(); |
| 874 if (eula_path.empty()) { | 911 if (eula_path.empty()) { |
| 875 LOG(ERROR) << "No EULA path available"; | 912 LOG(ERROR) << "No EULA path available"; |
| 876 return installer::EULA_REJECTED; | 913 return installer::EULA_REJECTED; |
| 877 } | 914 } |
| 878 // Newer versions of the caller pass an inner frame parameter that must | 915 // Newer versions of the caller pass an inner frame parameter that must |
| 879 // be given to the html page being launched. | 916 // be given to the html page being launched. |
| 880 installer::EulaHTMLDialog dlg(eula_path, inner_frame); | 917 installer::EulaHTMLDialog dlg(eula_path, inner_frame); |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1360 pipe_name += user_sid; | 1397 pipe_name += user_sid; |
| 1361 | 1398 |
| 1362 google_breakpad::ExceptionHandler* breakpad = | 1399 google_breakpad::ExceptionHandler* breakpad = |
| 1363 new google_breakpad::ExceptionHandler( | 1400 new google_breakpad::ExceptionHandler( |
| 1364 temp_directory.value(), NULL, NULL, NULL, | 1401 temp_directory.value(), NULL, NULL, NULL, |
| 1365 google_breakpad::ExceptionHandler::HANDLER_ALL, kLargerDumpType, | 1402 google_breakpad::ExceptionHandler::HANDLER_ALL, kLargerDumpType, |
| 1366 pipe_name.c_str(), GetCustomInfo(exe_path)); | 1403 pipe_name.c_str(), GetCustomInfo(exe_path)); |
| 1367 return breakpad; | 1404 return breakpad; |
| 1368 } | 1405 } |
| 1369 | 1406 |
| 1407 // Uninstalls multi-install Chrome Frame if the current operation is a | |
| 1408 // multi-install install or update. The operation is performed directly rather | |
| 1409 // than delegated to the existing install since there is no facility in older | |
| 1410 // versions of setup.exe to uninstall GCF without touching the binaries. The | |
| 1411 // binaries will be uninstalled during later processing if they are not in-use | |
| 1412 // (see UninstallBinariesIfUnused). |original_state| and |installer_state| are | |
| 1413 // updated to reflect the state of the world following the operation. | |
| 1414 void UninstallMultiChromeFrameIfPresent(const CommandLine& cmd_line, | |
| 1415 const MasterPreferences& prefs, | |
| 1416 InstallationState* original_state, | |
| 1417 InstallerState* installer_state) { | |
| 1418 // Early exit if not installing or updating multi-install product(s). | |
| 1419 if (installer_state->operation() != InstallerState::MULTI_INSTALL && | |
| 1420 installer_state->operation() != InstallerState::MULTI_UPDATE) { | |
| 1421 return; | |
| 1422 } | |
| 1423 | |
| 1424 // Early exit if Chrome Frame is not present as multi-install. | |
| 1425 const ProductState* chrome_frame_state = | |
| 1426 original_state->GetProductState(installer_state->system_install(), | |
| 1427 BrowserDistribution::CHROME_FRAME); | |
| 1428 if (!chrome_frame_state || !chrome_frame_state->is_multi_install()) | |
| 1429 return; | |
| 1430 | |
| 1431 LOG(INFO) << "Uninstalling multi-install Chrome Frame."; | |
| 1432 installer_state->UpdateStage(installer::UNINSTALLING_CHROME_FRAME); | |
| 1433 | |
| 1434 // Uninstall Chrome Frame without touching the multi-install binaries. | |
| 1435 // Simulate the uninstall as coming from the installed version. | |
| 1436 const CommandLine& uninstall_cmd(chrome_frame_state->uninstall_command()); | |
| 1437 MasterPreferences uninstall_prefs(uninstall_cmd); | |
| 1438 InstallerState uninstall_state; | |
| 1439 uninstall_state.Initialize(uninstall_cmd, uninstall_prefs, *original_state); | |
| 1440 const Product* chrome_frame = uninstall_state.FindProduct( | |
| 1441 BrowserDistribution::CHROME_FRAME); | |
| 1442 if (chrome_frame) { | |
| 1443 // No shared state should be left behind. | |
| 1444 const bool remove_all = true; | |
| 1445 // Don't accept no for an answer. | |
| 1446 const bool force_uninstall = true; | |
| 1447 installer::InstallStatus uninstall_status = | |
| 1448 installer::UninstallProduct(*original_state, uninstall_state, | |
| 1449 uninstall_cmd.GetProgram(), *chrome_frame, | |
| 1450 remove_all, force_uninstall, cmd_line); | |
| 1451 | |
| 1452 VLOG(1) << "Uninstallation of Chrome Frame returned status " | |
| 1453 << uninstall_status; | |
| 1454 } else { | |
| 1455 LOG(ERROR) << "Chrome Frame not found for uninstall."; | |
| 1456 } | |
| 1457 | |
| 1458 // Refresh state for the continuation of the original install/update. | |
| 1459 original_state->Initialize(); | |
| 1460 installer_state->Initialize(cmd_line, prefs, *original_state); | |
| 1461 } | |
| 1462 | |
| 1370 } // namespace | 1463 } // namespace |
| 1371 | 1464 |
| 1372 namespace installer { | 1465 namespace installer { |
| 1373 | 1466 |
| 1374 InstallStatus InstallProductsHelper( | 1467 InstallStatus InstallProductsHelper( |
| 1375 const InstallationState& original_state, | 1468 const InstallationState& original_state, |
| 1376 const CommandLine& cmd_line, | 1469 const CommandLine& cmd_line, |
| 1377 const MasterPreferences& prefs, | 1470 const MasterPreferences& prefs, |
| 1378 const InstallerState& installer_state, | 1471 const InstallerState& installer_state, |
| 1379 base::FilePath* installer_directory, | 1472 base::FilePath* installer_directory, |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1768 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); | 1861 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); |
| 1769 return exit_code; | 1862 return exit_code; |
| 1770 } else { | 1863 } else { |
| 1771 LOG(ERROR) << "Non admin user can not install system level Chrome."; | 1864 LOG(ERROR) << "Non admin user can not install system level Chrome."; |
| 1772 installer_state.WriteInstallerResult(installer::INSUFFICIENT_RIGHTS, | 1865 installer_state.WriteInstallerResult(installer::INSUFFICIENT_RIGHTS, |
| 1773 IDS_INSTALL_INSUFFICIENT_RIGHTS_BASE, NULL); | 1866 IDS_INSTALL_INSUFFICIENT_RIGHTS_BASE, NULL); |
| 1774 return installer::INSUFFICIENT_RIGHTS; | 1867 return installer::INSUFFICIENT_RIGHTS; |
| 1775 } | 1868 } |
| 1776 } | 1869 } |
| 1777 | 1870 |
| 1871 UninstallMultiChromeFrameIfPresent(cmd_line, prefs, | |
| 1872 &original_state, &installer_state); | |
| 1873 | |
| 1778 base::FilePath installer_directory; | 1874 base::FilePath installer_directory; |
| 1779 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; | 1875 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; |
| 1780 // If --uninstall option is not specified, we assume it is install case. | 1876 // If --uninstall option is given, uninstall the identified product(s) |
| 1781 if (!is_uninstall) { | 1877 if (is_uninstall) { |
| 1878 install_status = | |
| 1879 UninstallProducts(original_state, installer_state, cmd_line); | |
| 1880 } else { | |
| 1881 // If --uninstall option is not specified, we assume it is install case. | |
| 1782 install_status = | 1882 install_status = |
| 1783 InstallProducts(original_state, cmd_line, prefs, &installer_state, | 1883 InstallProducts(original_state, cmd_line, prefs, &installer_state, |
| 1784 &installer_directory); | 1884 &installer_directory); |
| 1785 } | 1885 } |
| 1786 // If --uninstall option is given or only the binaries are present and they're | |
| 1787 // not in-use, uninstall the identified product(s). | |
| 1788 if (is_uninstall || (install_status == installer::UNUSED_BINARIES && | |
| 1789 !installer_state.AreBinariesInUse(original_state))) { | |
| 1790 install_status = | |
| 1791 UninstallProducts(original_state, installer_state, cmd_line); | |
| 1792 // Report that the binaries were uninstalled if they were. This translates | |
| 1793 // into a successful install return code. | |
| 1794 if (!is_uninstall && IsUninstallSuccess(install_status)) { | |
| 1795 install_status = installer::UNUSED_BINARIES_UNINSTALLED; | |
| 1796 installer_state.WriteInstallerResult(install_status, 0, NULL); | |
| 1797 } | |
| 1798 } | |
| 1799 | 1886 |
| 1800 // Validate that the machine is now in a good state following the operation. | 1887 // Validate that the machine is now in a good state following the operation. |
| 1801 // TODO(grt): change this to log at DFATAL once we're convinced that the | 1888 // TODO(grt): change this to log at DFATAL once we're convinced that the |
| 1802 // validator handles all cases properly. | 1889 // validator handles all cases properly. |
| 1803 InstallationValidator::InstallationType installation_type = | 1890 InstallationValidator::InstallationType installation_type = |
| 1804 InstallationValidator::NO_PRODUCTS; | 1891 InstallationValidator::NO_PRODUCTS; |
| 1805 LOG_IF(ERROR, | 1892 LOG_IF(ERROR, |
| 1806 !InstallationValidator::ValidateInstallationType(system_install, | 1893 !InstallationValidator::ValidateInstallationType(system_install, |
| 1807 &installation_type)); | 1894 &installation_type)); |
| 1808 | 1895 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1859 // Call the newly updated setup.exe with kUncompressedArchive and | 1946 // Call the newly updated setup.exe with kUncompressedArchive and |
| 1860 // kMigrateChromeFrame to perform the migration. | 1947 // kMigrateChromeFrame to perform the migration. |
| 1861 LaunchChromeFrameMigrationProcess(*chrome_frame_state, cmd_line, | 1948 LaunchChromeFrameMigrationProcess(*chrome_frame_state, cmd_line, |
| 1862 installer_directory, system_install); | 1949 installer_directory, system_install); |
| 1863 } | 1950 } |
| 1864 | 1951 |
| 1865 VLOG(1) << "Installation complete, returning: " << return_code; | 1952 VLOG(1) << "Installation complete, returning: " << return_code; |
| 1866 | 1953 |
| 1867 return return_code; | 1954 return return_code; |
| 1868 } | 1955 } |
| OLD | NEW |