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

Side by Side Diff: components/web_restrictions/content_resolver_web_restrictions_provider.cc

Issue 1631603002: Web restrictions component only. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 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 unified diff | Download patch
OLDNEW
(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 const size_t kMaxCacheSize = 100;
20
21 void AsyncShouldProceed(const GURL& url,
22 jlong callback,
23 const base::android::JavaRef<jobject>& java_provider) {
24 JNIEnv* env = base::android::AttachCurrentThread();
25 Java_ContentResolverWebRestrictionsProvider_shouldProceed(
26 env, java_provider.obj(), callback,
27 base::android::ConvertUTF8ToJavaString(env, url.spec()).obj());
28 }
29
30 void AsyncRequestPermission(
31 const GURL& url,
32 jlong callback,
33 const base::android::JavaRef<jobject>& java_provider) {
34 JNIEnv* env = base::android::AttachCurrentThread();
35 Java_ContentResolverWebRestrictionsProvider_requestPermission(
36 env, java_provider.obj(), callback,
37 base::android::ConvertUTF8ToJavaString(env, url.spec()).obj());
38 }
39
40 bool AsyncCheckSupportsRequest(
41 const base::android::JavaRef<jobject>& java_provider) {
42 JNIEnv* env = base::android::AttachCurrentThread();
43 return Java_ContentResolverWebRestrictionsProvider_supportsRequest(
44 env, java_provider.obj());
45 }
46
47 } // namespace
48
49 // A wrapper to the callback class to facilitate getting a callback from java
50 // into C++. Objects of this class delete itself only when they are called back
51 // so we must ensure that happens even for error cases.
52 class SelfDeletingCallback {
53 public:
54 SelfDeletingCallback(
55 const GURL& url,
56 const base::Callback<void(bool)>& callback,
57 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
58 const std::string& provider_authority,
59 ContentResolverWebRestrictionsProvider* provider);
60 void RequestSuccess(bool request_success);
61 void ShouldProceed(bool should_proceed, std::string error_page);
62
63 private:
64 // Only the callback can delete itself. We must ensure it is indeed
65 // called back.
66 ~SelfDeletingCallback() {}
67
68 GURL url_;
69 base::Callback<void(bool)> callback_;
70 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
71 std::string provider_authority_;
72 ContentResolverWebRestrictionsProvider* provider_;
73
74 DISALLOW_COPY_AND_ASSIGN(SelfDeletingCallback);
75 };
76
77 SelfDeletingCallback::SelfDeletingCallback(
78 const GURL& url,
79 const base::Callback<void(bool)>& callback,
80 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
81 const std::string& provider_authority,
82 ContentResolverWebRestrictionsProvider* provider)
83 : url_(url),
84 callback_(callback),
85 task_runner_(task_runner),
86 provider_authority_(provider_authority),
87 provider_(provider) {}
88
89 void SelfDeletingCallback::ShouldProceed(bool should_proceed,
90 std::string error_page) {
91 task_runner_->PostTask(
92 FROM_HERE,
93 base::Bind(&ContentResolverWebRestrictionsProvider::UpdateCache,
94 base::Unretained(provider_), provider_authority_, url_,
95 should_proceed, error_page));
96 task_runner_->PostTask(FROM_HERE, base::Bind(callback_, should_proceed));
97 delete this;
98 }
99
100 void SelfDeletingCallback::RequestSuccess(bool request_success) {
101 task_runner_->PostTask(FROM_HERE, base::Bind(callback_, request_success));
102 delete this;
103 }
104
105 // static
106 bool ContentResolverWebRestrictionsProvider::Register(JNIEnv* env) {
107 return RegisterNativesImpl(env);
108 }
109
110 ContentResolverWebRestrictionsProvider::ContentResolverWebRestrictionsProvider()
111 : initialized_(false), supports_request_(false) {
112 single_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();
113 base::SequencedWorkerPool* worker_pool =
114 content::BrowserThread::GetBlockingPool();
115 background_task_runner_ =
116 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior(
117 worker_pool->GetSequenceToken(),
118 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
119 }
120
121 ContentResolverWebRestrictionsProvider::
122 ~ContentResolverWebRestrictionsProvider() {
123 if (java_provider_.is_null())
124 return;
125 JNIEnv* env = base::android::AttachCurrentThread();
126 Java_ContentResolverWebRestrictionsProvider_onDestroy(env,
127 java_provider_.obj());
128 java_provider_.Reset();
129 }
130
131 void ContentResolverWebRestrictionsProvider::SetAuthority(
132 const std::string& content_provider_authority) {
133 DCHECK(single_thread_task_runner_->BelongsToCurrentThread());
134 // Destroy any existing content resolver.
135 JNIEnv* env = base::android::AttachCurrentThread();
136 if (!java_provider_.is_null()) {
137 Java_ContentResolverWebRestrictionsProvider_onDestroy(env,
138 java_provider_.obj());
139 java_provider_.Reset();
140 }
141 ClearCache();
142 provider_authority_ = content_provider_authority;
143
144 // Initialize the content resolver.
145 initialized_ = !content_provider_authority.empty();
146 if (!initialized_)
147 return;
148 java_provider_.Reset(Java_ContentResolverWebRestrictionsProvider_create(
149 env,
150 base::android::ConvertUTF8ToJavaString(env, content_provider_authority)
151 .obj(),
152 reinterpret_cast<jlong>(this)));
153 supports_request_ = false;
154 base::PostTaskAndReplyWithResult(
155 content::BrowserThread::GetBlockingPool(), FROM_HERE,
156 base::Bind(&AsyncCheckSupportsRequest, java_provider_),
157 base::Bind(&ContentResolverWebRestrictionsProvider::RequestSupportKnown,
158 base::Unretained(this), provider_authority_));
159 }
160
161 UrlAccess ContentResolverWebRestrictionsProvider::ShouldProceed(
162 bool is_main_frame,
163 const GURL& url,
164 const base::Callback<void(bool)>& callback) {
165 DCHECK(single_thread_task_runner_->BelongsToCurrentThread());
166 if (!initialized_)
167 return ALLOW;
168 auto iter = url_access_cache_.find(url);
169 if (iter != url_access_cache_.end()) {
170 RecordURLAccess(url);
171 return iter->second ? ALLOW : DISALLOW;
172 }
173 SelfDeletingCallback* wrapped_callback = new SelfDeletingCallback(
174 url, callback, single_thread_task_runner_, provider_authority_, this);
175 background_task_runner_->PostTask(
176 FROM_HERE,
177 base::Bind(&AsyncShouldProceed, url,
178 reinterpret_cast<jlong>(wrapped_callback), java_provider_));
179 return PENDING;
180 }
181
182 bool ContentResolverWebRestrictionsProvider::SupportsRequest() const {
183 return initialized_ && supports_request_;
184 }
185
186 bool ContentResolverWebRestrictionsProvider::GetErrorHtml(
187 const GURL& url,
188 std::string* error_page) const {
189 DCHECK(single_thread_task_runner_->BelongsToCurrentThread());
190 if (!initialized_)
191 return false;
192 auto iter = error_page_cache_.find(url);
193 if (iter == error_page_cache_.end())
194 return false;
195 *error_page = iter->second;
196 return true;
197 }
198
199 void ContentResolverWebRestrictionsProvider::RequestPermission(
200 const GURL& url,
201 const base::Callback<void(bool)>& request_success) {
202 if (!initialized_) {
203 request_success.Run(false);
204 return;
205 }
206 SelfDeletingCallback* wrapped_callback =
207 new SelfDeletingCallback(url, request_success, single_thread_task_runner_,
208 provider_authority_, this);
209 background_task_runner_->PostTask(
210 FROM_HERE,
211 base::Bind(&AsyncRequestPermission, url,
212 reinterpret_cast<jlong>(wrapped_callback), java_provider_));
213 }
214
215 void ContentResolverWebRestrictionsProvider::OnWebRestrictionsChanged() {
216 single_thread_task_runner_->PostTask(
217 FROM_HERE, base::Bind(&ContentResolverWebRestrictionsProvider::ClearCache,
218 base::Unretained(this)));
219 }
220
221 void ContentResolverWebRestrictionsProvider::RecordURLAccess(const GURL& url) {
222 DCHECK(single_thread_task_runner_->BelongsToCurrentThread());
223 // Move the URL to the front of the cache.
224 recent_urls_.remove(url);
225 recent_urls_.push_front(url);
226 }
227
228 void ContentResolverWebRestrictionsProvider::UpdateCache(
229 std::string provider_authority,
230 GURL url,
231 bool should_proceed,
232 std::string error_page) {
233 DCHECK(single_thread_task_runner_->BelongsToCurrentThread());
234 // If the webrestrictions provider changed when the old one was being queried,
235 // do not update the cache for the new provider.
236 if (provider_authority != provider_authority_)
237 return;
238 RecordURLAccess(url);
239 if (recent_urls_.size() >= kMaxCacheSize) {
240 url_access_cache_.erase(recent_urls_.back());
241 error_page_cache_.erase(recent_urls_.back());
242 recent_urls_.pop_back();
243 }
244 url_access_cache_[url] = should_proceed;
245 if (!error_page.empty()) {
246 error_page_cache_[url] = error_page;
247 } else {
248 error_page_cache_.erase(url);
249 }
250 }
251
252 void ContentResolverWebRestrictionsProvider::RequestSupportKnown(
253 std::string provider_authority,
254 bool supports_request) {
255 // |supports_request_| is initialized to false.
256 DCHECK(!supports_request_);
257 DCHECK(single_thread_task_runner_->BelongsToCurrentThread());
258 // If the webrestrictions provider changed when the old one was being queried,
259 // ignore the result.
260 if (provider_authority != provider_authority_)
261 return;
262 supports_request_ = supports_request;
263 }
264
265 void ContentResolverWebRestrictionsProvider::ClearCache() {
266 DCHECK(single_thread_task_runner_->BelongsToCurrentThread());
267 error_page_cache_.clear();
268 url_access_cache_.clear();
269 recent_urls_.clear();
270 }
271
272 void ShouldProceed(JNIEnv* env,
273 const base::android::JavaParamRef<jclass>& clazz,
274 jlong callback_ptr,
275 jboolean should_proceed,
276 const base::android::JavaParamRef<jstring>& j_error_page) {
277 SelfDeletingCallback* callback =
278 reinterpret_cast<SelfDeletingCallback*>(callback_ptr);
279 std::string error_page;
280 if (!j_error_page.is_null())
281 error_page = base::android::ConvertJavaStringToUTF8(j_error_page);
282 callback->ShouldProceed(should_proceed, error_page);
283 }
284
285 void RequestSuccess(JNIEnv* env,
286 const base::android::JavaParamRef<jclass>& clazz,
287 jlong callback_ptr,
288 jboolean request_success) {
289 SelfDeletingCallback* callback =
290 reinterpret_cast<SelfDeletingCallback*>(callback_ptr);
291 callback->RequestSuccess(request_success);
292 }
293
294 void NotifyWebRestrictionsChanged(
295 JNIEnv* env,
296 const base::android::JavaParamRef<jclass>& clazz,
297 jlong provider_ptr) {
298 ContentResolverWebRestrictionsProvider* provider =
299 reinterpret_cast<ContentResolverWebRestrictionsProvider*>(provider_ptr);
300 // TODO(knn): Also reload existing interstitials/error pages.
301 provider->OnWebRestrictionsChanged();
302 }
303
304 } // namespace web_restrictions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698