Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 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 "components/web_restrictions/content_resolver_web_restrictions_provider .h" | |
| 6 | |
| 7 #include "base/android/jni_string.h" | |
| 8 #include "base/android/scoped_java_ref.h" | |
| 9 #include "base/bind.h" | |
| 10 #include "base/location.h" | |
| 11 #include "base/thread_task_runner_handle.h" | |
| 12 #include "content/public/browser/browser_thread.h" | |
| 13 #include "jni/ContentResolverWebRestrictionsProvider_jni.h" | |
| 14 | |
| 15 namespace web_restrictions { | |
| 16 | |
| 17 namespace { | |
| 18 | |
| 19 namespace cache_helper { | |
|
Bernhard Bauer
2016/01/28 12:15:14
I don't think this namespace is necessary, as all
knn
2016/01/28 18:10:37
More for structure but redundant now, I have made
| |
| 20 | |
| 21 const size_t kMaxCacheSize = 100; | |
| 22 | |
| 23 void RecordAccess(std::list<GURL>* recent_urls, const GURL& url) { | |
| 24 // Move the url to the front of the cache. | |
|
Bernhard Bauer
2016/01/28 12:15:14
Nit: URL
knn
2016/01/28 18:10:37
Done.
| |
| 25 recent_urls->remove(url); | |
| 26 recent_urls->push_front(url); | |
| 27 } | |
| 28 | |
| 29 void InsertValue(std::map<GURL, std::string>* error_page_cache, | |
| 30 std::map<GURL, bool>* url_access_cache, | |
| 31 std::list<GURL>* recent_urls, | |
| 32 const GURL& url, | |
| 33 bool should_proceed, | |
| 34 const base::android::JavaParamRef<jstring>& j_error_page) { | |
|
Bernhard Bauer
2016/01/28 12:15:14
Use JavaRef (JavaParamRef is only a temporary thin
knn
2016/01/28 18:10:37
Good catch!
| |
| 35 RecordAccess(recent_urls, url); | |
| 36 if (recent_urls->size() >= kMaxCacheSize) { | |
| 37 url_access_cache->erase(recent_urls->back()); | |
| 38 error_page_cache->erase(recent_urls->back()); | |
| 39 recent_urls->pop_back(); | |
| 40 } | |
| 41 (*url_access_cache)[url] = should_proceed; | |
| 42 if (!j_error_page.is_null()) { | |
| 43 (*error_page_cache)[url] = | |
| 44 base::android::ConvertJavaStringToUTF8(j_error_page); | |
| 45 } else { | |
| 46 error_page_cache->erase(url); | |
| 47 } | |
| 48 } | |
| 49 | |
| 50 } // namespace cache_helper | |
| 51 | |
| 52 namespace async_helper { | |
| 53 | |
| 54 void ShouldProceed(const GURL& url, | |
| 55 jlong callback, | |
| 56 const base::android::JavaRef<jobject>& java_provider) { | |
| 57 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 58 Java_ContentResolverWebRestrictionsProvider_shouldProceed( | |
| 59 env, java_provider.obj(), callback, | |
| 60 base::android::ConvertUTF8ToJavaString(env, url.spec()).obj()); | |
| 61 } | |
| 62 | |
| 63 void RequestPermission(const GURL& url, | |
| 64 jlong callback, | |
| 65 const base::android::JavaRef<jobject>& java_provider) { | |
| 66 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 67 Java_ContentResolverWebRestrictionsProvider_requestPermission( | |
| 68 env, java_provider.obj(), callback, | |
| 69 base::android::ConvertUTF8ToJavaString(env, url.spec()).obj()); | |
| 70 } | |
| 71 | |
| 72 } // namespace async_helper | |
| 73 | |
| 74 } // namespace | |
| 75 | |
| 76 // A wrapper to the callback class to facilitate getting a callback from java | |
| 77 // into C++. Objects of this class delete itself only when they are called back | |
| 78 // so we must ensure that happens even for error cases. | |
| 79 class SelfDeletingCallback { | |
| 80 public: | |
| 81 SelfDeletingCallback(const GURL& url, | |
| 82 const base::Callback<void(bool)>& callback, | |
| 83 const scoped_refptr<base::TaskRunner>& callback_runner, | |
| 84 ContentResolverWebRestrictionsProvider* provider); | |
| 85 void RequestSuccess(bool request_success); | |
| 86 void ShouldProceed(bool should_proceed, | |
| 87 const base::android::JavaParamRef<jstring>& error_page); | |
| 88 | |
| 89 private: | |
| 90 // Only the callback can delete itself. We must ensure it is indeed | |
| 91 // called back. | |
| 92 ~SelfDeletingCallback() {} | |
| 93 | |
| 94 GURL url_; | |
| 95 base::Callback<void(bool)> callback_; | |
| 96 scoped_refptr<base::TaskRunner> callback_runner_; | |
| 97 ContentResolverWebRestrictionsProvider* provider_; | |
| 98 | |
| 99 DISALLOW_COPY_AND_ASSIGN(SelfDeletingCallback); | |
| 100 }; | |
| 101 | |
| 102 SelfDeletingCallback::SelfDeletingCallback( | |
| 103 const GURL& url, | |
| 104 const base::Callback<void(bool)>& callback, | |
| 105 const scoped_refptr<base::TaskRunner>& callback_runner, | |
| 106 ContentResolverWebRestrictionsProvider* provider) | |
| 107 : url_(url), | |
| 108 callback_(callback), | |
| 109 callback_runner_(callback_runner), | |
| 110 provider_(provider) {} | |
| 111 | |
| 112 void SelfDeletingCallback::ShouldProceed( | |
| 113 bool should_proceed, | |
| 114 const base::android::JavaParamRef<jstring>& error_page) { | |
| 115 cache_helper::InsertValue( | |
|
Bernhard Bauer
2016/01/28 12:15:14
Just make this a method on |provider_|? That would
knn
2016/01/28 18:10:37
Done.
| |
| 116 &provider_->error_page_cache_, &provider_->url_access_cache_, | |
| 117 &provider_->recent_urls_, url_, should_proceed, error_page); | |
| 118 callback_runner_->PostTask(FROM_HERE, base::Bind(callback_, should_proceed)); | |
| 119 delete this; | |
| 120 } | |
| 121 | |
| 122 void SelfDeletingCallback::RequestSuccess(bool request_success) { | |
| 123 callback_runner_->PostTask(FROM_HERE, base::Bind(callback_, request_success)); | |
| 124 delete this; | |
| 125 } | |
| 126 | |
| 127 // static | |
| 128 bool ContentResolverWebRestrictionsProvider::Register(JNIEnv* env) { | |
| 129 return RegisterNativesImpl(env); | |
| 130 } | |
| 131 | |
| 132 ContentResolverWebRestrictionsProvider::ContentResolverWebRestrictionsProvider() | |
| 133 : initialized_(false), supports_request_(false) {} | |
| 134 | |
| 135 ContentResolverWebRestrictionsProvider:: | |
| 136 ~ContentResolverWebRestrictionsProvider() {} | |
| 137 | |
| 138 void ContentResolverWebRestrictionsProvider::Initialize( | |
| 139 const std::string& content_provider_authority) { | |
| 140 ClearCache(); | |
| 141 initialized_ = !content_provider_authority.empty(); | |
| 142 if (!initialized_) | |
| 143 return; | |
| 144 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 145 java_provider_.Reset(Java_ContentResolverWebRestrictionsProvider_create( | |
| 146 env, | |
| 147 base::android::ConvertUTF8ToJavaString(env, content_provider_authority) | |
| 148 .obj(), | |
| 149 reinterpret_cast<jlong>(this))); | |
| 150 supports_request_ = | |
| 151 Java_ContentResolverWebRestrictionsProvider_supportsRequest( | |
| 152 env, java_provider_.obj()); | |
| 153 } | |
| 154 | |
| 155 UrlAccess ContentResolverWebRestrictionsProvider::ShouldProceed( | |
| 156 bool is_main_frame, | |
| 157 const GURL& url, | |
| 158 const base::Callback<void(bool)>& callback) { | |
| 159 if (!initialized_) | |
| 160 return ALLOW; | |
| 161 auto iter = url_access_cache_.find(url); | |
| 162 if (iter != url_access_cache_.end()) { | |
| 163 cache_helper::RecordAccess(&recent_urls_, url); | |
| 164 return iter->second ? ALLOW : DISALLOW; | |
| 165 } | |
| 166 scoped_refptr<base::SingleThreadTaskRunner> callback_runner = | |
| 167 base::ThreadTaskRunnerHandle::Get(); | |
| 168 SelfDeletingCallback* wrapped_callback = | |
| 169 new SelfDeletingCallback(url, callback, callback_runner, this); | |
|
Bernhard Bauer
2016/01/28 12:15:14
I was going to write, "please mention that this de
knn
2016/01/28 18:10:37
Indeed we do not need to make it self deleting giv
| |
| 170 content::BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior( | |
|
Bernhard Bauer
2016/01/28 12:15:14
Speaking of multiple threads, you want to use a Se
knn
2016/01/28 18:10:37
Done.
| |
| 171 FROM_HERE, | |
| 172 base::Bind(&async_helper::ShouldProceed, url, | |
| 173 reinterpret_cast<jlong>(wrapped_callback), java_provider_), | |
| 174 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); | |
| 175 return PENDING; | |
| 176 } | |
| 177 | |
| 178 bool ContentResolverWebRestrictionsProvider::SupportsRequest() const { | |
| 179 return initialized_ && supports_request_; | |
| 180 } | |
| 181 | |
| 182 bool ContentResolverWebRestrictionsProvider::GetErrorHtml( | |
| 183 const GURL& url, | |
| 184 std::string* error_page) const { | |
| 185 if (!initialized_) | |
| 186 return false; | |
| 187 auto iter = error_page_cache_.find(url); | |
| 188 if (iter == error_page_cache_.end()) | |
| 189 return false; | |
| 190 *error_page = iter->second; | |
| 191 return true; | |
| 192 } | |
| 193 | |
| 194 void ContentResolverWebRestrictionsProvider::RequestPermission( | |
| 195 const GURL& url, | |
| 196 const base::Callback<void(bool)>& request_success) { | |
| 197 if (!initialized_) { | |
| 198 request_success.Run(false); | |
| 199 return; | |
| 200 } | |
| 201 scoped_refptr<base::SingleThreadTaskRunner> callback_runner = | |
| 202 base::ThreadTaskRunnerHandle::Get(); | |
| 203 SelfDeletingCallback* wrapped_callback = | |
| 204 new SelfDeletingCallback(url, request_success, callback_runner, this); | |
| 205 content::BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior( | |
| 206 FROM_HERE, | |
| 207 base::Bind(&async_helper::RequestPermission, url, | |
| 208 reinterpret_cast<jlong>(wrapped_callback), java_provider_), | |
| 209 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); | |
| 210 } | |
| 211 | |
| 212 void ContentResolverWebRestrictionsProvider::ClearCache() { | |
| 213 error_page_cache_.clear(); | |
| 214 url_access_cache_.clear(); | |
| 215 recent_urls_.clear(); | |
| 216 } | |
| 217 | |
| 218 void ShouldProceed(JNIEnv* env, | |
| 219 const base::android::JavaParamRef<jclass>& clazz, | |
| 220 jlong callback_ptr, | |
| 221 jboolean should_proceed, | |
| 222 const base::android::JavaParamRef<jstring>& error_page) { | |
| 223 SelfDeletingCallback* callback = | |
| 224 reinterpret_cast<SelfDeletingCallback*>(callback_ptr); | |
| 225 callback->ShouldProceed(should_proceed, error_page); | |
| 226 } | |
| 227 | |
| 228 void RequestSuccess(JNIEnv* env, | |
| 229 const base::android::JavaParamRef<jclass>& clazz, | |
| 230 jlong callback_ptr, | |
| 231 jboolean request_success) { | |
| 232 SelfDeletingCallback* callback = | |
| 233 reinterpret_cast<SelfDeletingCallback*>(callback_ptr); | |
| 234 callback->RequestSuccess(request_success); | |
| 235 } | |
| 236 | |
| 237 void NotifyWebRestrictionsChanged( | |
| 238 JNIEnv* env, | |
| 239 const base::android::JavaParamRef<jclass>& clazz, | |
| 240 jlong provider_ptr) { | |
| 241 ContentResolverWebRestrictionsProvider* provider = | |
| 242 reinterpret_cast<ContentResolverWebRestrictionsProvider*>(provider_ptr); | |
| 243 // TODO(knn): Also reload existing interstitials/error pages. | |
| 244 provider->ClearCache(); | |
| 245 } | |
| 246 | |
| 247 } // namespace web_restrictions | |
| OLD | NEW |