| Index: chrome/browser/extensions/webstore_standalone_installer.cc
|
| diff --git a/chrome/browser/extensions/webstore_standalone_installer.cc b/chrome/browser/extensions/webstore_standalone_installer.cc
|
| index 793309709659dba81eefff29b9a875d56e79854e..4f42f01b221312bc01654531b520157d9c2244e0 100644
|
| --- a/chrome/browser/extensions/webstore_standalone_installer.cc
|
| +++ b/chrome/browser/extensions/webstore_standalone_installer.cc
|
| @@ -5,6 +5,7 @@
|
| #include "chrome/browser/extensions/webstore_standalone_installer.h"
|
|
|
| #include "base/values.h"
|
| +#include "base/version.h"
|
| #include "chrome/browser/extensions/crx_installer.h"
|
| #include "chrome/browser/extensions/extension_install_prompt.h"
|
| #include "chrome/browser/extensions/extension_install_ui.h"
|
| @@ -44,12 +45,6 @@ WebstoreStandaloneInstaller::WebstoreStandaloneInstaller(
|
| rating_count_(0) {
|
| }
|
|
|
| -WebstoreStandaloneInstaller::~WebstoreStandaloneInstaller() {}
|
| -
|
| -//
|
| -// Private interface implementation.
|
| -//
|
| -
|
| void WebstoreStandaloneInstaller::BeginInstall() {
|
| // Add a ref to keep this alive for WebstoreDataFetcher.
|
| // All code paths from here eventually lead to either CompleteInstall or
|
| @@ -57,7 +52,7 @@ void WebstoreStandaloneInstaller::BeginInstall() {
|
| AddRef();
|
|
|
| if (!Extension::IdIsValid(id_)) {
|
| - CompleteInstall(kInvalidWebstoreItemId);
|
| + CompleteInstall(webstore_install::INVALID_ID, kInvalidWebstoreItemId);
|
| return;
|
| }
|
|
|
| @@ -72,10 +67,62 @@ void WebstoreStandaloneInstaller::BeginInstall() {
|
| webstore_data_fetcher_->Start();
|
| }
|
|
|
| -bool WebstoreStandaloneInstaller::CheckInstallValid(
|
| - const base::DictionaryValue& manifest,
|
| - std::string* error) {
|
| - return true;
|
| +//
|
| +// Private interface implementation.
|
| +//
|
| +
|
| +WebstoreStandaloneInstaller::~WebstoreStandaloneInstaller() {
|
| +}
|
| +
|
| +void WebstoreStandaloneInstaller::AbortInstall() {
|
| + callback_.Reset();
|
| + // Abort any in-progress fetches.
|
| + if (webstore_data_fetcher_) {
|
| + webstore_data_fetcher_.reset();
|
| + Release(); // Matches the AddRef in BeginInstall.
|
| + }
|
| +}
|
| +
|
| +void WebstoreStandaloneInstaller::CompleteInstall(
|
| + webstore_install::Result result,
|
| + const std::string& error) {
|
| + if (!callback_.is_null())
|
| + callback_.Run(result == webstore_install::SUCCESS, error);
|
| + Release(); // Matches the AddRef in BeginInstall.
|
| +}
|
| +
|
| +void WebstoreStandaloneInstaller::ProceedWithInstallPrompt() {
|
| + install_prompt_ = CreateInstallPrompt();
|
| + if (install_prompt_) {
|
| + ShowInstallUI();
|
| + // Control flow finishes up in InstallUIProceed or InstallUIAbort.
|
| + } else {
|
| + InstallUIProceed();
|
| + }
|
| +}
|
| +
|
| +scoped_refptr<const Extension>
|
| +WebstoreStandaloneInstaller::GetLocalizedExtensionForDisplay() {
|
| + if (!localized_extension_for_display_.get()) {
|
| + DCHECK(manifest_.get());
|
| + if (!manifest_.get())
|
| + return NULL;
|
| +
|
| + std::string error;
|
| + localized_extension_for_display_ =
|
| + ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
|
| + manifest_.get(),
|
| + Extension::REQUIRE_KEY | Extension::FROM_WEBSTORE,
|
| + id_,
|
| + localized_name_,
|
| + localized_description_,
|
| + &error);
|
| + }
|
| + return localized_extension_for_display_.get();
|
| +}
|
| +
|
| +void WebstoreStandaloneInstaller::OnManifestParsed() {
|
| + ProceedWithInstallPrompt();
|
| }
|
|
|
| scoped_ptr<ExtensionInstallPrompt>
|
| @@ -99,7 +146,8 @@ WebstoreStandaloneInstaller::CreateApproval() const {
|
|
|
| void WebstoreStandaloneInstaller::OnWebstoreRequestFailure() {
|
| OnWebStoreDataFetcherDone();
|
| - CompleteInstall(kWebstoreRequestError);
|
| + CompleteInstall(webstore_install::WEBSTORE_REQUEST_ERROR,
|
| + kWebstoreRequestError);
|
| }
|
|
|
| void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess(
|
| @@ -107,19 +155,19 @@ void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess(
|
| OnWebStoreDataFetcherDone();
|
|
|
| if (!CheckRequestorAlive()) {
|
| - CompleteInstall(std::string());
|
| + CompleteInstall(webstore_install::ABORTED, std::string());
|
| return;
|
| }
|
|
|
| std::string error;
|
|
|
| if (!CheckInlineInstallPermitted(*webstore_data, &error)) {
|
| - CompleteInstall(error);
|
| + CompleteInstall(webstore_install::NOT_PERMITTED, error);
|
| return;
|
| }
|
|
|
| if (!CheckRequestorPermitted(*webstore_data, &error)) {
|
| - CompleteInstall(error);
|
| + CompleteInstall(webstore_install::NOT_PERMITTED, error);
|
| return;
|
| }
|
|
|
| @@ -129,7 +177,8 @@ void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess(
|
| !webstore_data->GetString(kUsersKey, &localized_user_count_) ||
|
| !webstore_data->GetDouble(kAverageRatingKey, &average_rating_) ||
|
| !webstore_data->GetInteger(kRatingCountKey, &rating_count_)) {
|
| - CompleteInstall(kInvalidWebstoreResponseError);
|
| + CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
|
| + kInvalidWebstoreResponseError);
|
| return;
|
| }
|
|
|
| @@ -139,7 +188,8 @@ void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess(
|
|
|
| if (average_rating_ < ExtensionInstallPrompt::kMinExtensionRating ||
|
| average_rating_ > ExtensionInstallPrompt::kMaxExtensionRating) {
|
| - CompleteInstall(kInvalidWebstoreResponseError);
|
| + CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
|
| + kInvalidWebstoreResponseError);
|
| return;
|
| }
|
|
|
| @@ -149,7 +199,8 @@ void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess(
|
| (webstore_data->HasKey(kLocalizedDescriptionKey) &&
|
| !webstore_data->GetString(
|
| kLocalizedDescriptionKey, &localized_description_))) {
|
| - CompleteInstall(kInvalidWebstoreResponseError);
|
| + CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
|
| + kInvalidWebstoreResponseError);
|
| return;
|
| }
|
|
|
| @@ -158,13 +209,15 @@ void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess(
|
| if (webstore_data->HasKey(kIconUrlKey)) {
|
| std::string icon_url_string;
|
| if (!webstore_data->GetString(kIconUrlKey, &icon_url_string)) {
|
| - CompleteInstall(kInvalidWebstoreResponseError);
|
| + CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
|
| + kInvalidWebstoreResponseError);
|
| return;
|
| }
|
| icon_url = GURL(extension_urls::GetWebstoreLaunchURL()).Resolve(
|
| icon_url_string);
|
| if (!icon_url.is_valid()) {
|
| - CompleteInstall(kInvalidWebstoreResponseError);
|
| + CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
|
| + kInvalidWebstoreResponseError);
|
| return;
|
| }
|
| }
|
| @@ -187,7 +240,7 @@ void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess(
|
| void WebstoreStandaloneInstaller::OnWebstoreResponseParseFailure(
|
| const std::string& error) {
|
| OnWebStoreDataFetcherDone();
|
| - CompleteInstall(error);
|
| + CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE, error);
|
| }
|
|
|
| void WebstoreStandaloneInstaller::OnWebstoreParseSuccess(
|
| @@ -197,39 +250,38 @@ void WebstoreStandaloneInstaller::OnWebstoreParseSuccess(
|
| CHECK_EQ(id_, id);
|
|
|
| if (!CheckRequestorAlive()) {
|
| - CompleteInstall(std::string());
|
| + CompleteInstall(webstore_install::ABORTED, std::string());
|
| return;
|
| }
|
|
|
| manifest_.reset(manifest);
|
| icon_ = icon;
|
|
|
| - std::string error;
|
| - if (!CheckInstallValid(*manifest, &error)) {
|
| - DCHECK(!error.empty());
|
| - CompleteInstall(error);
|
| - return;
|
| - }
|
| -
|
| - install_prompt_ = CreateInstallPrompt();
|
| - if (install_prompt_) {
|
| - ShowInstallUI();
|
| - // Control flow finishes up in InstallUIProceed or InstallUIAbort.
|
| - } else {
|
| - InstallUIProceed();
|
| - }
|
| + OnManifestParsed();
|
| }
|
|
|
| void WebstoreStandaloneInstaller::OnWebstoreParseFailure(
|
| const std::string& id,
|
| InstallHelperResultCode result_code,
|
| const std::string& error_message) {
|
| - CompleteInstall(error_message);
|
| + webstore_install::Result install_result = webstore_install::UNKNOWN_ERROR;
|
| + switch (result_code) {
|
| + case WebstoreInstallHelper::Delegate::MANIFEST_ERROR:
|
| + install_result = webstore_install::INVALID_MANIFEST;
|
| + break;
|
| + case WebstoreInstallHelper::Delegate::ICON_ERROR:
|
| + install_result = webstore_install::ICON_ERROR;
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| +
|
| + CompleteInstall(install_result, error_message);
|
| }
|
|
|
| void WebstoreStandaloneInstaller::InstallUIProceed() {
|
| if (!CheckRequestorAlive()) {
|
| - CompleteInstall(std::string());
|
| + CompleteInstall(webstore_install::ABORTED, std::string());
|
| return;
|
| }
|
|
|
| @@ -237,28 +289,47 @@ void WebstoreStandaloneInstaller::InstallUIProceed() {
|
|
|
| ExtensionService* extension_service =
|
| ExtensionSystem::Get(profile_)->extension_service();
|
| - const Extension* extension =
|
| + const Extension* installed_extension =
|
| extension_service->GetExtensionById(id_, true /* include disabled */);
|
| - if (extension) {
|
| - std::string install_result; // Empty string for install success.
|
| + if (installed_extension) {
|
| + std::string install_message;
|
| + webstore_install::Result install_result = webstore_install::SUCCESS;
|
| + bool done = true;
|
|
|
| if (ExtensionPrefs::Get(profile_)->IsExtensionBlacklisted(id_)) {
|
| // Don't install a blacklisted extension.
|
| - install_result = kExtensionIsBlacklisted;
|
| - } else if (util::IsEphemeralApp(extension->id(), profile_) &&
|
| + install_result = webstore_install::BLACKLISTED;
|
| + install_message = kExtensionIsBlacklisted;
|
| + } else if (util::IsEphemeralApp(installed_extension->id(), profile_) &&
|
| !approval->is_ephemeral) {
|
| - // If the target extension has already been installed ephemerally, it can
|
| - // be promoted to a regular installed extension and downloading from the
|
| - // Web Store is not necessary.
|
| - extension_service->PromoteEphemeralApp(extension, false);
|
| + // If the target extension has already been installed ephemerally and is
|
| + // up to date, it can be promoted to a regular installed extension and
|
| + // downloading from the Web Store is not necessary.
|
| + const Extension* extension_to_install = GetLocalizedExtensionForDisplay();
|
| + if (!extension_to_install) {
|
| + CompleteInstall(webstore_install::INVALID_MANIFEST,
|
| + kInvalidManifestError);
|
| + return;
|
| + }
|
| +
|
| + if (installed_extension->version()->CompareTo(
|
| + *extension_to_install->version()) < 0) {
|
| + // If the existing extension is out of date, proceed with the install
|
| + // to update the extension.
|
| + done = false;
|
| + } else {
|
| + extension_service->PromoteEphemeralApp(installed_extension, false);
|
| + }
|
| } else if (!extension_service->IsExtensionEnabled(id_)) {
|
| // If the extension is installed but disabled, and not blacklisted,
|
| // enable it.
|
| extension_service->EnableExtension(id_);
|
| } // else extension is installed and enabled; no work to be done.
|
|
|
| - CompleteInstall(install_result);
|
| - return;
|
| + if (done) {
|
| + CompleteInstall(install_result, install_message);
|
| + return;
|
| + }
|
| }
|
|
|
| scoped_refptr<WebstoreInstaller> installer = new WebstoreInstaller(
|
| @@ -272,60 +343,47 @@ void WebstoreStandaloneInstaller::InstallUIProceed() {
|
| }
|
|
|
| void WebstoreStandaloneInstaller::InstallUIAbort(bool user_initiated) {
|
| - CompleteInstall(kUserCancelledError);
|
| + CompleteInstall(webstore_install::USER_CANCELLED, kUserCancelledError);
|
| }
|
|
|
| void WebstoreStandaloneInstaller::OnExtensionInstallSuccess(
|
| const std::string& id) {
|
| CHECK_EQ(id_, id);
|
| - CompleteInstall(std::string());
|
| + CompleteInstall(webstore_install::SUCCESS, std::string());
|
| }
|
|
|
| void WebstoreStandaloneInstaller::OnExtensionInstallFailure(
|
| const std::string& id,
|
| const std::string& error,
|
| - WebstoreInstaller::FailureReason cancelled) {
|
| + WebstoreInstaller::FailureReason reason) {
|
| CHECK_EQ(id_, id);
|
| - CompleteInstall(error);
|
| -}
|
|
|
| -void WebstoreStandaloneInstaller::AbortInstall() {
|
| - callback_.Reset();
|
| - // Abort any in-progress fetches.
|
| - if (webstore_data_fetcher_) {
|
| - webstore_data_fetcher_.reset();
|
| - Release(); // Matches the AddRef in BeginInstall.
|
| + webstore_install::Result install_result = webstore_install::UNKNOWN_ERROR;
|
| + switch (reason) {
|
| + case WebstoreInstaller::FAILURE_REASON_CANCELLED:
|
| + install_result = webstore_install::USER_CANCELLED;
|
| + break;
|
| + case WebstoreInstaller::FAILURE_REASON_DEPENDENCY_NOT_FOUND:
|
| + case WebstoreInstaller::FAILURE_REASON_DEPENDENCY_NOT_SHARED_MODULE:
|
| + install_result = webstore_install::MISSING_DEPENDENCIES;
|
| + break;
|
| + default:
|
| + break;
|
| }
|
| -}
|
| -
|
| -void WebstoreStandaloneInstaller::InvokeCallback(const std::string& error) {
|
| - if (!callback_.is_null())
|
| - callback_.Run(error.empty(), error);
|
| -}
|
|
|
| -void WebstoreStandaloneInstaller::CompleteInstall(const std::string& error) {
|
| - InvokeCallback(error);
|
| - Release(); // Matches the AddRef in BeginInstall.
|
| + CompleteInstall(install_result, error);
|
| }
|
|
|
| void WebstoreStandaloneInstaller::ShowInstallUI() {
|
| - std::string error;
|
| - localized_extension_for_display_ =
|
| - ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
|
| - manifest_.get(),
|
| - Extension::REQUIRE_KEY | Extension::FROM_WEBSTORE,
|
| - id_,
|
| - localized_name_,
|
| - localized_description_,
|
| - &error);
|
| - if (!localized_extension_for_display_.get()) {
|
| - CompleteInstall(kInvalidManifestError);
|
| + const Extension* localized_extension = GetLocalizedExtensionForDisplay();
|
| + if (!localized_extension) {
|
| + CompleteInstall(webstore_install::INVALID_MANIFEST, kInvalidManifestError);
|
| return;
|
| }
|
|
|
| install_ui_ = CreateInstallUI();
|
| install_ui_->ConfirmStandaloneInstall(
|
| - this, localized_extension_for_display_.get(), &icon_, install_prompt_);
|
| + this, localized_extension, &icon_, install_prompt_);
|
| }
|
|
|
| void WebstoreStandaloneInstaller::OnWebStoreDataFetcherDone() {
|
|
|