1 // Copyright (c) 2012 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/chrome_quota_permission_context.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/infobars/infobar_service.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/tab_contents/tab_util.h"
15 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
16 #include "chrome/browser/ui/website_settings/permission_bubble_request.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/grit/generated_resources.h"
19 #include "chrome/grit/locale_settings.h"
20 #include "components/infobars/core/confirm_infobar_delegate.h"
21 #include "components/infobars/core/infobar.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/navigation_details.h"
24 #include "content/public/browser/web_contents.h"
25 #include "grit/theme_resources.h"
26 #include "net/base/net_util.h"
27 #include "storage/common/quota/quota_types.h"
28 #include "ui/base/l10n/l10n_util.h"
33 // If the site requested larger quota than this threshold, show a different
34 // message to the user.
35 const int64 kRequestLargeQuotaThreshold
= 5 * 1024 * 1024;
37 // QuotaPermissionRequest ---------------------------------------------
39 class QuotaPermissionRequest
: public PermissionBubbleRequest
{
41 QuotaPermissionRequest(
42 ChromeQuotaPermissionContext
* context
,
43 const GURL
& origin_url
,
44 int64 requested_quota
,
46 const std::string
& display_languages
,
47 const content::QuotaPermissionContext::PermissionCallback
& callback
);
49 ~QuotaPermissionRequest() override
;
51 // PermissionBubbleRequest:
52 int GetIconID() const override
;
53 base::string16
GetMessageText() const override
;
54 base::string16
GetMessageTextFragment() const override
;
55 bool HasUserGesture() const override
;
56 GURL
GetRequestingHostname() const override
;
57 void PermissionGranted() override
;
58 void PermissionDenied() override
;
59 void Cancelled() override
;
60 void RequestFinished() override
;
63 scoped_refptr
<ChromeQuotaPermissionContext
> context_
;
65 std::string display_languages_
;
66 int64 requested_quota_
;
68 content::QuotaPermissionContext::PermissionCallback callback_
;
70 DISALLOW_COPY_AND_ASSIGN(QuotaPermissionRequest
);
73 QuotaPermissionRequest::QuotaPermissionRequest(
74 ChromeQuotaPermissionContext
* context
,
75 const GURL
& origin_url
,
76 int64 requested_quota
,
78 const std::string
& display_languages
,
79 const content::QuotaPermissionContext::PermissionCallback
& callback
)
81 origin_url_(origin_url
),
82 display_languages_(display_languages
),
83 requested_quota_(requested_quota
),
84 user_gesture_(user_gesture
),
85 callback_(callback
) {}
87 QuotaPermissionRequest::~QuotaPermissionRequest() {}
89 int QuotaPermissionRequest::GetIconID() const {
90 // TODO(gbillock): get the proper image here
91 return IDR_INFOBAR_WARNING
;
94 base::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 net::kFormatUrlOmitUsernamePassword
|
101 net::kFormatUrlOmitTrailingSlashOnBareHostname
,
102 net::UnescapeRule::SPACES
, NULL
, NULL
, NULL
)
106 base::string16
QuotaPermissionRequest::GetMessageTextFragment() const {
107 return l10n_util::GetStringUTF16(IDS_REQUEST_QUOTA_PERMISSION_FRAGMENT
);
110 bool QuotaPermissionRequest::HasUserGesture() const {
111 return user_gesture_
;
114 GURL
QuotaPermissionRequest::GetRequestingHostname() const {
118 void QuotaPermissionRequest::PermissionGranted() {
119 context_
->DispatchCallbackOnIOThread(
121 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW
);
122 callback_
= content::QuotaPermissionContext::PermissionCallback();
125 void QuotaPermissionRequest::PermissionDenied() {
126 context_
->DispatchCallbackOnIOThread(
128 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_DISALLOW
);
129 callback_
= content::QuotaPermissionContext::PermissionCallback();
132 void QuotaPermissionRequest::Cancelled() {
135 void QuotaPermissionRequest::RequestFinished() {
136 if (!callback_
.is_null()) {
137 context_
->DispatchCallbackOnIOThread(
139 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED
);
146 // RequestQuotaInfoBarDelegate ------------------------------------------------
148 class RequestQuotaInfoBarDelegate
: public ConfirmInfoBarDelegate
{
150 // Creates a request quota infobar and delegate and adds the infobar to
151 // |infobar_service|.
153 InfoBarService
* infobar_service
,
154 ChromeQuotaPermissionContext
* context
,
155 const GURL
& origin_url
,
156 int64 requested_quota
,
157 const std::string
& display_languages
,
158 const content::QuotaPermissionContext::PermissionCallback
& callback
);
161 RequestQuotaInfoBarDelegate(
162 ChromeQuotaPermissionContext
* context
,
163 const GURL
& origin_url
,
164 int64 requested_quota
,
165 const std::string
& display_languages
,
166 const content::QuotaPermissionContext::PermissionCallback
& callback
);
167 ~RequestQuotaInfoBarDelegate() override
;
169 // ConfirmInfoBarDelegate:
170 base::string16
GetMessageText() const override
;
171 bool Accept() override
;
172 bool Cancel() override
;
174 scoped_refptr
<ChromeQuotaPermissionContext
> context_
;
176 std::string display_languages_
;
177 int64 requested_quota_
;
178 content::QuotaPermissionContext::PermissionCallback callback_
;
180 DISALLOW_COPY_AND_ASSIGN(RequestQuotaInfoBarDelegate
);
184 void RequestQuotaInfoBarDelegate::Create(
185 InfoBarService
* infobar_service
,
186 ChromeQuotaPermissionContext
* context
,
187 const GURL
& origin_url
,
188 int64 requested_quota
,
189 const std::string
& display_languages
,
190 const content::QuotaPermissionContext::PermissionCallback
& callback
) {
191 infobar_service
->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
192 scoped_ptr
<ConfirmInfoBarDelegate
>(new RequestQuotaInfoBarDelegate(
193 context
, origin_url
, requested_quota
, display_languages
, callback
))));
196 RequestQuotaInfoBarDelegate::RequestQuotaInfoBarDelegate(
197 ChromeQuotaPermissionContext
* context
,
198 const GURL
& origin_url
,
199 int64 requested_quota
,
200 const std::string
& display_languages
,
201 const content::QuotaPermissionContext::PermissionCallback
& callback
)
202 : ConfirmInfoBarDelegate(),
204 origin_url_(origin_url
),
205 display_languages_(display_languages
),
206 requested_quota_(requested_quota
),
207 callback_(callback
) {
210 RequestQuotaInfoBarDelegate::~RequestQuotaInfoBarDelegate() {
211 if (!callback_
.is_null()) {
212 context_
->DispatchCallbackOnIOThread(
214 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED
);
218 base::string16
RequestQuotaInfoBarDelegate::GetMessageText() const {
219 // If the site requested larger quota than this threshold, show a different
220 // message to the user.
221 return l10n_util::GetStringFUTF16(
222 (requested_quota_
> kRequestLargeQuotaThreshold
?
223 IDS_REQUEST_LARGE_QUOTA_INFOBAR_QUESTION
:
224 IDS_REQUEST_QUOTA_INFOBAR_QUESTION
),
225 net::FormatUrl(origin_url_
, display_languages_
,
226 net::kFormatUrlOmitUsernamePassword
|
227 net::kFormatUrlOmitTrailingSlashOnBareHostname
,
228 net::UnescapeRule::SPACES
, NULL
, NULL
, NULL
)
232 bool RequestQuotaInfoBarDelegate::Accept() {
233 context_
->DispatchCallbackOnIOThread(
235 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW
);
239 bool RequestQuotaInfoBarDelegate::Cancel() {
240 context_
->DispatchCallbackOnIOThread(
242 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED
);
249 // ChromeQuotaPermissionContext -----------------------------------------------
251 ChromeQuotaPermissionContext::ChromeQuotaPermissionContext() {
254 void ChromeQuotaPermissionContext::RequestQuotaPermission(
255 const content::StorageQuotaParams
& params
,
256 int render_process_id
,
257 const PermissionCallback
& callback
) {
258 if (params
.storage_type
!= storage::kStorageTypePersistent
) {
259 // For now we only support requesting quota with this interface
260 // for Persistent storage type.
261 callback
.Run(QUOTA_PERMISSION_RESPONSE_DISALLOW
);
265 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
)) {
266 content::BrowserThread::PostTask(
267 content::BrowserThread::UI
, FROM_HERE
,
268 base::Bind(&ChromeQuotaPermissionContext::RequestQuotaPermission
, this,
269 params
, render_process_id
, callback
));
273 content::WebContents
* web_contents
=
274 tab_util::GetWebContentsByID(render_process_id
,
275 params
.render_view_id
);
277 // The tab may have gone away or the request may not be from a tab.
278 LOG(WARNING
) << "Attempt to request quota tabless renderer: "
279 << render_process_id
<< "," << params
.render_view_id
;
280 DispatchCallbackOnIOThread(callback
, QUOTA_PERMISSION_RESPONSE_CANCELLED
);
284 if (PermissionBubbleManager::Enabled()) {
285 PermissionBubbleManager
* bubble_manager
=
286 PermissionBubbleManager::FromWebContents(web_contents
);
287 if (bubble_manager
) {
288 bubble_manager
->AddRequest(new QuotaPermissionRequest(this,
289 params
.origin_url
, params
.requested_size
, params
.user_gesture
,
290 Profile::FromBrowserContext(web_contents
->GetBrowserContext())->
291 GetPrefs()->GetString(prefs::kAcceptLanguages
),
297 InfoBarService
* infobar_service
=
298 InfoBarService::FromWebContents(web_contents
);
299 if (!infobar_service
) {
300 // The tab has no infobar service.
301 LOG(WARNING
) << "Attempt to request quota from a background page: "
302 << render_process_id
<< "," << params
.render_view_id
;
303 DispatchCallbackOnIOThread(callback
, QUOTA_PERMISSION_RESPONSE_CANCELLED
);
306 RequestQuotaInfoBarDelegate::Create(
307 infobar_service
, this, params
.origin_url
, params
.requested_size
,
308 Profile::FromBrowserContext(web_contents
->GetBrowserContext())->
309 GetPrefs()->GetString(prefs::kAcceptLanguages
),
313 void ChromeQuotaPermissionContext::DispatchCallbackOnIOThread(
314 const PermissionCallback
& callback
,
315 QuotaPermissionResponse response
) {
316 DCHECK_EQ(false, callback
.is_null());
318 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
)) {
319 content::BrowserThread::PostTask(
320 content::BrowserThread::IO
, FROM_HERE
,
321 base::Bind(&ChromeQuotaPermissionContext::DispatchCallbackOnIOThread
,
322 this, callback
, response
));
326 callback
.Run(response
);
329 ChromeQuotaPermissionContext::~ChromeQuotaPermissionContext() {}