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