| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // This file contains the definitions of the installer functions that build | 5 // This file contains the definitions of the installer functions that build |
| 6 // the WorkItemList used to install the application. | 6 // the WorkItemList used to install the application. |
| 7 | 7 |
| 8 #include "chrome/installer/setup/install_worker.h" | 8 #include "chrome/installer/setup/install_worker.h" |
| 9 | 9 |
| 10 #include <windows.h> // NOLINT | 10 #include <windows.h> // NOLINT |
| 11 #include <atlsecurity.h> | 11 #include <atlsecurity.h> |
| 12 #include <oaidl.h> | 12 #include <oaidl.h> |
| 13 #include <shlobj.h> | 13 #include <shlobj.h> |
| 14 #include <stddef.h> | 14 #include <stddef.h> |
| 15 #include <stdint.h> | 15 #include <stdint.h> |
| 16 #include <time.h> | 16 #include <time.h> |
| 17 | 17 |
| 18 #include <memory> | 18 #include <memory> |
| 19 #include <vector> | 19 #include <vector> |
| 20 | 20 |
| 21 #include "base/bind.h" | 21 #include "base/bind.h" |
| 22 #include "base/command_line.h" | 22 #include "base/command_line.h" |
| 23 #include "base/files/file_path.h" | 23 #include "base/files/file_path.h" |
| 24 #include "base/files/file_util.h" | 24 #include "base/files/file_util.h" |
| 25 #include "base/logging.h" | 25 #include "base/logging.h" |
| 26 #include "base/macros.h" | |
| 27 #include "base/path_service.h" | |
| 28 #include "base/strings/string_util.h" | 26 #include "base/strings/string_util.h" |
| 29 #include "base/strings/utf_string_conversions.h" | 27 #include "base/strings/utf_string_conversions.h" |
| 30 #include "base/version.h" | 28 #include "base/version.h" |
| 31 #include "base/win/registry.h" | 29 #include "base/win/registry.h" |
| 32 #include "base/win/windows_version.h" | |
| 33 #include "chrome/common/chrome_constants.h" | |
| 34 #include "chrome/common/chrome_switches.h" | |
| 35 #include "chrome/installer/setup/app_launcher_installer.h" | |
| 36 #include "chrome/installer/setup/install.h" | |
| 37 #include "chrome/installer/setup/installer_state.h" | 30 #include "chrome/installer/setup/installer_state.h" |
| 38 #include "chrome/installer/setup/persistent_histogram_storage.h" | 31 #include "chrome/installer/setup/persistent_histogram_storage.h" |
| 39 #include "chrome/installer/setup/setup_constants.h" | 32 #include "chrome/installer/setup/setup_constants.h" |
| 40 #include "chrome/installer/setup/setup_util.h" | 33 #include "chrome/installer/setup/setup_util.h" |
| 41 #include "chrome/installer/setup/update_active_setup_version_work_item.h" | 34 #include "chrome/installer/setup/update_active_setup_version_work_item.h" |
| 42 #include "chrome/installer/util/app_registration_data.h" | 35 #include "chrome/installer/util/app_registration_data.h" |
| 43 #include "chrome/installer/util/browser_distribution.h" | 36 #include "chrome/installer/util/browser_distribution.h" |
| 44 #include "chrome/installer/util/callback_work_item.h" | 37 #include "chrome/installer/util/callback_work_item.h" |
| 45 #include "chrome/installer/util/conditional_work_item_list.h" | 38 #include "chrome/installer/util/conditional_work_item_list.h" |
| 46 #include "chrome/installer/util/create_reg_key_work_item.h" | 39 #include "chrome/installer/util/create_reg_key_work_item.h" |
| 47 #include "chrome/installer/util/firewall_manager_win.h" | 40 #include "chrome/installer/util/firewall_manager_win.h" |
| 48 #include "chrome/installer/util/google_update_constants.h" | 41 #include "chrome/installer/util/google_update_constants.h" |
| 49 #include "chrome/installer/util/helper.h" | |
| 50 #include "chrome/installer/util/install_util.h" | 42 #include "chrome/installer/util/install_util.h" |
| 51 #include "chrome/installer/util/installation_state.h" | 43 #include "chrome/installer/util/installation_state.h" |
| 52 #include "chrome/installer/util/l10n_string_util.h" | 44 #include "chrome/installer/util/l10n_string_util.h" |
| 45 #include "chrome/installer/util/non_updating_app_registration_data.h" |
| 53 #include "chrome/installer/util/product.h" | 46 #include "chrome/installer/util/product.h" |
| 54 #include "chrome/installer/util/set_reg_value_work_item.h" | 47 #include "chrome/installer/util/set_reg_value_work_item.h" |
| 55 #include "chrome/installer/util/shell_util.h" | 48 #include "chrome/installer/util/shell_util.h" |
| 49 #include "chrome/installer/util/updating_app_registration_data.h" |
| 56 #include "chrome/installer/util/util_constants.h" | 50 #include "chrome/installer/util/util_constants.h" |
| 57 #include "chrome/installer/util/work_item_list.h" | 51 #include "chrome/installer/util/work_item_list.h" |
| 58 | 52 |
| 59 using base::ASCIIToUTF16; | 53 using base::ASCIIToUTF16; |
| 60 using base::win::RegKey; | 54 using base::win::RegKey; |
| 61 | 55 |
| 62 namespace installer { | 56 namespace installer { |
| 63 | 57 |
| 64 namespace { | 58 namespace { |
| 65 | 59 |
| 66 // Although the UUID of the ChromeFrame class is used for the "current" value, | |
| 67 // this is done only as a convenience; there is no need for the GUID of the Low | |
| 68 // Rights policies to match the ChromeFrame class's GUID. Hence, it is safe to | |
| 69 // use this completely unrelated GUID for the "old" policies. | |
| 70 const wchar_t kIELowRightsPolicyOldGuid[] = | |
| 71 L"{6C288DD7-76FB-4721-B628-56FAC252E199}"; | |
| 72 | |
| 73 const wchar_t kElevationPolicyKeyPath[] = | |
| 74 L"SOFTWARE\\Microsoft\\Internet Explorer\\Low Rights\\ElevationPolicy\\"; | |
| 75 | |
| 76 void GetOldIELowRightsElevationPolicyKeyPath(base::string16* key_path) { | |
| 77 key_path->assign(kElevationPolicyKeyPath, | |
| 78 arraysize(kElevationPolicyKeyPath) - 1); | |
| 79 key_path->append(kIELowRightsPolicyOldGuid, | |
| 80 arraysize(kIELowRightsPolicyOldGuid)- 1); | |
| 81 } | |
| 82 | |
| 83 // Local helper to call AddRegisterComDllWorkItems for all DLLs in a set of | |
| 84 // products managed by a given package. | |
| 85 // |old_version| can be NULL to indicate no Chrome is currently installed. | |
| 86 void AddRegisterComDllWorkItemsForPackage(const InstallerState& installer_state, | |
| 87 const base::Version* old_version, | |
| 88 const base::Version& new_version, | |
| 89 WorkItemList* work_item_list) { | |
| 90 // First collect the list of DLLs to be registered from each product. | |
| 91 std::vector<base::FilePath> com_dll_list; | |
| 92 installer_state.AddComDllList(&com_dll_list); | |
| 93 | |
| 94 // Then, if we got some, attempt to unregister the DLLs from the old | |
| 95 // version directory and then re-register them in the new one. | |
| 96 // Note that if we are migrating the install directory then we will not | |
| 97 // successfully unregister the old DLLs. | |
| 98 // TODO(robertshield): See whether we need to fix the migration case. | |
| 99 // TODO(robertshield): If we ever remove a DLL from a product, this will | |
| 100 // not unregister it on update. We should build the unregistration list from | |
| 101 // saved state instead of assuming it is the same as the registration list. | |
| 102 if (!com_dll_list.empty()) { | |
| 103 if (old_version) { | |
| 104 base::FilePath old_dll_path(installer_state.target_path().AppendASCII( | |
| 105 old_version->GetString())); | |
| 106 | |
| 107 installer::AddRegisterComDllWorkItems(old_dll_path, | |
| 108 com_dll_list, | |
| 109 installer_state.system_install(), | |
| 110 false, // Unregister | |
| 111 true, // May fail | |
| 112 work_item_list); | |
| 113 } | |
| 114 | |
| 115 base::FilePath dll_path(installer_state.target_path().AppendASCII( | |
| 116 new_version.GetString())); | |
| 117 installer::AddRegisterComDllWorkItems(dll_path, | |
| 118 com_dll_list, | |
| 119 installer_state.system_install(), | |
| 120 true, // Register | |
| 121 false, // Must succeed. | |
| 122 work_item_list); | |
| 123 } | |
| 124 } | |
| 125 | |
| 126 void AddInstallerCopyTasks(const InstallerState& installer_state, | 60 void AddInstallerCopyTasks(const InstallerState& installer_state, |
| 127 const base::FilePath& setup_path, | 61 const base::FilePath& setup_path, |
| 128 const base::FilePath& archive_path, | 62 const base::FilePath& archive_path, |
| 129 const base::FilePath& temp_path, | 63 const base::FilePath& temp_path, |
| 130 const base::Version& new_version, | 64 const base::Version& new_version, |
| 131 WorkItemList* install_list) { | 65 WorkItemList* install_list) { |
| 132 DCHECK(install_list); | 66 DCHECK(install_list); |
| 133 base::FilePath installer_dir( | 67 base::FilePath installer_dir( |
| 134 installer_state.GetInstallerDirectory(new_version)); | 68 installer_state.GetInstallerDirectory(new_version)); |
| 135 install_list->AddCreateDirWorkItem(installer_dir); | 69 install_list->AddCreateDirWorkItem(installer_dir); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 bool is_new_install, | 154 bool is_new_install, |
| 221 WorkItemList* list) { | 155 WorkItemList* list) { |
| 222 list->AddCallbackWorkItem( | 156 list->AddCallbackWorkItem( |
| 223 base::Bind(&AddFirewallRulesCallback, | 157 base::Bind(&AddFirewallRulesCallback, |
| 224 installer_state.system_install(), | 158 installer_state.system_install(), |
| 225 dist, | 159 dist, |
| 226 installer_state.target_path().Append(kChromeExe), | 160 installer_state.target_path().Append(kChromeExe), |
| 227 is_new_install)); | 161 is_new_install)); |
| 228 } | 162 } |
| 229 | 163 |
| 230 void AddProductSpecificWorkItems(const InstallationState& original_state, | |
| 231 const InstallerState& installer_state, | |
| 232 const base::FilePath& setup_path, | |
| 233 const base::Version& new_version, | |
| 234 const base::Version* current_version, | |
| 235 bool add_language_identifier, | |
| 236 WorkItemList* list) { | |
| 237 const Products& products = installer_state.products(); | |
| 238 for (Products::const_iterator it = products.begin(); it < products.end(); | |
| 239 ++it) { | |
| 240 const Product& p = **it; | |
| 241 if (p.is_chrome()) { | |
| 242 AddOsUpgradeWorkItems(installer_state, setup_path, new_version, p, | |
| 243 list); | |
| 244 AddFirewallRulesWorkItems(installer_state, p.distribution(), | |
| 245 current_version == nullptr, list); | |
| 246 | |
| 247 #if defined(GOOGLE_CHROME_BUILD) | |
| 248 if (!InstallUtil::IsChromeSxSProcess()) { | |
| 249 // Remove the app launcher key as it has been deprecated. | |
| 250 RemoveAppLauncherVersionKey(installer_state.root_key()); | |
| 251 } | |
| 252 #endif // GOOGLE_CHROME_BUILD | |
| 253 InstallUtil::AddUpdateDowngradeVersionItem( | |
| 254 installer_state.system_install(), current_version, new_version, | |
| 255 p.distribution(), list); | |
| 256 } | |
| 257 if (p.is_chrome_binaries()) | |
| 258 AddQuickEnableChromeFrameWorkItems(installer_state, list); | |
| 259 } | |
| 260 } | |
| 261 | |
| 262 // This is called when an MSI installation is run. It may be that a user is | 164 // This is called when an MSI installation is run. It may be that a user is |
| 263 // attempting to install the MSI on top of a non-MSI managed installation. If | 165 // attempting to install the MSI on top of a non-MSI managed installation. If |
| 264 // so, try and remove any existing "Add/Remove Programs" entry, as we want the | 166 // so, try and remove any existing "Add/Remove Programs" entry, as we want the |
| 265 // uninstall to be managed entirely by the MSI machinery (accessible via the | 167 // uninstall to be managed entirely by the MSI machinery (accessible via the |
| 266 // Add/Remove programs dialog). | 168 // Add/Remove programs dialog). |
| 267 void AddDeleteUninstallEntryForMSIWorkItems( | 169 void AddDeleteUninstallEntryForMSIWorkItems( |
| 268 const InstallerState& installer_state, | 170 const InstallerState& installer_state, |
| 269 const Product& product, | 171 const Product& product, |
| 270 WorkItemList* work_item_list) { | 172 WorkItemList* work_item_list) { |
| 271 DCHECK(installer_state.is_msi()) | 173 DCHECK(installer_state.is_msi()) |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 delete_old_archive_work_item->set_rollback_enabled(false); | 211 delete_old_archive_work_item->set_rollback_enabled(false); |
| 310 } | 212 } |
| 311 } | 213 } |
| 312 | 214 |
| 313 // Delete any new_chrome.exe if present (we will end up creating a new one | 215 // Delete any new_chrome.exe if present (we will end up creating a new one |
| 314 // if required) and then copy chrome.exe | 216 // if required) and then copy chrome.exe |
| 315 base::FilePath new_chrome_exe(target_path.Append(installer::kChromeNewExe)); | 217 base::FilePath new_chrome_exe(target_path.Append(installer::kChromeNewExe)); |
| 316 | 218 |
| 317 install_list->AddDeleteTreeWorkItem(new_chrome_exe, temp_path); | 219 install_list->AddDeleteTreeWorkItem(new_chrome_exe, temp_path); |
| 318 | 220 |
| 319 // TODO(grt): Remove this check in M35. | 221 install_list->AddCopyTreeWorkItem( |
| 320 if (installer_state.IsChromeFrameRunning(original_state)) { | 222 src_path.Append(installer::kChromeExe).value(), |
| 321 VLOG(1) << "Chrome Frame in use. Copying to new_chrome.exe"; | 223 target_path.Append(installer::kChromeExe).value(), temp_path.value(), |
| 322 install_list->AddCopyTreeWorkItem( | 224 WorkItem::NEW_NAME_IF_IN_USE, new_chrome_exe.value()); |
| 323 src_path.Append(installer::kChromeExe).value(), | |
| 324 new_chrome_exe.value(), | |
| 325 temp_path.value(), | |
| 326 WorkItem::ALWAYS); | |
| 327 } else { | |
| 328 install_list->AddCopyTreeWorkItem( | |
| 329 src_path.Append(installer::kChromeExe).value(), | |
| 330 target_path.Append(installer::kChromeExe).value(), | |
| 331 temp_path.value(), | |
| 332 WorkItem::NEW_NAME_IF_IN_USE, | |
| 333 new_chrome_exe.value()); | |
| 334 } | |
| 335 | 225 |
| 336 // Install kVisualElementsManifest if it is present in |src_path|. No need to | 226 // Install kVisualElementsManifest if it is present in |src_path|. No need to |
| 337 // make this a conditional work item as if the file is not there now, it will | 227 // make this a conditional work item as if the file is not there now, it will |
| 338 // never be. | 228 // never be. |
| 339 if (base::PathExists( | 229 if (base::PathExists( |
| 340 src_path.Append(installer::kVisualElementsManifest))) { | 230 src_path.Append(installer::kVisualElementsManifest))) { |
| 341 install_list->AddMoveTreeWorkItem( | 231 install_list->AddMoveTreeWorkItem( |
| 342 src_path.Append(installer::kVisualElementsManifest).value(), | 232 src_path.Append(installer::kVisualElementsManifest).value(), |
| 343 target_path.Append(installer::kVisualElementsManifest).value(), | 233 target_path.Append(installer::kVisualElementsManifest).value(), |
| 344 temp_path.value(), | 234 temp_path.value(), |
| (...skipping 26 matching lines...) Expand all Loading... |
| 371 ->AddDeleteTreeWorkItem(target_path.Append(installer::kChromeOldExe), | 261 ->AddDeleteTreeWorkItem(target_path.Append(installer::kChromeOldExe), |
| 372 temp_path) | 262 temp_path) |
| 373 ->set_best_effort(true); | 263 ->set_best_effort(true); |
| 374 } | 264 } |
| 375 | 265 |
| 376 // Adds work items to remove COM registration for |product|'s deprecated | 266 // Adds work items to remove COM registration for |product|'s deprecated |
| 377 // DelegateExecute verb handler. | 267 // DelegateExecute verb handler. |
| 378 void AddCleanupDelegateExecuteWorkItems(const InstallerState& installer_state, | 268 void AddCleanupDelegateExecuteWorkItems(const InstallerState& installer_state, |
| 379 const Product& product, | 269 const Product& product, |
| 380 WorkItemList* list) { | 270 WorkItemList* list) { |
| 381 if (product.is_chrome()) { | 271 VLOG(1) << "Adding unregistration items for DelegateExecute verb handler."; |
| 382 VLOG(1) << "Adding unregistration items for DelegateExecute verb handler."; | 272 const base::string16 handler_class_uuid = |
| 383 const base::string16 handler_class_uuid = | 273 product.distribution()->GetCommandExecuteImplClsid(); |
| 384 product.distribution()->GetCommandExecuteImplClsid(); | 274 DCHECK(!handler_class_uuid.empty()); |
| 385 DCHECK(!handler_class_uuid.empty()); | |
| 386 | 275 |
| 387 const HKEY root = installer_state.root_key(); | 276 const HKEY root = installer_state.root_key(); |
| 388 base::string16 delegate_execute_path(L"Software\\Classes\\CLSID\\"); | 277 base::string16 delegate_execute_path(L"Software\\Classes\\CLSID\\"); |
| 389 delegate_execute_path.append(handler_class_uuid); | 278 delegate_execute_path.append(handler_class_uuid); |
| 390 // Delete both 64 and 32 keys to handle 32->64 or 64->32 migration. | 279 // Delete both 64 and 32 keys to handle 32->64 or 64->32 migration. |
| 391 list->AddDeleteRegKeyWorkItem(root, delegate_execute_path, KEY_WOW64_32KEY); | 280 list->AddDeleteRegKeyWorkItem(root, delegate_execute_path, KEY_WOW64_32KEY); |
| 392 list->AddDeleteRegKeyWorkItem(root, delegate_execute_path, KEY_WOW64_64KEY); | 281 list->AddDeleteRegKeyWorkItem(root, delegate_execute_path, KEY_WOW64_64KEY); |
| 393 } | |
| 394 } | 282 } |
| 395 | 283 |
| 396 // Add to the ACL of an object on disk. This follows the method from MSDN: | 284 // Add to the ACL of an object on disk. This follows the method from MSDN: |
| 397 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa379283.aspx | 285 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa379283.aspx |
| 398 // This is done using explicit flags rather than the "security string" format | 286 // This is done using explicit flags rather than the "security string" format |
| 399 // because strings do not necessarily read what is written which makes it | 287 // because strings do not necessarily read what is written which makes it |
| 400 // difficult to de-dup. Working with the binary format is always exact and the | 288 // difficult to de-dup. Working with the binary format is always exact and the |
| 401 // system libraries will properly ignore duplicate ACL entries. | 289 // system libraries will properly ignore duplicate ACL entries. |
| 402 bool AddAclToPath(const base::FilePath& path, | 290 bool AddAclToPath(const base::FilePath& path, |
| 403 const CSid& trustee, | 291 const CSid& trustee, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 | 323 |
| 436 // Attach the updated ACL as the object's DACL. | 324 // Attach the updated ACL as the object's DACL. |
| 437 if (!ATL::AtlSetDacl(path.value().c_str(), SE_FILE_OBJECT, dacl)) { | 325 if (!ATL::AtlSetDacl(path.value().c_str(), SE_FILE_OBJECT, dacl)) { |
| 438 DPLOG(ERROR) << "Failed setting DACL for path \"" << path.value() << "\""; | 326 DPLOG(ERROR) << "Failed setting DACL for path \"" << path.value() << "\""; |
| 439 return false; | 327 return false; |
| 440 } | 328 } |
| 441 | 329 |
| 442 return true; | 330 return true; |
| 443 } | 331 } |
| 444 | 332 |
| 333 // Migrates the usagestats value from the binaries to Chrome when migrating |
| 334 // multi-install Chrome to single-install. |
| 335 void AddMigrateUsageStatsWorkItems(const InstallationState& original_state, |
| 336 const InstallerState& installer_state, |
| 337 WorkItemList* install_list) { |
| 338 // This operation doesn't apply to SxS Chrome. |
| 339 if (InstallUtil::IsChromeSxSProcess()) |
| 340 return; |
| 341 |
| 342 // Bail out if an existing multi-install Chrome is not being migrated to |
| 343 // single-install. |
| 344 if (!installer_state.is_migrating_to_single()) { |
| 345 VLOG(1) << "No multi-install Chrome found to migrate to single-install."; |
| 346 return; |
| 347 } |
| 348 |
| 349 const ProductState* binaries_state = original_state.GetProductState( |
| 350 installer_state.system_install(), BrowserDistribution::CHROME_BINARIES); |
| 351 |
| 352 // There is nothing to be done if the binaries do not have stats. |
| 353 DWORD usagestats = 0; |
| 354 if (!binaries_state || !binaries_state->GetUsageStats(&usagestats)) { |
| 355 VLOG(1) << "No usagestats value found to migrate to single-install."; |
| 356 return; |
| 357 } |
| 358 |
| 359 VLOG(1) << "Migrating usagestats value from multi-install to single-install."; |
| 360 |
| 361 // Write the value that was read to Chrome's ClientState key. |
| 362 install_list->AddSetRegValueWorkItem( |
| 363 installer_state.root_key(), |
| 364 installer_state.product().distribution()->GetStateKey(), KEY_WOW64_32KEY, |
| 365 google_update::kRegUsageStatsField, usagestats, true); |
| 366 } |
| 367 |
| 445 } // namespace | 368 } // namespace |
| 446 | 369 |
| 447 // This method adds work items to create (or update) Chrome uninstall entry in | 370 // This method adds work items to create (or update) Chrome uninstall entry in |
| 448 // either the Control Panel->Add/Remove Programs list or in the Omaha client | 371 // either the Control Panel->Add/Remove Programs list or in the Omaha client |
| 449 // state key if running under an MSI installer. | 372 // state key if running under an MSI installer. |
| 450 void AddUninstallShortcutWorkItems(const InstallerState& installer_state, | 373 void AddUninstallShortcutWorkItems(const InstallerState& installer_state, |
| 451 const base::FilePath& setup_path, | 374 const base::FilePath& setup_path, |
| 452 const base::Version& new_version, | 375 const base::Version& new_version, |
| 453 const Product& product, | 376 const Product& product, |
| 454 WorkItemList* install_list) { | 377 WorkItemList* install_list) { |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 627 false); // do not overwrite language | 550 false); // do not overwrite language |
| 628 } | 551 } |
| 629 list->AddSetRegValueWorkItem(root, | 552 list->AddSetRegValueWorkItem(root, |
| 630 version_key, | 553 version_key, |
| 631 KEY_WOW64_32KEY, | 554 KEY_WOW64_32KEY, |
| 632 google_update::kRegVersionField, | 555 google_update::kRegVersionField, |
| 633 ASCIIToUTF16(new_version.GetString()), | 556 ASCIIToUTF16(new_version.GetString()), |
| 634 true); // overwrite version | 557 true); // overwrite version |
| 635 } | 558 } |
| 636 | 559 |
| 637 // Mirror oeminstall the first time anything is installed multi. There is no | |
| 638 // need to update the value on future install/update runs since this value never | |
| 639 // changes. Note that the value is removed by Google Update after EULA | |
| 640 // acceptance is processed. | |
| 641 void AddOemInstallWorkItems(const InstallationState& original_state, | |
| 642 const InstallerState& installer_state, | |
| 643 WorkItemList* install_list) { | |
| 644 DCHECK(installer_state.is_multi_install()); | |
| 645 const bool system_install = installer_state.system_install(); | |
| 646 if (!original_state.GetProductState(system_install, | |
| 647 BrowserDistribution::CHROME_BINARIES)) { | |
| 648 const HKEY root_key = installer_state.root_key(); | |
| 649 base::string16 multi_key( | |
| 650 installer_state.multi_package_binaries_distribution()->GetStateKey()); | |
| 651 | |
| 652 // Copy the value from Chrome unless Chrome isn't installed or being | |
| 653 // installed. | |
| 654 BrowserDistribution::Type source_type; | |
| 655 if (installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER)) { | |
| 656 source_type = BrowserDistribution::CHROME_BROWSER; | |
| 657 } else if (!installer_state.products().empty()) { | |
| 658 // Pick a product, any product. | |
| 659 source_type = installer_state.products()[0]->distribution()->GetType(); | |
| 660 } else { | |
| 661 // Nothing is being installed? Entirely unexpected, so do no harm. | |
| 662 LOG(ERROR) << "No products found in AddOemInstallWorkItems"; | |
| 663 return; | |
| 664 } | |
| 665 const ProductState* source_product = | |
| 666 original_state.GetNonVersionedProductState(system_install, source_type); | |
| 667 | |
| 668 base::string16 oem_install; | |
| 669 if (source_product->GetOemInstall(&oem_install)) { | |
| 670 VLOG(1) << "Mirroring oeminstall=\"" << oem_install << "\" from " | |
| 671 << BrowserDistribution::GetSpecificDistribution(source_type)-> | |
| 672 GetDisplayName(); | |
| 673 install_list->AddCreateRegKeyWorkItem( | |
| 674 root_key, multi_key, KEY_WOW64_32KEY); | |
| 675 // Always overwrite an old value. | |
| 676 install_list->AddSetRegValueWorkItem(root_key, | |
| 677 multi_key, | |
| 678 KEY_WOW64_32KEY, | |
| 679 google_update::kRegOemInstallField, | |
| 680 oem_install, | |
| 681 true); | |
| 682 } else { | |
| 683 // Clear any old value. | |
| 684 install_list->AddDeleteRegValueWorkItem( | |
| 685 root_key, | |
| 686 multi_key, | |
| 687 KEY_WOW64_32KEY, | |
| 688 google_update::kRegOemInstallField); | |
| 689 } | |
| 690 } | |
| 691 } | |
| 692 | |
| 693 // Mirror eulaaccepted the first time anything is installed multi. There is no | |
| 694 // need to update the value on future install/update runs since | |
| 695 // GoogleUpdateSettings::SetEULAConsent will modify the value for both the | |
| 696 // relevant product and for the binaries. | |
| 697 void AddEulaAcceptedWorkItems(const InstallationState& original_state, | |
| 698 const InstallerState& installer_state, | |
| 699 WorkItemList* install_list) { | |
| 700 DCHECK(installer_state.is_multi_install()); | |
| 701 const bool system_install = installer_state.system_install(); | |
| 702 if (!original_state.GetProductState(system_install, | |
| 703 BrowserDistribution::CHROME_BINARIES)) { | |
| 704 const HKEY root_key = installer_state.root_key(); | |
| 705 base::string16 multi_key( | |
| 706 installer_state.multi_package_binaries_distribution()->GetStateKey()); | |
| 707 | |
| 708 // Copy the value from the product with the greatest value. | |
| 709 bool have_eula_accepted = false; | |
| 710 BrowserDistribution::Type product_type = BrowserDistribution::NUM_TYPES; | |
| 711 DWORD eula_accepted = 0; | |
| 712 const Products& products = installer_state.products(); | |
| 713 for (Products::const_iterator it = products.begin(); it < products.end(); | |
| 714 ++it) { | |
| 715 const Product& product = **it; | |
| 716 if (product.is_chrome_binaries()) | |
| 717 continue; | |
| 718 DWORD dword_value = 0; | |
| 719 BrowserDistribution::Type this_type = product.distribution()->GetType(); | |
| 720 const ProductState* product_state = | |
| 721 original_state.GetNonVersionedProductState( | |
| 722 system_install, this_type); | |
| 723 if (product_state->GetEulaAccepted(&dword_value) && | |
| 724 (!have_eula_accepted || dword_value > eula_accepted)) { | |
| 725 have_eula_accepted = true; | |
| 726 eula_accepted = dword_value; | |
| 727 product_type = this_type; | |
| 728 } | |
| 729 } | |
| 730 | |
| 731 if (have_eula_accepted) { | |
| 732 VLOG(1) << "Mirroring eulaaccepted=" << eula_accepted << " from " | |
| 733 << BrowserDistribution::GetSpecificDistribution(product_type)-> | |
| 734 GetDisplayName(); | |
| 735 install_list->AddCreateRegKeyWorkItem( | |
| 736 root_key, multi_key, KEY_WOW64_32KEY); | |
| 737 install_list->AddSetRegValueWorkItem(root_key, | |
| 738 multi_key, | |
| 739 KEY_WOW64_32KEY, | |
| 740 google_update::kRegEULAAceptedField, | |
| 741 eula_accepted, | |
| 742 true); | |
| 743 } else { | |
| 744 // Clear any old value. | |
| 745 install_list->AddDeleteRegValueWorkItem( | |
| 746 root_key, | |
| 747 multi_key, | |
| 748 KEY_WOW64_32KEY, | |
| 749 google_update::kRegEULAAceptedField); | |
| 750 } | |
| 751 } | |
| 752 } | |
| 753 | |
| 754 // Adds work items that make registry adjustments for Google Update. | |
| 755 void AddGoogleUpdateWorkItems(const InstallationState& original_state, | |
| 756 const InstallerState& installer_state, | |
| 757 WorkItemList* install_list) { | |
| 758 // Is a multi-install product being installed or over-installed? | |
| 759 if (installer_state.operation() != InstallerState::MULTI_INSTALL && | |
| 760 installer_state.operation() != InstallerState::MULTI_UPDATE) { | |
| 761 VLOG(1) << "AddGoogleUpdateWorkItems noop: " << installer_state.operation(); | |
| 762 return; | |
| 763 } | |
| 764 | |
| 765 const bool system_install = installer_state.system_install(); | |
| 766 const HKEY root_key = installer_state.root_key(); | |
| 767 base::string16 multi_key( | |
| 768 installer_state.multi_package_binaries_distribution()->GetStateKey()); | |
| 769 | |
| 770 // For system-level installs, make sure the ClientStateMedium key for the | |
| 771 // binaries exists. | |
| 772 if (system_install) { | |
| 773 install_list->AddCreateRegKeyWorkItem( | |
| 774 root_key, | |
| 775 installer_state.multi_package_binaries_distribution() | |
| 776 ->GetStateMediumKey() | |
| 777 .c_str(), | |
| 778 KEY_WOW64_32KEY); | |
| 779 } | |
| 780 | |
| 781 // Creating the ClientState key for binaries, if we're migrating to multi then | |
| 782 // copy over Chrome's brand code if it has one. | |
| 783 if (installer_state.state_type() != BrowserDistribution::CHROME_BINARIES) { | |
| 784 const ProductState* chrome_product_state = | |
| 785 original_state.GetNonVersionedProductState( | |
| 786 system_install, BrowserDistribution::CHROME_BROWSER); | |
| 787 | |
| 788 const base::string16& brand(chrome_product_state->brand()); | |
| 789 if (!brand.empty()) { | |
| 790 install_list->AddCreateRegKeyWorkItem( | |
| 791 root_key, multi_key, KEY_WOW64_32KEY); | |
| 792 // Write Chrome's brand code to the multi key. Never overwrite the value | |
| 793 // if one is already present (although this shouldn't happen). | |
| 794 install_list->AddSetRegValueWorkItem(root_key, | |
| 795 multi_key, | |
| 796 KEY_WOW64_32KEY, | |
| 797 google_update::kRegBrandField, | |
| 798 brand, | |
| 799 false); | |
| 800 } | |
| 801 } | |
| 802 | |
| 803 AddOemInstallWorkItems(original_state, installer_state, install_list); | |
| 804 AddEulaAcceptedWorkItems(original_state, installer_state, install_list); | |
| 805 AddUsageStatsWorkItems(original_state, installer_state, install_list); | |
| 806 | |
| 807 // TODO(grt): check for other keys/values we should put in the package's | |
| 808 // ClientState and/or Clients key. | |
| 809 } | |
| 810 | |
| 811 void AddUsageStatsWorkItems(const InstallationState& original_state, | |
| 812 const InstallerState& installer_state, | |
| 813 WorkItemList* install_list) { | |
| 814 DCHECK(installer_state.operation() == InstallerState::MULTI_INSTALL || | |
| 815 installer_state.operation() == InstallerState::MULTI_UPDATE); | |
| 816 | |
| 817 HKEY root_key = installer_state.root_key(); | |
| 818 bool value_found = false; | |
| 819 DWORD usagestats = 0; | |
| 820 const Products& products = installer_state.products(); | |
| 821 | |
| 822 // Search for an existing usagestats value for any product. | |
| 823 for (Products::const_iterator scan = products.begin(), end = products.end(); | |
| 824 !value_found && scan != end; ++scan) { | |
| 825 if ((*scan)->is_chrome_binaries()) | |
| 826 continue; | |
| 827 BrowserDistribution* dist = (*scan)->distribution(); | |
| 828 const ProductState* product_state = | |
| 829 original_state.GetNonVersionedProductState( | |
| 830 installer_state.system_install(), dist->GetType()); | |
| 831 value_found = product_state->GetUsageStats(&usagestats); | |
| 832 } | |
| 833 | |
| 834 // If a value was found, write it in the appropriate location for the | |
| 835 // binaries and remove all values from the products. | |
| 836 if (value_found) { | |
| 837 base::string16 state_key( | |
| 838 installer_state.multi_package_binaries_distribution()->GetStateKey()); | |
| 839 install_list->AddCreateRegKeyWorkItem(root_key, state_key, KEY_WOW64_32KEY); | |
| 840 // Overwrite any existing value so that overinstalls (where Omaha writes a | |
| 841 // new value into a product's state key) pick up the correct value. | |
| 842 install_list->AddSetRegValueWorkItem(root_key, | |
| 843 state_key, | |
| 844 KEY_WOW64_32KEY, | |
| 845 google_update::kRegUsageStatsField, | |
| 846 usagestats, | |
| 847 true); | |
| 848 | |
| 849 for (Products::const_iterator scan = products.begin(), end = products.end(); | |
| 850 scan != end; ++scan) { | |
| 851 if ((*scan)->is_chrome_binaries()) | |
| 852 continue; | |
| 853 BrowserDistribution* dist = (*scan)->distribution(); | |
| 854 if (installer_state.system_install()) { | |
| 855 install_list->AddDeleteRegValueWorkItem( | |
| 856 root_key, | |
| 857 dist->GetStateMediumKey(), | |
| 858 KEY_WOW64_32KEY, | |
| 859 google_update::kRegUsageStatsField); | |
| 860 // Previous versions of Chrome also wrote a value in HKCU even for | |
| 861 // system-level installs, so clean that up. | |
| 862 install_list->AddDeleteRegValueWorkItem( | |
| 863 HKEY_CURRENT_USER, | |
| 864 dist->GetStateKey(), | |
| 865 KEY_WOW64_32KEY, | |
| 866 google_update::kRegUsageStatsField); | |
| 867 } | |
| 868 install_list->AddDeleteRegValueWorkItem( | |
| 869 root_key, | |
| 870 dist->GetStateKey(), | |
| 871 KEY_WOW64_32KEY, | |
| 872 google_update::kRegUsageStatsField); | |
| 873 } | |
| 874 } | |
| 875 } | |
| 876 | |
| 877 // Migrates the usagestats value from the binaries to Chrome when migrating | |
| 878 // multi-install Chrome to single-install. | |
| 879 void AddMigrateUsageStatesWorkItems(const InstallationState& original_state, | |
| 880 const InstallerState& installer_state, | |
| 881 WorkItemList* install_list) { | |
| 882 // Ensure that a non-multi install or update is being processed (i.e., | |
| 883 // no "--multi-install" on the command line). | |
| 884 if (installer_state.is_multi_install()) | |
| 885 return; | |
| 886 | |
| 887 // This operation doesn't apply to SxS Chrome. | |
| 888 if (InstallUtil::IsChromeSxSProcess()) | |
| 889 return; | |
| 890 | |
| 891 // Ensure that Chrome is the product being installed or updated (there are no | |
| 892 // other products, so it is especially unexpected for this to fail). | |
| 893 const Product* chrome_product = | |
| 894 installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER); | |
| 895 if (!chrome_product) { | |
| 896 LOG(DFATAL) << "Not operating on Chrome while migrating to single-install."; | |
| 897 return; | |
| 898 } | |
| 899 | |
| 900 // Bail out if an existing multi-install Chrome is not being migrated to | |
| 901 // single-install. | |
| 902 if (!installer_state.is_migrating_to_single()) { | |
| 903 VLOG(1) << "No multi-install Chrome found to migrate to single-install."; | |
| 904 return; | |
| 905 } | |
| 906 | |
| 907 const ProductState* binaries_state = original_state.GetProductState( | |
| 908 installer_state.system_install(), | |
| 909 BrowserDistribution::CHROME_BINARIES); | |
| 910 | |
| 911 // There is nothing to be done if the binaries do not have stats. | |
| 912 DWORD usagestats = 0; | |
| 913 if (!binaries_state || !binaries_state->GetUsageStats(&usagestats)) { | |
| 914 VLOG(1) << "No usagestats value found to migrate to single-install."; | |
| 915 return; | |
| 916 } | |
| 917 | |
| 918 VLOG(1) << "Migrating usagestats value from multi-install to single-install."; | |
| 919 | |
| 920 // Write the value that was read to Chrome's ClientState key. | |
| 921 install_list->AddSetRegValueWorkItem( | |
| 922 installer_state.root_key(), | |
| 923 chrome_product->distribution()->GetStateKey(), | |
| 924 KEY_WOW64_32KEY, | |
| 925 google_update::kRegUsageStatsField, | |
| 926 usagestats, | |
| 927 true); | |
| 928 } | |
| 929 | |
| 930 bool AppendPostInstallTasks(const InstallerState& installer_state, | 560 bool AppendPostInstallTasks(const InstallerState& installer_state, |
| 931 const base::FilePath& setup_path, | 561 const base::FilePath& setup_path, |
| 932 const base::Version* current_version, | 562 const base::Version* current_version, |
| 933 const base::Version& new_version, | 563 const base::Version& new_version, |
| 934 WorkItemList* post_install_task_list) { | 564 WorkItemList* post_install_task_list) { |
| 935 DCHECK(post_install_task_list); | 565 DCHECK(post_install_task_list); |
| 936 | 566 |
| 937 HKEY root = installer_state.root_key(); | 567 HKEY root = installer_state.root_key(); |
| 938 const Products& products = installer_state.products(); | |
| 939 base::FilePath new_chrome_exe( | 568 base::FilePath new_chrome_exe( |
| 940 installer_state.target_path().Append(installer::kChromeNewExe)); | 569 installer_state.target_path().Append(installer::kChromeNewExe)); |
| 941 | 570 |
| 942 // Append work items that will only be executed if this was an update. | 571 // Append work items that will only be executed if this was an update. |
| 943 // We update the 'opv' value with the current version that is active, | 572 // We update the 'opv' value with the current version that is active, |
| 944 // the 'cpv' value with the critical update version (if present), and the | 573 // the 'cpv' value with the critical update version (if present), and the |
| 945 // 'cmd' value with the rename command to run. | 574 // 'cmd' value with the rename command to run. |
| 946 { | 575 { |
| 947 std::unique_ptr<WorkItemList> in_use_update_work_items( | 576 std::unique_ptr<WorkItemList> in_use_update_work_items( |
| 948 WorkItem::CreateConditionalWorkItemList( | 577 WorkItem::CreateConditionalWorkItemList( |
| 949 new ConditionRunIfFileExists(new_chrome_exe))); | 578 new ConditionRunIfFileExists(new_chrome_exe))); |
| 950 in_use_update_work_items->set_log_message("InUseUpdateWorkItemList"); | 579 in_use_update_work_items->set_log_message("InUseUpdateWorkItemList"); |
| 951 | 580 |
| 952 // |critical_version| will be valid only if this in-use update includes a | 581 // |critical_version| will be valid only if this in-use update includes a |
| 953 // version considered critical relative to the version being updated. | 582 // version considered critical relative to the version being updated. |
| 954 base::Version critical_version(installer_state.DetermineCriticalVersion( | 583 base::Version critical_version(installer_state.DetermineCriticalVersion( |
| 955 current_version, new_version)); | 584 current_version, new_version)); |
| 956 base::FilePath installer_path( | 585 base::FilePath installer_path( |
| 957 installer_state.GetInstallerDirectory(new_version).Append( | 586 installer_state.GetInstallerDirectory(new_version).Append( |
| 958 setup_path.BaseName())); | 587 setup_path.BaseName())); |
| 959 | 588 |
| 960 base::CommandLine rename(installer_path); | 589 base::CommandLine rename(installer_path); |
| 961 rename.AppendSwitch(switches::kRenameChromeExe); | 590 rename.AppendSwitch(switches::kRenameChromeExe); |
| 962 if (installer_state.system_install()) | 591 if (installer_state.system_install()) |
| 963 rename.AppendSwitch(switches::kSystemLevel); | 592 rename.AppendSwitch(switches::kSystemLevel); |
| 964 | 593 |
| 965 if (installer_state.verbose_logging()) | 594 if (installer_state.verbose_logging()) |
| 966 rename.AppendSwitch(switches::kVerboseLogging); | 595 rename.AppendSwitch(switches::kVerboseLogging); |
| 967 | 596 |
| 968 base::string16 version_key; | 597 BrowserDistribution* dist = installer_state.product().distribution(); |
| 969 for (size_t i = 0; i < products.size(); ++i) { | 598 const base::string16 version_key(dist->GetVersionKey()); |
| 970 BrowserDistribution* dist = products[i]->distribution(); | |
| 971 version_key = dist->GetVersionKey(); | |
| 972 | 599 |
| 973 if (current_version) { | 600 if (current_version) { |
| 974 in_use_update_work_items->AddSetRegValueWorkItem( | 601 in_use_update_work_items->AddSetRegValueWorkItem( |
| 975 root, | 602 root, version_key, KEY_WOW64_32KEY, |
| 976 version_key, | 603 google_update::kRegOldVersionField, |
| 977 KEY_WOW64_32KEY, | 604 ASCIIToUTF16(current_version->GetString()), true); |
| 978 google_update::kRegOldVersionField, | 605 } |
| 979 ASCIIToUTF16(current_version->GetString()), | 606 if (critical_version.IsValid()) { |
| 980 true); | 607 in_use_update_work_items->AddSetRegValueWorkItem( |
| 981 } | 608 root, version_key, KEY_WOW64_32KEY, |
| 982 if (critical_version.IsValid()) { | 609 google_update::kRegCriticalVersionField, |
| 983 in_use_update_work_items->AddSetRegValueWorkItem( | 610 ASCIIToUTF16(critical_version.GetString()), true); |
| 984 root, | 611 } else { |
| 985 version_key, | 612 in_use_update_work_items->AddDeleteRegValueWorkItem( |
| 986 KEY_WOW64_32KEY, | 613 root, version_key, KEY_WOW64_32KEY, |
| 987 google_update::kRegCriticalVersionField, | 614 google_update::kRegCriticalVersionField); |
| 988 ASCIIToUTF16(critical_version.GetString()), | 615 } |
| 989 true); | |
| 990 } else { | |
| 991 in_use_update_work_items->AddDeleteRegValueWorkItem( | |
| 992 root, | |
| 993 version_key, | |
| 994 KEY_WOW64_32KEY, | |
| 995 google_update::kRegCriticalVersionField); | |
| 996 } | |
| 997 | 616 |
| 998 // Adding this registry entry for all products (but the binaries) is | 617 // Append the distribution-specific flags to the command line (e.g., |
| 999 // overkill. However, as it stands, we don't have a way to know which | 618 // "--chrome-sxs" for SxS/canary). |
| 1000 // product will check the key and run the command, so we add it for all. | 619 base::CommandLine product_rename_cmd(rename); |
| 1001 // The first to run it will perform the operation and clean up the other | 620 installer_state.product().AppendRenameFlags(&product_rename_cmd); |
| 1002 // values. | 621 in_use_update_work_items->AddSetRegValueWorkItem( |
| 1003 if (dist->GetType() != BrowserDistribution::CHROME_BINARIES) { | 622 root, version_key, KEY_WOW64_32KEY, google_update::kRegRenameCmdField, |
| 1004 base::CommandLine product_rename_cmd(rename); | 623 product_rename_cmd.GetCommandLineString(), true); |
| 1005 products[i]->AppendRenameFlags(&product_rename_cmd); | |
| 1006 in_use_update_work_items->AddSetRegValueWorkItem( | |
| 1007 root, | |
| 1008 version_key, | |
| 1009 KEY_WOW64_32KEY, | |
| 1010 google_update::kRegRenameCmdField, | |
| 1011 product_rename_cmd.GetCommandLineString(), | |
| 1012 true); | |
| 1013 } | |
| 1014 } | |
| 1015 | 624 |
| 1016 post_install_task_list->AddWorkItem(in_use_update_work_items.release()); | 625 post_install_task_list->AddWorkItem(in_use_update_work_items.release()); |
| 1017 } | 626 } |
| 1018 | 627 |
| 1019 // Append work items that will be executed if this was NOT an in-use update. | 628 // Append work items that will be executed if this was NOT an in-use update. |
| 1020 { | 629 { |
| 1021 std::unique_ptr<WorkItemList> regular_update_work_items( | 630 std::unique_ptr<WorkItemList> regular_update_work_items( |
| 1022 WorkItem::CreateConditionalWorkItemList( | 631 WorkItem::CreateConditionalWorkItemList( |
| 1023 new Not(new ConditionRunIfFileExists(new_chrome_exe)))); | 632 new Not(new ConditionRunIfFileExists(new_chrome_exe)))); |
| 1024 regular_update_work_items->set_log_message("RegularUpdateWorkItemList"); | 633 regular_update_work_items->set_log_message("RegularUpdateWorkItemList"); |
| 1025 | 634 |
| 1026 // Since this was not an in-use-update, delete 'opv', 'cpv', and 'cmd' keys. | 635 // Since this was not an in-use-update, delete 'opv', 'cpv', and 'cmd' keys. |
| 1027 for (size_t i = 0; i < products.size(); ++i) { | 636 BrowserDistribution* dist = installer_state.product().distribution(); |
| 1028 BrowserDistribution* dist = products[i]->distribution(); | 637 const base::string16 version_key(dist->GetVersionKey()); |
| 1029 base::string16 version_key(dist->GetVersionKey()); | 638 regular_update_work_items->AddDeleteRegValueWorkItem( |
| 1030 regular_update_work_items->AddDeleteRegValueWorkItem( | 639 root, version_key, KEY_WOW64_32KEY, google_update::kRegOldVersionField); |
| 1031 root, | 640 regular_update_work_items->AddDeleteRegValueWorkItem( |
| 1032 version_key, | 641 root, version_key, KEY_WOW64_32KEY, |
| 1033 KEY_WOW64_32KEY, | 642 google_update::kRegCriticalVersionField); |
| 1034 google_update::kRegOldVersionField); | 643 regular_update_work_items->AddDeleteRegValueWorkItem( |
| 1035 regular_update_work_items->AddDeleteRegValueWorkItem( | 644 root, version_key, KEY_WOW64_32KEY, google_update::kRegRenameCmdField); |
| 1036 root, | |
| 1037 version_key, | |
| 1038 KEY_WOW64_32KEY, | |
| 1039 google_update::kRegCriticalVersionField); | |
| 1040 regular_update_work_items->AddDeleteRegValueWorkItem( | |
| 1041 root, | |
| 1042 version_key, | |
| 1043 KEY_WOW64_32KEY, | |
| 1044 google_update::kRegRenameCmdField); | |
| 1045 } | |
| 1046 | 645 |
| 1047 post_install_task_list->AddWorkItem(regular_update_work_items.release()); | 646 post_install_task_list->AddWorkItem(regular_update_work_items.release()); |
| 1048 } | 647 } |
| 1049 | 648 |
| 1050 AddRegisterComDllWorkItemsForPackage(installer_state, current_version, | |
| 1051 new_version, post_install_task_list); | |
| 1052 | |
| 1053 // If we're told that we're an MSI install, make sure to set the marker | 649 // If we're told that we're an MSI install, make sure to set the marker |
| 1054 // in the client state key so that future updates do the right thing. | 650 // in the client state key so that future updates do the right thing. |
| 1055 if (installer_state.is_msi()) { | 651 if (installer_state.is_msi()) { |
| 1056 for (size_t i = 0; i < products.size(); ++i) { | 652 const Product& product = installer_state.product(); |
| 1057 const Product* product = products[i]; | 653 AddSetMsiMarkerWorkItem(installer_state, product.distribution(), true, |
| 1058 AddSetMsiMarkerWorkItem(installer_state, product->distribution(), true, | 654 post_install_task_list); |
| 1059 post_install_task_list); | |
| 1060 | 655 |
| 1061 // We want MSI installs to take over the Add/Remove Programs entry. Make a | 656 // We want MSI installs to take over the Add/Remove Programs entry. Make a |
| 1062 // best-effort attempt to delete any entry left over from previous non-MSI | 657 // best-effort attempt to delete any entry left over from previous non-MSI |
| 1063 // installations for the same type of install (system or per user). | 658 // installations for the same type of install (system or per user). |
| 1064 if (product->ShouldCreateUninstallEntry()) { | 659 if (product.ShouldCreateUninstallEntry()) { |
| 1065 AddDeleteUninstallEntryForMSIWorkItems(installer_state, *product, | 660 AddDeleteUninstallEntryForMSIWorkItems(installer_state, product, |
| 1066 post_install_task_list); | 661 post_install_task_list); |
| 1067 } | |
| 1068 } | 662 } |
| 1069 } | 663 } |
| 1070 | 664 |
| 1071 return true; | 665 return true; |
| 1072 } | 666 } |
| 1073 | 667 |
| 1074 void AddInstallWorkItems(const InstallationState& original_state, | 668 void AddInstallWorkItems(const InstallationState& original_state, |
| 1075 const InstallerState& installer_state, | 669 const InstallerState& installer_state, |
| 1076 const base::FilePath& setup_path, | 670 const base::FilePath& setup_path, |
| 1077 const base::FilePath& archive_path, | 671 const base::FilePath& archive_path, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1102 return AddAclToPath(histogram_storage_dir, | 696 return AddAclToPath(histogram_storage_dir, |
| 1103 ATL::Sids::AuthenticatedUser(), | 697 ATL::Sids::AuthenticatedUser(), |
| 1104 FILE_GENERIC_READ | FILE_DELETE_CHILD, | 698 FILE_GENERIC_READ | FILE_DELETE_CHILD, |
| 1105 CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE); | 699 CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE); |
| 1106 }, | 700 }, |
| 1107 histogram_storage_dir)); | 701 histogram_storage_dir)); |
| 1108 add_acl_to_histogram_storage_dir_work_item->set_best_effort(true); | 702 add_acl_to_histogram_storage_dir_work_item->set_best_effort(true); |
| 1109 add_acl_to_histogram_storage_dir_work_item->set_rollback_enabled(false); | 703 add_acl_to_histogram_storage_dir_work_item->set_rollback_enabled(false); |
| 1110 } | 704 } |
| 1111 | 705 |
| 1112 if (installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER) || | 706 AddChromeWorkItems(original_state, installer_state, setup_path, archive_path, |
| 1113 installer_state.FindProduct(BrowserDistribution::CHROME_BINARIES)) { | 707 src_path, temp_path, current_version, new_version, |
| 1114 AddChromeWorkItems(original_state, | 708 install_list); |
| 1115 installer_state, | |
| 1116 setup_path, | |
| 1117 archive_path, | |
| 1118 src_path, | |
| 1119 temp_path, | |
| 1120 current_version, | |
| 1121 new_version, | |
| 1122 install_list); | |
| 1123 } | |
| 1124 | |
| 1125 #if defined(GOOGLE_CHROME_BUILD) | |
| 1126 // For Chrome, unconditionally remove the legacy app_host.exe. | |
| 1127 if (!InstallUtil::IsChromeSxSProcess()) | |
| 1128 AddRemoveLegacyAppHostExeWorkItems(target_path, temp_path, install_list); | |
| 1129 #endif // GOOGLE_CHROME_BUILD | |
| 1130 | 709 |
| 1131 // Copy installer in install directory | 710 // Copy installer in install directory |
| 1132 AddInstallerCopyTasks(installer_state, setup_path, archive_path, temp_path, | 711 AddInstallerCopyTasks(installer_state, setup_path, archive_path, temp_path, |
| 1133 new_version, install_list); | 712 new_version, install_list); |
| 1134 | 713 |
| 1135 const HKEY root = installer_state.root_key(); | 714 const HKEY root = installer_state.root_key(); |
| 1136 // Only set "lang" for user-level installs since for system-level, the install | 715 // Only set "lang" for user-level installs since for system-level, the install |
| 1137 // language may not be related to a given user's runtime language. | 716 // language may not be related to a given user's runtime language. |
| 1138 const bool add_language_identifier = !installer_state.system_install(); | 717 const bool add_language_identifier = !installer_state.system_install(); |
| 1139 | 718 |
| 1140 const Products& products = installer_state.products(); | 719 const Product& product = installer_state.product(); |
| 1141 for (Products::const_iterator it = products.begin(); it < products.end(); | 720 AddUninstallShortcutWorkItems(installer_state, setup_path, new_version, |
| 1142 ++it) { | 721 product, install_list); |
| 1143 const Product& product = **it; | |
| 1144 | 722 |
| 1145 AddUninstallShortcutWorkItems(installer_state, setup_path, new_version, | 723 BrowserDistribution* dist = product.distribution(); |
| 1146 product, install_list); | 724 AddVersionKeyWorkItems(root, dist->GetVersionKey(), dist->GetDisplayName(), |
| 725 new_version, add_language_identifier, install_list); |
| 1147 | 726 |
| 1148 BrowserDistribution* dist = product.distribution(); | 727 AddCleanupDelegateExecuteWorkItems(installer_state, product, install_list); |
| 1149 AddVersionKeyWorkItems(root, | 728 AddCleanupDeprecatedPerUserRegistrationsWorkItems(product, install_list); |
| 1150 dist->GetVersionKey(), | |
| 1151 dist->GetDisplayName(), | |
| 1152 new_version, | |
| 1153 add_language_identifier, | |
| 1154 install_list); | |
| 1155 | 729 |
| 1156 AddCleanupDelegateExecuteWorkItems(installer_state, product, install_list); | 730 AddActiveSetupWorkItems(installer_state, new_version, product, install_list); |
| 1157 AddCleanupDeprecatedPerUserRegistrationsWorkItems(product, install_list); | |
| 1158 | 731 |
| 1159 AddActiveSetupWorkItems(installer_state, new_version, product, | 732 AddOsUpgradeWorkItems(installer_state, setup_path, new_version, product, |
| 733 install_list); |
| 734 AddFirewallRulesWorkItems(installer_state, dist, current_version == nullptr, |
| 1160 install_list); | 735 install_list); |
| 1161 } | |
| 1162 | 736 |
| 1163 // Ensure that the Clients key for the binaries is gone for single installs | 737 InstallUtil::AddUpdateDowngradeVersionItem(installer_state.system_install(), |
| 1164 // (but not for SxS Chrome). | 738 current_version, new_version, dist, |
| 1165 if (!installer_state.is_multi_install() && | 739 install_list); |
| 1166 !InstallUtil::IsChromeSxSProcess()) { | |
| 1167 BrowserDistribution* binaries_dist = | |
| 1168 BrowserDistribution::GetSpecificDistribution( | |
| 1169 BrowserDistribution::CHROME_BINARIES); | |
| 1170 install_list->AddDeleteRegKeyWorkItem(root, | |
| 1171 binaries_dist->GetVersionKey(), | |
| 1172 KEY_WOW64_32KEY); | |
| 1173 } | |
| 1174 | |
| 1175 #if defined(GOOGLE_CHROME_BUILD) | |
| 1176 if (!InstallUtil::IsChromeSxSProcess()) | |
| 1177 AddRemoveLegacyAppCommandsWorkItems(installer_state, install_list); | |
| 1178 #endif // GOOGLE_CHROME_BUILD | |
| 1179 | |
| 1180 // Add any remaining work items that involve special settings for | |
| 1181 // each product. | |
| 1182 AddProductSpecificWorkItems(original_state, installer_state, setup_path, | |
| 1183 new_version, current_version, | |
| 1184 add_language_identifier, install_list); | |
| 1185 | |
| 1186 // Copy over brand, usagestats, and other values. | |
| 1187 AddGoogleUpdateWorkItems(original_state, installer_state, install_list); | |
| 1188 | 740 |
| 1189 // Migrate usagestats back to Chrome. | 741 // Migrate usagestats back to Chrome. |
| 1190 AddMigrateUsageStatesWorkItems(original_state, installer_state, install_list); | 742 AddMigrateUsageStatsWorkItems(original_state, installer_state, install_list); |
| 1191 | 743 |
| 1192 // Append the tasks that run after the installation. | 744 // Append the tasks that run after the installation. |
| 1193 AppendPostInstallTasks(installer_state, | 745 AppendPostInstallTasks(installer_state, |
| 1194 setup_path, | 746 setup_path, |
| 1195 current_version, | 747 current_version, |
| 1196 new_version, | 748 new_version, |
| 1197 install_list); | 749 install_list); |
| 1198 } | 750 } |
| 1199 | 751 |
| 1200 void AddRegisterComDllWorkItems(const base::FilePath& dll_folder, | |
| 1201 const std::vector<base::FilePath>& dll_list, | |
| 1202 bool system_level, | |
| 1203 bool do_register, | |
| 1204 bool best_effort, | |
| 1205 WorkItemList* work_item_list) { | |
| 1206 DCHECK(work_item_list); | |
| 1207 if (dll_list.empty()) { | |
| 1208 VLOG(1) << "No COM DLLs to register"; | |
| 1209 } else { | |
| 1210 std::vector<base::FilePath>::const_iterator dll_iter(dll_list.begin()); | |
| 1211 for (; dll_iter != dll_list.end(); ++dll_iter) { | |
| 1212 base::FilePath dll_path = dll_folder.Append(*dll_iter); | |
| 1213 WorkItem* work_item = work_item_list->AddSelfRegWorkItem( | |
| 1214 dll_path.value(), do_register, !system_level); | |
| 1215 DCHECK(work_item); | |
| 1216 work_item->set_best_effort(best_effort); | |
| 1217 } | |
| 1218 } | |
| 1219 } | |
| 1220 | |
| 1221 void AddSetMsiMarkerWorkItem(const InstallerState& installer_state, | 752 void AddSetMsiMarkerWorkItem(const InstallerState& installer_state, |
| 1222 BrowserDistribution* dist, | 753 BrowserDistribution* dist, |
| 1223 bool set, | 754 bool set, |
| 1224 WorkItemList* work_item_list) { | 755 WorkItemList* work_item_list) { |
| 1225 DCHECK(work_item_list); | 756 DCHECK(work_item_list); |
| 1226 DWORD msi_value = set ? 1 : 0; | 757 DWORD msi_value = set ? 1 : 0; |
| 1227 WorkItem* set_msi_work_item = | 758 WorkItem* set_msi_work_item = |
| 1228 work_item_list->AddSetRegValueWorkItem(installer_state.root_key(), | 759 work_item_list->AddSetRegValueWorkItem(installer_state.root_key(), |
| 1229 dist->GetStateKey(), | 760 dist->GetStateKey(), |
| 1230 KEY_WOW64_32KEY, | 761 KEY_WOW64_32KEY, |
| 1231 google_update::kRegMSIField, | 762 google_update::kRegMSIField, |
| 1232 msi_value, | 763 msi_value, |
| 1233 true); | 764 true); |
| 1234 DCHECK(set_msi_work_item); | 765 DCHECK(set_msi_work_item); |
| 1235 set_msi_work_item->set_best_effort(true); | 766 set_msi_work_item->set_best_effort(true); |
| 1236 set_msi_work_item->set_log_message("Could not write MSI marker!"); | 767 set_msi_work_item->set_log_message("Could not write MSI marker!"); |
| 1237 } | 768 } |
| 1238 | 769 |
| 1239 void AddCleanupDeprecatedPerUserRegistrationsWorkItems(const Product& product, | 770 void AddCleanupDeprecatedPerUserRegistrationsWorkItems(const Product& product, |
| 1240 WorkItemList* list) { | 771 WorkItemList* list) { |
| 1241 if (product.is_chrome()) { | 772 BrowserDistribution* dist = product.distribution(); |
| 1242 BrowserDistribution* dist = product.distribution(); | |
| 1243 | 773 |
| 1244 // TODO(gab): Remove cleanup code for Metro after M53. | 774 // This cleanup was added in M49. There are still enough active users on M48 |
| 1245 VLOG(1) << "Adding unregistration items for per-user Metro keys."; | 775 // and earlier today (M55 timeframe) to justify keeping this cleanup in-place. |
| 1246 list->AddDeleteRegKeyWorkItem(HKEY_CURRENT_USER, | 776 // Remove this when that population stops shrinking. |
| 1247 dist->GetRegistryPath() + L"\\Metro", | 777 VLOG(1) << "Adding unregistration items for per-user Metro keys."; |
| 1248 KEY_WOW64_32KEY); | 778 list->AddDeleteRegKeyWorkItem( |
| 1249 list->AddDeleteRegKeyWorkItem(HKEY_CURRENT_USER, | 779 HKEY_CURRENT_USER, dist->GetRegistryPath() + L"\\Metro", KEY_WOW64_32KEY); |
| 1250 dist->GetRegistryPath() + L"\\Metro", | 780 list->AddDeleteRegKeyWorkItem( |
| 1251 KEY_WOW64_64KEY); | 781 HKEY_CURRENT_USER, dist->GetRegistryPath() + L"\\Metro", KEY_WOW64_64KEY); |
| 1252 } | |
| 1253 } | 782 } |
| 1254 | 783 |
| 1255 void AddActiveSetupWorkItems(const InstallerState& installer_state, | 784 void AddActiveSetupWorkItems(const InstallerState& installer_state, |
| 1256 const base::Version& new_version, | 785 const base::Version& new_version, |
| 1257 const Product& product, | 786 const Product& product, |
| 1258 WorkItemList* list) { | 787 WorkItemList* list) { |
| 1259 DCHECK(installer_state.operation() != InstallerState::UNINSTALL); | 788 DCHECK(installer_state.operation() != InstallerState::UNINSTALL); |
| 1260 BrowserDistribution* dist = product.distribution(); | 789 BrowserDistribution* dist = product.distribution(); |
| 1261 | 790 |
| 1262 if (!product.is_chrome() || !installer_state.system_install()) { | 791 if (!installer_state.system_install()) { |
| 1263 const char* install_level = | 792 VLOG(1) << "No Active Setup processing to do for user-level " |
| 1264 installer_state.system_install() ? "system" : "user"; | 793 << dist->GetDisplayName(); |
| 1265 VLOG(1) << "No Active Setup processing to do for " << install_level | |
| 1266 << "-level " << dist->GetDisplayName(); | |
| 1267 return; | 794 return; |
| 1268 } | 795 } |
| 1269 DCHECK(installer_state.RequiresActiveSetup()); | 796 DCHECK(installer_state.RequiresActiveSetup()); |
| 1270 | 797 |
| 1271 const HKEY root = HKEY_LOCAL_MACHINE; | 798 const HKEY root = HKEY_LOCAL_MACHINE; |
| 1272 const base::string16 active_setup_path(InstallUtil::GetActiveSetupPath(dist)); | 799 const base::string16 active_setup_path(InstallUtil::GetActiveSetupPath(dist)); |
| 1273 | 800 |
| 1274 VLOG(1) << "Adding registration items for Active Setup."; | 801 VLOG(1) << "Adding registration items for Active Setup."; |
| 1275 list->AddCreateRegKeyWorkItem( | 802 list->AddCreateRegKeyWorkItem( |
| 1276 root, active_setup_path, WorkItem::kWow64Default); | 803 root, active_setup_path, WorkItem::kWow64Default); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1308 active_setup_path, | 835 active_setup_path, |
| 1309 WorkItem::kWow64Default, | 836 WorkItem::kWow64Default, |
| 1310 L"IsInstalled", | 837 L"IsInstalled", |
| 1311 static_cast<DWORD>(1U), | 838 static_cast<DWORD>(1U), |
| 1312 true); | 839 true); |
| 1313 | 840 |
| 1314 list->AddWorkItem(new UpdateActiveSetupVersionWorkItem( | 841 list->AddWorkItem(new UpdateActiveSetupVersionWorkItem( |
| 1315 active_setup_path, UpdateActiveSetupVersionWorkItem::UPDATE)); | 842 active_setup_path, UpdateActiveSetupVersionWorkItem::UPDATE)); |
| 1316 } | 843 } |
| 1317 | 844 |
| 1318 void AddDeleteOldIELowRightsPolicyWorkItems( | |
| 1319 const InstallerState& installer_state, | |
| 1320 WorkItemList* install_list) { | |
| 1321 DCHECK(install_list); | |
| 1322 | |
| 1323 base::string16 key_path; | |
| 1324 GetOldIELowRightsElevationPolicyKeyPath(&key_path); | |
| 1325 install_list->AddDeleteRegKeyWorkItem( | |
| 1326 installer_state.root_key(), key_path, WorkItem::kWow64Default); | |
| 1327 } | |
| 1328 | |
| 1329 void AppendUninstallCommandLineFlags(const InstallerState& installer_state, | 845 void AppendUninstallCommandLineFlags(const InstallerState& installer_state, |
| 1330 const Product& product, | 846 const Product& product, |
| 1331 base::CommandLine* uninstall_cmd) { | 847 base::CommandLine* uninstall_cmd) { |
| 1332 DCHECK(uninstall_cmd); | 848 DCHECK(uninstall_cmd); |
| 1333 | 849 |
| 1334 uninstall_cmd->AppendSwitch(installer::switches::kUninstall); | 850 uninstall_cmd->AppendSwitch(installer::switches::kUninstall); |
| 1335 | 851 |
| 1336 // Append the product-specific uninstall flags. | 852 // Append the product-specific uninstall flags. |
| 1337 product.AppendProductFlags(uninstall_cmd); | 853 product.AppendProductFlags(uninstall_cmd); |
| 1338 if (installer_state.is_msi()) | 854 if (installer_state.is_msi()) |
| 1339 uninstall_cmd->AppendSwitch(installer::switches::kMsi); | 855 uninstall_cmd->AppendSwitch(installer::switches::kMsi); |
| 1340 if (installer_state.system_install()) | 856 if (installer_state.system_install()) |
| 1341 uninstall_cmd->AppendSwitch(installer::switches::kSystemLevel); | 857 uninstall_cmd->AppendSwitch(installer::switches::kSystemLevel); |
| 1342 if (installer_state.verbose_logging()) | 858 if (installer_state.verbose_logging()) |
| 1343 uninstall_cmd->AppendSwitch(installer::switches::kVerboseLogging); | 859 uninstall_cmd->AppendSwitch(installer::switches::kVerboseLogging); |
| 1344 } | 860 } |
| 1345 | 861 |
| 1346 void RefreshElevationPolicy() { | |
| 1347 const wchar_t kIEFrameDll[] = L"ieframe.dll"; | |
| 1348 const char kIERefreshPolicy[] = "IERefreshElevationPolicy"; | |
| 1349 | |
| 1350 HMODULE ieframe = LoadLibrary(kIEFrameDll); | |
| 1351 if (ieframe) { | |
| 1352 typedef HRESULT (__stdcall *IERefreshPolicy)(); | |
| 1353 IERefreshPolicy ie_refresh_policy = reinterpret_cast<IERefreshPolicy>( | |
| 1354 GetProcAddress(ieframe, kIERefreshPolicy)); | |
| 1355 | |
| 1356 if (ie_refresh_policy) { | |
| 1357 ie_refresh_policy(); | |
| 1358 } else { | |
| 1359 VLOG(1) << kIERefreshPolicy << " not supported."; | |
| 1360 } | |
| 1361 | |
| 1362 FreeLibrary(ieframe); | |
| 1363 } else { | |
| 1364 VLOG(1) << "Cannot load " << kIEFrameDll; | |
| 1365 } | |
| 1366 } | |
| 1367 | |
| 1368 void AddOsUpgradeWorkItems(const InstallerState& installer_state, | 862 void AddOsUpgradeWorkItems(const InstallerState& installer_state, |
| 1369 const base::FilePath& setup_path, | 863 const base::FilePath& setup_path, |
| 1370 const base::Version& new_version, | 864 const base::Version& new_version, |
| 1371 const Product& product, | 865 const Product& product, |
| 1372 WorkItemList* install_list) { | 866 WorkItemList* install_list) { |
| 1373 const HKEY root_key = installer_state.root_key(); | 867 const HKEY root_key = installer_state.root_key(); |
| 1374 base::string16 cmd_key( | 868 base::string16 cmd_key( |
| 1375 GetRegCommandKey(product.distribution(), kCmdOnOsUpgrade)); | 869 GetRegCommandKey(product.distribution(), kCmdOnOsUpgrade)); |
| 1376 | 870 |
| 1377 if (installer_state.operation() == InstallerState::UNINSTALL) { | 871 if (installer_state.operation() == InstallerState::UNINSTALL) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1391 cmd_line.AppendSwitch(installer::switches::kSystemLevel); | 885 cmd_line.AppendSwitch(installer::switches::kSystemLevel); |
| 1392 // Log everything for now. | 886 // Log everything for now. |
| 1393 cmd_line.AppendSwitch(installer::switches::kVerboseLogging); | 887 cmd_line.AppendSwitch(installer::switches::kVerboseLogging); |
| 1394 | 888 |
| 1395 AppCommand cmd(cmd_line.GetCommandLineString()); | 889 AppCommand cmd(cmd_line.GetCommandLineString()); |
| 1396 cmd.set_is_auto_run_on_os_upgrade(true); | 890 cmd.set_is_auto_run_on_os_upgrade(true); |
| 1397 cmd.AddWorkItems(installer_state.root_key(), cmd_key, install_list); | 891 cmd.AddWorkItems(installer_state.root_key(), cmd_key, install_list); |
| 1398 } | 892 } |
| 1399 } | 893 } |
| 1400 | 894 |
| 1401 void AddQuickEnableChromeFrameWorkItems(const InstallerState& installer_state, | |
| 1402 WorkItemList* work_item_list) { | |
| 1403 DCHECK(work_item_list); | |
| 1404 | |
| 1405 base::string16 cmd_key( | |
| 1406 GetRegCommandKey(BrowserDistribution::GetSpecificDistribution( | |
| 1407 BrowserDistribution::CHROME_BINARIES), | |
| 1408 kCmdQuickEnableCf)); | |
| 1409 | |
| 1410 // Unconditionally remove the legacy Quick Enable command from the binaries. | |
| 1411 // Do this even if multi-install Chrome isn't installed to ensure that it is | |
| 1412 // not left behind in any case. | |
| 1413 work_item_list->AddDeleteRegKeyWorkItem( | |
| 1414 installer_state.root_key(), cmd_key, KEY_WOW64_32KEY) | |
| 1415 ->set_log_message("removing " + base::UTF16ToASCII(kCmdQuickEnableCf) + | |
| 1416 " command"); | |
| 1417 } | |
| 1418 | |
| 1419 } // namespace installer | 895 } // namespace installer |
| OLD | NEW |