Index: content/renderer/render_frame_impl.cc |
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc |
index 5872c9af4e4436f9af9e34e0acdde8474500dfb7..239242e971f83f2bfb27c6d86ea77bd57d66476f 100644 |
--- a/content/renderer/render_frame_impl.cc |
+++ b/content/renderer/render_frame_impl.cc |
@@ -124,6 +124,7 @@ |
#include "third_party/WebKit/public/web/WebDocument.h" |
#include "third_party/WebKit/public/web/WebFrameWidget.h" |
#include "third_party/WebKit/public/web/WebGlyphCache.h" |
+#include "third_party/WebKit/public/web/WebKit.h" |
#include "third_party/WebKit/public/web/WebLocalFrame.h" |
#include "third_party/WebKit/public/web/WebMediaStreamRegistry.h" |
#include "third_party/WebKit/public/web/WebNavigationPolicy.h" |
@@ -136,6 +137,7 @@ |
#include "third_party/WebKit/public/web/WebSearchableFormData.h" |
#include "third_party/WebKit/public/web/WebSecurityOrigin.h" |
#include "third_party/WebKit/public/web/WebSecurityPolicy.h" |
+#include "third_party/WebKit/public/web/WebSerializedScriptValue.h" |
#include "third_party/WebKit/public/web/WebSurroundingText.h" |
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h" |
#include "third_party/WebKit/public/web/WebView.h" |
@@ -184,6 +186,8 @@ using blink::WebContextMenuData; |
using blink::WebData; |
using blink::WebDataSource; |
using blink::WebDocument; |
+using blink::WebDOMEvent; |
+using blink::WebDOMMessageEvent; |
using blink::WebElement; |
using blink::WebExternalPopupMenu; |
using blink::WebExternalPopupMenuClient; |
@@ -204,6 +208,7 @@ using blink::WebScriptSource; |
using blink::WebSearchableFormData; |
using blink::WebSecurityOrigin; |
using blink::WebSecurityPolicy; |
+using blink::WebSerializedScriptValue; |
using blink::WebServiceWorkerProvider; |
using blink::WebStorageQuotaCallbacks; |
using blink::WebString; |
@@ -1028,6 +1033,7 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) { |
IPC_MESSAGE_HANDLER(FrameMsg_DisownOpener, OnDisownOpener) |
IPC_MESSAGE_HANDLER(FrameMsg_CommitNavigation, OnCommitNavigation) |
IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateSandboxFlags, OnDidUpdateSandboxFlags) |
+ IPC_MESSAGE_HANDLER(FrameMsg_PostMessageEvent, OnPostMessageEvent) |
#if defined(OS_ANDROID) |
IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItems, OnSelectPopupMenuItems) |
#elif defined(OS_MACOSX) |
@@ -1553,6 +1559,77 @@ void RenderFrameImpl::OnDidUpdateSandboxFlags(SandboxFlags flags) { |
frame_->setFrameOwnerSandboxFlags(ContentToWebSandboxFlags(flags)); |
} |
+void RenderFrameImpl::OnPostMessageEvent( |
+ const FrameMsg_PostMessage_Params& params) { |
+ // Find the source frame if it exists. |
+ WebFrame* source_frame = NULL; |
+ if (params.source_view_routing_id != MSG_ROUTING_NONE) { |
+ // Support a legacy postMessage path for specifying a source RenderView; |
+ // this is currently used when sending messages to Android WebView. |
+ // TODO(alexmos): This path can be removed once crbug.com/473258 is fixed. |
+ RenderViewImpl* source_view = |
+ RenderViewImpl::FromRoutingID(params.source_view_routing_id); |
+ if (source_view) |
+ source_frame = source_view->webview()->mainFrame(); |
+ } else if (params.source_routing_id != MSG_ROUTING_NONE) { |
+ RenderFrameProxy* source_proxy = |
+ RenderFrameProxy::FromRoutingID(params.source_routing_id); |
+ if (source_proxy) { |
+ // Currently, navigating a top-level frame cross-process does not swap |
+ // the WebLocalFrame for a WebRemoteFrame in the frame tree, and the |
+ // WebRemoteFrame will not have an associated blink::Frame. If this is |
+ // the case for |source_proxy|, use the corresponding (swapped-out) |
+ // WebLocalFrame instead, so that event.source for this message can be |
+ // set and used properly. |
+ if (source_proxy->IsMainFrameDetachedFromTree()) |
+ source_frame = source_proxy->render_view()->webview()->mainFrame(); |
+ else |
+ source_frame = source_proxy->web_frame(); |
+ } |
+ } |
+ |
+ // If the message contained MessagePorts, create the corresponding endpoints. |
+ blink::WebMessagePortChannelArray channels = |
+ WebMessagePortChannelImpl::CreatePorts( |
+ params.message_ports, params.new_routing_ids, |
+ base::MessageLoopProxy::current().get()); |
+ |
+ WebSerializedScriptValue serialized_script_value; |
+ if (params.is_data_raw_string) { |
+ v8::HandleScope handle_scope(blink::mainThreadIsolate()); |
+ v8::Local<v8::Context> context = frame_->mainWorldScriptContext(); |
+ v8::Context::Scope context_scope(context); |
+ V8ValueConverterImpl converter; |
+ converter.SetDateAllowed(true); |
+ converter.SetRegExpAllowed(true); |
+ scoped_ptr<base::Value> value(new base::StringValue(params.data)); |
+ v8::Handle<v8::Value> result_value = converter.ToV8Value(value.get(), |
+ context); |
+ serialized_script_value = WebSerializedScriptValue::serialize(result_value); |
+ } else { |
+ serialized_script_value = WebSerializedScriptValue::fromString(params.data); |
+ } |
+ |
+ // Create an event with the message. The next-to-last parameter to |
+ // initMessageEvent is the last event ID, which is not used with postMessage. |
+ WebDOMEvent event = frame_->document().createEvent("MessageEvent"); |
+ WebDOMMessageEvent msg_event = event.to<WebDOMMessageEvent>(); |
+ msg_event.initMessageEvent("message", |
+ // |canBubble| and |cancellable| are always false |
+ false, false, |
+ serialized_script_value, |
+ params.source_origin, source_frame, "", channels); |
+ |
+ // We must pass in the target_origin to do the security check on this side, |
+ // since it may have changed since the original postMessage call was made. |
+ WebSecurityOrigin target_origin; |
+ if (!params.target_origin.empty()) { |
+ target_origin = |
+ WebSecurityOrigin::createFromString(WebString(params.target_origin)); |
+ } |
+ frame_->dispatchMessageEventWithOriginCheck(target_origin, msg_event); |
+} |
+ |
#if defined(OS_ANDROID) |
void RenderFrameImpl::OnSelectPopupMenuItems( |
bool canceled, |
@@ -3459,31 +3536,23 @@ bool RenderFrameImpl::willCheckAndDispatchMessageEvent( |
blink::WebDOMMessageEvent event) { |
DCHECK(!frame_ || frame_ == target_frame); |
+ // Currently, a postMessage that targets a cross-process frame can be plumbed |
+ // either through this function or RenderFrameProxy::postMessageEvent. This |
+ // function is used when the target cross-process frame is a top-level frame |
+ // which has been swapped out. In that case, the corresponding WebLocalFrame |
+ // currently remains in the frame tree even in site-per-process mode (see |
+ // OnSwapOut). RenderFrameProxy::postMessageEvent is used in |
+ // --site-per-process mode for all other cases. |
+ // |
+ // TODO(alexmos, nasko): When swapped-out:// disappears, this should be |
+ // cleaned up so that RenderFrameProxy::postMessageEvent is the only path for |
+ // cross-process postMessages. |
if (!is_swapped_out_) |
return false; |
- ViewMsg_PostMessage_Params params; |
- params.is_data_raw_string = false; |
- params.data = event.data().toString(); |
- params.source_origin = event.origin(); |
- if (!target_origin.isNull()) |
- params.target_origin = target_origin.toString(); |
- |
- params.message_ports = |
- WebMessagePortChannelImpl::ExtractMessagePortIDs(event.releaseChannels()); |
- |
- // Include the routing ID for the source frame (if one exists), which the |
- // browser process will translate into the routing ID for the equivalent |
- // frame in the target process. |
- params.source_routing_id = MSG_ROUTING_NONE; |
- if (source_frame) { |
- RenderViewImpl* source_view = |
- RenderViewImpl::FromWebView(source_frame->view()); |
- if (source_view) |
- params.source_routing_id = source_view->routing_id(); |
- } |
- |
- Send(new ViewHostMsg_RouteMessageEvent(render_view_->routing_id_, params)); |
+ CHECK(render_frame_proxy_); |
alexmos
2015/04/02 23:17:00
Am I correct in assuming the proxy_ will always ex
Charlie Reis
2015/04/06 16:18:55
I think the only way it could happen is in a befor
alexmos
2015/04/07 18:44:39
Just to summarize what we discussed offline. befo
|
+ render_frame_proxy_->postMessageEvent( |
+ source_frame, render_frame_proxy_->web_frame(), target_origin, event); |
return true; |
} |