Index: content/browser/frame_host/render_frame_host_impl.cc |
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc |
index e33649f7e9db3c1e7fa85626e2a4bf8dc145298a..b09c451ffb96035529934ac3ebc5bf8d8046d317 100644 |
--- a/content/browser/frame_host/render_frame_host_impl.cc |
+++ b/content/browser/frame_host/render_frame_host_impl.cc |
@@ -550,6 +550,7 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) { |
OnDidChangeSandboxFlags) |
IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeFrameOwnerProperties, |
OnDidChangeFrameOwnerProperties) |
+ IPC_MESSAGE_HANDLER(FrameHostMsg_BlockedLoad, OnBlockedLoad) |
IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateTitle, OnUpdateTitle) |
IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateEncoding, OnUpdateEncoding) |
IPC_MESSAGE_HANDLER(FrameHostMsg_BeginNavigation, |
@@ -1516,6 +1517,28 @@ void RenderFrameHostImpl::OnDidChangeFrameOwnerProperties( |
} |
} |
+void RenderFrameHostImpl::OnBlockedLoad() { |
+ // When a frame is blocked by X-Frame-Options or CSP frame-ancestors, the |
+ // blocked frame needs to get a unique origin, which ensures that it |
+ // appears as a normal cross-origin document, and is the desired behavior |
+ // according to spec: https://www.w3.org/TR/CSP2/#directive-frame-ancestors |
+ // This sets the unique origin on both the browser and renderer sides. The |
+ // IPC to renderer may be required when a cross-process subframe is blocked, |
+ // since the blocking currently occurs in the pending RenderFrame, but the |
+ // actual blocked frame will be left in the current RenderFrame in a |
+ // different process. |
+ // |
+ // TODO(mkwst, alexmos): This will probably be called directly rather than |
+ // from an renderer IPC once X-Frame-Options and CSP enforcement moves to the |
+ // browser process (https://crbug.com/555418). |
+ frame_tree_node_->SetCurrentOrigin(url::Origin()); |
+ |
+ if (this == frame_tree_node_->render_manager()->pending_frame_host()) { |
+ RenderFrameHost* current_rfh = frame_tree_node_->current_frame_host(); |
+ current_rfh->Send(new FrameMsg_BlockedLoad(current_rfh->GetRoutingID())); |
+ } |
+} |
+ |
void RenderFrameHostImpl::OnUpdateTitle( |
const base::string16& title, |
blink::WebTextDirection title_direction) { |
@@ -1557,11 +1580,22 @@ void RenderFrameHostImpl::OnDispatchLoad() { |
RenderFrameProxyHost* proxy = |
frame_tree_node()->render_manager()->GetProxyToParent(); |
if (!proxy) { |
+ // A valid special case where the proxy won't exist occurs when a frame |
+ // gets blocked due to X-Frame-Options or CSP while it is still pending. |
+ // (The proxy in the parent isn't created until commit.) In that case, it |
+ // is ok to ignore this load event dispatch, since it will be done as part |
+ // of forwarding the blocked notification (see |
+ // FrameMsg_CancelLoadAfterXFrameOptionsOrCSPDenied). |
+ // |
+ // TODO(mkwst, alexmos): This won't be necessary once X-Frame-Options and |
+ // CSP enforcement moves to the browser process (https://crbug.com/555418). |
+ if (this != frame_tree_node_->current_frame_host()) |
+ return; |
+ |
bad_message::ReceivedBadMessage(GetProcess(), |
bad_message::RFH_NO_PROXY_TO_PARENT); |
return; |
} |
- |
proxy->Send(new FrameMsg_DispatchLoad(proxy->GetRoutingID())); |
} |