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

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: moar comments 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(const GURL& url,
55 const base::Callback<void(bool)>& callback,
56 const scoped_refptr<base::TaskRunner>& callback_runner,
57 ContentResolverWebRestrictionsProvider* provider);
58 void RequestSuccess(bool request_success);
59 void ShouldProceed(bool should_proceed,
60 const base::android::JavaRef<jstring>& error_page);
61
62 private:
63 // Only the callback can delete itself. We must ensure it is indeed
64 // called back.
65 ~SelfDeletingCallback() {}
66
67 GURL url_;
68 base::Callback<void(bool)> callback_;
69 scoped_refptr<base::TaskRunner> callback_runner_;
70 ContentResolverWebRestrictionsProvider* provider_;
71
72 DISALLOW_COPY_AND_ASSIGN(SelfDeletingCallback);
73 };
74
75 SelfDeletingCallback::SelfDeletingCallback(
76 const GURL& url,
77 const base::Callback<void(bool)>& callback,
78 const scoped_refptr<base::TaskRunner>& callback_runner,
Bernhard Bauer 2016/02/03 16:15:42 If the contract of ContentResolverWebRestrictionsP
knn 2016/02/03 17:15:09 Done.
79 ContentResolverWebRestrictionsProvider* provider)
80 : url_(url),
81 callback_(callback),
82 callback_runner_(callback_runner),
83 provider_(provider) {}
84
85 void SelfDeletingCallback::ShouldProceed(
86 bool should_proceed,
87 const base::android::JavaRef<jstring>& j_error_page) {
88 std::string* error_page = nullptr;
89 if (!j_error_page.is_null()) {
90 // Will be owned by the callback to which it is passed.
91 error_page = new std::string();
92 *error_page = base::android::ConvertJavaStringToUTF8(j_error_page);
93 }
94 content::BrowserThread::PostTask(
95 content::BrowserThread::IO, FROM_HERE,
96 base::Bind(&ContentResolverWebRestrictionsProvider::UpdateCache,
97 base::Unretained(provider_), url_, should_proceed,
aberent 2016/02/03 16:22:07 Is |provider_| still guaranteed to still exist? Do
knn 2016/02/03 16:26:07 Yes, it is like a singleton should only be reset w
aberent 2016/02/03 17:56:15 I am confused. It is the lifetime of the C++ Conte
knn 2016/02/03 18:51:13 Yes, what you are saying is correct there are no *
98 base::Owned(error_page)));
Bernhard Bauer 2016/02/03 16:15:42 Could we wrap this in a scoped_ptr to make sure no
knn 2016/02/03 17:15:08 Passing by value now.
99 callback_runner_->PostTask(FROM_HERE, base::Bind(callback_, should_proceed));
100 delete this;
101 }
102
103 void SelfDeletingCallback::RequestSuccess(bool request_success) {
104 callback_runner_->PostTask(FROM_HERE, base::Bind(callback_, request_success));
105 delete this;
106 }
107
108 // static
109 bool ContentResolverWebRestrictionsProvider::Register(JNIEnv* env) {
110 return RegisterNativesImpl(env);
111 }
112
113 ContentResolverWebRestrictionsProvider::ContentResolverWebRestrictionsProvider()
114 : initialized_(false), supports_request_(false) {
115 base::SequencedWorkerPool* worker_pool =
116 content::BrowserThread::GetBlockingPool();
117 background_task_runner_ =
118 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior(
119 worker_pool->GetSequenceToken(),
120 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
121 }
122
123 ContentResolverWebRestrictionsProvider::
124 ~ContentResolverWebRestrictionsProvider() {
125 if (java_provider_.is_null())
126 return;
127 JNIEnv* env = base::android::AttachCurrentThread();
128 Java_ContentResolverWebRestrictionsProvider_onDestroy(env,
129 java_provider_.obj());
130 }
131
132 void ContentResolverWebRestrictionsProvider::SetAuthority(
133 const std::string& content_provider_authority) {
134 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
135 // Destroy any existing content resolver.
136 JNIEnv* env = base::android::AttachCurrentThread();
137 if (!java_provider_.is_null()) {
138 Java_ContentResolverWebRestrictionsProvider_onDestroy(env,
139 java_provider_.obj());
140 java_provider_.Reset();
141 }
142 ClearCache();
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)));
159 }
160
161 UrlAccess ContentResolverWebRestrictionsProvider::ShouldProceed(
162 bool is_main_frame,
163 const GURL& url,
164 const base::Callback<void(bool)>& callback) {
165 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
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 scoped_refptr<base::SingleThreadTaskRunner> callback_runner =
174 base::ThreadTaskRunnerHandle::Get();
175 SelfDeletingCallback* wrapped_callback =
176 new SelfDeletingCallback(url, callback, callback_runner, this);
177 background_task_runner_->PostTask(
178 FROM_HERE,
179 base::Bind(&AsyncShouldProceed, url,
180 reinterpret_cast<jlong>(wrapped_callback), java_provider_));
181 return PENDING;
182 }
183
184 bool ContentResolverWebRestrictionsProvider::SupportsRequest() const {
185 return initialized_ && supports_request_;
186 }
187
188 bool ContentResolverWebRestrictionsProvider::GetErrorHtml(
189 const GURL& url,
190 std::string* error_page) const {
191 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
192 if (!initialized_)
193 return false;
194 auto iter = error_page_cache_.find(url);
195 if (iter == error_page_cache_.end())
196 return false;
197 *error_page = iter->second;
198 return true;
199 }
200
201 void ContentResolverWebRestrictionsProvider::RequestPermission(
202 const GURL& url,
203 const base::Callback<void(bool)>& request_success) {
204 if (!initialized_) {
205 request_success.Run(false);
206 return;
207 }
208 scoped_refptr<base::SingleThreadTaskRunner> callback_runner =
209 base::ThreadTaskRunnerHandle::Get();
210 SelfDeletingCallback* wrapped_callback =
211 new SelfDeletingCallback(url, request_success, callback_runner, this);
212 background_task_runner_->PostTask(
213 FROM_HERE,
214 base::Bind(&AsyncRequestPermission, url,
215 reinterpret_cast<jlong>(wrapped_callback), java_provider_));
216 }
217
218 void ContentResolverWebRestrictionsProvider::ClearCache() {
219 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
220 error_page_cache_.clear();
221 url_access_cache_.clear();
222 recent_urls_.clear();
223 }
224
225 void ContentResolverWebRestrictionsProvider::RecordURLAccess(const GURL& url) {
226 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
227 // Move the URL to the front of the cache.
228 recent_urls_.remove(url);
229 recent_urls_.push_front(url);
230 }
231
232 void ContentResolverWebRestrictionsProvider::UpdateCache(
233 const GURL& url,
234 bool should_proceed,
235 std::string* error_page /* owned by the callback */) {
236 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
237 RecordURLAccess(url);
238 if (recent_urls_.size() >= kMaxCacheSize) {
239 url_access_cache_.erase(recent_urls_.back());
240 error_page_cache_.erase(recent_urls_.back());
241 recent_urls_.pop_back();
242 }
243 url_access_cache_[url] = should_proceed;
244 if (error_page) {
245 error_page_cache_[url] = *error_page;
Bernhard Bauer 2016/02/03 16:15:42 Hm... We pass this as a pointer to this method to
knn 2016/02/03 16:23:56 I am using pointers mostly to indicate missing val
Bernhard Bauer 2016/02/03 16:26:49 Yeah, I don't think anyone would legitimately want
knn 2016/02/03 17:15:09 Acknowledged.
246 } else {
247 error_page_cache_.erase(url);
248 }
249 }
250
251 void ContentResolverWebRestrictionsProvider::RequestSupportKnown(
252 bool supports_request) {
253 // |supports_request_| is initialized to false.
254 DCHECK(!supports_request_);
255 supports_request_ = supports_request;
256 }
257
258 void ShouldProceed(JNIEnv* env,
259 const base::android::JavaParamRef<jclass>& clazz,
260 jlong callback_ptr,
261 jboolean should_proceed,
262 const base::android::JavaParamRef<jstring>& error_page) {
263 SelfDeletingCallback* callback =
264 reinterpret_cast<SelfDeletingCallback*>(callback_ptr);
265 callback->ShouldProceed(should_proceed, error_page);
266 }
267
268 void RequestSuccess(JNIEnv* env,
269 const base::android::JavaParamRef<jclass>& clazz,
270 jlong callback_ptr,
271 jboolean request_success) {
272 SelfDeletingCallback* callback =
273 reinterpret_cast<SelfDeletingCallback*>(callback_ptr);
274 callback->RequestSuccess(request_success);
275 }
276
277 void NotifyWebRestrictionsChanged(
278 JNIEnv* env,
279 const base::android::JavaParamRef<jclass>& clazz,
280 jlong provider_ptr) {
281 ContentResolverWebRestrictionsProvider* provider =
282 reinterpret_cast<ContentResolverWebRestrictionsProvider*>(provider_ptr);
283 // TODO(knn): Also reload existing interstitials/error pages.
284 content::BrowserThread::PostTask(
285 content::BrowserThread::IO, FROM_HERE,
286 base::Bind(&ContentResolverWebRestrictionsProvider::ClearCache,
287 base::Unretained(provider)));
aberent 2016/02/03 16:22:07 As above; do we know that |provider| hasn't been d
288 }
289
290 } // namespace web_restrictions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698