Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <windows.h> | 5 #include <windows.h> |
| 6 #include <msi.h> | 6 #include <msi.h> |
| 7 #include <shellapi.h> | 7 #include <shellapi.h> |
| 8 #include <shlobj.h> | 8 #include <shlobj.h> |
| 9 | 9 |
| 10 #include <string> | 10 #include <string> |
| 11 | 11 |
| 12 #include "base/at_exit.h" | 12 #include "base/at_exit.h" |
| 13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
| 14 #include "base/command_line.h" | 14 #include "base/command_line.h" |
| 15 #include "base/file_util.h" | 15 #include "base/file_util.h" |
| 16 #include "base/file_version_info.h" | 16 #include "base/file_version_info.h" |
| 17 #include "base/path_service.h" | 17 #include "base/path_service.h" |
| 18 #include "base/process_util.h" | 18 #include "base/process_util.h" |
| 19 #include "base/string_number_conversions.h" | 19 #include "base/string_number_conversions.h" |
| 20 #include "base/string_util.h" | 20 #include "base/string_util.h" |
| 21 #include "base/utf_string_conversions.h" | 21 #include "base/utf_string_conversions.h" |
| 22 #include "base/values.h" | 22 #include "base/values.h" |
| 23 #include "base/win/registry.h" | |
| 23 #include "base/win/scoped_handle.h" | 24 #include "base/win/scoped_handle.h" |
| 24 #include "base/win/win_util.h" | 25 #include "base/win/win_util.h" |
| 25 #include "base/win/windows_version.h" | 26 #include "base/win/windows_version.h" |
| 26 #include "breakpad/src/client/windows/handler/exception_handler.h" | 27 #include "breakpad/src/client/windows/handler/exception_handler.h" |
| 27 #include "chrome/common/chrome_switches.h" | 28 #include "chrome/common/chrome_switches.h" |
| 28 #include "chrome/installer/setup/chrome_frame_ready_mode.h" | 29 #include "chrome/installer/setup/chrome_frame_ready_mode.h" |
| 29 #include "chrome/installer/setup/install.h" | 30 #include "chrome/installer/setup/install.h" |
| 30 #include "chrome/installer/setup/setup_constants.h" | 31 #include "chrome/installer/setup/setup_constants.h" |
| 31 #include "chrome/installer/setup/setup_util.h" | 32 #include "chrome/installer/setup/setup_util.h" |
| 32 #include "chrome/installer/setup/uninstall.h" | 33 #include "chrome/installer/setup/uninstall.h" |
| 33 #include "chrome/installer/util/browser_distribution.h" | 34 #include "chrome/installer/util/browser_distribution.h" |
| 35 #include "chrome/installer/util/channel_info.h" | |
| 34 #include "chrome/installer/util/delete_after_reboot_helper.h" | 36 #include "chrome/installer/util/delete_after_reboot_helper.h" |
| 35 #include "chrome/installer/util/delete_tree_work_item.h" | 37 #include "chrome/installer/util/delete_tree_work_item.h" |
| 36 #include "chrome/installer/util/google_update_settings.h" | 38 #include "chrome/installer/util/google_update_settings.h" |
| 37 #include "chrome/installer/util/google_update_constants.h" | 39 #include "chrome/installer/util/google_update_constants.h" |
| 38 #include "chrome/installer/util/helper.h" | 40 #include "chrome/installer/util/helper.h" |
| 39 #include "chrome/installer/util/html_dialog.h" | 41 #include "chrome/installer/util/html_dialog.h" |
| 40 #include "chrome/installer/util/install_util.h" | 42 #include "chrome/installer/util/install_util.h" |
| 41 #include "chrome/installer/util/installer_state.h" | 43 #include "chrome/installer/util/installer_state.h" |
| 42 #include "chrome/installer/util/installation_state.h" | 44 #include "chrome/installer/util/installation_state.h" |
| 43 #include "chrome/installer/util/l10n_string_util.h" | 45 #include "chrome/installer/util/l10n_string_util.h" |
| 44 #include "chrome/installer/util/logging_installer.h" | 46 #include "chrome/installer/util/logging_installer.h" |
| 45 #include "chrome/installer/util/lzma_util.h" | 47 #include "chrome/installer/util/lzma_util.h" |
| 46 #include "chrome/installer/util/master_preferences.h" | 48 #include "chrome/installer/util/master_preferences.h" |
| 47 #include "chrome/installer/util/master_preferences_constants.h" | 49 #include "chrome/installer/util/master_preferences_constants.h" |
| 48 #include "chrome/installer/util/package_properties.h" | |
| 49 #include "chrome/installer/util/shell_util.h" | 50 #include "chrome/installer/util/shell_util.h" |
| 50 #include "chrome/installer/util/util_constants.h" | 51 #include "chrome/installer/util/util_constants.h" |
| 51 | 52 |
| 52 #include "installer_util_strings.h" // NOLINT | 53 #include "installer_util_strings.h" // NOLINT |
| 53 | 54 |
| 54 using installer::InstallerState; | 55 using installer::InstallerState; |
| 55 using installer::InstallationState; | 56 using installer::InstallationState; |
| 56 using installer::Product; | 57 using installer::Product; |
| 57 using installer::ProductPackageMapping; | |
| 58 using installer::ProductState; | 58 using installer::ProductState; |
| 59 using installer::Products; | 59 using installer::Products; |
| 60 using installer::Package; | |
| 61 using installer::Packages; | |
| 62 using installer::MasterPreferences; | 60 using installer::MasterPreferences; |
| 63 | 61 |
| 64 const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices"; | 62 const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices"; |
| 65 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; | 63 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; |
| 66 const wchar_t kSystemPrincipalSid[] = L"S-1-5-18"; | 64 const wchar_t kSystemPrincipalSid[] = L"S-1-5-18"; |
| 67 | 65 |
| 68 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>( | 66 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>( |
| 69 MiniDumpWithProcessThreadData | // Get PEB and TEB. | 67 MiniDumpWithProcessThreadData | // Get PEB and TEB. |
| 70 MiniDumpWithUnloadedModules | // Get unloaded modules when available. | 68 MiniDumpWithUnloadedModules | // Get unloaded modules when available. |
| 71 MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack. | 69 MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack. |
| 72 | 70 |
| 73 namespace { | 71 namespace { |
| 74 | 72 |
| 75 // This method unpacks and uncompresses the given archive file. For Chrome | 73 // This method unpacks and uncompresses the given archive file. For Chrome |
| 76 // install we are creating a uncompressed archive that contains all the files | 74 // install we are creating a uncompressed archive that contains all the files |
| 77 // needed for the installer. This uncompressed archive is later compressed. | 75 // needed for the installer. This uncompressed archive is later compressed. |
| 78 // | 76 // |
| 79 // This method first uncompresses archive specified by parameter "archive" | 77 // This method first uncompresses archive specified by parameter "archive" |
| 80 // and assumes that it will result in an uncompressed full archive file | 78 // and assumes that it will result in an uncompressed full archive file |
| 81 // (chrome.7z) or uncompressed archive patch file (chrome_patch.diff). If it | 79 // (chrome.7z) or uncompressed archive patch file (chrome_patch.diff). If it |
| 82 // is patch file, it is applied to the old archive file that should be | 80 // is patch file, it is applied to the old archive file that should be |
| 83 // present on the system already. As the final step the new archive file | 81 // present on the system already. As the final step the new archive file |
| 84 // is unpacked in the path specified by parameter "output_directory". | 82 // is unpacked in the path specified by parameter "output_directory". |
| 85 DWORD UnPackArchive(const FilePath& archive, | 83 DWORD UnPackArchive(const FilePath& archive, |
| 86 const Package& installation, | 84 const InstallerState& installer_state, |
| 87 const FilePath& temp_path, | 85 const FilePath& temp_path, |
| 88 const FilePath& output_directory, | 86 const FilePath& output_directory, |
| 89 bool& incremental_install) { | 87 bool& incremental_install) { |
| 90 // First uncompress the payload. This could be a differential | 88 // First uncompress the payload. This could be a differential |
| 91 // update (patch.7z) or full archive (chrome.7z). If this uncompress fails | 89 // update (patch.7z) or full archive (chrome.7z). If this uncompress fails |
| 92 // return with error. | 90 // return with error. |
| 93 std::wstring unpacked_file; | 91 std::wstring unpacked_file; |
| 94 int32 ret = LzmaUtil::UnPackArchive(archive.value(), temp_path.value(), | 92 int32 ret = LzmaUtil::UnPackArchive(archive.value(), temp_path.value(), |
| 95 &unpacked_file); | 93 &unpacked_file); |
| 96 if (ret != NO_ERROR) | 94 if (ret != NO_ERROR) |
| 97 return ret; | 95 return ret; |
| 98 | 96 |
| 99 FilePath uncompressed_archive(temp_path.Append(installer::kChromeArchive)); | 97 FilePath uncompressed_archive(temp_path.Append(installer::kChromeArchive)); |
| 100 scoped_ptr<Version> archive_version( | 98 scoped_ptr<Version> archive_version( |
| 101 installer::GetVersionFromArchiveDir(installation.path())); | 99 installer::GetVersionFromArchiveDir(installer_state.target_path())); |
| 102 | 100 |
| 103 // Check if this is differential update and if it is, patch it to the | 101 // Check if this is differential update and if it is, patch it to the |
| 104 // installer archive that should already be on the machine. We assume | 102 // installer archive that should already be on the machine. We assume |
| 105 // it is a differential installer if chrome.7z is not found. | 103 // it is a differential installer if chrome.7z is not found. |
| 106 if (!file_util::PathExists(uncompressed_archive)) { | 104 if (!file_util::PathExists(uncompressed_archive)) { |
| 107 incremental_install = true; | 105 incremental_install = true; |
| 108 VLOG(1) << "Differential patch found. Applying to existing archive."; | 106 VLOG(1) << "Differential patch found. Applying to existing archive."; |
| 109 if (!archive_version.get()) { | 107 if (!archive_version.get()) { |
| 110 LOG(ERROR) << "Can not use differential update when Chrome is not " | 108 LOG(ERROR) << "Can not use differential update when Chrome is not " |
| 111 << "installed on the system."; | 109 << "installed on the system."; |
| 112 return installer::CHROME_NOT_INSTALLED; | 110 return installer::CHROME_NOT_INSTALLED; |
| 113 } | 111 } |
| 114 | 112 |
| 115 FilePath existing_archive(installation.path().Append( | 113 FilePath existing_archive(installer_state.target_path().Append( |
| 116 UTF8ToWide(archive_version->GetString()))); | 114 UTF8ToWide(archive_version->GetString()))); |
| 117 existing_archive = existing_archive.Append(installer::kInstallerDir); | 115 existing_archive = existing_archive.Append(installer::kInstallerDir); |
| 118 existing_archive = existing_archive.Append(installer::kChromeArchive); | 116 existing_archive = existing_archive.Append(installer::kChromeArchive); |
| 119 if (int i = installer::ApplyDiffPatch(FilePath(existing_archive), | 117 if (int i = installer::ApplyDiffPatch(FilePath(existing_archive), |
| 120 FilePath(unpacked_file), | 118 FilePath(unpacked_file), |
| 121 FilePath(uncompressed_archive))) { | 119 FilePath(uncompressed_archive))) { |
| 122 LOG(ERROR) << "Binary patching failed with error " << i; | 120 LOG(ERROR) << "Binary patching failed with error " << i; |
| 123 return i; | 121 return i; |
| 124 } | 122 } |
| 125 } | 123 } |
| 126 | 124 |
| 127 // Unpack the uncompressed archive. | 125 // Unpack the uncompressed archive. |
| 128 return LzmaUtil::UnPackArchive(uncompressed_archive.value(), | 126 return LzmaUtil::UnPackArchive(uncompressed_archive.value(), |
| 129 output_directory.value(), &unpacked_file); | 127 output_directory.value(), &unpacked_file); |
| 130 } | 128 } |
| 131 | 129 |
| 132 | 130 |
| 133 // This function is called when --rename-chrome-exe option is specified on | 131 // This function is called when --rename-chrome-exe option is specified on |
| 134 // setup.exe command line. This function assumes an in-use update has happened | 132 // setup.exe command line. This function assumes an in-use update has happened |
| 135 // for Chrome so there should be a file called new_chrome.exe on the file | 133 // for Chrome so there should be a file called new_chrome.exe on the file |
| 136 // system and a key called 'opv' in the registry. This function will move | 134 // system and a key called 'opv' in the registry. This function will move |
| 137 // new_chrome.exe to chrome.exe and delete 'opv' key in one atomic operation. | 135 // new_chrome.exe to chrome.exe and delete 'opv' key in one atomic operation. |
| 138 installer::InstallStatus RenameChromeExecutables( | 136 installer::InstallStatus RenameChromeExecutables( |
| 139 const Package& installation) { | 137 const InstallerState& installer_state) { |
| 140 FilePath chrome_exe(installation.path().Append(installer::kChromeExe)); | 138 const FilePath &target_path = installer_state.target_path(); |
| 141 FilePath chrome_old_exe(installation.path().Append( | 139 FilePath chrome_exe(target_path.Append(installer::kChromeExe)); |
| 142 installer::kChromeOldExe)); | 140 FilePath chrome_old_exe(target_path.Append(installer::kChromeOldExe)); |
| 143 FilePath chrome_new_exe(installation.path().Append( | 141 FilePath chrome_new_exe(target_path.Append(installer::kChromeNewExe)); |
| 144 installer::kChromeNewExe)); | |
| 145 | 142 |
| 146 scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); | 143 scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); |
| 147 install_list->AddDeleteTreeWorkItem(chrome_old_exe); | 144 install_list->AddDeleteTreeWorkItem(chrome_old_exe); |
| 148 FilePath temp_path; | 145 FilePath temp_path; |
| 149 if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) { | 146 if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) { |
| 150 LOG(ERROR) << "Failed to create Temp directory " << temp_path.value(); | 147 LOG(ERROR) << "Failed to create Temp directory " << temp_path.value(); |
| 151 return installer::RENAME_FAILED; | 148 return installer::RENAME_FAILED; |
| 152 } | 149 } |
| 153 | 150 |
| 154 install_list->AddCopyTreeWorkItem(chrome_new_exe.value(), | 151 install_list->AddCopyTreeWorkItem(chrome_new_exe.value(), |
| 155 chrome_exe.value(), | 152 chrome_exe.value(), |
| 156 temp_path.ToWStringHack(), | 153 temp_path.ToWStringHack(), |
| 157 WorkItem::IF_DIFFERENT, | 154 WorkItem::IF_DIFFERENT, |
| 158 std::wstring()); | 155 std::wstring()); |
| 159 install_list->AddDeleteTreeWorkItem(chrome_new_exe); | 156 install_list->AddDeleteTreeWorkItem(chrome_new_exe); |
| 160 | 157 |
| 161 HKEY reg_root = installation.system_level() ? HKEY_LOCAL_MACHINE : | 158 HKEY reg_root = installer_state.root_key(); |
| 162 HKEY_CURRENT_USER; | 159 const Products& products = installer_state.products(); |
| 163 const Products& products = installation.products(); | |
| 164 for (size_t i = 0; i < products.size(); ++i) { | 160 for (size_t i = 0; i < products.size(); ++i) { |
| 165 const Product* product = products[i]; | 161 const Product* product = products[i]; |
| 166 BrowserDistribution* browser_dist = product->distribution(); | 162 BrowserDistribution* browser_dist = product->distribution(); |
| 167 std::wstring version_key(browser_dist->GetVersionKey()); | 163 std::wstring version_key(browser_dist->GetVersionKey()); |
| 168 install_list->AddDeleteRegValueWorkItem(reg_root, | 164 install_list->AddDeleteRegValueWorkItem(reg_root, |
| 169 version_key, | 165 version_key, |
| 170 google_update::kRegOldVersionField); | 166 google_update::kRegOldVersionField); |
| 171 install_list->AddDeleteRegValueWorkItem(reg_root, | 167 install_list->AddDeleteRegValueWorkItem(reg_root, |
| 172 version_key, | 168 version_key, |
| 173 google_update::kRegRenameCmdField); | 169 google_update::kRegRenameCmdField); |
| 174 } | 170 } |
| 175 installer::InstallStatus ret = installer::RENAME_SUCCESSFUL; | 171 installer::InstallStatus ret = installer::RENAME_SUCCESSFUL; |
| 176 if (!install_list->Do()) { | 172 if (!install_list->Do()) { |
| 177 LOG(ERROR) << "Renaming of executables failed. Rolling back any changes."; | 173 LOG(ERROR) << "Renaming of executables failed. Rolling back any changes."; |
| 178 install_list->Rollback(); | 174 install_list->Rollback(); |
| 179 ret = installer::RENAME_FAILED; | 175 ret = installer::RENAME_FAILED; |
| 180 } | 176 } |
| 181 file_util::Delete(temp_path, true); | 177 file_util::Delete(temp_path, true); |
| 182 return ret; | 178 return ret; |
| 183 } | 179 } |
| 184 | 180 |
| 181 // Checks for compatibility between the current state of the system and the | |
| 182 // desired operation. Also applies policy that mutates the desired operation; | |
| 183 // specifically, the |installer_state| object. The supported multi-install | |
| 184 // modes are: | |
| 185 // --multi-install --chrome --chrome-frame --ready-mode | |
| 186 // - If a non-multi Chrome Frame installation is present, Chrome Frame is | |
| 187 // removed from |installer_state|'s list of products (thereby preserving | |
| 188 // the existing SxS install). | |
| 189 // - If a multi Chrome Frame installation is present, its options are | |
| 190 // preserved (i.e., the --ready-mode command-line option is ignored). | |
| 191 // --multi-install --chrome-frame | |
| 192 // - If a non-multi Chrome Frame installation is present, fail. | |
| 193 // - If a Chrome installation on a different channel is present, fail. | |
| 194 // - If a Chrome installation is present, add it to the set of products to | |
| 195 // install. | |
| 196 // Also blocks simultaneous user-level and system-level installs. In the case | |
| 197 // of trying to install user-level Chrome when system-level exists, the | |
| 198 // existing system-level Chrome is launched. | |
| 185 bool CheckPreInstallConditions(const InstallationState& original_state, | 199 bool CheckPreInstallConditions(const InstallationState& original_state, |
| 186 const InstallerState& installer_state, | |
| 187 const Package& installation, | |
| 188 const MasterPreferences& prefs, | 200 const MasterPreferences& prefs, |
| 201 InstallerState* installer_state, | |
| 189 installer::InstallStatus* status) { | 202 installer::InstallStatus* status) { |
| 190 const Products& products = installation.products(); | 203 const Products& products = installer_state->products(); |
| 191 DCHECK(products.size()); | 204 DCHECK(products.size()); |
| 192 | 205 |
| 193 bool is_first_install = true; | 206 bool is_first_install = true; |
| 194 const bool system_level = installation.system_level(); | 207 const bool system_level = installer_state->system_install(); |
| 208 | |
| 209 if (installer_state->multi_install()) { | |
| 210 const Product* chrome = | |
| 211 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); | |
| 212 const Product* chrome_frame = | |
| 213 installer_state->FindProduct(BrowserDistribution::CHROME_FRAME); | |
| 214 const ProductState* cf_state = | |
| 215 original_state.GetProductState(system_level, | |
| 216 BrowserDistribution::CHROME_FRAME); | |
| 217 if (chrome != NULL) { | |
| 218 if (chrome_frame != NULL && | |
| 219 chrome_frame->HasOption(installer::kOptionReadyMode)) { | |
| 220 // We're being asked to install Chrome with Chrome Frame in ready-mode. | |
| 221 // This is an optimistic operation: if a SxS install of Chrome Frame | |
| 222 // is already present, don't touch it; if a multi-install of Chrome | |
| 223 // Frame is present, preserve its settings (ready-mode, CEEE). | |
| 224 if (cf_state != NULL) { | |
| 225 installer_state->RemoveProduct(chrome_frame); | |
| 226 chrome_frame = NULL; | |
| 227 if (cf_state->multi_install()) { | |
| 228 chrome_frame = installer_state->AddProductFromState( | |
| 229 BrowserDistribution::CHROME_FRAME, *cf_state); | |
| 230 VLOG(1) << "Upgrading existing multi-install " | |
| 231 << chrome_frame->distribution()->GetApplicationName() | |
| 232 << " rather than installing in ready-mode."; | |
| 233 } else { | |
| 234 VLOG(1) << "Skipping upgrade of single-install Chrome Frame rather " | |
| 235 "than installing in ready-mode."; | |
| 236 } | |
| 237 } else { | |
| 238 VLOG(1) << "Performing initial install of Chrome Frame ready-mode."; | |
| 239 } | |
| 240 } | |
| 241 } else if (chrome_frame != NULL) { | |
| 242 // We're being asked to install or update Chrome Frame alone. Fail if a | |
| 243 // single-install of Chrome Frame is already installed. | |
| 244 // TODO(grt): Add support for migration of Chrome Frame from single- to | |
| 245 // multi-install. | |
| 246 if (cf_state != NULL && !cf_state->multi_install()) { | |
| 247 *status = installer::NON_MULTI_INSTALLATION_EXISTS; | |
| 248 InstallUtil::WriteInstallerResult(system_level, | |
| 249 installer_state->state_key(), *status, | |
| 250 IDS_INSTALL_NON_MULTI_INSTALLATION_EXISTS_BASE, NULL); | |
| 251 return false; | |
| 252 } | |
| 253 const ProductState* chrome_state = | |
| 254 original_state.GetProductState(system_level, | |
| 255 BrowserDistribution::CHROME_BROWSER); | |
| 256 if (chrome_state != NULL) { | |
| 257 base::win::RegKey key; | |
|
tommi (sloooow) - chröme
2011/01/21 21:45:17
if ready-mode is being installed you need to check
grt (UTC plus 2)
2011/01/24 16:07:02
Done. Thanks for the patch you sent for doing thi
| |
| 258 installer::ChannelInfo cf_channel; | |
| 259 // Chrome Frame may not yet be installed, so peek into the registry | |
| 260 // directly to see what channel Google Update has specified. There will | |
| 261 // be no value if we're not being managed by Google Update. | |
| 262 if (key.Open(installer_state->root_key(), | |
| 263 chrome_frame->distribution()->GetStateKey().c_str(), | |
| 264 KEY_QUERY_VALUE) == ERROR_SUCCESS) { | |
| 265 cf_channel.Initialize(key); | |
| 266 } | |
| 267 // Fail if Chrome is already installed but is on a different update | |
| 268 // channel. | |
| 269 if (!cf_channel.EqualsBaseOf(chrome_state->channel())) { | |
| 270 *status = installer::CONFLICTING_CHANNEL_EXISTS; | |
| 271 InstallUtil::WriteInstallerResult(system_level, | |
| 272 installer_state->state_key(), *status, | |
| 273 IDS_INSTALL_CONFLICTING_CHANNEL_EXISTS_BASE, NULL); | |
| 274 return false; | |
| 275 } | |
| 276 // Otherwise, add Chrome to the set of products so that it is updated, | |
| 277 // too. | |
| 278 chrome = installer_state->AddProductFromState( | |
|
tommi (sloooow) - chröme
2011/01/21 21:45:17
is there a missing check for multi first?
grt (UTC plus 2)
2011/01/24 16:07:02
In this case, we'll transition an existing single
| |
| 279 BrowserDistribution::CHROME_BROWSER, *chrome_state); | |
| 280 VLOG(1) << "Upgrading existing multi-install " | |
| 281 << chrome->distribution()->GetApplicationName() | |
| 282 << " along with " | |
| 283 << chrome_frame->distribution()->GetApplicationName(); | |
| 284 } | |
|
tommi (sloooow) - chröme
2011/01/21 21:45:17
} else {
Check if ready-mode is being asked for.
grt (UTC plus 2)
2011/01/24 16:07:02
Done.
| |
| 285 } | |
| 286 } | |
|
tommi (sloooow) - chröme
2011/01/21 21:45:17
} else {
abort if ready-mode is specified?
abo
grt (UTC plus 2)
2011/01/24 16:07:02
For the former, setup.exe currently silently ignor
tommi (sloooow) - chröme
2011/01/24 19:39:39
Hmm.. maybe we should just log a warning for now.
grt (UTC plus 2)
2011/01/25 03:09:39
Done.
| |
| 195 | 287 |
| 196 for (size_t i = 0; i < products.size(); ++i) { | 288 for (size_t i = 0; i < products.size(); ++i) { |
| 197 const Product* product = products[i]; | 289 const Product* product = products[i]; |
| 198 BrowserDistribution* browser_dist = product->distribution(); | 290 BrowserDistribution* browser_dist = product->distribution(); |
| 291 | |
| 292 // Ensure that existing installs are of the same package type. | |
| 199 const ProductState* product_state = | 293 const ProductState* product_state = |
| 200 original_state.GetProductState(system_level, browser_dist->GetType()); | 294 original_state.GetProductState(system_level, browser_dist->GetType()); |
| 201 if (product_state != NULL) | 295 if (product_state != NULL) { |
| 202 is_first_install = false; | 296 is_first_install = false; |
| 297 // Is the existing install's package type the same as this run? | |
| 298 if (installer_state->multi_install()) { | |
| 299 if (!product_state->multi_install()) { | |
| 300 *status = installer::NON_MULTI_INSTALLATION_EXISTS; | |
| 301 InstallUtil::WriteInstallerResult(system_level, | |
| 302 installer_state->state_key(), *status, | |
| 303 IDS_INSTALL_NON_MULTI_INSTALLATION_EXISTS_BASE, NULL); | |
| 304 return false; | |
| 305 } | |
| 306 } else { | |
| 307 if (product_state->multi_install()) { | |
| 308 *status = installer::MULTI_INSTALLATION_EXISTS; | |
| 309 InstallUtil::WriteInstallerResult(system_level, | |
| 310 installer_state->state_key(), *status, | |
| 311 IDS_INSTALL_MULTI_INSTALLATION_EXISTS_BASE, NULL); | |
| 312 return false; | |
| 313 } | |
| 314 } | |
| 315 } | |
| 203 | 316 |
| 204 // Check to avoid simultaneous per-user and per-machine installs. | 317 // Check to avoid simultaneous per-user and per-machine installs. |
| 205 const ProductState* other_state = | 318 const ProductState* other_state = |
| 206 original_state.GetProductState(!system_level, browser_dist->GetType()); | 319 original_state.GetProductState(!system_level, browser_dist->GetType()); |
| 207 | |
| 208 if (other_state != NULL) { | 320 if (other_state != NULL) { |
| 209 LOG(ERROR) << "Already installed version " | 321 LOG(ERROR) << "Already installed version " |
| 210 << other_state->version().GetString() | 322 << other_state->version().GetString() |
| 211 << " conflicts with the current install mode."; | 323 << " conflicts with the current install mode."; |
| 212 if (!system_level && is_first_install && product->is_chrome()) { | 324 if (!system_level && is_first_install && product->is_chrome()) { |
| 213 // This is user-level install and there is a system-level chrome | 325 // This is user-level install and there is a system-level chrome |
| 214 // installation. Instruct Omaha to launch the existing one. There | 326 // installation. Instruct Google Update to launch the existing one. |
| 215 // should be no error dialog. | 327 // There should be no error dialog. |
| 216 FilePath chrome_exe(installer::GetChromeInstallPath(!system_level, | 328 FilePath chrome_exe(installer::GetChromeInstallPath(!system_level, |
| 217 browser_dist)); | 329 browser_dist)); |
| 218 if (chrome_exe.empty()) { | 330 if (chrome_exe.empty()) { |
| 219 // If we failed to construct install path. Give up. | 331 // If we failed to construct install path. Give up. |
| 220 *status = installer::OS_ERROR; | 332 *status = installer::OS_ERROR; |
| 221 InstallUtil::WriteInstallerResult(system_level, | 333 InstallUtil::WriteInstallerResult(system_level, |
| 222 installer_state.state_key(), *status, IDS_INSTALL_OS_ERROR_BASE, | 334 installer_state->state_key(), *status, IDS_INSTALL_OS_ERROR_BASE, |
| 223 NULL); | 335 NULL); |
| 224 } else { | 336 } else { |
| 225 *status = installer::EXISTING_VERSION_LAUNCHED; | 337 *status = installer::EXISTING_VERSION_LAUNCHED; |
| 226 chrome_exe = chrome_exe.Append(installer::kChromeExe); | 338 chrome_exe = chrome_exe.Append(installer::kChromeExe); |
| 227 CommandLine cmd(chrome_exe); | 339 CommandLine cmd(chrome_exe); |
| 228 cmd.AppendSwitch(switches::kFirstRun); | 340 cmd.AppendSwitch(switches::kFirstRun); |
| 229 InstallUtil::WriteInstallerResult(system_level, | 341 InstallUtil::WriteInstallerResult(system_level, |
| 230 installer_state.state_key(), *status, 0, NULL); | 342 installer_state->state_key(), *status, 0, NULL); |
| 231 VLOG(1) << "Launching existing system-level chrome instead."; | 343 VLOG(1) << "Launching existing system-level chrome instead."; |
| 232 base::LaunchApp(cmd, false, false, NULL); | 344 base::LaunchApp(cmd, false, false, NULL); |
| 233 } | 345 } |
| 234 return false; | 346 return false; |
| 235 } | 347 } |
| 236 | 348 |
| 237 // If the following compile assert fires it means that the InstallStatus | 349 // If the following compile assert fires it means that the InstallStatus |
| 238 // enumeration changed which will break the contract between the old | 350 // enumeration changed which will break the contract between the old |
| 239 // chrome installed and the new setup.exe that is trying to upgrade. | 351 // chrome installed and the new setup.exe that is trying to upgrade. |
| 240 COMPILE_ASSERT(installer::SXS_OPTION_NOT_SUPPORTED == 33, | 352 COMPILE_ASSERT(installer::CONFLICTING_CHANNEL_EXISTS == 39, |
| 241 dont_change_enum); | 353 dont_change_enum); |
| 242 | 354 |
| 243 // This is an update, not an install. Omaha should know the difference | 355 // This is an update, not an install. Omaha should know the difference |
| 244 // and not show a dialog. | 356 // and not show a dialog. |
| 245 *status = system_level ? installer::USER_LEVEL_INSTALL_EXISTS : | 357 *status = system_level ? installer::USER_LEVEL_INSTALL_EXISTS : |
| 246 installer::SYSTEM_LEVEL_INSTALL_EXISTS; | 358 installer::SYSTEM_LEVEL_INSTALL_EXISTS; |
| 247 int str_id = system_level ? IDS_INSTALL_USER_LEVEL_EXISTS_BASE : | 359 int str_id = system_level ? IDS_INSTALL_USER_LEVEL_EXISTS_BASE : |
| 248 IDS_INSTALL_SYSTEM_LEVEL_EXISTS_BASE; | 360 IDS_INSTALL_SYSTEM_LEVEL_EXISTS_BASE; |
| 249 InstallUtil::WriteInstallerResult(system_level, | 361 InstallUtil::WriteInstallerResult(system_level, |
| 250 installer_state.state_key(), *status, str_id, NULL); | 362 installer_state->state_key(), *status, str_id, NULL); |
| 251 return false; | 363 return false; |
| 252 } | 364 } |
| 253 } | 365 } |
| 254 | 366 |
| 367 // See what products are already installed in multi mode. When we do multi | |
| 368 // installs, we must upgrade all installations since they share the binaries. | |
| 369 if (installer_state->multi_install()) { | |
| 370 BrowserDistribution::Type product_checks[] = { | |
| 371 BrowserDistribution::CHROME_BROWSER, | |
| 372 BrowserDistribution::CHROME_FRAME | |
| 373 }; | |
| 374 | |
| 375 for (size_t i = 0; i < arraysize(product_checks); ++i) { | |
| 376 BrowserDistribution::Type type = product_checks[i]; | |
| 377 if (!installer_state->FindProduct(type)) { | |
| 378 const ProductState* state = | |
| 379 original_state.GetProductState(system_level, type); | |
| 380 if ((state != NULL) && state->multi_install()) { | |
| 381 installer_state->AddProductFromState(type, *state); | |
| 382 VLOG(1) << "Product already installed and must be included: " | |
| 383 << BrowserDistribution::GetSpecificDistribution( | |
| 384 type)->GetApplicationName(); | |
| 385 } | |
| 386 } | |
| 387 } | |
| 388 } | |
| 389 | |
| 255 // If no previous installation of Chrome, make sure installation directory | 390 // If no previous installation of Chrome, make sure installation directory |
| 256 // either does not exist or can be deleted (i.e. is not locked by some other | 391 // either does not exist or can be deleted (i.e. is not locked by some other |
| 257 // process). | 392 // process). |
| 258 if (is_first_install) { | 393 if (is_first_install) { |
| 259 if (file_util::PathExists(installation.path()) && | 394 if (file_util::PathExists(installer_state->target_path()) && |
| 260 !file_util::Delete(installation.path(), true)) { | 395 !file_util::Delete(installer_state->target_path(), true)) { |
| 261 LOG(ERROR) << "Installation directory " << installation.path().value() | 396 LOG(ERROR) << "Installation directory " |
| 397 << installer_state->target_path().value() | |
| 262 << " exists and can not be deleted."; | 398 << " exists and can not be deleted."; |
| 263 *status = installer::INSTALL_DIR_IN_USE; | 399 *status = installer::INSTALL_DIR_IN_USE; |
| 264 int str_id = IDS_INSTALL_DIR_IN_USE_BASE; | 400 int str_id = IDS_INSTALL_DIR_IN_USE_BASE; |
| 265 InstallUtil::WriteInstallerResult(system_level, | 401 InstallUtil::WriteInstallerResult(system_level, |
| 266 installer_state.state_key(), *status, str_id, NULL); | 402 installer_state->state_key(), *status, str_id, NULL); |
| 267 return false; | 403 return false; |
| 268 } | 404 } |
| 269 } | 405 } |
| 270 | 406 |
| 271 return true; | 407 return true; |
| 272 } | 408 } |
|
tommi (sloooow) - chröme
2011/01/21 21:45:17
just a general comment on this function. It's get
grt (UTC plus 2)
2011/01/24 16:07:02
Totally. For now, I've pulled out two funcs.
| |
| 273 | 409 |
| 274 installer::InstallStatus InstallChrome(const InstallationState& original_state, | 410 installer::InstallStatus InstallProducts( |
| 275 const InstallerState& installer_state, | 411 const InstallationState& original_state, |
| 276 const CommandLine& cmd_line, const Package& installation, | 412 const CommandLine& cmd_line, |
| 277 const MasterPreferences& prefs) { | 413 const MasterPreferences& prefs, |
| 414 InstallerState* installer_state) { | |
| 415 const bool system_install = installer_state->system_install(); | |
| 278 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; | 416 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; |
| 279 if (!CheckPreInstallConditions(original_state, installer_state, installation, | 417 if (!CheckPreInstallConditions(original_state, prefs, installer_state, |
| 280 prefs, &install_status)) | 418 &install_status)) |
| 281 return install_status; | 419 return install_status; |
| 282 | 420 |
| 283 // For install the default location for chrome.packed.7z is in current | 421 // For install the default location for chrome.packed.7z is in current |
| 284 // folder, so get that value first. | 422 // folder, so get that value first. |
| 285 FilePath archive(cmd_line.GetProgram().DirName().Append( | 423 FilePath archive(cmd_line.GetProgram().DirName().Append( |
| 286 installer::kChromeCompressedArchive)); | 424 installer::kChromeCompressedArchive)); |
| 287 | 425 |
| 288 // If --install-archive is given, get the user specified value | 426 // If --install-archive is given, get the user specified value |
| 289 if (cmd_line.HasSwitch(installer::switches::kInstallArchive)) { | 427 if (cmd_line.HasSwitch(installer::switches::kInstallArchive)) { |
| 290 archive = cmd_line.GetSwitchValuePath( | 428 archive = cmd_line.GetSwitchValuePath( |
| 291 installer::switches::kInstallArchive); | 429 installer::switches::kInstallArchive); |
| 292 } | 430 } |
| 293 VLOG(1) << "Archive found to install Chrome " << archive.value(); | 431 VLOG(1) << "Archive found to install Chrome " << archive.value(); |
| 294 const Products& products = installation.products(); | 432 const Products& products = installer_state->products(); |
| 295 | 433 |
| 296 // Create a temp folder where we will unpack Chrome archive. If it fails, | 434 // Create a temp folder where we will unpack Chrome archive. If it fails, |
| 297 // then we are doomed, so return immediately and no cleanup is required. | 435 // then we are doomed, so return immediately and no cleanup is required. |
| 298 FilePath temp_path; | 436 FilePath temp_path; |
| 299 if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) { | 437 if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) { |
| 300 LOG(ERROR) << "Could not create temporary path."; | 438 LOG(ERROR) << "Could not create temporary path."; |
| 301 InstallUtil::WriteInstallerResult(installer_state.system_install(), | 439 InstallUtil::WriteInstallerResult(system_install, |
| 302 installer_state.state_key(), installer::TEMP_DIR_FAILED, | 440 installer_state->state_key(), installer::TEMP_DIR_FAILED, |
| 303 IDS_INSTALL_TEMP_DIR_FAILED_BASE, NULL); | 441 IDS_INSTALL_TEMP_DIR_FAILED_BASE, NULL); |
| 304 return installer::TEMP_DIR_FAILED; | 442 return installer::TEMP_DIR_FAILED; |
| 305 } | 443 } |
| 306 VLOG(1) << "created path " << temp_path.value(); | 444 VLOG(1) << "created path " << temp_path.value(); |
| 307 | 445 |
| 308 FilePath unpack_path(temp_path.Append(installer::kInstallSourceDir)); | 446 FilePath unpack_path(temp_path.Append(installer::kInstallSourceDir)); |
| 309 bool incremental_install = false; | 447 bool incremental_install = false; |
| 310 if (UnPackArchive(archive, installation, temp_path, unpack_path, | 448 if (UnPackArchive(archive, *installer_state, temp_path, unpack_path, |
| 311 incremental_install)) { | 449 incremental_install)) { |
| 312 install_status = installer::UNCOMPRESSION_FAILED; | 450 install_status = installer::UNCOMPRESSION_FAILED; |
| 313 InstallUtil::WriteInstallerResult(installer_state.system_install(), | 451 InstallUtil::WriteInstallerResult(system_install, |
| 314 installer_state.state_key(), install_status, | 452 installer_state->state_key(), install_status, |
| 315 IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, NULL); | 453 IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, NULL); |
| 316 } else { | 454 } else { |
| 317 VLOG(1) << "unpacked to " << unpack_path.value(); | 455 VLOG(1) << "unpacked to " << unpack_path.value(); |
| 318 FilePath src_path(unpack_path.Append(installer::kInstallSourceChromeDir)); | 456 FilePath src_path(unpack_path.Append(installer::kInstallSourceChromeDir)); |
| 319 scoped_ptr<Version> | 457 scoped_ptr<Version> |
| 320 installer_version(installer::GetVersionFromArchiveDir(src_path)); | 458 installer_version(installer::GetVersionFromArchiveDir(src_path)); |
| 321 if (!installer_version.get()) { | 459 if (!installer_version.get()) { |
| 322 LOG(ERROR) << "Did not find any valid version in installer."; | 460 LOG(ERROR) << "Did not find any valid version in installer."; |
| 323 install_status = installer::INVALID_ARCHIVE; | 461 install_status = installer::INVALID_ARCHIVE; |
| 324 InstallUtil::WriteInstallerResult(installer_state.system_install(), | 462 InstallUtil::WriteInstallerResult(system_install, |
| 325 installer_state.state_key(), install_status, | 463 installer_state->state_key(), install_status, |
| 326 IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); | 464 IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); |
| 327 } else { | 465 } else { |
| 328 // TODO(tommi): Move towards having only a single version that is common | 466 // TODO(tommi): Move towards having only a single version that is common |
| 329 // to all products. Only the package should have a version since it | 467 // to all products. Only the package should have a version since it |
| 330 // represents all the binaries. When a single product is upgraded, all | 468 // represents all the binaries. When a single product is upgraded, all |
| 331 // currently installed product for the shared binary installation, should | 469 // currently installed product for the shared binary installation, should |
| 332 // (or rather must) be upgraded. | 470 // (or rather must) be upgraded. |
| 333 VLOG(1) << "version to install: " << installer_version->GetString(); | 471 VLOG(1) << "version to install: " << installer_version->GetString(); |
| 334 bool higher_version_installed = false; | 472 bool higher_version_installed = false; |
| 335 for (size_t i = 0; i < installation.products().size(); ++i) { | 473 for (size_t i = 0; i < installer_state->products().size(); ++i) { |
| 336 const Product* product = installation.products()[i]; | 474 const Product* product = installer_state->products()[i]; |
| 337 const ProductState* product_state = | 475 const ProductState* product_state = |
| 338 original_state.GetProductState(installer_state.system_install(), | 476 original_state.GetProductState(system_install, |
| 339 product->distribution()->GetType()); | 477 product->distribution()->GetType()); |
| 340 if (product_state != NULL && | 478 if (product_state != NULL && |
| 341 (product_state->version().CompareTo(*installer_version) > 0)) { | 479 (product_state->version().CompareTo(*installer_version) > 0)) { |
| 342 LOG(ERROR) << "Higher version is already installed."; | 480 LOG(ERROR) << "Higher version is already installed."; |
| 343 higher_version_installed = true; | 481 higher_version_installed = true; |
| 344 install_status = installer::HIGHER_VERSION_EXISTS; | 482 install_status = installer::HIGHER_VERSION_EXISTS; |
| 345 | 483 |
| 346 if (product->is_chrome()) { | 484 if (product->is_chrome()) { |
| 347 // TODO(robertshield): We should take the installer result text | 485 // TODO(robertshield): We should take the installer result text |
| 348 // strings from the Product. | 486 // strings from the Product. |
| 349 InstallUtil::WriteInstallerResult(installer_state.system_install(), | 487 InstallUtil::WriteInstallerResult(system_install, |
| 350 installer_state.state_key(), install_status, | 488 installer_state->state_key(), install_status, |
| 351 IDS_INSTALL_HIGHER_VERSION_BASE, NULL); | 489 IDS_INSTALL_HIGHER_VERSION_BASE, NULL); |
| 352 } else { | 490 } else { |
| 353 InstallUtil::WriteInstallerResult(installer_state.system_install(), | 491 InstallUtil::WriteInstallerResult(system_install, |
| 354 installer_state.state_key(), install_status, | 492 installer_state->state_key(), install_status, |
| 355 IDS_INSTALL_HIGHER_VERSION_CF_BASE, NULL); | 493 IDS_INSTALL_HIGHER_VERSION_CF_BASE, NULL); |
| 356 } | 494 } |
| 357 } | 495 } |
| 358 } | 496 } |
| 359 | 497 |
| 360 if (!higher_version_installed) { | 498 if (!higher_version_installed) { |
| 361 // We want to keep uncompressed archive (chrome.7z) that we get after | 499 // We want to keep uncompressed archive (chrome.7z) that we get after |
| 362 // uncompressing and binary patching. Get the location for this file. | 500 // uncompressing and binary patching. Get the location for this file. |
| 363 FilePath archive_to_copy(temp_path.Append(installer::kChromeArchive)); | 501 FilePath archive_to_copy(temp_path.Append(installer::kChromeArchive)); |
| 364 FilePath prefs_source_path(cmd_line.GetSwitchValueNative( | 502 FilePath prefs_source_path(cmd_line.GetSwitchValueNative( |
| 365 installer::switches::kInstallerData)); | 503 installer::switches::kInstallerData)); |
| 366 install_status = installer::InstallOrUpdateProduct(original_state, | 504 install_status = installer::InstallOrUpdateProduct(original_state, |
| 367 installer_state, cmd_line.GetProgram(), archive_to_copy, temp_path, | 505 *installer_state, cmd_line.GetProgram(), archive_to_copy, temp_path, |
| 368 prefs_source_path, prefs, *installer_version, installation); | 506 prefs_source_path, prefs, *installer_version); |
| 369 | 507 |
| 370 int install_msg_base = IDS_INSTALL_FAILED_BASE; | 508 int install_msg_base = IDS_INSTALL_FAILED_BASE; |
| 371 std::wstring chrome_exe; | 509 std::wstring chrome_exe; |
| 372 if (install_status == installer::SAME_VERSION_REPAIR_FAILED) { | 510 if (install_status == installer::SAME_VERSION_REPAIR_FAILED) { |
| 373 if (FindProduct(products, BrowserDistribution::CHROME_FRAME)) { | 511 if (installer_state->FindProduct(BrowserDistribution::CHROME_FRAME)) { |
| 374 install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_CF_BASE; | 512 install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_CF_BASE; |
| 375 } else { | 513 } else { |
| 376 install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_BASE; | 514 install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_BASE; |
| 377 } | 515 } |
| 378 } else if (install_status != installer::INSTALL_FAILED) { | 516 } else if (install_status != installer::INSTALL_FAILED) { |
| 379 if (installation.path().empty()) { | 517 if (installer_state->target_path().empty()) { |
| 380 // If we failed to construct install path, it means the OS call to | 518 // If we failed to construct install path, it means the OS call to |
| 381 // get %ProgramFiles% or %AppData% failed. Report this as failure. | 519 // get %ProgramFiles% or %AppData% failed. Report this as failure. |
| 382 install_msg_base = IDS_INSTALL_OS_ERROR_BASE; | 520 install_msg_base = IDS_INSTALL_OS_ERROR_BASE; |
| 383 install_status = installer::OS_ERROR; | 521 install_status = installer::OS_ERROR; |
| 384 } else { | 522 } else { |
| 385 chrome_exe = installation.path() | 523 chrome_exe = installer_state->target_path() |
| 386 .Append(installer::kChromeExe).value(); | 524 .Append(installer::kChromeExe).value(); |
| 387 chrome_exe = L"\"" + chrome_exe + L"\""; | 525 chrome_exe = L"\"" + chrome_exe + L"\""; |
| 388 install_msg_base = 0; | 526 install_msg_base = 0; |
| 389 } | 527 } |
| 390 } | 528 } |
| 391 | 529 |
| 392 const Product* chrome_install = | 530 const Product* chrome_install = |
| 393 FindProduct(products, BrowserDistribution::CHROME_BROWSER); | 531 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); |
| 394 | 532 |
| 395 bool value = false; | 533 bool value = false; |
| 396 if (chrome_install) { | 534 if (chrome_install) { |
| 397 prefs.GetBool( | 535 prefs.GetBool( |
| 398 installer::master_preferences::kDoNotRegisterForUpdateLaunch, | 536 installer::master_preferences::kDoNotRegisterForUpdateLaunch, |
| 399 &value); | 537 &value); |
| 400 } else { | 538 } else { |
| 401 value = true; // Never register. | 539 value = true; // Never register. |
| 402 } | 540 } |
| 403 | 541 |
| 404 bool write_chrome_launch_string = (!value) && | 542 bool write_chrome_launch_string = (!value) && |
| 405 (install_status != installer::IN_USE_UPDATED); | 543 (install_status != installer::IN_USE_UPDATED); |
| 406 | 544 |
| 407 InstallUtil::WriteInstallerResult(installer_state.system_install(), | 545 InstallUtil::WriteInstallerResult(system_install, |
| 408 installer_state.state_key(), install_status, install_msg_base, | 546 installer_state->state_key(), install_status, install_msg_base, |
| 409 write_chrome_launch_string ? &chrome_exe : NULL); | 547 write_chrome_launch_string ? &chrome_exe : NULL); |
| 410 | 548 |
| 411 if (install_status == installer::FIRST_INSTALL_SUCCESS) { | 549 if (install_status == installer::FIRST_INSTALL_SUCCESS) { |
| 412 VLOG(1) << "First install successful."; | 550 VLOG(1) << "First install successful."; |
| 413 if (chrome_install) { | 551 if (chrome_install) { |
| 414 // We never want to launch Chrome in system level install mode. | 552 // We never want to launch Chrome in system level install mode. |
| 415 bool do_not_launch_chrome = false; | 553 bool do_not_launch_chrome = false; |
| 416 prefs.GetBool( | 554 prefs.GetBool( |
| 417 installer::master_preferences::kDoNotLaunchChrome, | 555 installer::master_preferences::kDoNotLaunchChrome, |
| 418 &do_not_launch_chrome); | 556 &do_not_launch_chrome); |
| 419 if (!installation.system_level() && !do_not_launch_chrome) | 557 if (!system_install && !do_not_launch_chrome) |
| 420 chrome_install->LaunchChrome(); | 558 chrome_install->LaunchChrome(installer_state->target_path()); |
| 421 } | 559 } |
| 422 } else if ((install_status == installer::NEW_VERSION_UPDATED) || | 560 } else if ((install_status == installer::NEW_VERSION_UPDATED) || |
| 423 (install_status == installer::IN_USE_UPDATED)) { | 561 (install_status == installer::IN_USE_UPDATED)) { |
| 424 for (size_t i = 0; i < products.size(); ++i) { | 562 for (size_t i = 0; i < products.size(); ++i) { |
| 425 installer::RemoveLegacyRegistryKeys( | 563 installer::RemoveLegacyRegistryKeys( |
| 426 products[i]->distribution()); | 564 products[i]->distribution()); |
| 427 } | 565 } |
| 428 } | 566 } |
| 429 } | 567 } |
| 430 } | 568 } |
| 431 // There might be an experiment (for upgrade usually) that needs to happen. | 569 // There might be an experiment (for upgrade usually) that needs to happen. |
| 432 // An experiment's outcome can include chrome's uninstallation. If that is | 570 // An experiment's outcome can include chrome's uninstallation. If that is |
| 433 // the case we would not do that directly at this point but in another | 571 // the case we would not do that directly at this point but in another |
| 434 // instance of setup.exe | 572 // instance of setup.exe |
| 435 // | 573 // |
| 436 // There is another way to reach this same function if this is a system | 574 // There is another way to reach this same function if this is a system |
| 437 // level install. See HandleNonInstallCmdLineOptions(). | 575 // level install. See HandleNonInstallCmdLineOptions(). |
| 438 for (size_t i = 0; i < products.size(); ++i) { | 576 for (size_t i = 0; i < products.size(); ++i) { |
| 439 const Product* product = products[i]; | 577 const Product* product = products[i]; |
| 440 product->distribution()->LaunchUserExperiment(install_status, | 578 product->distribution()->LaunchUserExperiment(install_status, |
| 441 *installer_version, *product, installation.system_level()); | 579 *installer_version, *product, system_install); |
| 442 } | 580 } |
| 443 } | 581 } |
| 444 | 582 |
| 445 // Delete temporary files. These include install temporary directory | 583 // Delete temporary files. These include install temporary directory |
| 446 // and master profile file if present. Note that we do not care about rollback | 584 // and master profile file if present. Note that we do not care about rollback |
| 447 // here and we schedule for deletion on reboot below if the deletes fail. As | 585 // here and we schedule for deletion on reboot below if the deletes fail. As |
| 448 // such, we do not use DeleteTreeWorkItem. | 586 // such, we do not use DeleteTreeWorkItem. |
| 449 VLOG(1) << "Deleting temporary directory " << temp_path.value(); | 587 VLOG(1) << "Deleting temporary directory " << temp_path.value(); |
| 450 bool cleanup_success = file_util::Delete(temp_path, true); | 588 bool cleanup_success = file_util::Delete(temp_path, true); |
| 451 if (cmd_line.HasSwitch(installer::switches::kInstallerData)) { | 589 if (cmd_line.HasSwitch(installer::switches::kInstallerData)) { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 465 if (cmd_line.HasSwitch(installer::switches::kInstallerData)) { | 603 if (cmd_line.HasSwitch(installer::switches::kInstallerData)) { |
| 466 std::wstring prefs_path = cmd_line.GetSwitchValueNative( | 604 std::wstring prefs_path = cmd_line.GetSwitchValueNative( |
| 467 installer::switches::kInstallerData); | 605 installer::switches::kInstallerData); |
| 468 ScheduleDirectoryForDeletion(prefs_path.c_str()); | 606 ScheduleDirectoryForDeletion(prefs_path.c_str()); |
| 469 } | 607 } |
| 470 } | 608 } |
| 471 | 609 |
| 472 for (size_t i = 0; i < products.size(); ++i) { | 610 for (size_t i = 0; i < products.size(); ++i) { |
| 473 const Product* product = products[i]; | 611 const Product* product = products[i]; |
| 474 product->distribution()->UpdateInstallStatus( | 612 product->distribution()->UpdateInstallStatus( |
| 475 installer_state.system_install(), incremental_install, | 613 system_install, incremental_install, prefs.is_multi_install(), |
| 476 prefs.is_multi_install(), install_status); | 614 install_status); |
| 477 } | 615 } |
| 478 if (prefs.is_multi_install()) { | 616 if (installer_state->multi_install()) { |
| 479 installation.properties()->UpdateInstallStatus( | 617 installer_state->multi_package_binaries_distribution()->UpdateInstallStatus( |
| 480 installer_state.system_install(), incremental_install, true, | 618 system_install, incremental_install, true, install_status); |
| 481 install_status); | |
| 482 } | 619 } |
| 483 | 620 |
| 484 return install_status; | 621 return install_status; |
| 485 } | 622 } |
| 486 | 623 |
| 487 installer::InstallStatus UninstallProduct( | 624 installer::InstallStatus UninstallProduct( |
| 488 const InstallationState& original_state, | 625 const InstallationState& original_state, |
| 489 const InstallerState& installer_state, | 626 const InstallerState& installer_state, |
| 490 const CommandLine& cmd_line, | 627 const CommandLine& cmd_line, |
| 491 const Product& product) { | 628 const Product& product) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 532 return installer::EULA_ACCEPTED_OPT_IN; | 669 return installer::EULA_ACCEPTED_OPT_IN; |
| 533 } | 670 } |
| 534 VLOG(1) << "EULA accepted (no opt-in)"; | 671 VLOG(1) << "EULA accepted (no opt-in)"; |
| 535 return installer::EULA_ACCEPTED; | 672 return installer::EULA_ACCEPTED; |
| 536 } | 673 } |
| 537 | 674 |
| 538 // This method processes any command line options that make setup.exe do | 675 // This method processes any command line options that make setup.exe do |
| 539 // various tasks other than installation (renaming chrome.exe, showing eula | 676 // various tasks other than installation (renaming chrome.exe, showing eula |
| 540 // among others). This function returns true if any such command line option | 677 // among others). This function returns true if any such command line option |
| 541 // has been found and processed (so setup.exe should exit at that point). | 678 // has been found and processed (so setup.exe should exit at that point). |
| 542 bool HandleNonInstallCmdLineOptions(const InstallerState& installer_state, | 679 bool HandleNonInstallCmdLineOptions(const InstallationState& original_state, |
| 543 const CommandLine& cmd_line, | 680 const CommandLine& cmd_line, |
| 544 const ProductPackageMapping& installs, | 681 const InstallerState& installer_state, |
| 545 int* exit_code) { | 682 int* exit_code) { |
| 546 DCHECK(installs.products().size()); | |
| 547 bool handled = true; | 683 bool handled = true; |
| 548 // TODO(tommi): Split these checks up into functions and use a data driven | 684 // TODO(tommi): Split these checks up into functions and use a data driven |
| 549 // map of switch->function. | 685 // map of switch->function. |
| 550 if (cmd_line.HasSwitch(installer::switches::kUpdateSetupExe)) { | 686 if (cmd_line.HasSwitch(installer::switches::kUpdateSetupExe)) { |
| 551 installer::InstallStatus status = installer::SETUP_PATCH_FAILED; | 687 installer::InstallStatus status = installer::SETUP_PATCH_FAILED; |
| 552 // If --update-setup-exe command line option is given, we apply the given | 688 // If --update-setup-exe command line option is given, we apply the given |
| 553 // patch to current exe, and store the resulting binary in the path | 689 // patch to current exe, and store the resulting binary in the path |
| 554 // specified by --new-setup-exe. But we need to first unpack the file | 690 // specified by --new-setup-exe. But we need to first unpack the file |
| 555 // given in --update-setup-exe. | 691 // given in --update-setup-exe. |
| 556 FilePath temp_path; | 692 FilePath temp_path; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 581 NULL); | 717 NULL); |
| 582 } | 718 } |
| 583 file_util::Delete(temp_path, true); | 719 file_util::Delete(temp_path, true); |
| 584 } else if (cmd_line.HasSwitch(installer::switches::kShowEula)) { | 720 } else if (cmd_line.HasSwitch(installer::switches::kShowEula)) { |
| 585 // Check if we need to show the EULA. If it is passed as a command line | 721 // Check if we need to show the EULA. If it is passed as a command line |
| 586 // then the dialog is shown and regardless of the outcome setup exits here. | 722 // then the dialog is shown and regardless of the outcome setup exits here. |
| 587 std::wstring inner_frame = | 723 std::wstring inner_frame = |
| 588 cmd_line.GetSwitchValueNative(installer::switches::kShowEula); | 724 cmd_line.GetSwitchValueNative(installer::switches::kShowEula); |
| 589 *exit_code = ShowEULADialog(inner_frame); | 725 *exit_code = ShowEULADialog(inner_frame); |
| 590 if (installer::EULA_REJECTED != *exit_code) | 726 if (installer::EULA_REJECTED != *exit_code) |
| 591 GoogleUpdateSettings::SetEULAConsent(*installs.packages()[0].get(), true); | 727 GoogleUpdateSettings::SetEULAConsent(installer_state, true); |
| 592 } else if (cmd_line.HasSwitch( | 728 } else if (cmd_line.HasSwitch( |
| 593 installer::switches::kRegisterChromeBrowser)) { | 729 installer::switches::kRegisterChromeBrowser)) { |
| 594 const Product* chrome_install = | 730 const Product* chrome_install = |
| 595 FindProduct(installs.products(), BrowserDistribution::CHROME_BROWSER); | 731 installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER); |
| 596 DCHECK(chrome_install); | |
| 597 if (chrome_install) { | 732 if (chrome_install) { |
| 598 // If --register-chrome-browser option is specified, register all | 733 // If --register-chrome-browser option is specified, register all |
| 599 // Chrome protocol/file associations as well as register it as a valid | 734 // Chrome protocol/file associations as well as register it as a valid |
| 600 // browser for Start Menu->Internet shortcut. This option should only | 735 // browser for Start Menu->Internet shortcut. This option should only |
| 601 // be used when setup.exe is launched with admin rights. We do not | 736 // be used when setup.exe is launched with admin rights. We do not |
| 602 // make any user specific changes in this option. | 737 // make any user specific changes in this option. |
| 603 std::wstring chrome_exe(cmd_line.GetSwitchValueNative( | 738 std::wstring chrome_exe(cmd_line.GetSwitchValueNative( |
| 604 installer::switches::kRegisterChromeBrowser)); | 739 installer::switches::kRegisterChromeBrowser)); |
| 605 std::wstring suffix; | 740 std::wstring suffix; |
| 606 if (cmd_line.HasSwitch( | 741 if (cmd_line.HasSwitch( |
| 607 installer::switches::kRegisterChromeBrowserSuffix)) { | 742 installer::switches::kRegisterChromeBrowserSuffix)) { |
| 608 suffix = cmd_line.GetSwitchValueNative( | 743 suffix = cmd_line.GetSwitchValueNative( |
| 609 installer::switches::kRegisterChromeBrowserSuffix); | 744 installer::switches::kRegisterChromeBrowserSuffix); |
| 610 } | 745 } |
| 611 *exit_code = ShellUtil::RegisterChromeBrowser( | 746 *exit_code = ShellUtil::RegisterChromeBrowser( |
| 612 chrome_install->distribution(), chrome_exe, suffix, false); | 747 chrome_install->distribution(), chrome_exe, suffix, false); |
| 613 } else { | 748 } else { |
| 614 LOG(ERROR) << "Can't register browser - Chrome distribution not found"; | 749 LOG(DFATAL) << "Can't register browser - Chrome distribution not found"; |
| 615 *exit_code = installer::UNKNOWN_STATUS; | 750 *exit_code = installer::UNKNOWN_STATUS; |
| 616 } | 751 } |
| 617 } else if (cmd_line.HasSwitch(installer::switches::kRenameChromeExe)) { | 752 } else if (cmd_line.HasSwitch(installer::switches::kRenameChromeExe)) { |
| 618 // If --rename-chrome-exe is specified, we want to rename the executables | 753 // If --rename-chrome-exe is specified, we want to rename the executables |
| 619 // and exit. | 754 // and exit. |
| 620 const Packages& packages = installs.packages(); | 755 *exit_code = RenameChromeExecutables(installer_state); |
| 621 DCHECK_EQ(1U, packages.size()); | |
| 622 for (size_t i = 0; i < packages.size(); ++i) | |
| 623 *exit_code = RenameChromeExecutables(*packages[i].get()); | |
| 624 } else if (cmd_line.HasSwitch( | 756 } else if (cmd_line.HasSwitch( |
| 625 installer::switches::kRemoveChromeRegistration)) { | 757 installer::switches::kRemoveChromeRegistration)) { |
| 626 // This is almost reverse of --register-chrome-browser option above. | 758 // This is almost reverse of --register-chrome-browser option above. |
| 627 // Here we delete Chrome browser registration. This option should only | 759 // Here we delete Chrome browser registration. This option should only |
| 628 // be used when setup.exe is launched with admin rights. We do not | 760 // be used when setup.exe is launched with admin rights. We do not |
| 629 // make any user specific changes in this option. | 761 // make any user specific changes in this option. |
| 630 std::wstring suffix; | 762 std::wstring suffix; |
| 631 if (cmd_line.HasSwitch( | 763 if (cmd_line.HasSwitch( |
| 632 installer::switches::kRegisterChromeBrowserSuffix)) { | 764 installer::switches::kRegisterChromeBrowserSuffix)) { |
| 633 suffix = cmd_line.GetSwitchValueNative( | 765 suffix = cmd_line.GetSwitchValueNative( |
| 634 installer::switches::kRegisterChromeBrowserSuffix); | 766 installer::switches::kRegisterChromeBrowserSuffix); |
| 635 } | 767 } |
| 636 installer::InstallStatus tmp = installer::UNKNOWN_STATUS; | 768 installer::InstallStatus tmp = installer::UNKNOWN_STATUS; |
| 637 const Product* chrome_install = | 769 const Product* chrome_install = |
| 638 FindProduct(installs.products(), BrowserDistribution::CHROME_BROWSER); | 770 installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER); |
| 639 DCHECK(chrome_install); | 771 DCHECK(chrome_install); |
| 640 if (chrome_install) { | 772 if (chrome_install) { |
| 641 installer::DeleteChromeRegistrationKeys(chrome_install->distribution(), | 773 installer::DeleteChromeRegistrationKeys(chrome_install->distribution(), |
| 642 HKEY_LOCAL_MACHINE, suffix, tmp); | 774 HKEY_LOCAL_MACHINE, suffix, tmp); |
| 643 } | 775 } |
| 644 *exit_code = tmp; | 776 *exit_code = tmp; |
| 645 } else if (cmd_line.HasSwitch(installer::switches::kInactiveUserToast)) { | 777 } else if (cmd_line.HasSwitch(installer::switches::kInactiveUserToast)) { |
| 646 // Launch the inactive user toast experiment. | 778 // Launch the inactive user toast experiment. |
| 647 int flavor = -1; | 779 int flavor = -1; |
| 648 base::StringToInt(cmd_line.GetSwitchValueNative( | 780 base::StringToInt(cmd_line.GetSwitchValueNative( |
| 649 installer::switches::kInactiveUserToast), &flavor); | 781 installer::switches::kInactiveUserToast), &flavor); |
| 650 DCHECK_NE(-1, flavor); | 782 DCHECK_NE(-1, flavor); |
| 651 if (flavor == -1) { | 783 if (flavor == -1) { |
| 652 *exit_code = installer::UNKNOWN_STATUS; | 784 *exit_code = installer::UNKNOWN_STATUS; |
| 653 } else { | 785 } else { |
| 654 const Products& products = installs.products(); | 786 const Products& products = installer_state.products(); |
| 655 for (size_t i = 0; i < products.size(); ++i) { | 787 for (size_t i = 0; i < products.size(); ++i) { |
| 656 const Product* product = products[i]; | 788 const Product* product = products[i]; |
| 657 BrowserDistribution* browser_dist = product->distribution(); | 789 BrowserDistribution* browser_dist = product->distribution(); |
| 658 browser_dist->InactiveUserToastExperiment(flavor, *product); | 790 browser_dist->InactiveUserToastExperiment(flavor, *product, |
| 791 installer_state.target_path()); | |
| 659 } | 792 } |
| 660 } | 793 } |
| 661 } else if (cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { | 794 } else if (cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { |
| 662 const Products& products = installs.products(); | 795 const Products& products = installer_state.products(); |
| 663 for (size_t i = 0; i < products.size(); ++i) { | 796 for (size_t i = 0; i < products.size(); ++i) { |
| 664 const Product* product = products[i]; | 797 const Product* product = products[i]; |
| 665 BrowserDistribution* browser_dist = product->distribution(); | 798 BrowserDistribution* browser_dist = product->distribution(); |
| 666 // We started as system-level and have been re-launched as user level | 799 // We started as system-level and have been re-launched as user level |
| 667 // to continue with the toast experiment. | 800 // to continue with the toast experiment. |
| 668 scoped_ptr<Version> installed_version( | 801 scoped_ptr<Version> installed_version( |
| 669 InstallUtil::GetChromeVersion(browser_dist, installs.system_level())); | 802 InstallUtil::GetChromeVersion(browser_dist, |
| 803 installer_state.system_install())); | |
| 670 browser_dist->LaunchUserExperiment(installer::REENTRY_SYS_UPDATE, | 804 browser_dist->LaunchUserExperiment(installer::REENTRY_SYS_UPDATE, |
| 671 *installed_version, *product, true); | 805 *installed_version, *product, true); |
| 672 } | 806 } |
| 673 } else if (cmd_line.HasSwitch( | 807 } else if (cmd_line.HasSwitch( |
| 674 installer::switches::kChromeFrameReadyModeOptIn)) { | 808 installer::switches::kChromeFrameReadyModeOptIn)) { |
| 675 *exit_code = InstallUtil::GetInstallReturnCode( | 809 *exit_code = InstallUtil::GetInstallReturnCode( |
| 676 installer::ChromeFrameReadyModeOptIn(installer_state, cmd_line)); | 810 installer::ChromeFrameReadyModeOptIn(original_state, installer_state)); |
| 677 } else if (cmd_line.HasSwitch( | 811 } else if (cmd_line.HasSwitch( |
| 678 installer::switches::kChromeFrameReadyModeTempOptOut)) { | 812 installer::switches::kChromeFrameReadyModeTempOptOut)) { |
| 679 *exit_code = InstallUtil::GetInstallReturnCode( | 813 *exit_code = InstallUtil::GetInstallReturnCode( |
| 680 installer::ChromeFrameReadyModeTempOptOut(cmd_line)); | 814 installer::ChromeFrameReadyModeTempOptOut(original_state, |
| 815 installer_state)); | |
| 681 } else if (cmd_line.HasSwitch( | 816 } else if (cmd_line.HasSwitch( |
| 682 installer::switches::kChromeFrameReadyModeEndTempOptOut)) { | 817 installer::switches::kChromeFrameReadyModeEndTempOptOut)) { |
| 683 *exit_code = InstallUtil::GetInstallReturnCode( | 818 *exit_code = InstallUtil::GetInstallReturnCode( |
| 684 installer::ChromeFrameReadyModeEndTempOptOut(cmd_line)); | 819 installer::ChromeFrameReadyModeEndTempOptOut(original_state, |
| 820 installer_state)); | |
| 685 } else { | 821 } else { |
| 686 handled = false; | 822 handled = false; |
| 687 } | 823 } |
| 688 | 824 |
| 689 return handled; | 825 return handled; |
| 690 } | 826 } |
| 691 | 827 |
| 692 bool ShowRebootDialog() { | 828 bool ShowRebootDialog() { |
| 693 // Get a token for this process. | 829 // Get a token for this process. |
| 694 HANDLE token; | 830 HANDLE token; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 736 return false; | 872 return false; |
| 737 } | 873 } |
| 738 initialized_ = true; | 874 initialized_ = true; |
| 739 return true; | 875 return true; |
| 740 } | 876 } |
| 741 | 877 |
| 742 private: | 878 private: |
| 743 bool initialized_; | 879 bool initialized_; |
| 744 }; | 880 }; |
| 745 | 881 |
| 746 bool PopulateInstallations(bool for_uninstall, | |
| 747 const MasterPreferences& prefs, | |
| 748 ProductPackageMapping* installations) { | |
| 749 DCHECK(installations); | |
| 750 bool success = true; | |
| 751 | 882 |
| 752 bool implicit_chrome_install = false; | |
| 753 bool implicit_gcf_install = false; | |
| 754 | 883 |
| 755 // See what products are already installed in multi mode. | |
| 756 // When we do multi installs, we must upgrade all installations in sync since | |
| 757 // they share the binaries. Be careful to not do this when we're uninstalling | |
| 758 // a product. | |
| 759 if (prefs.is_multi_install() && !for_uninstall) { | |
| 760 struct CheckInstall { | |
| 761 bool* installed; | |
| 762 BrowserDistribution::Type type; | |
| 763 } product_checks[] = { | |
| 764 {&implicit_chrome_install, BrowserDistribution::CHROME_BROWSER}, | |
| 765 {&implicit_gcf_install, BrowserDistribution::CHROME_FRAME}, | |
| 766 }; | |
| 767 | 884 |
| 768 for (size_t i = 0; i < arraysize(product_checks); ++i) { | |
| 769 BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution( | |
| 770 product_checks[i].type, prefs); | |
| 771 *product_checks[i].installed = installer::IsInstalledAsMulti( | |
| 772 installations->system_level(), dist); | |
| 773 LOG_IF(INFO, *product_checks[i].installed) | |
| 774 << "Product already installed and must be included: " | |
| 775 << dist->GetApplicationName(); | |
| 776 } | |
| 777 } | |
| 778 | |
| 779 if (prefs.install_chrome() || implicit_chrome_install) { | |
| 780 VLOG(1) << (for_uninstall ? "Uninstall" : "Install") | |
| 781 << " distribution: Chrome"; | |
| 782 success = installations->AddDistribution( | |
| 783 BrowserDistribution::CHROME_BROWSER, prefs); | |
| 784 } | |
| 785 | |
| 786 if (success && (prefs.install_chrome_frame() || implicit_gcf_install)) { | |
| 787 VLOG(1) << (for_uninstall ? "Uninstall" : "Install") | |
| 788 << " distribution: Chrome Frame"; | |
| 789 success = installations->AddDistribution( | |
| 790 BrowserDistribution::CHROME_FRAME, prefs); | |
| 791 } | |
| 792 return success; | |
| 793 } | |
| 794 | 885 |
| 795 // Returns the Custom information for the client identified by the exe path | 886 // Returns the Custom information for the client identified by the exe path |
| 796 // passed in. This information is used for crash reporting. | 887 // passed in. This information is used for crash reporting. |
| 797 google_breakpad::CustomClientInfo* GetCustomInfo(const wchar_t* exe_path) { | 888 google_breakpad::CustomClientInfo* GetCustomInfo(const wchar_t* exe_path) { |
| 798 std::wstring product; | 889 std::wstring product; |
| 799 std::wstring version; | 890 std::wstring version; |
| 800 scoped_ptr<FileVersionInfo> | 891 scoped_ptr<FileVersionInfo> |
| 801 version_info(FileVersionInfo::CreateFileVersionInfo(FilePath(exe_path))); | 892 version_info(FileVersionInfo::CreateFileVersionInfo(FilePath(exe_path))); |
| 802 if (version_info.get()) { | 893 if (version_info.get()) { |
| 803 version = version_info->product_version(); | 894 version = version_info->product_version(); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 876 | 967 |
| 877 VLOG(1) << "multi install is " << prefs.is_multi_install(); | 968 VLOG(1) << "multi install is " << prefs.is_multi_install(); |
| 878 bool system_install = false; | 969 bool system_install = false; |
| 879 prefs.GetBool(installer::master_preferences::kSystemLevel, &system_install); | 970 prefs.GetBool(installer::master_preferences::kSystemLevel, &system_install); |
| 880 VLOG(1) << "system install is " << system_install; | 971 VLOG(1) << "system install is " << system_install; |
| 881 | 972 |
| 882 google_breakpad::scoped_ptr<google_breakpad::ExceptionHandler> breakpad( | 973 google_breakpad::scoped_ptr<google_breakpad::ExceptionHandler> breakpad( |
| 883 InitializeCrashReporting(system_install)); | 974 InitializeCrashReporting(system_install)); |
| 884 | 975 |
| 885 InstallationState original_state; | 976 InstallationState original_state; |
| 886 original_state.Initialize(prefs); | 977 original_state.Initialize(); |
| 887 | 978 |
| 888 InstallerState installer_state; | 979 InstallerState installer_state; |
| 889 installer_state.Initialize(prefs, original_state); | 980 installer_state.Initialize(cmd_line, prefs, original_state); |
| 890 const bool is_uninstall = cmd_line.HasSwitch(installer::switches::kUninstall); | 981 const bool is_uninstall = cmd_line.HasSwitch(installer::switches::kUninstall); |
| 891 | 982 |
| 892 ProductPackageMapping installations(prefs.is_multi_install(), system_install); | |
| 893 if (!PopulateInstallations(is_uninstall, prefs, &installations)) { | |
| 894 // Currently this can only fail if one of the installations is a multi and | |
| 895 // a pre-existing single installation exists or vice versa. | |
| 896 installer::InstallStatus status = installer::NON_MULTI_INSTALLATION_EXISTS; | |
| 897 int string_id = IDS_INSTALL_NON_MULTI_INSTALLATION_EXISTS_BASE; | |
| 898 if (!prefs.is_multi_install()) { | |
| 899 status = installer::MULTI_INSTALLATION_EXISTS; | |
| 900 string_id = IDS_INSTALL_MULTI_INSTALLATION_EXISTS_BASE; | |
| 901 } | |
| 902 LOG(ERROR) << "Failed to populate installations: " << status; | |
| 903 InstallUtil::WriteInstallerResult(system_install, | |
| 904 installer_state.state_key(), status, string_id, NULL); | |
| 905 return status; | |
| 906 } | |
| 907 | |
| 908 // Check to make sure current system is WinXP or later. If not, log | 983 // Check to make sure current system is WinXP or later. If not, log |
| 909 // error message and get out. | 984 // error message and get out. |
| 910 if (!InstallUtil::IsOSSupported()) { | 985 if (!InstallUtil::IsOSSupported()) { |
| 911 LOG(ERROR) << "Chrome only supports Windows XP or later."; | 986 LOG(ERROR) << "Chrome only supports Windows XP or later."; |
| 912 InstallUtil::WriteInstallerResult(system_install, | 987 InstallUtil::WriteInstallerResult(system_install, |
| 913 installer_state.state_key(), installer::OS_NOT_SUPPORTED, | 988 installer_state.state_key(), installer::OS_NOT_SUPPORTED, |
| 914 IDS_INSTALL_OS_NOT_SUPPORTED_BASE, NULL); | 989 IDS_INSTALL_OS_NOT_SUPPORTED_BASE, NULL); |
| 915 return installer::OS_NOT_SUPPORTED; | 990 return installer::OS_NOT_SUPPORTED; |
| 916 } | 991 } |
| 917 | 992 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 933 cmd_line.HasSwitch(installer::switches::kRegisterChromeBrowser) || | 1008 cmd_line.HasSwitch(installer::switches::kRegisterChromeBrowser) || |
| 934 cmd_line.HasSwitch( | 1009 cmd_line.HasSwitch( |
| 935 installer::switches::kRemoveChromeRegistration) || | 1010 installer::switches::kRemoveChromeRegistration) || |
| 936 cmd_line.HasSwitch(installer::switches::kInactiveUserToast) || | 1011 cmd_line.HasSwitch(installer::switches::kInactiveUserToast) || |
| 937 cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { | 1012 cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { |
| 938 return installer::SXS_OPTION_NOT_SUPPORTED; | 1013 return installer::SXS_OPTION_NOT_SUPPORTED; |
| 939 } | 1014 } |
| 940 } | 1015 } |
| 941 | 1016 |
| 942 int exit_code = 0; | 1017 int exit_code = 0; |
| 943 if (HandleNonInstallCmdLineOptions(installer_state, cmd_line, installations, | 1018 if (HandleNonInstallCmdLineOptions(original_state, cmd_line, installer_state, |
| 944 &exit_code)) | 1019 &exit_code)) |
| 945 return exit_code; | 1020 return exit_code; |
| 946 | 1021 |
| 947 if (system_install && !IsUserAnAdmin()) { | 1022 if (system_install && !IsUserAnAdmin()) { |
| 948 if (base::win::GetVersion() >= base::win::VERSION_VISTA && | 1023 if (base::win::GetVersion() >= base::win::VERSION_VISTA && |
| 949 !cmd_line.HasSwitch(installer::switches::kRunAsAdmin)) { | 1024 !cmd_line.HasSwitch(installer::switches::kRunAsAdmin)) { |
| 950 CommandLine new_cmd(CommandLine::NO_PROGRAM); | 1025 CommandLine new_cmd(CommandLine::NO_PROGRAM); |
| 951 new_cmd.AppendArguments(cmd_line, true); | 1026 new_cmd.AppendArguments(cmd_line, true); |
| 952 // Append --run-as-admin flag to let the new instance of setup.exe know | 1027 // Append --run-as-admin flag to let the new instance of setup.exe know |
| 953 // that we already tried to launch ourselves as admin. | 1028 // that we already tried to launch ourselves as admin. |
| 954 new_cmd.AppendSwitch(installer::switches::kRunAsAdmin); | 1029 new_cmd.AppendSwitch(installer::switches::kRunAsAdmin); |
| 955 DWORD exit_code = installer::UNKNOWN_STATUS; | 1030 DWORD exit_code = installer::UNKNOWN_STATUS; |
| 956 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); | 1031 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); |
| 957 return exit_code; | 1032 return exit_code; |
| 958 } else { | 1033 } else { |
| 959 LOG(ERROR) << "Non admin user can not install system level Chrome."; | 1034 LOG(ERROR) << "Non admin user can not install system level Chrome."; |
| 960 InstallUtil::WriteInstallerResult(system_install, | 1035 InstallUtil::WriteInstallerResult(system_install, |
| 961 installer_state.state_key(), installer::INSUFFICIENT_RIGHTS, | 1036 installer_state.state_key(), installer::INSUFFICIENT_RIGHTS, |
| 962 IDS_INSTALL_INSUFFICIENT_RIGHTS_BASE, NULL); | 1037 IDS_INSTALL_INSUFFICIENT_RIGHTS_BASE, NULL); |
| 963 return installer::INSUFFICIENT_RIGHTS; | 1038 return installer::INSUFFICIENT_RIGHTS; |
| 964 } | 1039 } |
| 965 } | 1040 } |
| 966 | 1041 |
| 967 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; | 1042 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; |
| 968 // If --uninstall option is given, uninstall chrome | 1043 // If --uninstall option is given, uninstall the identified product(s) |
| 969 if (is_uninstall) { | 1044 if (is_uninstall) { |
| 970 for (size_t i = 0; i < installations.products().size(); ++i) { | 1045 const Products& products = installer_state.products(); |
| 1046 for (size_t i = 0; i < products.size(); ++i) { | |
| 971 install_status = UninstallProduct(original_state, installer_state, | 1047 install_status = UninstallProduct(original_state, installer_state, |
| 972 cmd_line, *installations.products()[i]); | 1048 cmd_line, *products[i]); |
| 973 } | 1049 } |
| 974 } else { | 1050 } else { |
| 975 // If --uninstall option is not specified, we assume it is install case. | 1051 // If --uninstall option is not specified, we assume it is install case. |
| 976 const Packages& packages = installations.packages(); | 1052 VLOG(1) << "Installing to " << installer_state.target_path().value(); |
| 977 VLOG(1) << "Installing to " << packages.size() << " target paths"; | 1053 install_status = InstallProducts(original_state, cmd_line, prefs, |
| 978 for (size_t i = 0; i < packages.size(); ++i) { | 1054 &installer_state); |
| 979 install_status = InstallChrome(original_state, installer_state, cmd_line, | |
| 980 *packages[i].get(), prefs); | |
| 981 } | |
| 982 } | 1055 } |
| 983 | 1056 |
| 984 const Product* cf_install = | 1057 const Product* cf_install = |
| 985 FindProduct(installations.products(), BrowserDistribution::CHROME_FRAME); | 1058 installer_state.FindProduct(BrowserDistribution::CHROME_FRAME); |
| 986 | 1059 |
| 987 if (cf_install && | 1060 if (cf_install && |
| 988 !cmd_line.HasSwitch(installer::switches::kForceUninstall)) { | 1061 !cmd_line.HasSwitch(installer::switches::kForceUninstall)) { |
| 989 if (install_status == installer::UNINSTALL_REQUIRES_REBOOT) { | 1062 if (install_status == installer::UNINSTALL_REQUIRES_REBOOT) { |
| 990 ShowRebootDialog(); | 1063 ShowRebootDialog(); |
| 991 } else if (is_uninstall) { | 1064 } else if (is_uninstall) { |
| 992 // Only show the message box if Chrome Frame was the only product being | 1065 // Only show the message box if Chrome Frame was the only product being |
| 993 // uninstalled. | 1066 // uninstalled. |
| 994 if (installations.products().size() == 1U) { | 1067 if (installer_state.products().size() == 1U) { |
| 995 ::MessageBoxW(NULL, | 1068 ::MessageBoxW(NULL, |
| 996 installer::GetLocalizedString( | 1069 installer::GetLocalizedString( |
| 997 IDS_UNINSTALL_COMPLETE_BASE).c_str(), | 1070 IDS_UNINSTALL_COMPLETE_BASE).c_str(), |
| 998 cf_install->distribution()->GetApplicationName().c_str(), | 1071 cf_install->distribution()->GetApplicationName().c_str(), |
| 999 MB_OK); | 1072 MB_OK); |
| 1000 } | 1073 } |
| 1001 } | 1074 } |
| 1002 } | 1075 } |
| 1003 | 1076 |
| 1004 int return_code = 0; | 1077 int return_code = 0; |
| 1005 // MSI demands that custom actions always return 0 (ERROR_SUCCESS) or it will | 1078 // MSI demands that custom actions always return 0 (ERROR_SUCCESS) or it will |
| 1006 // rollback the action. If we're uninstalling we want to avoid this, so always | 1079 // rollback the action. If we're uninstalling we want to avoid this, so always |
| 1007 // report success, squashing any more informative return codes. | 1080 // report success, squashing any more informative return codes. |
| 1008 // TODO(tommi): Fix this loop when IsMsi has been moved out of the Product | 1081 if (!(installer_state.msi() && is_uninstall)) |
| 1009 // class. | 1082 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT |
| 1010 for (size_t i = 0; i < installations.products().size(); ++i) { | 1083 // to pass through, since this is only returned on uninstall which is |
| 1011 const Product* product = installations.products()[i]; | 1084 // never invoked directly by Google Update. |
| 1012 if (!(product->IsMsi() && is_uninstall)) { | 1085 return_code = InstallUtil::GetInstallReturnCode(install_status); |
| 1013 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT | |
| 1014 // to pass through, since this is only returned on uninstall which is | |
| 1015 // never invoked directly by Google Update. | |
| 1016 return_code = InstallUtil::GetInstallReturnCode(install_status); | |
| 1017 } | |
| 1018 } | |
| 1019 | 1086 |
| 1020 VLOG(1) << "Installation complete, returning: " << return_code; | 1087 VLOG(1) << "Installation complete, returning: " << return_code; |
| 1021 | 1088 |
| 1022 return return_code; | 1089 return return_code; |
| 1023 } | 1090 } |
| OLD | NEW |