Chromium Code Reviews| 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 988f9e876b4bdc989331f534aed27ff9014d36f5..1198ddef1a9b1db7a02181bc33529033e4555201 100644 |
| --- a/content/browser/frame_host/render_frame_proxy_host.cc |
| +++ b/content/browser/frame_host/render_frame_proxy_host.cc |
| @@ -8,8 +8,10 @@ |
| #include "content/browser/frame_host/cross_process_frame_connector.h" |
| #include "content/browser/frame_host/frame_tree.h" |
| #include "content/browser/frame_host/frame_tree_node.h" |
| +#include "content/browser/frame_host/render_frame_host_delegate.h" |
| #include "content/browser/frame_host/render_frame_host_impl.h" |
| #include "content/browser/frame_host/render_widget_host_view_child_frame.h" |
| +#include "content/browser/message_port_message_filter.h" |
| #include "content/browser/renderer_host/render_view_host_impl.h" |
| #include "content/browser/renderer_host/render_widget_host_view_base.h" |
| #include "content/browser/site_instance_impl.h" |
| @@ -117,6 +119,7 @@ bool RenderFrameProxyHost::OnMessageReceived(const IPC::Message& msg) { |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP(RenderFrameProxyHost, msg) |
| IPC_MESSAGE_HANDLER(FrameHostMsg_OpenURL, OnOpenURL) |
| + IPC_MESSAGE_HANDLER(FrameHostMsg_RouteMessageEvent, OnRouteMessageEvent) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| return handled; |
| @@ -162,4 +165,81 @@ void RenderFrameProxyHost::OnOpenURL( |
| frame_tree_node_->current_frame_host()->OpenURL(params, site_instance_.get()); |
| } |
| +void RenderFrameProxyHost::OnRouteMessageEvent( |
| + const FrameMsg_PostMessage_Params& params) { |
| + RenderFrameHostImpl* target_rfh = frame_tree_node()->current_frame_host(); |
| + |
| + // TODO(alexmos, lazyboy): The reason this check needs to be in the delegate |
| + // is <webview> support, since postMessages need to be allowed when the |
| + // target WebContents is dedicated to a browser plugin guest. This check |
| + // should be refactored and performed here once OOPIF support in <webview> |
| + // is further along. |
| + if (!target_rfh->delegate()->ShouldRouteMessageEvent(target_rfh, |
| + GetSiteInstance())) |
| + return; |
| + |
| + FrameMsg_PostMessage_Params new_params(params); |
| + |
| + // If there is a source_routing_id, translate it to the routing ID of the |
| + // equivalent RenderFrameProxyHost in the target process. |
| + if (new_params.source_routing_id != MSG_ROUTING_NONE) { |
| + RenderFrameHostImpl* source_rfh = RenderFrameHostImpl::FromID( |
| + GetProcess()->GetID(), new_params.source_routing_id); |
| + if (!source_rfh) { |
| + new_params.source_routing_id = MSG_ROUTING_NONE; |
| + } else { |
| + // Ensure that we have a swapped-out RVH and proxy for the source frame. |
| + // If it doesn't exist, create it on demand and also create its opener |
| + // chain, since those will also be accessible to the target page. |
| + // |
| + // TODO(alexmos): This currently only works for top-level frames and |
| + // won't create the right proxy if the message source is a subframe on a |
| + // cross-process tab. This will be cleaned up as part of moving opener |
| + // tracking to FrameTreeNode (https://crbug.com/225940). For now, if the |
| + // message is sent from a subframe on a cross-process tab, set the source |
| + // routing ID to the main frame of the source tab, which matches legacy |
| + // postMessage behavior prior to --site-per-process. |
| + int source_view_routing_id = |
| + target_rfh->delegate()->EnsureOpenerRenderViewsExist(source_rfh); |
| + |
| + RenderFrameProxyHost* source_proxy_in_target_site_instance = |
| + source_rfh->frame_tree_node() |
| + ->render_manager() |
| + ->GetRenderFrameProxyHost(target_rfh->GetSiteInstance()); |
| + if (source_proxy_in_target_site_instance) { |
| + new_params.source_routing_id = |
| + source_proxy_in_target_site_instance->GetRoutingID(); |
| + } else if (source_view_routing_id != MSG_ROUTING_NONE) { |
| + RenderViewHostImpl* source_rvh = RenderViewHostImpl::FromID( |
| + target_rfh->GetProcess()->GetID(), source_view_routing_id); |
| + CHECK(source_rvh); |
| + new_params.source_routing_id = source_rvh->main_frame_routing_id(); |
|
alexmos
2015/04/02 23:17:00
The test that fails without this path is MimeHandl
Charlie Reis
2015/04/06 16:18:55
Acknowledged.
|
| + } else { |
| + new_params.source_routing_id = MSG_ROUTING_NONE; |
| + } |
| + } |
| + } |
| + |
| + if (!params.message_ports.empty()) { |
| + // Updating the message port information has to be done in the IO thread; |
| + // MessagePortMessageFilter::RouteMessageEventWithMessagePorts will send |
| + // FrameMsg_PostMessageEvent after it's done. Note that a trivial solution |
| + // would've been to post a task on the IO thread to do the IO-thread-bound |
| + // work, and make that post a task back to WebContentsImpl in the UI |
| + // thread. But we cannot do that, since there's nothing to guarantee that |
| + // WebContentsImpl stays alive during the round trip. |
| + scoped_refptr<MessagePortMessageFilter> message_port_message_filter( |
| + static_cast<RenderProcessHostImpl*>(target_rfh->GetProcess()) |
| + ->message_port_message_filter()); |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + base::Bind(&MessagePortMessageFilter::RouteMessageEventWithMessagePorts, |
| + message_port_message_filter, target_rfh->GetRoutingID(), |
| + new_params)); |
| + } else { |
| + target_rfh->Send( |
| + new FrameMsg_PostMessageEvent(target_rfh->GetRoutingID(), new_params)); |
| + } |
| +} |
| + |
| } // namespace content |