blob: 3c12556941da37751a2eec3910f30349c507f41e [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
7#include <string>
8
[email protected]c8d98dd2011-10-18 23:12:089#include "base/bind.h"
[email protected]3853a4c2013-02-11 17:15:5710#include "base/prefs/pref_service.h"
[email protected]135cb802013-06-09 16:44:2011#include "base/strings/utf_string_conversions.h"
[email protected]4a8adfa02013-03-19 22:37:4612#include "chrome/browser/infobars/confirm_infobar_delegate.h"
[email protected]39308cb2013-12-06 03:01:4813#include "chrome/browser/infobars/infobar.h"
[email protected]4a8adfa02013-03-19 22:37:4614#include "chrome/browser/infobars/infobar_service.h"
[email protected]317f96c92011-05-31 06:53:4115#include "chrome/browser/profiles/profile.h"
[email protected]317f96c92011-05-31 06:53:4116#include "chrome/browser/tab_contents/tab_util.h"
[email protected]c032489d2014-02-11 19:07:2417#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
18#include "chrome/browser/ui/website_settings/permission_bubble_request.h"
[email protected]317f96c92011-05-31 06:53:4119#include "chrome/common/pref_names.h"
[email protected]c38831a12011-10-28 12:44:4920#include "content/public/browser/browser_thread.h"
[email protected]5b96836f2011-12-22 07:39:0021#include "content/public/browser/navigation_details.h"
[email protected]4f822f022012-12-20 19:11:4222#include "content/public/browser/web_contents.h"
[email protected]317f96c92011-05-31 06:53:4123#include "grit/generated_resources.h"
24#include "grit/locale_settings.h"
[email protected]d23cdeee2014-03-10 06:39:5325#include "grit/theme_resources.h"
[email protected]317f96c92011-05-31 06:53:4126#include "net/base/net_util.h"
27#include "ui/base/l10n/l10n_util.h"
[email protected]761fa4702013-07-02 15:25:1528#include "url/gurl.h"
[email protected]7660ec92013-05-30 05:12:3929#include "webkit/common/quota/quota_types.h"
[email protected]317f96c92011-05-31 06:53:4130
[email protected]c032489d2014-02-11 19:07:2431namespace {
32
33// If the site requested larger quota than this threshold, show a different
34// message to the user.
35const int64 kRequestLargeQuotaThreshold = 5 * 1024 * 1024;
36
37// QuotaPermissionRequest ---------------------------------------------
38
39class QuotaPermissionRequest : public PermissionBubbleRequest {
40 public:
41 QuotaPermissionRequest(
42 ChromeQuotaPermissionContext* context,
43 const GURL& origin_url,
44 int64 requested_quota,
[email protected]f78aa7722014-04-04 00:04:2545 bool user_gesture,
[email protected]c032489d2014-02-11 19:07:2446 const std::string& display_languages,
47 const content::QuotaPermissionContext::PermissionCallback& callback);
48
49 virtual ~QuotaPermissionRequest();
50
51 // PermissionBubbleRequest:
[email protected]d23cdeee2014-03-10 06:39:5352 virtual int GetIconID() const OVERRIDE;
[email protected]c032489d2014-02-11 19:07:2453 virtual base::string16 GetMessageText() const OVERRIDE;
54 virtual base::string16 GetMessageTextFragment() const OVERRIDE;
[email protected]d23cdeee2014-03-10 06:39:5355 virtual bool HasUserGesture() const OVERRIDE;
56 virtual GURL GetRequestingHostname() const OVERRIDE;
[email protected]c032489d2014-02-11 19:07:2457 virtual void PermissionGranted() OVERRIDE;
58 virtual void PermissionDenied() OVERRIDE;
59 virtual void Cancelled() OVERRIDE;
60 virtual void RequestFinished() OVERRIDE;
61
62 private:
63 scoped_refptr<ChromeQuotaPermissionContext> context_;
64 GURL origin_url_;
65 std::string display_languages_;
66 int64 requested_quota_;
[email protected]f78aa7722014-04-04 00:04:2567 bool user_gesture_;
[email protected]c032489d2014-02-11 19:07:2468 content::QuotaPermissionContext::PermissionCallback callback_;
69
70 DISALLOW_COPY_AND_ASSIGN(QuotaPermissionRequest);
71};
72
73QuotaPermissionRequest::QuotaPermissionRequest(
74 ChromeQuotaPermissionContext* context,
75 const GURL& origin_url,
76 int64 requested_quota,
[email protected]f78aa7722014-04-04 00:04:2577 bool user_gesture,
[email protected]c032489d2014-02-11 19:07:2478 const std::string& display_languages,
79 const content::QuotaPermissionContext::PermissionCallback& callback)
80 : context_(context),
81 origin_url_(origin_url),
82 display_languages_(display_languages),
83 requested_quota_(requested_quota),
[email protected]f78aa7722014-04-04 00:04:2584 user_gesture_(user_gesture),
[email protected]c032489d2014-02-11 19:07:2485 callback_(callback) {}
86
87QuotaPermissionRequest::~QuotaPermissionRequest() {}
88
[email protected]d23cdeee2014-03-10 06:39:5389int QuotaPermissionRequest::GetIconID() const {
90 // TODO(gbillock): get the proper image here
91 return IDR_INFOBAR_WARNING;
92}
93
[email protected]c032489d2014-02-11 19:07:2494base::string16 QuotaPermissionRequest::GetMessageText() const {
95 return l10n_util::GetStringFUTF16(
96 (requested_quota_ > kRequestLargeQuotaThreshold ?
97 IDS_REQUEST_LARGE_QUOTA_INFOBAR_QUESTION :
98 IDS_REQUEST_QUOTA_INFOBAR_QUESTION),
99 net::FormatUrl(origin_url_, display_languages_));
100}
101
102base::string16 QuotaPermissionRequest::GetMessageTextFragment() const {
103 return l10n_util::GetStringUTF16(IDS_REQUEST_QUOTA_PERMISSION_FRAGMENT);
104}
105
[email protected]d23cdeee2014-03-10 06:39:53106bool QuotaPermissionRequest::HasUserGesture() const {
[email protected]f78aa7722014-04-04 00:04:25107 return user_gesture_;
[email protected]c032489d2014-02-11 19:07:24108}
109
[email protected]d23cdeee2014-03-10 06:39:53110GURL QuotaPermissionRequest::GetRequestingHostname() const {
111 return origin_url_;
[email protected]c032489d2014-02-11 19:07:24112}
113
114void QuotaPermissionRequest::PermissionGranted() {
115 context_->DispatchCallbackOnIOThread(
116 callback_,
117 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW);
118 callback_ = content::QuotaPermissionContext::PermissionCallback();
119}
120
121void QuotaPermissionRequest::PermissionDenied() {
122 context_->DispatchCallbackOnIOThread(
123 callback_,
124 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_DISALLOW);
125 callback_ = content::QuotaPermissionContext::PermissionCallback();
126}
127
128void QuotaPermissionRequest::Cancelled() {
129}
130
131void QuotaPermissionRequest::RequestFinished() {
132 if (!callback_.is_null()) {
133 context_->DispatchCallbackOnIOThread(
134 callback_,
135 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED);
136 }
137
138 delete this;
139}
[email protected]631bb742011-11-02 11:29:39140
[email protected]49c71ac2013-05-03 01:36:22141
142// RequestQuotaInfoBarDelegate ------------------------------------------------
143
[email protected]317f96c92011-05-31 06:53:41144class RequestQuotaInfoBarDelegate : public ConfirmInfoBarDelegate {
145 public:
[email protected]39308cb2013-12-06 03:01:48146 // Creates a request quota infobar and delegate and adds the infobar to
147 // |infobar_service|.
[email protected]0be09932013-01-08 02:03:50148 static void Create(
149 InfoBarService* infobar_service,
150 ChromeQuotaPermissionContext* context,
151 const GURL& origin_url,
152 int64 requested_quota,
153 const std::string& display_languages,
[email protected]9a88ea992013-07-10 21:21:57154 const content::QuotaPermissionContext::PermissionCallback& callback);
[email protected]0be09932013-01-08 02:03:50155
156 private:
[email protected]317f96c92011-05-31 06:53:41157 RequestQuotaInfoBarDelegate(
[email protected]317f96c92011-05-31 06:53:41158 ChromeQuotaPermissionContext* context,
159 const GURL& origin_url,
160 int64 requested_quota,
161 const std::string& display_languages,
[email protected]9a88ea992013-07-10 21:21:57162 const content::QuotaPermissionContext::PermissionCallback& callback);
[email protected]49c71ac2013-05-03 01:36:22163 virtual ~RequestQuotaInfoBarDelegate();
[email protected]317f96c92011-05-31 06:53:41164
[email protected]49c71ac2013-05-03 01:36:22165 // ConfirmInfoBarDelegate:
[email protected]38eb4972013-01-07 18:35:05166 virtual bool ShouldExpireInternal(
[email protected]49c71ac2013-05-03 01:36:22167 const content::LoadCommittedDetails& details) const OVERRIDE;
[email protected]96920152013-12-04 21:00:16168 virtual base::string16 GetMessageText() const OVERRIDE;
[email protected]317f96c92011-05-31 06:53:41169 virtual bool Accept() OVERRIDE;
170 virtual bool Cancel() OVERRIDE;
171
172 scoped_refptr<ChromeQuotaPermissionContext> context_;
173 GURL origin_url_;
174 std::string display_languages_;
175 int64 requested_quota_;
[email protected]9a88ea992013-07-10 21:21:57176 content::QuotaPermissionContext::PermissionCallback callback_;
[email protected]49c71ac2013-05-03 01:36:22177
[email protected]317f96c92011-05-31 06:53:41178 DISALLOW_COPY_AND_ASSIGN(RequestQuotaInfoBarDelegate);
179};
180
[email protected]0be09932013-01-08 02:03:50181// static
182void RequestQuotaInfoBarDelegate::Create(
183 InfoBarService* infobar_service,
184 ChromeQuotaPermissionContext* context,
185 const GURL& origin_url,
186 int64 requested_quota,
187 const std::string& display_languages,
[email protected]9a88ea992013-07-10 21:21:57188 const content::QuotaPermissionContext::PermissionCallback& callback) {
[email protected]39308cb2013-12-06 03:01:48189 infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
190 scoped_ptr<ConfirmInfoBarDelegate>(new RequestQuotaInfoBarDelegate(
191 context, origin_url, requested_quota, display_languages, callback))));
[email protected]0be09932013-01-08 02:03:50192}
193
[email protected]49c71ac2013-05-03 01:36:22194RequestQuotaInfoBarDelegate::RequestQuotaInfoBarDelegate(
[email protected]49c71ac2013-05-03 01:36:22195 ChromeQuotaPermissionContext* context,
196 const GURL& origin_url,
197 int64 requested_quota,
198 const std::string& display_languages,
[email protected]9a88ea992013-07-10 21:21:57199 const content::QuotaPermissionContext::PermissionCallback& callback)
[email protected]39308cb2013-12-06 03:01:48200 : ConfirmInfoBarDelegate(),
[email protected]49c71ac2013-05-03 01:36:22201 context_(context),
202 origin_url_(origin_url),
203 display_languages_(display_languages),
204 requested_quota_(requested_quota),
205 callback_(callback) {
206}
207
208RequestQuotaInfoBarDelegate::~RequestQuotaInfoBarDelegate() {
209 if (!callback_.is_null()) {
210 context_->DispatchCallbackOnIOThread(
211 callback_,
[email protected]9a88ea992013-07-10 21:21:57212 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED);
[email protected]49c71ac2013-05-03 01:36:22213 }
214}
215
216bool RequestQuotaInfoBarDelegate::ShouldExpireInternal(
217 const content::LoadCommittedDetails& details) const {
218 return false;
219}
220
[email protected]6a72a632013-12-12 22:22:00221base::string16 RequestQuotaInfoBarDelegate::GetMessageText() const {
[email protected]9a88ea992013-07-10 21:21:57222 // If the site requested larger quota than this threshold, show a different
223 // message to the user.
[email protected]317f96c92011-05-31 06:53:41224 return l10n_util::GetStringFUTF16(
225 (requested_quota_ > kRequestLargeQuotaThreshold ?
226 IDS_REQUEST_LARGE_QUOTA_INFOBAR_QUESTION :
227 IDS_REQUEST_QUOTA_INFOBAR_QUESTION),
228 net::FormatUrl(origin_url_, display_languages_));
229}
230
231bool RequestQuotaInfoBarDelegate::Accept() {
232 context_->DispatchCallbackOnIOThread(
[email protected]9f9749a2012-03-02 19:37:00233 callback_,
[email protected]9a88ea992013-07-10 21:21:57234 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW);
[email protected]317f96c92011-05-31 06:53:41235 return true;
236}
237
238bool RequestQuotaInfoBarDelegate::Cancel() {
239 context_->DispatchCallbackOnIOThread(
[email protected]9f9749a2012-03-02 19:37:00240 callback_,
[email protected]9a88ea992013-07-10 21:21:57241 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED);
[email protected]317f96c92011-05-31 06:53:41242 return true;
243}
244
[email protected]49c71ac2013-05-03 01:36:22245} // namespace
246
247
248// ChromeQuotaPermissionContext -----------------------------------------------
[email protected]317f96c92011-05-31 06:53:41249
[email protected]9a88ea992013-07-10 21:21:57250ChromeQuotaPermissionContext::ChromeQuotaPermissionContext() {
251}
[email protected]317f96c92011-05-31 06:53:41252
253void ChromeQuotaPermissionContext::RequestQuotaPermission(
[email protected]f78aa7722014-04-04 00:04:25254 const content::StorageQuotaParams& params,
[email protected]317f96c92011-05-31 06:53:41255 int render_process_id,
[email protected]c8d98dd2011-10-18 23:12:08256 const PermissionCallback& callback) {
[email protected]f78aa7722014-04-04 00:04:25257 if (params.storage_type != quota::kStorageTypePersistent) {
[email protected]317f96c92011-05-31 06:53:41258 // For now we only support requesting quota with this interface
259 // for Persistent storage type.
[email protected]9f9749a2012-03-02 19:37:00260 callback.Run(QUOTA_PERMISSION_RESPONSE_DISALLOW);
[email protected]317f96c92011-05-31 06:53:41261 return;
262 }
263
[email protected]9a88ea992013-07-10 21:21:57264 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
265 content::BrowserThread::PostTask(
266 content::BrowserThread::UI, FROM_HERE,
[email protected]1c6bfbb2011-11-30 04:36:14267 base::Bind(&ChromeQuotaPermissionContext::RequestQuotaPermission, this,
[email protected]f78aa7722014-04-04 00:04:25268 params, render_process_id, callback));
[email protected]317f96c92011-05-31 06:53:41269 return;
270 }
271
[email protected]9a88ea992013-07-10 21:21:57272 content::WebContents* web_contents =
[email protected]f78aa7722014-04-04 00:04:25273 tab_util::GetWebContentsByID(render_process_id,
274 params.render_view_id);
[email protected]83ff91c2012-01-05 20:54:13275 if (!web_contents) {
[email protected]317f96c92011-05-31 06:53:41276 // The tab may have gone away or the request may not be from a tab.
277 LOG(WARNING) << "Attempt to request quota tabless renderer: "
[email protected]f78aa7722014-04-04 00:04:25278 << render_process_id << "," << params.render_view_id;
[email protected]9f9749a2012-03-02 19:37:00279 DispatchCallbackOnIOThread(callback, QUOTA_PERMISSION_RESPONSE_CANCELLED);
[email protected]317f96c92011-05-31 06:53:41280 return;
281 }
282
[email protected]c032489d2014-02-11 19:07:24283 if (PermissionBubbleManager::Enabled()) {
284 PermissionBubbleManager* bubble_manager =
285 PermissionBubbleManager::FromWebContents(web_contents);
286 bubble_manager->AddRequest(new QuotaPermissionRequest(this,
[email protected]f78aa7722014-04-04 00:04:25287 params.origin_url, params.requested_size, params.user_gesture,
[email protected]c032489d2014-02-11 19:07:24288 Profile::FromBrowserContext(web_contents->GetBrowserContext())->
289 GetPrefs()->GetString(prefs::kAcceptLanguages),
290 callback));
291 return;
292 }
293
[email protected]4f822f022012-12-20 19:11:42294 InfoBarService* infobar_service =
295 InfoBarService::FromWebContents(web_contents);
296 if (!infobar_service) {
297 // The tab has no infobar service.
[email protected]17f2adb2012-07-22 15:43:40298 LOG(WARNING) << "Attempt to request quota from a background page: "
[email protected]f78aa7722014-04-04 00:04:25299 << render_process_id << "," << params.render_view_id;
[email protected]17f2adb2012-07-22 15:43:40300 DispatchCallbackOnIOThread(callback, QUOTA_PERMISSION_RESPONSE_CANCELLED);
301 return;
302 }
[email protected]0be09932013-01-08 02:03:50303 RequestQuotaInfoBarDelegate::Create(
[email protected]f78aa7722014-04-04 00:04:25304 infobar_service, this, params.origin_url, params.requested_size,
[email protected]9a88ea992013-07-10 21:21:57305 Profile::FromBrowserContext(web_contents->GetBrowserContext())->
306 GetPrefs()->GetString(prefs::kAcceptLanguages),
[email protected]0be09932013-01-08 02:03:50307 callback);
[email protected]317f96c92011-05-31 06:53:41308}
309
310void ChromeQuotaPermissionContext::DispatchCallbackOnIOThread(
[email protected]c8d98dd2011-10-18 23:12:08311 const PermissionCallback& callback,
[email protected]9f9749a2012-03-02 19:37:00312 QuotaPermissionResponse response) {
[email protected]c8d98dd2011-10-18 23:12:08313 DCHECK_EQ(false, callback.is_null());
314
[email protected]9a88ea992013-07-10 21:21:57315 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) {
316 content::BrowserThread::PostTask(
317 content::BrowserThread::IO, FROM_HERE,
[email protected]c8d98dd2011-10-18 23:12:08318 base::Bind(&ChromeQuotaPermissionContext::DispatchCallbackOnIOThread,
319 this, callback, response));
[email protected]317f96c92011-05-31 06:53:41320 return;
321 }
[email protected]c8d98dd2011-10-18 23:12:08322
323 callback.Run(response);
[email protected]317f96c92011-05-31 06:53:41324}
[email protected]649d1c02012-04-27 02:56:21325
326ChromeQuotaPermissionContext::~ChromeQuotaPermissionContext() {}