Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2059)

Unified Diff: android_webview/native/aw_quota_manager_bridge.cc

Issue 12253057: Implement WebStorage API methods (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Implementation mostly done. Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: android_webview/native/aw_quota_manager_bridge.cc
diff --git a/android_webview/native/aw_quota_manager_bridge.cc b/android_webview/native/aw_quota_manager_bridge.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d7058cce98ffb8c5afa05795b737705fb1c8c8d8
--- /dev/null
+++ b/android_webview/native/aw_quota_manager_bridge.cc
@@ -0,0 +1,417 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "android_webview/native/aw_quota_manager_bridge.h"
+
+#include "android_webview/browser/aw_browser_context.h"
+#include "android_webview/browser/aw_content_browser_client.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/common/content_client.h"
+#include "googleurl/src/gurl.h"
+#include "jni/AwQuotaManagerBridge_jni.h"
+#include "webkit/quota/quota_manager.h"
+
+using base::android::AttachCurrentThread;
+using base::WeakPtr;
+using content::BrowserThread;
+using content::StoragePartition;
+using quota::QuotaManager;
+
+namespace android_webview {
+
+namespace {
+
+void IgnoreStatus(quota::QuotaStatusCode status_code) {}
+
+class GetOriginsIOThreadSwitcher
mkosiba (inactive) 2013/02/19 11:37:13 this seems more like an OriginsUsageAndQuotaGetter
boliu 2013/02/20 00:53:50 Renamed to GetOriginsTask.
+ : public base::RefCountedThreadSafe<GetOriginsIOThreadSwitcher> {
+ public:
+ GetOriginsIOThreadSwitcher(
+ const base::WeakPtr<AwQuotaManagerBridge>& bridge,
mkosiba (inactive) 2013/02/19 11:37:13 IMO this dude should take a on_results_obtained ba
boliu 2013/02/20 00:53:50 Did the bind jcallbakc_id into Callback thing.
+ int jcallback_id);
+
+ void GetOriginsOnIOThread();
mkosiba (inactive) 2013/02/19 11:37:13 this should be an internal detail.
boliu 2013/02/20 00:53:50 Renamed this to Run.
+
+ private:
+ friend class base::RefCountedThreadSafe<GetOriginsIOThreadSwitcher>;
+ ~GetOriginsIOThreadSwitcher();
+
+ void GetOriginsCallback(const std::set<GURL>& origins,
+ quota::StorageType type);
+
+ void AddToData(const GURL& origin,
+ quota::QuotaStatusCode status_code,
+ int64 usage,
+ int64 quota);
+
+ void CheckDone();
+ void DoneOnUIThread();
+
+ base::WeakPtr<AwQuotaManagerBridge> bridge_;
+ int jcallback_id_;
+ quota::QuotaManager* quota_manager_;
+ std::vector<std::string> origin_;
+ std::vector<int64> quota_;
+ std::vector<int64> usage_;
+
+ size_t num_callbacks_to_wait_;
+ size_t num_callbacks_received_;
+
+ DISALLOW_COPY_AND_ASSIGN(GetOriginsIOThreadSwitcher);
+};
+
+GetOriginsIOThreadSwitcher::GetOriginsIOThreadSwitcher(
+ const base::WeakPtr<AwQuotaManagerBridge>& bridge,
+ int jcallback_id)
+ : bridge_(bridge),
+ jcallback_id_(jcallback_id),
+ quota_manager_(bridge->GetQuotaManager()) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ AddRef(); // Matched in DoneOnUIThread.
mkosiba (inactive) 2013/02/19 11:37:13 this calls for the "The more you know" meme, but d
boliu 2013/02/19 17:03:21 I knew that...I just have to convince myself this
boliu 2013/02/20 00:53:50 I'm convinced. Done :)
+}
+
+void GetOriginsIOThreadSwitcher::GetOriginsOnIOThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ quota_manager_->GetOriginsModifiedSince(
+ quota::kStorageTypeTemporary,
+ base::Time() /* Since beginning of time. */,
+ base::Bind(&GetOriginsIOThreadSwitcher::GetOriginsCallback,
mkosiba (inactive) 2013/02/19 11:37:13 nit: OnOriginsObtained ?
boliu 2013/02/20 00:53:50 Done.
+ this));
+}
+
+void GetOriginsIOThreadSwitcher::GetOriginsCallback(
+ const std::set<GURL>& origins, quota::StorageType type) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ num_callbacks_to_wait_ = origins.size();
+ num_callbacks_received_ = 0u;
+
+ for (std::set<GURL>::const_iterator origin = origins.begin();
+ origin != origins.end();
+ ++origin) {
+ quota_manager_->GetUsageAndQuota(
+ *origin,
+ type,
+ base::Bind(&GetOriginsIOThreadSwitcher::AddToData,
mkosiba (inactive) 2013/02/19 11:37:13 OnUsageAndQuotaObtained?
boliu 2013/02/20 00:53:50 Done.
+ this,
+ *origin));
+ }
+
+ CheckDone();
+}
+
+void GetOriginsIOThreadSwitcher::AddToData(const GURL& origin,
+ quota::QuotaStatusCode status_code,
+ int64 usage,
+ int64 quota) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (status_code == quota::kQuotaStatusOk) {
+ origin_.push_back(origin.spec());
+ quota_.push_back(quota);
+ usage_.push_back(usage);
+ }
+
+ ++num_callbacks_received_;
+ CheckDone();
+}
+
+void GetOriginsIOThreadSwitcher::CheckDone() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (num_callbacks_received_ == num_callbacks_to_wait_) {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ &GetOriginsIOThreadSwitcher::DoneOnUIThread,
+ this));
+ } else if (num_callbacks_received_ > num_callbacks_to_wait_) {
+ NOTREACHED();
+ }
+}
+
+void GetOriginsIOThreadSwitcher::DoneOnUIThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (bridge_)
+ bridge_->GetOriginsCallback(jcallback_id_, origin_, quota_, usage_);
+ Release(); // Matched by constructor.
+}
+
+GetOriginsIOThreadSwitcher::~GetOriginsIOThreadSwitcher() {}
+
+} // namespace
+
+namespace internal {
+
+IOThreadSwitcher::IOThreadSwitcher(const WeakPtr<AwQuotaManagerBridge>& bridge)
+ : bridge_(bridge),
+ quota_manager_(bridge->GetQuotaManager()) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
+
+IOThreadSwitcher::~IOThreadSwitcher() {}
+
+void IOThreadSwitcher::DeleteAllDataOnIOThread() {
mkosiba (inactive) 2013/02/19 11:37:13 DeleteAllOriginData...?
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ quota_manager_->GetOriginsModifiedSince(
+ quota::kStorageTypeTemporary,
+ base::Time() /* Since beginning of time. */,
+ base::Bind(&IOThreadSwitcher::DeleteOrigins, this));
+}
+
+void IOThreadSwitcher::DeleteOriginOnIOThread(const GURL& origin) {
mkosiba (inactive) 2013/02/19 11:37:13 DeleteOriginData... ?
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ quota_manager_->DeleteOriginData(
+ origin,
+ quota::kStorageTypeTemporary /* ignored due to mask below */,
+ quota::QuotaClient::kAllClientsMask,
+ base::Bind(&IgnoreStatus));
+}
+
+void IOThreadSwitcher::GetQuotaForOriginOnIOThread(
+ const GURL& origin, int jcallback_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ quota_manager_->GetUsageAndQuota(
+ origin,
+ quota::kStorageTypeTemporary,
+ base::Bind(&IOThreadSwitcher::GetQuotaForOriginCallback,
mkosiba (inactive) 2013/02/19 11:37:13 OnQuotaObtained?
+ this,
+ jcallback_id));
+}
+
+void IOThreadSwitcher::GetUsageForOriginOnIOThread(
+ const GURL& origin, int jcallback_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ quota_manager_->GetUsageAndQuota(
+ origin,
+ quota::kStorageTypeTemporary,
+ base::Bind(&IOThreadSwitcher::GetUsageForOriginCallback,
mkosiba (inactive) 2013/02/19 11:37:13 OnUsageObtained?
+ this,
+ jcallback_id));
+}
+
+void IOThreadSwitcher::DeleteOrigins(
mkosiba (inactive) 2013/02/19 11:37:13 DeleteOriginDataOnIOThread ?
+ const std::set<GURL>& origins, quota::StorageType type) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // TODO(boliu): Maybe not spam the db thread?
+ for (std::set<GURL>::const_iterator origin = origins.begin();
+ origin != origins.end();
+ ++origin) {
+ quota_manager_->DeleteOriginData(*origin,
+ type,
+ quota::QuotaClient::kAllClientsMask,
+ base::Bind(&IgnoreStatus));
+ }
+}
+
+void IOThreadSwitcher::GetQuotaForOriginCallback(
+ int jcallback_id,
+ quota::QuotaStatusCode status_code,
+ int64 usage,
+ int64 quota) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (status_code != quota::kQuotaStatusOk) {
+ // Indicate error. TODO(boliu): Check this does not mean infinite.
+ quota = -1;
+ }
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ &internal::IOThreadSwitcher::GetQuotaForOriginCallbackOnUiThread,
+ this,
+ jcallback_id,
+ quota));
+}
+
+void IOThreadSwitcher::GetUsageForOriginCallback(
mkosiba (inactive) 2013/02/19 11:37:13 seems like you might be better off to have one pat
boliu 2013/02/20 00:53:50 Done.
+ int jcallback_id,
+ quota::QuotaStatusCode status_code,
+ int64 usage,
+ int64 quota) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (status_code != quota::kQuotaStatusOk) {
+ // Indicate error. TODO(boliu): Check this does not mean infinite.
+ usage = -1;
+ }
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ &internal::IOThreadSwitcher::GetUsageForOriginCallbackOnUiThread,
+ this,
+ jcallback_id,
+ quota));
mkosiba (inactive) 2013/02/19 11:37:13 s/usage/quota/ see? you really do need to merge t
boliu 2013/02/20 00:53:50 Since both are int64, so it's still easy to mess t
+}
+
+void IOThreadSwitcher::GetQuotaForOriginCallbackOnUiThread(
+ int jcallback_id, int64 quota) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (bridge_)
+ bridge_->GetQuotaForOriginCallback(jcallback_id, quota);
+}
+
+void IOThreadSwitcher::GetUsageForOriginCallbackOnUiThread(
+ int jcallback_id, int64 usage) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (bridge_)
+ bridge_->GetUsageForOriginCallback(jcallback_id, usage);
+}
+
+} // namespace internal
+
+// static
+jint GetDefaultNativeAwQuotaManagerBridge(JNIEnv* env, jclass clazz) {
+ content::ContentBrowserClient* cbc = content::GetContentClient()->browser();
mkosiba (inactive) 2013/02/19 11:37:13 uh.. maybe just browserClient?
boliu 2013/02/20 00:53:50 Done.
+ DCHECK(cbc);
+
+ AwContentBrowserClient* acbc =
mkosiba (inactive) 2013/02/19 11:37:13 awBrowserClient?
boliu 2013/02/20 00:53:50 Done.
+ AwContentBrowserClient::FromContentBrowserClient(cbc);
+ AwBrowserContext* browser_context = acbc->GetAwBrowserContext();
+ DCHECK(browser_context);
+
+ AwQuotaManagerBridge* bridge = browser_context->GetQuotaManagerBridge();
+ DCHECK(bridge);
+ return reinterpret_cast<jint>(bridge);
+}
+
+// static
+AwQuotaManagerBridge* AwQuotaManagerBridge::Create(
+ AwBrowserContext* browser_context) {
+ return new AwQuotaManagerBridge(browser_context);
+}
+
+AwQuotaManagerBridge::AwQuotaManagerBridge(AwBrowserContext* browser_context)
+ : browser_context_(browser_context),
+ io_thread_switcher_(new internal::IOThreadSwitcher(AsWeakPtr())) {
+}
+
+void AwQuotaManagerBridge::Init(JNIEnv* env, jobject object) {
+ java_ref_ = JavaObjectWeakGlobalRef(env, object);
+}
+
+QuotaManager* AwQuotaManagerBridge::GetQuotaManager() const {
+ // AndroidWebview does not use per-site storage partitions.
+ // TODO(boliu): Get @ajwong to review this before submit.
+ StoragePartition* storage_partition =
+ content::BrowserContext::GetStoragePartitionForSite(
+ browser_context_, GURL());
+ DCHECK(storage_partition);
+
+ QuotaManager* quota_manager = storage_partition->GetQuotaManager();
+ DCHECK(quota_manager);
+ return quota_manager;
+}
+
+void AwQuotaManagerBridge::DeleteAllData(JNIEnv* env, jobject object) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ BrowserThread::PostTask(
mkosiba (inactive) 2013/02/19 11:37:13 IMO this means that the encapsulation provided by
boliu 2013/02/20 00:53:50 The old IOThreadSwitcher was never meant to encaps
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&internal::IOThreadSwitcher::DeleteAllDataOnIOThread,
+ io_thread_switcher_.get()));
+}
+
+void AwQuotaManagerBridge::DeleteOrigin(
+ JNIEnv* env, jobject object, jstring origin) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&internal::IOThreadSwitcher::DeleteOriginOnIOThread,
+ io_thread_switcher_.get(),
+ GURL(base::android::ConvertJavaStringToUTF16(env, origin))));
+}
+
+void AwQuotaManagerBridge::GetOrigins(
+ JNIEnv* env, jobject object, jint callback_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&GetOriginsIOThreadSwitcher::GetOriginsOnIOThread,
+ new GetOriginsIOThreadSwitcher(AsWeakPtr(), callback_id)));
+}
+
+void AwQuotaManagerBridge::GetQuotaForOrigin(
+ JNIEnv* env, jobject object, jstring origin, jint callback_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&internal::IOThreadSwitcher::GetQuotaForOriginOnIOThread,
+ io_thread_switcher_.get(),
+ GURL(base::android::ConvertJavaStringToUTF16(env, origin)),
+ callback_id));
+}
+
+void AwQuotaManagerBridge::GetUsageForOrigin(
+ JNIEnv* env, jobject object, jstring origin, jint callback_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&internal::IOThreadSwitcher::GetUsageForOriginOnIOThread,
+ io_thread_switcher_.get(),
+ GURL(base::android::ConvertJavaStringToUTF16(env, origin)),
+ callback_id));
+}
+
+void AwQuotaManagerBridge::GetOriginsCallback(
+ int jcallback_id,
+ const std::vector<std::string>& origin,
+ const std::vector<int64>& quota,
+ const std::vector<int64>& usage) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (obj.is_null())
+ return;
+
+ Java_AwQuotaManagerBridge_onGetOriginsCallback(
+ env,
+ obj.obj(),
+ jcallback_id,
+ base::android::ToJavaArrayOfStrings(env, origin).obj(),
+ base::android::ToJavaLongArray(env, quota.begin(), quota.size()).obj(),
+ base::android::ToJavaLongArray(env, usage.begin(), usage.size()).obj());
+}
+
+void AwQuotaManagerBridge::GetQuotaForOriginCallback(
+ int jcallback_id, int64 quota) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (obj.is_null())
+ return;
+
+ android_webview::Java_AwQuotaManagerBridge_onGetQuotaForOriginCallback(
+ AttachCurrentThread(),
+ obj.obj(),
+ jcallback_id,
+ quota);
+
+}
+
+void AwQuotaManagerBridge::GetUsageForOriginCallback(
+ int jcallback_id, int64 usage) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (obj.is_null())
+ return;
+
+ android_webview::Java_AwQuotaManagerBridge_onGetUsageForOriginCallback(
+ AttachCurrentThread(),
+ obj.obj(),
+ jcallback_id,
+ usage);
+}
+
+bool RegisterAwQuotaManagerBridge(JNIEnv* env) {
+ return RegisterNativesImpl(env) >= 0;
+}
+
+} // namespace android_webview

Powered by Google App Engine
This is Rietveld 408576698