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.h"
14 #include "chrome/browser/infobars/infobar_service.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/tab_contents/tab_util.h"
17 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
18 #include "chrome/browser/ui/website_settings/permission_bubble_request.h"
19 #include "chrome/common/pref_names.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 "net/base/net_util.h"
26 #include "ui/base/l10n/l10n_util.h"
28 #include "webkit/common/quota/quota_types.h"
32 // If the site requested larger quota than this threshold, show a different
33 // message to the user.
34 const int64 kRequestLargeQuotaThreshold
= 5 * 1024 * 1024;
36 // QuotaPermissionRequest ---------------------------------------------
38 class QuotaPermissionRequest
: public PermissionBubbleRequest
{
40 QuotaPermissionRequest(
41 ChromeQuotaPermissionContext
* context
,
42 const GURL
& origin_url
,
43 int64 requested_quota
,
44 const std::string
& display_languages
,
45 const content::QuotaPermissionContext::PermissionCallback
& callback
);
47 virtual ~QuotaPermissionRequest();
49 // PermissionBubbleRequest:
50 virtual base::string16
GetMessageText() const OVERRIDE
;
51 virtual base::string16
GetMessageTextFragment() const OVERRIDE
;
52 virtual base::string16
GetAlternateAcceptButtonText() const OVERRIDE
;
53 virtual base::string16
GetAlternateDenyButtonText() const OVERRIDE
;
54 virtual void PermissionGranted() OVERRIDE
;
55 virtual void PermissionDenied() OVERRIDE
;
56 virtual void Cancelled() OVERRIDE
;
57 virtual void RequestFinished() OVERRIDE
;
60 scoped_refptr
<ChromeQuotaPermissionContext
> context_
;
62 std::string display_languages_
;
63 int64 requested_quota_
;
64 content::QuotaPermissionContext::PermissionCallback callback_
;
66 DISALLOW_COPY_AND_ASSIGN(QuotaPermissionRequest
);
69 QuotaPermissionRequest::QuotaPermissionRequest(
70 ChromeQuotaPermissionContext
* context
,
71 const GURL
& origin_url
,
72 int64 requested_quota
,
73 const std::string
& display_languages
,
74 const content::QuotaPermissionContext::PermissionCallback
& callback
)
76 origin_url_(origin_url
),
77 display_languages_(display_languages
),
78 requested_quota_(requested_quota
),
79 callback_(callback
) {}
81 QuotaPermissionRequest::~QuotaPermissionRequest() {}
83 base::string16
QuotaPermissionRequest::GetMessageText() const {
84 return l10n_util::GetStringFUTF16(
85 (requested_quota_
> kRequestLargeQuotaThreshold
?
86 IDS_REQUEST_LARGE_QUOTA_INFOBAR_QUESTION
:
87 IDS_REQUEST_QUOTA_INFOBAR_QUESTION
),
88 net::FormatUrl(origin_url_
, display_languages_
));
91 base::string16
QuotaPermissionRequest::GetMessageTextFragment() const {
92 return l10n_util::GetStringUTF16(IDS_REQUEST_QUOTA_PERMISSION_FRAGMENT
);
95 base::string16
QuotaPermissionRequest::GetAlternateAcceptButtonText() const {
96 return base::string16();
99 base::string16
QuotaPermissionRequest::GetAlternateDenyButtonText() const {
100 return base::string16();
103 void QuotaPermissionRequest::PermissionGranted() {
104 context_
->DispatchCallbackOnIOThread(
106 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW
);
107 callback_
= content::QuotaPermissionContext::PermissionCallback();
110 void QuotaPermissionRequest::PermissionDenied() {
111 context_
->DispatchCallbackOnIOThread(
113 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_DISALLOW
);
114 callback_
= content::QuotaPermissionContext::PermissionCallback();
117 void QuotaPermissionRequest::Cancelled() {
120 void QuotaPermissionRequest::RequestFinished() {
121 if (!callback_
.is_null()) {
122 context_
->DispatchCallbackOnIOThread(
124 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED
);
131 // RequestQuotaInfoBarDelegate ------------------------------------------------
133 class RequestQuotaInfoBarDelegate
: public ConfirmInfoBarDelegate
{
135 // Creates a request quota infobar and delegate and adds the infobar to
136 // |infobar_service|.
138 InfoBarService
* infobar_service
,
139 ChromeQuotaPermissionContext
* context
,
140 const GURL
& origin_url
,
141 int64 requested_quota
,
142 const std::string
& display_languages
,
143 const content::QuotaPermissionContext::PermissionCallback
& callback
);
146 RequestQuotaInfoBarDelegate(
147 ChromeQuotaPermissionContext
* context
,
148 const GURL
& origin_url
,
149 int64 requested_quota
,
150 const std::string
& display_languages
,
151 const content::QuotaPermissionContext::PermissionCallback
& callback
);
152 virtual ~RequestQuotaInfoBarDelegate();
154 // ConfirmInfoBarDelegate:
155 virtual bool ShouldExpireInternal(
156 const content::LoadCommittedDetails
& details
) const OVERRIDE
;
157 virtual base::string16
GetMessageText() const OVERRIDE
;
158 virtual bool Accept() OVERRIDE
;
159 virtual bool Cancel() OVERRIDE
;
161 scoped_refptr
<ChromeQuotaPermissionContext
> context_
;
163 std::string display_languages_
;
164 int64 requested_quota_
;
165 content::QuotaPermissionContext::PermissionCallback callback_
;
167 DISALLOW_COPY_AND_ASSIGN(RequestQuotaInfoBarDelegate
);
171 void RequestQuotaInfoBarDelegate::Create(
172 InfoBarService
* infobar_service
,
173 ChromeQuotaPermissionContext
* context
,
174 const GURL
& origin_url
,
175 int64 requested_quota
,
176 const std::string
& display_languages
,
177 const content::QuotaPermissionContext::PermissionCallback
& callback
) {
178 infobar_service
->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
179 scoped_ptr
<ConfirmInfoBarDelegate
>(new RequestQuotaInfoBarDelegate(
180 context
, origin_url
, requested_quota
, display_languages
, callback
))));
183 RequestQuotaInfoBarDelegate::RequestQuotaInfoBarDelegate(
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 : ConfirmInfoBarDelegate(),
191 origin_url_(origin_url
),
192 display_languages_(display_languages
),
193 requested_quota_(requested_quota
),
194 callback_(callback
) {
197 RequestQuotaInfoBarDelegate::~RequestQuotaInfoBarDelegate() {
198 if (!callback_
.is_null()) {
199 context_
->DispatchCallbackOnIOThread(
201 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED
);
205 bool RequestQuotaInfoBarDelegate::ShouldExpireInternal(
206 const content::LoadCommittedDetails
& details
) const {
210 base::string16
RequestQuotaInfoBarDelegate::GetMessageText() const {
211 // If the site requested larger quota than this threshold, show a different
212 // message to the user.
213 return l10n_util::GetStringFUTF16(
214 (requested_quota_
> kRequestLargeQuotaThreshold
?
215 IDS_REQUEST_LARGE_QUOTA_INFOBAR_QUESTION
:
216 IDS_REQUEST_QUOTA_INFOBAR_QUESTION
),
217 net::FormatUrl(origin_url_
, display_languages_
));
220 bool RequestQuotaInfoBarDelegate::Accept() {
221 context_
->DispatchCallbackOnIOThread(
223 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW
);
227 bool RequestQuotaInfoBarDelegate::Cancel() {
228 context_
->DispatchCallbackOnIOThread(
230 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED
);
237 // ChromeQuotaPermissionContext -----------------------------------------------
239 ChromeQuotaPermissionContext::ChromeQuotaPermissionContext() {
242 void ChromeQuotaPermissionContext::RequestQuotaPermission(
243 const GURL
& origin_url
,
244 quota::StorageType type
,
245 int64 requested_quota
,
246 int render_process_id
,
248 const PermissionCallback
& callback
) {
249 if (type
!= quota::kStorageTypePersistent
) {
250 // For now we only support requesting quota with this interface
251 // for Persistent storage type.
252 callback
.Run(QUOTA_PERMISSION_RESPONSE_DISALLOW
);
256 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
)) {
257 content::BrowserThread::PostTask(
258 content::BrowserThread::UI
, FROM_HERE
,
259 base::Bind(&ChromeQuotaPermissionContext::RequestQuotaPermission
, this,
260 origin_url
, type
, requested_quota
, render_process_id
,
261 render_view_id
, callback
));
265 content::WebContents
* web_contents
=
266 tab_util::GetWebContentsByID(render_process_id
, render_view_id
);
268 // The tab may have gone away or the request may not be from a tab.
269 LOG(WARNING
) << "Attempt to request quota tabless renderer: "
270 << render_process_id
<< "," << render_view_id
;
271 DispatchCallbackOnIOThread(callback
, QUOTA_PERMISSION_RESPONSE_CANCELLED
);
275 if (PermissionBubbleManager::Enabled()) {
276 PermissionBubbleManager
* bubble_manager
=
277 PermissionBubbleManager::FromWebContents(web_contents
);
278 bubble_manager
->AddRequest(new QuotaPermissionRequest(this,
279 origin_url
, requested_quota
,
280 Profile::FromBrowserContext(web_contents
->GetBrowserContext())->
281 GetPrefs()->GetString(prefs::kAcceptLanguages
),
286 InfoBarService
* infobar_service
=
287 InfoBarService::FromWebContents(web_contents
);
288 if (!infobar_service
) {
289 // The tab has no infobar service.
290 LOG(WARNING
) << "Attempt to request quota from a background page: "
291 << render_process_id
<< "," << render_view_id
;
292 DispatchCallbackOnIOThread(callback
, QUOTA_PERMISSION_RESPONSE_CANCELLED
);
295 RequestQuotaInfoBarDelegate::Create(
296 infobar_service
, this, origin_url
, requested_quota
,
297 Profile::FromBrowserContext(web_contents
->GetBrowserContext())->
298 GetPrefs()->GetString(prefs::kAcceptLanguages
),
302 void ChromeQuotaPermissionContext::DispatchCallbackOnIOThread(
303 const PermissionCallback
& callback
,
304 QuotaPermissionResponse response
) {
305 DCHECK_EQ(false, callback
.is_null());
307 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
)) {
308 content::BrowserThread::PostTask(
309 content::BrowserThread::IO
, FROM_HERE
,
310 base::Bind(&ChromeQuotaPermissionContext::DispatchCallbackOnIOThread
,
311 this, callback
, response
));
315 callback
.Run(response
);
318 ChromeQuotaPermissionContext::~ChromeQuotaPermissionContext() {}