Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / extensions / api / dashboard_private / dashboard_private_api.cc
blob87fb551264a69d4de9536a49e24ce7e4139a8ee4
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/dashboard_private/dashboard_private_api.h"
7 #include "base/bind.h"
8 #include "base/thread_task_runner_handle.h"
9 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "components/crx_file/id_util.h"
12 #include "extensions/common/extension.h"
13 #include "net/base/load_flags.h"
14 #include "net/url_request/url_request.h"
15 #include "url/gurl.h"
17 namespace extensions {
19 namespace ShowPermissionPromptForDelegatedInstall =
20 api::dashboard_private::ShowPermissionPromptForDelegatedInstall;
21 namespace ShowPermissionPromptForDelegatedBundleInstall =
22 api::dashboard_private::ShowPermissionPromptForDelegatedBundleInstall;
24 namespace {
26 // Error messages that can be returned by the API.
27 const char kAlreadyInstalledError[] = "This item is already installed";
28 const char kCannotSpecifyIconDataAndUrlError[] =
29 "You cannot specify both icon data and an icon url";
30 const char kInvalidBundleError[] = "Invalid bundle";
31 const char kInvalidIconUrlError[] = "Invalid icon url";
32 const char kInvalidIdError[] = "Invalid id";
33 const char kInvalidManifestError[] = "Invalid manifest";
34 const char kUserCancelledError[] = "User cancelled install";
36 api::dashboard_private::Result WebstoreInstallHelperResultToApiResult(
37 WebstoreInstallHelper::Delegate::InstallHelperResultCode result) {
38 switch (result) {
39 case WebstoreInstallHelper::Delegate::UNKNOWN_ERROR:
40 return api::dashboard_private::RESULT_UNKNOWN_ERROR;
41 case WebstoreInstallHelper::Delegate::ICON_ERROR:
42 return api::dashboard_private::RESULT_ICON_ERROR;
43 case WebstoreInstallHelper::Delegate::MANIFEST_ERROR:
44 return api::dashboard_private::RESULT_MANIFEST_ERROR;
46 NOTREACHED();
47 return api::dashboard_private::RESULT_NONE;
50 } // namespace
52 DashboardPrivateShowPermissionPromptForDelegatedInstallFunction::
53 DashboardPrivateShowPermissionPromptForDelegatedInstallFunction() {
56 DashboardPrivateShowPermissionPromptForDelegatedInstallFunction::
57 ~DashboardPrivateShowPermissionPromptForDelegatedInstallFunction() {
60 ExtensionFunction::ResponseAction
61 DashboardPrivateShowPermissionPromptForDelegatedInstallFunction::Run() {
62 params_ = Params::Create(*args_);
63 EXTENSION_FUNCTION_VALIDATE(params_);
65 if (!crx_file::id_util::IdIsValid(params_->details.id)) {
66 return RespondNow(BuildResponse(api::dashboard_private::RESULT_INVALID_ID,
67 kInvalidIdError));
70 if (params_->details.icon_data && params_->details.icon_url) {
71 return RespondNow(BuildResponse(api::dashboard_private::RESULT_ICON_ERROR,
72 kCannotSpecifyIconDataAndUrlError));
75 GURL icon_url;
76 if (params_->details.icon_url) {
77 icon_url = source_url().Resolve(*params_->details.icon_url);
78 if (!icon_url.is_valid()) {
79 return RespondNow(BuildResponse(
80 api::dashboard_private::RESULT_INVALID_ICON_URL,
81 kInvalidIconUrlError));
85 net::URLRequestContextGetter* context_getter = nullptr;
86 if (!icon_url.is_empty())
87 context_getter = browser_context()->GetRequestContext();
89 scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper(
90 this, params_->details.id, params_->details.manifest, icon_url,
91 context_getter);
93 // The helper will call us back via OnWebstoreParseSuccess or
94 // OnWebstoreParseFailure.
95 helper->Start();
97 // Matched with a Release in OnWebstoreParseSuccess/OnWebstoreParseFailure.
98 AddRef();
100 // The response is sent asynchronously in OnWebstoreParseSuccess/
101 // OnWebstoreParseFailure.
102 return RespondLater();
105 void DashboardPrivateShowPermissionPromptForDelegatedInstallFunction::
106 OnWebstoreParseSuccess(
107 const std::string& id,
108 const SkBitmap& icon,
109 base::DictionaryValue* parsed_manifest) {
110 CHECK_EQ(params_->details.id, id);
111 CHECK(parsed_manifest);
113 std::string localized_name = params_->details.localized_name ?
114 *params_->details.localized_name : std::string();
116 std::string error;
117 dummy_extension_ = ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
118 parsed_manifest,
119 Extension::FROM_WEBSTORE,
121 localized_name,
122 std::string(),
123 &error);
125 if (!dummy_extension_.get()) {
126 OnWebstoreParseFailure(params_->details.id,
127 WebstoreInstallHelper::Delegate::MANIFEST_ERROR,
128 kInvalidManifestError);
129 return;
132 content::WebContents* web_contents = GetAssociatedWebContents();
133 if (!web_contents) {
134 // The browser window has gone away.
135 Respond(BuildResponse(api::dashboard_private::RESULT_USER_CANCELLED,
136 kUserCancelledError));
137 // Matches the AddRef in Run().
138 Release();
139 return;
141 install_prompt_.reset(new ExtensionInstallPrompt(web_contents));
142 install_prompt_->ConfirmPermissionsForDelegatedInstall(
143 this, dummy_extension_.get(), details().delegated_user, &icon);
144 // Control flow finishes up in InstallUIProceed or InstallUIAbort.
147 void DashboardPrivateShowPermissionPromptForDelegatedInstallFunction::
148 OnWebstoreParseFailure(
149 const std::string& id,
150 WebstoreInstallHelper::Delegate::InstallHelperResultCode result,
151 const std::string& error_message) {
152 CHECK_EQ(params_->details.id, id);
154 Respond(BuildResponse(WebstoreInstallHelperResultToApiResult(result),
155 error_message));
157 // Matches the AddRef in Run().
158 Release();
161 void DashboardPrivateShowPermissionPromptForDelegatedInstallFunction::
162 InstallUIProceed() {
163 Respond(BuildResponse(api::dashboard_private::RESULT_SUCCESS, std::string()));
165 // Matches the AddRef in Run().
166 Release();
169 void DashboardPrivateShowPermissionPromptForDelegatedInstallFunction::
170 InstallUIAbort(bool user_initiated) {
171 Respond(BuildResponse(api::dashboard_private::RESULT_USER_CANCELLED,
172 kUserCancelledError));
174 // Matches the AddRef in Run().
175 Release();
178 ExtensionFunction::ResponseValue
179 DashboardPrivateShowPermissionPromptForDelegatedInstallFunction::BuildResponse(
180 api::dashboard_private::Result result, const std::string& error) {
181 if (result != api::dashboard_private::RESULT_SUCCESS)
182 return ErrorWithArguments(CreateResults(result), error);
184 // The web store expects an empty string on success, so don't use
185 // RESULT_SUCCESS here.
186 return ArgumentList(
187 CreateResults(api::dashboard_private::RESULT_EMPTY_STRING));
190 scoped_ptr<base::ListValue>
191 DashboardPrivateShowPermissionPromptForDelegatedInstallFunction::CreateResults(
192 api::dashboard_private::Result result) const {
193 return ShowPermissionPromptForDelegatedInstall::Results::Create(result);
196 DashboardPrivateShowPermissionPromptForDelegatedBundleInstallFunction::
197 DashboardPrivateShowPermissionPromptForDelegatedBundleInstallFunction()
198 : chrome_details_(this) {
201 DashboardPrivateShowPermissionPromptForDelegatedBundleInstallFunction::
202 ~DashboardPrivateShowPermissionPromptForDelegatedBundleInstallFunction() {
205 ExtensionFunction::ResponseAction
206 DashboardPrivateShowPermissionPromptForDelegatedBundleInstallFunction::Run() {
207 params_ = Params::Create(*args_);
208 EXTENSION_FUNCTION_VALIDATE(params_);
210 if (params_->contents.empty())
211 return RespondNow(Error(kInvalidBundleError));
213 if (params_->details.icon_url) {
214 GURL icon_url = source_url().Resolve(*params_->details.icon_url);
215 if (!icon_url.is_valid())
216 return RespondNow(Error(kInvalidIconUrlError));
218 // The bitmap fetcher will call us back via OnFetchComplete.
219 icon_fetcher_.reset(new chrome::BitmapFetcher(icon_url, this));
220 icon_fetcher_->Init(
221 browser_context()->GetRequestContext(), std::string(),
222 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
223 net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES);
224 icon_fetcher_->Start();
225 } else {
226 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(
227 &DashboardPrivateShowPermissionPromptForDelegatedBundleInstallFunction::
228 OnFetchComplete,
229 this, GURL(), nullptr));
232 AddRef(); // Balanced in OnFetchComplete.
234 // The response is sent in OnFetchComplete or OnInstallApproval.
235 return RespondLater();
238 void DashboardPrivateShowPermissionPromptForDelegatedBundleInstallFunction::
239 OnFetchComplete(const GURL& url, const SkBitmap* bitmap) {
240 BundleInstaller::ItemList items;
241 for (const auto& entry : params_->contents) {
242 BundleInstaller::Item item;
243 item.id = entry->id;
244 item.manifest = entry->manifest;
245 item.localized_name = entry->localized_name;
246 if (entry->icon_url)
247 item.icon_url = source_url().Resolve(*entry->icon_url);
248 items.push_back(item);
250 if (items.empty()) {
251 Respond(Error(kAlreadyInstalledError));
252 Release(); // Matches the AddRef in Run.
253 return;
256 bundle_.reset(new BundleInstaller(chrome_details_.GetCurrentBrowser(),
257 params_->details.localized_name,
258 bitmap ? *bitmap : SkBitmap(),
259 std::string(), details().delegated_user,
260 items));
262 bundle_->PromptForApproval(base::Bind(
263 &DashboardPrivateShowPermissionPromptForDelegatedBundleInstallFunction::
264 OnInstallApproval,
265 this));
267 Release(); // Matches the AddRef in Run.
270 void DashboardPrivateShowPermissionPromptForDelegatedBundleInstallFunction::
271 OnInstallApproval(BundleInstaller::ApprovalState state) {
272 if (state != BundleInstaller::APPROVED) {
273 Respond(Error(state == BundleInstaller::USER_CANCELED
274 ? kUserCancelledError
275 : kInvalidBundleError));
276 return;
279 Respond(NoArguments());
282 } // namespace extensions