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 |