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 |