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/confirm_infobar_delegate.h"
13 #include "chrome/browser/infobars/infobar_service.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/tab_contents/tab_util.h"
16 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
17 #include "chrome/browser/ui/website_settings/permission_bubble_request.h"
18 #include "chrome/common/pref_names.h"
19 #include "components/infobars/core/infobar.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/navigation_details.h"
22 #include "content/public/browser/web_contents.h"
23 #include "grit/generated_resources.h"
24 #include "grit/locale_settings.h"
25 #include "grit/theme_resources.h"
26 #include "net/base/net_util.h"
27 #include "ui/base/l10n/l10n_util.h"
29 #include "webkit/common/quota/quota_types.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 virtual ~QuotaPermissionRequest();
51 // PermissionBubbleRequest:
52 virtual int GetIconID() const OVERRIDE
;
53 virtual base::string16
GetMessageText() const OVERRIDE
;
54 virtual base::string16
GetMessageTextFragment() const OVERRIDE
;
55 virtual bool HasUserGesture() const OVERRIDE
;
56 virtual GURL
GetRequestingHostname() const OVERRIDE
;
57 virtual void PermissionGranted() OVERRIDE
;
58 virtual void PermissionDenied() OVERRIDE
;
59 virtual void Cancelled() OVERRIDE
;
60 virtual 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_
));
102 base::string16
QuotaPermissionRequest::GetMessageTextFragment() const {
103 return l10n_util::GetStringUTF16(IDS_REQUEST_QUOTA_PERMISSION_FRAGMENT
);
106 bool QuotaPermissionRequest::HasUserGesture() const {
107 return user_gesture_
;
110 GURL
QuotaPermissionRequest::GetRequestingHostname() const {
114 void QuotaPermissionRequest::PermissionGranted() {
115 context_
->DispatchCallbackOnIOThread(
117 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW
);
118 callback_
= content::QuotaPermissionContext::PermissionCallback();
121 void QuotaPermissionRequest::PermissionDenied() {
122 context_
->DispatchCallbackOnIOThread(
124 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_DISALLOW
);
125 callback_
= content::QuotaPermissionContext::PermissionCallback();
128 void QuotaPermissionRequest::Cancelled() {
131 void QuotaPermissionRequest::RequestFinished() {
132 if (!callback_
.is_null()) {
133 context_
->DispatchCallbackOnIOThread(
135 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED
);
142 // RequestQuotaInfoBarDelegate ------------------------------------------------
144 class RequestQuotaInfoBarDelegate
: public ConfirmInfoBarDelegate
{
146 // Creates a request quota infobar and delegate and adds the infobar to
147 // |infobar_service|.
149 InfoBarService
* infobar_service
,
150 ChromeQuotaPermissionContext
* context
,
151 const GURL
& origin_url
,
152 int64 requested_quota
,
153 const std::string
& display_languages
,
154 const content::QuotaPermissionContext::PermissionCallback
& callback
);
157 RequestQuotaInfoBarDelegate(
158 ChromeQuotaPermissionContext
* context
,
159 const GURL
& origin_url
,
160 int64 requested_quota
,
161 const std::string
& display_languages
,
162 const content::QuotaPermissionContext::PermissionCallback
& callback
);
163 virtual ~RequestQuotaInfoBarDelegate();
165 // ConfirmInfoBarDelegate:
166 virtual bool ShouldExpireInternal(
167 const NavigationDetails
& details
) const OVERRIDE
;
168 virtual base::string16
GetMessageText() const OVERRIDE
;
169 virtual bool Accept() OVERRIDE
;
170 virtual bool Cancel() OVERRIDE
;
172 scoped_refptr
<ChromeQuotaPermissionContext
> context_
;
174 std::string display_languages_
;
175 int64 requested_quota_
;
176 content::QuotaPermissionContext::PermissionCallback callback_
;
178 DISALLOW_COPY_AND_ASSIGN(RequestQuotaInfoBarDelegate
);
182 void RequestQuotaInfoBarDelegate::Create(
183 InfoBarService
* infobar_service
,
184 ChromeQuotaPermissionContext
* context
,
185 const GURL
& origin_url
,
186 int64 requested_quota
,
187 const std::string
& display_languages
,
188 const content::QuotaPermissionContext::PermissionCallback
& callback
) {
189 infobar_service
->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
190 scoped_ptr
<ConfirmInfoBarDelegate
>(new RequestQuotaInfoBarDelegate(
191 context
, origin_url
, requested_quota
, display_languages
, callback
))));
194 RequestQuotaInfoBarDelegate::RequestQuotaInfoBarDelegate(
195 ChromeQuotaPermissionContext
* context
,
196 const GURL
& origin_url
,
197 int64 requested_quota
,
198 const std::string
& display_languages
,
199 const content::QuotaPermissionContext::PermissionCallback
& callback
)
200 : ConfirmInfoBarDelegate(),
202 origin_url_(origin_url
),
203 display_languages_(display_languages
),
204 requested_quota_(requested_quota
),
205 callback_(callback
) {
208 RequestQuotaInfoBarDelegate::~RequestQuotaInfoBarDelegate() {
209 if (!callback_
.is_null()) {
210 context_
->DispatchCallbackOnIOThread(
212 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED
);
216 bool RequestQuotaInfoBarDelegate::ShouldExpireInternal(
217 const NavigationDetails
& details
) const {
221 base::string16
RequestQuotaInfoBarDelegate::GetMessageText() const {
222 // If the site requested larger quota than this threshold, show a different
223 // message to the user.
224 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_
));
231 bool RequestQuotaInfoBarDelegate::Accept() {
232 context_
->DispatchCallbackOnIOThread(
234 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW
);
238 bool RequestQuotaInfoBarDelegate::Cancel() {
239 context_
->DispatchCallbackOnIOThread(
241 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED
);
248 // ChromeQuotaPermissionContext -----------------------------------------------
250 ChromeQuotaPermissionContext::ChromeQuotaPermissionContext() {
253 void ChromeQuotaPermissionContext::RequestQuotaPermission(
254 const content::StorageQuotaParams
& params
,
255 int render_process_id
,
256 const PermissionCallback
& callback
) {
257 if (params
.storage_type
!= quota::kStorageTypePersistent
) {
258 // For now we only support requesting quota with this interface
259 // for Persistent storage type.
260 callback
.Run(QUOTA_PERMISSION_RESPONSE_DISALLOW
);
264 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
)) {
265 content::BrowserThread::PostTask(
266 content::BrowserThread::UI
, FROM_HERE
,
267 base::Bind(&ChromeQuotaPermissionContext::RequestQuotaPermission
, this,
268 params
, render_process_id
, callback
));
272 content::WebContents
* web_contents
=
273 tab_util::GetWebContentsByID(render_process_id
,
274 params
.render_view_id
);
276 // The tab may have gone away or the request may not be from a tab.
277 LOG(WARNING
) << "Attempt to request quota tabless renderer: "
278 << render_process_id
<< "," << params
.render_view_id
;
279 DispatchCallbackOnIOThread(callback
, QUOTA_PERMISSION_RESPONSE_CANCELLED
);
283 if (PermissionBubbleManager::Enabled()) {
284 PermissionBubbleManager
* bubble_manager
=
285 PermissionBubbleManager::FromWebContents(web_contents
);
286 if (bubble_manager
) {
287 bubble_manager
->AddRequest(new QuotaPermissionRequest(this,
288 params
.origin_url
, params
.requested_size
, params
.user_gesture
,
289 Profile::FromBrowserContext(web_contents
->GetBrowserContext())->
290 GetPrefs()->GetString(prefs::kAcceptLanguages
),
296 InfoBarService
* infobar_service
=
297 InfoBarService::FromWebContents(web_contents
);
298 if (!infobar_service
) {
299 // The tab has no infobar service.
300 LOG(WARNING
) << "Attempt to request quota from a background page: "
301 << render_process_id
<< "," << params
.render_view_id
;
302 DispatchCallbackOnIOThread(callback
, QUOTA_PERMISSION_RESPONSE_CANCELLED
);
305 RequestQuotaInfoBarDelegate::Create(
306 infobar_service
, this, params
.origin_url
, params
.requested_size
,
307 Profile::FromBrowserContext(web_contents
->GetBrowserContext())->
308 GetPrefs()->GetString(prefs::kAcceptLanguages
),
312 void ChromeQuotaPermissionContext::DispatchCallbackOnIOThread(
313 const PermissionCallback
& callback
,
314 QuotaPermissionResponse response
) {
315 DCHECK_EQ(false, callback
.is_null());
317 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
)) {
318 content::BrowserThread::PostTask(
319 content::BrowserThread::IO
, FROM_HERE
,
320 base::Bind(&ChromeQuotaPermissionContext::DispatchCallbackOnIOThread
,
321 this, callback
, response
));
325 callback
.Run(response
);
328 ChromeQuotaPermissionContext::~ChromeQuotaPermissionContext() {}