| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/crx_installer.h" | 5 #include "chrome/browser/extensions/crx_installer.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <set> | 8 #include <set> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 allow_silent_install_(false), | 101 allow_silent_install_(false), |
| 102 bypass_blacklist_for_test_(false), | 102 bypass_blacklist_for_test_(false), |
| 103 install_cause_(extension_misc::INSTALL_CAUSE_UNSET), | 103 install_cause_(extension_misc::INSTALL_CAUSE_UNSET), |
| 104 creation_flags_(Extension::NO_FLAGS), | 104 creation_flags_(Extension::NO_FLAGS), |
| 105 off_store_install_allow_reason_(OffStoreInstallDisallowed), | 105 off_store_install_allow_reason_(OffStoreInstallDisallowed), |
| 106 did_handle_successfully_(true), | 106 did_handle_successfully_(true), |
| 107 record_oauth2_grant_(false), | 107 record_oauth2_grant_(false), |
| 108 error_on_unsupported_requirements_(false), | 108 error_on_unsupported_requirements_(false), |
| 109 requirements_checker_(new extensions::RequirementsChecker()), | 109 requirements_checker_(new extensions::RequirementsChecker()), |
| 110 has_requirement_errors_(false), | 110 has_requirement_errors_(false), |
| 111 install_wait_for_idle_(true) { | 111 install_wait_for_idle_(true), |
| 112 update_from_settings_page_(false) { |
| 112 installer_task_runner_ = frontend_weak->GetFileTaskRunner(); | 113 installer_task_runner_ = frontend_weak->GetFileTaskRunner(); |
| 113 if (!approval) | 114 if (!approval) |
| 114 return; | 115 return; |
| 115 | 116 |
| 116 CHECK(profile_->IsSameProfile(approval->profile)); | 117 CHECK(profile_->IsSameProfile(approval->profile)); |
| 117 if (client_) { | 118 if (client_) { |
| 118 client_->install_ui()->SetUseAppInstalledBubble( | 119 client_->install_ui()->SetUseAppInstalledBubble( |
| 119 approval->use_app_installed_bubble); | 120 approval->use_app_installed_bubble); |
| 120 client_->install_ui()->SetSkipPostInstallUI(approval->skip_post_install_ui); | 121 client_->install_ui()->SetSkipPostInstallUI(approval->skip_post_install_ui); |
| 121 } | 122 } |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 } | 422 } |
| 422 | 423 |
| 423 ConfirmInstall(); | 424 ConfirmInstall(); |
| 424 } | 425 } |
| 425 | 426 |
| 426 void CrxInstaller::ConfirmInstall() { | 427 void CrxInstaller::ConfirmInstall() { |
| 427 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 428 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 428 if (!frontend_weak_.get() || frontend_weak_->browser_terminating()) | 429 if (!frontend_weak_.get() || frontend_weak_->browser_terminating()) |
| 429 return; | 430 return; |
| 430 | 431 |
| 432 // Check whether this install is initiated from the settings page to |
| 433 // update an existing extension or app. |
| 434 CheckUpdateFromSettingsPage(); |
| 435 |
| 431 string16 error; | 436 string16 error; |
| 432 if (!ExtensionSystem::Get(profile_)->management_policy()-> | 437 if (!ExtensionSystem::Get(profile_)->management_policy()-> |
| 433 UserMayLoad(extension_, &error)) { | 438 UserMayLoad(extension_, &error)) { |
| 434 ReportFailureFromUIThread(CrxInstallerError(error)); | 439 ReportFailureFromUIThread(CrxInstallerError(error)); |
| 435 return; | 440 return; |
| 436 } | 441 } |
| 437 | 442 |
| 438 GURL overlapping_url; | 443 GURL overlapping_url; |
| 439 const Extension* overlapping_extension = | 444 const Extension* overlapping_extension = |
| 440 frontend_weak_->extensions()-> | 445 frontend_weak_->extensions()-> |
| 441 GetHostedAppByOverlappingWebExtent(extension_->web_extent()); | 446 GetHostedAppByOverlappingWebExtent(extension_->web_extent()); |
| 442 if (overlapping_extension && | 447 if (overlapping_extension && |
| 443 overlapping_extension->id() != extension_->id()) { | 448 overlapping_extension->id() != extension_->id()) { |
| 444 ReportFailureFromUIThread( | 449 ReportFailureFromUIThread( |
| 445 CrxInstallerError( | 450 CrxInstallerError( |
| 446 l10n_util::GetStringFUTF16( | 451 l10n_util::GetStringFUTF16( |
| 447 IDS_EXTENSION_OVERLAPPING_WEB_EXTENT, | 452 IDS_EXTENSION_OVERLAPPING_WEB_EXTENT, |
| 448 UTF8ToUTF16(overlapping_extension->name())))); | 453 UTF8ToUTF16(overlapping_extension->name())))); |
| 449 return; | 454 return; |
| 450 } | 455 } |
| 451 | 456 |
| 452 current_version_ = | 457 current_version_ = |
| 453 frontend_weak_->extension_prefs()->GetVersionString(extension_->id()); | 458 frontend_weak_->extension_prefs()->GetVersionString(extension_->id()); |
| 454 | 459 |
| 455 if (client_ && (!allow_silent_install_ || !approved_)) { | 460 if (client_ && |
| 456 AddRef(); // Balanced in Proceed() and Abort(). | 461 (!allow_silent_install_ || !approved_) && |
| 462 !update_from_settings_page_) { |
| 463 AddRef(); // Balanced in InstallUIProceed() and InstallUIAbort(). |
| 457 client_->ConfirmInstall(this, extension_.get(), show_dialog_callback_); | 464 client_->ConfirmInstall(this, extension_.get(), show_dialog_callback_); |
| 458 } else { | 465 } else { |
| 459 if (!installer_task_runner_->PostTask( | 466 if (!installer_task_runner_->PostTask( |
| 460 FROM_HERE, | 467 FROM_HERE, |
| 461 base::Bind(&CrxInstaller::CompleteInstall, this))) | 468 base::Bind(&CrxInstaller::CompleteInstall, this))) |
| 462 NOTREACHED(); | 469 NOTREACHED(); |
| 463 } | 470 } |
| 464 return; | 471 return; |
| 465 } | 472 } |
| 466 | 473 |
| 467 void CrxInstaller::InstallUIProceed() { | 474 void CrxInstaller::InstallUIProceed() { |
| 468 if (!installer_task_runner_->PostTask( | 475 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 469 FROM_HERE, | |
| 470 base::Bind(&CrxInstaller::CompleteInstall, this))) | |
| 471 NOTREACHED(); | |
| 472 | 476 |
| 473 Release(); // balanced in ConfirmInstall(). | 477 if (!frontend_weak_.get() || frontend_weak_->browser_terminating()) |
| 478 return; |
| 479 |
| 480 // If update_from_settings_page_ boolean is true, this functions is |
| 481 // getting called in response to ExtensionInstallPrompt::ConfirmReEnable() |
| 482 // and if it is false, this function is called in response to |
| 483 // ExtensionInstallPrompt::ConfirmInstall(). |
| 484 if (update_from_settings_page_) { |
| 485 frontend_weak_->GrantPermissionsAndEnableExtension( |
| 486 extension_.get(), client_->record_oauth2_grant()); |
| 487 } else { |
| 488 if (!installer_task_runner_->PostTask( |
| 489 FROM_HERE, |
| 490 base::Bind(&CrxInstaller::CompleteInstall, this))) |
| 491 NOTREACHED(); |
| 492 } |
| 493 |
| 494 Release(); // balanced in ConfirmInstall() or ConfirmReEnable(). |
| 474 } | 495 } |
| 475 | 496 |
| 476 void CrxInstaller::InstallUIAbort(bool user_initiated) { | 497 void CrxInstaller::InstallUIAbort(bool user_initiated) { |
| 477 std::string histogram_name = user_initiated ? | 498 // If update_from_settings_page_ boolean is true, this functions is |
| 478 "Extensions.Permissions_InstallCancel" : | 499 // getting called in response to ExtensionInstallPrompt::ConfirmReEnable() |
| 479 "Extensions.Permissions_InstallAbort"; | 500 // and if it is false, this function is called in response to |
| 480 ExtensionService::RecordPermissionMessagesHistogram( | 501 // ExtensionInstallPrompt::ConfirmInstall(). |
| 481 extension_, histogram_name.c_str()); | 502 if (!update_from_settings_page_) { |
| 503 std::string histogram_name = user_initiated ? |
| 504 "Extensions.Permissions_InstallCancel" : |
| 505 "Extensions.Permissions_InstallAbort"; |
| 506 ExtensionService::RecordPermissionMessagesHistogram( |
| 507 extension_, histogram_name.c_str()); |
| 482 | 508 |
| 483 // Kill the theme loading bubble. | 509 // Kill the theme loading bubble. |
| 484 content::NotificationService* service = | 510 content::NotificationService* service = |
| 485 content::NotificationService::current(); | 511 content::NotificationService::current(); |
| 486 service->Notify(chrome::NOTIFICATION_NO_THEME_DETECTED, | 512 service->Notify(chrome::NOTIFICATION_NO_THEME_DETECTED, |
| 487 content::Source<CrxInstaller>(this), | 513 content::Source<CrxInstaller>(this), |
| 488 content::NotificationService::NoDetails()); | 514 content::NotificationService::NoDetails()); |
| 489 | 515 |
| 490 NotifyCrxInstallComplete(false); | 516 NotifyCrxInstallComplete(false); |
| 517 } |
| 491 | 518 |
| 492 Release(); // balanced in ConfirmInstall(). | 519 Release(); // balanced in ConfirmInstall() or ConfirmReEnable(). |
| 493 | 520 |
| 494 // We're done. Since we don't post any more tasks to ourself, our ref count | 521 // We're done. Since we don't post any more tasks to ourself, our ref count |
| 495 // should go to zero and we die. The destructor will clean up the temp dir. | 522 // should go to zero and we die. The destructor will clean up the temp dir. |
| 496 } | 523 } |
| 497 | 524 |
| 498 void CrxInstaller::CompleteInstall() { | 525 void CrxInstaller::CompleteInstall() { |
| 499 DCHECK(installer_task_runner_->RunsTasksOnCurrentThread()); | 526 DCHECK(installer_task_runner_->RunsTasksOnCurrentThread()); |
| 500 | 527 |
| 501 if (!current_version_.empty()) { | 528 if (!current_version_.empty()) { |
| 502 Version current_version(current_version_); | 529 Version current_version(current_version_); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 // Delete temporary files. | 631 // Delete temporary files. |
| 605 CleanupTempFiles(); | 632 CleanupTempFiles(); |
| 606 } | 633 } |
| 607 | 634 |
| 608 void CrxInstaller::ReportSuccessFromUIThread() { | 635 void CrxInstaller::ReportSuccessFromUIThread() { |
| 609 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 636 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 610 | 637 |
| 611 if (!frontend_weak_.get() || frontend_weak_->browser_terminating()) | 638 if (!frontend_weak_.get() || frontend_weak_->browser_terminating()) |
| 612 return; | 639 return; |
| 613 | 640 |
| 614 // If there is a client, tell the client about installation. | 641 if (!update_from_settings_page_) { |
| 615 if (client_) { | 642 // If there is a client, tell the client about installation. |
| 616 client_->OnInstallSuccess(extension_.get(), install_icon_.get()); | 643 if (client_) |
| 617 } | 644 client_->OnInstallSuccess(extension_.get(), install_icon_.get()); |
| 618 | 645 |
| 619 if (client_ && !approved_) | 646 if (client_ && !approved_) |
| 620 record_oauth2_grant_ = client_->record_oauth2_grant(); | 647 record_oauth2_grant_ = client_->record_oauth2_grant(); |
| 621 | 648 |
| 622 // We update the extension's granted permissions if the user already approved | 649 // We update the extension's granted permissions if the user already |
| 623 // the install (client_ is non NULL), or we are allowed to install this | 650 // approved the install (client_ is non NULL), or we are allowed to install |
| 624 // silently. | 651 // this silently. |
| 625 if (client_ || allow_silent_install_) { | 652 if (client_ || allow_silent_install_) { |
| 626 PermissionsUpdater perms_updater(profile()); | 653 PermissionsUpdater perms_updater(profile()); |
| 627 perms_updater.GrantActivePermissions(extension_, record_oauth2_grant_); | 654 perms_updater.GrantActivePermissions(extension_, record_oauth2_grant_); |
| 655 } |
| 628 } | 656 } |
| 629 | 657 |
| 630 // Install the extension if it's not blacklisted, but notify either way. | 658 // Install the extension if it's not blacklisted, but notify either way. |
| 631 base::Closure on_success = | 659 base::Closure on_success = |
| 632 base::Bind(&ExtensionService::OnExtensionInstalled, | 660 base::Bind(&ExtensionService::OnExtensionInstalled, |
| 633 frontend_weak_, | 661 frontend_weak_, |
| 634 extension_, | 662 extension_, |
| 635 page_ordinal_, | 663 page_ordinal_, |
| 636 has_requirement_errors_, | 664 has_requirement_errors_, |
| 637 install_wait_for_idle_); | 665 install_wait_for_idle_); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 667 // Some users (such as the download shelf) need to know when a | 695 // Some users (such as the download shelf) need to know when a |
| 668 // CRXInstaller is done. Listening for the EXTENSION_* events | 696 // CRXInstaller is done. Listening for the EXTENSION_* events |
| 669 // is problematic because they don't know anything about the | 697 // is problematic because they don't know anything about the |
| 670 // extension before it is unpacked, so they cannot filter based | 698 // extension before it is unpacked, so they cannot filter based |
| 671 // on the extension. | 699 // on the extension. |
| 672 content::NotificationService::current()->Notify( | 700 content::NotificationService::current()->Notify( |
| 673 chrome::NOTIFICATION_CRX_INSTALLER_DONE, | 701 chrome::NOTIFICATION_CRX_INSTALLER_DONE, |
| 674 content::Source<CrxInstaller>(this), | 702 content::Source<CrxInstaller>(this), |
| 675 content::Details<const Extension>(success ? extension_.get() : NULL)); | 703 content::Details<const Extension>(success ? extension_.get() : NULL)); |
| 676 | 704 |
| 677 // We're done. We don't post any more tasks to ourselves so we are deleted | 705 if (success) |
| 678 // soon. | 706 ConfirmReEnable(); |
| 679 extension_ = NULL; | 707 |
| 680 } | 708 } |
| 681 | 709 |
| 682 void CrxInstaller::CleanupTempFiles() { | 710 void CrxInstaller::CleanupTempFiles() { |
| 683 if (!installer_task_runner_->RunsTasksOnCurrentThread()) { | 711 if (!installer_task_runner_->RunsTasksOnCurrentThread()) { |
| 684 if (!installer_task_runner_->PostTask( | 712 if (!installer_task_runner_->PostTask( |
| 685 FROM_HERE, | 713 FROM_HERE, |
| 686 base::Bind(&CrxInstaller::CleanupTempFiles, this))) { | 714 base::Bind(&CrxInstaller::CleanupTempFiles, this))) { |
| 687 NOTREACHED(); | 715 NOTREACHED(); |
| 688 } | 716 } |
| 689 return; | 717 return; |
| 690 } | 718 } |
| 691 | 719 |
| 692 // Delete the temp directory and crx file as necessary. | 720 // Delete the temp directory and crx file as necessary. |
| 693 if (!temp_dir_.value().empty()) { | 721 if (!temp_dir_.value().empty()) { |
| 694 extension_file_util::DeleteFile(temp_dir_, true); | 722 extension_file_util::DeleteFile(temp_dir_, true); |
| 695 temp_dir_ = base::FilePath(); | 723 temp_dir_ = base::FilePath(); |
| 696 } | 724 } |
| 697 | 725 |
| 698 if (delete_source_ && !source_file_.value().empty()) { | 726 if (delete_source_ && !source_file_.value().empty()) { |
| 699 extension_file_util::DeleteFile(source_file_, false); | 727 extension_file_util::DeleteFile(source_file_, false); |
| 700 source_file_ = base::FilePath(); | 728 source_file_ = base::FilePath(); |
| 701 } | 729 } |
| 702 } | 730 } |
| 703 | 731 |
| 732 void CrxInstaller::CheckUpdateFromSettingsPage() { |
| 733 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 734 |
| 735 if (!frontend_weak_.get() || frontend_weak_->browser_terminating()) |
| 736 return; |
| 737 |
| 738 if (off_store_install_allow_reason_ != OffStoreInstallAllowedFromSettingsPage) |
| 739 return; |
| 740 |
| 741 const Extension* installed_extension = |
| 742 frontend_weak_->GetInstalledExtension(extension_->id()); |
| 743 if (installed_extension) { |
| 744 // Previous version of the extension exists. |
| 745 update_from_settings_page_ = true; |
| 746 expected_id_ = installed_extension->id(); |
| 747 install_source_ = installed_extension->location(); |
| 748 install_cause_ = extension_misc::INSTALL_CAUSE_UPDATE; |
| 749 } |
| 750 } |
| 751 |
| 752 void CrxInstaller::ConfirmReEnable() { |
| 753 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 754 |
| 755 if (!frontend_weak_.get() || frontend_weak_->browser_terminating()) |
| 756 return; |
| 757 |
| 758 if (!update_from_settings_page_) |
| 759 return; |
| 760 |
| 761 extensions::ExtensionPrefs* prefs = frontend_weak_->extension_prefs(); |
| 762 if (!prefs->DidExtensionEscalatePermissions(extension_->id())) |
| 763 return; |
| 764 |
| 765 if (client_) { |
| 766 AddRef(); // Balanced in InstallUIProceed() and InstallUIAbort(). |
| 767 client_->ConfirmReEnable(this, extension_.get()); |
| 768 } |
| 769 } |
| 770 |
| 704 } // namespace extensions | 771 } // namespace extensions |
| OLD | NEW |