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 <windows.h> | 5 #include <windows.h> |
6 #include <msi.h> | 6 #include <msi.h> |
7 #include <shellapi.h> | 7 #include <shellapi.h> |
8 #include <shlobj.h> | 8 #include <shlobj.h> |
9 | 9 |
10 #include "base/at_exit.h" | 10 #include "base/at_exit.h" |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 return LzmaUtil::UnPackArchive(uncompressed_archive.value(), | 141 return LzmaUtil::UnPackArchive(uncompressed_archive.value(), |
142 output_directory.value(), &unpacked_file); | 142 output_directory.value(), &unpacked_file); |
143 } | 143 } |
144 | 144 |
145 // In multi-install, adds all products to |installer_state| that are | 145 // In multi-install, adds all products to |installer_state| that are |
146 // multi-installed and must be updated along with the products already present | 146 // multi-installed and must be updated along with the products already present |
147 // in |installer_state|. | 147 // in |installer_state|. |
148 void AddExistingMultiInstalls(const InstallationState& original_state, | 148 void AddExistingMultiInstalls(const InstallationState& original_state, |
149 InstallerState* installer_state) { | 149 InstallerState* installer_state) { |
150 if (installer_state->is_multi_install()) { | 150 if (installer_state->is_multi_install()) { |
151 for (size_t i = 0; i < BrowserDistribution::kNumProductTypes; ++i) { | 151 for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) { |
152 BrowserDistribution::Type type = BrowserDistribution::kProductTypes[i]; | 152 BrowserDistribution::Type type = |
| 153 static_cast<BrowserDistribution::Type>(i); |
| 154 |
153 if (!installer_state->FindProduct(type)) { | 155 if (!installer_state->FindProduct(type)) { |
154 const ProductState* state = | 156 const ProductState* state = |
155 original_state.GetProductState(installer_state->system_install(), | 157 original_state.GetProductState(installer_state->system_install(), |
156 type); | 158 type); |
157 if ((state != NULL) && state->is_multi_install()) { | 159 if ((state != NULL) && state->is_multi_install()) { |
158 installer_state->AddProductFromState(type, *state); | 160 installer_state->AddProductFromState(type, *state); |
159 VLOG(1) << "Product already installed and must be included: " | 161 VLOG(1) << "Product already installed and must be included: " |
160 << BrowserDistribution::GetSpecificDistribution( | 162 << BrowserDistribution::GetSpecificDistribution( |
161 type)->GetAppShortCutName(); | 163 type)->GetAppShortCutName(); |
162 } | 164 } |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 << " application and try again."; | 328 << " application and try again."; |
327 *status = installer::INCONSISTENT_UPDATE_POLICY; | 329 *status = installer::INCONSISTENT_UPDATE_POLICY; |
328 installer_state.WriteInstallerResult( | 330 installer_state.WriteInstallerResult( |
329 *status, IDS_INSTALL_INCONSISTENT_UPDATE_POLICY_BASE, NULL); | 331 *status, IDS_INSTALL_INCONSISTENT_UPDATE_POLICY_BASE, NULL); |
330 } | 332 } |
331 | 333 |
332 return settings_are_valid; | 334 return settings_are_valid; |
333 #endif // defined(GOOGLE_CHROME_BUILD) | 335 #endif // defined(GOOGLE_CHROME_BUILD) |
334 } | 336 } |
335 | 337 |
336 // The supported multi-install modes are: | 338 // If Chrome Frame is being installed by itself in multi-mode, non-ready-mode: |
337 // --multi-install --chrome --chrome-frame --ready-mode | 339 // - If a non-multi Chrome Frame installation is present, fail. |
| 340 // If Chrome Frame is being installed by itself in multi-mode, ready-mode: |
| 341 // - If no Chrome installation is present, fail. |
| 342 // - If a Chrome installation is present, add it to the set of products to |
| 343 // install. |
| 344 // If Chrome Frame is being installed with Chrome in multi-mode, ready-mode: |
338 // - If a non-multi Chrome Frame installation is present, Chrome Frame is | 345 // - If a non-multi Chrome Frame installation is present, Chrome Frame is |
339 // removed from |installer_state|'s list of products (thereby preserving | 346 // removed from |installer_state|'s list of products (thereby preserving |
340 // the existing SxS install). | 347 // the existing SxS install). |
341 // - If a multi Chrome Frame installation is present, its options are | 348 // - If a multi Chrome Frame installation is present, its options are |
342 // preserved (i.e., the --ready-mode command-line option is ignored). | 349 // preserved (i.e., the --ready-mode command-line option is ignored). |
343 // --multi-install --chrome-frame | 350 // If any product is being installed in single-mode that already exists in |
344 // - If a non-multi Chrome Frame installation is present, fail. | 351 // multi-mode, fail. |
345 // - If --ready-mode and no Chrome installation is present, fail. | |
346 // - If a Chrome installation is present, add it to the set of products to | |
347 // install. | |
348 bool CheckMultiInstallConditions(const InstallationState& original_state, | 352 bool CheckMultiInstallConditions(const InstallationState& original_state, |
349 InstallerState* installer_state, | 353 InstallerState* installer_state, |
350 installer::InstallStatus* status) { | 354 installer::InstallStatus* status) { |
351 const Products& products = installer_state->products(); | 355 const Products& products = installer_state->products(); |
352 DCHECK(products.size()); | 356 DCHECK(products.size()); |
353 | 357 |
354 const bool system_level = installer_state->system_install(); | 358 const bool system_level = installer_state->system_install(); |
355 | 359 |
356 if (installer_state->is_multi_install()) { | 360 if (installer_state->is_multi_install()) { |
357 const Product* chrome = | 361 const Product* chrome = |
358 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); | 362 installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); |
| 363 const Product* app_host = |
| 364 installer_state->FindProduct(BrowserDistribution::CHROME_APP_HOST); |
| 365 const Product* binaries = |
| 366 installer_state->FindProduct(BrowserDistribution::CHROME_BINARIES); |
359 const Product* chrome_frame = | 367 const Product* chrome_frame = |
360 installer_state->FindProduct(BrowserDistribution::CHROME_FRAME); | 368 installer_state->FindProduct(BrowserDistribution::CHROME_FRAME); |
361 const ProductState* cf_state = | 369 const ProductState* cf_state = |
362 original_state.GetProductState(system_level, | 370 original_state.GetProductState(system_level, |
363 BrowserDistribution::CHROME_FRAME); | 371 BrowserDistribution::CHROME_FRAME); |
364 if (chrome != NULL) { | 372 const ProductState* chrome_state = |
365 if (chrome_frame != NULL && | 373 original_state.GetProductState(system_level, |
| 374 BrowserDistribution::CHROME_BROWSER); |
| 375 |
| 376 if (!binaries) { |
| 377 if (app_host && !chrome && !chrome_frame && !cf_state && !chrome_state) { |
| 378 DCHECK(!system_level); |
| 379 // App Host may use Chrome/Chrome binaries at system-level. |
| 380 if (original_state.GetProductState( |
| 381 true, // system |
| 382 BrowserDistribution::CHROME_BROWSER) || |
| 383 original_state.GetProductState( |
| 384 true, // system |
| 385 BrowserDistribution::CHROME_BINARIES)) { |
| 386 return true; |
| 387 } else { |
| 388 return false; |
| 389 } |
| 390 } else { |
| 391 // Every other scenario requires the binaries to be installed/updated |
| 392 // simultaneous to the main product. |
| 393 return false; |
| 394 } |
| 395 } |
| 396 |
| 397 if (chrome) { |
| 398 if (chrome_frame && |
366 chrome_frame->HasOption(installer::kOptionReadyMode)) { | 399 chrome_frame->HasOption(installer::kOptionReadyMode)) { |
367 // We're being asked to install Chrome with Chrome Frame in ready-mode. | 400 // We're being asked to install Chrome with Chrome Frame in ready-mode. |
368 // This is an optimistic operation: if a SxS install of Chrome Frame | 401 // This is an optimistic operation: if a SxS install of Chrome Frame |
369 // is already present, don't touch it; if a multi-install of Chrome | 402 // is already present, don't touch it; if a multi-install of Chrome |
370 // Frame is present, preserve its settings (ready-mode). | 403 // Frame is present, preserve its settings (ready-mode). |
371 if (cf_state != NULL) { | 404 if (cf_state != NULL) { |
372 installer_state->RemoveProduct(chrome_frame); | 405 installer_state->RemoveProduct(chrome_frame); |
373 chrome_frame = NULL; | 406 chrome_frame = NULL; |
374 if (cf_state->is_multi_install()) { | 407 if (cf_state->is_multi_install()) { |
375 chrome_frame = installer_state->AddProductFromState( | 408 chrome_frame = installer_state->AddProductFromState( |
376 BrowserDistribution::CHROME_FRAME, *cf_state); | 409 BrowserDistribution::CHROME_FRAME, *cf_state); |
377 VLOG(1) << "Upgrading existing multi-install Chrome Frame rather " | 410 VLOG(1) << "Upgrading existing multi-install Chrome Frame rather " |
378 "than installing in ready-mode."; | 411 "than installing in ready-mode."; |
379 } else { | 412 } else { |
380 VLOG(1) << "Skipping upgrade of single-install Chrome Frame rather " | 413 VLOG(1) << "Skipping upgrade of single-install Chrome Frame rather " |
381 "than installing in ready-mode."; | 414 "than installing in ready-mode."; |
382 } | 415 } |
383 } else { | 416 } else { |
384 VLOG(1) << "Performing initial install of Chrome Frame ready-mode."; | 417 VLOG(1) << "Performing initial install of Chrome Frame ready-mode."; |
385 } | 418 } |
386 } | 419 } |
387 } else if (chrome_frame != NULL) { | 420 } else if (chrome_state != NULL) { |
388 // We're being asked to install or update Chrome Frame alone. | 421 // Chrome Frame is being installed in multi-install mode, and Chrome is |
389 const ProductState* chrome_state = | 422 // already present. Add Chrome to the set of products (making it |
390 original_state.GetProductState(system_level, | 423 // multi-install in the process) so that it is updated, too. |
391 BrowserDistribution::CHROME_BROWSER); | 424 scoped_ptr<Product> multi_chrome(new Product( |
392 if (chrome_state != NULL) { | 425 BrowserDistribution::GetSpecificDistribution( |
393 // Add Chrome to the set of products (making it multi-install in the | 426 BrowserDistribution::CHROME_BROWSER))); |
394 // process) so that it is updated, too. | 427 multi_chrome->SetOption(installer::kOptionMultiInstall, true); |
395 scoped_ptr<Product> multi_chrome(new Product( | 428 chrome = installer_state->AddProduct(&multi_chrome); |
396 BrowserDistribution::GetSpecificDistribution( | 429 VLOG(1) << "Upgrading existing Chrome browser in multi-install mode."; |
397 BrowserDistribution::CHROME_BROWSER))); | 430 } else if (chrome_frame && |
398 multi_chrome->SetOption(installer::kOptionMultiInstall, true); | 431 chrome_frame->HasOption(installer::kOptionReadyMode)) { |
399 chrome = installer_state->AddProduct(&multi_chrome); | 432 // Chrome Frame with ready-mode is to be installed, yet Chrome is |
400 VLOG(1) << "Upgrading existing multi-install Chrome browser along with " | 433 // neither installed nor being installed. Fail. |
401 << chrome_frame->distribution()->GetAppShortCutName(); | 434 LOG(ERROR) << "Cannot install Chrome Frame in ready mode without Chrome."; |
402 } else if (chrome_frame->HasOption(installer::kOptionReadyMode)) { | 435 *status = installer::READY_MODE_REQUIRES_CHROME; |
403 // Chrome Frame with ready-mode is to be installed, yet Chrome is | 436 installer_state->WriteInstallerResult( |
404 // neither installed nor being installed. Fail. | 437 *status, IDS_INSTALL_READY_MODE_REQUIRES_CHROME_BASE, NULL); |
405 LOG(ERROR) << "Cannot install Chrome Frame in ready mode without " | 438 return false; |
406 "Chrome."; | |
407 *status = installer::READY_MODE_REQUIRES_CHROME; | |
408 installer_state->WriteInstallerResult(*status, | |
409 IDS_INSTALL_READY_MODE_REQUIRES_CHROME_BASE, NULL); | |
410 return false; | |
411 } | |
412 } | 439 } |
413 | 440 |
414 // Fail if we're installing Chrome Frame when a single-install of it is | 441 // Fail if we're installing Chrome Frame when a single-install of it is |
415 // already installed. | 442 // already installed. |
416 // TODO(grt): Add support for migration of Chrome Frame from single- to | 443 // TODO(grt): Add support for migration of Chrome Frame from single- to |
417 // multi-install. | 444 // multi-install. |
418 if (chrome_frame != NULL && | 445 if (chrome_frame && cf_state && !cf_state->is_multi_install()) { |
419 cf_state != NULL && !cf_state->is_multi_install()) { | |
420 LOG(ERROR) << "Cannot migrate existing Chrome Frame installation to " | 446 LOG(ERROR) << "Cannot migrate existing Chrome Frame installation to " |
421 "multi-install."; | 447 << "multi-install."; |
422 *status = installer::NON_MULTI_INSTALLATION_EXISTS; | 448 *status = installer::NON_MULTI_INSTALLATION_EXISTS; |
423 installer_state->WriteInstallerResult(*status, | 449 installer_state->WriteInstallerResult(*status, |
424 IDS_INSTALL_NON_MULTI_INSTALLATION_EXISTS_BASE, NULL); | 450 IDS_INSTALL_NON_MULTI_INSTALLATION_EXISTS_BASE, NULL); |
425 return false; | 451 return false; |
426 } | 452 } |
427 } else if (DCHECK_IS_ON()) { | 453 } else { |
| 454 // This is a non-multi installation. |
| 455 |
428 // It isn't possible to stuff two products into a single-install | 456 // It isn't possible to stuff two products into a single-install |
429 // InstallerState. Abort the process here in debug builds just in case | 457 // InstallerState. Abort the process here in debug builds just in case |
430 // someone finds a way. | 458 // someone finds a way. |
431 DCHECK_EQ(1U, products.size()); | 459 DCHECK_EQ(1U, products.size()); |
| 460 if (products.size() != 1) |
| 461 return false; |
| 462 |
| 463 // Check for an existing installation of the product. |
| 464 const ProductState* product_state = original_state.GetProductState( |
| 465 system_level, products[0]->distribution()->GetType()); |
| 466 if (product_state != NULL) { |
| 467 // Block downgrades from multi-install to single-install. |
| 468 if (product_state->is_multi_install()) { |
| 469 LOG(ERROR) << "Multi-install " |
| 470 << products[0]->distribution()->GetAppShortCutName() |
| 471 << " exists; aborting single install."; |
| 472 *status = installer::MULTI_INSTALLATION_EXISTS; |
| 473 installer_state->WriteInstallerResult(*status, |
| 474 IDS_INSTALL_MULTI_INSTALLATION_EXISTS_BASE, NULL); |
| 475 return false; |
| 476 } |
| 477 } |
| 478 |
| 479 } |
| 480 |
| 481 return true; |
| 482 } |
| 483 |
| 484 bool CheckAppHostPreconditions(const InstallationState& original_state, |
| 485 InstallerState* installer_state) { |
| 486 if (!installer_state->FindProduct(BrowserDistribution::CHROME_APP_HOST)) |
| 487 return true; |
| 488 |
| 489 if (!installer_state->is_multi_install()) { |
| 490 VLOG(1) << "Application Host may only be installed in multi-install mode."; |
| 491 return false; |
| 492 } |
| 493 |
| 494 if (installer_state->system_install()) { |
| 495 VLOG(1) << "Application Host may only be installed at user-level."; |
| 496 return false; |
432 } | 497 } |
433 | 498 |
434 return true; | 499 return true; |
435 } | 500 } |
436 | 501 |
437 // Checks for compatibility between the current state of the system and the | 502 // Checks for compatibility between the current state of the system and the |
438 // desired operation. Also applies policy that mutates the desired operation; | 503 // desired operation. Also applies policy that mutates the desired operation; |
439 // specifically, the |installer_state| object. | 504 // specifically, the |installer_state| object. |
440 // Also blocks simultaneous user-level and system-level installs. In the case | 505 // Also blocks simultaneous user-level and system-level installs. In the case |
441 // of trying to install user-level Chrome when system-level exists, the | 506 // of trying to install user-level Chrome when system-level exists, the |
442 // existing system-level Chrome is launched. | 507 // existing system-level Chrome is launched. |
443 // When the pre-install conditions are not satisfied, the result is written to | 508 // When the pre-install conditions are not satisfied, the result is written to |
444 // the registry (via WriteInstallerResult), |status| is set appropriately, and | 509 // the registry (via WriteInstallerResult), |status| is set appropriately, and |
445 // false is returned. | 510 // false is returned. |
446 bool CheckPreInstallConditions(const InstallationState& original_state, | 511 bool CheckPreInstallConditions(const InstallationState& original_state, |
447 InstallerState* installer_state, | 512 InstallerState* installer_state, |
448 installer::InstallStatus* status) { | 513 installer::InstallStatus* status) { |
449 // See what products are already installed in multi mode. When we do multi | 514 if (!CheckAppHostPreconditions(original_state, installer_state)) |
450 // installs, we must upgrade all installations since they share the binaries. | 515 return false; |
451 AddExistingMultiInstalls(original_state, installer_state); | 516 |
| 517 if (!CheckMultiInstallConditions(original_state, installer_state, status)) |
| 518 return false; |
452 | 519 |
453 const Products& products = installer_state->products(); | 520 const Products& products = installer_state->products(); |
454 if (products.empty()) { | 521 if (products.empty()) { |
455 // We haven't been given any products on which to operate. | 522 // We haven't been given any products on which to operate. |
456 LOG(ERROR) | 523 LOG(ERROR) |
457 << "Not given any products to install and no products found to update."; | 524 << "Not given any products to install and no products found to update."; |
458 *status = installer::CHROME_NOT_INSTALLED; | 525 *status = installer::CHROME_NOT_INSTALLED; |
459 installer_state->WriteInstallerResult(*status, | 526 installer_state->WriteInstallerResult(*status, |
460 IDS_INSTALL_NO_PRODUCTS_TO_UPDATE_BASE, NULL); | 527 IDS_INSTALL_NO_PRODUCTS_TO_UPDATE_BASE, NULL); |
461 return false; | 528 return false; |
462 } | 529 } |
463 | 530 |
464 if (!CheckMultiInstallConditions(original_state, installer_state, status)) | 531 // See what products are already installed in multi mode. When we do multi |
465 return false; | 532 // installs, we must upgrade all installations since they share the binaries. |
| 533 AddExistingMultiInstalls(original_state, installer_state); |
466 | 534 |
467 bool is_first_install = true; | 535 if (!installer_state->system_install()) { |
468 const bool system_level = installer_state->system_install(); | 536 // This is a user-level installation. Make sure that we are not installing |
| 537 // on top of an existing system-level installation. |
| 538 for (size_t i = 0; i < products.size(); ++i) { |
| 539 const Product* product = products[i]; |
| 540 BrowserDistribution* browser_dist = product->distribution(); |
| 541 const ProductState* user_level_product_state = |
| 542 original_state.GetProductState(false, browser_dist->GetType()); |
| 543 const ProductState* system_level_product_state = |
| 544 original_state.GetProductState(true, browser_dist->GetType()); |
469 | 545 |
470 for (size_t i = 0; i < products.size(); ++i) { | 546 // Allow upgrades to proceed so that out-of-date versions are not left |
471 const Product* product = products[i]; | 547 // around. |
472 BrowserDistribution* browser_dist = product->distribution(); | 548 if (user_level_product_state) |
| 549 continue; |
473 | 550 |
474 // Check for an existing installation of the product. | 551 // This is a new user-level install... |
475 const ProductState* product_state = | |
476 original_state.GetProductState(system_level, browser_dist->GetType()); | |
477 if (product_state != NULL) { | |
478 is_first_install = false; | |
479 // Block downgrades from multi-install to single-install. | |
480 if (!installer_state->is_multi_install() && | |
481 product_state->is_multi_install()) { | |
482 LOG(ERROR) << "Multi-install " << browser_dist->GetAppShortCutName() | |
483 << " exists; aborting single install."; | |
484 *status = installer::MULTI_INSTALLATION_EXISTS; | |
485 installer_state->WriteInstallerResult(*status, | |
486 IDS_INSTALL_MULTI_INSTALLATION_EXISTS_BASE, NULL); | |
487 return false; | |
488 } | |
489 } | |
490 | 552 |
491 // Check to avoid attempting to lay down a user-level installation on top | 553 if (system_level_product_state) { |
492 // of a system-level one. | 554 // ... and the product already exists at system-level. |
493 const ProductState* other_state = | |
494 original_state.GetProductState(!system_level, browser_dist->GetType()); | |
495 if (other_state != NULL && !system_level) { | |
496 if (is_first_install) { | |
497 // This is a user-level install and there is a system-level install of | |
498 // the product. | |
499 LOG(ERROR) << "Already installed version " | 555 LOG(ERROR) << "Already installed version " |
500 << other_state->version().GetString() | 556 << system_level_product_state->version().GetString() |
501 << " at system-level conflicts with this one at user-level."; | 557 << " at system-level conflicts with this one at user-level."; |
502 if (product->is_chrome()) { | 558 if (product->is_chrome()) { |
503 // Instruct Google Update to launch the existing system-level Chrome. | 559 // Instruct Google Update to launch the existing system-level Chrome. |
504 // There should be no error dialog. | 560 // There should be no error dialog. |
505 FilePath chrome_exe(installer::GetChromeInstallPath(!system_level, | 561 FilePath install_path(installer::GetChromeInstallPath(true, // system |
506 browser_dist)); | 562 browser_dist)); |
507 if (chrome_exe.empty()) { | 563 if (install_path.empty()) { |
508 // If we failed to construct install path. Give up. | 564 // Give up if we failed to construct the install path. |
509 *status = installer::OS_ERROR; | 565 *status = installer::OS_ERROR; |
510 installer_state->WriteInstallerResult(*status, | 566 installer_state->WriteInstallerResult(*status, |
511 IDS_INSTALL_OS_ERROR_BASE, NULL); | 567 IDS_INSTALL_OS_ERROR_BASE, |
| 568 NULL); |
512 } else { | 569 } else { |
513 *status = installer::EXISTING_VERSION_LAUNCHED; | 570 *status = installer::EXISTING_VERSION_LAUNCHED; |
514 chrome_exe = chrome_exe.Append(installer::kChromeExe); | 571 FilePath chrome_exe = install_path.Append(installer::kChromeExe); |
515 CommandLine cmd(chrome_exe); | 572 CommandLine cmd(chrome_exe); |
516 cmd.AppendSwitch(switches::kFirstRun); | 573 cmd.AppendSwitch(switches::kFirstRun); |
517 installer_state->WriteInstallerResult(*status, 0, NULL); | 574 installer_state->WriteInstallerResult(*status, 0, NULL); |
518 VLOG(1) << "Launching existing system-level chrome instead."; | 575 VLOG(1) << "Launching existing system-level chrome instead."; |
519 base::LaunchProcess(cmd, base::LaunchOptions(), NULL); | 576 base::LaunchProcess(cmd, base::LaunchOptions(), NULL); |
520 } | 577 } |
521 } else { | 578 } else { |
522 // Display an error message for Chrome Frame. | 579 // Display an error message for other products. |
523 *status = installer::SYSTEM_LEVEL_INSTALL_EXISTS; | 580 *status = installer::SYSTEM_LEVEL_INSTALL_EXISTS; |
524 installer_state->WriteInstallerResult(*status, | 581 installer_state->WriteInstallerResult( |
525 IDS_INSTALL_SYSTEM_LEVEL_EXISTS_BASE, NULL); | 582 *status, IDS_INSTALL_SYSTEM_LEVEL_EXISTS_BASE, NULL); |
526 } | 583 } |
527 return false; | 584 return false; |
528 } | 585 } |
529 // This is an update, not a new install. Allow it to take place so that | |
530 // out-of-date versions are not left around. | |
531 } | |
532 } | |
533 | |
534 // If no previous installation of Chrome, make sure installation directory | |
535 // either does not exist or can be deleted (i.e. is not locked by some other | |
536 // process). | |
537 if (is_first_install) { | |
538 if (file_util::PathExists(installer_state->target_path()) && | |
539 !file_util::Delete(installer_state->target_path(), true)) { | |
540 LOG(ERROR) << "Installation directory " | |
541 << installer_state->target_path().value() | |
542 << " exists and can not be deleted."; | |
543 *status = installer::INSTALL_DIR_IN_USE; | |
544 int str_id = IDS_INSTALL_DIR_IN_USE_BASE; | |
545 installer_state->WriteInstallerResult(*status, str_id, NULL); | |
546 return false; | |
547 } | 586 } |
548 } | 587 } |
549 | 588 |
550 return true; | 589 return true; |
551 } | 590 } |
552 | 591 |
553 installer::InstallStatus InstallProductsHelper( | 592 installer::InstallStatus InstallProductsHelper( |
554 const InstallationState& original_state, | 593 const InstallationState& original_state, |
555 const CommandLine& cmd_line, | 594 const CommandLine& cmd_line, |
556 const MasterPreferences& prefs, | 595 const MasterPreferences& prefs, |
557 const InstallerState& installer_state, | 596 const InstallerState& installer_state, |
558 installer::ArchiveType* archive_type) { | 597 installer::ArchiveType* archive_type) { |
559 DCHECK(archive_type); | 598 DCHECK(archive_type); |
560 const bool system_install = installer_state.system_install(); | 599 const bool system_install = installer_state.system_install(); |
561 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; | 600 installer::InstallStatus install_status = installer::UNKNOWN_STATUS; |
562 | 601 |
563 // For install the default location for chrome.packed.7z is in current | 602 // For install the default location for chrome.packed.7z is in current |
564 // folder, so get that value first. | 603 // folder, so get that value first. |
565 FilePath archive(cmd_line.GetProgram().DirName().Append( | 604 FilePath archive(cmd_line.GetProgram().DirName().Append( |
566 installer::kChromeCompressedArchive)); | 605 installer::kChromeCompressedArchive)); |
567 | 606 |
568 // If --install-archive is given, get the user specified value | 607 // If --install-archive is given, get the user specified value |
569 if (cmd_line.HasSwitch(installer::switches::kInstallArchive)) { | 608 if (cmd_line.HasSwitch(installer::switches::kInstallArchive)) { |
570 archive = cmd_line.GetSwitchValuePath( | 609 archive = cmd_line.GetSwitchValuePath( |
571 installer::switches::kInstallArchive); | 610 installer::switches::kInstallArchive); |
572 } | 611 } |
573 VLOG(1) << "Archive found to install Chrome " << archive.value(); | 612 |
574 const Products& products = installer_state.products(); | 613 const Products& products = installer_state.products(); |
575 | 614 |
576 // Create a temp folder where we will unpack Chrome archive. If it fails, | 615 // Create a temp folder where we will unpack Chrome archive. If it fails, |
577 // then we are doomed, so return immediately and no cleanup is required. | 616 // then we are doomed, so return immediately and no cleanup is required. |
578 installer::SelfCleaningTempDir temp_path; | 617 installer::SelfCleaningTempDir temp_path; |
579 if (!temp_path.Initialize(installer_state.target_path().DirName(), | 618 if (!temp_path.Initialize(installer_state.target_path().DirName(), |
580 installer::kInstallTempDir)) { | 619 installer::kInstallTempDir)) { |
581 PLOG(ERROR) << "Could not create temporary path."; | 620 PLOG(ERROR) << "Could not create temporary path."; |
582 installer_state.WriteInstallerResult(installer::TEMP_DIR_FAILED, | 621 installer_state.WriteInstallerResult(installer::TEMP_DIR_FAILED, |
583 IDS_INSTALL_TEMP_DIR_FAILED_BASE, NULL); | 622 IDS_INSTALL_TEMP_DIR_FAILED_BASE, NULL); |
584 return installer::TEMP_DIR_FAILED; | 623 return installer::TEMP_DIR_FAILED; |
585 } | 624 } |
586 VLOG(1) << "created path " << temp_path.path().value(); | 625 VLOG(1) << "created path " << temp_path.path().value(); |
587 | 626 |
588 FilePath unpack_path(temp_path.path().Append(installer::kInstallSourceDir)); | 627 FilePath unpack_path(temp_path.path().Append(installer::kInstallSourceDir)); |
589 if (UnPackArchive(archive, installer_state, temp_path.path(), unpack_path, | 628 |
590 archive_type)) { | 629 bool unpacked = false; |
591 install_status = (*archive_type) == installer::INCREMENTAL_ARCHIVE_TYPE ? | 630 |
592 installer::APPLY_DIFF_PATCH_FAILED : installer::UNCOMPRESSION_FAILED; | 631 // We want to keep uncompressed archive (chrome.7z) that we get after |
593 installer_state.WriteInstallerResult(install_status, | 632 // uncompressing and binary patching. Get the location for this file. |
594 IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, NULL); | 633 FilePath archive_to_copy; |
| 634 if (file_util::PathExists(archive)) { |
| 635 VLOG(1) << "Archive found to install Chrome " << archive.value(); |
| 636 if (UnPackArchive(archive, installer_state, temp_path.path(), unpack_path, |
| 637 archive_type)) { |
| 638 install_status = (*archive_type) == installer::INCREMENTAL_ARCHIVE_TYPE ? |
| 639 installer::APPLY_DIFF_PATCH_FAILED : installer::UNCOMPRESSION_FAILED; |
| 640 installer_state.WriteInstallerResult( |
| 641 install_status, |
| 642 IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, |
| 643 NULL); |
| 644 } else { |
| 645 unpacked = true; |
| 646 archive_to_copy = temp_path.path().Append(installer::kChromeArchive); |
| 647 } |
595 } else { | 648 } else { |
| 649 FilePath uncompressed_archive(cmd_line.GetProgram().DirName().Append( |
| 650 installer::kChromeArchive)); |
| 651 |
| 652 if (file_util::PathExists(uncompressed_archive)) { |
| 653 VLOG(1) << "Uncompressed archive found to install Chrome " |
| 654 << uncompressed_archive.value(); |
| 655 *archive_type = installer::FULL_ARCHIVE_TYPE; |
| 656 string16 unpacked_file; |
| 657 if (LzmaUtil::UnPackArchive(uncompressed_archive.value(), |
| 658 unpack_path.value(), &unpacked_file)) { |
| 659 installer_state.WriteInstallerResult( |
| 660 installer::UNCOMPRESSION_FAILED, |
| 661 IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, |
| 662 NULL); |
| 663 } else { |
| 664 unpacked = true; |
| 665 archive_to_copy = uncompressed_archive; |
| 666 } |
| 667 } |
| 668 } |
| 669 if (unpacked) { |
596 VLOG(1) << "unpacked to " << unpack_path.value(); | 670 VLOG(1) << "unpacked to " << unpack_path.value(); |
597 FilePath src_path(unpack_path.Append(installer::kInstallSourceChromeDir)); | 671 FilePath src_path(unpack_path.Append(installer::kInstallSourceChromeDir)); |
598 scoped_ptr<Version> | 672 scoped_ptr<Version> |
599 installer_version(installer::GetMaxVersionFromArchiveDir(src_path)); | 673 installer_version(installer::GetMaxVersionFromArchiveDir(src_path)); |
600 if (!installer_version.get()) { | 674 if (!installer_version.get()) { |
601 LOG(ERROR) << "Did not find any valid version in installer."; | 675 LOG(ERROR) << "Did not find any valid version in installer."; |
602 install_status = installer::INVALID_ARCHIVE; | 676 install_status = installer::INVALID_ARCHIVE; |
603 installer_state.WriteInstallerResult(install_status, | 677 installer_state.WriteInstallerResult(install_status, |
604 IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); | 678 IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); |
605 } else { | 679 } else { |
(...skipping 11 matching lines...) Expand all Loading... |
617 if (product_state != NULL && | 691 if (product_state != NULL && |
618 (product_state->version().CompareTo(*installer_version) > 0)) { | 692 (product_state->version().CompareTo(*installer_version) > 0)) { |
619 LOG(ERROR) << "Higher version of " | 693 LOG(ERROR) << "Higher version of " |
620 << product->distribution()->GetAppShortCutName() | 694 << product->distribution()->GetAppShortCutName() |
621 << " is already installed."; | 695 << " is already installed."; |
622 higher_products |= (1 << product->distribution()->GetType()); | 696 higher_products |= (1 << product->distribution()->GetType()); |
623 } | 697 } |
624 } | 698 } |
625 | 699 |
626 if (higher_products != 0) { | 700 if (higher_products != 0) { |
627 COMPILE_ASSERT(BrowserDistribution::NUM_TYPES == 3, | 701 COMPILE_ASSERT(BrowserDistribution::NUM_TYPES == 4, |
628 add_support_for_new_products_here_); | 702 add_support_for_new_products_here_); |
629 const uint32 kBrowserBit = 1 << BrowserDistribution::CHROME_BROWSER; | 703 const uint32 kBrowserBit = 1 << BrowserDistribution::CHROME_BROWSER; |
630 const uint32 kGCFBit = 1 << BrowserDistribution::CHROME_FRAME; | 704 const uint32 kGCFBit = 1 << BrowserDistribution::CHROME_FRAME; |
| 705 const uint32 kAppHostBit = 1 << BrowserDistribution::CHROME_APP_HOST; |
631 int message_id = 0; | 706 int message_id = 0; |
632 | 707 |
633 proceed_with_installation = false; | 708 proceed_with_installation = false; |
634 install_status = installer::HIGHER_VERSION_EXISTS; | 709 install_status = installer::HIGHER_VERSION_EXISTS; |
635 if ((higher_products & kBrowserBit) != 0) { | 710 switch (higher_products) { |
636 if ((higher_products & kGCFBit) != 0) | 711 case kBrowserBit: |
| 712 message_id = IDS_INSTALL_HIGHER_VERSION_BASE; |
| 713 break; |
| 714 case kGCFBit: |
| 715 message_id = IDS_INSTALL_HIGHER_VERSION_CF_BASE; |
| 716 break; |
| 717 case kGCFBit | kBrowserBit: |
637 message_id = IDS_INSTALL_HIGHER_VERSION_CB_CF_BASE; | 718 message_id = IDS_INSTALL_HIGHER_VERSION_CB_CF_BASE; |
638 else | 719 break; |
639 message_id = IDS_INSTALL_HIGHER_VERSION_BASE; | 720 default: |
640 } else { | 721 message_id = IDS_INSTALL_HIGHER_VERSION_APP_HOST_BASE; |
641 DCHECK(higher_products == kGCFBit); | 722 break; |
642 message_id = IDS_INSTALL_HIGHER_VERSION_CF_BASE; | |
643 } | 723 } |
644 | 724 |
645 installer_state.WriteInstallerResult(install_status, message_id, NULL); | 725 installer_state.WriteInstallerResult(install_status, message_id, NULL); |
646 } | 726 } |
647 | 727 |
648 proceed_with_installation = | 728 proceed_with_installation = |
649 proceed_with_installation && | 729 proceed_with_installation && |
650 CheckGroupPolicySettings(original_state, installer_state, | 730 CheckGroupPolicySettings(original_state, installer_state, |
651 *installer_version, &install_status); | 731 *installer_version, &install_status); |
652 | 732 |
653 if (proceed_with_installation) { | 733 if (proceed_with_installation) { |
654 // We want to keep uncompressed archive (chrome.7z) that we get after | |
655 // uncompressing and binary patching. Get the location for this file. | |
656 FilePath archive_to_copy( | |
657 temp_path.path().Append(installer::kChromeArchive)); | |
658 FilePath prefs_source_path(cmd_line.GetSwitchValueNative( | 734 FilePath prefs_source_path(cmd_line.GetSwitchValueNative( |
659 installer::switches::kInstallerData)); | 735 installer::switches::kInstallerData)); |
660 install_status = installer::InstallOrUpdateProduct(original_state, | 736 install_status = installer::InstallOrUpdateProduct(original_state, |
661 installer_state, cmd_line.GetProgram(), archive_to_copy, | 737 installer_state, cmd_line.GetProgram(), archive_to_copy, |
662 temp_path.path(), prefs_source_path, prefs, *installer_version); | 738 temp_path.path(), prefs_source_path, prefs, *installer_version); |
663 | 739 |
664 int install_msg_base = IDS_INSTALL_FAILED_BASE; | 740 int install_msg_base = IDS_INSTALL_FAILED_BASE; |
665 string16 chrome_exe; | 741 string16 chrome_exe; |
666 string16 quoted_chrome_exe; | 742 string16 quoted_chrome_exe; |
667 if (install_status == installer::SAME_VERSION_REPAIR_FAILED) { | 743 if (install_status == installer::SAME_VERSION_REPAIR_FAILED) { |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
872 << uninstall_cmd << ")"; | 948 << uninstall_cmd << ")"; |
873 } | 949 } |
874 } | 950 } |
875 } | 951 } |
876 | 952 |
877 installer::InstallStatus UninstallProducts( | 953 installer::InstallStatus UninstallProducts( |
878 const InstallationState& original_state, | 954 const InstallationState& original_state, |
879 const InstallerState& installer_state, | 955 const InstallerState& installer_state, |
880 const CommandLine& cmd_line) { | 956 const CommandLine& cmd_line) { |
881 const Products& products = installer_state.products(); | 957 const Products& products = installer_state.products(); |
882 // InstallerState::Initialize always puts Chrome first, and we rely on that | 958 |
883 // here for this reason: if Chrome is in-use, the user will be prompted to | 959 if (installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER)) { |
884 // confirm uninstallation. Upon cancel, we should not continue with the | 960 // InstallerState::Initialize always puts Chrome first, and we rely on that |
885 // other products. | 961 // here for this reason: if Chrome is in-use, the user will be prompted to |
886 DCHECK(products.size() < 2 || products[0]->is_chrome()); | 962 // confirm uninstallation. Upon cancel, we should not continue with the |
| 963 // other products. |
| 964 DCHECK(products[0]->is_chrome()); |
| 965 } |
| 966 if (installer_state.FindProduct(BrowserDistribution::CHROME_BINARIES)) { |
| 967 // Chrome Binaries should be last; if something else is cancelled, they |
| 968 // should stay. |
| 969 DCHECK(products[products.size() - 1]->is_chrome_binaries()); |
| 970 } |
| 971 |
887 installer::InstallStatus install_status = installer::UNINSTALL_SUCCESSFUL; | 972 installer::InstallStatus install_status = installer::UNINSTALL_SUCCESSFUL; |
888 installer::InstallStatus prod_status = installer::UNKNOWN_STATUS; | 973 installer::InstallStatus prod_status = installer::UNKNOWN_STATUS; |
889 const bool force = cmd_line.HasSwitch(installer::switches::kForceUninstall); | 974 const bool force = cmd_line.HasSwitch(installer::switches::kForceUninstall); |
890 const bool remove_all = !cmd_line.HasSwitch( | 975 const bool remove_all = !cmd_line.HasSwitch( |
891 installer::switches::kDoNotRemoveSharedItems); | 976 installer::switches::kDoNotRemoveSharedItems); |
892 | 977 |
893 for (size_t i = 0; | 978 for (size_t i = 0; |
894 install_status != installer::UNINSTALL_CANCELLED && | 979 install_status != installer::UNINSTALL_CANCELLED && |
895 i < products.size(); | 980 i < products.size(); |
896 ++i) { | 981 ++i) { |
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1396 if (!(installer_state.is_msi() && is_uninstall)) | 1481 if (!(installer_state.is_msi() && is_uninstall)) |
1397 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT | 1482 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT |
1398 // to pass through, since this is only returned on uninstall which is | 1483 // to pass through, since this is only returned on uninstall which is |
1399 // never invoked directly by Google Update. | 1484 // never invoked directly by Google Update. |
1400 return_code = InstallUtil::GetInstallReturnCode(install_status); | 1485 return_code = InstallUtil::GetInstallReturnCode(install_status); |
1401 | 1486 |
1402 VLOG(1) << "Installation complete, returning: " << return_code; | 1487 VLOG(1) << "Installation complete, returning: " << return_code; |
1403 | 1488 |
1404 return return_code; | 1489 return return_code; |
1405 } | 1490 } |
OLD | NEW |