OLD | NEW |
| (Empty) |
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/browser/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 "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" | |
19 #include "storage/common/quota/quota_types.h" | |
20 #include "url/gurl.h" | |
21 | |
22 using base::android::AttachCurrentThread; | |
23 using base::android::JavaParamRef; | |
24 using base::android::ScopedJavaLocalRef; | |
25 using content::BrowserThread; | |
26 using content::StoragePartition; | |
27 using storage::QuotaClient; | |
28 using storage::QuotaManager; | |
29 | |
30 namespace android_webview { | |
31 | |
32 namespace { | |
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. | |
38 class GetOriginsTask : public base::RefCountedThreadSafe<GetOriginsTask> { | |
39 public: | |
40 GetOriginsTask(const AwQuotaManagerBridgeImpl::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, | |
50 storage::StorageType type); | |
51 | |
52 void OnUsageAndQuotaObtained(const GURL& origin, | |
53 storage::QuotaStatusCode status_code, | |
54 int64_t usage, | |
55 int64_t quota); | |
56 | |
57 void CheckDone(); | |
58 void DoneOnUIThread(); | |
59 | |
60 AwQuotaManagerBridgeImpl::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 | |
73 GetOriginsTask::GetOriginsTask( | |
74 const AwQuotaManagerBridgeImpl::GetOriginsCallback& callback, | |
75 QuotaManager* quota_manager) | |
76 : ui_callback_(callback), quota_manager_(quota_manager) { | |
77 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
78 } | |
79 | |
80 GetOriginsTask::~GetOriginsTask() {} | |
81 | |
82 void GetOriginsTask::Run() { | |
83 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
84 BrowserThread::PostTask( | |
85 BrowserThread::IO, FROM_HERE, | |
86 base::Bind(&QuotaManager::GetOriginsModifiedSince, quota_manager_, | |
87 storage::kStorageTypeTemporary, | |
88 base::Time() /* Since beginning of time. */, | |
89 base::Bind(&GetOriginsTask::OnOriginsObtained, this))); | |
90 } | |
91 | |
92 void GetOriginsTask::OnOriginsObtained(const std::set<GURL>& origins, | |
93 storage::StorageType type) { | |
94 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 | |
108 void GetOriginsTask::OnUsageAndQuotaObtained( | |
109 const GURL& origin, | |
110 storage::QuotaStatusCode status_code, | |
111 int64_t usage, | |
112 int64_t quota) { | |
113 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
114 if (status_code == storage::kQuotaStatusOk) { | |
115 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 | |
124 void 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. | |
135 void GetOriginsTask::DoneOnUIThread() { | |
136 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
137 ui_callback_.Run(origin_, usage_, quota_); | |
138 } | |
139 | |
140 void 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 | |
151 jlong GetDefaultNativeAwQuotaManagerBridge(JNIEnv* env, | |
152 const JavaParamRef<jclass>& clazz) { | |
153 AwBrowserContext* browser_context = | |
154 AwContentBrowserClient::GetAwBrowserContext(); | |
155 | |
156 AwQuotaManagerBridgeImpl* bridge = static_cast<AwQuotaManagerBridgeImpl*>( | |
157 browser_context->GetQuotaManagerBridge()); | |
158 DCHECK(bridge); | |
159 return reinterpret_cast<intptr_t>(bridge); | |
160 } | |
161 | |
162 // static | |
163 scoped_refptr<AwQuotaManagerBridge> AwQuotaManagerBridgeImpl::Create( | |
164 AwBrowserContext* browser_context) { | |
165 return new AwQuotaManagerBridgeImpl(browser_context); | |
166 } | |
167 | |
168 AwQuotaManagerBridgeImpl::AwQuotaManagerBridgeImpl( | |
169 AwBrowserContext* browser_context) | |
170 : browser_context_(browser_context), weak_factory_(this) {} | |
171 | |
172 AwQuotaManagerBridgeImpl::~AwQuotaManagerBridgeImpl() {} | |
173 | |
174 void AwQuotaManagerBridgeImpl::Init(JNIEnv* env, | |
175 const JavaParamRef<jobject>& object) { | |
176 java_ref_ = JavaObjectWeakGlobalRef(env, object); | |
177 } | |
178 | |
179 StoragePartition* AwQuotaManagerBridgeImpl::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 | |
189 QuotaManager* AwQuotaManagerBridgeImpl::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 | |
197 void AwQuotaManagerBridgeImpl::DeleteAllData( | |
198 JNIEnv* env, | |
199 const JavaParamRef<jobject>& object) { | |
200 RunOnUIThread( | |
201 base::Bind(&AwQuotaManagerBridgeImpl::DeleteAllDataOnUiThread, this)); | |
202 } | |
203 | |
204 void AwQuotaManagerBridgeImpl::DeleteAllDataOnUiThread() { | |
205 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
206 GetStoragePartition()->ClearData( | |
207 // Clear all web storage data except cookies. | |
208 StoragePartition::REMOVE_DATA_MASK_APPCACHE | | |
209 StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS | | |
210 StoragePartition::REMOVE_DATA_MASK_INDEXEDDB | | |
211 StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE | | |
212 StoragePartition::REMOVE_DATA_MASK_WEBSQL, | |
213 StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY, GURL(), | |
214 StoragePartition::OriginMatcherFunction(), base::Time(), | |
215 base::Time::Max(), base::Bind(&base::DoNothing)); | |
216 } | |
217 | |
218 void AwQuotaManagerBridgeImpl::DeleteOrigin( | |
219 JNIEnv* env, | |
220 const JavaParamRef<jobject>& object, | |
221 const JavaParamRef<jstring>& origin) { | |
222 base::string16 origin_string( | |
223 base::android::ConvertJavaStringToUTF16(env, origin)); | |
224 RunOnUIThread(base::Bind(&AwQuotaManagerBridgeImpl::DeleteOriginOnUiThread, | |
225 this, origin_string)); | |
226 } | |
227 | |
228 void AwQuotaManagerBridgeImpl::DeleteOriginOnUiThread( | |
229 const base::string16& origin) { | |
230 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
231 StoragePartition* storage_partition = GetStoragePartition(); | |
232 storage_partition->ClearDataForOrigin( | |
233 // All (temporary) QuotaClient types. | |
234 StoragePartition::REMOVE_DATA_MASK_APPCACHE | | |
235 StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS | | |
236 StoragePartition::REMOVE_DATA_MASK_INDEXEDDB | | |
237 StoragePartition::REMOVE_DATA_MASK_WEBSQL, | |
238 StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY, GURL(origin), | |
239 storage_partition->GetURLRequestContext(), base::Bind(&base::DoNothing)); | |
240 } | |
241 | |
242 void AwQuotaManagerBridgeImpl::GetOrigins(JNIEnv* env, | |
243 const JavaParamRef<jobject>& object, | |
244 jint callback_id) { | |
245 RunOnUIThread(base::Bind(&AwQuotaManagerBridgeImpl::GetOriginsOnUiThread, | |
246 this, callback_id)); | |
247 } | |
248 | |
249 void AwQuotaManagerBridgeImpl::GetOriginsOnUiThread(jint callback_id) { | |
250 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
251 | |
252 const GetOriginsCallback ui_callback = | |
253 base::Bind(&AwQuotaManagerBridgeImpl::GetOriginsCallbackImpl, | |
254 weak_factory_.GetWeakPtr(), callback_id); | |
255 | |
256 (new GetOriginsTask(ui_callback, GetQuotaManager()))->Run(); | |
257 } | |
258 | |
259 void AwQuotaManagerBridgeImpl::GetOriginsCallbackImpl( | |
260 int jcallback_id, | |
261 const std::vector<std::string>& origin, | |
262 const std::vector<int64_t>& usage, | |
263 const std::vector<int64_t>& quota) { | |
264 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
265 JNIEnv* env = AttachCurrentThread(); | |
266 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
267 if (obj.is_null()) | |
268 return; | |
269 | |
270 Java_AwQuotaManagerBridge_onGetOriginsCallback( | |
271 env, obj, jcallback_id, base::android::ToJavaArrayOfStrings(env, origin), | |
272 base::android::ToJavaLongArray(env, usage), | |
273 base::android::ToJavaLongArray(env, quota)); | |
274 } | |
275 | |
276 namespace { | |
277 | |
278 void OnUsageAndQuotaObtained( | |
279 const AwQuotaManagerBridgeImpl::QuotaUsageCallback& ui_callback, | |
280 storage::QuotaStatusCode status_code, | |
281 int64_t usage, | |
282 int64_t quota) { | |
283 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
284 if (status_code != storage::kQuotaStatusOk) { | |
285 usage = 0; | |
286 quota = 0; | |
287 } | |
288 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
289 base::Bind(ui_callback, usage, quota)); | |
290 } | |
291 | |
292 } // namespace | |
293 | |
294 void AwQuotaManagerBridgeImpl::GetUsageAndQuotaForOrigin( | |
295 JNIEnv* env, | |
296 const JavaParamRef<jobject>& object, | |
297 const JavaParamRef<jstring>& origin, | |
298 jint callback_id, | |
299 bool is_quota) { | |
300 base::string16 origin_string( | |
301 base::android::ConvertJavaStringToUTF16(env, origin)); | |
302 RunOnUIThread( | |
303 base::Bind(&AwQuotaManagerBridgeImpl::GetUsageAndQuotaForOriginOnUiThread, | |
304 this, origin_string, callback_id, is_quota)); | |
305 } | |
306 | |
307 void AwQuotaManagerBridgeImpl::GetUsageAndQuotaForOriginOnUiThread( | |
308 const base::string16& origin, | |
309 jint callback_id, | |
310 bool is_quota) { | |
311 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
312 const QuotaUsageCallback ui_callback = | |
313 base::Bind(&AwQuotaManagerBridgeImpl::QuotaUsageCallbackImpl, | |
314 weak_factory_.GetWeakPtr(), callback_id, is_quota); | |
315 | |
316 BrowserThread::PostTask( | |
317 BrowserThread::IO, FROM_HERE, | |
318 base::Bind(&QuotaManager::GetUsageAndQuota, GetQuotaManager(), | |
319 GURL(origin), storage::kStorageTypeTemporary, | |
320 base::Bind(&OnUsageAndQuotaObtained, ui_callback))); | |
321 } | |
322 | |
323 void AwQuotaManagerBridgeImpl::QuotaUsageCallbackImpl(int jcallback_id, | |
324 bool is_quota, | |
325 int64_t usage, | |
326 int64_t quota) { | |
327 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
328 JNIEnv* env = AttachCurrentThread(); | |
329 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
330 if (obj.is_null()) | |
331 return; | |
332 | |
333 Java_AwQuotaManagerBridge_onGetUsageAndQuotaForOriginCallback( | |
334 env, obj, jcallback_id, is_quota, usage, quota); | |
335 } | |
336 | |
337 bool RegisterAwQuotaManagerBridge(JNIEnv* env) { | |
338 return RegisterNativesImpl(env); | |
339 } | |
340 | |
341 } // namespace android_webview | |
OLD | NEW |