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 <algorithm> | |
| 11 #include <functional> | |
| 10 #include <string> | 12 #include <string> |
| 11 | 13 |
| 12 #include "base/at_exit.h" | 14 #include "base/at_exit.h" |
| 13 #include "base/basictypes.h" | 15 #include "base/basictypes.h" |
| 14 #include "base/command_line.h" | 16 #include "base/command_line.h" |
| 15 #include "base/file_util.h" | 17 #include "base/file_util.h" |
| 16 #include "base/file_version_info.h" | 18 #include "base/file_version_info.h" |
| 17 #include "base/memory/scoped_temp_dir.h" | 19 #include "base/memory/scoped_temp_dir.h" |
| 18 #include "base/path_service.h" | 20 #include "base/path_service.h" |
| 19 #include "base/process_util.h" | 21 #include "base/process_util.h" |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 134 *archive_type = installer::FULL_ARCHIVE_TYPE; | 136 *archive_type = installer::FULL_ARCHIVE_TYPE; |
| 135 } | 137 } |
| 136 | 138 |
| 137 installer_state.UpdateStage(installer::UNPACKING); | 139 installer_state.UpdateStage(installer::UNPACKING); |
| 138 | 140 |
| 139 // Unpack the uncompressed archive. | 141 // Unpack the uncompressed archive. |
| 140 return LzmaUtil::UnPackArchive(uncompressed_archive.value(), | 142 return LzmaUtil::UnPackArchive(uncompressed_archive.value(), |
| 141 output_directory.value(), &unpacked_file); | 143 output_directory.value(), &unpacked_file); |
| 142 } | 144 } |
| 143 | 145 |
| 146 // In multi-install, adds all products to |installer_state| that are | |
| 147 // multi-installed and must be updated along with the products already present | |
| 148 // in |installer_state|. | |
| 149 void AddExistingMultiInstalls(const InstallationState& original_state, | |
|
grt (UTC plus 2)
2011/05/07 03:18:47
Note to reviewers: this function was simply moved
| |
| 150 InstallerState* installer_state) { | |
| 151 if (installer_state->is_multi_install()) { | |
| 152 BrowserDistribution::Type product_checks[] = { | |
|
robertshield
2011/05/09 14:03:57
We have occurrences of this particular array in a
grt (UTC plus 2)
2011/05/09 14:29:52
Done.
| |
| 153 BrowserDistribution::CHROME_BROWSER, | |
| 154 BrowserDistribution::CHROME_FRAME | |
| 155 }; | |
| 156 | |
| 157 for (size_t i = 0; i < arraysize(product_checks); ++i) { | |
| 158 BrowserDistribution::Type type = product_checks[i]; | |
| 159 if (!installer_state->FindProduct(type)) { | |
| 160 const ProductState* state = | |
| 161 original_state.GetProductState(installer_state->system_install(), | |
| 162 type); | |
| 163 if ((state != NULL) && state->is_multi_install()) { | |
| 164 installer_state->AddProductFromState(type, *state); | |
| 165 VLOG(1) << "Product already installed and must be included: " | |
| 166 << BrowserDistribution::GetSpecificDistribution( | |
| 167 type)->GetApplicationName(); | |
| 168 } | |
| 169 } | |
| 170 } | |
| 171 } | |
| 172 } | |
| 173 | |
| 144 // This function is called when --rename-chrome-exe option is specified on | 174 // This function is called when --rename-chrome-exe option is specified on |
| 145 // setup.exe command line. This function assumes an in-use update has happened | 175 // setup.exe command line. This function assumes an in-use update has happened |
| 146 // for Chrome so there should be a file called new_chrome.exe on the file | 176 // for Chrome so there should be a file called new_chrome.exe on the file |
| 147 // system and a key called 'opv' in the registry. This function will move | 177 // system and a key called 'opv' in the registry. This function will move |
| 148 // new_chrome.exe to chrome.exe and delete 'opv' key in one atomic operation. | 178 // new_chrome.exe to chrome.exe and delete 'opv' key in one atomic operation. |
| 149 installer::InstallStatus RenameChromeExecutables( | 179 installer::InstallStatus RenameChromeExecutables( |
| 150 const InstallerState& installer_state) { | 180 const InstallationState& original_state, |
| 151 const FilePath &target_path = installer_state.target_path(); | 181 InstallerState* installer_state) { |
| 182 // See what products are already installed in multi mode. When we do the | |
| 183 // rename for multi installs, we must update all installations since they | |
| 184 // share the binaries. | |
| 185 AddExistingMultiInstalls(original_state, installer_state); | |
| 186 const FilePath &target_path = installer_state->target_path(); | |
| 152 FilePath chrome_exe(target_path.Append(installer::kChromeExe)); | 187 FilePath chrome_exe(target_path.Append(installer::kChromeExe)); |
| 153 FilePath chrome_new_exe(target_path.Append(installer::kChromeNewExe)); | 188 FilePath chrome_new_exe(target_path.Append(installer::kChromeNewExe)); |
| 154 FilePath chrome_old_exe(target_path.Append(installer::kChromeOldExe)); | 189 FilePath chrome_old_exe(target_path.Append(installer::kChromeOldExe)); |
| 155 | 190 |
| 156 // Create a temporary backup directory on the same volume as chrome.exe so | 191 // Create a temporary backup directory on the same volume as chrome.exe so |
| 157 // that moving in-use files doesn't lead to trouble. | 192 // that moving in-use files doesn't lead to trouble. |
| 158 installer::SelfCleaningTempDir temp_path; | 193 installer::SelfCleaningTempDir temp_path; |
| 159 if (!temp_path.Initialize(target_path.DirName(), | 194 if (!temp_path.Initialize(target_path.DirName(), |
| 160 installer::kInstallTempDir)) { | 195 installer::kInstallTempDir)) { |
| 161 PLOG(ERROR) << "Failed to create Temp directory " | 196 PLOG(ERROR) << "Failed to create Temp directory " |
| 162 << target_path.DirName() | 197 << target_path.DirName() |
| 163 .Append(installer::kInstallTempDir).value(); | 198 .Append(installer::kInstallTempDir).value(); |
| 164 return installer::RENAME_FAILED; | 199 return installer::RENAME_FAILED; |
| 165 } | 200 } |
| 166 scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); | 201 scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); |
| 167 // Move chrome.exe to old_chrome.exe, then move new_chrome.exe to chrome.exe. | 202 // Move chrome.exe to old_chrome.exe, then move new_chrome.exe to chrome.exe. |
| 168 install_list->AddMoveTreeWorkItem(chrome_exe.value(), | 203 install_list->AddMoveTreeWorkItem(chrome_exe.value(), |
| 169 chrome_old_exe.value(), | 204 chrome_old_exe.value(), |
| 170 temp_path.path().value()); | 205 temp_path.path().value()); |
| 171 install_list->AddMoveTreeWorkItem(chrome_new_exe.value(), | 206 install_list->AddMoveTreeWorkItem(chrome_new_exe.value(), |
| 172 chrome_exe.value(), | 207 chrome_exe.value(), |
| 173 temp_path.path().value()); | 208 temp_path.path().value()); |
| 174 install_list->AddDeleteTreeWorkItem(chrome_new_exe, temp_path.path()); | 209 install_list->AddDeleteTreeWorkItem(chrome_new_exe, temp_path.path()); |
| 175 // old_chrome.exe is still in use in most cases, so ignore failures here. | 210 // old_chrome.exe is still in use in most cases, so ignore failures here. |
| 176 install_list->AddDeleteTreeWorkItem(chrome_old_exe, temp_path.path()) | 211 install_list->AddDeleteTreeWorkItem(chrome_old_exe, temp_path.path()) |
| 177 ->set_ignore_failure(true); | 212 ->set_ignore_failure(true); |
| 178 | 213 |
| 179 HKEY reg_root = installer_state.root_key(); | 214 // Collect the set of distributions we need to update. |
| 180 const Products& products = installer_state.products(); | 215 BrowserDistribution* dists[BrowserDistribution::NUM_TYPES]; |
| 181 for (size_t i = 0; i < products.size(); ++i) { | 216 int num_dists = 0; |
| 182 const Product* product = products[i]; | 217 if (installer_state->is_multi_install()) |
| 183 BrowserDistribution* browser_dist = product->distribution(); | 218 dists[num_dists++] = installer_state->multi_package_binaries_distribution(); |
| 184 std::wstring version_key(browser_dist->GetVersionKey()); | 219 const Products& products = installer_state->products(); |
| 220 num_dists = std::transform(products.begin(), products.end(), | |
| 221 &dists[num_dists], | |
| 222 std::mem_fun(&Product::distribution)) - &dists[0]; | |
|
robertshield
2011/05/09 14:03:57
The above eight lines are a bit too clever imo. Th
grt (UTC plus 2)
2011/05/09 14:29:52
Done.
| |
| 223 | |
| 224 // Add work items to delete the "opv" and "cmd" values from all distributions. | |
| 225 HKEY reg_root = installer_state->root_key(); | |
| 226 std::wstring version_key; | |
| 227 for (int i = 0; i < num_dists; ++i) { | |
| 228 version_key = dists[i]->GetVersionKey(); | |
| 185 install_list->AddDeleteRegValueWorkItem(reg_root, | 229 install_list->AddDeleteRegValueWorkItem(reg_root, |
| 186 version_key, | 230 version_key, |
| 187 google_update::kRegOldVersionField); | 231 google_update::kRegOldVersionField); |
| 188 install_list->AddDeleteRegValueWorkItem(reg_root, | 232 install_list->AddDeleteRegValueWorkItem(reg_root, |
| 189 version_key, | 233 version_key, |
| 190 google_update::kRegRenameCmdField); | 234 google_update::kRegRenameCmdField); |
| 191 } | 235 } |
| 192 installer::InstallStatus ret = installer::RENAME_SUCCESSFUL; | 236 installer::InstallStatus ret = installer::RENAME_SUCCESSFUL; |
| 193 if (!install_list->Do()) { | 237 if (!install_list->Do()) { |
| 194 LOG(ERROR) << "Renaming of executables failed. Rolling back any changes."; | 238 LOG(ERROR) << "Renaming of executables failed. Rolling back any changes."; |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 322 } else if (DCHECK_IS_ON()) { | 366 } else if (DCHECK_IS_ON()) { |
| 323 // It isn't possible to stuff two products into a single-install | 367 // It isn't possible to stuff two products into a single-install |
| 324 // InstallerState. Abort the process here in debug builds just in case | 368 // InstallerState. Abort the process here in debug builds just in case |
| 325 // someone finds a way. | 369 // someone finds a way. |
| 326 DCHECK_EQ(1U, products.size()); | 370 DCHECK_EQ(1U, products.size()); |
| 327 } | 371 } |
| 328 | 372 |
| 329 return true; | 373 return true; |
| 330 } | 374 } |
| 331 | 375 |
| 332 // In multi-install, adds all products to |installer_state| that are | |
| 333 // multi-installed and must be updated along with the products already present | |
| 334 // in |installer_state|. | |
| 335 void AddExistingMultiInstalls(const InstallationState& original_state, | |
| 336 InstallerState* installer_state) { | |
| 337 if (installer_state->is_multi_install()) { | |
| 338 BrowserDistribution::Type product_checks[] = { | |
| 339 BrowserDistribution::CHROME_BROWSER, | |
| 340 BrowserDistribution::CHROME_FRAME | |
| 341 }; | |
| 342 | |
| 343 for (size_t i = 0; i < arraysize(product_checks); ++i) { | |
| 344 BrowserDistribution::Type type = product_checks[i]; | |
| 345 if (!installer_state->FindProduct(type)) { | |
| 346 const ProductState* state = | |
| 347 original_state.GetProductState(installer_state->system_install(), | |
| 348 type); | |
| 349 if ((state != NULL) && state->is_multi_install()) { | |
| 350 installer_state->AddProductFromState(type, *state); | |
| 351 VLOG(1) << "Product already installed and must be included: " | |
| 352 << BrowserDistribution::GetSpecificDistribution( | |
| 353 type)->GetApplicationName(); | |
| 354 } | |
| 355 } | |
| 356 } | |
| 357 } | |
| 358 } | |
| 359 | |
| 360 // Checks for compatibility between the current state of the system and the | 376 // Checks for compatibility between the current state of the system and the |
| 361 // desired operation. Also applies policy that mutates the desired operation; | 377 // desired operation. Also applies policy that mutates the desired operation; |
| 362 // specifically, the |installer_state| object. | 378 // specifically, the |installer_state| object. |
| 363 // Also blocks simultaneous user-level and system-level installs. In the case | 379 // Also blocks simultaneous user-level and system-level installs. In the case |
| 364 // of trying to install user-level Chrome when system-level exists, the | 380 // of trying to install user-level Chrome when system-level exists, the |
| 365 // existing system-level Chrome is launched. | 381 // existing system-level Chrome is launched. |
| 366 // When the pre-install conditions are not satisfied, the result is written to | 382 // When the pre-install conditions are not satisfied, the result is written to |
| 367 // the registry (via WriteInstallerResult), |status| is set appropriately, and | 383 // the registry (via WriteInstallerResult), |status| is set appropriately, and |
| 368 // false is returned. | 384 // false is returned. |
| 369 bool CheckPreInstallConditions(const InstallationState& original_state, | 385 bool CheckPreInstallConditions(const InstallationState& original_state, |
| (...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 847 } | 863 } |
| 848 *exit_code = ShellUtil::RegisterChromeBrowser( | 864 *exit_code = ShellUtil::RegisterChromeBrowser( |
| 849 chrome_install->distribution(), chrome_exe, suffix, false); | 865 chrome_install->distribution(), chrome_exe, suffix, false); |
| 850 } else { | 866 } else { |
| 851 LOG(DFATAL) << "Can't register browser - Chrome distribution not found"; | 867 LOG(DFATAL) << "Can't register browser - Chrome distribution not found"; |
| 852 *exit_code = installer::UNKNOWN_STATUS; | 868 *exit_code = installer::UNKNOWN_STATUS; |
| 853 } | 869 } |
| 854 } else if (cmd_line.HasSwitch(installer::switches::kRenameChromeExe)) { | 870 } else if (cmd_line.HasSwitch(installer::switches::kRenameChromeExe)) { |
| 855 // If --rename-chrome-exe is specified, we want to rename the executables | 871 // If --rename-chrome-exe is specified, we want to rename the executables |
| 856 // and exit. | 872 // and exit. |
| 857 *exit_code = RenameChromeExecutables(*installer_state); | 873 *exit_code = RenameChromeExecutables(original_state, installer_state); |
| 858 } else if (cmd_line.HasSwitch( | 874 } else if (cmd_line.HasSwitch( |
| 859 installer::switches::kRemoveChromeRegistration)) { | 875 installer::switches::kRemoveChromeRegistration)) { |
| 860 // This is almost reverse of --register-chrome-browser option above. | 876 // This is almost reverse of --register-chrome-browser option above. |
| 861 // Here we delete Chrome browser registration. This option should only | 877 // Here we delete Chrome browser registration. This option should only |
| 862 // be used when setup.exe is launched with admin rights. We do not | 878 // be used when setup.exe is launched with admin rights. We do not |
| 863 // make any user specific changes in this option. | 879 // make any user specific changes in this option. |
| 864 std::wstring suffix; | 880 std::wstring suffix; |
| 865 if (cmd_line.HasSwitch( | 881 if (cmd_line.HasSwitch( |
| 866 installer::switches::kRegisterChromeBrowserSuffix)) { | 882 installer::switches::kRegisterChromeBrowserSuffix)) { |
| 867 suffix = cmd_line.GetSwitchValueNative( | 883 suffix = cmd_line.GetSwitchValueNative( |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1208 if (!(installer_state.is_msi() && is_uninstall)) | 1224 if (!(installer_state.is_msi() && is_uninstall)) |
| 1209 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT | 1225 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT |
| 1210 // to pass through, since this is only returned on uninstall which is | 1226 // to pass through, since this is only returned on uninstall which is |
| 1211 // never invoked directly by Google Update. | 1227 // never invoked directly by Google Update. |
| 1212 return_code = InstallUtil::GetInstallReturnCode(install_status); | 1228 return_code = InstallUtil::GetInstallReturnCode(install_status); |
| 1213 | 1229 |
| 1214 VLOG(1) << "Installation complete, returning: " << return_code; | 1230 VLOG(1) << "Installation complete, returning: " << return_code; |
| 1215 | 1231 |
| 1216 return return_code; | 1232 return return_code; |
| 1217 } | 1233 } |
| OLD | NEW |