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/browser/web_restrictions_client.cc

Issue 1890203002: Implement Web Restrictions in WebView. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/web_restrictions/browser/web_restrictions_client.h" 5 #include "components/web_restrictions/browser/web_restrictions_client.h"
6 6
7 #include "base/android/jni_string.h" 7 #include "base/android/jni_string.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/location.h" 9 #include "base/location.h"
10 #include "base/thread_task_runner_handle.h" 10 #include "base/thread_task_runner_handle.h"
11 #include "content/public/browser/browser_thread.h" 11 #include "content/public/browser/browser_thread.h"
12 #include "jni/WebRestrictionsClient_jni.h" 12 #include "jni/WebRestrictionsClient_jni.h"
13 13
14 using base::android::ScopedJavaGlobalRef; 14 using base::android::ScopedJavaGlobalRef;
15 15
16 namespace web_restrictions { 16 namespace web_restrictions {
17 17
18 namespace { 18 namespace {
19 19
20 const size_t kMaxCacheSize = 100; 20 const size_t kMaxCacheSize = 100;
21 21
22 bool RequestPermissionTask( 22 bool RequestPermissionTask(
23 const GURL& url, 23 const std::string& url,
24 const base::android::JavaRef<jobject>& java_provider) { 24 const base::android::JavaRef<jobject>& java_provider) {
25 JNIEnv* env = base::android::AttachCurrentThread(); 25 JNIEnv* env = base::android::AttachCurrentThread();
26 return Java_WebRestrictionsClient_requestPermission( 26 return Java_WebRestrictionsClient_requestPermission(
27 env, java_provider.obj(), 27 env, java_provider.obj(),
28 base::android::ConvertUTF8ToJavaString(env, url.spec()).obj()); 28 base::android::ConvertUTF8ToJavaString(env, url).obj());
29 } 29 }
30 30
31 bool CheckSupportsRequestTask( 31 bool CheckSupportsRequestTask(
32 const base::android::JavaRef<jobject>& java_provider) { 32 const base::android::JavaRef<jobject>& java_provider) {
33 JNIEnv* env = base::android::AttachCurrentThread(); 33 JNIEnv* env = base::android::AttachCurrentThread();
34 return Java_WebRestrictionsClient_supportsRequest(env, java_provider.obj()); 34 return Java_WebRestrictionsClient_supportsRequest(env, java_provider.obj());
35 } 35 }
36 36
37 } // namespace 37 } // namespace
38 38
39 // static 39 // static
40 bool WebRestrictionsClient::Register(JNIEnv* env) { 40 bool WebRestrictionsClient::Register(JNIEnv* env) {
41 return RegisterNativesImpl(env); 41 return RegisterNativesImpl(env);
42 } 42 }
43 43
44 WebRestrictionsClient::WebRestrictionsClient() 44 WebRestrictionsClient::WebRestrictionsClient()
45 : initialized_(false), supports_request_(false) { 45 : initialized_(false), supports_request_(false) {
46 single_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get(); 46 io_thread_task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread(
Bernhard Bauer 2016/04/18 14:48:34 If you are not injecting this as a dependency, jus
aberent 2016/05/18 20:06:50 Done.
47 content::BrowserThread::IO);
47 base::SequencedWorkerPool* worker_pool = 48 base::SequencedWorkerPool* worker_pool =
48 content::BrowserThread::GetBlockingPool(); 49 content::BrowserThread::GetBlockingPool();
49 background_task_runner_ = 50 background_task_runner_ =
50 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( 51 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior(
51 worker_pool->GetSequenceToken(), 52 worker_pool->GetSequenceToken(),
52 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); 53 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
53 } 54 }
54 55
55 WebRestrictionsClient::~WebRestrictionsClient() { 56 WebRestrictionsClient::~WebRestrictionsClient() {
56 if (java_provider_.is_null()) 57 if (java_provider_.is_null())
57 return; 58 return;
58 JNIEnv* env = base::android::AttachCurrentThread(); 59 JNIEnv* env = base::android::AttachCurrentThread();
59 Java_WebRestrictionsClient_onDestroy(env, java_provider_.obj()); 60 Java_WebRestrictionsClient_onDestroy(env, java_provider_.obj());
60 java_provider_.Reset(); 61 java_provider_.Reset();
61 } 62 }
62 63
63 void WebRestrictionsClient::SetAuthority( 64 void WebRestrictionsClient::SetAuthority(
64 const std::string& content_provider_authority) { 65 const std::string& content_provider_authority) {
65 DCHECK(single_thread_task_runner_->BelongsToCurrentThread()); 66 // This is called from the UI thread in normal use.
67 if (io_thread_task_runner_->BelongsToCurrentThread()) {
68 // Only used for testing. Avoids need for complex multithreading in tests.
69 SetAuthorityTask(content_provider_authority);
Bernhard Bauer 2016/04/18 14:48:34 You could just friend the test class and call SetA
aberent 2016/05/18 20:06:50 Done.
70 } else {
71 // Run a task on the IO thread to do the real work.
72 io_thread_task_runner_->PostTask(
73 FROM_HERE,
74 base::Bind(&WebRestrictionsClient::SetAuthorityTask,
75 base::Unretained(this), content_provider_authority));
76 }
77 }
78
79 void WebRestrictionsClient::SetAuthorityTask(
80 const std::string& content_provider_authority) {
81 DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
66 // Destroy any existing content resolver. 82 // Destroy any existing content resolver.
67 JNIEnv* env = base::android::AttachCurrentThread(); 83 JNIEnv* env = base::android::AttachCurrentThread();
68 if (!java_provider_.is_null()) { 84 if (!java_provider_.is_null()) {
69 Java_WebRestrictionsClient_onDestroy(env, java_provider_.obj()); 85 Java_WebRestrictionsClient_onDestroy(env, java_provider_.obj());
70 java_provider_.Reset(); 86 java_provider_.Reset();
71 } 87 }
72 ClearCache(); 88 ClearCache();
73 provider_authority_ = content_provider_authority; 89 provider_authority_ = content_provider_authority;
74 90
75 // Initialize the content resolver. 91 // Initialize the content resolver.
76 initialized_ = !content_provider_authority.empty(); 92 initialized_ = !content_provider_authority.empty();
77 if (!initialized_) 93 if (!initialized_)
78 return; 94 return;
79 java_provider_.Reset(Java_WebRestrictionsClient_create( 95 java_provider_.Reset(Java_WebRestrictionsClient_create(
80 env, 96 env,
81 base::android::ConvertUTF8ToJavaString(env, content_provider_authority) 97 base::android::ConvertUTF8ToJavaString(env, content_provider_authority)
82 .obj(), 98 .obj(),
83 reinterpret_cast<jlong>(this))); 99 reinterpret_cast<jlong>(this)));
84 supports_request_ = false; 100 supports_request_ = false;
85 base::PostTaskAndReplyWithResult( 101 base::PostTaskAndReplyWithResult(
86 content::BrowserThread::GetBlockingPool(), FROM_HERE, 102 content::BrowserThread::GetBlockingPool(), FROM_HERE,
87 base::Bind(&CheckSupportsRequestTask, java_provider_), 103 base::Bind(&CheckSupportsRequestTask, java_provider_),
88 base::Bind(&WebRestrictionsClient::RequestSupportKnown, 104 base::Bind(&WebRestrictionsClient::RequestSupportKnown,
89 base::Unretained(this), provider_authority_)); 105 base::Unretained(this), provider_authority_));
90 } 106 }
91 107
92 UrlAccess WebRestrictionsClient::ShouldProceed( 108 UrlAccess WebRestrictionsClient::ShouldProceed(
93 bool is_main_frame, 109 bool is_main_frame,
94 const GURL& url, 110 const std::string& url,
95 const base::Callback<void(bool)>& callback) { 111 const base::Callback<void(bool)>& callback) {
96 DCHECK(single_thread_task_runner_->BelongsToCurrentThread()); 112 DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
97 if (!initialized_) 113 if (!initialized_)
98 return ALLOW; 114 return ALLOW;
99 auto iter = cache_.find(url); 115
100 if (iter != cache_.end()) { 116 std::unique_ptr<const WebRestrictionsClientResult> result =
117 cache_.GetCacheEntry(url);
118 if (result.get()) {
Bernhard Bauer 2016/04/18 14:48:34 The .get() is unnecessary -- unique_ptr has a bool
aberent 2016/05/18 20:06:50 Done.
101 RecordURLAccess(url); 119 RecordURLAccess(url);
102 JNIEnv* env = base::android::AttachCurrentThread(); 120 return result->ShouldProceed() ? ALLOW : DISALLOW;
103 return Java_ShouldProceedResult_shouldProceed(env, iter->second.obj())
104 ? ALLOW
105 : DISALLOW;
106 } 121 }
107 base::PostTaskAndReplyWithResult( 122 base::PostTaskAndReplyWithResult(
108 background_task_runner_.get(), FROM_HERE, 123 background_task_runner_.get(), FROM_HERE,
109 base::Bind(&WebRestrictionsClient::ShouldProceedTask, url, 124 base::Bind(&WebRestrictionsClient::ShouldProceedTask, url,
110 java_provider_), 125 java_provider_),
111 base::Bind(&WebRestrictionsClient::OnShouldProceedComplete, 126 base::Bind(&WebRestrictionsClient::OnShouldProceedComplete,
112 base::Unretained(this), provider_authority_, url, callback)); 127 base::Unretained(this), provider_authority_, url, callback));
113 128
114 return PENDING; 129 return PENDING;
115 } 130 }
116 131
117 bool WebRestrictionsClient::SupportsRequest() const { 132 bool WebRestrictionsClient::SupportsRequest() const {
118 return initialized_ && supports_request_; 133 return initialized_ && supports_request_;
119 } 134 }
120 135
121 int WebRestrictionsClient::GetResultColumnCount(const GURL& url) const {
122 DCHECK(single_thread_task_runner_->BelongsToCurrentThread());
123 if (!initialized_)
124 return 0;
125 auto iter = cache_.find(url);
126 if (iter == cache_.end())
127 return 0;
128 return Java_ShouldProceedResult_getColumnCount(
129 base::android::AttachCurrentThread(), iter->second.obj());
130 }
131
132 std::string WebRestrictionsClient::GetResultColumnName(const GURL& url,
133 int column) const {
134 DCHECK(single_thread_task_runner_->BelongsToCurrentThread());
135 if (!initialized_)
136 return std::string();
137 auto iter = cache_.find(url);
138 if (iter == cache_.end())
139 return std::string();
140
141 JNIEnv* env = base::android::AttachCurrentThread();
142 return base::android::ConvertJavaStringToUTF8(
143 env,
144 Java_ShouldProceedResult_getColumnName(env, iter->second.obj(), column)
145 .obj());
146 }
147
148 int WebRestrictionsClient::GetResultIntValue(const GURL& url,
149 int column) const {
150 DCHECK(single_thread_task_runner_->BelongsToCurrentThread());
151 if (!initialized_)
152 return 0;
153 auto iter = cache_.find(url);
154 if (iter == cache_.end())
155 return 0;
156 return Java_ShouldProceedResult_getInt(base::android::AttachCurrentThread(),
157 iter->second.obj(), column);
158 }
159
160 std::string WebRestrictionsClient::GetResultStringValue(const GURL& url,
161 int column) const {
162 DCHECK(single_thread_task_runner_->BelongsToCurrentThread());
163 if (!initialized_)
164 return std::string();
165 auto iter = cache_.find(url);
166 if (iter == cache_.end())
167 return std::string();
168
169 JNIEnv* env = base::android::AttachCurrentThread();
170 return base::android::ConvertJavaStringToUTF8(
171 env, Java_ShouldProceedResult_getString(env, iter->second.obj(), column)
172 .obj());
173 }
174
175 void WebRestrictionsClient::RequestPermission( 136 void WebRestrictionsClient::RequestPermission(
176 const GURL& url, 137 const std::string& url,
177 const base::Callback<void(bool)>& request_success) { 138 const base::Callback<void(bool)>& request_success) {
178 if (!initialized_) { 139 if (!initialized_) {
179 request_success.Run(false); 140 request_success.Run(false);
180 return; 141 return;
181 } 142 }
182 base::PostTaskAndReplyWithResult( 143 base::PostTaskAndReplyWithResult(
183 background_task_runner_.get(), FROM_HERE, 144 background_task_runner_.get(), FROM_HERE,
184 base::Bind(&RequestPermissionTask, url, java_provider_), request_success); 145 base::Bind(&RequestPermissionTask, url, java_provider_), request_success);
185 } 146 }
186 147
187 void WebRestrictionsClient::OnWebRestrictionsChanged() { 148 void WebRestrictionsClient::OnWebRestrictionsChanged() {
188 single_thread_task_runner_->PostTask( 149 io_thread_task_runner_->PostTask(
189 FROM_HERE, 150 FROM_HERE,
190 base::Bind(&WebRestrictionsClient::ClearCache, base::Unretained(this))); 151 base::Bind(&WebRestrictionsClient::ClearCache, base::Unretained(this)));
191 } 152 }
192 153
193 void WebRestrictionsClient::RecordURLAccess(const GURL& url) { 154 void WebRestrictionsClient::RecordURLAccess(const std::string& url) {
194 DCHECK(single_thread_task_runner_->BelongsToCurrentThread()); 155 DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
195 // Move the URL to the front of the cache. 156 // Move the URL to the front of the cache.
196 recent_urls_.remove(url); 157 recent_urls_.remove(url);
197 recent_urls_.push_front(url); 158 recent_urls_.push_front(url);
198 } 159 }
199 160
200 void WebRestrictionsClient::UpdateCache(std::string provider_authority, 161 void WebRestrictionsClient::UpdateCache(std::string provider_authority,
201 GURL url, 162 std::string url,
Bernhard Bauer 2016/04/18 14:48:34 This should be const-ref (as should have been the
aberent 2016/05/18 20:06:50 Done.
202 ScopedJavaGlobalRef<jobject> result) { 163 ScopedJavaGlobalRef<jobject> result) {
203 DCHECK(single_thread_task_runner_->BelongsToCurrentThread()); 164 DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
204 // If the webrestrictions provider changed when the old one was being queried, 165 // If the webrestrictions provider changed when the old one was being queried,
205 // do not update the cache for the new provider. 166 // do not update the cache for the new provider.
206 if (provider_authority != provider_authority_) 167 if (provider_authority != provider_authority_)
207 return; 168 return;
208 RecordURLAccess(url); 169 RecordURLAccess(url);
209 if (recent_urls_.size() >= kMaxCacheSize) { 170 if (recent_urls_.size() >= kMaxCacheSize) {
210 cache_.erase(recent_urls_.back()); 171 cache_.RemoveCacheEntry(recent_urls_.back());
211 recent_urls_.pop_back(); 172 recent_urls_.pop_back();
212 } 173 }
213 cache_[url] = result; 174 cache_.SetCacheEntry(url, WebRestrictionsClientResult(result));
214 } 175 }
215 176
216 void WebRestrictionsClient::RequestSupportKnown(std::string provider_authority, 177 void WebRestrictionsClient::RequestSupportKnown(std::string provider_authority,
217 bool supports_request) { 178 bool supports_request) {
218 // |supports_request_| is initialized to false. 179 // |supports_request_| is initialized to false.
219 DCHECK(!supports_request_); 180 DCHECK(!supports_request_);
220 DCHECK(single_thread_task_runner_->BelongsToCurrentThread()); 181 DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
221 // If the webrestrictions provider changed when the old one was being queried, 182 // If the webrestrictions provider changed when the old one was being queried,
222 // ignore the result. 183 // ignore the result.
223 if (provider_authority != provider_authority_) 184 if (provider_authority != provider_authority_)
224 return; 185 return;
225 supports_request_ = supports_request; 186 supports_request_ = supports_request;
226 } 187 }
227 188
228 void WebRestrictionsClient::OnShouldProceedComplete( 189 void WebRestrictionsClient::OnShouldProceedComplete(
229 std::string provider_authority, 190 std::string provider_authority,
230 const GURL& url, 191 const std::string& url,
231 const base::Callback<void(bool)>& callback, 192 const base::Callback<void(bool)>& callback,
232 const ScopedJavaGlobalRef<jobject>& result) { 193 const ScopedJavaGlobalRef<jobject>& result) {
233 UpdateCache(provider_authority, url, result); 194 UpdateCache(provider_authority, url, result);
234 JNIEnv* env = base::android::AttachCurrentThread(); 195 callback.Run(cache_.GetCacheEntry(url)->ShouldProceed());
235 callback.Run(Java_ShouldProceedResult_shouldProceed(env, result.obj()));
236 } 196 }
237 197
238 void WebRestrictionsClient::ClearCache() { 198 void WebRestrictionsClient::ClearCache() {
239 DCHECK(single_thread_task_runner_->BelongsToCurrentThread()); 199 DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
240 cache_.clear(); 200 cache_.Clear();
241 recent_urls_.clear(); 201 recent_urls_.clear();
242 } 202 }
243 203
204 std::unique_ptr<const WebRestrictionsClientResult>
205 WebRestrictionsClient::GetCachedWebRestrictionsResult(const std::string& url) {
206 return cache_.GetCacheEntry(url);
207 }
208
244 // static 209 // static
245 ScopedJavaGlobalRef<jobject> WebRestrictionsClient::ShouldProceedTask( 210 ScopedJavaGlobalRef<jobject> WebRestrictionsClient::ShouldProceedTask(
246 const GURL& url, 211 const std::string& url,
247 const base::android::JavaRef<jobject>& java_provider) { 212 const base::android::JavaRef<jobject>& java_provider) {
248 JNIEnv* env = base::android::AttachCurrentThread(); 213 JNIEnv* env = base::android::AttachCurrentThread();
249 base::android::ScopedJavaGlobalRef<jobject> result( 214 base::android::ScopedJavaGlobalRef<jobject> result(
250 Java_WebRestrictionsClient_shouldProceed( 215 Java_WebRestrictionsClient_shouldProceed(
251 env, java_provider.obj(), 216 env, java_provider.obj(),
252 base::android::ConvertUTF8ToJavaString(env, url.spec()).obj())); 217 base::android::ConvertUTF8ToJavaString(env, url).obj()));
253 return result; 218 return result;
254 } 219 }
255 220
221 std::unique_ptr<const WebRestrictionsClientResult>
222 WebRestrictionsCache::GetCacheEntry(const std::string& url) {
223 lock_.Acquire();
Bernhard Bauer 2016/04/18 14:48:34 Use base::AutoLock for this. That way you can also
aberent 2016/05/18 20:06:50 Done.
224 std::unique_ptr<const WebRestrictionsClientResult> result;
225 auto iter = cache_data_.find(url);
226 if (iter != cache_data_.end())
227 // This has to be thread-safe, so copy the data.
228 result.reset(new WebRestrictionsClientResult(iter->second));
229 lock_.Release();
230 return result;
231 }
232
233 void WebRestrictionsCache::SetCacheEntry(
234 const std::string& url,
235 const WebRestrictionsClientResult& entry) {
236 lock_.Acquire();
237 cache_data_[url] = entry;
238 lock_.Release();
239 }
240
241 void WebRestrictionsCache::RemoveCacheEntry(const std::string& url) {
242 lock_.Acquire();
243 cache_data_.erase(url);
244 lock_.Release();
245 }
246
247 void WebRestrictionsCache::Clear() {
248 lock_.Acquire();
249 cache_data_.clear();
250 lock_.Release();
251 }
252
256 void NotifyWebRestrictionsChanged( 253 void NotifyWebRestrictionsChanged(
Bernhard Bauer 2016/04/18 14:48:34 Actually, we could remove this and just directly c
aberent 2016/05/18 20:06:50 Done.
257 JNIEnv* env, 254 JNIEnv* env,
258 const base::android::JavaParamRef<jobject>& clazz, 255 const base::android::JavaParamRef<jobject>& clazz,
259 jlong provider_ptr) { 256 jlong provider_ptr) {
260 WebRestrictionsClient* provider = 257 WebRestrictionsClient* provider =
261 reinterpret_cast<WebRestrictionsClient*>(provider_ptr); 258 reinterpret_cast<WebRestrictionsClient*>(provider_ptr);
262 // TODO(knn): Also reload existing interstitials/error pages. 259 // TODO(knn): Also reload existing interstitials/error pages.
263 provider->OnWebRestrictionsChanged(); 260 provider->OnWebRestrictionsChanged();
264 } 261 }
265 262
266 } // namespace web_restrictions 263 } // namespace web_restrictions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698