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

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: Charlie's nits Created 5 years, 8 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
« no previous file with comments | « content/renderer/render_frame_impl.h ('k') | content/renderer/render_frame_proxy.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/renderer/render_frame_impl.cc
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 88b26d2e20fc7dc1884a675f35c497d2481b4490..703363fbbc7265fbf1673d2b10c12e04152ec599 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -125,6 +125,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"
@@ -137,6 +138,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/WebSettings.h"
#include "third_party/WebKit/public/web/WebSurroundingText.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
@@ -186,6 +188,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;
@@ -206,6 +210,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;
@@ -1049,6 +1054,7 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateSandboxFlags, OnDidUpdateSandboxFlags)
IPC_MESSAGE_HANDLER(FrameMsg_SetTextTrackSettings,
OnTextTrackSettingsChanged)
+ IPC_MESSAGE_HANDLER(FrameMsg_PostMessageEvent, OnPostMessageEvent)
#if defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItems, OnSelectPopupMenuItems)
#elif defined(OS_MACOSX)
@@ -1261,6 +1267,12 @@ void RenderFrameImpl::OnSwapOut(
render_view_->SetSwappedOut(true);
is_swapped_out_ = true;
+ // Set the proxy here, since OnStop() below could cause an onload event
+ // handler to execute, which could trigger code such as
+ // willCheckAndDispatchMessageEvent() that needs the proxy.
+ if (proxy)
+ set_render_frame_proxy(proxy);
+
// Now that we're swapped out and filtering IPC messages, stop loading to
// ensure that no other in-progress navigation continues. We do this here
// to avoid sending a DidStopLoading message to the browser process.
@@ -1310,8 +1322,6 @@ void RenderFrameImpl::OnSwapOut(
// TODO(nasko): delete the frame here, since we've replaced it with a
// proxy.
}
- } else {
- set_render_frame_proxy(proxy);
}
}
@@ -1602,6 +1612,77 @@ void RenderFrameImpl::OnTextTrackSettingsChanged(
WebString::fromUTF8(params.text_track_text_size));
}
+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,
@@ -3571,31 +3652,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_);
+ render_frame_proxy_->postMessageEvent(
+ source_frame, render_frame_proxy_->web_frame(), target_origin, event);
return true;
}
« no previous file with comments | « content/renderer/render_frame_impl.h ('k') | content/renderer/render_frame_proxy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698