| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/installer/setup/setup_main.h" | 5 #include "chrome/installer/setup/setup_main.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <msi.h> | 8 #include <msi.h> |
| 9 #include <shellapi.h> | 9 #include <shellapi.h> |
| 10 #include <shlobj.h> | 10 #include <shlobj.h> |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 #include "chrome/installer/util/util_constants.h" | 78 #include "chrome/installer/util/util_constants.h" |
| 79 #include "components/crash/content/app/crash_switches.h" | 79 #include "components/crash/content/app/crash_switches.h" |
| 80 #include "components/crash/content/app/run_as_crashpad_handler_win.h" | 80 #include "components/crash/content/app/run_as_crashpad_handler_win.h" |
| 81 #include "content/public/common/content_switches.h" | 81 #include "content/public/common/content_switches.h" |
| 82 | 82 |
| 83 using installer::InstallerState; | 83 using installer::InstallerState; |
| 84 using installer::InstallationState; | 84 using installer::InstallationState; |
| 85 using installer::MasterPreferences; | 85 using installer::MasterPreferences; |
| 86 using installer::Product; | 86 using installer::Product; |
| 87 using installer::ProductState; | 87 using installer::ProductState; |
| 88 using installer::Products; | |
| 89 | 88 |
| 90 namespace { | 89 namespace { |
| 91 | 90 |
| 92 const wchar_t kSystemPrincipalSid[] = L"S-1-5-18"; | 91 const wchar_t kSystemPrincipalSid[] = L"S-1-5-18"; |
| 93 const wchar_t kDisplayVersion[] = L"DisplayVersion"; | 92 const wchar_t kDisplayVersion[] = L"DisplayVersion"; |
| 94 const wchar_t kMsiDisplayVersionOverwriteDelay[] = L"10"; // seconds as string | 93 const wchar_t kMsiDisplayVersionOverwriteDelay[] = L"10"; // seconds as string |
| 95 const wchar_t kMsiProductIdPrefix[] = L"EnterpriseProduct"; | 94 const wchar_t kMsiProductIdPrefix[] = L"EnterpriseProduct"; |
| 96 | 95 |
| 97 // Overwrite an existing DisplayVersion as written by the MSI installer | 96 // Overwrite an existing DisplayVersion as written by the MSI installer |
| 98 // with the real version number of Chrome. | 97 // with the real version number of Chrome. |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 | 214 |
| 216 // Returns the MSI product ID from the ClientState key that is populated for MSI | 215 // Returns the MSI product ID from the ClientState key that is populated for MSI |
| 217 // installs. This property is encoded in a value name whose format is | 216 // installs. This property is encoded in a value name whose format is |
| 218 // "EnterpriseId<GUID>" where <GUID> is the MSI product id. <GUID> is in the | 217 // "EnterpriseId<GUID>" where <GUID> is the MSI product id. <GUID> is in the |
| 219 // format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. The id will be returned if | 218 // format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. The id will be returned if |
| 220 // found otherwise this method will return an empty string. | 219 // found otherwise this method will return an empty string. |
| 221 // | 220 // |
| 222 // This format is strange and its provenance is shrouded in mystery but it has | 221 // This format is strange and its provenance is shrouded in mystery but it has |
| 223 // the data we need, so use it. | 222 // the data we need, so use it. |
| 224 base::string16 FindMsiProductId(const InstallerState& installer_state, | 223 base::string16 FindMsiProductId(const InstallerState& installer_state, |
| 225 const Product* product) { | 224 const Product& product) { |
| 226 HKEY reg_root = installer_state.root_key(); | 225 HKEY reg_root = installer_state.root_key(); |
| 227 BrowserDistribution* dist = product->distribution(); | 226 BrowserDistribution* dist = product.distribution(); |
| 228 DCHECK(dist); | 227 DCHECK(dist); |
| 229 | 228 |
| 230 base::win::RegistryValueIterator value_iter(reg_root, | 229 base::win::RegistryValueIterator value_iter(reg_root, |
| 231 dist->GetStateKey().c_str()); | 230 dist->GetStateKey().c_str()); |
| 232 for (; value_iter.Valid(); ++value_iter) { | 231 for (; value_iter.Valid(); ++value_iter) { |
| 233 base::string16 value_name(value_iter.Name()); | 232 base::string16 value_name(value_iter.Name()); |
| 234 if (base::StartsWith(value_name, kMsiProductIdPrefix, | 233 if (base::StartsWith(value_name, kMsiProductIdPrefix, |
| 235 base::CompareCase::INSENSITIVE_ASCII)) { | 234 base::CompareCase::INSENSITIVE_ASCII)) { |
| 236 return value_name.substr(arraysize(kMsiProductIdPrefix) - 1); | 235 return value_name.substr(arraysize(kMsiProductIdPrefix) - 1); |
| 237 } | 236 } |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 "Setup.Install.ApplyArchivePatchTime.background", elapsed_time); | 330 "Setup.Install.ApplyArchivePatchTime.background", elapsed_time); |
| 332 } else { | 331 } else { |
| 333 UMA_HISTOGRAM_LONG_TIMES( | 332 UMA_HISTOGRAM_LONG_TIMES( |
| 334 "Setup.Install.ApplyArchivePatchTime", elapsed_time); | 333 "Setup.Install.ApplyArchivePatchTime", elapsed_time); |
| 335 } | 334 } |
| 336 | 335 |
| 337 *archive_type = installer::INCREMENTAL_ARCHIVE_TYPE; | 336 *archive_type = installer::INCREMENTAL_ARCHIVE_TYPE; |
| 338 return true; | 337 return true; |
| 339 } | 338 } |
| 340 | 339 |
| 341 // In multi-install, adds all products to |installer_state| that are | |
| 342 // multi-installed and must be updated along with the products already present | |
| 343 // in |installer_state|. | |
| 344 void AddExistingMultiInstalls(const InstallationState& original_state, | |
| 345 InstallerState* installer_state) { | |
| 346 if (installer_state->is_multi_install()) { | |
| 347 for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) { | |
| 348 BrowserDistribution::Type type = | |
| 349 static_cast<BrowserDistribution::Type>(i); | |
| 350 | |
| 351 if (!installer_state->FindProduct(type)) { | |
| 352 const ProductState* state = | |
| 353 original_state.GetProductState(installer_state->system_install(), | |
| 354 type); | |
| 355 if (state) { | |
| 356 if (state->is_multi_install()) { | |
| 357 installer_state->AddProductFromState(type, *state); | |
| 358 VLOG(1) << "Product already installed and must be included: " | |
| 359 << BrowserDistribution::GetSpecificDistribution(type) | |
| 360 ->GetDisplayName(); | |
| 361 } | |
| 362 } else if (type == BrowserDistribution::CHROME_BROWSER) { | |
| 363 // Chrome is not installed from Google Update's point of view (missing | |
| 364 // "pv" in its Clients key). This is an edge case resulting from | |
| 365 // either local tampering or from a bug when a multi-install Chrome | |
| 366 // Frame was uninstalled; see https://crbug.com/579627. Check to see | |
| 367 // if any user has run Chrome within the last 28 days. | |
| 368 const bool is_used = IsChromeActivelyUsed(*installer_state); | |
| 369 UMA_HISTOGRAM_BOOLEAN("Setup.Install.StrandedChromeIsUsed", is_used); | |
| 370 if (is_used) { | |
| 371 // Add Chrome to the set of products to update to avoid leaving it | |
| 372 // behind. | |
| 373 std::unique_ptr<Product> multi_chrome(new Product( | |
| 374 BrowserDistribution::GetSpecificDistribution(type))); | |
| 375 multi_chrome->SetOption(installer::kOptionMultiInstall, true); | |
| 376 Product* chrome = installer_state->AddProduct(&multi_chrome); | |
| 377 VLOG(1) << "Broken install of product to be included for repair: " | |
| 378 << chrome->distribution()->GetDisplayName(); | |
| 379 } // else uninstall the binaries in UninstallBinariesIfUnused. | |
| 380 } | |
| 381 } | |
| 382 } | |
| 383 } | |
| 384 } | |
| 385 | |
| 386 void RecordNumDeleteOldVersionsAttempsBeforeAbort(int num_attempts) { | 340 void RecordNumDeleteOldVersionsAttempsBeforeAbort(int num_attempts) { |
| 387 UMA_HISTOGRAM_COUNTS_100( | 341 UMA_HISTOGRAM_COUNTS_100( |
| 388 "Setup.Install.NumDeleteOldVersionsAttemptsBeforeAbort", num_attempts); | 342 "Setup.Install.NumDeleteOldVersionsAttemptsBeforeAbort", num_attempts); |
| 389 } | 343 } |
| 390 | 344 |
| 391 // Repetitively attempts to delete all files that belong to old versions of | 345 // Repetitively attempts to delete all files that belong to old versions of |
| 392 // Chrome from |install_dir|. Waits 15 seconds before the first attempt and 5 | 346 // Chrome from |install_dir|. Waits 15 seconds before the first attempt and 5 |
| 393 // minutes after each unsuccessful attempt. Returns when no files that belong to | 347 // minutes after each unsuccessful attempt. Returns when no files that belong to |
| 394 // an old version of Chrome remain or when another process tries to acquire the | 348 // an old version of Chrome remain or when another process tries to acquire the |
| 395 // SetupSingleton. | 349 // SetupSingleton. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 // setup.exe command line. This function assumes an in-use update has happened | 405 // setup.exe command line. This function assumes an in-use update has happened |
| 452 // for Chrome so there should be a file called new_chrome.exe on the file | 406 // for Chrome so there should be a file called new_chrome.exe on the file |
| 453 // system and a key called 'opv' in the registry. This function will move | 407 // system and a key called 'opv' in the registry. This function will move |
| 454 // new_chrome.exe to chrome.exe and delete 'opv' key in one atomic operation. | 408 // new_chrome.exe to chrome.exe and delete 'opv' key in one atomic operation. |
| 455 // This function also deletes elevation policies associated with the old version | 409 // This function also deletes elevation policies associated with the old version |
| 456 // if they exist. |setup_exe| is the path to the current executable. | 410 // if they exist. |setup_exe| is the path to the current executable. |
| 457 installer::InstallStatus RenameChromeExecutables( | 411 installer::InstallStatus RenameChromeExecutables( |
| 458 const base::FilePath& setup_exe, | 412 const base::FilePath& setup_exe, |
| 459 const InstallationState& original_state, | 413 const InstallationState& original_state, |
| 460 InstallerState* installer_state) { | 414 InstallerState* installer_state) { |
| 461 // See what products are already installed in multi mode. When we do the | |
| 462 // rename for multi installs, we must update all installations since they | |
| 463 // share the binaries. | |
| 464 AddExistingMultiInstalls(original_state, installer_state); | |
| 465 const base::FilePath &target_path = installer_state->target_path(); | 415 const base::FilePath &target_path = installer_state->target_path(); |
| 466 base::FilePath chrome_exe(target_path.Append(installer::kChromeExe)); | 416 base::FilePath chrome_exe(target_path.Append(installer::kChromeExe)); |
| 467 base::FilePath chrome_new_exe(target_path.Append(installer::kChromeNewExe)); | 417 base::FilePath chrome_new_exe(target_path.Append(installer::kChromeNewExe)); |
| 468 base::FilePath chrome_old_exe(target_path.Append(installer::kChromeOldExe)); | 418 base::FilePath chrome_old_exe(target_path.Append(installer::kChromeOldExe)); |
| 469 | 419 |
| 470 // Create a temporary backup directory on the same volume as chrome.exe so | 420 // Create a temporary backup directory on the same volume as chrome.exe so |
| 471 // that moving in-use files doesn't lead to trouble. | 421 // that moving in-use files doesn't lead to trouble. |
| 472 installer::SelfCleaningTempDir temp_path; | 422 installer::SelfCleaningTempDir temp_path; |
| 473 if (!temp_path.Initialize(target_path.DirName(), | 423 if (!temp_path.Initialize(target_path.DirName(), |
| 474 installer::kInstallTempDir)) { | 424 installer::kInstallTempDir)) { |
| 475 PLOG(ERROR) << "Failed to create Temp directory " | 425 PLOG(ERROR) << "Failed to create Temp directory " |
| 476 << target_path.DirName() | 426 << target_path.DirName() |
| 477 .Append(installer::kInstallTempDir).value(); | 427 .Append(installer::kInstallTempDir).value(); |
| 478 return installer::RENAME_FAILED; | 428 return installer::RENAME_FAILED; |
| 479 } | 429 } |
| 480 std::unique_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); | 430 std::unique_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); |
| 481 // Move chrome.exe to old_chrome.exe, then move new_chrome.exe to chrome.exe. | 431 // Move chrome.exe to old_chrome.exe, then move new_chrome.exe to chrome.exe. |
| 482 install_list->AddMoveTreeWorkItem(chrome_exe.value(), | 432 install_list->AddMoveTreeWorkItem(chrome_exe.value(), |
| 483 chrome_old_exe.value(), | 433 chrome_old_exe.value(), |
| 484 temp_path.path().value(), | 434 temp_path.path().value(), |
| 485 WorkItem::ALWAYS_MOVE); | 435 WorkItem::ALWAYS_MOVE); |
| 486 install_list->AddMoveTreeWorkItem(chrome_new_exe.value(), | 436 install_list->AddMoveTreeWorkItem(chrome_new_exe.value(), |
| 487 chrome_exe.value(), | 437 chrome_exe.value(), |
| 488 temp_path.path().value(), | 438 temp_path.path().value(), |
| 489 WorkItem::ALWAYS_MOVE); | 439 WorkItem::ALWAYS_MOVE); |
| 490 install_list->AddDeleteTreeWorkItem(chrome_new_exe, temp_path.path()); | 440 install_list->AddDeleteTreeWorkItem(chrome_new_exe, temp_path.path()); |
| 491 | 441 |
| 492 // Add work items to delete the "opv", "cpv", and "cmd" values from all | 442 // Add work items to delete Chrome's "opv", "cpv", and "cmd" values. |
| 493 // products we're operating on (which including the multi-install binaries). | 443 // TODO(grt): Clean this up; https://crbug.com/577816. |
| 494 const Products& products = installer_state->products(); | |
| 495 HKEY reg_root = installer_state->root_key(); | 444 HKEY reg_root = installer_state->root_key(); |
| 496 base::string16 version_key; | 445 base::string16 version_key; |
| 497 for (Products::const_iterator it = products.begin(); it < products.end(); | 446 version_key = installer_state->product().distribution()->GetVersionKey(); |
| 498 ++it) { | 447 install_list->AddDeleteRegValueWorkItem(reg_root, version_key, |
| 499 version_key = (*it)->distribution()->GetVersionKey(); | 448 KEY_WOW64_32KEY, |
| 500 install_list->AddDeleteRegValueWorkItem(reg_root, | 449 google_update::kRegOldVersionField); |
| 501 version_key, | 450 install_list->AddDeleteRegValueWorkItem( |
| 502 KEY_WOW64_32KEY, | 451 reg_root, version_key, KEY_WOW64_32KEY, |
| 503 google_update::kRegOldVersionField); | 452 google_update::kRegCriticalVersionField); |
| 504 install_list->AddDeleteRegValueWorkItem( | 453 install_list->AddDeleteRegValueWorkItem(reg_root, version_key, |
| 505 reg_root, | 454 KEY_WOW64_32KEY, |
| 506 version_key, | 455 google_update::kRegRenameCmdField); |
| 507 KEY_WOW64_32KEY, | |
| 508 google_update::kRegCriticalVersionField); | |
| 509 install_list->AddDeleteRegValueWorkItem(reg_root, | |
| 510 version_key, | |
| 511 KEY_WOW64_32KEY, | |
| 512 google_update::kRegRenameCmdField); | |
| 513 } | |
| 514 // old_chrome.exe is still in use in most cases, so ignore failures here. | 456 // old_chrome.exe is still in use in most cases, so ignore failures here. |
| 515 install_list->AddDeleteTreeWorkItem(chrome_old_exe, temp_path.path()) | 457 install_list->AddDeleteTreeWorkItem(chrome_old_exe, temp_path.path()) |
| 516 ->set_best_effort(true); | 458 ->set_best_effort(true); |
| 517 | 459 |
| 518 installer::InstallStatus ret = installer::RENAME_SUCCESSFUL; | 460 installer::InstallStatus ret = installer::RENAME_SUCCESSFUL; |
| 519 if (install_list->Do()) { | 461 if (install_list->Do()) { |
| 520 installer::LaunchDeleteOldVersionsProcess(setup_exe, *installer_state); | 462 installer::LaunchDeleteOldVersionsProcess(setup_exe, *installer_state); |
| 521 } else { | 463 } else { |
| 522 LOG(ERROR) << "Renaming of executables failed. Rolling back any changes."; | 464 LOG(ERROR) << "Renaming of executables failed. Rolling back any changes."; |
| 523 install_list->Rollback(); | 465 install_list->Rollback(); |
| 524 ret = installer::RENAME_FAILED; | 466 ret = installer::RENAME_FAILED; |
| 525 } | 467 } |
| 526 // temp_path's dtor will take care of deleting or scheduling itself for | 468 // temp_path's dtor will take care of deleting or scheduling itself for |
| 527 // deletion at reboot when this scope closes. | 469 // deletion at reboot when this scope closes. |
| 528 VLOG(1) << "Deleting temporary directory " << temp_path.path().value(); | 470 VLOG(1) << "Deleting temporary directory " << temp_path.path().value(); |
| 529 | 471 |
| 530 return ret; | 472 return ret; |
| 531 } | 473 } |
| 532 | 474 |
| 533 // Fail with UNUSED_BINARIES if only the binaries are being updated. | |
| 534 bool CheckMultiInstallConditions(const InstallationState& original_state, | |
| 535 InstallerState* installer_state, | |
| 536 installer::InstallStatus* status) { | |
| 537 const Products& products = installer_state->products(); | |
| 538 DCHECK(products.size()); | |
| 539 | |
| 540 const bool system_level = installer_state->system_install(); | |
| 541 | |
| 542 if (installer_state->is_multi_install()) { | |
| 543 const Product* chrome = | |
| 544 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); | |
| 545 const Product* binaries = | |
| 546 installer_state->FindProduct(BrowserDistribution::CHROME_BINARIES); | |
| 547 const ProductState* chrome_state = | |
| 548 original_state.GetProductState(system_level, | |
| 549 BrowserDistribution::CHROME_BROWSER); | |
| 550 | |
| 551 if (binaries) { | |
| 552 if (products.size() == 1) { | |
| 553 // There are no products aside from the binaries, so there is no update | |
| 554 // to be applied. This can happen after multi-install Chrome Frame is | |
| 555 // migrated to single-install. This is treated as an update failure | |
| 556 // unless the binaries are not in-use, in which case they will be | |
| 557 // uninstalled and success will be reported (see handling in wWinMain). | |
| 558 VLOG(1) << "No products to be updated."; | |
| 559 *status = installer::UNUSED_BINARIES; | |
| 560 installer_state->WriteInstallerResult(*status, 0, NULL); | |
| 561 return false; | |
| 562 } | |
| 563 } else { | |
| 564 // This will only be hit if --multi-install is given with no products. | |
| 565 return true; | |
| 566 } | |
| 567 | |
| 568 if (!chrome && chrome_state) { | |
| 569 // A product other than Chrome is being installed in multi-install mode, | |
| 570 // and Chrome is already present. Add Chrome to the set of products | |
| 571 // (making it multi-install in the process) so that it is updated, too. | |
| 572 std::unique_ptr<Product> multi_chrome( | |
| 573 new Product(BrowserDistribution::GetSpecificDistribution( | |
| 574 BrowserDistribution::CHROME_BROWSER))); | |
| 575 multi_chrome->SetOption(installer::kOptionMultiInstall, true); | |
| 576 chrome = installer_state->AddProduct(&multi_chrome); | |
| 577 VLOG(1) << "Upgrading existing Chrome browser in multi-install mode."; | |
| 578 } | |
| 579 } // else migrate multi-install Chrome to single-install. | |
| 580 | |
| 581 return true; | |
| 582 } | |
| 583 | |
| 584 // Checks for compatibility between the current state of the system and the | 475 // Checks for compatibility between the current state of the system and the |
| 585 // desired operation. Also applies policy that mutates the desired operation; | 476 // desired operation. |
| 586 // specifically, the |installer_state| object. | |
| 587 // Also blocks simultaneous user-level and system-level installs. In the case | 477 // Also blocks simultaneous user-level and system-level installs. In the case |
| 588 // of trying to install user-level Chrome when system-level exists, the | 478 // of trying to install user-level Chrome when system-level exists, the |
| 589 // existing system-level Chrome is launched. | 479 // existing system-level Chrome is launched. |
| 590 // When the pre-install conditions are not satisfied, the result is written to | 480 // When the pre-install conditions are not satisfied, the result is written to |
| 591 // the registry (via WriteInstallerResult), |status| is set appropriately, and | 481 // the registry (via WriteInstallerResult), |status| is set appropriately, and |
| 592 // false is returned. | 482 // false is returned. |
| 593 bool CheckPreInstallConditions(const InstallationState& original_state, | 483 bool CheckPreInstallConditions(const InstallationState& original_state, |
| 594 InstallerState* installer_state, | 484 const InstallerState& installer_state, |
| 595 installer::InstallStatus* status) { | 485 installer::InstallStatus* status) { |
| 596 // See what products are already installed in multi mode. When we do multi | 486 if (!installer_state.system_install()) { |
| 597 // installs, we must upgrade all installations since they share the binaries. | |
| 598 AddExistingMultiInstalls(original_state, installer_state); | |
| 599 | |
| 600 if (!CheckMultiInstallConditions(original_state, installer_state, status)) { | |
| 601 DCHECK_NE(*status, installer::UNKNOWN_STATUS); | |
| 602 return false; | |
| 603 } | |
| 604 | |
| 605 const Products& products = installer_state->products(); | |
| 606 if (products.empty()) { | |
| 607 // We haven't been given any products on which to operate. | |
| 608 LOG(ERROR) | |
| 609 << "Not given any products to install and no products found to update."; | |
| 610 *status = installer::CHROME_NOT_INSTALLED; | |
| 611 installer_state->WriteInstallerResult(*status, | |
| 612 IDS_INSTALL_NO_PRODUCTS_TO_UPDATE_BASE, nullptr); | |
| 613 return false; | |
| 614 } | |
| 615 | |
| 616 if (!installer_state->system_install()) { | |
| 617 // This is a user-level installation. Make sure that we are not installing | 487 // This is a user-level installation. Make sure that we are not installing |
| 618 // on top of an existing system-level installation. | 488 // on top of an existing system-level installation. |
| 619 for (Products::const_iterator it = products.begin(); it < products.end(); | 489 const Product& product = installer_state.product(); |
| 620 ++it) { | 490 BrowserDistribution* browser_dist = product.distribution(); |
| 621 const Product& product = **it; | |
| 622 BrowserDistribution* browser_dist = product.distribution(); | |
| 623 | 491 |
| 624 // Skip over the binaries, as it's okay for them to be at both levels | 492 const ProductState* user_level_product_state = |
| 625 // for different products. | 493 original_state.GetProductState(false, browser_dist->GetType()); |
| 626 if (browser_dist->GetType() == BrowserDistribution::CHROME_BINARIES) | 494 const ProductState* system_level_product_state = |
| 627 continue; | 495 original_state.GetProductState(true, browser_dist->GetType()); |
| 628 | 496 |
| 629 const ProductState* user_level_product_state = | 497 // Allow upgrades to proceed so that out-of-date versions are not left |
| 630 original_state.GetProductState(false, browser_dist->GetType()); | 498 // around. |
| 631 const ProductState* system_level_product_state = | 499 if (user_level_product_state) |
| 632 original_state.GetProductState(true, browser_dist->GetType()); | 500 return true; |
| 633 | 501 |
| 634 // Allow upgrades to proceed so that out-of-date versions are not left | 502 // This is a new user-level install... |
| 635 // around. | |
| 636 if (user_level_product_state) | |
| 637 continue; | |
| 638 | 503 |
| 639 // This is a new user-level install... | 504 if (system_level_product_state) { |
| 640 | 505 // ... and the product already exists at system-level. |
| 641 if (system_level_product_state) { | 506 LOG(ERROR) << "Already installed version " |
| 642 // ... and the product already exists at system-level. | 507 << system_level_product_state->version().GetString() |
| 643 LOG(ERROR) << "Already installed version " | 508 << " at system-level conflicts with this one at user-level."; |
| 644 << system_level_product_state->version().GetString() | 509 // Instruct Google Update to launch the existing system-level Chrome. |
| 645 << " at system-level conflicts with this one at user-level."; | 510 // There should be no error dialog. |
| 646 if (product.is_chrome()) { | 511 base::FilePath install_path( |
| 647 // Instruct Google Update to launch the existing system-level Chrome. | 512 installer::GetChromeInstallPath(true, // system |
| 648 // There should be no error dialog. | 513 browser_dist)); |
| 649 base::FilePath install_path(installer::GetChromeInstallPath( | 514 if (install_path.empty()) { |
| 650 true, // system | 515 // Give up if we failed to construct the install path. |
| 651 browser_dist)); | 516 *status = installer::OS_ERROR; |
| 652 if (install_path.empty()) { | 517 installer_state.WriteInstallerResult(*status, IDS_INSTALL_OS_ERROR_BASE, |
| 653 // Give up if we failed to construct the install path. | 518 nullptr); |
| 654 *status = installer::OS_ERROR; | 519 } else { |
| 655 installer_state->WriteInstallerResult(*status, | 520 *status = installer::EXISTING_VERSION_LAUNCHED; |
| 656 IDS_INSTALL_OS_ERROR_BASE, | 521 base::FilePath chrome_exe = install_path.Append(installer::kChromeExe); |
| 657 nullptr); | 522 base::CommandLine cmd(chrome_exe); |
| 658 } else { | 523 cmd.AppendSwitch(switches::kForceFirstRun); |
| 659 *status = installer::EXISTING_VERSION_LAUNCHED; | 524 installer_state.WriteInstallerResult( |
| 660 base::FilePath chrome_exe = | 525 *status, IDS_INSTALL_EXISTING_VERSION_LAUNCHED_BASE, nullptr); |
| 661 install_path.Append(installer::kChromeExe); | 526 VLOG(1) << "Launching existing system-level chrome instead."; |
| 662 base::CommandLine cmd(chrome_exe); | 527 base::LaunchProcess(cmd, base::LaunchOptions()); |
| 663 cmd.AppendSwitch(switches::kForceFirstRun); | |
| 664 installer_state->WriteInstallerResult( | |
| 665 *status, IDS_INSTALL_EXISTING_VERSION_LAUNCHED_BASE, nullptr); | |
| 666 VLOG(1) << "Launching existing system-level chrome instead."; | |
| 667 base::LaunchProcess(cmd, base::LaunchOptions()); | |
| 668 } | |
| 669 } else { | |
| 670 // It's no longer possible for |product| to be anything other than | |
| 671 // Chrome. | |
| 672 NOTREACHED(); | |
| 673 } | |
| 674 return false; | |
| 675 } | 528 } |
| 529 return false; |
| 676 } | 530 } |
| 677 } | 531 } |
| 678 | 532 |
| 679 return true; | 533 return true; |
| 680 } | 534 } |
| 681 | 535 |
| 682 // Initializes |temp_path| to "Temp" within the target directory, and | 536 // Initializes |temp_path| to "Temp" within the target directory, and |
| 683 // |unpack_path| to a random directory beginning with "source" within | 537 // |unpack_path| to a random directory beginning with "source" within |
| 684 // |temp_path|. Returns false on error. | 538 // |temp_path|. Returns false on error. |
| 685 bool CreateTemporaryAndUnpackDirectories( | 539 bool CreateTemporaryAndUnpackDirectories( |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 return installer::UninstallProduct( | 582 return installer::UninstallProduct( |
| 729 original_state, installer_state, setup_exe, product, remove_all, | 583 original_state, installer_state, setup_exe, product, remove_all, |
| 730 force_uninstall, cmd_line); | 584 force_uninstall, cmd_line); |
| 731 } | 585 } |
| 732 | 586 |
| 733 installer::InstallStatus UninstallProducts( | 587 installer::InstallStatus UninstallProducts( |
| 734 const InstallationState& original_state, | 588 const InstallationState& original_state, |
| 735 const InstallerState& installer_state, | 589 const InstallerState& installer_state, |
| 736 const base::FilePath& setup_exe, | 590 const base::FilePath& setup_exe, |
| 737 const base::CommandLine& cmd_line) { | 591 const base::CommandLine& cmd_line) { |
| 738 const Products& products = installer_state.products(); | |
| 739 | |
| 740 // System-level Chrome will be launched via this command if its program gets | 592 // System-level Chrome will be launched via this command if its program gets |
| 741 // set below. | 593 // set below. |
| 742 base::CommandLine system_level_cmd(base::CommandLine::NO_PROGRAM); | 594 base::CommandLine system_level_cmd(base::CommandLine::NO_PROGRAM); |
| 743 | 595 |
| 744 const Product* chrome = | 596 const Product& chrome = installer_state.product(); |
| 745 installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER); | 597 if (cmd_line.HasSwitch(installer::switches::kSelfDestruct) && |
| 746 if (chrome) { | 598 !installer_state.system_install()) { |
| 747 // InstallerState::Initialize always puts Chrome first, and we rely on that | 599 BrowserDistribution* dist = chrome.distribution(); |
| 748 // here for this reason: if Chrome is in-use, the user will be prompted to | 600 const base::FilePath system_exe_path( |
| 749 // confirm uninstallation. Upon cancel, we should not continue with the | 601 installer::GetChromeInstallPath(true, dist) |
| 750 // other products. | 602 .Append(installer::kChromeExe)); |
| 751 DCHECK(products[0]->is_chrome()); | 603 system_level_cmd.SetProgram(system_exe_path); |
| 752 | |
| 753 if (cmd_line.HasSwitch(installer::switches::kSelfDestruct) && | |
| 754 !installer_state.system_install()) { | |
| 755 BrowserDistribution* dist = chrome->distribution(); | |
| 756 const base::FilePath system_exe_path( | |
| 757 installer::GetChromeInstallPath(true, dist) | |
| 758 .Append(installer::kChromeExe)); | |
| 759 system_level_cmd.SetProgram(system_exe_path); | |
| 760 } | |
| 761 } | |
| 762 if (installer_state.FindProduct(BrowserDistribution::CHROME_BINARIES)) { | |
| 763 // Chrome Binaries should be last; if something else is cancelled, they | |
| 764 // should stay. | |
| 765 DCHECK(products.back()->is_chrome_binaries()); | |
| 766 } | 604 } |
| 767 | 605 |
| 768 installer::InstallStatus install_status = installer::UNINSTALL_SUCCESSFUL; | 606 installer::InstallStatus install_status = installer::UNINSTALL_SUCCESSFUL; |
| 769 installer::InstallStatus prod_status = installer::UNKNOWN_STATUS; | |
| 770 const bool force = cmd_line.HasSwitch(installer::switches::kForceUninstall); | 607 const bool force = cmd_line.HasSwitch(installer::switches::kForceUninstall); |
| 771 const bool remove_all = !cmd_line.HasSwitch( | 608 const bool remove_all = !cmd_line.HasSwitch( |
| 772 installer::switches::kDoNotRemoveSharedItems); | 609 installer::switches::kDoNotRemoveSharedItems); |
| 773 | 610 |
| 774 for (Products::const_iterator it = products.begin(); | 611 install_status = |
| 775 install_status != installer::UNINSTALL_CANCELLED && it < products.end(); | 612 UninstallProduct(original_state, installer_state, setup_exe, cmd_line, |
| 776 ++it) { | 613 remove_all, force, installer_state.product()); |
| 777 prod_status = UninstallProduct(original_state, installer_state, setup_exe, | |
| 778 cmd_line, remove_all, force, **it); | |
| 779 if (prod_status != installer::UNINSTALL_SUCCESSFUL) | |
| 780 install_status = prod_status; | |
| 781 } | |
| 782 | 614 |
| 783 installer::CleanUpInstallationDirectoryAfterUninstall( | 615 installer::CleanUpInstallationDirectoryAfterUninstall( |
| 784 original_state, installer_state, setup_exe, &install_status); | 616 original_state, installer_state, setup_exe, &install_status); |
| 785 | 617 |
| 786 // The app and vendor dirs may now be empty. Make a last-ditch attempt to | 618 // The app and vendor dirs may now be empty. Make a last-ditch attempt to |
| 787 // delete them. | 619 // delete them. |
| 788 installer::DeleteChromeDirectoriesIfEmpty(installer_state.target_path()); | 620 installer::DeleteChromeDirectoriesIfEmpty(installer_state.target_path()); |
| 789 | 621 |
| 790 // Trigger Active Setup if it was requested for the chrome product. This needs | 622 // Trigger Active Setup if it was requested for the chrome product. This needs |
| 791 // to be done after the UninstallProduct calls as some of them might | 623 // to be done after the UninstallProduct calls as some of them might |
| 792 // otherwise terminate the process launched by TriggerActiveSetupCommand(). | 624 // otherwise terminate the process launched by TriggerActiveSetupCommand(). |
| 793 if (chrome && cmd_line.HasSwitch(installer::switches::kTriggerActiveSetup)) | 625 if (cmd_line.HasSwitch(installer::switches::kTriggerActiveSetup)) |
| 794 InstallUtil::TriggerActiveSetupCommand(); | 626 InstallUtil::TriggerActiveSetupCommand(); |
| 795 | 627 |
| 796 if (!system_level_cmd.GetProgram().empty()) | 628 if (!system_level_cmd.GetProgram().empty()) |
| 797 base::LaunchProcess(system_level_cmd, base::LaunchOptions()); | 629 base::LaunchProcess(system_level_cmd, base::LaunchOptions()); |
| 798 | 630 |
| 799 // Tell Google Update that an uninstall has taken place. | 631 // Tell Google Update that an uninstall has taken place. |
| 800 // Ignore the return value: success or failure of Google Update | 632 // Ignore the return value: success or failure of Google Update |
| 801 // has no bearing on the success or failure of Chrome's uninstallation. | 633 // has no bearing on the success or failure of Chrome's uninstallation. |
| 802 google_update::UninstallGoogleUpdate(installer_state.system_install()); | 634 google_update::UninstallGoogleUpdate(installer_state.system_install()); |
| 803 | 635 |
| 804 return install_status; | 636 return install_status; |
| 805 } | 637 } |
| 806 | 638 |
| 807 // Uninstall the binaries if they are the only product present and they're not | |
| 808 // in-use. | |
| 809 void UninstallBinariesIfUnused( | |
| 810 const InstallationState& original_state, | |
| 811 const InstallerState& installer_state, | |
| 812 installer::InstallStatus* install_status) { | |
| 813 // Early exit if the binaries are still in use. | |
| 814 if (*install_status != installer::UNUSED_BINARIES || | |
| 815 installer_state.AreBinariesInUse(original_state)) { | |
| 816 return; | |
| 817 } | |
| 818 | |
| 819 LOG(INFO) << "Uninstalling unused binaries"; | |
| 820 installer_state.SetStage(installer::UNINSTALLING_BINARIES); | |
| 821 | |
| 822 // Create an InstallerState that represents a force uninstall of Chrome | |
| 823 // residing with the installed version of the binaries. This will result in | |
| 824 // removing Chrome and all of its program files and associated registrations | |
| 825 // (aside from user data). | |
| 826 const ProductState* binaries_state = | |
| 827 original_state.GetProductState(installer_state.system_install(), | |
| 828 BrowserDistribution::CHROME_BINARIES); | |
| 829 base::CommandLine uninstall_cmd(binaries_state->uninstall_command()); | |
| 830 uninstall_cmd.AppendSwitch(installer::switches::kChrome); | |
| 831 uninstall_cmd.AppendSwitch(installer::switches::kForceUninstall); | |
| 832 MasterPreferences uninstall_prefs(uninstall_cmd); | |
| 833 InstallerState uninstall_state; | |
| 834 uninstall_state.Initialize(uninstall_cmd, uninstall_prefs, original_state); | |
| 835 *install_status = UninstallProducts(original_state, uninstall_state, | |
| 836 uninstall_cmd.GetProgram(), | |
| 837 uninstall_cmd); | |
| 838 | |
| 839 // Report that the binaries were uninstalled if they were. This translates | |
| 840 // into a successful install/update return code. | |
| 841 if (IsUninstallSuccess(*install_status)) { | |
| 842 *install_status = installer::UNUSED_BINARIES_UNINSTALLED; | |
| 843 #if defined(GOOGLE_CHROME_BUILD) | |
| 844 // Write the result for the sake of Google Update in Google Chrome builds, | |
| 845 // but skip this for Chromium builds. The reason is a bit icky: Chromium | |
| 846 // builds lump the "ClientState" and "Clients" keys into a single key. As a | |
| 847 // consequence, writing this value causes Software\Chromium to be re-created | |
| 848 // after it was deleted during the uninstall. Google Chrome builds don't | |
| 849 // suffer this since the two keys are distinct and have different lifetimes. | |
| 850 installer_state.WriteInstallerResult(*install_status, 0, NULL); | |
| 851 #endif | |
| 852 } | |
| 853 } | |
| 854 | |
| 855 installer::InstallStatus InstallProducts( | 639 installer::InstallStatus InstallProducts( |
| 856 const InstallationState& original_state, | 640 const InstallationState& original_state, |
| 857 const base::FilePath& setup_exe, | 641 const base::FilePath& setup_exe, |
| 858 const base::CommandLine& cmd_line, | 642 const base::CommandLine& cmd_line, |
| 859 const MasterPreferences& prefs, | 643 const MasterPreferences& prefs, |
| 860 InstallerState* installer_state, | 644 InstallerState* installer_state, |
| 861 base::FilePath* installer_directory) { | 645 base::FilePath* installer_directory) { |
| 862 DCHECK(installer_state); | 646 DCHECK(installer_state); |
| 863 const bool system_install = installer_state->system_install(); | 647 const bool system_install = installer_state->system_install(); |
| 864 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; | 648 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; |
| 865 installer::ArchiveType archive_type = installer::UNKNOWN_ARCHIVE_TYPE; | 649 installer::ArchiveType archive_type = installer::UNKNOWN_ARCHIVE_TYPE; |
| 866 installer_state->SetStage(installer::PRECONDITIONS); | 650 installer_state->SetStage(installer::PRECONDITIONS); |
| 867 // Remove any legacy "-multifail" or "-stage:*" values from the product's | 651 // Remove any legacy "-multifail" or "-stage:*" values from the product's |
| 868 // "ap" value. | 652 // "ap" value. |
| 869 BrowserDistribution::GetSpecificDistribution(installer_state->state_type())-> | 653 BrowserDistribution::GetSpecificDistribution(installer_state->state_type())-> |
| 870 UpdateInstallStatus(system_install, archive_type, install_status); | 654 UpdateInstallStatus(system_install, archive_type, install_status); |
| 871 | 655 |
| 872 // Drop to background processing mode if the process was started below the | 656 // Drop to background processing mode if the process was started below the |
| 873 // normal process priority class. This is done here because InstallProducts- | 657 // normal process priority class. This is done here because InstallProducts- |
| 874 // Helper has read-only access to the state and because the action also | 658 // Helper has read-only access to the state and because the action also |
| 875 // affects everything else that runs below. | 659 // affects everything else that runs below. |
| 876 bool entered_background_mode = installer::AdjustProcessPriority(); | 660 bool entered_background_mode = installer::AdjustProcessPriority(); |
| 877 installer_state->set_background_mode(entered_background_mode); | 661 installer_state->set_background_mode(entered_background_mode); |
| 878 VLOG_IF(1, entered_background_mode) << "Entered background processing mode."; | 662 VLOG_IF(1, entered_background_mode) << "Entered background processing mode."; |
| 879 | 663 |
| 880 if (CheckPreInstallConditions(original_state, installer_state, | 664 if (CheckPreInstallConditions(original_state, *installer_state, |
| 881 &install_status)) { | 665 &install_status)) { |
| 882 VLOG(1) << "Installing to " << installer_state->target_path().value(); | 666 VLOG(1) << "Installing to " << installer_state->target_path().value(); |
| 883 install_status = InstallProductsHelper( | 667 install_status = InstallProductsHelper( |
| 884 original_state, setup_exe, cmd_line, prefs, *installer_state, | 668 original_state, setup_exe, cmd_line, prefs, *installer_state, |
| 885 installer_directory, &archive_type); | 669 installer_directory, &archive_type); |
| 886 } else { | 670 } else { |
| 887 // CheckPreInstallConditions must set the status on failure. | 671 // CheckPreInstallConditions must set the status on failure. |
| 888 DCHECK_NE(install_status, installer::UNKNOWN_STATUS); | 672 DCHECK_NE(install_status, installer::UNKNOWN_STATUS); |
| 889 } | 673 } |
| 890 | 674 |
| 891 // Delete the master preferences file if present. Note that we do not care | 675 // Delete the master preferences file if present. Note that we do not care |
| 892 // about rollback here and we schedule for deletion on reboot if the delete | 676 // about rollback here and we schedule for deletion on reboot if the delete |
| 893 // fails. As such, we do not use DeleteTreeWorkItem. | 677 // fails. As such, we do not use DeleteTreeWorkItem. |
| 894 if (cmd_line.HasSwitch(installer::switches::kInstallerData)) { | 678 if (cmd_line.HasSwitch(installer::switches::kInstallerData)) { |
| 895 base::FilePath prefs_path(cmd_line.GetSwitchValuePath( | 679 base::FilePath prefs_path(cmd_line.GetSwitchValuePath( |
| 896 installer::switches::kInstallerData)); | 680 installer::switches::kInstallerData)); |
| 897 if (!base::DeleteFile(prefs_path, false)) { | 681 if (!base::DeleteFile(prefs_path, false)) { |
| 898 LOG(ERROR) << "Failed deleting master preferences file " | 682 LOG(ERROR) << "Failed deleting master preferences file " |
| 899 << prefs_path.value() | 683 << prefs_path.value() |
| 900 << ", scheduling for deletion after reboot."; | 684 << ", scheduling for deletion after reboot."; |
| 901 ScheduleFileSystemEntityForDeletion(prefs_path); | 685 ScheduleFileSystemEntityForDeletion(prefs_path); |
| 902 } | 686 } |
| 903 } | 687 } |
| 904 | 688 |
| 905 const Products& products = installer_state->products(); | 689 installer_state->product().distribution()->UpdateInstallStatus( |
| 906 for (Products::const_iterator it = products.begin(); it < products.end(); | 690 system_install, archive_type, install_status); |
| 907 ++it) { | |
| 908 (*it)->distribution()->UpdateInstallStatus( | |
| 909 system_install, archive_type, install_status); | |
| 910 } | |
| 911 | |
| 912 // Handle installer::UNUSED_BINARIES returned by CheckPreInstallConditions. | |
| 913 UninstallBinariesIfUnused(original_state, *installer_state, &install_status); | |
| 914 | 691 |
| 915 return install_status; | 692 return install_status; |
| 916 } | 693 } |
| 917 | 694 |
| 918 installer::InstallStatus ShowEULADialog(const base::string16& inner_frame) { | 695 installer::InstallStatus ShowEULADialog(const base::string16& inner_frame) { |
| 919 VLOG(1) << "About to show EULA"; | 696 VLOG(1) << "About to show EULA"; |
| 920 base::string16 eula_path = installer::GetLocalizedEulaResource(); | 697 base::string16 eula_path = installer::GetLocalizedEulaResource(); |
| 921 if (eula_path.empty()) { | 698 if (eula_path.empty()) { |
| 922 LOG(ERROR) << "No EULA path available"; | 699 LOG(ERROR) << "No EULA path available"; |
| 923 return installer::EULA_REJECTED; | 700 return installer::EULA_REJECTED; |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1090 if (installer::EULA_REJECTED != *exit_code) { | 867 if (installer::EULA_REJECTED != *exit_code) { |
| 1091 if (GoogleUpdateSettings::SetEULAConsent( | 868 if (GoogleUpdateSettings::SetEULAConsent( |
| 1092 *original_state, BrowserDistribution::GetDistribution(), true)) { | 869 *original_state, BrowserDistribution::GetDistribution(), true)) { |
| 1093 CreateEULASentinel(BrowserDistribution::GetDistribution()); | 870 CreateEULASentinel(BrowserDistribution::GetDistribution()); |
| 1094 } | 871 } |
| 1095 } | 872 } |
| 1096 } else if (cmd_line.HasSwitch(installer::switches::kConfigureUserSettings)) { | 873 } else if (cmd_line.HasSwitch(installer::switches::kConfigureUserSettings)) { |
| 1097 // NOTE: Should the work done here, on kConfigureUserSettings, change: | 874 // NOTE: Should the work done here, on kConfigureUserSettings, change: |
| 1098 // kActiveSetupVersion in install_worker.cc needs to be increased for Active | 875 // kActiveSetupVersion in install_worker.cc needs to be increased for Active |
| 1099 // Setup to invoke this again for all users of this install. | 876 // Setup to invoke this again for all users of this install. |
| 1100 const Product* chrome_install = | 877 const Product& chrome_install = installer_state->product(); |
| 1101 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); | |
| 1102 installer::InstallStatus status = installer::INVALID_STATE_FOR_OPTION; | 878 installer::InstallStatus status = installer::INVALID_STATE_FOR_OPTION; |
| 1103 if (chrome_install && installer_state->system_install()) { | 879 if (installer_state->system_install()) { |
| 1104 bool force = | 880 bool force = |
| 1105 cmd_line.HasSwitch(installer::switches::kForceConfigureUserSettings); | 881 cmd_line.HasSwitch(installer::switches::kForceConfigureUserSettings); |
| 1106 installer::HandleActiveSetupForBrowser(installer_state->target_path(), | 882 installer::HandleActiveSetupForBrowser(installer_state->target_path(), |
| 1107 *chrome_install, force); | 883 chrome_install, force); |
| 1108 status = installer::INSTALL_REPAIRED; | 884 status = installer::INSTALL_REPAIRED; |
| 1109 } else { | 885 } else { |
| 1110 LOG(DFATAL) << "chrome_install:" << chrome_install | 886 LOG(DFATAL) |
| 1111 << ", system_install:" << installer_state->system_install(); | 887 << "--configure-user-settings is incompatible with user-level"; |
| 1112 } | 888 } |
| 1113 *exit_code = InstallUtil::GetInstallReturnCode(status); | 889 *exit_code = InstallUtil::GetInstallReturnCode(status); |
| 1114 } else if (cmd_line.HasSwitch(installer::switches::kRegisterDevChrome)) { | 890 } else if (cmd_line.HasSwitch(installer::switches::kRegisterDevChrome)) { |
| 1115 installer::InstallStatus status = RegisterDevChrome( | 891 installer::InstallStatus status = RegisterDevChrome( |
| 1116 *original_state, *installer_state, setup_exe, cmd_line); | 892 *original_state, *installer_state, setup_exe, cmd_line); |
| 1117 *exit_code = InstallUtil::GetInstallReturnCode(status); | 893 *exit_code = InstallUtil::GetInstallReturnCode(status); |
| 1118 } else if (cmd_line.HasSwitch(installer::switches::kRegisterChromeBrowser)) { | 894 } else if (cmd_line.HasSwitch(installer::switches::kRegisterChromeBrowser)) { |
| 1119 installer::InstallStatus status = installer::UNKNOWN_STATUS; | 895 installer::InstallStatus status = installer::UNKNOWN_STATUS; |
| 1120 const Product* chrome_install = | 896 const Product& chrome_install = installer_state->product(); |
| 1121 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); | 897 // If --register-chrome-browser option is specified, register all Chrome |
| 1122 if (chrome_install) { | 898 // protocol/file associations, as well as register it as a valid browser for |
| 1123 // If --register-chrome-browser option is specified, register all | 899 // Start Menu->Internet shortcut. This switch will also register Chrome as a |
| 1124 // Chrome protocol/file associations, as well as register it as a valid | 900 // valid handler for a set of URL protocols that Chrome may become the |
| 1125 // browser for Start Menu->Internet shortcut. This switch will also | 901 // default handler for, either by the user marking Chrome as the default |
| 1126 // register Chrome as a valid handler for a set of URL protocols that | 902 // browser, through the Windows Default Programs control panel settings, or |
| 1127 // Chrome may become the default handler for, either by the user marking | 903 // through website use of registerProtocolHandler. These protocols are found |
| 1128 // Chrome as the default browser, through the Windows Default Programs | 904 // in ShellUtil::kPotentialProtocolAssociations. The |
| 1129 // control panel settings, or through website use of | 905 // --register-url-protocol will additionally register Chrome as a potential |
| 1130 // registerProtocolHandler. These protocols are found in | 906 // handler for the supplied protocol, and is used if a website registers a |
| 1131 // ShellUtil::kPotentialProtocolAssociations. | 907 // handler for a protocol not found in |
| 1132 // The --register-url-protocol will additionally register Chrome as a | 908 // ShellUtil::kPotentialProtocolAssociations. These options should only be |
| 1133 // potential handler for the supplied protocol, and is used if a website | 909 // used when setup.exe is launched with admin rights. We do not make any |
| 1134 // registers a handler for a protocol not found in | 910 // user specific changes with this option. |
| 1135 // ShellUtil::kPotentialProtocolAssociations. | 911 DCHECK(IsUserAnAdmin()); |
| 1136 // These options should only be used when setup.exe is launched with admin | 912 base::FilePath chrome_exe(cmd_line.GetSwitchValuePath( |
| 1137 // rights. We do not make any user specific changes with this option. | 913 installer::switches::kRegisterChromeBrowser)); |
| 1138 DCHECK(IsUserAnAdmin()); | 914 base::string16 suffix; |
| 1139 base::FilePath chrome_exe(cmd_line.GetSwitchValuePath( | 915 if (cmd_line.HasSwitch(installer::switches::kRegisterChromeBrowserSuffix)) { |
| 1140 installer::switches::kRegisterChromeBrowser)); | 916 suffix = cmd_line.GetSwitchValueNative( |
| 1141 base::string16 suffix; | 917 installer::switches::kRegisterChromeBrowserSuffix); |
| 1142 if (cmd_line.HasSwitch( | 918 } |
| 1143 installer::switches::kRegisterChromeBrowserSuffix)) { | 919 if (cmd_line.HasSwitch(installer::switches::kRegisterURLProtocol)) { |
| 1144 suffix = cmd_line.GetSwitchValueNative( | 920 base::string16 protocol = cmd_line.GetSwitchValueNative( |
| 1145 installer::switches::kRegisterChromeBrowserSuffix); | 921 installer::switches::kRegisterURLProtocol); |
| 1146 } | 922 // ShellUtil::RegisterChromeForProtocol performs all registration |
| 1147 if (cmd_line.HasSwitch(installer::switches::kRegisterURLProtocol)) { | 923 // done by ShellUtil::RegisterChromeBrowser, as well as registering |
| 1148 base::string16 protocol = cmd_line.GetSwitchValueNative( | 924 // with Windows as capable of handling the supplied protocol. |
| 1149 installer::switches::kRegisterURLProtocol); | 925 if (ShellUtil::RegisterChromeForProtocol(chrome_install.distribution(), |
| 1150 // ShellUtil::RegisterChromeForProtocol performs all registration | 926 chrome_exe, suffix, protocol, |
| 1151 // done by ShellUtil::RegisterChromeBrowser, as well as registering | 927 false)) |
| 1152 // with Windows as capable of handling the supplied protocol. | 928 status = installer::IN_USE_UPDATED; |
| 1153 if (ShellUtil::RegisterChromeForProtocol( | |
| 1154 chrome_install->distribution(), chrome_exe, suffix, protocol, | |
| 1155 false)) | |
| 1156 status = installer::IN_USE_UPDATED; | |
| 1157 } else { | |
| 1158 if (ShellUtil::RegisterChromeBrowser(chrome_install->distribution(), | |
| 1159 chrome_exe, suffix, false)) | |
| 1160 status = installer::IN_USE_UPDATED; | |
| 1161 } | |
| 1162 } else { | 929 } else { |
| 1163 LOG(DFATAL) << "Can't register browser - Chrome distribution not found"; | 930 if (ShellUtil::RegisterChromeBrowser(chrome_install.distribution(), |
| 931 chrome_exe, suffix, false)) |
| 932 status = installer::IN_USE_UPDATED; |
| 1164 } | 933 } |
| 1165 *exit_code = InstallUtil::GetInstallReturnCode(status); | 934 *exit_code = InstallUtil::GetInstallReturnCode(status); |
| 1166 } else if (cmd_line.HasSwitch(installer::switches::kDeleteOldVersions) || | 935 } else if (cmd_line.HasSwitch(installer::switches::kDeleteOldVersions) || |
| 1167 cmd_line.HasSwitch(installer::switches::kRenameChromeExe)) { | 936 cmd_line.HasSwitch(installer::switches::kRenameChromeExe)) { |
| 1168 std::unique_ptr<installer::SetupSingleton> setup_singleton( | 937 std::unique_ptr<installer::SetupSingleton> setup_singleton( |
| 1169 installer::SetupSingleton::Acquire( | 938 installer::SetupSingleton::Acquire( |
| 1170 cmd_line, MasterPreferences::ForCurrentProcess(), original_state, | 939 cmd_line, MasterPreferences::ForCurrentProcess(), original_state, |
| 1171 installer_state)); | 940 installer_state)); |
| 1172 if (!setup_singleton) { | 941 if (!setup_singleton) { |
| 1173 *exit_code = installer::SETUP_SINGLETON_ACQUISITION_FAILED; | 942 *exit_code = installer::SETUP_SINGLETON_ACQUISITION_FAILED; |
| 1174 } else if (cmd_line.HasSwitch(installer::switches::kDeleteOldVersions)) { | 943 } else if (cmd_line.HasSwitch(installer::switches::kDeleteOldVersions)) { |
| 1175 // In multi-install mode, determine what products are installed to | |
| 1176 // populate the target_path() used below. | |
| 1177 AddExistingMultiInstalls(*original_state, installer_state); | |
| 1178 | |
| 1179 *exit_code = RepeatDeleteOldVersions(installer_state->target_path(), | 944 *exit_code = RepeatDeleteOldVersions(installer_state->target_path(), |
| 1180 *setup_singleton); | 945 *setup_singleton); |
| 1181 } else { | 946 } else { |
| 1182 DCHECK(cmd_line.HasSwitch(installer::switches::kRenameChromeExe)); | 947 DCHECK(cmd_line.HasSwitch(installer::switches::kRenameChromeExe)); |
| 1183 *exit_code = | 948 *exit_code = |
| 1184 RenameChromeExecutables(setup_exe, *original_state, installer_state); | 949 RenameChromeExecutables(setup_exe, *original_state, installer_state); |
| 1185 } | 950 } |
| 1186 } else if (cmd_line.HasSwitch( | 951 } else if (cmd_line.HasSwitch( |
| 1187 installer::switches::kRemoveChromeRegistration)) { | 952 installer::switches::kRemoveChromeRegistration)) { |
| 1188 // This is almost reverse of --register-chrome-browser option above. | 953 // This is almost reverse of --register-chrome-browser option above. |
| 1189 // Here we delete Chrome browser registration. This option should only | 954 // Here we delete Chrome browser registration. This option should only |
| 1190 // be used when setup.exe is launched with admin rights. We do not | 955 // be used when setup.exe is launched with admin rights. We do not |
| 1191 // make any user specific changes in this option. | 956 // make any user specific changes in this option. |
| 1192 base::string16 suffix; | 957 base::string16 suffix; |
| 1193 if (cmd_line.HasSwitch( | 958 if (cmd_line.HasSwitch( |
| 1194 installer::switches::kRegisterChromeBrowserSuffix)) { | 959 installer::switches::kRegisterChromeBrowserSuffix)) { |
| 1195 suffix = cmd_line.GetSwitchValueNative( | 960 suffix = cmd_line.GetSwitchValueNative( |
| 1196 installer::switches::kRegisterChromeBrowserSuffix); | 961 installer::switches::kRegisterChromeBrowserSuffix); |
| 1197 } | 962 } |
| 1198 installer::InstallStatus tmp = installer::UNKNOWN_STATUS; | 963 installer::InstallStatus tmp = installer::UNKNOWN_STATUS; |
| 1199 const Product* chrome_install = | 964 const Product& chrome_install = installer_state->product(); |
| 1200 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); | 965 installer::DeleteChromeRegistrationKeys(*installer_state, |
| 1201 DCHECK(chrome_install); | 966 chrome_install.distribution(), |
| 1202 if (chrome_install) { | 967 HKEY_LOCAL_MACHINE, suffix, &tmp); |
| 1203 installer::DeleteChromeRegistrationKeys(*installer_state, | |
| 1204 chrome_install->distribution(), HKEY_LOCAL_MACHINE, suffix, &tmp); | |
| 1205 } | |
| 1206 *exit_code = tmp; | 968 *exit_code = tmp; |
| 1207 } else if (cmd_line.HasSwitch(installer::switches::kOnOsUpgrade)) { | 969 } else if (cmd_line.HasSwitch(installer::switches::kOnOsUpgrade)) { |
| 1208 const Product* chrome_install = | 970 const Product& chrome_install = installer_state->product(); |
| 1209 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); | |
| 1210 installer::InstallStatus status = installer::INVALID_STATE_FOR_OPTION; | 971 installer::InstallStatus status = installer::INVALID_STATE_FOR_OPTION; |
| 1211 if (chrome_install) { | 972 std::unique_ptr<FileVersionInfo> version_info( |
| 1212 std::unique_ptr<FileVersionInfo> version_info( | 973 FileVersionInfo::CreateFileVersionInfo(setup_exe)); |
| 1213 FileVersionInfo::CreateFileVersionInfo(setup_exe)); | 974 const base::Version installed_version( |
| 1214 const base::Version installed_version( | 975 base::UTF16ToUTF8(version_info->product_version())); |
| 1215 base::UTF16ToUTF8(version_info->product_version())); | 976 if (installed_version.IsValid()) { |
| 1216 if (installed_version.IsValid()) { | 977 installer::HandleOsUpgradeForBrowser(*installer_state, chrome_install, |
| 1217 installer::HandleOsUpgradeForBrowser(*installer_state, *chrome_install, | 978 installed_version); |
| 1218 installed_version); | 979 status = installer::INSTALL_REPAIRED; |
| 1219 status = installer::INSTALL_REPAIRED; | |
| 1220 } else { | |
| 1221 LOG(DFATAL) << "Failed to extract product version from " | |
| 1222 << setup_exe.value(); | |
| 1223 } | |
| 1224 } else { | 980 } else { |
| 1225 LOG(DFATAL) << "Chrome product not found."; | 981 LOG(DFATAL) << "Failed to extract product version from " |
| 982 << setup_exe.value(); |
| 1226 } | 983 } |
| 1227 *exit_code = InstallUtil::GetInstallReturnCode(status); | 984 *exit_code = InstallUtil::GetInstallReturnCode(status); |
| 1228 } else if (cmd_line.HasSwitch(installer::switches::kInactiveUserToast)) { | 985 } else if (cmd_line.HasSwitch(installer::switches::kInactiveUserToast)) { |
| 1229 // Launch the inactive user toast experiment. | 986 // Launch the inactive user toast experiment. |
| 1230 int flavor = -1; | 987 int flavor = -1; |
| 1231 base::StringToInt(cmd_line.GetSwitchValueNative( | 988 base::StringToInt(cmd_line.GetSwitchValueNative( |
| 1232 installer::switches::kInactiveUserToast), &flavor); | 989 installer::switches::kInactiveUserToast), &flavor); |
| 1233 std::string experiment_group = | 990 std::string experiment_group = |
| 1234 cmd_line.GetSwitchValueASCII(installer::switches::kExperimentGroup); | 991 cmd_line.GetSwitchValueASCII(installer::switches::kExperimentGroup); |
| 1235 DCHECK_NE(-1, flavor); | 992 DCHECK_NE(-1, flavor); |
| 1236 if (flavor == -1) { | 993 if (flavor == -1) { |
| 1237 *exit_code = installer::UNKNOWN_STATUS; | 994 *exit_code = installer::UNKNOWN_STATUS; |
| 1238 } else { | 995 } else { |
| 1239 // This code is called (via setup.exe relaunch) only if a product is known | 996 // This code is called (via setup.exe relaunch) only if a product is known |
| 1240 // to run user experiments, so no check is required. | 997 // to run user experiments, so no check is required. |
| 1241 const Products& products = installer_state->products(); | 998 installer::InactiveUserToastExperiment( |
| 1242 for (Products::const_iterator it = products.begin(); it < products.end(); | 999 flavor, base::ASCIIToUTF16(experiment_group), |
| 1243 ++it) { | 1000 installer_state->product(), installer_state->target_path()); |
| 1244 const Product& product = **it; | |
| 1245 installer::InactiveUserToastExperiment( | |
| 1246 flavor, base::ASCIIToUTF16(experiment_group), product, | |
| 1247 installer_state->target_path()); | |
| 1248 } | |
| 1249 } | 1001 } |
| 1250 } else if (cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { | 1002 } else if (cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { |
| 1251 const Products& products = installer_state->products(); | 1003 const Product& product = installer_state->product(); |
| 1252 for (Products::const_iterator it = products.begin(); it < products.end(); | 1004 BrowserDistribution* browser_dist = product.distribution(); |
| 1253 ++it) { | 1005 // We started as system-level and have been re-launched as user level |
| 1254 const Product& product = **it; | 1006 // to continue with the toast experiment. |
| 1255 BrowserDistribution* browser_dist = product.distribution(); | 1007 base::Version installed_version; |
| 1256 // We started as system-level and have been re-launched as user level | 1008 InstallUtil::GetChromeVersion(browser_dist, true, &installed_version); |
| 1257 // to continue with the toast experiment. | 1009 if (!installed_version.IsValid()) { |
| 1258 base::Version installed_version; | 1010 LOG(ERROR) << "No installation of " << browser_dist->GetDisplayName() |
| 1259 InstallUtil::GetChromeVersion(browser_dist, true, &installed_version); | 1011 << " found for system-level toast."; |
| 1260 if (!installed_version.IsValid()) { | 1012 } else { |
| 1261 LOG(ERROR) << "No installation of " | 1013 product.LaunchUserExperiment(setup_exe, installer::REENTRY_SYS_UPDATE, |
| 1262 << browser_dist->GetDisplayName() | 1014 true); |
| 1263 << " found for system-level toast."; | |
| 1264 } else { | |
| 1265 product.LaunchUserExperiment( | |
| 1266 setup_exe, installer::REENTRY_SYS_UPDATE, true); | |
| 1267 } | |
| 1268 } | 1015 } |
| 1269 } else if (cmd_line.HasSwitch(installer::switches::kPatch)) { | 1016 } else if (cmd_line.HasSwitch(installer::switches::kPatch)) { |
| 1270 const std::string patch_type_str( | 1017 const std::string patch_type_str( |
| 1271 cmd_line.GetSwitchValueASCII(installer::switches::kPatch)); | 1018 cmd_line.GetSwitchValueASCII(installer::switches::kPatch)); |
| 1272 const base::FilePath input_file( | 1019 const base::FilePath input_file( |
| 1273 cmd_line.GetSwitchValuePath(installer::switches::kInputFile)); | 1020 cmd_line.GetSwitchValuePath(installer::switches::kInputFile)); |
| 1274 const base::FilePath patch_file( | 1021 const base::FilePath patch_file( |
| 1275 cmd_line.GetSwitchValuePath(installer::switches::kPatchFile)); | 1022 cmd_line.GetSwitchValuePath(installer::switches::kPatchFile)); |
| 1276 const base::FilePath output_file( | 1023 const base::FilePath output_file( |
| 1277 cmd_line.GetSwitchValuePath(installer::switches::kOutputFile)); | 1024 cmd_line.GetSwitchValuePath(installer::switches::kOutputFile)); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1301 cmd_line.GetSwitchValueNative( | 1048 cmd_line.GetSwitchValueNative( |
| 1302 installer::switches::kSetDisplayVersionValue)); | 1049 installer::switches::kSetDisplayVersionValue)); |
| 1303 *exit_code = OverwriteDisplayVersions(registry_product, registry_value); | 1050 *exit_code = OverwriteDisplayVersions(registry_product, registry_value); |
| 1304 } else { | 1051 } else { |
| 1305 handled = false; | 1052 handled = false; |
| 1306 } | 1053 } |
| 1307 | 1054 |
| 1308 return handled; | 1055 return handled; |
| 1309 } | 1056 } |
| 1310 | 1057 |
| 1311 // Uninstalls multi-install Chrome Frame if the current operation is a | |
| 1312 // multi-install install or update. The operation is performed directly rather | |
| 1313 // than delegated to the existing install since there is no facility in older | |
| 1314 // versions of setup.exe to uninstall GCF without touching the binaries. The | |
| 1315 // binaries will be uninstalled during later processing if they are not in-use | |
| 1316 // (see UninstallBinariesIfUnused). |original_state| and |installer_state| are | |
| 1317 // updated to reflect the state of the world following the operation. | |
| 1318 void UninstallMultiChromeFrameIfPresent(const base::CommandLine& cmd_line, | |
| 1319 const MasterPreferences& prefs, | |
| 1320 InstallationState* original_state, | |
| 1321 InstallerState* installer_state) { | |
| 1322 // Early exit if not installing or updating. | |
| 1323 if (installer_state->operation() == InstallerState::UNINSTALL) | |
| 1324 return; | |
| 1325 | |
| 1326 // Early exit if Chrome Frame is not present as multi-install. | |
| 1327 const ProductState* chrome_frame_state = | |
| 1328 original_state->GetProductState(installer_state->system_install(), | |
| 1329 BrowserDistribution::CHROME_FRAME); | |
| 1330 if (!chrome_frame_state || !chrome_frame_state->is_multi_install()) | |
| 1331 return; | |
| 1332 | |
| 1333 LOG(INFO) << "Uninstalling multi-install Chrome Frame."; | |
| 1334 installer_state->SetStage(installer::UNINSTALLING_CHROME_FRAME); | |
| 1335 | |
| 1336 // Uninstall Chrome Frame without touching the multi-install binaries. | |
| 1337 // Simulate the uninstall as coming from the installed version. | |
| 1338 const base::CommandLine& uninstall_cmd( | |
| 1339 chrome_frame_state->uninstall_command()); | |
| 1340 MasterPreferences uninstall_prefs(uninstall_cmd); | |
| 1341 InstallerState uninstall_state; | |
| 1342 uninstall_state.Initialize(uninstall_cmd, uninstall_prefs, *original_state); | |
| 1343 // Post M32, uninstall_prefs and uninstall_state won't have Chrome Frame in | |
| 1344 // them since they've lost the power to do Chrome Frame installs. | |
| 1345 const Product* chrome_frame_product = uninstall_state.AddProductFromState( | |
| 1346 BrowserDistribution::CHROME_FRAME, *chrome_frame_state); | |
| 1347 if (chrome_frame_product) { | |
| 1348 // No shared state should be left behind. | |
| 1349 const bool remove_all = true; | |
| 1350 // Don't accept no for an answer. | |
| 1351 const bool force_uninstall = true; | |
| 1352 installer::InstallStatus uninstall_status = | |
| 1353 installer::UninstallProduct(*original_state, uninstall_state, | |
| 1354 uninstall_cmd.GetProgram(), | |
| 1355 *chrome_frame_product, remove_all, | |
| 1356 force_uninstall, cmd_line); | |
| 1357 | |
| 1358 VLOG(1) << "Uninstallation of Chrome Frame returned status " | |
| 1359 << uninstall_status; | |
| 1360 } else { | |
| 1361 LOG(ERROR) << "Chrome Frame not found for uninstall."; | |
| 1362 } | |
| 1363 | |
| 1364 // Refresh state for the continuation of the original install/update. | |
| 1365 original_state->Initialize(); | |
| 1366 installer_state->Initialize(cmd_line, prefs, *original_state); | |
| 1367 } | |
| 1368 | |
| 1369 } // namespace | 1058 } // namespace |
| 1370 | 1059 |
| 1371 namespace installer { | 1060 namespace installer { |
| 1372 | 1061 |
| 1373 InstallStatus InstallProductsHelper(const InstallationState& original_state, | 1062 InstallStatus InstallProductsHelper(const InstallationState& original_state, |
| 1374 const base::FilePath& setup_exe, | 1063 const base::FilePath& setup_exe, |
| 1375 const base::CommandLine& cmd_line, | 1064 const base::CommandLine& cmd_line, |
| 1376 const MasterPreferences& prefs, | 1065 const MasterPreferences& prefs, |
| 1377 const InstallerState& installer_state, | 1066 const InstallerState& installer_state, |
| 1378 base::FilePath* installer_directory, | 1067 base::FilePath* installer_directory, |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1479 if (!installer_version.get()) { | 1168 if (!installer_version.get()) { |
| 1480 LOG(ERROR) << "Did not find any valid version in installer."; | 1169 LOG(ERROR) << "Did not find any valid version in installer."; |
| 1481 install_status = INVALID_ARCHIVE; | 1170 install_status = INVALID_ARCHIVE; |
| 1482 installer_state.WriteInstallerResult(install_status, | 1171 installer_state.WriteInstallerResult(install_status, |
| 1483 IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); | 1172 IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); |
| 1484 } else { | 1173 } else { |
| 1485 VLOG(1) << "version to install: " << installer_version->GetString(); | 1174 VLOG(1) << "version to install: " << installer_version->GetString(); |
| 1486 bool proceed_with_installation = true; | 1175 bool proceed_with_installation = true; |
| 1487 | 1176 |
| 1488 if (!IsDowngradeAllowed(prefs)) { | 1177 if (!IsDowngradeAllowed(prefs)) { |
| 1489 uint32_t higher_products = 0; | 1178 const Product& product = installer_state.product(); |
| 1490 static_assert( | 1179 const ProductState* product_state = original_state.GetProductState( |
| 1491 sizeof(higher_products) * 8 > BrowserDistribution::NUM_TYPES, | 1180 system_install, product.distribution()->GetType()); |
| 1492 "too many distribution types"); | 1181 if (product_state != NULL && |
| 1493 const Products& products = installer_state.products(); | 1182 (product_state->version().CompareTo(*installer_version) > 0)) { |
| 1494 for (Products::const_iterator it = products.begin(); it < products.end(); | 1183 LOG(ERROR) << "Higher version of " |
| 1495 ++it) { | 1184 << product.distribution()->GetDisplayName() |
| 1496 const Product& product = **it; | 1185 << " is already installed."; |
| 1497 const ProductState* product_state = original_state.GetProductState( | |
| 1498 system_install, product.distribution()->GetType()); | |
| 1499 if (product_state != NULL && | |
| 1500 (product_state->version().CompareTo(*installer_version) > 0)) { | |
| 1501 LOG(ERROR) << "Higher version of " | |
| 1502 << product.distribution()->GetDisplayName() | |
| 1503 << " is already installed."; | |
| 1504 higher_products |= (1 << product.distribution()->GetType()); | |
| 1505 } | |
| 1506 } | |
| 1507 | |
| 1508 if (higher_products != 0) { | |
| 1509 static_assert(BrowserDistribution::NUM_TYPES == 3, | |
| 1510 "add support for new products here"); | |
| 1511 int message_id = IDS_INSTALL_HIGHER_VERSION_BASE; | 1186 int message_id = IDS_INSTALL_HIGHER_VERSION_BASE; |
| 1512 proceed_with_installation = false; | 1187 proceed_with_installation = false; |
| 1513 install_status = HIGHER_VERSION_EXISTS; | 1188 install_status = HIGHER_VERSION_EXISTS; |
| 1514 installer_state.WriteInstallerResult(install_status, message_id, NULL); | 1189 installer_state.WriteInstallerResult(install_status, message_id, NULL); |
| 1515 } | 1190 } |
| 1516 } | 1191 } |
| 1517 | 1192 |
| 1518 if (proceed_with_installation) { | 1193 if (proceed_with_installation) { |
| 1519 base::FilePath prefs_source_path(cmd_line.GetSwitchValueNative( | 1194 base::FilePath prefs_source_path(cmd_line.GetSwitchValueNative( |
| 1520 switches::kInstallerData)); | 1195 switches::kInstallerData)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1536 install_status = OS_ERROR; | 1211 install_status = OS_ERROR; |
| 1537 } else { | 1212 } else { |
| 1538 chrome_exe = installer_state.target_path().Append(kChromeExe); | 1213 chrome_exe = installer_state.target_path().Append(kChromeExe); |
| 1539 quoted_chrome_exe = L"\"" + chrome_exe.value() + L"\""; | 1214 quoted_chrome_exe = L"\"" + chrome_exe.value() + L"\""; |
| 1540 install_msg_base = 0; | 1215 install_msg_base = 0; |
| 1541 } | 1216 } |
| 1542 } | 1217 } |
| 1543 | 1218 |
| 1544 installer_state.SetStage(FINISHING); | 1219 installer_state.SetStage(FINISHING); |
| 1545 | 1220 |
| 1546 // Only do Chrome-specific stuff (like launching the browser) if | 1221 const Product& chrome_install = installer_state.product(); |
| 1547 // Chrome was specifically requested (rather than being upgraded as | |
| 1548 // part of a multi-install). | |
| 1549 const Product* chrome_install = prefs.install_chrome() ? | |
| 1550 installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER) : | |
| 1551 NULL; | |
| 1552 | 1222 |
| 1553 bool do_not_register_for_update_launch = false; | 1223 bool do_not_register_for_update_launch = false; |
| 1554 if (chrome_install) { | 1224 prefs.GetBool(master_preferences::kDoNotRegisterForUpdateLaunch, |
| 1555 prefs.GetBool(master_preferences::kDoNotRegisterForUpdateLaunch, | 1225 &do_not_register_for_update_launch); |
| 1556 &do_not_register_for_update_launch); | |
| 1557 } else { | |
| 1558 do_not_register_for_update_launch = true; // Never register. | |
| 1559 } | |
| 1560 | 1226 |
| 1561 bool write_chrome_launch_string = | 1227 bool write_chrome_launch_string = |
| 1562 (!do_not_register_for_update_launch && | 1228 (!do_not_register_for_update_launch && |
| 1563 install_status != IN_USE_UPDATED); | 1229 install_status != IN_USE_UPDATED); |
| 1564 | 1230 |
| 1565 installer_state.WriteInstallerResult(install_status, install_msg_base, | 1231 installer_state.WriteInstallerResult(install_status, install_msg_base, |
| 1566 write_chrome_launch_string ? "ed_chrome_exe : NULL); | 1232 write_chrome_launch_string ? "ed_chrome_exe : NULL); |
| 1567 | 1233 |
| 1568 if (install_status == FIRST_INSTALL_SUCCESS) { | 1234 if (install_status == FIRST_INSTALL_SUCCESS) { |
| 1569 VLOG(1) << "First install successful."; | 1235 VLOG(1) << "First install successful."; |
| 1570 if (chrome_install) { | 1236 // We never want to launch Chrome in system level install mode. |
| 1571 // We never want to launch Chrome in system level install mode. | 1237 bool do_not_launch_chrome = false; |
| 1572 bool do_not_launch_chrome = false; | 1238 prefs.GetBool(master_preferences::kDoNotLaunchChrome, |
| 1573 prefs.GetBool(master_preferences::kDoNotLaunchChrome, | 1239 &do_not_launch_chrome); |
| 1574 &do_not_launch_chrome); | 1240 if (!system_install && !do_not_launch_chrome) |
| 1575 if (!system_install && !do_not_launch_chrome) | 1241 chrome_install.LaunchChrome(installer_state.target_path()); |
| 1576 chrome_install->LaunchChrome(installer_state.target_path()); | |
| 1577 } | |
| 1578 } else if ((install_status == NEW_VERSION_UPDATED) || | 1242 } else if ((install_status == NEW_VERSION_UPDATED) || |
| 1579 (install_status == IN_USE_UPDATED)) { | 1243 (install_status == IN_USE_UPDATED)) { |
| 1580 const Product* chrome = installer_state.FindProduct( | 1244 const Product& chrome = installer_state.product(); |
| 1581 BrowserDistribution::CHROME_BROWSER); | 1245 DCHECK_NE(chrome_exe.value(), base::string16()); |
| 1582 if (chrome != NULL) { | 1246 RemoveChromeLegacyRegistryKeys(chrome.distribution(), chrome_exe); |
| 1583 DCHECK_NE(chrome_exe.value(), base::string16()); | |
| 1584 RemoveChromeLegacyRegistryKeys(chrome->distribution(), chrome_exe); | |
| 1585 } | |
| 1586 } | 1247 } |
| 1587 } | 1248 } |
| 1588 } | 1249 } |
| 1589 | 1250 |
| 1590 // There might be an experiment (for upgrade usually) that needs to happen. | 1251 // There might be an experiment (for upgrade usually) that needs to happen. |
| 1591 // An experiment's outcome can include chrome's uninstallation. If that is | 1252 // An experiment's outcome can include chrome's uninstallation. If that is |
| 1592 // the case we would not do that directly at this point but in another | 1253 // the case we would not do that directly at this point but in another |
| 1593 // instance of setup.exe | 1254 // instance of setup.exe |
| 1594 // | 1255 // |
| 1595 // There is another way to reach this same function if this is a system | 1256 // There is another way to reach this same function if this is a system |
| 1596 // level install. See HandleNonInstallCmdLineOptions(). | 1257 // level install. See HandleNonInstallCmdLineOptions(). |
| 1597 { | 1258 { |
| 1598 // If installation failed, use the path to the currently running setup. | 1259 // If installation failed, use the path to the currently running setup. |
| 1599 // If installation succeeded, use the path to setup in the installer dir. | 1260 // If installation succeeded, use the path to setup in the installer dir. |
| 1600 base::FilePath setup_path(setup_exe); | 1261 base::FilePath setup_path(setup_exe); |
| 1601 if (InstallUtil::GetInstallReturnCode(install_status) == 0) { | 1262 if (InstallUtil::GetInstallReturnCode(install_status) == 0) { |
| 1602 setup_path = installer_state.GetInstallerDirectory(*installer_version) | 1263 setup_path = installer_state.GetInstallerDirectory(*installer_version) |
| 1603 .Append(setup_path.BaseName()); | 1264 .Append(setup_path.BaseName()); |
| 1604 } | 1265 } |
| 1605 const Products& products = installer_state.products(); | 1266 installer_state.product().LaunchUserExperiment(setup_path, install_status, |
| 1606 for (Products::const_iterator it = products.begin(); it < products.end(); | 1267 system_install); |
| 1607 ++it) { | |
| 1608 const Product& product = **it; | |
| 1609 product.LaunchUserExperiment(setup_path, install_status, system_install); | |
| 1610 } | |
| 1611 } | 1268 } |
| 1612 | 1269 |
| 1613 // If the installation completed successfully... | 1270 // If the installation completed successfully... |
| 1614 if (InstallUtil::GetInstallReturnCode(install_status) == 0) { | 1271 if (InstallUtil::GetInstallReturnCode(install_status) == 0) { |
| 1615 // Update the DisplayVersion created by an MSI-based install. | 1272 // Update the DisplayVersion created by an MSI-based install. |
| 1616 base::FilePath master_preferences_file( | 1273 base::FilePath master_preferences_file( |
| 1617 installer_state.target_path().AppendASCII( | 1274 installer_state.target_path().AppendASCII( |
| 1618 installer::kDefaultMasterPrefs)); | 1275 installer::kDefaultMasterPrefs)); |
| 1619 std::string install_id; | 1276 std::string install_id; |
| 1620 if (prefs.GetString(installer::master_preferences::kMsiProductId, | 1277 if (prefs.GetString(installer::master_preferences::kMsiProductId, |
| 1621 &install_id)) { | 1278 &install_id)) { |
| 1622 // A currently active MSI install will have specified the master- | 1279 // A currently active MSI install will have specified the master- |
| 1623 // preferences file on the command-line that includes the product-id. | 1280 // preferences file on the command-line that includes the product-id. |
| 1624 // We must delay the setting of the DisplayVersion until after the | 1281 // We must delay the setting of the DisplayVersion until after the |
| 1625 // grandparent "msiexec" process has exited. | 1282 // grandparent "msiexec" process has exited. |
| 1626 base::FilePath new_setup = | 1283 base::FilePath new_setup = |
| 1627 installer_state.GetInstallerDirectory(*installer_version) | 1284 installer_state.GetInstallerDirectory(*installer_version) |
| 1628 .Append(kSetupExe); | 1285 .Append(kSetupExe); |
| 1629 DelayedOverwriteDisplayVersions( | 1286 DelayedOverwriteDisplayVersions( |
| 1630 new_setup, install_id, *installer_version); | 1287 new_setup, install_id, *installer_version); |
| 1631 } else { | 1288 } else { |
| 1632 // Only when called by the MSI installer do we need to delay setting | 1289 // Only when called by the MSI installer do we need to delay setting |
| 1633 // the DisplayVersion. In other runs, such as those done by the auto- | 1290 // the DisplayVersion. In other runs, such as those done by the auto- |
| 1634 // update action, we set the value immediately. | 1291 // update action, we set the value immediately. |
| 1635 const Product* chrome = installer_state.FindProduct( | 1292 const Product& chrome = installer_state.product(); |
| 1636 BrowserDistribution::CHROME_BROWSER); | 1293 // Get the app's MSI Product-ID from an entry in ClientState. |
| 1637 if (chrome != NULL) { | 1294 base::string16 app_guid = FindMsiProductId(installer_state, chrome); |
| 1638 // Get the app's MSI Product-ID from an entry in ClientState. | 1295 if (!app_guid.empty()) { |
| 1639 base::string16 app_guid = FindMsiProductId(installer_state, chrome); | 1296 OverwriteDisplayVersions( |
| 1640 if (!app_guid.empty()) { | 1297 app_guid, base::UTF8ToUTF16(installer_version->GetString())); |
| 1641 OverwriteDisplayVersions(app_guid, | |
| 1642 base::UTF8ToUTF16( | |
| 1643 installer_version->GetString())); | |
| 1644 } | |
| 1645 } | 1298 } |
| 1646 } | 1299 } |
| 1647 // Return the path to the directory containing the newly installed | 1300 // Return the path to the directory containing the newly installed |
| 1648 // setup.exe and uncompressed archive if the caller requested it. | 1301 // setup.exe and uncompressed archive if the caller requested it. |
| 1649 if (installer_directory) { | 1302 if (installer_directory) { |
| 1650 *installer_directory = | 1303 *installer_directory = |
| 1651 installer_state.GetInstallerDirectory(*installer_version); | 1304 installer_state.GetInstallerDirectory(*installer_version); |
| 1652 } | 1305 } |
| 1653 } | 1306 } |
| 1654 | 1307 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1687 | 1340 |
| 1688 // install_util uses chrome paths. | 1341 // install_util uses chrome paths. |
| 1689 chrome::RegisterPathProvider(); | 1342 chrome::RegisterPathProvider(); |
| 1690 | 1343 |
| 1691 const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess(); | 1344 const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess(); |
| 1692 installer::InitInstallerLogging(prefs); | 1345 installer::InitInstallerLogging(prefs); |
| 1693 | 1346 |
| 1694 const base::CommandLine& cmd_line = *base::CommandLine::ForCurrentProcess(); | 1347 const base::CommandLine& cmd_line = *base::CommandLine::ForCurrentProcess(); |
| 1695 VLOG(1) << "Command Line: " << cmd_line.GetCommandLineString(); | 1348 VLOG(1) << "Command Line: " << cmd_line.GetCommandLineString(); |
| 1696 | 1349 |
| 1697 VLOG(1) << "multi install is " << prefs.is_multi_install(); | |
| 1698 bool system_install = false; | 1350 bool system_install = false; |
| 1699 prefs.GetBool(installer::master_preferences::kSystemLevel, &system_install); | 1351 prefs.GetBool(installer::master_preferences::kSystemLevel, &system_install); |
| 1700 VLOG(1) << "system install is " << system_install; | 1352 VLOG(1) << "system install is " << system_install; |
| 1701 | 1353 |
| 1702 InstallationState original_state; | 1354 InstallationState original_state; |
| 1703 original_state.Initialize(); | 1355 original_state.Initialize(); |
| 1704 | 1356 |
| 1705 InstallerState installer_state; | 1357 InstallerState installer_state; |
| 1706 installer_state.Initialize(cmd_line, prefs, original_state); | 1358 installer_state.Initialize(cmd_line, prefs, original_state); |
| 1707 | 1359 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1737 base::win::ScopedCOMInitializer com_initializer; | 1389 base::win::ScopedCOMInitializer com_initializer; |
| 1738 if (!com_initializer.succeeded()) { | 1390 if (!com_initializer.succeeded()) { |
| 1739 installer_state.WriteInstallerResult( | 1391 installer_state.WriteInstallerResult( |
| 1740 installer::OS_ERROR, IDS_INSTALL_OS_ERROR_BASE, NULL); | 1392 installer::OS_ERROR, IDS_INSTALL_OS_ERROR_BASE, NULL); |
| 1741 return installer::OS_ERROR; | 1393 return installer::OS_ERROR; |
| 1742 } | 1394 } |
| 1743 | 1395 |
| 1744 // Some command line options don't work with SxS install/uninstall | 1396 // Some command line options don't work with SxS install/uninstall |
| 1745 if (InstallUtil::IsChromeSxSProcess()) { | 1397 if (InstallUtil::IsChromeSxSProcess()) { |
| 1746 if (system_install || | 1398 if (system_install || |
| 1747 prefs.is_multi_install() || | |
| 1748 cmd_line.HasSwitch(installer::switches::kSelfDestruct) || | 1399 cmd_line.HasSwitch(installer::switches::kSelfDestruct) || |
| 1749 cmd_line.HasSwitch(installer::switches::kMakeChromeDefault) || | 1400 cmd_line.HasSwitch(installer::switches::kMakeChromeDefault) || |
| 1750 cmd_line.HasSwitch(installer::switches::kRegisterChromeBrowser) || | 1401 cmd_line.HasSwitch(installer::switches::kRegisterChromeBrowser) || |
| 1751 cmd_line.HasSwitch(installer::switches::kRemoveChromeRegistration) || | 1402 cmd_line.HasSwitch(installer::switches::kRemoveChromeRegistration) || |
| 1752 cmd_line.HasSwitch(installer::switches::kInactiveUserToast) || | 1403 cmd_line.HasSwitch(installer::switches::kInactiveUserToast) || |
| 1753 cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { | 1404 cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { |
| 1754 return installer::SXS_OPTION_NOT_SUPPORTED; | 1405 return installer::SXS_OPTION_NOT_SUPPORTED; |
| 1755 } | 1406 } |
| 1756 } | 1407 } |
| 1757 | 1408 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1804 std::unique_ptr<installer::SetupSingleton> setup_singleton( | 1455 std::unique_ptr<installer::SetupSingleton> setup_singleton( |
| 1805 installer::SetupSingleton::Acquire(cmd_line, prefs, &original_state, | 1456 installer::SetupSingleton::Acquire(cmd_line, prefs, &original_state, |
| 1806 &installer_state)); | 1457 &installer_state)); |
| 1807 if (!setup_singleton) { | 1458 if (!setup_singleton) { |
| 1808 installer_state.WriteInstallerResult( | 1459 installer_state.WriteInstallerResult( |
| 1809 installer::SETUP_SINGLETON_ACQUISITION_FAILED, | 1460 installer::SETUP_SINGLETON_ACQUISITION_FAILED, |
| 1810 IDS_INSTALL_SINGLETON_ACQUISITION_FAILED_BASE, nullptr); | 1461 IDS_INSTALL_SINGLETON_ACQUISITION_FAILED_BASE, nullptr); |
| 1811 return installer::SETUP_SINGLETON_ACQUISITION_FAILED; | 1462 return installer::SETUP_SINGLETON_ACQUISITION_FAILED; |
| 1812 } | 1463 } |
| 1813 | 1464 |
| 1814 UninstallMultiChromeFrameIfPresent(cmd_line, prefs, | |
| 1815 &original_state, &installer_state); | |
| 1816 | |
| 1817 base::FilePath installer_directory; | 1465 base::FilePath installer_directory; |
| 1818 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; | 1466 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; |
| 1819 // If --uninstall option is given, uninstall the identified product(s) | 1467 // If --uninstall option is given, uninstall the identified product(s) |
| 1820 if (is_uninstall) { | 1468 if (is_uninstall) { |
| 1821 install_status = | 1469 install_status = |
| 1822 UninstallProducts(original_state, installer_state, setup_exe, cmd_line); | 1470 UninstallProducts(original_state, installer_state, setup_exe, cmd_line); |
| 1823 } else { | 1471 } else { |
| 1824 // If --uninstall option is not specified, we assume it is install case. | 1472 // If --uninstall option is not specified, we assume it is install case. |
| 1825 install_status = | 1473 install_status = |
| 1826 InstallProducts(original_state, setup_exe, cmd_line, prefs, | 1474 InstallProducts(original_state, setup_exe, cmd_line, prefs, |
| 1827 &installer_state, &installer_directory); | 1475 &installer_state, &installer_directory); |
| 1476 DoLegacyCleanups(installer_state, install_status); |
| 1828 } | 1477 } |
| 1829 | 1478 |
| 1830 UMA_HISTOGRAM_ENUMERATION("Setup.Install.Result", install_status, | 1479 UMA_HISTOGRAM_ENUMERATION("Setup.Install.Result", install_status, |
| 1831 installer::MAX_INSTALL_STATUS); | 1480 installer::MAX_INSTALL_STATUS); |
| 1832 | 1481 |
| 1833 // Dump peak memory usage. | 1482 // Dump peak memory usage. |
| 1834 std::unique_ptr<base::ProcessMetrics> process_metrics( | 1483 std::unique_ptr<base::ProcessMetrics> process_metrics( |
| 1835 base::ProcessMetrics::CreateProcessMetrics( | 1484 base::ProcessMetrics::CreateProcessMetrics( |
| 1836 base::GetCurrentProcessHandle())); | 1485 base::GetCurrentProcessHandle())); |
| 1837 UMA_HISTOGRAM_MEMORY_KB("Setup.Install.PeakPagefileUsage", | 1486 UMA_HISTOGRAM_MEMORY_KB("Setup.Install.PeakPagefileUsage", |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1849 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT | 1498 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT |
| 1850 // to pass through, since this is only returned on uninstall which is | 1499 // to pass through, since this is only returned on uninstall which is |
| 1851 // never invoked directly by Google Update. | 1500 // never invoked directly by Google Update. |
| 1852 return_code = InstallUtil::GetInstallReturnCode(install_status); | 1501 return_code = InstallUtil::GetInstallReturnCode(install_status); |
| 1853 } | 1502 } |
| 1854 | 1503 |
| 1855 VLOG(1) << "Installation complete, returning: " << return_code; | 1504 VLOG(1) << "Installation complete, returning: " << return_code; |
| 1856 | 1505 |
| 1857 return return_code; | 1506 return return_code; |
| 1858 } | 1507 } |
| OLD | NEW |