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 |