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. 4 5 #include "chrome/browser/chrome_quota_permission_context.h" 6 7 #include <string> 8 9 #include "base/bind.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/common/pref_names.h" 17 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/navigation_details.h" 19 #include "content/public/browser/web_contents.h" 20 #include "grit/generated_resources.h" 21 #include "grit/locale_settings.h" 22 #include "net/base/net_util.h" 23 #include "ui/base/l10n/l10n_util.h" 24 #include "url/gurl.h" 25 #include "webkit/common/quota/quota_types.h" 26 27 28 29 // RequestQuotaInfoBarDelegate ------------------------------------------------ 30 31 namespace { 32 33 class RequestQuotaInfoBarDelegate : public ConfirmInfoBarDelegate { 34 public: 35 // Creates a request quota infobar delegate and adds it to |infobar_service|. 36 static void Create( 37 InfoBarService* infobar_service, 38 ChromeQuotaPermissionContext* context, 39 const GURL& origin_url, 40 int64 requested_quota, 41 const std::string& display_languages, 42 const content::QuotaPermissionContext::PermissionCallback& callback); 43 44 private: 45 RequestQuotaInfoBarDelegate( 46 InfoBarService* infobar_service, 47 ChromeQuotaPermissionContext* context, 48 const GURL& origin_url, 49 int64 requested_quota, 50 const std::string& display_languages, 51 const content::QuotaPermissionContext::PermissionCallback& callback); 52 virtual ~RequestQuotaInfoBarDelegate(); 53 54 // ConfirmInfoBarDelegate: 55 virtual bool ShouldExpireInternal( 56 const content::LoadCommittedDetails& details) const OVERRIDE; 57 virtual string16 GetMessageText() const OVERRIDE; 58 virtual bool Accept() OVERRIDE; 59 virtual bool Cancel() OVERRIDE; 60 61 scoped_refptr<ChromeQuotaPermissionContext> context_; 62 GURL origin_url_; 63 std::string display_languages_; 64 int64 requested_quota_; 65 content::QuotaPermissionContext::PermissionCallback callback_; 66 67 DISALLOW_COPY_AND_ASSIGN(RequestQuotaInfoBarDelegate); 68 }; 69 70 // static 71 void RequestQuotaInfoBarDelegate::Create( 72 InfoBarService* infobar_service, 73 ChromeQuotaPermissionContext* context, 74 const GURL& origin_url, 75 int64 requested_quota, 76 const std::string& display_languages, 77 const content::QuotaPermissionContext::PermissionCallback& callback) { 78 infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>( 79 new RequestQuotaInfoBarDelegate(infobar_service, context, origin_url, 80 requested_quota, display_languages, 81 callback))); 82 } 83 84 RequestQuotaInfoBarDelegate::RequestQuotaInfoBarDelegate( 85 InfoBarService* infobar_service, 86 ChromeQuotaPermissionContext* context, 87 const GURL& origin_url, 88 int64 requested_quota, 89 const std::string& display_languages, 90 const content::QuotaPermissionContext::PermissionCallback& callback) 91 : ConfirmInfoBarDelegate(infobar_service), 92 context_(context), 93 origin_url_(origin_url), 94 display_languages_(display_languages), 95 requested_quota_(requested_quota), 96 callback_(callback) { 97 } 98 99 RequestQuotaInfoBarDelegate::~RequestQuotaInfoBarDelegate() { 100 if (!callback_.is_null()) { 101 context_->DispatchCallbackOnIOThread( 102 callback_, 103 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED); 104 } 105 } 106 107 bool RequestQuotaInfoBarDelegate::ShouldExpireInternal( 108 const content::LoadCommittedDetails& details) const { 109 return false; 110 } 111 112 string16 RequestQuotaInfoBarDelegate::GetMessageText() const { 113 // If the site requested larger quota than this threshold, show a different 114 // message to the user. 115 const int64 kRequestLargeQuotaThreshold = 5 * 1024 * 1024; 116 return l10n_util::GetStringFUTF16( 117 (requested_quota_ > kRequestLargeQuotaThreshold ? 118 IDS_REQUEST_LARGE_QUOTA_INFOBAR_QUESTION : 119 IDS_REQUEST_QUOTA_INFOBAR_QUESTION), 120 net::FormatUrl(origin_url_, display_languages_)); 121 } 122 123 bool RequestQuotaInfoBarDelegate::Accept() { 124 context_->DispatchCallbackOnIOThread( 125 callback_, 126 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW); 127 return true; 128 } 129 130 bool RequestQuotaInfoBarDelegate::Cancel() { 131 context_->DispatchCallbackOnIOThread( 132 callback_, 133 content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED); 134 return true; 135 } 136 137 } // namespace 138 139 140 // ChromeQuotaPermissionContext ----------------------------------------------- 141 142 ChromeQuotaPermissionContext::ChromeQuotaPermissionContext() { 143 } 144 145 void ChromeQuotaPermissionContext::RequestQuotaPermission( 146 const GURL& origin_url, 147 quota::StorageType type, 148 int64 requested_quota, 149 int render_process_id, 150 int render_view_id, 151 const PermissionCallback& callback) { 152 if (type != quota::kStorageTypePersistent) { 153 // For now we only support requesting quota with this interface 154 // for Persistent storage type. 155 callback.Run(QUOTA_PERMISSION_RESPONSE_DISALLOW); 156 return; 157 } 158 159 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { 160 content::BrowserThread::PostTask( 161 content::BrowserThread::UI, FROM_HERE, 162 base::Bind(&ChromeQuotaPermissionContext::RequestQuotaPermission, this, 163 origin_url, type, requested_quota, render_process_id, 164 render_view_id, callback)); 165 return; 166 } 167 168 content::WebContents* web_contents = 169 tab_util::GetWebContentsByID(render_process_id, render_view_id); 170 if (!web_contents) { 171 // The tab may have gone away or the request may not be from a tab. 172 LOG(WARNING) << "Attempt to request quota tabless renderer: " 173 << render_process_id << "," << render_view_id; 174 DispatchCallbackOnIOThread(callback, QUOTA_PERMISSION_RESPONSE_CANCELLED); 175 return; 176 } 177 178 InfoBarService* infobar_service = 179 InfoBarService::FromWebContents(web_contents); 180 if (!infobar_service) { 181 // The tab has no infobar service. 182 LOG(WARNING) << "Attempt to request quota from a background page: " 183 << render_process_id << "," << render_view_id; 184 DispatchCallbackOnIOThread(callback, QUOTA_PERMISSION_RESPONSE_CANCELLED); 185 return; 186 } 187 RequestQuotaInfoBarDelegate::Create( 188 infobar_service, this, origin_url, requested_quota, 189 Profile::FromBrowserContext(web_contents->GetBrowserContext())-> 190 GetPrefs()->GetString(prefs::kAcceptLanguages), 191 callback); 192 } 193 194 void ChromeQuotaPermissionContext::DispatchCallbackOnIOThread( 195 const PermissionCallback& callback, 196 QuotaPermissionResponse response) { 197 DCHECK_EQ(false, callback.is_null()); 198 199 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) { 200 content::BrowserThread::PostTask( 201 content::BrowserThread::IO, FROM_HERE, 202 base::Bind(&ChromeQuotaPermissionContext::DispatchCallbackOnIOThread, 203 this, callback, response)); 204 return; 205 } 206 207 callback.Run(response); 208 } 209 210 ChromeQuotaPermissionContext::~ChromeQuotaPermissionContext() {} 211