Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: chrome/installer/setup/setup_main.cc

Issue 2589753002: Remove multi-install from chrome/installer/setup. (Closed)
Patch Set: sync to position 441108 Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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 ? &quoted_chrome_exe : NULL); 1232 write_chrome_launch_string ? &quoted_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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698