blob: b10a864a1ed009e9b92b2cbca17db79a47646754 [file] [log] [blame]
[email protected]2a3a0592013-02-22 18:53:041// 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/browser/aw_quota_manager_bridge.h"
6
ctzsm8cfa2b452017-05-19 03:54:227#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 "base/synchronization/waitable_event.h"
14#include "content/public/browser/browser_thread.h"
15#include "content/public/browser/storage_partition.h"
16#include "content/public/common/content_client.h"
17#include "jni/AwQuotaManagerBridge_jni.h"
18#include "storage/browser/quota/quota_manager.h"
Sasha Bermeisterb8957f82018-01-04 04:17:4019#include "third_party/WebKit/common/quota/quota_types.mojom.h"
ctzsm8cfa2b452017-05-19 03:54:2220#include "url/gurl.h"
21
22using base::android::AttachCurrentThread;
23using base::android::JavaParamRef;
24using base::android::ScopedJavaLocalRef;
25using content::BrowserThread;
26using content::StoragePartition;
27using storage::QuotaClient;
28using storage::QuotaManager;
29
[email protected]2a3a0592013-02-22 18:53:0430namespace android_webview {
[email protected]1a64c312013-10-08 12:56:2631
ctzsm8cfa2b452017-05-19 03:54:2232namespace {
33
34// This object lives on UI and IO threads. Care need to be taken to make sure
35// there are no concurrent accesses to instance variables. Also this object
36// is refcounted in the various callbacks, and is destroyed when all callbacks
37// are destroyed at the end of DoneOnUIThread.
38class GetOriginsTask : public base::RefCountedThreadSafe<GetOriginsTask> {
39 public:
40 GetOriginsTask(const AwQuotaManagerBridge::GetOriginsCallback& callback,
41 QuotaManager* quota_manager);
42
43 void Run();
44
45 private:
46 friend class base::RefCountedThreadSafe<GetOriginsTask>;
47 ~GetOriginsTask();
48
49 void OnOriginsObtained(const std::set<GURL>& origins,
Sasha Bermeisterb8957f82018-01-04 04:17:4050 blink::mojom::StorageType type);
ctzsm8cfa2b452017-05-19 03:54:2251
52 void OnUsageAndQuotaObtained(const GURL& origin,
Sasha Bermeisterb8957f82018-01-04 04:17:4053 blink::mojom::QuotaStatusCode status_code,
ctzsm8cfa2b452017-05-19 03:54:2254 int64_t usage,
55 int64_t quota);
56
57 void CheckDone();
58 void DoneOnUIThread();
59
60 AwQuotaManagerBridge::GetOriginsCallback ui_callback_;
61 scoped_refptr<QuotaManager> quota_manager_;
62
63 std::vector<std::string> origin_;
64 std::vector<int64_t> usage_;
65 std::vector<int64_t> quota_;
66
67 size_t num_callbacks_to_wait_;
68 size_t num_callbacks_received_;
69
70 DISALLOW_COPY_AND_ASSIGN(GetOriginsTask);
71};
72
73GetOriginsTask::GetOriginsTask(
74 const AwQuotaManagerBridge::GetOriginsCallback& callback,
75 QuotaManager* quota_manager)
76 : ui_callback_(callback), quota_manager_(quota_manager) {
77 DCHECK_CURRENTLY_ON(BrowserThread::UI);
78}
79
80GetOriginsTask::~GetOriginsTask() {}
81
82void GetOriginsTask::Run() {
83 DCHECK_CURRENTLY_ON(BrowserThread::UI);
84 BrowserThread::PostTask(
85 BrowserThread::IO, FROM_HERE,
86 base::Bind(&QuotaManager::GetOriginsModifiedSince, quota_manager_,
Sasha Bermeisterb8957f82018-01-04 04:17:4087 blink::mojom::StorageType::kTemporary,
ctzsm8cfa2b452017-05-19 03:54:2288 base::Time() /* Since beginning of time. */,
89 base::Bind(&GetOriginsTask::OnOriginsObtained, this)));
90}
91
92void GetOriginsTask::OnOriginsObtained(const std::set<GURL>& origins,
Sasha Bermeisterb8957f82018-01-04 04:17:4093 blink::mojom::StorageType type) {
ctzsm8cfa2b452017-05-19 03:54:2294 DCHECK_CURRENTLY_ON(BrowserThread::IO);
95 num_callbacks_to_wait_ = origins.size();
96 num_callbacks_received_ = 0u;
97
98 for (std::set<GURL>::const_iterator origin = origins.begin();
99 origin != origins.end(); ++origin) {
100 quota_manager_->GetUsageAndQuota(
101 *origin, type,
102 base::Bind(&GetOriginsTask::OnUsageAndQuotaObtained, this, *origin));
103 }
104
105 CheckDone();
106}
107
Sasha Bermeisterb8957f82018-01-04 04:17:40108void GetOriginsTask::OnUsageAndQuotaObtained(
109 const GURL& origin,
110 blink::mojom::QuotaStatusCode status_code,
111 int64_t usage,
112 int64_t quota) {
ctzsm8cfa2b452017-05-19 03:54:22113 DCHECK_CURRENTLY_ON(BrowserThread::IO);
Sasha Bermeisterb8957f82018-01-04 04:17:40114 if (status_code == blink::mojom::QuotaStatusCode::kOk) {
ctzsm8cfa2b452017-05-19 03:54:22115 origin_.push_back(origin.spec());
116 usage_.push_back(usage);
117 quota_.push_back(quota);
118 }
119
120 ++num_callbacks_received_;
121 CheckDone();
122}
123
124void GetOriginsTask::CheckDone() {
125 DCHECK_CURRENTLY_ON(BrowserThread::IO);
126 if (num_callbacks_received_ == num_callbacks_to_wait_) {
127 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
128 base::Bind(&GetOriginsTask::DoneOnUIThread, this));
129 } else if (num_callbacks_received_ > num_callbacks_to_wait_) {
130 NOTREACHED();
131 }
132}
133
134// This method is to avoid copying the 3 vector arguments into a bound callback.
135void GetOriginsTask::DoneOnUIThread() {
136 DCHECK_CURRENTLY_ON(BrowserThread::UI);
137 ui_callback_.Run(origin_, usage_, quota_);
138}
139
140void RunOnUIThread(const base::Closure& task) {
141 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
142 task.Run();
143 } else {
144 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, task);
145 }
146}
147
148} // namespace
149
150// static
Daniel Bratell7aacf952017-11-21 17:51:25151jlong JNI_AwQuotaManagerBridge_GetDefaultNativeAwQuotaManagerBridge(
152 JNIEnv* env,
153 const JavaParamRef<jclass>& clazz) {
ctzsm8cfa2b452017-05-19 03:54:22154 AwBrowserContext* browser_context =
155 AwContentBrowserClient::GetAwBrowserContext();
156
157 AwQuotaManagerBridge* bridge = static_cast<AwQuotaManagerBridge*>(
158 browser_context->GetQuotaManagerBridge());
159 DCHECK(bridge);
160 return reinterpret_cast<intptr_t>(bridge);
161}
162
163// static
164scoped_refptr<AwQuotaManagerBridge> AwQuotaManagerBridge::Create(
165 AwBrowserContext* browser_context) {
166 return new AwQuotaManagerBridge(browser_context);
167}
168
169AwQuotaManagerBridge::AwQuotaManagerBridge(AwBrowserContext* browser_context)
170 : browser_context_(browser_context), weak_factory_(this) {}
[email protected]1a64c312013-10-08 12:56:26171
[email protected]2a3a0592013-02-22 18:53:04172AwQuotaManagerBridge::~AwQuotaManagerBridge() {}
[email protected]1a64c312013-10-08 12:56:26173
ctzsm8cfa2b452017-05-19 03:54:22174void AwQuotaManagerBridge::Init(JNIEnv* env,
175 const JavaParamRef<jobject>& object) {
176 java_ref_ = JavaObjectWeakGlobalRef(env, object);
177}
178
179StoragePartition* AwQuotaManagerBridge::GetStoragePartition() const {
180 DCHECK_CURRENTLY_ON(BrowserThread::UI);
181
182 // AndroidWebview does not use per-site storage partitions.
183 StoragePartition* storage_partition =
184 content::BrowserContext::GetDefaultStoragePartition(browser_context_);
185 DCHECK(storage_partition);
186 return storage_partition;
187}
188
189QuotaManager* AwQuotaManagerBridge::GetQuotaManager() const {
190 DCHECK_CURRENTLY_ON(BrowserThread::UI);
191
192 QuotaManager* quota_manager = GetStoragePartition()->GetQuotaManager();
193 DCHECK(quota_manager);
194 return quota_manager;
195}
196
197void AwQuotaManagerBridge::DeleteAllData(JNIEnv* env,
198 const JavaParamRef<jobject>& object) {
199 RunOnUIThread(
200 base::Bind(&AwQuotaManagerBridge::DeleteAllDataOnUiThread, this));
201}
202
203void AwQuotaManagerBridge::DeleteAllDataOnUiThread() {
204 DCHECK_CURRENTLY_ON(BrowserThread::UI);
205 GetStoragePartition()->ClearData(
206 // Clear all web storage data except cookies.
207 StoragePartition::REMOVE_DATA_MASK_APPCACHE |
208 StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
209 StoragePartition::REMOVE_DATA_MASK_INDEXEDDB |
210 StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE |
211 StoragePartition::REMOVE_DATA_MASK_WEBSQL,
212 StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY, GURL(),
213 StoragePartition::OriginMatcherFunction(), base::Time(),
214 base::Time::Max(), base::Bind(&base::DoNothing));
215}
216
217void AwQuotaManagerBridge::DeleteOrigin(JNIEnv* env,
218 const JavaParamRef<jobject>& object,
219 const JavaParamRef<jstring>& origin) {
220 base::string16 origin_string(
221 base::android::ConvertJavaStringToUTF16(env, origin));
222 RunOnUIThread(base::Bind(&AwQuotaManagerBridge::DeleteOriginOnUiThread, this,
223 origin_string));
224}
225
226void AwQuotaManagerBridge::DeleteOriginOnUiThread(
227 const base::string16& origin) {
228 DCHECK_CURRENTLY_ON(BrowserThread::UI);
229 StoragePartition* storage_partition = GetStoragePartition();
230 storage_partition->ClearDataForOrigin(
231 // All (temporary) QuotaClient types.
232 StoragePartition::REMOVE_DATA_MASK_APPCACHE |
233 StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
234 StoragePartition::REMOVE_DATA_MASK_INDEXEDDB |
235 StoragePartition::REMOVE_DATA_MASK_WEBSQL,
Randy Smith9512b33d2017-12-12 19:57:55236 StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY, GURL(origin));
ctzsm8cfa2b452017-05-19 03:54:22237}
238
239void AwQuotaManagerBridge::GetOrigins(JNIEnv* env,
240 const JavaParamRef<jobject>& object,
241 jint callback_id) {
242 RunOnUIThread(base::Bind(&AwQuotaManagerBridge::GetOriginsOnUiThread, this,
243 callback_id));
244}
245
246void AwQuotaManagerBridge::GetOriginsOnUiThread(jint callback_id) {
247 DCHECK_CURRENTLY_ON(BrowserThread::UI);
248
249 const GetOriginsCallback ui_callback =
250 base::Bind(&AwQuotaManagerBridge::GetOriginsCallbackImpl,
251 weak_factory_.GetWeakPtr(), callback_id);
252
253 (new GetOriginsTask(ui_callback, GetQuotaManager()))->Run();
254}
255
256void AwQuotaManagerBridge::GetOriginsCallbackImpl(
257 int jcallback_id,
258 const std::vector<std::string>& origin,
259 const std::vector<int64_t>& usage,
260 const std::vector<int64_t>& quota) {
261 DCHECK_CURRENTLY_ON(BrowserThread::UI);
262 JNIEnv* env = AttachCurrentThread();
263 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
264 if (obj.is_null())
265 return;
266
267 Java_AwQuotaManagerBridge_onGetOriginsCallback(
268 env, obj, jcallback_id, base::android::ToJavaArrayOfStrings(env, origin),
269 base::android::ToJavaLongArray(env, usage),
270 base::android::ToJavaLongArray(env, quota));
271}
272
273namespace {
274
275void OnUsageAndQuotaObtained(
276 const AwQuotaManagerBridge::QuotaUsageCallback& ui_callback,
Sasha Bermeisterb8957f82018-01-04 04:17:40277 blink::mojom::QuotaStatusCode status_code,
ctzsm8cfa2b452017-05-19 03:54:22278 int64_t usage,
279 int64_t quota) {
280 DCHECK_CURRENTLY_ON(BrowserThread::IO);
Sasha Bermeisterb8957f82018-01-04 04:17:40281 if (status_code != blink::mojom::QuotaStatusCode::kOk) {
ctzsm8cfa2b452017-05-19 03:54:22282 usage = 0;
283 quota = 0;
284 }
285 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
286 base::Bind(ui_callback, usage, quota));
287}
288
289} // namespace
290
291void AwQuotaManagerBridge::GetUsageAndQuotaForOrigin(
292 JNIEnv* env,
293 const JavaParamRef<jobject>& object,
294 const JavaParamRef<jstring>& origin,
295 jint callback_id,
296 bool is_quota) {
297 base::string16 origin_string(
298 base::android::ConvertJavaStringToUTF16(env, origin));
299 RunOnUIThread(
300 base::Bind(&AwQuotaManagerBridge::GetUsageAndQuotaForOriginOnUiThread,
301 this, origin_string, callback_id, is_quota));
302}
303
304void AwQuotaManagerBridge::GetUsageAndQuotaForOriginOnUiThread(
305 const base::string16& origin,
306 jint callback_id,
307 bool is_quota) {
308 DCHECK_CURRENTLY_ON(BrowserThread::UI);
309 const QuotaUsageCallback ui_callback =
310 base::Bind(&AwQuotaManagerBridge::QuotaUsageCallbackImpl,
311 weak_factory_.GetWeakPtr(), callback_id, is_quota);
312
313 BrowserThread::PostTask(
314 BrowserThread::IO, FROM_HERE,
315 base::Bind(&QuotaManager::GetUsageAndQuota, GetQuotaManager(),
Sasha Bermeisterb8957f82018-01-04 04:17:40316 GURL(origin), blink::mojom::StorageType::kTemporary,
ctzsm8cfa2b452017-05-19 03:54:22317 base::Bind(&OnUsageAndQuotaObtained, ui_callback)));
318}
319
320void AwQuotaManagerBridge::QuotaUsageCallbackImpl(int jcallback_id,
321 bool is_quota,
322 int64_t usage,
323 int64_t quota) {
324 DCHECK_CURRENTLY_ON(BrowserThread::UI);
325 JNIEnv* env = AttachCurrentThread();
326 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
327 if (obj.is_null())
328 return;
329
330 Java_AwQuotaManagerBridge_onGetUsageAndQuotaForOriginCallback(
331 env, obj, jcallback_id, is_quota, usage, quota);
332}
333
[email protected]2a3a0592013-02-22 18:53:04334} // namespace android_webview