Index: components/web_restriction/content_resolver_web_restriction_provider.cc |
diff --git a/components/web_restriction/content_resolver_web_restriction_provider.cc b/components/web_restriction/content_resolver_web_restriction_provider.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2ba9ad6d21a5c2ca3b6545a786f4640c1c8f4328 |
--- /dev/null |
+++ b/components/web_restriction/content_resolver_web_restriction_provider.cc |
@@ -0,0 +1,156 @@ |
+// Copyright 2015 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 "components/web_restriction/content_resolver_web_restriction_provider.h" |
+ |
+#include "base/android/jni_string.h" |
+#include "base/android/scoped_java_ref.h" |
+#include "base/bind.h" |
+#include "base/location.h" |
+#include "base/thread_task_runner_handle.h" |
+#include "jni/ContentResolverWebRestrictionProvider_jni.h" |
+ |
+namespace { |
+const size_t kMaxCacheSize = 100; |
+} // namespace |
+ |
+namespace web_restriction { |
+namespace android { |
+ |
+SelfDeletingCallback::SelfDeletingCallback( |
+ const GURL& url, |
+ const base::Callback<void(bool)>& callback, |
+ const scoped_refptr<base::TaskRunner>& callback_runner, |
+ ContentResolverWebRestrictionProvider* provider) |
+ : url_(url), |
+ callback_(callback), |
+ callback_runner_(callback_runner), |
+ provider_(provider) {} |
+ |
+SelfDeletingCallback::~SelfDeletingCallback() {} |
+ |
+void SelfDeletingCallback::ShouldProceed( |
+ JNIEnv* env, |
+ const base::android::JavaParamRef<jobject>& obj, |
+ jboolean should_proceed, |
+ const base::android::JavaParamRef<jstring>& j_error_page) { |
+ auto& url_access_cache = provider_->url_access_cache_; |
+ auto& error_page_cache = provider_->error_page_cache_; |
+ auto& recent_urls = provider_->recent_urls_; |
+ url_access_cache.erase(url_); |
+ error_page_cache.erase(url_); |
+ recent_urls.remove(url_); |
+ if (recent_urls.size() >= kMaxCacheSize) { |
+ url_access_cache.erase(recent_urls.back()); |
+ error_page_cache.erase(recent_urls.back()); |
+ recent_urls.pop_back(); |
+ } |
+ recent_urls.push_front(url_); |
+ url_access_cache[url_] = should_proceed; |
+ if (!j_error_page.is_null()) { |
+ error_page_cache[url_] = |
+ base::android::ConvertJavaStringToUTF8(j_error_page); |
+ } |
+ callback_runner_->PostTask(FROM_HERE, base::Bind(callback_, should_proceed)); |
+ delete this; |
+} |
+void SelfDeletingCallback::RequestSuccess( |
+ JNIEnv* env, |
+ const base::android::JavaParamRef<jobject>& obj, |
+ jboolean request_success) { |
+ callback_runner_->PostTask(FROM_HERE, base::Bind(callback_, request_success)); |
+ delete this; |
+} |
+ |
+} // namespace android |
+ |
+// static |
+bool ContentResolverWebRestrictionProvider::Register(JNIEnv* env) { |
+ return android::RegisterNativesImpl(env); |
+} |
+ |
+ContentResolverWebRestrictionProvider::ContentResolverWebRestrictionProvider() { |
+ initialized_ = false; |
+} |
+ |
+ContentResolverWebRestrictionProvider:: |
+ ~ContentResolverWebRestrictionProvider() {} |
+ |
+void ContentResolverWebRestrictionProvider::Initialize( |
+ const std::string& content_provider_authority) { |
+ DCHECK(!content_provider_authority.empty()); |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
+ java_provider_.Reset( |
+ android::Java_ContentResolverWebRestrictionProvider_create( |
+ env, base::android::ConvertUTF8ToJavaString( |
+ env, content_provider_authority) |
+ .obj())); |
+ supports_request_ = |
+ android::Java_ContentResolverWebRestrictionProvider_supportsRequest( |
+ env, java_provider_.obj()); |
+ error_page_cache_.clear(); |
+ url_access_cache_.clear(); |
+ recent_urls_.clear(); |
+ initialized_ = true; |
+} |
+ |
+UrlAccess ContentResolverWebRestrictionProvider::ShouldProceed( |
+ bool is_main_frame, |
+ const GURL& url, |
+ const base::Callback<void(bool)>& callback) { |
+ if (!initialized_) |
+ return ALLOW; |
+ auto iter = url_access_cache_.find(url); |
+ if (iter != url_access_cache_.end()) { |
+ // Move the url to the front of the cache. |
+ recent_urls_.remove(url); |
+ recent_urls_.push_front(url); |
+ return iter->second ? ALLOW : DISALLOW; |
+ } |
+ scoped_refptr<base::SingleThreadTaskRunner> callback_runner = |
+ base::ThreadTaskRunnerHandle::Get(); |
+ android::SelfDeletingCallback* wrapped_callback = |
+ new android::SelfDeletingCallback(url, callback, callback_runner, this); |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
+ android::Java_ContentResolverWebRestrictionProvider_shouldProceed( |
+ env, java_provider_.obj(), reinterpret_cast<jlong>(wrapped_callback), |
+ base::android::ConvertUTF8ToJavaString(env, url.spec()).obj()); |
+ return PENDING; |
+} |
+ |
+bool ContentResolverWebRestrictionProvider::SupportsRequest() const { |
+ return initialized_ && supports_request_; |
+} |
+ |
+bool ContentResolverWebRestrictionProvider::GetErrorHtml( |
+ const GURL& url, |
+ std::string* error_page) const { |
+ if (!initialized_) |
+ return false; |
+ auto iter = error_page_cache_.find(url); |
+ if (iter == error_page_cache_.end()) |
+ return false; |
+ *error_page = iter->second; |
+ return true; |
+} |
+ |
+void ContentResolverWebRestrictionProvider::RequestPermission( |
+ const GURL& url, |
+ const base::Callback<void(bool)>& request_success) { |
+ if (!initialized_) { |
+ request_success.Run(false); |
+ return; |
+ } |
+ scoped_refptr<base::SingleThreadTaskRunner> callback_runner = |
+ base::ThreadTaskRunnerHandle::Get(); |
+ android::SelfDeletingCallback* wrapped_callback = |
+ new android::SelfDeletingCallback(url, request_success, callback_runner, |
+ this); |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
+ android::Java_ContentResolverWebRestrictionProvider_requestPermission( |
+ env, java_provider_.obj(), reinterpret_cast<jlong>(wrapped_callback), |
+ base::android::ConvertUTF8ToJavaString(env, url.spec()).obj()); |
+} |
+ |
+} // namespace web_restriction |