Index: content/browser/frame_host/render_frame_proxy_host.cc |
diff --git a/content/browser/frame_host/render_frame_proxy_host.cc b/content/browser/frame_host/render_frame_proxy_host.cc |
index 7d79501b10298b3e1037d26cfd1962540fb94178..2e09d76202cfe7a2de8436df19bd465d45f83566 100644 |
--- a/content/browser/frame_host/render_frame_proxy_host.cc |
+++ b/content/browser/frame_host/render_frame_proxy_host.cc |
@@ -135,6 +135,8 @@ bool RenderFrameProxyHost::OnMessageReceived(const IPC::Message& msg) { |
IPC_BEGIN_MESSAGE_MAP(RenderFrameProxyHost, msg) |
IPC_MESSAGE_HANDLER(FrameHostMsg_Detach, OnDetach) |
IPC_MESSAGE_HANDLER(FrameHostMsg_OpenURL, OnOpenURL) |
+ IPC_MESSAGE_HANDLER(FrameHostMsg_ForwardContentSecurityPolicyViolation, |
+ OnForwardContentSecurityPolicyViolation) |
IPC_MESSAGE_HANDLER(FrameHostMsg_RouteMessageEvent, OnRouteMessageEvent) |
IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeOpener, OnDidChangeOpener) |
IPC_MESSAGE_HANDLER(FrameHostMsg_AdvanceFocus, OnAdvanceFocus) |
@@ -268,6 +270,64 @@ void RenderFrameProxyHost::OnOpenURL( |
params.resource_request_body); |
} |
+bool RenderFrameProxyHost::CanForwardViolationToCurrentDocument( |
+ const url::Origin& origin_declaring_violated_csp, |
+ const std::string& violated_csp_header) { |
+ RenderFrameHostImpl* current_rfh = frame_tree_node_->current_frame_host(); |
+ if (!origin_declaring_violated_csp.IsSameOriginWith( |
+ current_rfh->GetLastCommittedOrigin())) { |
+ return false; |
+ } |
+ |
+ if (!current_rfh->frame_tree_node()->ContainsContentSecurityPolicyHeader( |
+ violated_csp_header)) { |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
+// TODO(lukasza): http://crbug.com/376522: Forwarding should not be needed once |
+// processing of frame-src, plugin-types and similar CSP directives is done in |
+// the browser process. |
+void RenderFrameProxyHost::OnForwardContentSecurityPolicyViolation( |
+ const url::Origin& origin_declaring_violated_csp, |
+ const ContentSecurityPolicyViolation& violation) { |
+ // Try to verify that the CSP violation will be reported in the same document |
+ // as the one that declared the violated CSP (i.e. that navigation of |
+ // |current_rfh| didn't win a race with ForwardContentSecurityPolicyViolation |
+ // IPC message). |
+ // |
+ // The checks made by CanForwardViolationToCurrentDocument are not 100% |
+ // accurate, but a mistake should be safe to make until we can get rid of |
+ // forwarding as part of moving CSP processing to the browser process |
+ // (http://crbug.com/376522). The mistake should be safe, because: |
+ // 1. We check that we don't disclose information cross-origin. |
+ // 2. |violation.report_endpoints| works from any document of the right origin |
+ // 3. It should be fine to write a console message as long as it reaches the |
+ // console associated with the frame that used to host the document |
+ // declaring the violated CSP. |
+ // 4. In case of a race, an incorrect "securitypolicyviolation" event can be |
+ // raised but this should be mitigated by: |
+ // - low likelyhood of this happening (repro requires 1) different document |
+ // from the same origin, 2) with the same csp header present, 3) |
+ // navigated in a racey way with the csp check [e.g. navigating parent |
+ // frame while checking child frame doesn't have the race - the child |
+ // RFPH will be torn down before the violation-forwarding-ipc reaches |
+ // it]). |
+ // - low likelyhood of adverse effects (a page is unlikely to change its |
+ // core behavior in response to a csp violation event) |
+ if (!CanForwardViolationToCurrentDocument(origin_declaring_violated_csp, |
+ violation.header)) { |
+ return; |
+ } |
+ |
+ // Forward CSP violation report to the frame that declared the CSP. |
+ RenderFrameHostImpl* current_rfh = frame_tree_node_->current_frame_host(); |
+ current_rfh->Send(new FrameMsg_ReportContentSecurityPolicyViolation( |
+ current_rfh->GetRoutingID(), violation)); |
+} |
+ |
void RenderFrameProxyHost::OnRouteMessageEvent( |
const FrameMsg_PostMessage_Params& params) { |
RenderFrameHostImpl* target_rfh = frame_tree_node()->current_frame_host(); |