| 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> |
| 11 #include <stddef.h> | 11 #include <stddef.h> |
| 12 #include <stdint.h> | 12 #include <stdint.h> |
| 13 | 13 |
| 14 #include <memory> |
| 14 #include <string> | 15 #include <string> |
| 15 | 16 |
| 16 #include "base/at_exit.h" | 17 #include "base/at_exit.h" |
| 17 #include "base/command_line.h" | 18 #include "base/command_line.h" |
| 18 #include "base/file_version_info.h" | 19 #include "base/file_version_info.h" |
| 19 #include "base/files/file_path.h" | 20 #include "base/files/file_path.h" |
| 20 #include "base/files/file_util.h" | 21 #include "base/files/file_util.h" |
| 21 #include "base/files/scoped_temp_dir.h" | 22 #include "base/files/scoped_temp_dir.h" |
| 22 #include "base/macros.h" | 23 #include "base/macros.h" |
| 23 #include "base/memory/scoped_ptr.h" | |
| 24 #include "base/metrics/histogram_macros.h" | 24 #include "base/metrics/histogram_macros.h" |
| 25 #include "base/path_service.h" | 25 #include "base/path_service.h" |
| 26 #include "base/process/launch.h" | 26 #include "base/process/launch.h" |
| 27 #include "base/process/memory.h" | 27 #include "base/process/memory.h" |
| 28 #include "base/strings/string16.h" | 28 #include "base/strings/string16.h" |
| 29 #include "base/strings/string_number_conversions.h" | 29 #include "base/strings/string_number_conversions.h" |
| 30 #include "base/strings/string_util.h" | 30 #include "base/strings/string_util.h" |
| 31 #include "base/strings/stringprintf.h" | 31 #include "base/strings/stringprintf.h" |
| 32 #include "base/strings/utf_string_conversions.h" | 32 #include "base/strings/utf_string_conversions.h" |
| 33 #include "base/time/time.h" | 33 #include "base/time/time.h" |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 base::Process writer = base::LaunchProcess(command_line, launch_options); | 166 base::Process writer = base::LaunchProcess(command_line, launch_options); |
| 167 if (!writer.IsValid()) { | 167 if (!writer.IsValid()) { |
| 168 PLOG(ERROR) << "Failed to set DisplayVersion: " | 168 PLOG(ERROR) << "Failed to set DisplayVersion: " |
| 169 << "could not launch subprocess to make desired changes." | 169 << "could not launch subprocess to make desired changes." |
| 170 << " <<" << command_line.GetCommandLineString() << ">>"; | 170 << " <<" << command_line.GetCommandLineString() << ">>"; |
| 171 } | 171 } |
| 172 } | 172 } |
| 173 | 173 |
| 174 // Returns NULL if no compressed archive is available for processing, otherwise | 174 // Returns NULL if no compressed archive is available for processing, otherwise |
| 175 // returns a patch helper configured to uncompress and patch. | 175 // returns a patch helper configured to uncompress and patch. |
| 176 scoped_ptr<installer::ArchivePatchHelper> CreateChromeArchiveHelper( | 176 std::unique_ptr<installer::ArchivePatchHelper> CreateChromeArchiveHelper( |
| 177 const base::FilePath& setup_exe, | 177 const base::FilePath& setup_exe, |
| 178 const base::CommandLine& command_line, | 178 const base::CommandLine& command_line, |
| 179 const installer::InstallerState& installer_state, | 179 const installer::InstallerState& installer_state, |
| 180 const base::FilePath& working_directory) { | 180 const base::FilePath& working_directory) { |
| 181 // A compressed archive is ordinarily given on the command line by the mini | 181 // A compressed archive is ordinarily given on the command line by the mini |
| 182 // installer. If one was not given, look for chrome.packed.7z next to the | 182 // installer. If one was not given, look for chrome.packed.7z next to the |
| 183 // running program. | 183 // running program. |
| 184 base::FilePath compressed_archive( | 184 base::FilePath compressed_archive( |
| 185 command_line.GetSwitchValuePath(installer::switches::kInstallArchive)); | 185 command_line.GetSwitchValuePath(installer::switches::kInstallArchive)); |
| 186 bool compressed_archive_specified = !compressed_archive.empty(); | 186 bool compressed_archive_specified = !compressed_archive.empty(); |
| 187 if (!compressed_archive_specified) { | 187 if (!compressed_archive_specified) { |
| 188 compressed_archive = setup_exe.DirName().Append( | 188 compressed_archive = setup_exe.DirName().Append( |
| 189 installer::kChromeCompressedArchive); | 189 installer::kChromeCompressedArchive); |
| 190 } | 190 } |
| 191 | 191 |
| 192 // Fail if no compressed archive is found. | 192 // Fail if no compressed archive is found. |
| 193 if (!base::PathExists(compressed_archive)) { | 193 if (!base::PathExists(compressed_archive)) { |
| 194 if (compressed_archive_specified) { | 194 if (compressed_archive_specified) { |
| 195 LOG(ERROR) << installer::switches::kInstallArchive << "=" | 195 LOG(ERROR) << installer::switches::kInstallArchive << "=" |
| 196 << compressed_archive.value() << " not found."; | 196 << compressed_archive.value() << " not found."; |
| 197 } | 197 } |
| 198 return scoped_ptr<installer::ArchivePatchHelper>(); | 198 return std::unique_ptr<installer::ArchivePatchHelper>(); |
| 199 } | 199 } |
| 200 | 200 |
| 201 // chrome.7z is either extracted directly from the compressed archive into the | 201 // chrome.7z is either extracted directly from the compressed archive into the |
| 202 // working dir or is the target of patching in the working dir. | 202 // working dir or is the target of patching in the working dir. |
| 203 base::FilePath target(working_directory.Append(installer::kChromeArchive)); | 203 base::FilePath target(working_directory.Append(installer::kChromeArchive)); |
| 204 DCHECK(!base::PathExists(target)); | 204 DCHECK(!base::PathExists(target)); |
| 205 | 205 |
| 206 // Specify an empty path for the patch source since it isn't yet known that | 206 // Specify an empty path for the patch source since it isn't yet known that |
| 207 // one is needed. It will be supplied in UncompressAndPatchChromeArchive if it | 207 // one is needed. It will be supplied in UncompressAndPatchChromeArchive if it |
| 208 // is. | 208 // is. |
| 209 return scoped_ptr<installer::ArchivePatchHelper>( | 209 return std::unique_ptr<installer::ArchivePatchHelper>( |
| 210 new installer::ArchivePatchHelper(working_directory, | 210 new installer::ArchivePatchHelper(working_directory, compressed_archive, |
| 211 compressed_archive, | 211 base::FilePath(), target)); |
| 212 base::FilePath(), | |
| 213 target)); | |
| 214 } | 212 } |
| 215 | 213 |
| 216 // Returns the MSI product ID from the ClientState key that is populated for MSI | 214 // Returns the MSI product ID from the ClientState key that is populated for MSI |
| 217 // installs. This property is encoded in a value name whose format is | 215 // installs. This property is encoded in a value name whose format is |
| 218 // "EnterpriseId<GUID>" where <GUID> is the MSI product id. <GUID> is in the | 216 // "EnterpriseId<GUID>" where <GUID> is the MSI product id. <GUID> is in the |
| 219 // format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. The id will be returned if | 217 // format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. The id will be returned if |
| 220 // found otherwise this method will return an empty string. | 218 // found otherwise this method will return an empty string. |
| 221 // | 219 // |
| 222 // This format is strange and its provenance is shrouded in mystery but it has | 220 // This format is strange and its provenance is shrouded in mystery but it has |
| 223 // the data we need, so use it. | 221 // the data we need, so use it. |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 // Create a temporary backup directory on the same volume as chrome.exe so | 383 // Create a temporary backup directory on the same volume as chrome.exe so |
| 386 // that moving in-use files doesn't lead to trouble. | 384 // that moving in-use files doesn't lead to trouble. |
| 387 installer::SelfCleaningTempDir temp_path; | 385 installer::SelfCleaningTempDir temp_path; |
| 388 if (!temp_path.Initialize(target_path.DirName(), | 386 if (!temp_path.Initialize(target_path.DirName(), |
| 389 installer::kInstallTempDir)) { | 387 installer::kInstallTempDir)) { |
| 390 PLOG(ERROR) << "Failed to create Temp directory " | 388 PLOG(ERROR) << "Failed to create Temp directory " |
| 391 << target_path.DirName() | 389 << target_path.DirName() |
| 392 .Append(installer::kInstallTempDir).value(); | 390 .Append(installer::kInstallTempDir).value(); |
| 393 return installer::RENAME_FAILED; | 391 return installer::RENAME_FAILED; |
| 394 } | 392 } |
| 395 scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); | 393 std::unique_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); |
| 396 // Move chrome.exe to old_chrome.exe, then move new_chrome.exe to chrome.exe. | 394 // Move chrome.exe to old_chrome.exe, then move new_chrome.exe to chrome.exe. |
| 397 install_list->AddMoveTreeWorkItem(chrome_exe.value(), | 395 install_list->AddMoveTreeWorkItem(chrome_exe.value(), |
| 398 chrome_old_exe.value(), | 396 chrome_old_exe.value(), |
| 399 temp_path.path().value(), | 397 temp_path.path().value(), |
| 400 WorkItem::ALWAYS_MOVE); | 398 WorkItem::ALWAYS_MOVE); |
| 401 install_list->AddMoveTreeWorkItem(chrome_new_exe.value(), | 399 install_list->AddMoveTreeWorkItem(chrome_new_exe.value(), |
| 402 chrome_exe.value(), | 400 chrome_exe.value(), |
| 403 temp_path.path().value(), | 401 temp_path.path().value(), |
| 404 WorkItem::ALWAYS_MOVE); | 402 WorkItem::ALWAYS_MOVE); |
| 405 install_list->AddDeleteTreeWorkItem(chrome_new_exe, temp_path.path()); | 403 install_list->AddDeleteTreeWorkItem(chrome_new_exe, temp_path.path()); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 } | 477 } |
| 480 } else { | 478 } else { |
| 481 // This will only be hit if --multi-install is given with no products. | 479 // This will only be hit if --multi-install is given with no products. |
| 482 return true; | 480 return true; |
| 483 } | 481 } |
| 484 | 482 |
| 485 if (!chrome && chrome_state) { | 483 if (!chrome && chrome_state) { |
| 486 // A product other than Chrome is being installed in multi-install mode, | 484 // A product other than Chrome is being installed in multi-install mode, |
| 487 // and Chrome is already present. Add Chrome to the set of products | 485 // and Chrome is already present. Add Chrome to the set of products |
| 488 // (making it multi-install in the process) so that it is updated, too. | 486 // (making it multi-install in the process) so that it is updated, too. |
| 489 scoped_ptr<Product> multi_chrome(new Product( | 487 std::unique_ptr<Product> multi_chrome( |
| 490 BrowserDistribution::GetSpecificDistribution( | 488 new Product(BrowserDistribution::GetSpecificDistribution( |
| 491 BrowserDistribution::CHROME_BROWSER))); | 489 BrowserDistribution::CHROME_BROWSER))); |
| 492 multi_chrome->SetOption(installer::kOptionMultiInstall, true); | 490 multi_chrome->SetOption(installer::kOptionMultiInstall, true); |
| 493 chrome = installer_state->AddProduct(&multi_chrome); | 491 chrome = installer_state->AddProduct(&multi_chrome); |
| 494 VLOG(1) << "Upgrading existing Chrome browser in multi-install mode."; | 492 VLOG(1) << "Upgrading existing Chrome browser in multi-install mode."; |
| 495 } | 493 } |
| 496 } // else migrate multi-install Chrome to single-install. | 494 } // else migrate multi-install Chrome to single-install. |
| 497 | 495 |
| 498 return true; | 496 return true; |
| 499 } | 497 } |
| 500 | 498 |
| (...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1228 if (chrome_install) { | 1226 if (chrome_install) { |
| 1229 installer::DeleteChromeRegistrationKeys(*installer_state, | 1227 installer::DeleteChromeRegistrationKeys(*installer_state, |
| 1230 chrome_install->distribution(), HKEY_LOCAL_MACHINE, suffix, &tmp); | 1228 chrome_install->distribution(), HKEY_LOCAL_MACHINE, suffix, &tmp); |
| 1231 } | 1229 } |
| 1232 *exit_code = tmp; | 1230 *exit_code = tmp; |
| 1233 } else if (cmd_line.HasSwitch(installer::switches::kOnOsUpgrade)) { | 1231 } else if (cmd_line.HasSwitch(installer::switches::kOnOsUpgrade)) { |
| 1234 const Product* chrome_install = | 1232 const Product* chrome_install = |
| 1235 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); | 1233 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); |
| 1236 installer::InstallStatus status = installer::INVALID_STATE_FOR_OPTION; | 1234 installer::InstallStatus status = installer::INVALID_STATE_FOR_OPTION; |
| 1237 if (chrome_install) { | 1235 if (chrome_install) { |
| 1238 scoped_ptr<FileVersionInfo> version_info( | 1236 std::unique_ptr<FileVersionInfo> version_info( |
| 1239 FileVersionInfo::CreateFileVersionInfo(setup_exe)); | 1237 FileVersionInfo::CreateFileVersionInfo(setup_exe)); |
| 1240 const base::Version installed_version( | 1238 const base::Version installed_version( |
| 1241 base::UTF16ToUTF8(version_info->product_version())); | 1239 base::UTF16ToUTF8(version_info->product_version())); |
| 1242 if (installed_version.IsValid()) { | 1240 if (installed_version.IsValid()) { |
| 1243 installer::HandleOsUpgradeForBrowser(*installer_state, *chrome_install, | 1241 installer::HandleOsUpgradeForBrowser(*installer_state, *chrome_install, |
| 1244 installed_version); | 1242 installed_version); |
| 1245 status = installer::INSTALL_REPAIRED; | 1243 status = installer::INSTALL_REPAIRED; |
| 1246 } else { | 1244 } else { |
| 1247 LOG(DFATAL) << "Failed to extract product version from " | 1245 LOG(DFATAL) << "Failed to extract product version from " |
| 1248 << setup_exe.value(); | 1246 << setup_exe.value(); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1424 *archive_type = UNKNOWN_ARCHIVE_TYPE; | 1422 *archive_type = UNKNOWN_ARCHIVE_TYPE; |
| 1425 base::FilePath uncompressed_archive(cmd_line.GetSwitchValuePath( | 1423 base::FilePath uncompressed_archive(cmd_line.GetSwitchValuePath( |
| 1426 switches::kUncompressedArchive)); | 1424 switches::kUncompressedArchive)); |
| 1427 if (uncompressed_archive.empty()) { | 1425 if (uncompressed_archive.empty()) { |
| 1428 base::Version previous_version; | 1426 base::Version previous_version; |
| 1429 if (cmd_line.HasSwitch(installer::switches::kPreviousVersion)) { | 1427 if (cmd_line.HasSwitch(installer::switches::kPreviousVersion)) { |
| 1430 previous_version = base::Version(cmd_line.GetSwitchValueASCII( | 1428 previous_version = base::Version(cmd_line.GetSwitchValueASCII( |
| 1431 installer::switches::kPreviousVersion)); | 1429 installer::switches::kPreviousVersion)); |
| 1432 } | 1430 } |
| 1433 | 1431 |
| 1434 scoped_ptr<ArchivePatchHelper> archive_helper( | 1432 std::unique_ptr<ArchivePatchHelper> archive_helper( |
| 1435 CreateChromeArchiveHelper(setup_exe, cmd_line, installer_state, | 1433 CreateChromeArchiveHelper(setup_exe, cmd_line, installer_state, |
| 1436 unpack_path)); | 1434 unpack_path)); |
| 1437 if (archive_helper) { | 1435 if (archive_helper) { |
| 1438 VLOG(1) << "Installing Chrome from compressed archive " | 1436 VLOG(1) << "Installing Chrome from compressed archive " |
| 1439 << archive_helper->compressed_archive().value(); | 1437 << archive_helper->compressed_archive().value(); |
| 1440 if (!UncompressAndPatchChromeArchive(original_state, | 1438 if (!UncompressAndPatchChromeArchive(original_state, |
| 1441 installer_state, | 1439 installer_state, |
| 1442 archive_helper.get(), | 1440 archive_helper.get(), |
| 1443 archive_type, | 1441 archive_type, |
| 1444 &install_status, | 1442 &install_status, |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1485 UMA_HISTOGRAM_MEDIUM_TIMES( | 1483 UMA_HISTOGRAM_MEDIUM_TIMES( |
| 1486 "Setup.Install.UnpackFullArchiveTime.background", elapsed_time); | 1484 "Setup.Install.UnpackFullArchiveTime.background", elapsed_time); |
| 1487 } else { | 1485 } else { |
| 1488 UMA_HISTOGRAM_MEDIUM_TIMES( | 1486 UMA_HISTOGRAM_MEDIUM_TIMES( |
| 1489 "Setup.Install.UnpackFullArchiveTime", elapsed_time); | 1487 "Setup.Install.UnpackFullArchiveTime", elapsed_time); |
| 1490 } | 1488 } |
| 1491 | 1489 |
| 1492 VLOG(1) << "unpacked to " << unpack_path.value(); | 1490 VLOG(1) << "unpacked to " << unpack_path.value(); |
| 1493 base::FilePath src_path( | 1491 base::FilePath src_path( |
| 1494 unpack_path.Append(kInstallSourceChromeDir)); | 1492 unpack_path.Append(kInstallSourceChromeDir)); |
| 1495 scoped_ptr<Version> | 1493 std::unique_ptr<Version> installer_version( |
| 1496 installer_version(GetMaxVersionFromArchiveDir(src_path)); | 1494 GetMaxVersionFromArchiveDir(src_path)); |
| 1497 if (!installer_version.get()) { | 1495 if (!installer_version.get()) { |
| 1498 LOG(ERROR) << "Did not find any valid version in installer."; | 1496 LOG(ERROR) << "Did not find any valid version in installer."; |
| 1499 install_status = INVALID_ARCHIVE; | 1497 install_status = INVALID_ARCHIVE; |
| 1500 installer_state.WriteInstallerResult(install_status, | 1498 installer_state.WriteInstallerResult(install_status, |
| 1501 IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); | 1499 IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); |
| 1502 } else { | 1500 } else { |
| 1503 VLOG(1) << "version to install: " << installer_version->GetString(); | 1501 VLOG(1) << "version to install: " << installer_version->GetString(); |
| 1504 bool proceed_with_installation = true; | 1502 bool proceed_with_installation = true; |
| 1505 | 1503 |
| 1506 uint32_t higher_products = 0; | 1504 uint32_t higher_products = 0; |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1847 // to pass through, since this is only returned on uninstall which is | 1845 // to pass through, since this is only returned on uninstall which is |
| 1848 // never invoked directly by Google Update. | 1846 // never invoked directly by Google Update. |
| 1849 return_code = InstallUtil::GetInstallReturnCode(install_status); | 1847 return_code = InstallUtil::GetInstallReturnCode(install_status); |
| 1850 } | 1848 } |
| 1851 | 1849 |
| 1852 installer::EndPersistentHistogramStorage(installer_state.target_path()); | 1850 installer::EndPersistentHistogramStorage(installer_state.target_path()); |
| 1853 VLOG(1) << "Installation complete, returning: " << return_code; | 1851 VLOG(1) << "Installation complete, returning: " << return_code; |
| 1854 | 1852 |
| 1855 return return_code; | 1853 return return_code; |
| 1856 } | 1854 } |
| OLD | NEW |