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

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: Respond to comments, and fix a possible race in displaying error page Created 4 years, 7 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/logging.h"
10 #include "base/threading/thread_task_runner_handle.h" 11 #include "base/threading/thread_task_runner_handle.h"
11 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/browser_thread.h"
12 #include "jni/WebRestrictionsClient_jni.h" 13 #include "jni/WebRestrictionsClient_jni.h"
13 14
14 using base::android::ScopedJavaGlobalRef; 15 using base::android::ScopedJavaGlobalRef;
15 16
16 namespace web_restrictions { 17 namespace web_restrictions {
17 18
18 namespace { 19 namespace {
19 20
20 const size_t kMaxCacheSize = 100; 21 const size_t kMaxCacheSize = 100;
21 22
22 bool RequestPermissionTask( 23 bool RequestPermissionTask(
23 const GURL& url, 24 const std::string& url,
24 const base::android::JavaRef<jobject>& java_provider) { 25 const base::android::JavaRef<jobject>& java_provider) {
25 JNIEnv* env = base::android::AttachCurrentThread(); 26 JNIEnv* env = base::android::AttachCurrentThread();
26 return Java_WebRestrictionsClient_requestPermission( 27 return Java_WebRestrictionsClient_requestPermission(
27 env, java_provider.obj(), 28 env, java_provider.obj(),
28 base::android::ConvertUTF8ToJavaString(env, url.spec()).obj()); 29 base::android::ConvertUTF8ToJavaString(env, url).obj());
29 } 30 }
30 31
31 bool CheckSupportsRequestTask( 32 bool CheckSupportsRequestTask(
32 const base::android::JavaRef<jobject>& java_provider) { 33 const base::android::JavaRef<jobject>& java_provider) {
33 JNIEnv* env = base::android::AttachCurrentThread(); 34 JNIEnv* env = base::android::AttachCurrentThread();
34 return Java_WebRestrictionsClient_supportsRequest(env, java_provider.obj()); 35 return Java_WebRestrictionsClient_supportsRequest(env, java_provider.obj());
35 } 36 }
36 37
37 } // namespace 38 } // namespace
38 39
39 // static 40 // static
40 bool WebRestrictionsClient::Register(JNIEnv* env) { 41 bool WebRestrictionsClient::Register(JNIEnv* env) {
41 return RegisterNativesImpl(env); 42 return RegisterNativesImpl(env);
42 } 43 }
43 44
44 WebRestrictionsClient::WebRestrictionsClient() 45 WebRestrictionsClient::WebRestrictionsClient()
45 : initialized_(false), supports_request_(false) { 46 : initialized_(false), supports_request_(false) {
46 single_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();
47 base::SequencedWorkerPool* worker_pool = 47 base::SequencedWorkerPool* worker_pool =
48 content::BrowserThread::GetBlockingPool(); 48 content::BrowserThread::GetBlockingPool();
49 background_task_runner_ = 49 background_task_runner_ =
50 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( 50 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior(
51 worker_pool->GetSequenceToken(), 51 worker_pool->GetSequenceToken(),
52 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); 52 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
53 } 53 }
54 54
55 WebRestrictionsClient::~WebRestrictionsClient() { 55 WebRestrictionsClient::~WebRestrictionsClient() {
56 if (java_provider_.is_null()) 56 if (java_provider_.is_null())
57 return; 57 return;
58 JNIEnv* env = base::android::AttachCurrentThread(); 58 JNIEnv* env = base::android::AttachCurrentThread();
59 Java_WebRestrictionsClient_onDestroy(env, java_provider_.obj()); 59 Java_WebRestrictionsClient_onDestroy(env, java_provider_.obj());
60 java_provider_.Reset(); 60 java_provider_.Reset();
61 } 61 }
62 62
63 void WebRestrictionsClient::SetAuthority( 63 void WebRestrictionsClient::SetAuthority(
64 const std::string& content_provider_authority) { 64 const std::string& content_provider_authority) {
65 DCHECK(single_thread_task_runner_->BelongsToCurrentThread()); 65 // This is called from the UI thread, but class members should only be
66 // accessed from the IO thread.
67 content::BrowserThread::PostTask(
68 content::BrowserThread::IO, FROM_HERE,
69 base::Bind(&WebRestrictionsClient::SetAuthorityTask,
70 base::Unretained(this), content_provider_authority));
71 }
72
73 void WebRestrictionsClient::SetAuthorityTask(
74 const std::string& content_provider_authority) {
75 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
66 // Destroy any existing content resolver. 76 // Destroy any existing content resolver.
67 JNIEnv* env = base::android::AttachCurrentThread(); 77 JNIEnv* env = base::android::AttachCurrentThread();
68 if (!java_provider_.is_null()) { 78 if (!java_provider_.is_null()) {
69 Java_WebRestrictionsClient_onDestroy(env, java_provider_.obj()); 79 Java_WebRestrictionsClient_onDestroy(env, java_provider_.obj());
70 java_provider_.Reset(); 80 java_provider_.Reset();
71 } 81 }
72 ClearCache(); 82 ClearCache();
73 provider_authority_ = content_provider_authority; 83 provider_authority_ = content_provider_authority;
74 84
75 // Initialize the content resolver. 85 // Initialize the content resolver.
76 initialized_ = !content_provider_authority.empty(); 86 initialized_ = !content_provider_authority.empty();
77 if (!initialized_) 87 if (!initialized_)
78 return; 88 return;
79 java_provider_.Reset(Java_WebRestrictionsClient_create( 89 java_provider_.Reset(Java_WebRestrictionsClient_create(
80 env, 90 env,
81 base::android::ConvertUTF8ToJavaString(env, content_provider_authority) 91 base::android::ConvertUTF8ToJavaString(env, content_provider_authority)
82 .obj(), 92 .obj(),
83 reinterpret_cast<jlong>(this))); 93 reinterpret_cast<jlong>(this)));
84 supports_request_ = false; 94 supports_request_ = false;
85 base::PostTaskAndReplyWithResult( 95 base::PostTaskAndReplyWithResult(
86 content::BrowserThread::GetBlockingPool(), FROM_HERE, 96 content::BrowserThread::GetBlockingPool(), FROM_HERE,
87 base::Bind(&CheckSupportsRequestTask, java_provider_), 97 base::Bind(&CheckSupportsRequestTask, java_provider_),
88 base::Bind(&WebRestrictionsClient::RequestSupportKnown, 98 base::Bind(&WebRestrictionsClient::RequestSupportKnown,
89 base::Unretained(this), provider_authority_)); 99 base::Unretained(this), provider_authority_));
90 } 100 }
91 101
92 UrlAccess WebRestrictionsClient::ShouldProceed( 102 UrlAccess WebRestrictionsClient::ShouldProceed(
93 bool is_main_frame, 103 bool is_main_frame,
94 const GURL& url, 104 const std::string& url,
95 const base::Callback<void(bool)>& callback) { 105 const base::Callback<void(bool)>& callback) {
96 DCHECK(single_thread_task_runner_->BelongsToCurrentThread()); 106 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
97 if (!initialized_) 107 if (!initialized_)
98 return ALLOW; 108 return ALLOW;
99 auto iter = cache_.find(url); 109
100 if (iter != cache_.end()) { 110 std::unique_ptr<const WebRestrictionsClientResult> result =
111 cache_.GetCacheEntry(url);
112 if (result) {
101 RecordURLAccess(url); 113 RecordURLAccess(url);
102 JNIEnv* env = base::android::AttachCurrentThread(); 114 return result->ShouldProceed() ? ALLOW : DISALLOW;
103 return Java_ShouldProceedResult_shouldProceed(env, iter->second.obj())
104 ? ALLOW
105 : DISALLOW;
106 } 115 }
107 base::PostTaskAndReplyWithResult( 116 base::PostTaskAndReplyWithResult(
108 background_task_runner_.get(), FROM_HERE, 117 background_task_runner_.get(), FROM_HERE,
109 base::Bind(&WebRestrictionsClient::ShouldProceedTask, url, 118 base::Bind(&WebRestrictionsClient::ShouldProceedTask, url,
110 java_provider_), 119 java_provider_),
111 base::Bind(&WebRestrictionsClient::OnShouldProceedComplete, 120 base::Bind(&WebRestrictionsClient::OnShouldProceedComplete,
112 base::Unretained(this), provider_authority_, url, callback)); 121 base::Unretained(this), provider_authority_, url, callback));
113 122
114 return PENDING; 123 return PENDING;
115 } 124 }
116 125
117 bool WebRestrictionsClient::SupportsRequest() const { 126 bool WebRestrictionsClient::SupportsRequest() const {
118 return initialized_ && supports_request_; 127 return initialized_ && supports_request_;
119 } 128 }
120 129
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( 130 void WebRestrictionsClient::RequestPermission(
176 const GURL& url, 131 const std::string& url,
177 const base::Callback<void(bool)>& request_success) { 132 const base::Callback<void(bool)>& request_success) {
178 if (!initialized_) { 133 if (!initialized_) {
179 request_success.Run(false); 134 request_success.Run(false);
180 return; 135 return;
181 } 136 }
182 base::PostTaskAndReplyWithResult( 137 base::PostTaskAndReplyWithResult(
183 background_task_runner_.get(), FROM_HERE, 138 background_task_runner_.get(), FROM_HERE,
184 base::Bind(&RequestPermissionTask, url, java_provider_), request_success); 139 base::Bind(&RequestPermissionTask, url, java_provider_), request_success);
185 } 140 }
186 141
187 void WebRestrictionsClient::OnWebRestrictionsChanged() { 142 void WebRestrictionsClient::OnWebRestrictionsChanged(
188 single_thread_task_runner_->PostTask( 143 JNIEnv* env,
189 FROM_HERE, 144 const base::android::JavaParamRef<jobject>& obj) {
145 content::BrowserThread::PostTask(
146 content::BrowserThread::IO, FROM_HERE,
190 base::Bind(&WebRestrictionsClient::ClearCache, base::Unretained(this))); 147 base::Bind(&WebRestrictionsClient::ClearCache, base::Unretained(this)));
191 } 148 }
192 149
193 void WebRestrictionsClient::RecordURLAccess(const GURL& url) { 150 void WebRestrictionsClient::RecordURLAccess(const std::string& url) {
194 DCHECK(single_thread_task_runner_->BelongsToCurrentThread()); 151 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
195 // Move the URL to the front of the cache. 152 // Move the URL to the front of the cache.
196 recent_urls_.remove(url); 153 recent_urls_.remove(url);
197 recent_urls_.push_front(url); 154 recent_urls_.push_front(url);
198 } 155 }
199 156
200 void WebRestrictionsClient::UpdateCache(std::string provider_authority, 157 void WebRestrictionsClient::UpdateCache(const std::string& provider_authority,
201 GURL url, 158 const std::string& url,
202 ScopedJavaGlobalRef<jobject> result) { 159 ScopedJavaGlobalRef<jobject> result) {
203 DCHECK(single_thread_task_runner_->BelongsToCurrentThread()); 160 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
204 // If the webrestrictions provider changed when the old one was being queried, 161 // If the webrestrictions provider changed when the old one was being queried,
205 // do not update the cache for the new provider. 162 // do not update the cache for the new provider.
206 if (provider_authority != provider_authority_) 163 if (provider_authority != provider_authority_)
207 return; 164 return;
208 RecordURLAccess(url); 165 RecordURLAccess(url);
209 if (recent_urls_.size() >= kMaxCacheSize) { 166 if (recent_urls_.size() >= kMaxCacheSize) {
210 cache_.erase(recent_urls_.back()); 167 cache_.RemoveCacheEntry(recent_urls_.back());
211 recent_urls_.pop_back(); 168 recent_urls_.pop_back();
212 } 169 }
213 cache_[url] = result; 170 cache_.SetCacheEntry(url, WebRestrictionsClientResult(result));
214 } 171 }
215 172
216 void WebRestrictionsClient::RequestSupportKnown(std::string provider_authority, 173 void WebRestrictionsClient::RequestSupportKnown(
217 bool supports_request) { 174 const std::string& provider_authority,
175 bool supports_request) {
218 // |supports_request_| is initialized to false. 176 // |supports_request_| is initialized to false.
219 DCHECK(!supports_request_); 177 DCHECK(!supports_request_);
220 DCHECK(single_thread_task_runner_->BelongsToCurrentThread()); 178 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
221 // If the webrestrictions provider changed when the old one was being queried, 179 // If the webrestrictions provider changed when the old one was being queried,
222 // ignore the result. 180 // ignore the result.
223 if (provider_authority != provider_authority_) 181 if (provider_authority != provider_authority_)
224 return; 182 return;
225 supports_request_ = supports_request; 183 supports_request_ = supports_request;
226 } 184 }
227 185
228 void WebRestrictionsClient::OnShouldProceedComplete( 186 void WebRestrictionsClient::OnShouldProceedComplete(
229 std::string provider_authority, 187 std::string provider_authority,
230 const GURL& url, 188 const std::string& url,
231 const base::Callback<void(bool)>& callback, 189 const base::Callback<void(bool)>& callback,
232 const ScopedJavaGlobalRef<jobject>& result) { 190 const ScopedJavaGlobalRef<jobject>& result) {
233 UpdateCache(provider_authority, url, result); 191 UpdateCache(provider_authority, url, result);
234 JNIEnv* env = base::android::AttachCurrentThread(); 192 callback.Run(cache_.GetCacheEntry(url)->ShouldProceed());
235 callback.Run(Java_ShouldProceedResult_shouldProceed(env, result.obj()));
236 } 193 }
237 194
238 void WebRestrictionsClient::ClearCache() { 195 void WebRestrictionsClient::ClearCache() {
239 DCHECK(single_thread_task_runner_->BelongsToCurrentThread()); 196 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
240 cache_.clear(); 197 cache_.Clear();
241 recent_urls_.clear(); 198 recent_urls_.clear();
242 } 199 }
243 200
201 std::unique_ptr<WebRestrictionsClientResult>
202 WebRestrictionsClient::GetCachedWebRestrictionsResult(const std::string& url) {
203 return cache_.GetCacheEntry(url);
204 }
205
244 // static 206 // static
245 ScopedJavaGlobalRef<jobject> WebRestrictionsClient::ShouldProceedTask( 207 ScopedJavaGlobalRef<jobject> WebRestrictionsClient::ShouldProceedTask(
246 const GURL& url, 208 const std::string& url,
247 const base::android::JavaRef<jobject>& java_provider) { 209 const base::android::JavaRef<jobject>& java_provider) {
248 JNIEnv* env = base::android::AttachCurrentThread(); 210 JNIEnv* env = base::android::AttachCurrentThread();
249 base::android::ScopedJavaGlobalRef<jobject> result( 211 base::android::ScopedJavaGlobalRef<jobject> result(
250 Java_WebRestrictionsClient_shouldProceed( 212 Java_WebRestrictionsClient_shouldProceed(
251 env, java_provider.obj(), 213 env, java_provider.obj(),
252 base::android::ConvertUTF8ToJavaString(env, url.spec()).obj())); 214 base::android::ConvertUTF8ToJavaString(env, url).obj()));
253 return result; 215 return result;
254 } 216 }
255 217
256 void NotifyWebRestrictionsChanged( 218 std::unique_ptr<WebRestrictionsClientResult>
257 JNIEnv* env, 219 WebRestrictionsClient::Cache::GetCacheEntry(const std::string& url) {
258 const base::android::JavaParamRef<jobject>& clazz, 220 base::AutoLock lock(lock_);
259 jlong provider_ptr) { 221 auto iter = cache_data_.find(url);
260 WebRestrictionsClient* provider = 222 if (iter == cache_data_.end())
261 reinterpret_cast<WebRestrictionsClient*>(provider_ptr); 223 return nullptr;
262 // TODO(knn): Also reload existing interstitials/error pages. 224 // This has to be thread-safe, so copy the data.
263 provider->OnWebRestrictionsChanged(); 225 return std::unique_ptr<WebRestrictionsClientResult>(
226 new WebRestrictionsClientResult(iter->second));
227 }
228
229 void WebRestrictionsClient::Cache::SetCacheEntry(
230 const std::string& url,
231 const WebRestrictionsClientResult& entry) {
232 base::AutoLock lock(lock_);
233 cache_data_.emplace(url, entry);
234 }
235
236 void WebRestrictionsClient::Cache::RemoveCacheEntry(const std::string& url) {
237 base::AutoLock lock(lock_);
238 cache_data_.erase(url);
239 }
240
241 void WebRestrictionsClient::Cache::Clear() {
242 base::AutoLock lock(lock_);
243 cache_data_.clear();
264 } 244 }
265 245
266 } // namespace web_restrictions 246 } // namespace web_restrictions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698