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

Side by Side Diff: android_webview/browser/aw_contents_io_thread_client_impl.cc

Issue 2889193004: [WebView] Replace AwContentsIoThreadClient, InputStream and AwWebResourceResponse (Closed)
Patch Set: fix test crash Created 3 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
(Empty)
1 // Copyright (c) 2012 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 "android_webview/browser/aw_contents_io_thread_client_impl.h"
6
7 #include <map>
8 #include <memory>
9 #include <utility>
10
11 #include "android_webview/browser/aw_contents_background_thread_client.h"
12 #include "android_webview/browser/aw_web_resource_response_impl.h"
13 #include "android_webview/browser/net/aw_web_resource_request.h"
14 #include "android_webview/common/devtools_instrumentation.h"
15 #include "base/android/jni_array.h"
16 #include "base/android/jni_string.h"
17 #include "base/android/jni_weak_ref.h"
18 #include "base/lazy_instance.h"
19 #include "base/synchronization/lock.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/render_frame_host.h"
22 #include "content/public/browser/render_process_host.h"
23 #include "content/public/browser/render_view_host.h"
24 #include "content/public/browser/resource_request_info.h"
25 #include "content/public/browser/web_contents.h"
26 #include "content/public/browser/web_contents_observer.h"
27 #include "jni/AwContentsIoThreadClient_jni.h"
28 #include "net/url_request/url_request.h"
29
30 using base::android::AttachCurrentThread;
31 using base::android::ConvertUTF8ToJavaString;
32 using base::android::JavaRef;
33 using base::android::ScopedJavaLocalRef;
34 using base::android::ToJavaArrayOfStrings;
35 using base::LazyInstance;
36 using content::BrowserThread;
37 using content::RenderFrameHost;
38 using content::ResourceType;
39 using content::WebContents;
40 using std::map;
41 using std::pair;
42 using std::string;
43
44 namespace android_webview {
45
46 namespace {
47
48 struct IoThreadClientData {
49 bool pending_association;
50 JavaObjectWeakGlobalRef io_thread_client;
51
52 IoThreadClientData();
53 };
54
55 IoThreadClientData::IoThreadClientData() : pending_association(false) {}
56
57 typedef map<pair<int, int>, IoThreadClientData>
58 RenderFrameHostToIoThreadClientType;
59
60 // When browser side navigation is enabled, RenderFrameIDs do not have
61 // valid render process host and render frame ids for frame navigations.
62 // We need to identify these by using Frame Tree Node ids.
63 typedef map<int, IoThreadClientData> FrameTreeNodeToIoThreadClientType;
64
65 static pair<int, int> GetRenderFrameHostIdPair(RenderFrameHost* rfh) {
66 return pair<int, int>(rfh->GetProcess()->GetID(), rfh->GetRoutingID());
67 }
68
69 // RfhToIoThreadClientMap -----------------------------------------------------
70 class RfhToIoThreadClientMap {
71 public:
72 static RfhToIoThreadClientMap* GetInstance();
73 void Set(pair<int, int> rfh_id, const IoThreadClientData& client);
74 bool Get(pair<int, int> rfh_id, IoThreadClientData* client);
75 void Erase(pair<int, int> rfh_id);
76
77 void Set(int frame_tree_node_id, const IoThreadClientData& client);
78 bool Get(int frame_tree_node_id, IoThreadClientData* client);
79 void Erase(int frame_tree_node_id);
80
81 private:
82 base::Lock map_lock_;
83 RenderFrameHostToIoThreadClientType rfh_to_io_thread_client_;
84 FrameTreeNodeToIoThreadClientType frame_tree_node_to_io_thread_client_;
85 };
86
87 // static
88 LazyInstance<RfhToIoThreadClientMap>::DestructorAtExit g_instance_ =
89 LAZY_INSTANCE_INITIALIZER;
90
91 // static
92 LazyInstance<JavaObjectWeakGlobalRef>::DestructorAtExit g_sw_instance_ =
93 LAZY_INSTANCE_INITIALIZER;
94
95 // static
96 RfhToIoThreadClientMap* RfhToIoThreadClientMap::GetInstance() {
97 return g_instance_.Pointer();
98 }
99
100 void RfhToIoThreadClientMap::Set(pair<int, int> rfh_id,
101 const IoThreadClientData& client) {
102 base::AutoLock lock(map_lock_);
103 rfh_to_io_thread_client_[rfh_id] = client;
104 }
105
106 bool RfhToIoThreadClientMap::Get(pair<int, int> rfh_id,
107 IoThreadClientData* client) {
108 base::AutoLock lock(map_lock_);
109 RenderFrameHostToIoThreadClientType::iterator iterator =
110 rfh_to_io_thread_client_.find(rfh_id);
111 if (iterator == rfh_to_io_thread_client_.end())
112 return false;
113
114 *client = iterator->second;
115 return true;
116 }
117
118 void RfhToIoThreadClientMap::Erase(pair<int, int> rfh_id) {
119 base::AutoLock lock(map_lock_);
120 rfh_to_io_thread_client_.erase(rfh_id);
121 }
122
123 void RfhToIoThreadClientMap::Set(int frame_tree_node_id,
124 const IoThreadClientData& client) {
125 base::AutoLock lock(map_lock_);
126 frame_tree_node_to_io_thread_client_[frame_tree_node_id] = client;
127 }
128
129 bool RfhToIoThreadClientMap::Get(int frame_tree_node_id,
130 IoThreadClientData* client) {
131 base::AutoLock lock(map_lock_);
132 FrameTreeNodeToIoThreadClientType::iterator iterator =
133 frame_tree_node_to_io_thread_client_.find(frame_tree_node_id);
134 if (iterator == frame_tree_node_to_io_thread_client_.end())
135 return false;
136
137 *client = iterator->second;
138 return true;
139 }
140
141 void RfhToIoThreadClientMap::Erase(int frame_tree_node_id) {
142 base::AutoLock lock(map_lock_);
143 frame_tree_node_to_io_thread_client_.erase(frame_tree_node_id);
144 }
145
146 // ClientMapEntryUpdater ------------------------------------------------------
147
148 class ClientMapEntryUpdater : public content::WebContentsObserver {
149 public:
150 ClientMapEntryUpdater(JNIEnv* env,
151 WebContents* web_contents,
152 jobject jdelegate);
153
154 void RenderFrameCreated(RenderFrameHost* render_frame_host) override;
155 void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
156 void WebContentsDestroyed() override;
157
158 private:
159 JavaObjectWeakGlobalRef jdelegate_;
160 };
161
162 ClientMapEntryUpdater::ClientMapEntryUpdater(JNIEnv* env,
163 WebContents* web_contents,
164 jobject jdelegate)
165 : content::WebContentsObserver(web_contents), jdelegate_(env, jdelegate) {
166 DCHECK(web_contents);
167 DCHECK(jdelegate);
168
169 if (web_contents->GetMainFrame())
170 RenderFrameCreated(web_contents->GetMainFrame());
171 }
172
173 void ClientMapEntryUpdater::RenderFrameCreated(RenderFrameHost* rfh) {
174 IoThreadClientData client_data;
175 client_data.io_thread_client = jdelegate_;
176 client_data.pending_association = false;
177 RfhToIoThreadClientMap::GetInstance()->Set(GetRenderFrameHostIdPair(rfh),
178 client_data);
179 RfhToIoThreadClientMap::GetInstance()->Set(rfh->GetFrameTreeNodeId(),
180 client_data);
181 }
182
183 void ClientMapEntryUpdater::RenderFrameDeleted(RenderFrameHost* rfh) {
184 RfhToIoThreadClientMap::GetInstance()->Erase(GetRenderFrameHostIdPair(rfh));
185 RfhToIoThreadClientMap::GetInstance()->Erase(rfh->GetFrameTreeNodeId());
186 }
187
188 void ClientMapEntryUpdater::WebContentsDestroyed() {
189 delete this;
190 }
191
192 } // namespace
193
194 // AwContentsIoThreadClientImpl -----------------------------------------------
195
196 // static
197 std::unique_ptr<AwContentsIoThreadClient> AwContentsIoThreadClient::FromID(
198 int render_process_id,
199 int render_frame_id) {
200 pair<int, int> rfh_id(render_process_id, render_frame_id);
201 IoThreadClientData client_data;
202 if (!RfhToIoThreadClientMap::GetInstance()->Get(rfh_id, &client_data))
203 return std::unique_ptr<AwContentsIoThreadClient>();
204
205 JNIEnv* env = AttachCurrentThread();
206 ScopedJavaLocalRef<jobject> java_delegate =
207 client_data.io_thread_client.get(env);
208 DCHECK(!client_data.pending_association || java_delegate.is_null());
209 return std::unique_ptr<AwContentsIoThreadClient>(
210 new AwContentsIoThreadClientImpl(client_data.pending_association,
211 java_delegate));
212 }
213
214 std::unique_ptr<AwContentsIoThreadClient> AwContentsIoThreadClient::FromID(
215 int frame_tree_node_id) {
216 IoThreadClientData client_data;
217 if (!RfhToIoThreadClientMap::GetInstance()->Get(frame_tree_node_id,
218 &client_data))
219 return std::unique_ptr<AwContentsIoThreadClient>();
220
221 JNIEnv* env = AttachCurrentThread();
222 ScopedJavaLocalRef<jobject> java_delegate =
223 client_data.io_thread_client.get(env);
224 DCHECK(!client_data.pending_association || java_delegate.is_null());
225 return std::unique_ptr<AwContentsIoThreadClient>(
226 new AwContentsIoThreadClientImpl(client_data.pending_association,
227 java_delegate));
228 }
229
230 // static
231 void AwContentsIoThreadClient::SubFrameCreated(int render_process_id,
232 int parent_render_frame_id,
233 int child_render_frame_id) {
234 pair<int, int> parent_rfh_id(render_process_id, parent_render_frame_id);
235 pair<int, int> child_rfh_id(render_process_id, child_render_frame_id);
236 IoThreadClientData client_data;
237 if (!RfhToIoThreadClientMap::GetInstance()->Get(parent_rfh_id,
238 &client_data)) {
239 NOTREACHED();
240 return;
241 }
242
243 RfhToIoThreadClientMap::GetInstance()->Set(child_rfh_id, client_data);
244 }
245
246 // static
247 void AwContentsIoThreadClientImpl::RegisterPendingContents(
248 WebContents* web_contents) {
249 IoThreadClientData client_data;
250 client_data.pending_association = true;
251 RfhToIoThreadClientMap::GetInstance()->Set(
252 GetRenderFrameHostIdPair(web_contents->GetMainFrame()), client_data);
253 }
254
255 // static
256 void AwContentsIoThreadClientImpl::Associate(WebContents* web_contents,
257 const JavaRef<jobject>& jclient) {
258 JNIEnv* env = AttachCurrentThread();
259 // The ClientMapEntryUpdater lifespan is tied to the WebContents.
260 new ClientMapEntryUpdater(env, web_contents, jclient.obj());
261 }
262
263 // static
264 void AwContentsIoThreadClientImpl::SetServiceWorkerIoThreadClient(
265 const base::android::JavaRef<jobject>& jclient,
266 const base::android::JavaRef<jobject>& browser_context) {
267 // TODO: currently there is only one browser context so it is ok to
268 // store in a global variable, in the future use browser_context to
269 // obtain the correct instance.
270 JavaObjectWeakGlobalRef temp(AttachCurrentThread(), jclient.obj());
271 g_sw_instance_.Get() = temp;
272 }
273
274 // static
275 std::unique_ptr<AwContentsIoThreadClient>
276 AwContentsIoThreadClient::GetServiceWorkerIoThreadClient() {
277 JNIEnv* env = AttachCurrentThread();
278 ScopedJavaLocalRef<jobject> java_delegate = g_sw_instance_.Get().get(env);
279
280 if (java_delegate.is_null())
281 return std::unique_ptr<AwContentsIoThreadClient>();
282
283 return std::unique_ptr<AwContentsIoThreadClient>(
284 new AwContentsIoThreadClientImpl(false, java_delegate));
285 }
286
287 AwContentsIoThreadClientImpl::AwContentsIoThreadClientImpl(
288 bool pending_association,
289 const JavaRef<jobject>& obj)
290 : pending_association_(pending_association), java_object_(obj) {}
291
292 AwContentsIoThreadClientImpl::~AwContentsIoThreadClientImpl() {
293 // explict, out-of-line destructor.
294 }
295
296 bool AwContentsIoThreadClientImpl::PendingAssociation() const {
297 return pending_association_;
298 }
299
300 AwContentsIoThreadClient::CacheMode AwContentsIoThreadClientImpl::GetCacheMode()
301 const {
302 DCHECK_CURRENTLY_ON(BrowserThread::IO);
303 if (java_object_.is_null())
304 return AwContentsIoThreadClient::LOAD_DEFAULT;
305
306 JNIEnv* env = AttachCurrentThread();
307 return static_cast<AwContentsIoThreadClient::CacheMode>(
308 Java_AwContentsIoThreadClient_getCacheMode(env, java_object_));
309 }
310
311 namespace {
312
313 std::unique_ptr<AwWebResourceResponse> RunShouldInterceptRequest(
314 const AwWebResourceRequest& request,
315 JavaObjectWeakGlobalRef ref) {
316 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
317 JNIEnv* env = AttachCurrentThread();
318 base::android::ScopedJavaLocalRef<jobject> obj = ref.get(env);
319 if (obj.is_null())
320 return nullptr;
321
322 AwWebResourceRequest::AwJavaWebResourceRequest java_web_resource_request;
323 AwWebResourceRequest::ConvertToJava(env, request, &java_web_resource_request);
324
325 devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback(
326 "shouldInterceptRequest");
327 ScopedJavaLocalRef<jobject> ret =
328 AwContentsBackgroundThreadClient::shouldInterceptRequest(
329 env, obj, java_web_resource_request.jurl, request.is_main_frame,
330 request.has_user_gesture, java_web_resource_request.jmethod,
331 java_web_resource_request.jheader_names,
332 java_web_resource_request.jheader_values);
333 return std::unique_ptr<AwWebResourceResponse>(
334 ret.is_null() ? nullptr : new AwWebResourceResponseImpl(ret));
335 }
336
337 std::unique_ptr<AwWebResourceResponse> ReturnNull() {
338 return std::unique_ptr<AwWebResourceResponse>();
339 }
340
341 } // namespace
342
343 void AwContentsIoThreadClientImpl::ShouldInterceptRequestAsync(
344 const net::URLRequest* request,
345 const ShouldInterceptRequestResultCallback callback) {
346 DCHECK_CURRENTLY_ON(BrowserThread::IO);
347 base::Callback<std::unique_ptr<AwWebResourceResponse>()> get_response =
348 base::Bind(&ReturnNull);
349 JNIEnv* env = AttachCurrentThread();
350 if (bg_thread_client_object_.is_null() && !java_object_.is_null()) {
351 bg_thread_client_object_.Reset(
352 Java_AwContentsIoThreadClient_getBackgroundThreadClient(env,
353 java_object_));
354 }
355 if (!bg_thread_client_object_.is_null()) {
356 get_response = base::Bind(
357 &RunShouldInterceptRequest, AwWebResourceRequest(*request),
358 JavaObjectWeakGlobalRef(env, bg_thread_client_object_.obj()));
359 }
360 BrowserThread::PostTaskAndReplyWithResult(BrowserThread::FILE, FROM_HERE,
361 get_response, callback);
362 }
363
364 bool AwContentsIoThreadClientImpl::ShouldBlockContentUrls() const {
365 DCHECK_CURRENTLY_ON(BrowserThread::IO);
366 if (java_object_.is_null())
367 return false;
368
369 JNIEnv* env = AttachCurrentThread();
370 return Java_AwContentsIoThreadClient_shouldBlockContentUrls(env,
371 java_object_);
372 }
373
374 bool AwContentsIoThreadClientImpl::ShouldBlockFileUrls() const {
375 DCHECK_CURRENTLY_ON(BrowserThread::IO);
376 if (java_object_.is_null())
377 return false;
378
379 JNIEnv* env = AttachCurrentThread();
380 return Java_AwContentsIoThreadClient_shouldBlockFileUrls(env, java_object_);
381 }
382
383 bool AwContentsIoThreadClientImpl::ShouldAcceptThirdPartyCookies() const {
384 DCHECK_CURRENTLY_ON(BrowserThread::IO);
385 if (java_object_.is_null())
386 return false;
387
388 JNIEnv* env = AttachCurrentThread();
389 return Java_AwContentsIoThreadClient_shouldAcceptThirdPartyCookies(
390 env, java_object_);
391 }
392
393 bool AwContentsIoThreadClientImpl::GetSafeBrowsingEnabled() const {
394 DCHECK_CURRENTLY_ON(BrowserThread::IO);
395 if (java_object_.is_null())
396 return false;
397
398 JNIEnv* env = AttachCurrentThread();
399 return Java_AwContentsIoThreadClient_getSafeBrowsingEnabled(env,
400 java_object_);
401 }
402
403 bool AwContentsIoThreadClientImpl::ShouldBlockNetworkLoads() const {
404 DCHECK_CURRENTLY_ON(BrowserThread::IO);
405 if (java_object_.is_null())
406 return false;
407
408 JNIEnv* env = AttachCurrentThread();
409 return Java_AwContentsIoThreadClient_shouldBlockNetworkLoads(env,
410 java_object_);
411 }
412
413 } // namespace android_webview
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698