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

Side by Side Diff: content/browser/loader/navigation_resource_throttle.cc

Issue 2321543002: Merge CrossSiteResourceHandler and NavigationResourceThrottle (Closed)
Patch Set: Addressed comments Created 4 years, 3 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 "content/browser/loader/navigation_resource_throttle.h" 5 #include "content/browser/loader/navigation_resource_throttle.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback.h" 10 #include "base/callback.h"
11 #include "base/location.h" 11 #include "base/location.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/ref_counted.h" 13 #include "base/memory/ref_counted.h"
14 #include "content/browser/frame_host/navigation_handle_impl.h" 14 #include "content/browser/frame_host/navigation_handle_impl.h"
15 #include "content/browser/frame_host/render_frame_host_impl.h" 15 #include "content/browser/frame_host/render_frame_host_impl.h"
16 #include "content/browser/loader/resource_dispatcher_host_impl.h"
16 #include "content/browser/loader/resource_loader.h" 17 #include "content/browser/loader/resource_loader.h"
17 #include "content/browser/loader/resource_request_info_impl.h" 18 #include "content/browser/loader/resource_request_info_impl.h"
18 #include "content/public/browser/browser_thread.h" 19 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/navigation_data.h" 20 #include "content/public/browser/navigation_data.h"
20 #include "content/public/browser/resource_context.h" 21 #include "content/public/browser/resource_context.h"
21 #include "content/public/browser/resource_controller.h" 22 #include "content/public/browser/resource_controller.h"
22 #include "content/public/browser/resource_dispatcher_host_delegate.h" 23 #include "content/public/browser/resource_dispatcher_host_delegate.h"
23 #include "content/public/browser/resource_request_info.h" 24 #include "content/public/browser/resource_request_info.h"
24 #include "content/public/common/referrer.h" 25 #include "content/public/common/referrer.h"
25 #include "content/public/common/ssl_status.h" 26 #include "content/public/common/ssl_status.h"
26 #include "net/url_request/redirect_info.h" 27 #include "net/url_request/redirect_info.h"
27 #include "net/url_request/url_request.h" 28 #include "net/url_request/url_request.h"
28 #include "net/url_request/url_request_context.h" 29 #include "net/url_request/url_request_context.h"
29 #include "net/url_request/url_request_job_factory.h" 30 #include "net/url_request/url_request_job_factory.h"
30 #include "ui/base/page_transition_types.h" 31 #include "ui/base/page_transition_types.h"
31 32
32 namespace content { 33 namespace content {
33 34
34 namespace { 35 namespace {
36
37 // Used in unit tests to make UI checks succeed even if there is no
38 // NavigationHandle and to transfer all navigations.
39 bool g_ui_checks_always_succeed = false;
40 bool g_force_transfer = false;
41
35 typedef base::Callback<void(NavigationThrottle::ThrottleCheckResult)> 42 typedef base::Callback<void(NavigationThrottle::ThrottleCheckResult)>
36 UIChecksPerformedCallback; 43 UIChecksPerformedCallback;
37 44
38 void SendCheckResultToIOThread(UIChecksPerformedCallback callback, 45 void SendCheckResultToIOThread(UIChecksPerformedCallback callback,
39 NavigationThrottle::ThrottleCheckResult result) { 46 NavigationThrottle::ThrottleCheckResult result) {
40 DCHECK_CURRENTLY_ON(BrowserThread::UI); 47 DCHECK_CURRENTLY_ON(BrowserThread::UI);
41 DCHECK_NE(result, NavigationThrottle::DEFER); 48 DCHECK_NE(result, NavigationThrottle::DEFER);
42 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 49 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
43 base::Bind(callback, result)); 50 base::Bind(callback, result));
44 } 51 }
45 52
46 void CheckWillStartRequestOnUIThread( 53 void CheckWillStartRequestOnUIThread(
47 UIChecksPerformedCallback callback, 54 UIChecksPerformedCallback callback,
48 int render_process_id, 55 int render_process_id,
49 int render_frame_host_id, 56 int render_frame_host_id,
50 const std::string& method, 57 const std::string& method,
51 const scoped_refptr<content::ResourceRequestBodyImpl>& 58 const scoped_refptr<content::ResourceRequestBodyImpl>&
52 resource_request_body, 59 resource_request_body,
53 const Referrer& sanitized_referrer, 60 const Referrer& sanitized_referrer,
54 bool has_user_gesture, 61 bool has_user_gesture,
55 ui::PageTransition transition, 62 ui::PageTransition transition,
56 bool is_external_protocol, 63 bool is_external_protocol,
57 RequestContextType request_context_type) { 64 RequestContextType request_context_type) {
58 DCHECK_CURRENTLY_ON(BrowserThread::UI); 65 DCHECK_CURRENTLY_ON(BrowserThread::UI);
59 RenderFrameHostImpl* render_frame_host = 66 RenderFrameHostImpl* render_frame_host =
60 RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id); 67 RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id);
68 if (g_ui_checks_always_succeed) {
69 SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED);
70 return;
71 }
72
61 if (!render_frame_host) { 73 if (!render_frame_host) {
62 SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED); 74 SendCheckResultToIOThread(callback, NavigationThrottle::CANCEL);
63 return; 75 return;
64 } 76 }
65 77
66 NavigationHandleImpl* navigation_handle = 78 NavigationHandleImpl* navigation_handle =
67 render_frame_host->navigation_handle(); 79 render_frame_host->navigation_handle();
68 if (!navigation_handle) { 80 if (!navigation_handle) {
69 SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED); 81 SendCheckResultToIOThread(callback, NavigationThrottle::CANCEL);
70 return; 82 return;
71 } 83 }
72 84
73 navigation_handle->WillStartRequest( 85 navigation_handle->WillStartRequest(
74 method, resource_request_body, sanitized_referrer, has_user_gesture, 86 method, resource_request_body, sanitized_referrer, has_user_gesture,
75 transition, is_external_protocol, request_context_type, 87 transition, is_external_protocol, request_context_type,
76 base::Bind(&SendCheckResultToIOThread, callback)); 88 base::Bind(&SendCheckResultToIOThread, callback));
77 } 89 }
78 90
79 void CheckWillRedirectRequestOnUIThread( 91 void CheckWillRedirectRequestOnUIThread(
80 UIChecksPerformedCallback callback, 92 UIChecksPerformedCallback callback,
81 int render_process_id, 93 int render_process_id,
82 int render_frame_host_id, 94 int render_frame_host_id,
83 const GURL& new_url, 95 const GURL& new_url,
84 const std::string& new_method, 96 const std::string& new_method,
85 const GURL& new_referrer_url, 97 const GURL& new_referrer_url,
86 bool new_is_external_protocol, 98 bool new_is_external_protocol,
87 scoped_refptr<net::HttpResponseHeaders> headers) { 99 scoped_refptr<net::HttpResponseHeaders> headers) {
88 DCHECK_CURRENTLY_ON(BrowserThread::UI); 100 DCHECK_CURRENTLY_ON(BrowserThread::UI);
89 RenderFrameHostImpl* render_frame_host = 101 RenderFrameHostImpl* render_frame_host =
90 RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id); 102 RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id);
103 if (g_ui_checks_always_succeed) {
104 SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED);
105 return;
106 }
107
91 if (!render_frame_host) { 108 if (!render_frame_host) {
92 SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED); 109 SendCheckResultToIOThread(callback, NavigationThrottle::CANCEL);
93 return; 110 return;
94 } 111 }
95 112
96 NavigationHandleImpl* navigation_handle = 113 NavigationHandleImpl* navigation_handle =
97 render_frame_host->navigation_handle(); 114 render_frame_host->navigation_handle();
98 if (!navigation_handle) { 115 if (!navigation_handle) {
99 SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED); 116 SendCheckResultToIOThread(callback, NavigationThrottle::CANCEL);
100 return; 117 return;
101 } 118 }
102 119
103 GURL new_validated_url(new_url); 120 GURL new_validated_url(new_url);
104 RenderProcessHost::FromID(render_process_id) 121 RenderProcessHost::FromID(render_process_id)
105 ->FilterURL(false, &new_validated_url); 122 ->FilterURL(false, &new_validated_url);
106 navigation_handle->WillRedirectRequest( 123 navigation_handle->WillRedirectRequest(
107 new_validated_url, new_method, new_referrer_url, new_is_external_protocol, 124 new_validated_url, new_method, new_referrer_url, new_is_external_protocol,
108 headers, base::Bind(&SendCheckResultToIOThread, callback)); 125 headers, base::Bind(&SendCheckResultToIOThread, callback));
109 } 126 }
110 127
111 void WillProcessResponseOnUIThread( 128 void WillProcessResponseOnUIThread(
112 UIChecksPerformedCallback callback, 129 UIChecksPerformedCallback callback,
113 int render_process_id, 130 int render_process_id,
114 int render_frame_host_id, 131 int render_frame_host_id,
115 scoped_refptr<net::HttpResponseHeaders> headers, 132 scoped_refptr<net::HttpResponseHeaders> headers,
116 const SSLStatus& ssl_status, 133 const SSLStatus& ssl_status,
134 const GlobalRequestID& request_id,
135 bool should_replace_current_entry,
136 bool is_download,
137 bool is_stream,
138 const base::Closure& transfer_callback,
117 std::unique_ptr<NavigationData> navigation_data) { 139 std::unique_ptr<NavigationData> navigation_data) {
118 DCHECK_CURRENTLY_ON(BrowserThread::UI); 140 DCHECK_CURRENTLY_ON(BrowserThread::UI);
119 RenderFrameHostImpl* render_frame_host = 141 RenderFrameHostImpl* render_frame_host =
120 RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id); 142 RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id);
143 if (g_force_transfer) {
144 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, transfer_callback);
145 }
146
147 if (g_ui_checks_always_succeed) {
148 SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED);
149 return;
150 }
151
121 if (!render_frame_host) { 152 if (!render_frame_host) {
122 SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED); 153 SendCheckResultToIOThread(callback, NavigationThrottle::CANCEL);
123 return; 154 return;
124 } 155 }
125 156
126 NavigationHandleImpl* navigation_handle = 157 NavigationHandleImpl* navigation_handle =
127 render_frame_host->navigation_handle(); 158 render_frame_host->navigation_handle();
128 if (!navigation_handle) { 159 if (!navigation_handle) {
129 SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED); 160 SendCheckResultToIOThread(callback, NavigationThrottle::CANCEL);
130 return; 161 return;
131 } 162 }
132 163
133 if (navigation_data) 164 if (navigation_data)
134 navigation_handle->set_navigation_data(std::move(navigation_data)); 165 navigation_handle->set_navigation_data(std::move(navigation_data));
135 166
136 navigation_handle->WillProcessResponse( 167 navigation_handle->WillProcessResponse(
137 render_frame_host, headers, ssl_status, 168 render_frame_host, headers, ssl_status, request_id,
169 should_replace_current_entry, is_download, is_stream, transfer_callback,
138 base::Bind(&SendCheckResultToIOThread, callback)); 170 base::Bind(&SendCheckResultToIOThread, callback));
139 } 171 }
140 172
141 } // namespace 173 } // namespace
142 174
143 NavigationResourceThrottle::NavigationResourceThrottle( 175 NavigationResourceThrottle::NavigationResourceThrottle(
144 net::URLRequest* request, 176 net::URLRequest* request,
145 ResourceDispatcherHostDelegate* resource_dispatcher_host_delegate, 177 ResourceDispatcherHostDelegate* resource_dispatcher_host_delegate,
146 RequestContextType request_context_type) 178 RequestContextType request_context_type)
147 : request_(request), 179 : request_(request),
148 resource_dispatcher_host_delegate_(resource_dispatcher_host_delegate), 180 resource_dispatcher_host_delegate_(resource_dispatcher_host_delegate),
149 request_context_type_(request_context_type), 181 request_context_type_(request_context_type),
182 in_cross_site_transition_(false),
183 on_transfer_done_result_(NavigationThrottle::DEFER),
150 weak_ptr_factory_(this) {} 184 weak_ptr_factory_(this) {}
151 185
152 NavigationResourceThrottle::~NavigationResourceThrottle() {} 186 NavigationResourceThrottle::~NavigationResourceThrottle() {}
153 187
154 void NavigationResourceThrottle::WillStartRequest(bool* defer) { 188 void NavigationResourceThrottle::WillStartRequest(bool* defer) {
155 DCHECK_CURRENTLY_ON(BrowserThread::IO); 189 DCHECK_CURRENTLY_ON(BrowserThread::IO);
156 const ResourceRequestInfoImpl* info = 190 const ResourceRequestInfoImpl* info =
157 ResourceRequestInfoImpl::ForRequest(request_); 191 ResourceRequestInfoImpl::ForRequest(request_);
158 if (!info) 192 if (!info)
159 return; 193 return;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 BrowserThread::UI, FROM_HERE, 252 BrowserThread::UI, FROM_HERE,
219 base::Bind(&CheckWillRedirectRequestOnUIThread, callback, 253 base::Bind(&CheckWillRedirectRequestOnUIThread, callback,
220 render_process_id, render_frame_id, redirect_info.new_url, 254 render_process_id, render_frame_id, redirect_info.new_url,
221 redirect_info.new_method, GURL(redirect_info.new_referrer), 255 redirect_info.new_method, GURL(redirect_info.new_referrer),
222 new_is_external_protocol, response_headers)); 256 new_is_external_protocol, response_headers));
223 *defer = true; 257 *defer = true;
224 } 258 }
225 259
226 void NavigationResourceThrottle::WillProcessResponse(bool* defer) { 260 void NavigationResourceThrottle::WillProcessResponse(bool* defer) {
227 DCHECK_CURRENTLY_ON(BrowserThread::IO); 261 DCHECK_CURRENTLY_ON(BrowserThread::IO);
228 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_); 262 const ResourceRequestInfoImpl* info =
263 ResourceRequestInfoImpl::ForRequest(request_);
229 if (!info) 264 if (!info)
230 return; 265 return;
231 266
232 int render_process_id, render_frame_id; 267 int render_process_id, render_frame_id;
233 if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id)) 268 if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id))
234 return; 269 return;
235 270
236 // Send a copy of the response headers to the NavigationHandle on the UI 271 // Send a copy of the response headers to the NavigationHandle on the UI
237 // thread. 272 // thread.
238 scoped_refptr<net::HttpResponseHeaders> response_headers; 273 scoped_refptr<net::HttpResponseHeaders> response_headers;
239 if (request_->response_headers()) { 274 if (request_->response_headers()) {
240 response_headers = new net::HttpResponseHeaders( 275 response_headers = new net::HttpResponseHeaders(
241 request_->response_headers()->raw_headers()); 276 request_->response_headers()->raw_headers());
242 } 277 }
243 278
244 std::unique_ptr<NavigationData> cloned_data; 279 std::unique_ptr<NavigationData> cloned_data;
245 if (resource_dispatcher_host_delegate_) { 280 if (resource_dispatcher_host_delegate_) {
246 // Ask the embedder for a NavigationData instance. 281 // Ask the embedder for a NavigationData instance.
247 NavigationData* navigation_data = 282 NavigationData* navigation_data =
248 resource_dispatcher_host_delegate_->GetNavigationData(request_); 283 resource_dispatcher_host_delegate_->GetNavigationData(request_);
249 284
250 // Clone the embedder's NavigationData before moving it to the UI thread. 285 // Clone the embedder's NavigationData before moving it to the UI thread.
251 if (navigation_data) 286 if (navigation_data)
252 cloned_data = navigation_data->Clone(); 287 cloned_data = navigation_data->Clone();
253 } 288 }
254 289
255 UIChecksPerformedCallback callback = 290 UIChecksPerformedCallback callback =
256 base::Bind(&NavigationResourceThrottle::OnUIChecksPerformed, 291 base::Bind(&NavigationResourceThrottle::OnUIChecksPerformed,
257 weak_ptr_factory_.GetWeakPtr()); 292 weak_ptr_factory_.GetWeakPtr());
293 base::Closure transfer_callback =
294 base::Bind(&NavigationResourceThrottle::InitiateTransfer,
295 weak_ptr_factory_.GetWeakPtr());
258 296
259 SSLStatus ssl_status; 297 SSLStatus ssl_status;
260 if (request_->ssl_info().cert.get()) { 298 if (request_->ssl_info().cert.get()) {
261 ResourceLoader::GetSSLStatusForRequest( 299 ResourceLoader::GetSSLStatusForRequest(
262 request_->url(), request_->ssl_info(), info->GetChildID(), &ssl_status); 300 request_->url(), request_->ssl_info(), info->GetChildID(), &ssl_status);
263 } 301 }
264 302
265 BrowserThread::PostTask( 303 BrowserThread::PostTask(
266 BrowserThread::UI, FROM_HERE, 304 BrowserThread::UI, FROM_HERE,
267 base::Bind(&WillProcessResponseOnUIThread, callback, render_process_id, 305 base::Bind(&WillProcessResponseOnUIThread, callback, render_process_id,
268 render_frame_id, response_headers, ssl_status, 306 render_frame_id, response_headers, ssl_status,
307 info->GetGlobalRequestID(),
308 info->should_replace_current_entry(), info->IsDownload(),
309 info->is_stream(), transfer_callback,
269 base::Passed(&cloned_data))); 310 base::Passed(&cloned_data)));
270 *defer = true; 311 *defer = true;
271 } 312 }
272 313
273 const char* NavigationResourceThrottle::GetNameForLogging() const { 314 const char* NavigationResourceThrottle::GetNameForLogging() const {
274 return "NavigationResourceThrottle"; 315 return "NavigationResourceThrottle";
275 } 316 }
276 317
318 void NavigationResourceThrottle::SetUIChecksAlwaysSuccedForTesting(
319 bool ui_checks_always_succeed) {
320 g_ui_checks_always_succeed = ui_checks_always_succeed;
321 }
322
323 void NavigationResourceThrottle::SetForceTransferForTesting(
324 bool force_transfer) {
325 g_force_transfer = force_transfer;
326 }
327
277 void NavigationResourceThrottle::OnUIChecksPerformed( 328 void NavigationResourceThrottle::OnUIChecksPerformed(
278 NavigationThrottle::ThrottleCheckResult result) { 329 NavigationThrottle::ThrottleCheckResult result) {
279 DCHECK_CURRENTLY_ON(BrowserThread::IO); 330 DCHECK_CURRENTLY_ON(BrowserThread::IO);
331 DCHECK_NE(NavigationThrottle::DEFER, result);
332 if (in_cross_site_transition_) {
333 on_transfer_done_result_ = result;
334 return;
335 }
336
280 if (result == NavigationThrottle::CANCEL_AND_IGNORE) { 337 if (result == NavigationThrottle::CANCEL_AND_IGNORE) {
281 controller()->CancelAndIgnore(); 338 controller()->CancelAndIgnore();
282 } else if (result == NavigationThrottle::CANCEL) { 339 } else if (result == NavigationThrottle::CANCEL) {
283 controller()->Cancel(); 340 controller()->Cancel();
284 } else if (result == NavigationThrottle::BLOCK_REQUEST) { 341 } else if (result == NavigationThrottle::BLOCK_REQUEST) {
285 controller()->CancelWithError(net::ERR_BLOCKED_BY_CLIENT); 342 controller()->CancelWithError(net::ERR_BLOCKED_BY_CLIENT);
286 } else { 343 } else {
287 controller()->Resume(); 344 controller()->Resume();
288 } 345 }
289 } 346 }
290 347
348 void NavigationResourceThrottle::InitiateTransfer() {
349 DCHECK_CURRENTLY_ON(BrowserThread::IO);
350 in_cross_site_transition_ = true;
351 ResourceRequestInfoImpl* info =
352 ResourceRequestInfoImpl::ForRequest(request_);
353 ResourceDispatcherHostImpl::Get()->MarkAsTransferredNavigation(
354 info->GetGlobalRequestID(),
355 base::Bind(&NavigationResourceThrottle::OnTransferComplete,
356 weak_ptr_factory_.GetWeakPtr()));
357 }
358
359 void NavigationResourceThrottle::OnTransferComplete() {
360 DCHECK_CURRENTLY_ON(BrowserThread::IO);
361 DCHECK(in_cross_site_transition_);
362 in_cross_site_transition_ = false;
363
364 // If the results of the checks on the UI thread are known, unblock the
nasko 2016/09/09 23:30:27 Is it guaranteed that the result from the UI threa
clamy 2016/09/12 15:31:37 Yes. See the DCHECK line 331 (UI thread binds OnUI
365 // navigation. Otherwise, wait until the callback has executed.
366 if (on_transfer_done_result_ != NavigationThrottle::DEFER) {
367 OnUIChecksPerformed(on_transfer_done_result_);
368 on_transfer_done_result_ = NavigationThrottle::DEFER;
369 }
370 }
371
291 } // namespace content 372 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698