Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2287)

Unified Diff: content/renderer/render_frame_impl.cc

Issue 1046933005: Refactor postMessage for out-of-process iframes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Enable SupportCrossProcessPostMessage test on FYI bots Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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;
}

Powered by Google App Engine
This is Rietveld 408576698