Index: chrome/browser/extensions/api/webstore_private/webstore_private_api.cc |
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc |
index 86171d5283f1d6bcc34283862eb70b9e748d71df..66f8fa826f9104380f7d0285e124da550c9269d2 100644 |
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc |
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc |
@@ -19,6 +19,7 @@ |
#include "chrome/browser/extensions/install_tracker.h" |
#include "chrome/browser/gpu/gpu_feature_checker.h" |
#include "chrome/browser/profiles/profile.h" |
+#include "chrome/browser/safe_image_fetcher.h" |
#include "chrome/browser/signin/signin_manager_factory.h" |
#include "chrome/browser/ui/app_list/app_list_service.h" |
#include "chrome/browser/ui/app_list/app_list_util.h" |
@@ -31,6 +32,7 @@ |
#include "extensions/browser/extension_system.h" |
#include "extensions/browser/extension_util.h" |
#include "extensions/common/extension.h" |
+#include "url/gurl.h" |
namespace extensions { |
@@ -43,6 +45,7 @@ namespace GetEphemeralAppsEnabled = |
namespace GetIsLauncherEnabled = api::webstore_private::GetIsLauncherEnabled; |
namespace GetStoreLogin = api::webstore_private::GetStoreLogin; |
namespace GetWebGLStatus = api::webstore_private::GetWebGLStatus; |
+namespace InstallBundle = api::webstore_private::InstallBundle; |
namespace IsInIncognitoMode = api::webstore_private::IsInIncognitoMode; |
namespace LaunchEphemeralApp = api::webstore_private::LaunchEphemeralApp; |
namespace SetStoreLogin = api::webstore_private::SetStoreLogin; |
@@ -155,9 +158,12 @@ static base::LazyInstance<PendingApprovals> g_pending_approvals = |
// A preference set by the web store to indicate login information for |
// purchased apps. |
const char kWebstoreLogin[] = "extensions.webstore_login"; |
+ |
+// Error messages that can be returned by the API. |
const char kAlreadyInstalledError[] = "This item is already installed"; |
const char kCannotSpecifyIconDataAndUrlError[] = |
"You cannot specify both icon data and an icon url"; |
+const char kInvalidBundleError[] = "Invalid bundle"; |
const char kInvalidIconUrlError[] = "Invalid icon url"; |
const char kInvalidIdError[] = "Invalid id"; |
const char kInvalidManifestError[] = "Invalid manifest"; |
@@ -165,7 +171,7 @@ const char kNoPreviousBeginInstallWithManifestError[] = |
"* does not match a previous call to beginInstallWithManifest3"; |
const char kUserCancelledError[] = "User cancelled install"; |
-WebstoreInstaller::Delegate* test_webstore_installer_delegate = NULL; |
+WebstoreInstaller::Delegate* test_webstore_installer_delegate = nullptr; |
// We allow the web store to set a string containing login information when a |
// purchase is made, so that when a user logs into sync with a different |
@@ -266,7 +272,7 @@ WebstorePrivateFunctionWithPermissionPrompt<Params>::Run() { |
if (response) |
return RespondNow(response.Pass()); |
- net::URLRequestContextGetter* context_getter = NULL; |
+ net::URLRequestContextGetter* context_getter = nullptr; |
if (!icon_url.is_empty()) |
context_getter = browser_context()->GetRequestContext(); |
@@ -586,6 +592,102 @@ WebstorePrivateShowPermissionPromptForDelegatedInstallFunction::CreateResults( |
return ShowPermissionPromptForDelegatedInstall::Results::Create(result); |
} |
+WebstorePrivateInstallBundleFunction::WebstorePrivateInstallBundleFunction() |
+ : chrome_details_(this) { |
+} |
+ |
+WebstorePrivateInstallBundleFunction::~WebstorePrivateInstallBundleFunction() { |
+} |
+ |
+ExtensionFunction::ResponseAction WebstorePrivateInstallBundleFunction::Run() { |
+ params_ = InstallBundle::Params::Create(*args_); |
+ EXTENSION_FUNCTION_VALIDATE(params_); |
+ |
+ GURL icon_url; |
+ if (params_->details.icon_url) { |
+ icon_url = source_url().Resolve(*params_->details.icon_url); |
asargent_no_longer_on_chrome
2015/03/26 18:12:50
FYI, I think the icon_url we're passed is probably
Marc Treib
2015/03/27 11:52:12
Acknowledged.
|
+ if (!icon_url.is_valid()) |
+ return RespondNow(Error(kInvalidIconUrlError)); |
+ } |
+ |
+ if (params_->contents.empty()) |
+ return RespondNow(Error(kInvalidBundleError)); |
+ |
+ // The image fetcher will call us back via OnIconFetched. |
+ icon_fetcher_.reset(new SafeImageFetcher( |
+ icon_url, browser_context()->GetRequestContext(), |
+ base::Bind(&WebstorePrivateInstallBundleFunction::OnIconFetched, |
+ base::Unretained(this)))); |
+ |
+ // Matched with a Release in OnIconFetched, OnInstallApproval, or |
+ // OnInstallComplete. |
+ AddRef(); |
asargent_no_longer_on_chrome
2015/03/26 18:12:50
Instead of doing manual AddRef/Release calls and u
Marc Treib
2015/03/27 11:52:12
Indeed, that's much nicer, thanks! Done.
|
+ |
+ // The response is sent asynchronously in OnIconFetched, OnInstallApproval, or |
+ // OnInstallComplete. |
+ return RespondLater(); |
+} |
+ |
+void WebstorePrivateInstallBundleFunction::OnIconFetched(const SkBitmap& icon) { |
+ InstallTracker* tracker = InstallTracker::Get(browser_context()); |
+ DCHECK(tracker); |
+ |
+ std::string authuser; |
+ if (params_->details.authuser) |
+ authuser = *params_->details.authuser; |
+ |
+ BundleInstaller::ItemList items; |
+ for (const auto& entry : params_->contents) { |
+ // Skip already-installed items. |
+ if (util::IsExtensionInstalledPermanently(entry->id, browser_context()) || |
+ tracker->GetActiveInstall(entry->id)) { |
+ continue; |
+ } |
+ BundleInstaller::Item item; |
+ item.id = entry->id; |
+ item.manifest = entry->manifest; |
+ item.localized_name = entry->localized_name; |
+ if (entry->icon_url) |
+ item.icon_url = source_url().Resolve(*entry->icon_url); |
+ items.push_back(item); |
+ } |
+ if (items.empty()) { |
+ Respond(Error(kAlreadyInstalledError)); |
+ Release(); |
+ return; |
+ } |
+ bundle_.reset(new BundleInstaller(chrome_details_.GetCurrentBrowser(), |
+ params_->details.localized_name, |
+ icon, authuser, items)); |
+ |
+ // The bundle installer will call us back via OnInstallApproval. |
+ bundle_->PromptForApproval( |
+ base::Bind(&WebstorePrivateInstallBundleFunction::OnInstallApproval, |
+ base::Unretained(this))); |
+} |
+ |
+void WebstorePrivateInstallBundleFunction::OnInstallApproval( |
+ BundleInstaller::ApprovalState state) { |
+ if (state != BundleInstaller::APPROVED) { |
+ Respond(Error(state == BundleInstaller::USER_CANCELED |
+ ? kUserCancelledError |
+ : kInvalidBundleError)); |
+ Release(); |
+ return; |
+ } |
+ |
+ // The bundle installer will call us back via OnInstallComplete. |
+ bundle_->CompleteInstall( |
+ chrome_details_.GetAssociatedWebContents(), |
+ base::Bind(&WebstorePrivateInstallBundleFunction::OnInstallComplete, |
+ base::Unretained(this))); |
+} |
+ |
+void WebstorePrivateInstallBundleFunction::OnInstallComplete() { |
+ Respond(NoArguments()); |
+ Release(); |
+} |
+ |
WebstorePrivateEnableAppLauncherFunction:: |
WebstorePrivateEnableAppLauncherFunction() : chrome_details_(this) {} |