15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/installer/setup/setup_main.h" 6ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <msi.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shellapi.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shlobj.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string> 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/at_exit.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_version_info.h" 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/files/file_path.h" 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/scoped_temp_dir.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 23a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/launch.h" 247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string16.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h" 277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/stringprintf.h" 28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_com_initializer.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_comptr.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/win_util.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "breakpad/src/client/windows/handler/exception_handler.h" 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_constants.h" 38e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/common/chrome_paths.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 40ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chrome/installer/setup/archive_patch_helper.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/setup/install.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/setup/install_worker.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/setup/setup_constants.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/setup/setup_util.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/setup/uninstall.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/browser_distribution.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/channel_info.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/delete_after_reboot_helper.h" 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/delete_tree_work_item.h" 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/installer/util/eula_util.h" 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/google_update_constants.h" 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/google_update_settings.h" 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/google_update_util.h" 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/helper.h" 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/html_dialog.h" 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/install_util.h" 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/installation_state.h" 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/installation_validator.h" 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/installer_state.h" 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/l10n_string_util.h" 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/logging_installer.h" 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/lzma_util.h" 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/master_preferences.h" 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/master_preferences_constants.h" 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/self_cleaning_temp_dir.h" 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/shell_util.h" 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/installer/util/user_experiment.h" 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "installer_util_strings.h" // NOLINT 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using installer::InstallerState; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using installer::InstallationState; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using installer::InstallationValidator; 7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)using installer::MasterPreferences; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using installer::Product; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using installer::ProductState; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using installer::Products; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices"; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kSystemPrincipalSid[] = L"S-1-5-18"; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>( 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MiniDumpWithProcessThreadData | // Get PEB and TEB. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MiniDumpWithUnloadedModules | // Get unloaded modules when available. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 90ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Returns NULL if no compressed archive is available for processing, otherwise 91ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// returns a patch helper configured to uncompress and patch. 92ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochscoped_ptr<installer::ArchivePatchHelper> CreateChromeArchiveHelper( 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& setup_exe, 94ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const CommandLine& command_line, 95ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const installer::InstallerState& installer_state, 96ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const base::FilePath& working_directory) { 97ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // A compressed archive is ordinarily given on the command line by the mini 98ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // installer. If one was not given, look for chrome.packed.7z next to the 99ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // running program. 100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::FilePath compressed_archive( 101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch command_line.GetSwitchValuePath(installer::switches::kInstallArchive)); 102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool compressed_archive_specified = !compressed_archive.empty(); 103ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!compressed_archive_specified) { 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) compressed_archive = setup_exe.DirName().Append( 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) installer::kChromeCompressedArchive); 106ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 108ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Fail if no compressed archive is found. 109ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!base::PathExists(compressed_archive)) { 110ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (compressed_archive_specified) { 111ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch LOG(ERROR) << installer::switches::kInstallArchive << "=" 112ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch << compressed_archive.value() << " not found."; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 114ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return scoped_ptr<installer::ArchivePatchHelper>(); 115ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 117ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // chrome.7z is either extracted directly from the compressed archive into the 118ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // working dir or is the target of patching in the working dir. 119ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::FilePath target(working_directory.Append(installer::kChromeArchive)); 120ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(!base::PathExists(target)); 121ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 122ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Specify an empty path for the patch source since it isn't yet known that 123ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // one is needed. It will be supplied in UncompressAndPatchChromeArchive if it 124ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // is. 125ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return scoped_ptr<installer::ArchivePatchHelper>( 126ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch new installer::ArchivePatchHelper(working_directory, 127ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch compressed_archive, 128ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::FilePath(), 129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch target)); 130ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 131ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 132ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Workhorse for producing an uncompressed archive (chrome.7z) given a 133ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// chrome.packed.7z containing either a patch file based on the version of 134ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// chrome being updated or the full uncompressed archive. Returns true on 135ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// success, in which case |archive_type| is populated based on what was found. 136ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Returns false on failure, in which case |install_status| contains the error 137ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// code and the result is written to the registry (via WriteInstallerResult). 138ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool UncompressAndPatchChromeArchive( 139ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const installer::InstallationState& original_state, 140ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const installer::InstallerState& installer_state, 141ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch installer::ArchivePatchHelper* archive_helper, 142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch installer::ArchiveType* archive_type, 143ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch installer::InstallStatus* install_status) { 144ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch installer_state.UpdateStage(installer::UNCOMPRESSING); 145ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!archive_helper->Uncompress(NULL)) { 146ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *install_status = installer::UNCOMPRESSION_FAILED; 147ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch installer_state.WriteInstallerResult(*install_status, 148ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, 149ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NULL); 150ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return false; 151ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 152ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 153ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Short-circuit if uncompression produced the uncompressed archive rather 154ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // than a patch file. 155ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (base::PathExists(archive_helper->target())) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *archive_type = installer::FULL_ARCHIVE_TYPE; 157ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return true; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 160ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Find the installed version's archive to serve as the source for patching. 161ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::FilePath patch_source(installer::FindArchiveToPatch(original_state, 162ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch installer_state)); 163ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (patch_source.empty()) { 164ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch LOG(ERROR) << "Failed to find archive to patch."; 165ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *install_status = installer::DIFF_PATCH_SOURCE_MISSING; 166ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch installer_state.WriteInstallerResult(*install_status, 167ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, 168ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NULL); 169ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return false; 170ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 171ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch archive_helper->set_patch_source(patch_source); 172ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 173ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Try courgette first. Failing that, try bspatch. 174ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if ((installer_state.UpdateStage(installer::ENSEMBLE_PATCHING), 175ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch !archive_helper->EnsemblePatch()) && 176ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (installer_state.UpdateStage(installer::BINARY_PATCHING), 177ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch !archive_helper->BinaryPatch())) { 178ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *install_status = installer::APPLY_DIFF_PATCH_FAILED; 179ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch installer_state.WriteInstallerResult(*install_status, 180ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, 181ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NULL); 182ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return false; 183ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *archive_type = installer::INCREMENTAL_ARCHIVE_TYPE; 186ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return true; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In multi-install, adds all products to |installer_state| that are 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// multi-installed and must be updated along with the products already present 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in |installer_state|. 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AddExistingMultiInstalls(const InstallationState& original_state, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallerState* installer_state) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (installer_state->is_multi_install()) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::Type type = 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<BrowserDistribution::Type>(i); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!installer_state->FindProduct(type)) { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProductState* state = 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original_state.GetProductState(installer_state->system_install(), 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((state != NULL) && state->is_multi_install()) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->AddProductFromState(type, *state); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Product already installed and must be included: " 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << BrowserDistribution::GetSpecificDistribution(type)-> 2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) GetDisplayName(); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function is called when --rename-chrome-exe option is specified on 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// setup.exe command line. This function assumes an in-use update has happened 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for Chrome so there should be a file called new_chrome.exe on the file 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// system and a key called 'opv' in the registry. This function will move 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// new_chrome.exe to chrome.exe and delete 'opv' key in one atomic operation. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function also deletes elevation policies associated with the old version 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if they exist. 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)installer::InstallStatus RenameChromeExecutables( 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const InstallationState& original_state, 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallerState* installer_state) { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See what products are already installed in multi mode. When we do the 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // rename for multi installs, we must update all installations since they 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // share the binaries. 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddExistingMultiInstalls(original_state, installer_state); 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath &target_path = installer_state->target_path(); 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_exe(target_path.Append(installer::kChromeExe)); 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_new_exe(target_path.Append(installer::kChromeNewExe)); 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_old_exe(target_path.Append(installer::kChromeOldExe)); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a temporary backup directory on the same volume as chrome.exe so 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that moving in-use files doesn't lead to trouble. 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::SelfCleaningTempDir temp_path; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!temp_path.Initialize(target_path.DirName(), 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::kInstallTempDir)) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "Failed to create Temp directory " 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << target_path.DirName() 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .Append(installer::kInstallTempDir).value(); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return installer::RENAME_FAILED; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Move chrome.exe to old_chrome.exe, then move new_chrome.exe to chrome.exe. 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) install_list->AddMoveTreeWorkItem(chrome_exe.value(), 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_old_exe.value(), 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_path.path().value(), 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WorkItem::ALWAYS_MOVE); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) install_list->AddMoveTreeWorkItem(chrome_new_exe.value(), 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_exe.value(), 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_path.path().value(), 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WorkItem::ALWAYS_MOVE); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) install_list->AddDeleteTreeWorkItem(chrome_new_exe, temp_path.path()); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // old_chrome.exe is still in use in most cases, so ignore failures here. 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) install_list->AddDeleteTreeWorkItem(chrome_old_exe, temp_path.path())-> 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_ignore_failure(true); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add work items to delete the "opv", "cpv", and "cmd" values from all 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // products we're operating on (which including the multi-install binaries). 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Products& products = installer_state->products(); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HKEY reg_root = installer_state->root_key(); 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 version_key; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Products::const_iterator it = products.begin(); it < products.end(); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_key = (*it)->distribution()->GetVersionKey(); 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) install_list->AddDeleteRegValueWorkItem(reg_root, 267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version_key, 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) KEY_WOW64_32KEY, 269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) google_update::kRegOldVersionField); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) install_list->AddDeleteRegValueWorkItem( 271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reg_root, 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version_key, 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) KEY_WOW64_32KEY, 274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) google_update::kRegCriticalVersionField); 275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) install_list->AddDeleteRegValueWorkItem(reg_root, 276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) version_key, 277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) KEY_WOW64_32KEY, 278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) google_update::kRegRenameCmdField); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallStatus ret = installer::RENAME_SUCCESSFUL; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!install_list->Do()) { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Renaming of executables failed. Rolling back any changes."; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) install_list->Rollback(); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = installer::RENAME_FAILED; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // temp_path's dtor will take care of deleting or scheduling itself for 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // deletion at reboot when this scope closes. 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Deleting temporary directory " << temp_path.path().value(); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For each product that is being updated (i.e., already installed at an earlier 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// version), see if that product has an update policy override that differs from 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that for the binaries. If any are found, fail with an error indicating that 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the Group Policy settings are in an inconsistent state. Do not do this test 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for same-version installs, since it would be unkind to block attempts to 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// repair a corrupt installation. This function returns false when installation 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// should be halted, in which case |status| contains the relevant exit code and 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the proper installer result has been written to the registry. 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CheckGroupPolicySettings(const InstallationState& original_state, 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const InstallerState& installer_state, 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Version& new_version, 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallStatus* status) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(GOOGLE_CHROME_BUILD) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chromium builds are not updated via Google Update, so there are no 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Group Policy settings to consult. 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(status); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Single installs are always in good shape. 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!installer_state.is_multi_install()) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool settings_are_valid = true; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool is_system_install = installer_state.system_install(); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution* const binaries_dist = 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state.multi_package_binaries_distribution(); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the update policy for the binaries. 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GoogleUpdateSettings::UpdatePolicy binaries_policy = 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleUpdateSettings::GetAppUpdatePolicy(binaries_dist->GetAppGuid(), 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for differing update policies for all of the products being updated. 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Products& products = installer_state.products(); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Products::const_iterator scan = products.begin(); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Products::const_iterator end = products.end(); scan != end; ++scan) { 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution* dist = (*scan)->distribution(); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProductState* product_state = 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original_state.GetProductState(is_system_install, dist->GetType()); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Is an earlier version of this product already installed? 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (product_state != NULL && 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) product_state->version().CompareTo(new_version) < 0) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_overridden = false; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleUpdateSettings::UpdatePolicy app_policy = 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GoogleUpdateSettings::GetAppUpdatePolicy(dist->GetAppGuid(), 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &is_overridden); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_overridden && app_policy != binaries_policy) { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Found legacy Group Policy setting for " 3423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) << dist->GetDisplayName() << " (value: " << app_policy 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ") that does not match the setting for " 3443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) << binaries_dist->GetDisplayName() 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " (value: " << binaries_policy << ")."; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings_are_valid = false; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!settings_are_valid) { 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(grt): add " See http://goo.gl/+++ for details." to the end of this 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // log message and to the IDS_INSTALL_INCONSISTENT_UPDATE_POLICY string once 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we have a help center article that explains why this error is being 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reported and how to resolve it. 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Cannot apply update on account of inconsistent " 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Google Update Group Policy settings. Use the Group Policy " 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Editor to set the update policy override for the " 3593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) << binaries_dist->GetDisplayName() 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " application and try again."; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *status = installer::INCONSISTENT_UPDATE_POLICY; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state.WriteInstallerResult( 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *status, IDS_INSTALL_INCONSISTENT_UPDATE_POLICY_BASE, NULL); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return settings_are_valid; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(GOOGLE_CHROME_BUILD) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// If only the binaries are being updated, fail. 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If any product is being installed in single-mode that already exists in 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// multi-mode, fail. 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CheckMultiInstallConditions(const InstallationState& original_state, 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallerState* installer_state, 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallStatus* status) { 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Products& products = installer_state->products(); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(products.size()); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool system_level = installer_state->system_install(); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (installer_state->is_multi_install()) { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Product* chrome = 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Product* app_host = 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->FindProduct(BrowserDistribution::CHROME_APP_HOST); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Product* binaries = 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->FindProduct(BrowserDistribution::CHROME_BINARIES); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProductState* chrome_state = 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original_state.GetProductState(system_level, 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::CHROME_BROWSER); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (binaries) { 3934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (products.size() == 1) { 3944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // There are no products aside from the binaries, so there is no update 3954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // to be applied. This can happen after multi-install Chrome Frame is 3964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // migrated to single-install. This is treated as an update failure 3974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // unless the binaries are not in-use, in which case they will be 3984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // uninstalled and success will be reported (see handling in wWinMain). 399a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VLOG(1) << "No products to be updated."; 4004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *status = installer::UNUSED_BINARIES; 4014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) installer_state->WriteInstallerResult(*status, 0, NULL); 4024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 4034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will only be hit if --multi-install is given with no products, or 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if the app host is being installed and doesn't need the binaries at 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // user-level. 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The former case might be due to a request by an orphaned Application 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Host to re-install the binaries. Thus we add them to the installation. 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The latter case is fine and we let it be. 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is not an app host install and the binaries are not already 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // present, the installation will fail later due to a lack of products to 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // install. 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_host && !chrome && !chrome_state) { 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!system_level); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // App Host may use Chrome/Chrome binaries at system-level. 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (original_state.GetProductState( 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, // system 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::CHROME_BROWSER) || 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original_state.GetProductState( 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, // system 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::CHROME_BINARIES)) { 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VLOG(1) << "Installing/updating App Launcher without binaries."; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Somehow the binaries were present when the quick-enable app host 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // command was run, but now they appear to be missing. 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force binaries to be installed/updated. 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Product> binaries_to_add(new Product( 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::GetSpecificDistribution( 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::CHROME_BINARIES))); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) binaries_to_add->SetOption(installer::kOptionMultiInstall, true); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) binaries = installer_state->AddProduct(&binaries_to_add); 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VLOG(1) << 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Adding binaries for pre-existing App Launcher installation."; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!chrome && chrome_state) { 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A product other than Chrome is being installed in multi-install mode, 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and Chrome is already present. Add Chrome to the set of products 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (making it multi-install in the process) so that it is updated, too. 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Product> multi_chrome(new Product( 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::GetSpecificDistribution( 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::CHROME_BROWSER))); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) multi_chrome->SetOption(installer::kOptionMultiInstall, true); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome = installer_state->AddProduct(&multi_chrome); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Upgrading existing Chrome browser in multi-install mode."; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is a non-multi installation. 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for an existing installation of the product. 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProductState* product_state = original_state.GetProductState( 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_level, products[0]->distribution()->GetType()); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (product_state != NULL) { 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Block downgrades from multi-install to single-install. 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (product_state->is_multi_install()) { 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Multi-install " 4623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) << products[0]->distribution()->GetDisplayName() 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " exists; aborting single install."; 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *status = installer::MULTI_INSTALLATION_EXISTS; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->WriteInstallerResult(*status, 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_INSTALL_MULTI_INSTALLATION_EXISTS_BASE, NULL); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Checks app host pre-install conditions, specifically that this is a 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// user-level multi-install. When the pre-install conditions are not 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// satisfied, the result is written to the registry (via WriteInstallerResult), 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |status| is set appropriately, and false is returned. 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CheckAppHostPreconditions(const InstallationState& original_state, 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallerState* installer_state, 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallStatus* status) { 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (installer_state->FindProduct(BrowserDistribution::CHROME_APP_HOST)) { 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!installer_state->is_multi_install()) { 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(DFATAL) << "App Launcher requires multi install"; 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *status = installer::APP_HOST_REQUIRES_MULTI_INSTALL; 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No message string since there is nothing a user can do. 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->WriteInstallerResult(*status, 0, NULL); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (installer_state->system_install()) { 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(DFATAL) << "App Launcher may only be installed at user-level."; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *status = installer::APP_HOST_REQUIRES_USER_LEVEL; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No message string since there is nothing a user can do. 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->WriteInstallerResult(*status, 0, NULL); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Checks for compatibility between the current state of the system and the 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// desired operation. Also applies policy that mutates the desired operation; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// specifically, the |installer_state| object. 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Also blocks simultaneous user-level and system-level installs. In the case 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of trying to install user-level Chrome when system-level exists, the 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// existing system-level Chrome is launched. 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When the pre-install conditions are not satisfied, the result is written to 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the registry (via WriteInstallerResult), |status| is set appropriately, and 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// false is returned. 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CheckPreInstallConditions(const InstallationState& original_state, 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallerState* installer_state, 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallStatus* status) { 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CheckAppHostPreconditions(original_state, installer_state, status)) { 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(*status, installer::UNKNOWN_STATUS); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See what products are already installed in multi mode. When we do multi 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // installs, we must upgrade all installations since they share the binaries. 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddExistingMultiInstalls(original_state, installer_state); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CheckMultiInstallConditions(original_state, installer_state, status)) { 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(*status, installer::UNKNOWN_STATUS); 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Products& products = installer_state->products(); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (products.empty()) { 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We haven't been given any products on which to operate. 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Not given any products to install and no products found to update."; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *status = installer::CHROME_NOT_INSTALLED; 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->WriteInstallerResult(*status, 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_INSTALL_NO_PRODUCTS_TO_UPDATE_BASE, NULL); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!installer_state->system_install()) { 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is a user-level installation. Make sure that we are not installing 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on top of an existing system-level installation. 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Products::const_iterator it = products.begin(); it < products.end(); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Product& product = **it; 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution* browser_dist = product.distribution(); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip over the binaries, as it's okay for them to be at both levels 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for different products. 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_dist->GetType() == BrowserDistribution::CHROME_BINARIES) 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProductState* user_level_product_state = 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original_state.GetProductState(false, browser_dist->GetType()); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProductState* system_level_product_state = 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original_state.GetProductState(true, browser_dist->GetType()); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allow upgrades to proceed so that out-of-date versions are not left 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // around. 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (user_level_product_state) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is a new user-level install... 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (system_level_product_state) { 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ... and the product already exists at system-level. 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Already installed version " 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << system_level_product_state->version().GetString() 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " at system-level conflicts with this one at user-level."; 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (product.is_chrome()) { 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Instruct Google Update to launch the existing system-level Chrome. 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There should be no error dialog. 5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath install_path(installer::GetChromeInstallPath( 5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) true, // system 5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_dist)); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (install_path.empty()) { 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Give up if we failed to construct the install path. 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *status = installer::OS_ERROR; 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->WriteInstallerResult(*status, 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_INSTALL_OS_ERROR_BASE, 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *status = installer::EXISTING_VERSION_LAUNCHED; 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_exe = 5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) install_path.Append(installer::kChromeExe); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine cmd(chrome_exe); 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cmd.AppendSwitch(switches::kForceFirstRun); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->WriteInstallerResult(*status, 0, NULL); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Launching existing system-level chrome instead."; 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchProcess(cmd, base::LaunchOptions(), NULL); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // It's no longer possible for |product| to be anything other than 5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Chrome. 5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { // System-level install. 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // --ensure-google-update-present is supported for user-level only. 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The flag is generic, but its primary use case involves App Host. 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (installer_state->ensure_google_update_present()) { 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "--" << installer::switches::kEnsureGoogleUpdatePresent 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " is supported for user-level only."; 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *status = installer::APP_HOST_REQUIRES_USER_LEVEL; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No message string since there is nothing a user can do. 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->WriteInstallerResult(*status, 0, NULL); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 617ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Initializes |temp_path| to "Temp" within the target directory, and 618ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// |unpack_path| to a random directory beginning with "source" within 619ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// |temp_path|. Returns false on error. 620ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool CreateTemporaryAndUnpackDirectories( 621ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const InstallerState& installer_state, 622ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch installer::SelfCleaningTempDir* temp_path, 623ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::FilePath* unpack_path) { 624ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(temp_path && unpack_path); 625ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 626ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!temp_path->Initialize(installer_state.target_path().DirName(), 627ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch installer::kInstallTempDir)) { 628ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch PLOG(ERROR) << "Could not create temporary path."; 629ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return false; 630ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 631ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch VLOG(1) << "Created path " << temp_path->path().value(); 632ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 633a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::CreateTemporaryDirInDir(temp_path->path(), 634a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) installer::kInstallSourceDir, 635a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unpack_path)) { 636ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch PLOG(ERROR) << "Could not create temporary path for unpacked archive."; 637ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return false; 638ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 639ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 640ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return true; 641ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 642ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 643ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochinstaller::InstallStatus UninstallProduct( 644ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const InstallationState& original_state, 645ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const InstallerState& installer_state, 6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& setup_exe, 647ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const CommandLine& cmd_line, 648ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool remove_all, 649ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool force_uninstall, 650ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const Product& product) { 651ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const ProductState* product_state = 652ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch original_state.GetProductState(installer_state.system_install(), 653ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch product.distribution()->GetType()); 654ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (product_state != NULL) { 655ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch VLOG(1) << "version on the system: " 656ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << product_state->version().GetString(); 657ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else if (!force_uninstall) { 6583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(ERROR) << product.distribution()->GetDisplayName() 659ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << " not found for uninstall."; 660ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return installer::CHROME_NOT_INSTALLED; 661ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 662ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 663ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return installer::UninstallProduct( 6645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) original_state, installer_state, setup_exe, product, remove_all, 6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) force_uninstall, cmd_line); 666ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 667ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 668ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochinstaller::InstallStatus UninstallProducts( 669ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const InstallationState& original_state, 670ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const InstallerState& installer_state, 6715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& setup_exe, 672ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const CommandLine& cmd_line) { 673ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const Products& products = installer_state.products(); 674ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 675ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // System-level Chrome will be launched via this command if its program gets 676ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // set below. 677ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch CommandLine system_level_cmd(CommandLine::NO_PROGRAM); 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 679ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const Product* chrome = 680ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER); 681ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (chrome) { 682ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // InstallerState::Initialize always puts Chrome first, and we rely on that 683ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // here for this reason: if Chrome is in-use, the user will be prompted to 684ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // confirm uninstallation. Upon cancel, we should not continue with the 685ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // other products. 686ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(products[0]->is_chrome()); 687ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 688ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (cmd_line.HasSwitch(installer::switches::kSelfDestruct) && 689ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch !installer_state.system_install()) { 690ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch BrowserDistribution* dist = chrome->distribution(); 691ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const base::FilePath system_exe_path( 692ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch installer::GetChromeInstallPath(true, dist) 693ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch .Append(installer::kChromeExe)); 694ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch system_level_cmd.SetProgram(system_exe_path); 695ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 696ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 697ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (installer_state.FindProduct(BrowserDistribution::CHROME_BINARIES)) { 698ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Chrome Binaries should be last; if something else is cancelled, they 699ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // should stay. 700ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(products[products.size() - 1]->is_chrome_binaries()); 701ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallStatus install_status = installer::UNINSTALL_SUCCESSFUL; 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallStatus prod_status = installer::UNKNOWN_STATUS; 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool force = cmd_line.HasSwitch(installer::switches::kForceUninstall); 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool remove_all = !cmd_line.HasSwitch( 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::switches::kDoNotRemoveSharedItems); 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Products::const_iterator it = products.begin(); 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) install_status != installer::UNINSTALL_CANCELLED && it < products.end(); 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 7125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prod_status = UninstallProduct(original_state, installer_state, setup_exe, 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_line, remove_all, force, **it); 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prod_status != installer::UNINSTALL_SUCCESSFUL) 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) install_status = prod_status; 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) installer::CleanUpInstallationDirectoryAfterUninstall( 7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) original_state, installer_state, setup_exe, &install_status); 7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // The app and vendor dirs may now be empty. Make a last-ditch attempt to 7224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // delete them. 7234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) installer::DeleteChromeDirectoriesIfEmpty(installer_state.target_path()); 7244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 725a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Trigger Active Setup if it was requested for the chrome product. This needs 726a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // to be done after the UninstallProduct calls as some of them might 727a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // otherwise terminate the process launched by TriggerActiveSetupCommand(). 728a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (chrome && cmd_line.HasSwitch(installer::switches::kTriggerActiveSetup)) 7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InstallUtil::TriggerActiveSetupCommand(); 7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!system_level_cmd.GetProgram().empty()) 7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::LaunchProcess(system_level_cmd, base::LaunchOptions(), NULL); 7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tell Google Update that an uninstall has taken place. 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore the return value: success or failure of Google Update 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // has no bearing on the success or failure of Chrome's uninstallation. 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) google_update::UninstallGoogleUpdate(installer_state.system_install()); 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return install_status; 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 742a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Uninstall the binaries if they are the only product present and they're not 743a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// in-use. 744a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void UninstallBinariesIfUnused( 745a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const InstallationState& original_state, 746a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const InstallerState& installer_state, 747a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) installer::InstallStatus* install_status) { 748a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Early exit if the binaries are still in use. 749a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (*install_status != installer::UNUSED_BINARIES || 750a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) installer_state.AreBinariesInUse(original_state)) { 751a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 752a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 753a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 754a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOG(INFO) << "Uninstalling unused binaries"; 755a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) installer_state.UpdateStage(installer::UNINSTALLING_BINARIES); 756a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 757a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Simulate the uninstall as coming from the installed version. 758a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const ProductState* binaries_state = 759a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) original_state.GetProductState(installer_state.system_install(), 760a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BrowserDistribution::CHROME_BINARIES); 761a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const CommandLine& uninstall_cmd(binaries_state->uninstall_command()); 762a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MasterPreferences uninstall_prefs(uninstall_cmd); 763a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) InstallerState uninstall_state; 764a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uninstall_state.Initialize(uninstall_cmd, uninstall_prefs, original_state); 765a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 7665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *install_status = UninstallProducts(original_state, uninstall_state, 7675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uninstall_cmd.GetProgram(), 7685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uninstall_cmd); 769a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 770a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Report that the binaries were uninstalled if they were. This translates 771a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // into a successful install return code. 772a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (IsUninstallSuccess(*install_status)) { 773a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) *install_status = installer::UNUSED_BINARIES_UNINSTALLED; 774a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) installer_state.WriteInstallerResult(*install_status, 0, NULL); 775a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 776a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 777a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 778a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)installer::InstallStatus InstallProducts( 779a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const InstallationState& original_state, 7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& setup_exe, 781a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const CommandLine& cmd_line, 782a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const MasterPreferences& prefs, 783a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) InstallerState* installer_state, 784a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::FilePath* installer_directory) { 785a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(installer_state); 786a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const bool system_install = installer_state->system_install(); 787a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) installer::InstallStatus install_status = installer::UNKNOWN_STATUS; 788a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) installer::ArchiveType archive_type = installer::UNKNOWN_ARCHIVE_TYPE; 789a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool delegated_to_existing = false; 790a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) installer_state->UpdateStage(installer::PRECONDITIONS); 791a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // The stage provides more fine-grained information than -multifail, so remove 792a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // the -multifail suffix from the Google Update "ap" value. 793a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BrowserDistribution::GetSpecificDistribution(installer_state->state_type())-> 794a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) UpdateInstallStatus(system_install, archive_type, install_status); 795a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (CheckPreInstallConditions(original_state, installer_state, 796a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &install_status)) { 797a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VLOG(1) << "Installing to " << installer_state->target_path().value(); 798a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) install_status = InstallProductsHelper( 7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) original_state, setup_exe, cmd_line, prefs, *installer_state, 800a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) installer_directory, &archive_type, &delegated_to_existing); 801a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 802a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // CheckPreInstallConditions must set the status on failure. 803a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK_NE(install_status, installer::UNKNOWN_STATUS); 804a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 805a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 806a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Delete the master preferences file if present. Note that we do not care 807a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // about rollback here and we schedule for deletion on reboot if the delete 808a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // fails. As such, we do not use DeleteTreeWorkItem. 809a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (cmd_line.HasSwitch(installer::switches::kInstallerData)) { 810a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::FilePath prefs_path(cmd_line.GetSwitchValuePath( 811a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) installer::switches::kInstallerData)); 812a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::DeleteFile(prefs_path, false)) { 813a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOG(ERROR) << "Failed deleting master preferences file " 814a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << prefs_path.value() 815a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << ", scheduling for deletion after reboot."; 816a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ScheduleFileSystemEntityForDeletion(prefs_path); 817a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 818a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 819a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 820a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Early exit if this setup.exe delegated to another, since that one would 821a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // have taken care of UpdateInstallStatus and UpdateStage. 822a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (delegated_to_existing) 823a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return install_status; 824a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 825a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const Products& products = installer_state->products(); 826a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (Products::const_iterator it = products.begin(); it < products.end(); 827a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ++it) { 828a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) (*it)->distribution()->UpdateInstallStatus( 829a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) system_install, archive_type, install_status); 830a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 831a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 832a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) UninstallBinariesIfUnused(original_state, *installer_state, &install_status); 833a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 834a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) installer_state->UpdateStage(installer::NO_STAGE); 835a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return install_status; 836a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 837a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 8385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)installer::InstallStatus ShowEULADialog(const base::string16& inner_frame) { 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "About to show EULA"; 8405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 eula_path = installer::GetLocalizedEulaResource(); 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (eula_path.empty()) { 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "No EULA path available"; 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return installer::EULA_REJECTED; 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Newer versions of the caller pass an inner frame parameter that must 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be given to the html page being launched. 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::EulaHTMLDialog dlg(eula_path, inner_frame); 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::EulaHTMLDialog::Outcome outcome = dlg.ShowModal(); 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (installer::EulaHTMLDialog::REJECTED == outcome) { 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "EULA rejected or EULA failure"; 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return installer::EULA_REJECTED; 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (installer::EulaHTMLDialog::ACCEPTED_OPT_IN == outcome) { 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "EULA accepted (opt-in)"; 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return installer::EULA_ACCEPTED_OPT_IN; 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "EULA accepted (no opt-in)"; 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return installer::EULA_ACCEPTED; 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates the sentinel indicating that the EULA was required and has been 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// accepted. 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CreateEULASentinel(BrowserDistribution* dist) { 8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath eula_sentinel; 8650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!InstallUtil::GetEULASentinelFilePath(&eula_sentinel)) 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 868a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return (base::CreateDirectory(eula_sentinel.DirName()) && 869a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::WriteFile(eula_sentinel, "", 0) != -1); 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ActivateMetroChrome() { 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check to see if we're per-user or not. Need to do this since we may 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not have been invoked with --system-level even for a machine install. 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t exe_path[MAX_PATH * 2] = {}; 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetModuleFileName(NULL, exe_path, arraysize(exe_path)); 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_per_user_install = InstallUtil::IsPerUserInstall(exe_path); 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 app_model_id = ShellUtil::GetBrowserModelId( 8805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BrowserDistribution::GetDistribution(), is_per_user_install); 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedComPtr<IApplicationActivationManager> activator; 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = activator.CreateInstance(CLSID_ApplicationActivationManager); 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(hr)) { 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD pid = 0; 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = activator->ActivateApplication( 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) app_model_id.c_str(), L"open", AO_NONE, &pid); 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(ERROR, FAILED(hr)) << "Tried and failed to launch Metro Chrome. " 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "hr=" << std::hex << hr; 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)installer::InstallStatus RegisterDevChrome( 8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const InstallationState& original_state, 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const InstallerState& installer_state, 8975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& setup_exe, 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CommandLine& cmd_line) { 8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserDistribution* chrome_dist = 9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserDistribution::GetSpecificDistribution( 9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserDistribution::CHROME_BROWSER); 9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Only proceed with registering a dev chrome if no real Chrome installation 9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // of the same distribution are present on this system. 9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ProductState* existing_chrome = 9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) original_state.GetProductState(false, 9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserDistribution::CHROME_BROWSER); 9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!existing_chrome) { 9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) existing_chrome = 9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) original_state.GetProductState(true, BrowserDistribution::CHROME_BROWSER); 9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (existing_chrome) { 9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const wchar_t kPleaseUninstallYourChromeMessage[] = 9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) L"You already have a full-installation (non-dev) of %1ls, please " 9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) L"uninstall it first using Add/Remove Programs in the control panel."; 9165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 name(chrome_dist->GetDisplayName()); 9175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 message( 9185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::StringPrintf(kPleaseUninstallYourChromeMessage, name.c_str())); 9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Aborting operation: another installation of " << name 9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << " was found, as a last resort (if the product is not present " 9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "in Add/Remove Programs), try executing: " 9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << existing_chrome->uninstall_command().GetCommandLineString(); 9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessageBox(NULL, message.c_str(), NULL, MB_ICONERROR); 9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return installer::INSTALL_FAILED; 9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_exe( 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_line.GetSwitchValuePath(installer::switches::kRegisterDevChrome)); 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chrome_exe.empty()) 9315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) chrome_exe = setup_exe.DirName().Append(installer::kChromeExe); 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!chrome_exe.IsAbsolute()) 933c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chrome_exe = base::MakeAbsoluteFilePath(chrome_exe); 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallStatus status = installer::FIRST_INSTALL_SUCCESS; 9367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (base::PathExists(chrome_exe)) { 9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Product chrome(chrome_dist); 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the Start menu shortcut and pin it to the taskbar. 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellUtil::ShortcutProperties shortcut_properties(ShellUtil::CURRENT_USER); 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome.AddDefaultShortcutProperties(chrome_exe, &shortcut_properties); 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_properties.set_dual_mode(true); 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_properties.set_pin_to_taskbar(true); 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellUtil::CreateOrUpdateShortcut( 945a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, chrome_dist, 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_properties, ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS); 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register Chrome at user-level and make it default. 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<WorkItemList> delegate_execute_list( 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WorkItem::CreateWorkItemList()); 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::AddDelegateExecuteWorkItems( 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state, chrome_exe.DirName(), Version(), chrome, 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_execute_list.get()); 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_execute_list->Do(); 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShellUtil::CanMakeChromeDefaultUnattended()) { 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellUtil::MakeChromeDefault( 9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome_dist, ShellUtil::CURRENT_USER, chrome_exe.value(), true); 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ShellUtil::ShowMakeChromeDefaultSystemUI(chrome_dist, chrome_exe.value()); 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Path not found: " << chrome_exe.value(); 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = installer::INSTALL_FAILED; 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method processes any command line options that make setup.exe do 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// various tasks other than installation (renaming chrome.exe, showing eula 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// among others). This function returns true if any such command line option 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// has been found and processed (so setup.exe should exit at that point). 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HandleNonInstallCmdLineOptions(const InstallationState& original_state, 9735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& setup_exe, 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CommandLine& cmd_line, 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallerState* installer_state, 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* exit_code) { 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(gab): Add a local |status| variable which each block below sets; 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only determine the |exit_code| from |status| at the end (this will allow 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this method to validate that 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (!handled || status != installer::UNKNOWN_STATUS)). 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool handled = true; 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(tommi): Split these checks up into functions and use a data driven 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // map of switch->function. 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cmd_line.HasSwitch(installer::switches::kUpdateSetupExe)) { 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallStatus status = installer::SETUP_PATCH_FAILED; 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If --update-setup-exe command line option is given, we apply the given 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // patch to current exe, and store the resulting binary in the path 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // specified by --new-setup-exe. But we need to first unpack the file 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // given in --update-setup-exe. 9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::ScopedTempDir temp_path; 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!temp_path.CreateUniqueTempDir()) { 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "Could not create temporary path."; 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 994ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::FilePath compressed_archive(cmd_line.GetSwitchValuePath( 995ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch installer::switches::kUpdateSetupExe)); 996ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch VLOG(1) << "Opening archive " << compressed_archive.value(); 997ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (installer::ArchivePatchHelper::UncompressAndPatch( 998ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch temp_path.path(), 999ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch compressed_archive, 10005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) setup_exe, 1001ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch cmd_line.GetSwitchValuePath(installer::switches::kNewSetupExe))) { 1002ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch status = installer::NEW_VERSION_UPDATED; 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!temp_path.Delete()) { 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PLOG would be nice, but Delete() doesn't leave a meaningful value in 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the Windows last-error code. 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Scheduling temporary path " << temp_path.path().value() 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " for deletion at reboot."; 100968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ScheduleDirectoryForDeletion(temp_path.path()); 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *exit_code = InstallUtil::GetInstallReturnCode(status); 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*exit_code) { 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "setup.exe patching failed."; 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->WriteInstallerResult( 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status, IDS_SETUP_PATCH_FAILED_BASE, NULL); 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We will be exiting normally, so clear the stage indicator. 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->UpdateStage(installer::NO_STAGE); 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_line.HasSwitch(installer::switches::kShowEula)) { 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if we need to show the EULA. If it is passed as a command line 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then the dialog is shown and regardless of the outcome setup exits here. 10245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 inner_frame = 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_line.GetSwitchValueNative(installer::switches::kShowEula); 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *exit_code = ShowEULADialog(inner_frame); 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (installer::EULA_REJECTED != *exit_code) { 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GoogleUpdateSettings::SetEULAConsent( 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original_state, BrowserDistribution::GetDistribution(), true)) { 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateEULASentinel(BrowserDistribution::GetDistribution()); 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For a metro-originated launch, we now need to launch back into metro. 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cmd_line.HasSwitch(installer::switches::kShowEulaForMetro)) 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ActivateMetroChrome(); 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_line.HasSwitch(installer::switches::kConfigureUserSettings)) { 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: Should the work done here, on kConfigureUserSettings, change: 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // kActiveSetupVersion in install_worker.cc needs to be increased for Active 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Setup to invoke this again for all users of this install. 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Product* chrome_install = 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallStatus status = installer::INVALID_STATE_FOR_OPTION; 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chrome_install && installer_state->system_install()) { 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool force = 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_line.HasSwitch(installer::switches::kForceConfigureUserSettings); 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::HandleActiveSetupForBrowser(installer_state->target_path(), 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *chrome_install, force); 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = installer::INSTALL_REPAIRED; 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "chrome_install:" << chrome_install 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ", system_install:" << installer_state->system_install(); 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *exit_code = InstallUtil::GetInstallReturnCode(status); 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_line.HasSwitch(installer::switches::kRegisterDevChrome)) { 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallStatus status = RegisterDevChrome( 10575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) original_state, *installer_state, setup_exe, cmd_line); 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *exit_code = InstallUtil::GetInstallReturnCode(status); 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_line.HasSwitch(installer::switches::kRegisterChromeBrowser)) { 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallStatus status = installer::UNKNOWN_STATUS; 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Product* chrome_install = 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chrome_install) { 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If --register-chrome-browser option is specified, register all 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chrome protocol/file associations, as well as register it as a valid 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // browser for Start Menu->Internet shortcut. This switch will also 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // register Chrome as a valid handler for a set of URL protocols that 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chrome may become the default handler for, either by the user marking 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chrome as the default browser, through the Windows Default Programs 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // control panel settings, or through website use of 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // registerProtocolHandler. These protocols are found in 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ShellUtil::kPotentialProtocolAssociations. 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The --register-url-protocol will additionally register Chrome as a 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // potential handler for the supplied protocol, and is used if a website 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // registers a handler for a protocol not found in 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ShellUtil::kPotentialProtocolAssociations. 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These options should only be used when setup.exe is launched with admin 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // rights. We do not make any user specific changes with this option. 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsUserAnAdmin()); 10805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 chrome_exe(cmd_line.GetSwitchValueNative( 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::switches::kRegisterChromeBrowser)); 10825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 suffix; 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cmd_line.HasSwitch( 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::switches::kRegisterChromeBrowserSuffix)) { 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suffix = cmd_line.GetSwitchValueNative( 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::switches::kRegisterChromeBrowserSuffix); 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cmd_line.HasSwitch(installer::switches::kRegisterURLProtocol)) { 10895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 protocol = cmd_line.GetSwitchValueNative( 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::switches::kRegisterURLProtocol); 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ShellUtil::RegisterChromeForProtocol performs all registration 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // done by ShellUtil::RegisterChromeBrowser, as well as registering 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with Windows as capable of handling the supplied protocol. 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShellUtil::RegisterChromeForProtocol( 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_install->distribution(), chrome_exe, suffix, protocol, 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false)) 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = installer::IN_USE_UPDATED; 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShellUtil::RegisterChromeBrowser(chrome_install->distribution(), 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_exe, suffix, false)) 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = installer::IN_USE_UPDATED; 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Can't register browser - Chrome distribution not found"; 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *exit_code = InstallUtil::GetInstallReturnCode(status); 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_line.HasSwitch(installer::switches::kRenameChromeExe)) { 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If --rename-chrome-exe is specified, we want to rename the executables 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and exit. 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *exit_code = RenameChromeExecutables(original_state, installer_state); 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_line.HasSwitch( 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::switches::kRemoveChromeRegistration)) { 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is almost reverse of --register-chrome-browser option above. 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Here we delete Chrome browser registration. This option should only 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be used when setup.exe is launched with admin rights. We do not 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // make any user specific changes in this option. 11175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 suffix; 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cmd_line.HasSwitch( 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::switches::kRegisterChromeBrowserSuffix)) { 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suffix = cmd_line.GetSwitchValueNative( 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::switches::kRegisterChromeBrowserSuffix); 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallStatus tmp = installer::UNKNOWN_STATUS; 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Product* chrome_install = 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(chrome_install); 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chrome_install) { 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::DeleteChromeRegistrationKeys(*installer_state, 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_install->distribution(), HKEY_LOCAL_MACHINE, suffix, &tmp); 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *exit_code = tmp; 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_line.HasSwitch(installer::switches::kOnOsUpgrade)) { 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Product* chrome_install = 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallStatus status = installer::INVALID_STATE_FOR_OPTION; 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chrome_install) { 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::HandleOsUpgradeForBrowser(*installer_state, 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *chrome_install); 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = installer::INSTALL_REPAIRED; 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Chrome product not found."; 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *exit_code = InstallUtil::GetInstallReturnCode(status); 11442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (cmd_line.HasSwitch(installer::switches::kQueryEULAAcceptance)) { 11452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *exit_code = installer::IsEULAAccepted(installer_state->system_install()); 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_line.HasSwitch(installer::switches::kInactiveUserToast)) { 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Launch the inactive user toast experiment. 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flavor = -1; 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringToInt(cmd_line.GetSwitchValueNative( 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::switches::kInactiveUserToast), &flavor); 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string experiment_group = 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_line.GetSwitchValueASCII(installer::switches::kExperimentGroup); 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(-1, flavor); 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flavor == -1) { 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *exit_code = installer::UNKNOWN_STATUS; 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // This code is called (via setup.exe relaunch) only if a product is known 1158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // to run user experiments, so no check is required. 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Products& products = installer_state->products(); 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Products::const_iterator it = products.begin(); it < products.end(); 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Product& product = **it; 11632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) installer::InactiveUserToastExperiment( 11645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flavor, base::ASCIIToUTF16(experiment_group), product, 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->target_path()); 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Products& products = installer_state->products(); 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Products::const_iterator it = products.begin(); it < products.end(); 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Product& product = **it; 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution* browser_dist = product.distribution(); 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We started as system-level and have been re-launched as user level 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to continue with the toast experiment. 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Version installed_version; 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallUtil::GetChromeVersion(browser_dist, true, &installed_version); 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!installed_version.IsValid()) { 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "No installation of " 11803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) << browser_dist->GetDisplayName() 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " found for system-level toast."; 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 11832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) product.LaunchUserExperiment( 11845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) setup_exe, installer::REENTRY_SYS_UPDATE, true); 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else if (cmd_line.HasSwitch(installer::switches::kPatch)) { 1188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string patch_type_str( 1189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch cmd_line.GetSwitchValueASCII(installer::switches::kPatch)); 1190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::FilePath input_file( 1191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch cmd_line.GetSwitchValuePath(installer::switches::kInputFile)); 1192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::FilePath patch_file( 1193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch cmd_line.GetSwitchValuePath(installer::switches::kPatchFile)); 1194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::FilePath output_file( 1195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch cmd_line.GetSwitchValuePath(installer::switches::kOutputFile)); 1196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (patch_type_str == installer::kCourgette) { 1198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *exit_code = installer::CourgettePatchFiles(input_file, 1199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch patch_file, 1200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch output_file); 1201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else if (patch_type_str == installer::kBsdiff) { 1202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *exit_code = installer::BsdiffPatchFiles(input_file, 1203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch patch_file, 1204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch output_file); 1205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 1206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *exit_code = installer::PATCH_INVALID_ARGUMENTS; 1207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else if (cmd_line.HasSwitch(installer::switches::kReenableAutoupdates)) { 1209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // setup.exe has been asked to attempt to reenable updates for Chrome. 121078901d17b47ef1f8d6d0a89eaf37f9523ba1de85Ben Murdoch bool updates_enabled = GoogleUpdateSettings::ReenableAutoupdates(); 1211effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch *exit_code = updates_enabled ? installer::REENABLE_UPDATES_SUCCEEDED : 1212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch installer::REENABLE_UPDATES_FAILED; 1213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else { 1214ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch handled = false; 1215ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1216ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1217ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return handled; 1218ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 1219ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1220ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool ShowRebootDialog() { 1221ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Get a token for this process. 1222ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch HANDLE token; 1223ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!OpenProcessToken(GetCurrentProcess(), 1224ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 1225ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch &token)) { 1226ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LOG(ERROR) << "Failed to open token."; 1227ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return false; 1228ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1229ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1230ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Use a ScopedHandle to keep track of and eventually close our handle. 1231ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // TODO(robertshield): Add a Receive() method to base's ScopedHandle. 1232ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::win::ScopedHandle scoped_handle(token); 1233ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1234ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Get the LUID for the shutdown privilege. 1235ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch TOKEN_PRIVILEGES tkp = {0}; 1236ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid); 1237ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch tkp.PrivilegeCount = 1; 1238ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 1239ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1240ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Get the shutdown privilege for this process. 1241ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch AdjustTokenPrivileges(token, FALSE, &tkp, 0, 1242ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch reinterpret_cast<PTOKEN_PRIVILEGES>(NULL), 0); 1243ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (GetLastError() != ERROR_SUCCESS) { 1244ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LOG(ERROR) << "Unable to get shutdown privileges."; 1245ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return false; 1246ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1247ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1248ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Popup a dialog that will prompt to reboot using the default system message. 1249ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // TODO(robertshield): Add a localized, more specific string to the prompt. 1250ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch RestartDialog(NULL, NULL, EWX_REBOOT | EWX_FORCEIFHUNG); 1251ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return true; 1252ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 1253ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1254ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Returns the Custom information for the client identified by the exe path 1255ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// passed in. This information is used for crash reporting. 1256ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochgoogle_breakpad::CustomClientInfo* GetCustomInfo(const wchar_t* exe_path) { 12575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 product; 12585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 version; 1259ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch scoped_ptr<FileVersionInfo> version_info( 1260ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch FileVersionInfo::CreateFileVersionInfo(base::FilePath(exe_path))); 1261ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (version_info.get()) { 1262ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch version = version_info->product_version(); 1263ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch product = version_info->product_short_name(); 1264ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1265ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1266ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (version.empty()) 1267ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch version = L"0.1.0.0"; 1268ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1269ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (product.empty()) 1270ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch product = L"Chrome Installer"; 1271ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1272ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch static google_breakpad::CustomInfoEntry ver_entry(L"ver", version.c_str()); 1273ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch static google_breakpad::CustomInfoEntry prod_entry(L"prod", product.c_str()); 1274ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch static google_breakpad::CustomInfoEntry plat_entry(L"plat", L"Win32"); 1275ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch static google_breakpad::CustomInfoEntry type_entry(L"ptype", 1276ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch L"Chrome Installer"); 1277ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch static google_breakpad::CustomInfoEntry entries[] = { 1278ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ver_entry, prod_entry, plat_entry, type_entry }; 1279ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch static google_breakpad::CustomClientInfo custom_info = { 1280ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch entries, arraysize(entries) }; 1281ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return &custom_info; 1282ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 1283ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1284ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Initialize crash reporting for this process. This involves connecting to 1285ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// breakpad, etc. 12865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<google_breakpad::ExceptionHandler> InitializeCrashReporting( 1287ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool system_install) { 1288ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Only report crashes if the user allows it. 1289ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!GoogleUpdateSettings::GetCollectStatsConsent()) 12905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return scoped_ptr<google_breakpad::ExceptionHandler>(); 1291ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1292ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Get the alternate dump directory. We use the temp path. 1293ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::FilePath temp_directory; 1294a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::GetTempDir(&temp_directory) || temp_directory.empty()) 12955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return scoped_ptr<google_breakpad::ExceptionHandler>(); 1296ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1297ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch wchar_t exe_path[MAX_PATH * 2] = {0}; 1298ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch GetModuleFileName(NULL, exe_path, arraysize(exe_path)); 1299ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1300ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Build the pipe name. It can be either: 1301ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // System-wide install: "NamedPipe\GoogleCrashServices\S-1-5-18" 1302ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Per-user install: "NamedPipe\GoogleCrashServices\<user SID>" 13035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 user_sid = kSystemPrincipalSid; 1304ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1305ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!system_install) { 1306ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!base::win::GetUserSidString(&user_sid)) { 13075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return scoped_ptr<google_breakpad::ExceptionHandler>(); 1308ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1309ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1310ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 13115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 pipe_name = kGoogleUpdatePipeName; 1312ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pipe_name += user_sid; 1313ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 13145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return scoped_ptr<google_breakpad::ExceptionHandler>( 1315ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch new google_breakpad::ExceptionHandler( 1316ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch temp_directory.value(), NULL, NULL, NULL, 1317ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch google_breakpad::ExceptionHandler::HANDLER_ALL, kLargerDumpType, 13185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pipe_name.c_str(), GetCustomInfo(exe_path))); 1319ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 1320ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Uninstalls multi-install Chrome Frame if the current operation is a 1322a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// multi-install install or update. The operation is performed directly rather 1323a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// than delegated to the existing install since there is no facility in older 1324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// versions of setup.exe to uninstall GCF without touching the binaries. The 1325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// binaries will be uninstalled during later processing if they are not in-use 1326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// (see UninstallBinariesIfUnused). |original_state| and |installer_state| are 1327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// updated to reflect the state of the world following the operation. 1328a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void UninstallMultiChromeFrameIfPresent(const CommandLine& cmd_line, 1329a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const MasterPreferences& prefs, 1330a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) InstallationState* original_state, 1331a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) InstallerState* installer_state) { 1332a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Early exit if not installing or updating multi-install product(s). 1333a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (installer_state->operation() != InstallerState::MULTI_INSTALL && 1334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) installer_state->operation() != InstallerState::MULTI_UPDATE) { 1335a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 1336a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Early exit if Chrome Frame is not present as multi-install. 1339a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const ProductState* chrome_frame_state = 1340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) original_state->GetProductState(installer_state->system_install(), 1341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BrowserDistribution::CHROME_FRAME); 1342a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!chrome_frame_state || !chrome_frame_state->is_multi_install()) 1343a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 1344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOG(INFO) << "Uninstalling multi-install Chrome Frame."; 1346a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) installer_state->UpdateStage(installer::UNINSTALLING_CHROME_FRAME); 1347a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1348a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Uninstall Chrome Frame without touching the multi-install binaries. 1349a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Simulate the uninstall as coming from the installed version. 1350a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const CommandLine& uninstall_cmd(chrome_frame_state->uninstall_command()); 1351a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MasterPreferences uninstall_prefs(uninstall_cmd); 1352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) InstallerState uninstall_state; 1353a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uninstall_state.Initialize(uninstall_cmd, uninstall_prefs, *original_state); 1354010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Post M32, uninstall_prefs and uninstall_state won't have Chrome Frame in 1355010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // them since they've lost the power to do Chrome Frame installs. 1356010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const Product* chrome_frame_product = uninstall_state.AddProductFromState( 1357010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) BrowserDistribution::CHROME_FRAME, *chrome_frame_state); 1358a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (chrome_frame_product) { 1359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // No shared state should be left behind. 1360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const bool remove_all = true; 1361a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Don't accept no for an answer. 1362a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const bool force_uninstall = true; 1363a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) installer::InstallStatus uninstall_status = 1364a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) installer::UninstallProduct(*original_state, uninstall_state, 1365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uninstall_cmd.GetProgram(), 1366a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) *chrome_frame_product, remove_all, 1367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) force_uninstall, cmd_line); 1368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VLOG(1) << "Uninstallation of Chrome Frame returned status " 1370a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << uninstall_status; 1371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 1372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOG(ERROR) << "Chrome Frame not found for uninstall."; 1373a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1374a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1375a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Refresh state for the continuation of the original install/update. 1376a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) original_state->Initialize(); 1377a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) installer_state->Initialize(cmd_line, prefs, *original_state); 1378a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1379a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1380ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} // namespace 1381ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1382ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace installer { 1383ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 138468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)InstallStatus InstallProductsHelper( 1385ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const InstallationState& original_state, 13865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& setup_exe, 1387ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const CommandLine& cmd_line, 1388ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const MasterPreferences& prefs, 1389ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const InstallerState& installer_state, 139068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::FilePath* installer_directory, 139168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ArchiveType* archive_type, 1392ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool* delegated_to_existing) { 1393ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(archive_type); 1394ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(delegated_to_existing); 1395ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const bool system_install = installer_state.system_install(); 139668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) InstallStatus install_status = UNKNOWN_STATUS; 1397ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1398ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Drop to background processing mode if the process was started below the 1399ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // normal process priority class. 140068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool entered_background_mode = AdjustProcessPriority(); 1401ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch VLOG_IF(1, entered_background_mode) << "Entered background processing mode."; 1402ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1403ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Create a temp folder where we will unpack Chrome archive. If it fails, 1404ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // then we are doomed, so return immediately and no cleanup is required. 140568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) SelfCleaningTempDir temp_path; 1406ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::FilePath unpack_path; 1407ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!CreateTemporaryAndUnpackDirectories(installer_state, &temp_path, 1408ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch &unpack_path)) { 140968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) installer_state.WriteInstallerResult(TEMP_DIR_FAILED, 1410ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch IDS_INSTALL_TEMP_DIR_FAILED_BASE, 1411ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch NULL); 141268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return TEMP_DIR_FAILED; 1413ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1414ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1415ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Uncompress and optionally patch the archive if an uncompressed archive was 1416ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // not specified on the command line and a compressed archive is found. 141768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) *archive_type = UNKNOWN_ARCHIVE_TYPE; 1418ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::FilePath uncompressed_archive(cmd_line.GetSwitchValuePath( 141968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) switches::kUncompressedArchive)); 1420ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (uncompressed_archive.empty()) { 142168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<ArchivePatchHelper> archive_helper( 14225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChromeArchiveHelper(setup_exe, cmd_line, installer_state, 14235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) unpack_path)); 1424ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (archive_helper) { 1425ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch VLOG(1) << "Installing Chrome from compressed archive " 1426ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << archive_helper->compressed_archive().value(); 1427ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!UncompressAndPatchChromeArchive(original_state, 1428ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch installer_state, 1429ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch archive_helper.get(), 1430ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch archive_type, 1431ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch &install_status)) { 143268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK_NE(install_status, UNKNOWN_STATUS); 1433ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return install_status; 1434ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1435ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch uncompressed_archive = archive_helper->target(); 1436ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(!uncompressed_archive.empty()); 1437ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1438ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1439ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1440ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Check for an uncompressed archive alongside the current executable if one 1441ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // was not given or generated. 14425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (uncompressed_archive.empty()) 14435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uncompressed_archive = setup_exe.DirName().Append(kChromeArchive); 1444ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 144568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (*archive_type == UNKNOWN_ARCHIVE_TYPE) { 1446ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // An archive was not uncompressed or patched above. 1447ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (uncompressed_archive.empty() || 1448ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch !base::PathExists(uncompressed_archive)) { 1449ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LOG(ERROR) << "Cannot install Chrome without an uncompressed archive."; 1450ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch installer_state.WriteInstallerResult( 145168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) INVALID_ARCHIVE, IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); 145268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return INVALID_ARCHIVE; 1453ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 145468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) *archive_type = FULL_ARCHIVE_TYPE; 1455ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1456ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1457ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Unpack the uncompressed archive. 1458ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (LzmaUtil::UnPackArchive(uncompressed_archive.value(), 1459ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch unpack_path.value(), 1460ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch NULL)) { 1461ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch installer_state.WriteInstallerResult( 1462f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) UNPACKING_FAILED, 1463ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, 1464ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch NULL); 1465f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return UNPACKING_FAILED; 1466ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1467ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1468ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch VLOG(1) << "unpacked to " << unpack_path.value(); 1469ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::FilePath src_path( 147068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) unpack_path.Append(kInstallSourceChromeDir)); 1471ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch scoped_ptr<Version> 147268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) installer_version(GetMaxVersionFromArchiveDir(src_path)); 1473ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!installer_version.get()) { 1474ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LOG(ERROR) << "Did not find any valid version in installer."; 147568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) install_status = INVALID_ARCHIVE; 1476ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch installer_state.WriteInstallerResult(install_status, 1477ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); 1478ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else { 1479ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch VLOG(1) << "version to install: " << installer_version->GetString(); 1480ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool proceed_with_installation = true; 1481ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1482ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (installer_state.operation() == InstallerState::MULTI_INSTALL) { 1483ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // This is a new install of a multi-install product. Rather than give up 1484ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // in case a higher version of the binaries (including a single-install 1485ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // of Chrome, which can safely be migrated to multi-install by way of 1486ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // CheckMultiInstallConditions) is already installed, delegate to the 1487ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // installed setup.exe to install the product at hand. 14885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath existing_setup_exe; 1489ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (GetExistingHigherInstaller(original_state, system_install, 14905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *installer_version, &existing_setup_exe)) { 1491ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch VLOG(1) << "Deferring to existing installer."; 149268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) installer_state.UpdateStage(DEFERRING_TO_HIGHER_VERSION); 14935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (DeferToExistingInstall(existing_setup_exe, cmd_line, 14945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) installer_state, temp_path.path(), 14955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &install_status)) { 1496ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch *delegated_to_existing = true; 1497ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return install_status; 1498ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1499ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1500ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1501ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1502ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch uint32 higher_products = 0; 1503ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch COMPILE_ASSERT( 1504ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch sizeof(higher_products) * 8 > BrowserDistribution::NUM_TYPES, 1505ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch too_many_distribution_types_); 1506ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const Products& products = installer_state.products(); 1507ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (Products::const_iterator it = products.begin(); it < products.end(); 1508ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ++it) { 1509ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const Product& product = **it; 1510ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const ProductState* product_state = 1511ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch original_state.GetProductState(system_install, 1512ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch product.distribution()->GetType()); 1513ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (product_state != NULL && 1514ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch (product_state->version().CompareTo(*installer_version) > 0)) { 1515ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LOG(ERROR) << "Higher version of " 15163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) << product.distribution()->GetDisplayName() 1517ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << " is already installed."; 1518ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch higher_products |= (1 << product.distribution()->GetType()); 1519ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1520ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1522ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (higher_products != 0) { 1523ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch COMPILE_ASSERT(BrowserDistribution::NUM_TYPES == 4, 1524ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch add_support_for_new_products_here_); 1525ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const uint32 kBrowserBit = 1 << BrowserDistribution::CHROME_BROWSER; 1526ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const uint32 kAppHostBit = 1 << BrowserDistribution::CHROME_APP_HOST; 1527ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int message_id = 0; 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1529ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch proceed_with_installation = false; 153068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) install_status = HIGHER_VERSION_EXISTS; 1531ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch switch (higher_products) { 1532ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch case kBrowserBit: 1533ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch message_id = IDS_INSTALL_HIGHER_VERSION_BASE; 1534ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch break; 1535ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch default: 1536ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch message_id = IDS_INSTALL_HIGHER_VERSION_APP_LAUNCHER_BASE; 1537ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch break; 1538ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1540ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch installer_state.WriteInstallerResult(install_status, message_id, NULL); 1541ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1543ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch proceed_with_installation = 1544ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch proceed_with_installation && 1545ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch CheckGroupPolicySettings(original_state, installer_state, 1546ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch *installer_version, &install_status); 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1548ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (proceed_with_installation) { 1549ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If Google Update is absent at user-level, install it using the 1550ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Google Update installer from an existing system-level installation. 1551ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // This is for quick-enable App Host install from a system-level 1552ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Chrome Binaries installation. 1553ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!system_install && installer_state.ensure_google_update_present()) { 1554ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!google_update::EnsureUserLevelGoogleUpdatePresent()) { 1555ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LOG(ERROR) << "Failed to install Google Update"; 1556ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch proceed_with_installation = false; 155768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) install_status = INSTALL_OF_GOOGLE_UPDATE_FAILED; 1558ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch installer_state.WriteInstallerResult(install_status, 0, NULL); 1559ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1560ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 156168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 1562ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1564ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (proceed_with_installation) { 1565ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::FilePath prefs_source_path(cmd_line.GetSwitchValueNative( 156668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) switches::kInstallerData)); 156768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) install_status = InstallOrUpdateProduct( 15685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) original_state, installer_state, setup_exe, uncompressed_archive, 15695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) temp_path.path(), src_path, prefs_source_path, prefs, 15705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *installer_version); 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1572ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int install_msg_base = IDS_INSTALL_FAILED_BASE; 15735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 chrome_exe; 15745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 quoted_chrome_exe; 157568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (install_status == SAME_VERSION_REPAIR_FAILED) { 15765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_BASE; 157768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else if (install_status != INSTALL_FAILED) { 1578ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (installer_state.target_path().empty()) { 1579ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If we failed to construct install path, it means the OS call to 1580ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // get %ProgramFiles% or %AppData% failed. Report this as failure. 1581ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch install_msg_base = IDS_INSTALL_OS_ERROR_BASE; 158268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) install_status = OS_ERROR; 1583ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else { 158468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) chrome_exe = installer_state.target_path().Append(kChromeExe).value(); 1585ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch quoted_chrome_exe = L"\"" + chrome_exe + L"\""; 1586ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch install_msg_base = 0; 1587ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1588ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 159068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) installer_state.UpdateStage(FINISHING); 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1592ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Only do Chrome-specific stuff (like launching the browser) if 1593ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Chrome was specifically requested (rather than being upgraded as 1594ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // part of a multi-install). 1595ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const Product* chrome_install = prefs.install_chrome() ? 1596ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER) : 1597ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch NULL; 15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1599ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool do_not_register_for_update_launch = false; 1600ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (chrome_install) { 160168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) prefs.GetBool(master_preferences::kDoNotRegisterForUpdateLaunch, 160268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) &do_not_register_for_update_launch); 1603ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else { 1604ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch do_not_register_for_update_launch = true; // Never register. 1605ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1607ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool write_chrome_launch_string = 1608ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch (!do_not_register_for_update_launch && 160968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) install_status != IN_USE_UPDATED); 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1611ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch installer_state.WriteInstallerResult(install_status, install_msg_base, 1612ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch write_chrome_launch_string ? "ed_chrome_exe : NULL); 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 161468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (install_status == FIRST_INSTALL_SUCCESS) { 1615ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch VLOG(1) << "First install successful."; 1616ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (chrome_install) { 1617ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // We never want to launch Chrome in system level install mode. 1618ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool do_not_launch_chrome = false; 161968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) prefs.GetBool(master_preferences::kDoNotLaunchChrome, 162068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) &do_not_launch_chrome); 1621ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!system_install && !do_not_launch_chrome) 1622ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch chrome_install->LaunchChrome(installer_state.target_path()); 1623ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 162468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else if ((install_status == NEW_VERSION_UPDATED) || 162568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) (install_status == IN_USE_UPDATED)) { 1626ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const Product* chrome = installer_state.FindProduct( 1627ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch BrowserDistribution::CHROME_BROWSER); 1628ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (chrome != NULL) { 16295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_NE(chrome_exe, base::string16()); 163068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) RemoveChromeLegacyRegistryKeys(chrome->distribution(), chrome_exe); 1631ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1632ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1633ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1634ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1636ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // There might be an experiment (for upgrade usually) that needs to happen. 1637ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // An experiment's outcome can include chrome's uninstallation. If that is 1638ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // the case we would not do that directly at this point but in another 1639ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // instance of setup.exe 1640ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // 1641ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // There is another way to reach this same function if this is a system 1642ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // level install. See HandleNonInstallCmdLineOptions(). 1643ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch { 1644ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If installation failed, use the path to the currently running setup. 1645ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If installation succeeded, use the path to setup in the installer dir. 16465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath setup_path(setup_exe); 1647ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (InstallUtil::GetInstallReturnCode(install_status) == 0) { 1648ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch setup_path = installer_state.GetInstallerDirectory(*installer_version) 1649ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch .Append(setup_path.BaseName()); 1650ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1651ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const Products& products = installer_state.products(); 1652ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (Products::const_iterator it = products.begin(); it < products.end(); 1653ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ++it) { 1654ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const Product& product = **it; 16555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) product.LaunchUserExperiment(setup_path, install_status, system_install); 16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // If installation completed successfully, return the path to the directory 166068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // containing the newly installed setup.exe and uncompressed archive if the 166168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // caller requested it. 166268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (installer_directory && 166368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) InstallUtil::GetInstallReturnCode(install_status) == 0) { 166468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) *installer_directory = 166568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) installer_state.GetInstallerDirectory(*installer_version); 166668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 166768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 1668ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // temp_path's dtor will take care of deleting or scheduling itself for 1669ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // deletion at reboot when this scope closes. 1670ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch VLOG(1) << "Deleting temporary directory " << temp_path.path().value(); 16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1672ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return install_status; 16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} // namespace installer 16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, 16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t* command_line, int show_command) { 1679a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Check to see if the CPU is supported before doing anything else. There's 1680a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // very little than can safely be accomplished if the CPU isn't supported 1681a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // since dependent libraries (e.g., base) may use invalid instructions. 1682a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!installer::IsProcessorSupported()) 1683a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return installer::CPU_NOT_SUPPORTED; 1684a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The exit manager is in charge of calling the dtors of singletons. 16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AtExitManager exit_manager; 16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine::Init(0, NULL); 16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1689e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // install_util uses chrome paths. 1690e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch chrome::RegisterPathProvider(); 1691e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess(); 16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InitInstallerLogging(prefs); 16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); 16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Command Line: " << cmd_line.GetCommandLineString(); 16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "multi install is " << prefs.is_multi_install(); 16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool system_install = false; 17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs.GetBool(installer::master_preferences::kSystemLevel, &system_install); 17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "system install is " << system_install; 17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<google_breakpad::ExceptionHandler> breakpad( 17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitializeCrashReporting(system_install)); 17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallationState original_state; 17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original_state.Initialize(); 17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallerState installer_state; 17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state.Initialize(cmd_line, prefs, original_state); 17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool is_uninstall = cmd_line.HasSwitch(installer::switches::kUninstall); 17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check to make sure current system is WinXP or later. If not, log 17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // error message and get out. 17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!InstallUtil::IsOSSupported()) { 17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Chrome only supports Windows XP or later."; 17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state.WriteInstallerResult( 17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::OS_NOT_SUPPORTED, IDS_INSTALL_OS_NOT_SUPPORTED_BASE, NULL); 17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return installer::OS_NOT_SUPPORTED; 17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize COM for use later. 17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedCOMInitializer com_initializer; 17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!com_initializer.succeeded()) { 17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state.WriteInstallerResult( 17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::OS_ERROR, IDS_INSTALL_OS_ERROR_BASE, NULL); 17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return installer::OS_ERROR; 17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some command line options don't work with SxS install/uninstall 17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (InstallUtil::IsChromeSxSProcess()) { 17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (system_install || 17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs.is_multi_install() || 17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_line.HasSwitch(installer::switches::kForceUninstall) || 17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_line.HasSwitch(installer::switches::kMakeChromeDefault) || 17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_line.HasSwitch(installer::switches::kRegisterChromeBrowser) || 17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_line.HasSwitch(installer::switches::kRemoveChromeRegistration) || 17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_line.HasSwitch(installer::switches::kInactiveUserToast) || 17395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { 17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return installer::SXS_OPTION_NOT_SUPPORTED; 17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Some command line options are no longer supported and must error out. 17455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (installer::ContainsUnsupportedSwitch(cmd_line)) 17465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return installer::UNSUPPORTED_OPTION; 17475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 17485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // A variety of installer operations require the path to the current 17495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // executable. Get it once here for use throughout these operations. Note that 17505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the path service is the authoritative source for this path. One might think 17515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // that CommandLine::GetProgram would suffice, but it won't since 17525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // CreateProcess may have been called with a command line that is somewhat 17535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // ambiguous (e.g., an unquoted path with spaces, or a path lacking the file 17545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // extension), in which case CommandLineToArgv will not yield an argv with the 17555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // true path to the program at position 0. 17565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath setup_exe; 17575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!PathService::Get(base::FILE_EXE, &setup_exe)) { 17585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 17595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return installer::OS_ERROR; 17605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 17615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int exit_code = 0; 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HandleNonInstallCmdLineOptions( 17645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) original_state, setup_exe, cmd_line, &installer_state, &exit_code)) { 17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return exit_code; 17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (system_install && !IsUserAnAdmin()) { 17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::win::GetVersion() >= base::win::VERSION_VISTA && 17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !cmd_line.HasSwitch(installer::switches::kRunAsAdmin)) { 17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine new_cmd(CommandLine::NO_PROGRAM); 17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_cmd.AppendArguments(cmd_line, true); 17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Append --run-as-admin flag to let the new instance of setup.exe know 17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that we already tried to launch ourselves as admin. 17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_cmd.AppendSwitch(installer::switches::kRunAsAdmin); 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If system_install became true due to an environment variable, append 17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it to the command line here since env vars may not propagate past the 17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // elevation. 17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!new_cmd.HasSwitch(installer::switches::kSystemLevel)) 17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_cmd.AppendSwitch(installer::switches::kSystemLevel); 17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD exit_code = installer::UNKNOWN_STATUS; 17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return exit_code; 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Non admin user can not install system level Chrome."; 17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state.WriteInstallerResult(installer::INSUFFICIENT_RIGHTS, 17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_INSTALL_INSUFFICIENT_RIGHTS_BASE, NULL); 17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return installer::INSUFFICIENT_RIGHTS; 17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1793a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) UninstallMultiChromeFrameIfPresent(cmd_line, prefs, 1794a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &original_state, &installer_state); 1795a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 179668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::FilePath installer_directory; 17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallStatus install_status = installer::UNKNOWN_STATUS; 1798a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If --uninstall option is given, uninstall the identified product(s) 1799a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (is_uninstall) { 1800a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) install_status = 18015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UninstallProducts(original_state, installer_state, setup_exe, cmd_line); 1802a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 1803a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If --uninstall option is not specified, we assume it is install case. 18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) install_status = 18055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InstallProducts(original_state, setup_exe, cmd_line, prefs, 18065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &installer_state, &installer_directory); 18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Validate that the machine is now in a good state following the operation. 18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(grt): change this to log at DFATAL once we're convinced that the 18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // validator handles all cases properly. 18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallationValidator::InstallationType installation_type = 18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallationValidator::NO_PRODUCTS; 18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(ERROR, 18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !InstallationValidator::ValidateInstallationType(system_install, 18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &installation_type)); 18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int return_code = 0; 18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // MSI demands that custom actions always return 0 (ERROR_SUCCESS) or it will 18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // rollback the action. If we're uninstalling we want to avoid this, so always 18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // report success, squashing any more informative return codes. 182268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!(installer_state.is_msi() && is_uninstall)) { 18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT 18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to pass through, since this is only returned on uninstall which is 18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // never invoked directly by Google Update. 18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_code = InstallUtil::GetInstallReturnCode(install_status); 182768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 182868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Installation complete, returning: " << return_code; 18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return return_code; 18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1833