Chromium Code Reviews| 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 ae40c9cc1e24dee113f5f0317779ba0fbdfc1558..3e0eca428fd4dbae68899670e405506a9d3466f4 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(INSTALL_INVALID_ID, kInvalidWebstoreItemId); |
| return; |
| } |
| @@ -72,10 +67,61 @@ 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(InstallResult result, |
| + const std::string& error) { |
| + if (!callback_.is_null()) |
| + callback_.Run(result == 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 +145,7 @@ WebstoreStandaloneInstaller::CreateApproval() const { |
| void WebstoreStandaloneInstaller::OnWebstoreRequestFailure() { |
| OnWebStoreDataFetcherDone(); |
| - CompleteInstall(kWebstoreRequestError); |
| + CompleteInstall(INSTALL_WEBSTORE_REQUEST_ERROR, kWebstoreRequestError); |
| } |
| void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess( |
| @@ -107,19 +153,19 @@ void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess( |
| OnWebStoreDataFetcherDone(); |
| if (!CheckRequestorAlive()) { |
| - CompleteInstall(std::string()); |
| + CompleteInstall(INSTALL_ABORTED, std::string()); |
| return; |
| } |
| std::string error; |
| if (!CheckInlineInstallPermitted(*webstore_data, &error)) { |
| - CompleteInstall(error); |
| + CompleteInstall(INSTALL_NOT_PERMITTED, error); |
| return; |
| } |
| if (!CheckRequestorPermitted(*webstore_data, &error)) { |
| - CompleteInstall(error); |
| + CompleteInstall(INSTALL_NOT_PERMITTED, error); |
| return; |
| } |
| @@ -129,7 +175,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(INSTALL_INVALID_WEBSTORE_RESPONSE, |
| + kInvalidWebstoreResponseError); |
| return; |
| } |
| @@ -139,7 +186,8 @@ void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess( |
| if (average_rating_ < ExtensionInstallPrompt::kMinExtensionRating || |
| average_rating_ > ExtensionInstallPrompt::kMaxExtensionRating) { |
| - CompleteInstall(kInvalidWebstoreResponseError); |
| + CompleteInstall(INSTALL_INVALID_WEBSTORE_RESPONSE, |
| + kInvalidWebstoreResponseError); |
| return; |
| } |
| @@ -149,7 +197,8 @@ void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess( |
| (webstore_data->HasKey(kLocalizedDescriptionKey) && |
| !webstore_data->GetString( |
| kLocalizedDescriptionKey, &localized_description_))) { |
| - CompleteInstall(kInvalidWebstoreResponseError); |
| + CompleteInstall(INSTALL_INVALID_WEBSTORE_RESPONSE, |
| + kInvalidWebstoreResponseError); |
| return; |
| } |
| @@ -158,13 +207,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(INSTALL_INVALID_WEBSTORE_RESPONSE, |
| + kInvalidWebstoreResponseError); |
| return; |
| } |
| icon_url = GURL(extension_urls::GetWebstoreLaunchURL()).Resolve( |
| icon_url_string); |
| if (!icon_url.is_valid()) { |
| - CompleteInstall(kInvalidWebstoreResponseError); |
| + CompleteInstall(INSTALL_INVALID_WEBSTORE_RESPONSE, |
| + kInvalidWebstoreResponseError); |
| return; |
| } |
| } |
| @@ -187,7 +238,7 @@ void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess( |
| void WebstoreStandaloneInstaller::OnWebstoreResponseParseFailure( |
| const std::string& error) { |
| OnWebStoreDataFetcherDone(); |
| - CompleteInstall(error); |
| + CompleteInstall(INSTALL_INVALID_WEBSTORE_RESPONSE, error); |
| } |
| void WebstoreStandaloneInstaller::OnWebstoreParseSuccess( |
| @@ -197,39 +248,38 @@ void WebstoreStandaloneInstaller::OnWebstoreParseSuccess( |
| CHECK_EQ(id_, id); |
| if (!CheckRequestorAlive()) { |
| - CompleteInstall(std::string()); |
| + CompleteInstall(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); |
| + InstallResult install_result = INSTALL_UNKNOWN_ERROR; |
| + switch (result_code) { |
| + case WebstoreInstallHelper::Delegate::MANIFEST_ERROR: |
| + install_result = INSTALL_INVALID_MANIFEST; |
| + break; |
| + case WebstoreInstallHelper::Delegate::ICON_ERROR: |
| + install_result = INSTALL_ICON_ERROR; |
| + break; |
| + default: |
| + break; |
| + } |
| + |
| + CompleteInstall(install_result, error_message); |
| } |
| void WebstoreStandaloneInstaller::InstallUIProceed() { |
| if (!CheckRequestorAlive()) { |
| - CompleteInstall(std::string()); |
| + CompleteInstall(INSTALL_ABORTED, std::string()); |
| return; |
| } |
| @@ -237,28 +287,46 @@ 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; |
| + InstallResult install_result = 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 = INSTALL_BLACKLISTED; |
| + install_message = kExtensionIsBlacklisted; |
| + } else if (util::IsEphemeralApp(installed_extension->id(), profile_) && |
| !approval->is_ephemeral) { |
|
asargent_no_longer_on_chrome
2014/06/18 20:25:10
Something to think about for a future refactoring
tmdiep
2014/06/18 22:28:34
This is actually not specific to the EphemeralAppL
asargent_no_longer_on_chrome
2014/06/19 00:16:43
Ah, ok, that makes sense.
|
| - // 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(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 +340,47 @@ void WebstoreStandaloneInstaller::InstallUIProceed() { |
| } |
| void WebstoreStandaloneInstaller::InstallUIAbort(bool user_initiated) { |
| - CompleteInstall(kUserCancelledError); |
| + CompleteInstall(INSTALL_USER_CANCELLED, kUserCancelledError); |
| } |
| void WebstoreStandaloneInstaller::OnExtensionInstallSuccess( |
| const std::string& id) { |
| CHECK_EQ(id_, id); |
| - CompleteInstall(std::string()); |
| + CompleteInstall(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. |
| + InstallResult install_result = INSTALL_UNKNOWN_ERROR; |
| + switch (reason) { |
| + case WebstoreInstaller::FAILURE_REASON_CANCELLED: |
| + install_result = INSTALL_USER_CANCELLED; |
| + break; |
| + case WebstoreInstaller::FAILURE_REASON_DEPENDENCY_NOT_FOUND: |
| + case WebstoreInstaller::FAILURE_REASON_DEPENDENCY_NOT_SHARED_MODULE: |
| + install_result = 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(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() { |