blob: b4921431e12595e294d3105bb2d020f0d1e9d2cd [file] [log] [blame]
[email protected]9f9749a2012-03-02 19:37:001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]317f96c92011-05-31 06:53:412// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/chrome_quota_permission_context.h"
6
avie4d7b6f2015-12-26 00:59:187#include <stdint.h>
8
[email protected]317f96c92011-05-31 06:53:419#include <string>
10
[email protected]c8d98dd2011-10-18 23:12:0811#include "base/bind.h"
avie4d7b6f2015-12-26 00:59:1812#include "base/macros.h"
[email protected]135cb802013-06-09 16:44:2013#include "base/strings/utf_string_conversions.h"
avie4d7b6f2015-12-26 00:59:1814#include "build/build_config.h"
tsergeant58defcfb2016-07-19 23:47:2815#include "chrome/browser/permissions/permission_request.h"
timloh5b34b672017-03-08 01:49:3416#include "chrome/browser/permissions/permission_request_manager.h"
[email protected]317f96c92011-05-31 06:53:4117#include "chrome/browser/profiles/profile.h"
[email protected]317f96c92011-05-31 06:53:4118#include "chrome/browser/tab_contents/tab_util.h"
[email protected]af39f002014-08-22 10:18:1819#include "chrome/grit/generated_resources.h"
palmera6615c592015-09-24 00:49:0920#include "components/url_formatter/elide_url.h"
[email protected]c38831a12011-10-28 12:44:4921#include "content/public/browser/browser_thread.h"
[email protected]5b96836f2011-12-22 07:39:0022#include "content/public/browser/navigation_details.h"
[email protected]4f822f022012-12-20 19:11:4223#include "content/public/browser/web_contents.h"
pilgrim16330552014-09-10 01:32:2224#include "storage/common/quota/quota_types.h"
[email protected]317f96c92011-05-31 06:53:4125#include "ui/base/l10n/l10n_util.h"
[email protected]761fa4702013-07-02 15:25:1526#include "url/gurl.h"
[email protected]317f96c92011-05-31 06:53:4127
estade6d95d1d2015-10-02 18:55:2328#if defined(OS_ANDROID)
estade20c051a92016-10-15 22:53:2229#include "chrome/browser/android/android_theme_resources.h"
estade6d95d1d2015-10-02 18:55:2330#include "chrome/browser/infobars/infobar_service.h"
31#include "components/infobars/core/confirm_infobar_delegate.h"
32#include "components/infobars/core/infobar.h"
33#else
estade1e235b62017-02-15 01:40:3434#include "ui/vector_icons/vector_icons.h"
estade6d95d1d2015-10-02 18:55:2335#endif
36
[email protected]c032489d2014-02-11 19:07:2437namespace {
38
timlohaa3ce262017-06-01 05:29:4039// On Android, if the site requested larger quota than this threshold, show a
40// different message to the user.
avie4d7b6f2015-12-26 00:59:1841const int64_t kRequestLargeQuotaThreshold = 5 * 1024 * 1024;
[email protected]c032489d2014-02-11 19:07:2442
43// QuotaPermissionRequest ---------------------------------------------
44
tsergeant58defcfb2016-07-19 23:47:2845class QuotaPermissionRequest : public PermissionRequest {
[email protected]c032489d2014-02-11 19:07:2446 public:
47 QuotaPermissionRequest(
48 ChromeQuotaPermissionContext* context,
49 const GURL& origin_url,
timlohaa3ce262017-06-01 05:29:4050 bool is_large_quota_request_,
[email protected]c032489d2014-02-11 19:07:2451 const content::QuotaPermissionContext::PermissionCallback& callback);
52
Daniel Chenga542fca2014-10-21 09:51:2953 ~QuotaPermissionRequest() override;
[email protected]c032489d2014-02-11 19:07:2454
benwells46b02fa2016-04-20 02:37:0255 private:
tsergeant58defcfb2016-07-19 23:47:2856 // PermissionRequest:
estade20c051a92016-10-15 22:53:2257 IconId GetIconId() const override;
timlohaa3ce262017-06-01 05:29:4058#if defined(OS_ANDROID)
59 base::string16 GetMessageText() const override;
60#endif
Daniel Chenga542fca2014-10-21 09:51:2961 base::string16 GetMessageTextFragment() const override;
johnmefe4e96d2016-01-27 16:14:4162 GURL GetOrigin() const override;
Daniel Chenga542fca2014-10-21 09:51:2963 void PermissionGranted() override;
64 void PermissionDenied() override;
65 void Cancelled() override;
66 void RequestFinished() override;
tsergeant58defcfb2016-07-19 23:47:2867 PermissionRequestType GetPermissionRequestType() const override;
[email protected]c032489d2014-02-11 19:07:2468
timlohaa3ce262017-06-01 05:29:4069 const scoped_refptr<ChromeQuotaPermissionContext> context_;
70 const GURL origin_url_;
71 const bool is_large_quota_request_;
[email protected]c032489d2014-02-11 19:07:2472 content::QuotaPermissionContext::PermissionCallback callback_;
73
74 DISALLOW_COPY_AND_ASSIGN(QuotaPermissionRequest);
75};
76
77QuotaPermissionRequest::QuotaPermissionRequest(
78 ChromeQuotaPermissionContext* context,
79 const GURL& origin_url,
timlohaa3ce262017-06-01 05:29:4080 bool is_large_quota_request,
[email protected]c032489d2014-02-11 19:07:2481 const content::QuotaPermissionContext::PermissionCallback& callback)
82 : context_(context),
83 origin_url_(origin_url),
timlohaa3ce262017-06-01 05:29:4084 is_large_quota_request_(is_large_quota_request),
85 callback_(callback) {
86 // Suppress unused private field warning on desktop
87 (void)is_large_quota_request_;
88}
[email protected]c032489d2014-02-11 19:07:2489
90QuotaPermissionRequest::~QuotaPermissionRequest() {}
91
estade20c051a92016-10-15 22:53:2292PermissionRequest::IconId QuotaPermissionRequest::GetIconId() const {
[email protected]d23cdeee2014-03-10 06:39:5393 // TODO(gbillock): get the proper image here
estade20c051a92016-10-15 22:53:2294#if defined(OS_ANDROID)
95 return IDR_ANDROID_INFOBAR_WARNING;
96#else
estade1e235b62017-02-15 01:40:3497 return ui::kWarningIcon;
estade20c051a92016-10-15 22:53:2298#endif
[email protected]d23cdeee2014-03-10 06:39:5399}
100
timlohaa3ce262017-06-01 05:29:40101#if defined(OS_ANDROID)
102base::string16 QuotaPermissionRequest::GetMessageText() const {
103 // If the site requested larger quota than this threshold, show a different
104 // message to the user.
105 return l10n_util::GetStringFUTF16(
106 (is_large_quota_request_ ? IDS_REQUEST_LARGE_QUOTA_INFOBAR_QUESTION
107 : IDS_REQUEST_QUOTA_INFOBAR_QUESTION),
108 url_formatter::FormatUrlForSecurityDisplay(origin_url_));
109}
110#endif
111
[email protected]c032489d2014-02-11 19:07:24112base::string16 QuotaPermissionRequest::GetMessageTextFragment() const {
113 return l10n_util::GetStringUTF16(IDS_REQUEST_QUOTA_PERMISSION_FRAGMENT);
114}
115
johnmefe4e96d2016-01-27 16:14:41116GURL QuotaPermissionRequest::GetOrigin() const {
[email protected]d23cdeee2014-03-10 06:39:53117 return origin_url_;
[email protected]c032489d2014-02-11 19:07:24118}
119
120void QuotaPermissionRequest::PermissionGranted() {
121 context_->DispatchCallbackOnIOThread(
122 callback_,
123 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW);
124 callback_ = content::QuotaPermissionContext::PermissionCallback();
125}
126
127void QuotaPermissionRequest::PermissionDenied() {
128 context_->DispatchCallbackOnIOThread(
129 callback_,
130 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_DISALLOW);
131 callback_ = content::QuotaPermissionContext::PermissionCallback();
132}
133
134void QuotaPermissionRequest::Cancelled() {
135}
136
137void QuotaPermissionRequest::RequestFinished() {
138 if (!callback_.is_null()) {
139 context_->DispatchCallbackOnIOThread(
140 callback_,
141 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED);
142 }
143
144 delete this;
145}
[email protected]631bb742011-11-02 11:29:39146
tsergeant58defcfb2016-07-19 23:47:28147PermissionRequestType QuotaPermissionRequest::GetPermissionRequestType() const {
148 return PermissionRequestType::QUOTA;
benwells46b02fa2016-04-20 02:37:02149}
150
estade6d95d1d2015-10-02 18:55:23151#if defined(OS_ANDROID)
[email protected]49c71ac2013-05-03 01:36:22152// RequestQuotaInfoBarDelegate ------------------------------------------------
153
[email protected]317f96c92011-05-31 06:53:41154class RequestQuotaInfoBarDelegate : public ConfirmInfoBarDelegate {
155 public:
[email protected]39308cb2013-12-06 03:01:48156 // Creates a request quota infobar and delegate and adds the infobar to
157 // |infobar_service|.
[email protected]0be09932013-01-08 02:03:50158 static void Create(
159 InfoBarService* infobar_service,
160 ChromeQuotaPermissionContext* context,
161 const GURL& origin_url,
avie4d7b6f2015-12-26 00:59:18162 int64_t requested_quota,
[email protected]9a88ea992013-07-10 21:21:57163 const content::QuotaPermissionContext::PermissionCallback& callback);
[email protected]0be09932013-01-08 02:03:50164
165 private:
[email protected]317f96c92011-05-31 06:53:41166 RequestQuotaInfoBarDelegate(
[email protected]317f96c92011-05-31 06:53:41167 ChromeQuotaPermissionContext* context,
168 const GURL& origin_url,
avie4d7b6f2015-12-26 00:59:18169 int64_t requested_quota,
[email protected]9a88ea992013-07-10 21:21:57170 const content::QuotaPermissionContext::PermissionCallback& callback);
Daniel Chenga542fca2014-10-21 09:51:29171 ~RequestQuotaInfoBarDelegate() override;
[email protected]317f96c92011-05-31 06:53:41172
[email protected]49c71ac2013-05-03 01:36:22173 // ConfirmInfoBarDelegate:
dfalcantaraac4d93b2015-12-30 20:07:24174 infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
Daniel Chenga542fca2014-10-21 09:51:29175 base::string16 GetMessageText() const override;
176 bool Accept() override;
177 bool Cancel() override;
[email protected]317f96c92011-05-31 06:53:41178
179 scoped_refptr<ChromeQuotaPermissionContext> context_;
180 GURL origin_url_;
avie4d7b6f2015-12-26 00:59:18181 int64_t requested_quota_;
[email protected]9a88ea992013-07-10 21:21:57182 content::QuotaPermissionContext::PermissionCallback callback_;
[email protected]49c71ac2013-05-03 01:36:22183
[email protected]317f96c92011-05-31 06:53:41184 DISALLOW_COPY_AND_ASSIGN(RequestQuotaInfoBarDelegate);
185};
186
[email protected]0be09932013-01-08 02:03:50187// static
188void RequestQuotaInfoBarDelegate::Create(
189 InfoBarService* infobar_service,
190 ChromeQuotaPermissionContext* context,
191 const GURL& origin_url,
avie4d7b6f2015-12-26 00:59:18192 int64_t requested_quota,
[email protected]9a88ea992013-07-10 21:21:57193 const content::QuotaPermissionContext::PermissionCallback& callback) {
sdefresne316da452014-12-22 17:30:59194 infobar_service->AddInfoBar(infobar_service->CreateConfirmInfoBar(
dcheng4af48582016-04-19 00:29:35195 std::unique_ptr<ConfirmInfoBarDelegate>(new RequestQuotaInfoBarDelegate(
jshin1fb76462016-04-05 22:13:03196 context, origin_url, requested_quota, callback))));
[email protected]0be09932013-01-08 02:03:50197}
198
[email protected]49c71ac2013-05-03 01:36:22199RequestQuotaInfoBarDelegate::RequestQuotaInfoBarDelegate(
[email protected]49c71ac2013-05-03 01:36:22200 ChromeQuotaPermissionContext* context,
201 const GURL& origin_url,
avie4d7b6f2015-12-26 00:59:18202 int64_t requested_quota,
[email protected]9a88ea992013-07-10 21:21:57203 const content::QuotaPermissionContext::PermissionCallback& callback)
[email protected]39308cb2013-12-06 03:01:48204 : ConfirmInfoBarDelegate(),
[email protected]49c71ac2013-05-03 01:36:22205 context_(context),
206 origin_url_(origin_url),
[email protected]49c71ac2013-05-03 01:36:22207 requested_quota_(requested_quota),
avie4d7b6f2015-12-26 00:59:18208 callback_(callback) {}
[email protected]49c71ac2013-05-03 01:36:22209
210RequestQuotaInfoBarDelegate::~RequestQuotaInfoBarDelegate() {
211 if (!callback_.is_null()) {
212 context_->DispatchCallbackOnIOThread(
213 callback_,
[email protected]9a88ea992013-07-10 21:21:57214 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED);
[email protected]49c71ac2013-05-03 01:36:22215 }
216}
217
dfalcantaraac4d93b2015-12-30 20:07:24218infobars::InfoBarDelegate::InfoBarIdentifier
219RequestQuotaInfoBarDelegate::GetIdentifier() const {
220 return REQUEST_QUOTA_INFOBAR_DELEGATE;
221}
222
[email protected]6a72a632013-12-12 22:22:00223base::string16 RequestQuotaInfoBarDelegate::GetMessageText() const {
[email protected]9a88ea992013-07-10 21:21:57224 // If the site requested larger quota than this threshold, show a different
225 // message to the user.
[email protected]317f96c92011-05-31 06:53:41226 return l10n_util::GetStringFUTF16(
rsleevi24f64dc22015-08-07 21:39:21227 (requested_quota_ > kRequestLargeQuotaThreshold
228 ? IDS_REQUEST_LARGE_QUOTA_INFOBAR_QUESTION
229 : IDS_REQUEST_QUOTA_INFOBAR_QUESTION),
jshin1fb76462016-04-05 22:13:03230 url_formatter::FormatUrlForSecurityDisplay(origin_url_));
[email protected]317f96c92011-05-31 06:53:41231}
232
233bool RequestQuotaInfoBarDelegate::Accept() {
234 context_->DispatchCallbackOnIOThread(
[email protected]9f9749a2012-03-02 19:37:00235 callback_,
[email protected]9a88ea992013-07-10 21:21:57236 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW);
[email protected]317f96c92011-05-31 06:53:41237 return true;
238}
239
240bool RequestQuotaInfoBarDelegate::Cancel() {
241 context_->DispatchCallbackOnIOThread(
[email protected]9f9749a2012-03-02 19:37:00242 callback_,
[email protected]9a88ea992013-07-10 21:21:57243 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED);
[email protected]317f96c92011-05-31 06:53:41244 return true;
245}
estade6d95d1d2015-10-02 18:55:23246#endif
[email protected]317f96c92011-05-31 06:53:41247
[email protected]49c71ac2013-05-03 01:36:22248} // namespace
249
250
251// ChromeQuotaPermissionContext -----------------------------------------------
[email protected]317f96c92011-05-31 06:53:41252
[email protected]9a88ea992013-07-10 21:21:57253ChromeQuotaPermissionContext::ChromeQuotaPermissionContext() {
254}
[email protected]317f96c92011-05-31 06:53:41255
256void ChromeQuotaPermissionContext::RequestQuotaPermission(
[email protected]f78aa7722014-04-04 00:04:25257 const content::StorageQuotaParams& params,
[email protected]317f96c92011-05-31 06:53:41258 int render_process_id,
[email protected]c8d98dd2011-10-18 23:12:08259 const PermissionCallback& callback) {
[email protected]cd501a72014-08-22 19:58:31260 if (params.storage_type != storage::kStorageTypePersistent) {
[email protected]317f96c92011-05-31 06:53:41261 // For now we only support requesting quota with this interface
262 // for Persistent storage type.
[email protected]9f9749a2012-03-02 19:37:00263 callback.Run(QUOTA_PERMISSION_RESPONSE_DISALLOW);
[email protected]317f96c92011-05-31 06:53:41264 return;
265 }
266
[email protected]9a88ea992013-07-10 21:21:57267 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
268 content::BrowserThread::PostTask(
269 content::BrowserThread::UI, FROM_HERE,
tzik29ea5c72017-04-20 02:16:51270 base::BindOnce(&ChromeQuotaPermissionContext::RequestQuotaPermission,
271 this, params, render_process_id, callback));
[email protected]317f96c92011-05-31 06:53:41272 return;
273 }
274
nick6206d822016-12-09 20:05:03275 content::WebContents* web_contents = tab_util::GetWebContentsByFrameID(
276 render_process_id, params.render_frame_id);
[email protected]83ff91c2012-01-05 20:54:13277 if (!web_contents) {
[email protected]317f96c92011-05-31 06:53:41278 // The tab may have gone away or the request may not be from a tab.
279 LOG(WARNING) << "Attempt to request quota tabless renderer: "
nick6206d822016-12-09 20:05:03280 << render_process_id << "," << params.render_frame_id;
[email protected]9f9749a2012-03-02 19:37:00281 DispatchCallbackOnIOThread(callback, QUOTA_PERMISSION_RESPONSE_CANCELLED);
[email protected]317f96c92011-05-31 06:53:41282 return;
283 }
284
timloh5b34b672017-03-08 01:49:34285 if (PermissionRequestManager::IsEnabled()) {
286 PermissionRequestManager* permission_request_manager =
287 PermissionRequestManager::FromWebContents(web_contents);
288 if (permission_request_manager) {
timlohaa3ce262017-06-01 05:29:40289 bool is_large_quota_request =
290 params.requested_size > kRequestLargeQuotaThreshold;
291 permission_request_manager->AddRequest(new QuotaPermissionRequest(
292 this, params.origin_url, is_large_quota_request, callback));
timloh5b34b672017-03-08 01:49:34293 return;
294 }
estade6d95d1d2015-10-02 18:55:23295#if defined(OS_ANDROID)
timloh5b34b672017-03-08 01:49:34296 } else {
297 InfoBarService* infobar_service =
298 InfoBarService::FromWebContents(web_contents);
299 if (infobar_service) {
300 RequestQuotaInfoBarDelegate::Create(infobar_service, this,
301 params.origin_url,
302 params.requested_size, callback);
303 return;
304 }
estade6d95d1d2015-10-02 18:55:23305#endif
timloh5b34b672017-03-08 01:49:34306 }
[email protected]c032489d2014-02-11 19:07:24307
estade6d95d1d2015-10-02 18:55:23308 // The tab has no UI service for presenting the permissions request.
309 LOG(WARNING) << "Attempt to request quota from a background page: "
nick6206d822016-12-09 20:05:03310 << render_process_id << "," << params.render_frame_id;
estade6d95d1d2015-10-02 18:55:23311 DispatchCallbackOnIOThread(callback, QUOTA_PERMISSION_RESPONSE_CANCELLED);
[email protected]317f96c92011-05-31 06:53:41312}
313
314void ChromeQuotaPermissionContext::DispatchCallbackOnIOThread(
[email protected]c8d98dd2011-10-18 23:12:08315 const PermissionCallback& callback,
[email protected]9f9749a2012-03-02 19:37:00316 QuotaPermissionResponse response) {
[email protected]c8d98dd2011-10-18 23:12:08317 DCHECK_EQ(false, callback.is_null());
318
[email protected]9a88ea992013-07-10 21:21:57319 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) {
320 content::BrowserThread::PostTask(
321 content::BrowserThread::IO, FROM_HERE,
tzik29ea5c72017-04-20 02:16:51322 base::BindOnce(
323 &ChromeQuotaPermissionContext::DispatchCallbackOnIOThread, this,
324 callback, response));
[email protected]317f96c92011-05-31 06:53:41325 return;
326 }
[email protected]c8d98dd2011-10-18 23:12:08327
328 callback.Run(response);
[email protected]317f96c92011-05-31 06:53:41329}
[email protected]649d1c02012-04-27 02:56:21330
331ChromeQuotaPermissionContext::~ChromeQuotaPermissionContext() {}