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