Index: third_party/WebKit/Source/core/loader/FrameLoader.cpp |
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp |
index 8cd77648a4dd0116286c5cf0df7be66d44d27041..79b097f9281ca8c90899efa8dee67898f64e100a 100644 |
--- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp |
+++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp |
@@ -139,6 +139,63 @@ static void CheckForLegacyProtocolInSubresource( |
document, UseCounter::kLegacyProtocolEmbeddedAsSubresource); |
} |
+static NavigationPolicy MaybeCheckCSP( |
+ const ResourceRequest& request, |
+ NavigationType type, |
+ LocalFrame* frame, |
+ NavigationPolicy policy, |
+ bool should_check_main_world_content_security_policy, |
+ bool browser_side_navigation_enabled, |
+ ContentSecurityPolicy::CheckHeaderType check_header_type) { |
+ // If we're loading content into |frame| (NavigationPolicyCurrentTab), check |
+ // against the parent's Content Security Policy and kill the load if that |
+ // check fails, unless we should bypass the main world's CSP. |
+ if (policy == kNavigationPolicyCurrentTab && |
+ should_check_main_world_content_security_policy && |
+ // TODO(arthursonzogni): 'frame-src' check is disabled on the |
+ // renderer side with browser-side-navigation, but is enforced on the |
+ // browser side. See http://crbug.com/692595 for understanding why it |
+ // can't be enforced on both sides instead. |
+ !browser_side_navigation_enabled) { |
+ Frame* parent_frame = frame->Tree().Parent(); |
+ if (parent_frame) { |
+ ContentSecurityPolicy* parent_policy = |
+ parent_frame->GetSecurityContext()->GetContentSecurityPolicy(); |
+ if (!parent_policy->AllowFrameFromSource( |
+ request.Url(), request.GetRedirectStatus(), |
+ SecurityViolationReportingPolicy::kReport, check_header_type)) { |
+ // Fire a load event, as timing attacks would otherwise reveal that the |
+ // frame was blocked. This way, it looks like every other cross-origin |
+ // page load. |
+ frame->GetDocument()->EnforceSandboxFlags(kSandboxOrigin); |
+ frame->Owner()->DispatchLoad(); |
+ return kNavigationPolicyIgnore; |
+ } |
+ } |
+ } |
+ |
+ bool is_form_submission = type == kNavigationTypeFormSubmitted || |
+ type == kNavigationTypeFormResubmitted; |
+ if (is_form_submission && |
+ // 'form-action' check in the frame that is navigating is disabled on the |
+ // renderer side when PlzNavigate is enabled, but is enforced on the |
+ // browser side instead. |
+ // N.B. check in the frame that initiates the navigation stills occurs in |
+ // blink and is not enforced on the browser-side. |
+ // TODO(arthursonzogni) The 'form-action' check should be fully disabled |
+ // in blink when browser side navigation is enabled, except when the form |
+ // submission doesn't trigger a navigation(i.e. javascript urls). Please |
+ // see https://crbug.com/701749 |
+ !browser_side_navigation_enabled && |
+ !frame->GetDocument()->GetContentSecurityPolicy()->AllowFormAction( |
+ request.Url(), request.GetRedirectStatus(), |
+ SecurityViolationReportingPolicy::kReport, check_header_type)) { |
+ return kNavigationPolicyIgnore; |
+ } |
+ |
+ return policy; |
+} |
+ |
ResourceRequest FrameLoader::ResourceRequestForReload( |
FrameLoadType frame_load_type, |
const KURL& override_url, |
@@ -1370,51 +1427,12 @@ NavigationPolicy FrameLoader::ShouldContinueForNavigationPolicy( |
return kNavigationPolicyCurrentTab; |
Settings* settings = frame_->GetSettings(); |
- bool browser_side_navigation_enabled = |
- settings && settings->GetBrowserSideNavigationEnabled(); |
- |
- // If we're loading content into |m_frame| (NavigationPolicyCurrentTab), check |
- // against the parent's Content Security Policy and kill the load if that |
- // check fails, unless we should bypass the main world's CSP. |
- if (policy == kNavigationPolicyCurrentTab && |
- should_check_main_world_content_security_policy == |
- kCheckContentSecurityPolicy && |
- // TODO(arthursonzogni): 'frame-src' check is disabled on the |
- // renderer side with browser-side-navigation, but is enforced on the |
- // browser side. See http://crbug.com/692595 for understanding why it |
- // can't be enforced on both sides instead. |
- !browser_side_navigation_enabled) { |
- Frame* parent_frame = frame_->Tree().Parent(); |
- if (parent_frame) { |
- ContentSecurityPolicy* parent_policy = |
- parent_frame->GetSecurityContext()->GetContentSecurityPolicy(); |
- if (!parent_policy->AllowFrameFromSource(request.Url(), |
- request.GetRedirectStatus())) { |
- // Fire a load event, as timing attacks would otherwise reveal that the |
- // frame was blocked. This way, it looks like every other cross-origin |
- // page load. |
- frame_->GetDocument()->EnforceSandboxFlags(kSandboxOrigin); |
- frame_->Owner()->DispatchLoad(); |
- return kNavigationPolicyIgnore; |
- } |
- } |
- } |
- |
- bool is_form_submission = type == kNavigationTypeFormSubmitted || |
- type == kNavigationTypeFormResubmitted; |
- if (is_form_submission && |
- // 'form-action' check in the frame that is navigating is disabled on the |
- // renderer side when PlzNavigate is enabled, but is enforced on the |
- // browser side instead. |
- // N.B. check in the frame that initiates the navigation stills occurs in |
- // blink and is not enforced on the browser-side. |
- // TODO(arthursonzogni) The 'form-action' check should be fully disabled |
- // in blink when browser side navigation is enabled, except when the form |
- // submission doesn't trigger a navigation(i.e. javascript urls). Please |
- // see https://crbug.com/701749 |
- !browser_side_navigation_enabled && |
- !frame_->GetDocument()->GetContentSecurityPolicy()->AllowFormAction( |
- request.Url(), request.GetRedirectStatus())) { |
+ if (MaybeCheckCSP(request, type, frame_, policy, |
+ should_check_main_world_content_security_policy == |
+ kCheckContentSecurityPolicy, |
+ settings && settings->GetBrowserSideNavigationEnabled(), |
+ ContentSecurityPolicy::CheckHeaderType::kCheckEnforce) == |
+ kNavigationPolicyIgnore) { |
return kNavigationPolicyIgnore; |
} |
@@ -1439,6 +1457,31 @@ NavigationPolicy FrameLoader::ShouldContinueForNavigationPolicy( |
return kNavigationPolicyIgnore; |
} |
+NavigationPolicy FrameLoader::ShouldContinueForRedirectNavigationPolicy( |
+ const ResourceRequest& request, |
+ const SubstituteData& substitute_data, |
+ DocumentLoader* loader, |
+ ContentSecurityPolicyDisposition |
+ should_check_main_world_content_security_policy, |
+ NavigationType type, |
+ NavigationPolicy policy, |
+ FrameLoadType frame_load_type, |
+ bool is_client_redirect, |
+ HTMLFormElement* form) { |
+ Settings* settings = frame_->GetSettings(); |
+ // Check report-only CSP policies, which are not checked by |
+ // ShouldContinueForNavigationPolicy. |
+ MaybeCheckCSP(request, type, frame_, policy, |
+ should_check_main_world_content_security_policy == |
+ kCheckContentSecurityPolicy, |
+ settings && settings->GetBrowserSideNavigationEnabled(), |
+ ContentSecurityPolicy::CheckHeaderType::kCheckReportOnly); |
+ return ShouldContinueForNavigationPolicy( |
+ request, substitute_data, loader, |
+ should_check_main_world_content_security_policy, type, policy, |
+ frame_load_type, is_client_redirect, form); |
+} |
+ |
NavigationPolicy FrameLoader::CheckLoadCanStart( |
FrameLoadRequest& frame_load_request, |
FrameLoadType type, |
@@ -1453,6 +1496,20 @@ NavigationPolicy FrameLoader::CheckLoadCanStart( |
// request. |
ResourceRequest& resource_request = frame_load_request.GetResourceRequest(); |
RecordLatestRequiredCSP(); |
+ // Before modifying the request, check report-only CSP headers to give the |
+ // site owner a chance to learn about requests that need to be modified. |
+ // |
+ // TODO(estark): this doesn't work with --enable-browser-side-navigation, |
+ // wherein 'frame-src' is checked in the browser process. Figure out what to |
+ // do; maybe with browser-side navigation the upgrade should be happening in |
+ // the browser process too. See also https://crbug.com/692595 |
+ Settings* settings = frame_->GetSettings(); |
+ MaybeCheckCSP( |
+ resource_request, navigation_type, frame_, navigation_policy, |
+ frame_load_request.ShouldCheckMainWorldContentSecurityPolicy() == |
+ kCheckContentSecurityPolicy, |
+ settings && settings->GetBrowserSideNavigationEnabled(), |
+ ContentSecurityPolicy::CheckHeaderType::kCheckReportOnly); |
ModifyRequestForCSP(resource_request, nullptr); |
return ShouldContinueForNavigationPolicy( |