Chromium Code Reviews| Index: content/browser/frame_host/navigation_request.cc |
| diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc |
| index 5bf934e4b5ba66a187672cdcc8ac44cb870f24e4..94f4bb04d385cd0f59c1437a6a2f361dcb443be0 100644 |
| --- a/content/browser/frame_host/navigation_request.cc |
| +++ b/content/browser/frame_host/navigation_request.cc |
| @@ -383,7 +383,25 @@ void NavigationRequest::BeginNavigation() { |
| DCHECK(state_ == NOT_STARTED || state_ == WAITING_FOR_RENDERER_RESPONSE); |
| TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationRequest", this, |
| "BeginNavigation"); |
| + |
| state_ = STARTED; |
| + |
| + // Check Content Security Policy before the NavigationThrottles run. This is |
| + // so that the CSP should be allowed to modify the request such that the |
| + // navigation throttles allow, but would block it otherwise. For the same |
|
nasko
2017/06/05 20:46:29
I'm finding this sentence a bit hard to parse, but
estark
2017/06/06 00:38:02
Reworded, hopefully better now
nasko
2017/06/06 01:03:44
Much better! Thanks!
Can you also use the same wor
estark
2017/06/06 19:22:15
Done.
|
| + // reason, the navigation handle is created afterwards -- so that it gets the |
|
nasko
2017/06/05 20:46:29
nit: s/navigation handle/NavigationHande/
estark
2017/06/06 00:38:02
Done.
|
| + // request URL after potentially being modified by CSP. |
| + if (CheckContentSecurityPolicyFrameSrc(false /* is redirect */) == |
| + CONTENT_SECURITY_POLICY_CHECK_FAILED) { |
| + // Create a navigation handle so that the correct error code can be set on |
| + // it by OnRequestFailed(). |
| + CreateNavigationHandle(); |
| + OnRequestFailed(false, net::ERR_BLOCKED_BY_CLIENT); |
| + // DO NOT ADD CODE after this. The previous call to OnRequestFailed has |
|
nasko
2017/06/05 20:46:29
nit: empty line before the comment.
estark
2017/06/06 00:38:02
Done.
|
| + // destroyed the NavigationRequest. |
| + return; |
| + } |
| + |
| CreateNavigationHandle(); |
| RenderFrameDevToolsAgentHost::OnBeforeNavigation(navigation_handle_.get()); |
| @@ -508,6 +526,17 @@ void NavigationRequest::OnRequestRedirected( |
| common_params_.referrer = |
| Referrer::SanitizeForRequest(common_params_.url, common_params_.referrer); |
| + // Check Content Security Policy before the NavigationThrottles run. This is |
| + // so that the CSP should be allowed to modify the request such that the |
| + // navigation throttles allow, but would block it otherwise. |
| + if (CheckContentSecurityPolicyFrameSrc(true /* is redirect */) == |
| + CONTENT_SECURITY_POLICY_CHECK_FAILED) { |
| + OnRequestFailed(false, net::ERR_BLOCKED_BY_CLIENT); |
| + // DO NOT ADD CODE after this. The previous call to OnRequestFailed has |
|
nasko
2017/06/05 20:46:30
nit: an empty line before the comment.
estark
2017/06/06 00:38:02
Done.
|
| + // destroyed the NavigationRequest. |
| + return; |
| + } |
| + |
| // For non browser initiated navigations we need to check if the source has |
| // access to the URL. We always allow browser initiated requests. |
| // TODO(clamy): Kill the renderer if FilterURL fails? |
| @@ -894,4 +923,33 @@ void NavigationRequest::CommitNavigation() { |
| frame_tree_node_->ResetNavigationRequest(true, true); |
| } |
| +NavigationRequest::ContentSecurityPolicyCheckResult |
| +NavigationRequest::CheckContentSecurityPolicyFrameSrc(bool is_redirect) { |
| + if (common_params_.url.SchemeIs(url::kAboutScheme)) |
| + return CONTENT_SECURITY_POLICY_CHECK_PASSED; |
| + |
| + if (common_params_.should_check_main_world_csp == |
| + CSPDisposition::DO_NOT_CHECK) |
|
nasko
2017/06/05 20:46:29
nit: two line if statement needs {}.
estark
2017/06/06 00:38:02
Done.
|
| + return CONTENT_SECURITY_POLICY_CHECK_PASSED; |
| + |
| + // The CSP frame-src directive only applies to subframes. |
| + if (frame_tree_node()->IsMainFrame()) |
| + return CONTENT_SECURITY_POLICY_CHECK_PASSED; |
| + |
| + FrameTreeNode* parent_ftn = frame_tree_node()->parent(); |
| + DCHECK(parent_ftn); |
| + RenderFrameHostImpl* parent = parent_ftn->current_frame_host(); |
| + DCHECK(parent); |
| + |
| + SourceLocation source_location; |
| + if (common_params_.source_location) |
| + source_location = common_params_.source_location.value(); |
| + if (parent->IsAllowedByCsp(CSPDirective::FrameSrc, common_params_.url, |
| + is_redirect, source_location)) { |
|
nasko
2017/06/05 20:46:29
Can't we just pass in common_params_.source_locati
estark
2017/06/06 00:38:03
Changed to value_or
nasko
2017/06/06 01:03:44
Nice! TIL about value_or and the code does look ni
|
| + return CONTENT_SECURITY_POLICY_CHECK_PASSED; |
| + } |
| + |
| + return CONTENT_SECURITY_POLICY_CHECK_FAILED; |
| +} |
| + |
| } // namespace content |