OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/frame_host/navigation_request.h" | 5 #include "content/browser/frame_host/navigation_request.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
10 #include "content/browser/appcache/appcache_navigation_handle.h" | 10 #include "content/browser/appcache/appcache_navigation_handle.h" |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 | 376 |
377 NavigationRequest::~NavigationRequest() { | 377 NavigationRequest::~NavigationRequest() { |
378 TRACE_EVENT_ASYNC_END0("navigation", "NavigationRequest", this); | 378 TRACE_EVENT_ASYNC_END0("navigation", "NavigationRequest", this); |
379 } | 379 } |
380 | 380 |
381 void NavigationRequest::BeginNavigation() { | 381 void NavigationRequest::BeginNavigation() { |
382 DCHECK(!loader_); | 382 DCHECK(!loader_); |
383 DCHECK(state_ == NOT_STARTED || state_ == WAITING_FOR_RENDERER_RESPONSE); | 383 DCHECK(state_ == NOT_STARTED || state_ == WAITING_FOR_RENDERER_RESPONSE); |
384 TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationRequest", this, | 384 TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationRequest", this, |
385 "BeginNavigation"); | 385 "BeginNavigation"); |
| 386 |
386 state_ = STARTED; | 387 state_ = STARTED; |
| 388 |
| 389 // Check Content Security Policy before the NavigationThrottles run. This |
| 390 // gives CSP a chance to modify requests that NavigationThrottles would |
| 391 // otherwise block. Similarly, the NavigationHandle is created afterwards, so |
| 392 // that it gets the request URL after potentially being modified by CSP. |
| 393 if (CheckContentSecurityPolicyFrameSrc(false /* is redirect */) == |
| 394 CONTENT_SECURITY_POLICY_CHECK_FAILED) { |
| 395 // Create a navigation handle so that the correct error code can be set on |
| 396 // it by OnRequestFailed(). |
| 397 CreateNavigationHandle(); |
| 398 OnRequestFailed(false, net::ERR_BLOCKED_BY_CLIENT); |
| 399 |
| 400 // DO NOT ADD CODE after this. The previous call to OnRequestFailed has |
| 401 // destroyed the NavigationRequest. |
| 402 return; |
| 403 } |
| 404 |
387 CreateNavigationHandle(); | 405 CreateNavigationHandle(); |
388 | 406 |
389 RenderFrameDevToolsAgentHost::OnBeforeNavigation(navigation_handle_.get()); | 407 RenderFrameDevToolsAgentHost::OnBeforeNavigation(navigation_handle_.get()); |
390 | 408 |
391 if (ShouldMakeNetworkRequestForURL(common_params_.url) && | 409 if (ShouldMakeNetworkRequestForURL(common_params_.url) && |
392 !navigation_handle_->IsSameDocument()) { | 410 !navigation_handle_->IsSameDocument()) { |
393 // It's safe to use base::Unretained because this NavigationRequest owns | 411 // It's safe to use base::Unretained because this NavigationRequest owns |
394 // the NavigationHandle where the callback will be stored. | 412 // the NavigationHandle where the callback will be stored. |
395 // TODO(clamy): pass the method to the NavigationHandle instead of a | 413 // TODO(clamy): pass the method to the NavigationHandle instead of a |
396 // boolean. | 414 // boolean. |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 request_params_.redirect_response.push_back(response->head); | 519 request_params_.redirect_response.push_back(response->head); |
502 request_params_.redirect_infos.push_back(redirect_info); | 520 request_params_.redirect_infos.push_back(redirect_info); |
503 | 521 |
504 request_params_.redirects.push_back(common_params_.url); | 522 request_params_.redirects.push_back(common_params_.url); |
505 common_params_.url = redirect_info.new_url; | 523 common_params_.url = redirect_info.new_url; |
506 common_params_.method = redirect_info.new_method; | 524 common_params_.method = redirect_info.new_method; |
507 common_params_.referrer.url = GURL(redirect_info.new_referrer); | 525 common_params_.referrer.url = GURL(redirect_info.new_referrer); |
508 common_params_.referrer = | 526 common_params_.referrer = |
509 Referrer::SanitizeForRequest(common_params_.url, common_params_.referrer); | 527 Referrer::SanitizeForRequest(common_params_.url, common_params_.referrer); |
510 | 528 |
| 529 // Check Content Security Policy before the NavigationThrottles run. This |
| 530 // gives CSP a chance to modify requests that NavigationThrottles would |
| 531 // otherwise block. |
| 532 if (CheckContentSecurityPolicyFrameSrc(true /* is redirect */) == |
| 533 CONTENT_SECURITY_POLICY_CHECK_FAILED) { |
| 534 OnRequestFailed(false, net::ERR_BLOCKED_BY_CLIENT); |
| 535 |
| 536 // DO NOT ADD CODE after this. The previous call to OnRequestFailed has |
| 537 // destroyed the NavigationRequest. |
| 538 return; |
| 539 } |
| 540 |
511 // For non browser initiated navigations we need to check if the source has | 541 // For non browser initiated navigations we need to check if the source has |
512 // access to the URL. We always allow browser initiated requests. | 542 // access to the URL. We always allow browser initiated requests. |
513 // TODO(clamy): Kill the renderer if FilterURL fails? | 543 // TODO(clamy): Kill the renderer if FilterURL fails? |
514 GURL url = common_params_.url; | 544 GURL url = common_params_.url; |
515 if (!browser_initiated_ && source_site_instance()) { | 545 if (!browser_initiated_ && source_site_instance()) { |
516 source_site_instance()->GetProcess()->FilterURL(false, &url); | 546 source_site_instance()->GetProcess()->FilterURL(false, &url); |
517 // FilterURL sets the URL to about:blank if the CSP checks prevent the | 547 // FilterURL sets the URL to about:blank if the CSP checks prevent the |
518 // renderer from accessing it. | 548 // renderer from accessing it. |
519 if ((url == url::kAboutBlankURL) && (url != common_params_.url)) { | 549 if ((url == url::kAboutBlankURL) && (url != common_params_.url)) { |
520 navigation_handle_->set_net_error_code(net::ERR_ABORTED); | 550 navigation_handle_->set_net_error_code(net::ERR_ABORTED); |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
887 | 917 |
888 DCHECK_EQ(request_params_.has_user_gesture, begin_params_.has_user_gesture); | 918 DCHECK_EQ(request_params_.has_user_gesture, begin_params_.has_user_gesture); |
889 | 919 |
890 render_frame_host->CommitNavigation(response_.get(), std::move(body_), | 920 render_frame_host->CommitNavigation(response_.get(), std::move(body_), |
891 std::move(handle_), common_params_, | 921 std::move(handle_), common_params_, |
892 request_params_, is_view_source_); | 922 request_params_, is_view_source_); |
893 | 923 |
894 frame_tree_node_->ResetNavigationRequest(true, true); | 924 frame_tree_node_->ResetNavigationRequest(true, true); |
895 } | 925 } |
896 | 926 |
| 927 NavigationRequest::ContentSecurityPolicyCheckResult |
| 928 NavigationRequest::CheckContentSecurityPolicyFrameSrc(bool is_redirect) { |
| 929 if (common_params_.url.SchemeIs(url::kAboutScheme)) |
| 930 return CONTENT_SECURITY_POLICY_CHECK_PASSED; |
| 931 |
| 932 if (common_params_.should_check_main_world_csp == |
| 933 CSPDisposition::DO_NOT_CHECK) { |
| 934 return CONTENT_SECURITY_POLICY_CHECK_PASSED; |
| 935 } |
| 936 |
| 937 // The CSP frame-src directive only applies to subframes. |
| 938 if (frame_tree_node()->IsMainFrame()) |
| 939 return CONTENT_SECURITY_POLICY_CHECK_PASSED; |
| 940 |
| 941 FrameTreeNode* parent_ftn = frame_tree_node()->parent(); |
| 942 DCHECK(parent_ftn); |
| 943 RenderFrameHostImpl* parent = parent_ftn->current_frame_host(); |
| 944 DCHECK(parent); |
| 945 |
| 946 if (parent->IsAllowedByCsp( |
| 947 CSPDirective::FrameSrc, common_params_.url, is_redirect, |
| 948 common_params_.source_location.value_or(SourceLocation()))) { |
| 949 return CONTENT_SECURITY_POLICY_CHECK_PASSED; |
| 950 } |
| 951 |
| 952 return CONTENT_SECURITY_POLICY_CHECK_FAILED; |
| 953 } |
| 954 |
897 } // namespace content | 955 } // namespace content |
OLD | NEW |