aw_quota_manager_bridge_impl.cc revision 868fa2fe829687343ffae624259930155e16dbd8
1// Copyright (c) 2013 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 "android_webview/native/aw_quota_manager_bridge_impl.h" 6 7#include <set> 8 9#include "android_webview/browser/aw_browser_context.h" 10#include "android_webview/browser/aw_content_browser_client.h" 11#include "base/android/jni_array.h" 12#include "base/android/jni_string.h" 13#include "content/public/browser/browser_thread.h" 14#include "content/public/browser/storage_partition.h" 15#include "content/public/common/content_client.h" 16#include "googleurl/src/gurl.h" 17#include "jni/AwQuotaManagerBridge_jni.h" 18#include "webkit/browser/quota/quota_manager.h" 19#include "webkit/common/quota/quota_types.h" 20 21using base::android::AttachCurrentThread; 22using content::BrowserThread; 23using content::StoragePartition; 24using quota::QuotaClient; 25using quota::QuotaManager; 26 27namespace android_webview { 28 29namespace { 30 31// This object lives on UI and IO threads. Care need to be taken to make sure 32// there are no concurrent accesses to instance variables. Also this object 33// is refcounted in the various callbacks, and is destroyed when all callbacks 34// are destroyed at the end of DoneOnUIThread. 35class GetOriginsTask : public base::RefCountedThreadSafe<GetOriginsTask> { 36 public: 37 GetOriginsTask( 38 const AwQuotaManagerBridgeImpl::GetOriginsCallback& callback, 39 QuotaManager* quota_manager); 40 41 void Run(); 42 43 private: 44 friend class base::RefCountedThreadSafe<GetOriginsTask>; 45 ~GetOriginsTask(); 46 47 void OnOriginsObtained(const std::set<GURL>& origins, 48 quota::StorageType type); 49 50 void OnUsageAndQuotaObtained(const GURL& origin, 51 quota::QuotaStatusCode status_code, 52 int64 usage, 53 int64 quota); 54 55 void CheckDone(); 56 void DoneOnUIThread(); 57 58 AwQuotaManagerBridgeImpl::GetOriginsCallback ui_callback_; 59 scoped_refptr<QuotaManager> quota_manager_; 60 61 std::vector<std::string> origin_; 62 std::vector<int64> usage_; 63 std::vector<int64> quota_; 64 65 size_t num_callbacks_to_wait_; 66 size_t num_callbacks_received_; 67 68 DISALLOW_COPY_AND_ASSIGN(GetOriginsTask); 69}; 70 71GetOriginsTask::GetOriginsTask( 72 const AwQuotaManagerBridgeImpl::GetOriginsCallback& callback, 73 QuotaManager* quota_manager) 74 : ui_callback_(callback), 75 quota_manager_(quota_manager) { 76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 77} 78 79GetOriginsTask::~GetOriginsTask() {} 80 81void GetOriginsTask::Run() { 82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 83 BrowserThread::PostTask( 84 BrowserThread::IO, 85 FROM_HERE, 86 base::Bind(&QuotaManager::GetOriginsModifiedSince, 87 quota_manager_, 88 quota::kStorageTypeTemporary, 89 base::Time() /* Since beginning of time. */, 90 base::Bind(&GetOriginsTask::OnOriginsObtained, this))); 91} 92 93void GetOriginsTask::OnOriginsObtained( 94 const std::set<GURL>& origins, quota::StorageType type) { 95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 96 num_callbacks_to_wait_ = origins.size(); 97 num_callbacks_received_ = 0u; 98 99 for (std::set<GURL>::const_iterator origin = origins.begin(); 100 origin != origins.end(); 101 ++origin) { 102 quota_manager_->GetUsageAndQuota( 103 *origin, 104 type, 105 base::Bind(&GetOriginsTask::OnUsageAndQuotaObtained, this, *origin)); 106 } 107 108 CheckDone(); 109} 110 111void GetOriginsTask::OnUsageAndQuotaObtained(const GURL& origin, 112 quota::QuotaStatusCode status_code, 113 int64 usage, 114 int64 quota) { 115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 116 if (status_code == quota::kQuotaStatusOk) { 117 origin_.push_back(origin.spec()); 118 usage_.push_back(usage); 119 quota_.push_back(quota); 120 } 121 122 ++num_callbacks_received_; 123 CheckDone(); 124} 125 126void GetOriginsTask::CheckDone() { 127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 128 if (num_callbacks_received_ == num_callbacks_to_wait_) { 129 BrowserThread::PostTask( 130 BrowserThread::UI, 131 FROM_HERE, 132 base::Bind(&GetOriginsTask::DoneOnUIThread, this)); 133 } else if (num_callbacks_received_ > num_callbacks_to_wait_) { 134 NOTREACHED(); 135 } 136} 137 138// This method is to avoid copying the 3 vector arguments into a bound callback. 139void GetOriginsTask::DoneOnUIThread() { 140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 141 ui_callback_.Run(origin_, usage_, quota_); 142} 143 144} // namespace 145 146 147// static 148jint GetDefaultNativeAwQuotaManagerBridge(JNIEnv* env, jclass clazz) { 149 AwBrowserContext* browser_context = 150 AwContentBrowserClient::GetAwBrowserContext(); 151 152 AwQuotaManagerBridgeImpl* bridge = static_cast<AwQuotaManagerBridgeImpl*>( 153 browser_context->GetQuotaManagerBridge()); 154 DCHECK(bridge); 155 return reinterpret_cast<jint>(bridge); 156} 157 158AwQuotaManagerBridgeImpl::AwQuotaManagerBridgeImpl( 159 AwBrowserContext* browser_context) 160 : weak_factory_(this), 161 browser_context_(browser_context) { 162} 163 164AwQuotaManagerBridgeImpl::~AwQuotaManagerBridgeImpl() {} 165 166void AwQuotaManagerBridgeImpl::Init(JNIEnv* env, jobject object) { 167 java_ref_ = JavaObjectWeakGlobalRef(env, object); 168} 169 170StoragePartition* AwQuotaManagerBridgeImpl::GetStoragePartition() const { 171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 172 173 // AndroidWebview does not use per-site storage partitions. 174 StoragePartition* storage_partition = 175 content::BrowserContext::GetDefaultStoragePartition(browser_context_); 176 DCHECK(storage_partition); 177 return storage_partition; 178} 179 180QuotaManager* AwQuotaManagerBridgeImpl::GetQuotaManager() const { 181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 182 183 QuotaManager* quota_manager = GetStoragePartition()->GetQuotaManager(); 184 DCHECK(quota_manager); 185 return quota_manager; 186} 187 188// Cannot directly call StoragePartition clear data methods because cookies are 189// controlled separately. 190void AwQuotaManagerBridgeImpl::DeleteAllData(JNIEnv* env, jobject object) { 191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 192 GetStoragePartition()->AsyncClearData( 193 StoragePartition::kQuotaManagedTemporaryStorage | 194 StoragePartition::kLocalDomStorage | 195 StoragePartition::kSessionDomStorage); 196} 197 198void AwQuotaManagerBridgeImpl::DeleteOrigin( 199 JNIEnv* env, jobject object, jstring origin) { 200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 201 StoragePartition* storage_partition = GetStoragePartition(); 202 storage_partition->AsyncClearDataForOrigin( 203 StoragePartition::kQuotaManagedTemporaryStorage, 204 GURL(base::android::ConvertJavaStringToUTF16(env, origin)), 205 storage_partition->GetURLRequestContext()); 206} 207 208void AwQuotaManagerBridgeImpl::GetOrigins( 209 JNIEnv* env, jobject object, jint callback_id) { 210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 211 212 const GetOriginsCallback ui_callback = base::Bind( 213 &AwQuotaManagerBridgeImpl::GetOriginsCallbackImpl, 214 weak_factory_.GetWeakPtr(), 215 callback_id); 216 217 (new GetOriginsTask(ui_callback, GetQuotaManager()))->Run(); 218} 219 220void AwQuotaManagerBridgeImpl::GetOriginsCallbackImpl( 221 int jcallback_id, 222 const std::vector<std::string>& origin, 223 const std::vector<int64>& usage, 224 const std::vector<int64>& quota) { 225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 226 JNIEnv* env = AttachCurrentThread(); 227 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 228 if (obj.is_null()) 229 return; 230 231 Java_AwQuotaManagerBridge_onGetOriginsCallback( 232 env, 233 obj.obj(), 234 jcallback_id, 235 base::android::ToJavaArrayOfStrings(env, origin).obj(), 236 base::android::ToJavaLongArray(env, usage).obj(), 237 base::android::ToJavaLongArray(env, quota).obj()); 238} 239 240namespace { 241 242void OnUsageAndQuotaObtained( 243 const AwQuotaManagerBridgeImpl::QuotaUsageCallback& ui_callback, 244 quota::QuotaStatusCode status_code, 245 int64 usage, 246 int64 quota) { 247 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 248 if (status_code != quota::kQuotaStatusOk) { 249 usage = 0; 250 quota = 0; 251 } 252 BrowserThread::PostTask( 253 BrowserThread::UI, 254 FROM_HERE, 255 base::Bind(ui_callback, usage, quota)); 256} 257 258} // namespace 259 260void AwQuotaManagerBridgeImpl::GetUsageAndQuotaForOrigin( 261 JNIEnv* env, jobject object, 262 jstring origin, 263 jint callback_id, 264 bool is_quota) { 265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 266 const QuotaUsageCallback ui_callback = base::Bind( 267 &AwQuotaManagerBridgeImpl::QuotaUsageCallbackImpl, 268 weak_factory_.GetWeakPtr(), 269 callback_id, 270 is_quota); 271 272 BrowserThread::PostTask( 273 BrowserThread::IO, 274 FROM_HERE, 275 base::Bind(&QuotaManager::GetUsageAndQuota, 276 GetQuotaManager(), 277 GURL(base::android::ConvertJavaStringToUTF16(env, origin)), 278 quota::kStorageTypeTemporary, 279 base::Bind(&OnUsageAndQuotaObtained, ui_callback))); 280} 281 282void AwQuotaManagerBridgeImpl::QuotaUsageCallbackImpl( 283 int jcallback_id, bool is_quota, int64 usage, int64 quota) { 284 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 285 JNIEnv* env = AttachCurrentThread(); 286 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 287 if (obj.is_null()) 288 return; 289 290 Java_AwQuotaManagerBridge_onGetUsageAndQuotaForOriginCallback( 291 env, obj.obj(), jcallback_id, is_quota, usage, quota); 292} 293 294bool RegisterAwQuotaManagerBridge(JNIEnv* env) { 295 return RegisterNativesImpl(env) >= 0; 296} 297 298} // namespace android_webview 299