summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorcreis@chromium.org <creis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-15 00:03:49 +0000
committercreis@chromium.org <creis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-15 00:03:49 +0000
commitf546640b585b15e0fb4275dbe5b763b20d207a15 (patch)
tree44f425de9139c3686c7880210b15a75a4abea63a /content
parent4a372b9ac4db91e367754c930f396b2905830074 (diff)
downloadchromium_src-f546640b585b15e0fb4275dbe5b763b20d207a15.zip
chromium_src-f546640b585b15e0fb4275dbe5b763b20d207a15.tar.gz
chromium_src-f546640b585b15e0fb4275dbe5b763b20d207a15.tar.bz2
Adds support for calling postMessage on a frame living in a different renderer.
Patch partly from Karl Koscher <supersat@chromium.org> BUG=99202 TEST=PostMessage calls work after navigating a window to a different process. Review URL: https://chromiumcodereview.appspot.com/9108001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@137024 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/renderer_host/render_view_host_impl.cc7
-rw-r--r--content/browser/renderer_host/render_view_host_impl.h2
-rw-r--r--content/browser/renderer_host/render_view_host_manager_browsertest.cc149
-rw-r--r--content/browser/web_contents/web_contents_impl.cc40
-rw-r--r--content/browser/web_contents/web_contents_impl.h4
-rw-r--r--content/common/swapped_out_messages.cc1
-rw-r--r--content/common/view_messages.h26
-rw-r--r--content/public/browser/render_view_host_delegate.h6
-rw-r--r--content/renderer/render_view_impl.cc78
-rw-r--r--content/renderer/render_view_impl.h8
10 files changed, 317 insertions, 4 deletions
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index 7ea514c..f607477 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -875,6 +875,7 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
OnMsgDidChangeNumWheelEvents)
IPC_MESSAGE_HANDLER(ViewHostMsg_RouteCloseEvent,
OnMsgRouteCloseEvent)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_RouteMessageEvent, OnMsgRouteMessageEvent)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunJavaScriptMessage,
OnMsgRunJavaScriptMessage)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunBeforeUnloadConfirm,
@@ -1281,6 +1282,12 @@ void RenderViewHostImpl::OnMsgRouteCloseEvent() {
delegate_->RouteCloseEvent(this);
}
+void RenderViewHostImpl::OnMsgRouteMessageEvent(
+ const ViewMsg_PostMessage_Params& params) {
+ // Give to the delegate to route to the active RenderViewHost.
+ delegate_->RouteMessageEvent(this, params);
+}
+
void RenderViewHostImpl::OnMsgRunJavaScriptMessage(
const string16& message,
const string16& default_prompt,
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h
index 9f1972d..e1a54fe 100644
--- a/content/browser/renderer_host/render_view_host_impl.h
+++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -38,6 +38,7 @@ struct ViewHostMsg_CreateWindow_Params;
struct ViewHostMsg_DidFailProvisionalLoadWithError_Params;
struct ViewHostMsg_ShowPopup_Params;
struct ViewMsg_Navigate_Params;
+struct ViewMsg_PostMessage_Params;
struct ViewMsg_StopFinding_Params;
namespace base {
@@ -486,6 +487,7 @@ class CONTENT_EXPORT RenderViewHostImpl
const gfx::Rect& end_rect);
void OnMsgPasteFromSelectionClipboard();
void OnMsgRouteCloseEvent();
+ void OnMsgRouteMessageEvent(const ViewMsg_PostMessage_Params& params);
void OnMsgRunJavaScriptMessage(const string16& message,
const string16& default_prompt,
const GURL& frame_url,
diff --git a/content/browser/renderer_host/render_view_host_manager_browsertest.cc b/content/browser/renderer_host/render_view_host_manager_browsertest.cc
index ec3552c..9312241 100644
--- a/content/browser/renderer_host/render_view_host_manager_browsertest.cc
+++ b/content/browser/renderer_host/render_view_host_manager_browsertest.cc
@@ -5,6 +5,7 @@
#include "base/file_util.h"
#include "base/memory/ref_counted.h"
#include "base/path_service.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
@@ -394,7 +395,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
ui_test_utils::NavigateToURL(browser(),
https_server.GetURL("files/title1.html"));
scoped_refptr<SiteInstance> new_site_instance(
- browser()->GetSelectedWebContents()->GetSiteInstance());
+ new_contents->GetSiteInstance());
EXPECT_NE(orig_site_instance, new_site_instance);
// Clicking the original link in the first tab should cause us to swap back.
@@ -434,6 +435,152 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
close_observer.Wait();
}
+// Test for crbug.com/99202. PostMessage calls should still work after
+// navigating the source and target windows to different sites.
+// Specifically:
+// 1) Create 3 windows (opener, "foo", and _blank) and send "foo" cross-process.
+// 2) Fail to post a message from "foo" to opener with the wrong target origin.
+// 3) Post a message from "foo" to opener, which replies back to "foo".
+// 4) Post a message from _blank to "foo".
+IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
+ SupportCrossProcessPostMessage) {
+ // Start two servers with different sites.
+ ASSERT_TRUE(test_server()->Start());
+ net::TestServer https_server(
+ net::TestServer::TYPE_HTTPS,
+ net::TestServer::kLocalhost,
+ FilePath(FILE_PATH_LITERAL("chrome/test/data")));
+ ASSERT_TRUE(https_server.Start());
+
+ // Load a page with links that open in a new window.
+ std::string replacement_path;
+ ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
+ "files/click-noreferrer-links.html",
+ https_server.host_port_pair(),
+ &replacement_path));
+ ui_test_utils::NavigateToURL(browser(),
+ test_server()->GetURL(replacement_path));
+
+ // Get the original SiteInstance and RVHM for later comparison.
+ content::WebContents* opener_contents = browser()->GetSelectedWebContents();
+ scoped_refptr<SiteInstance> orig_site_instance(
+ opener_contents->GetSiteInstance());
+ EXPECT_TRUE(orig_site_instance != NULL);
+ RenderViewHostManager* opener_manager =
+ static_cast<WebContentsImpl*>(opener_contents)->
+ GetRenderManagerForTesting();
+
+ // 1) Open two more windows, one named. These initially have openers but no
+ // reference to each other. We will later post a message between them.
+
+ // First, a named target=foo window.
+ ui_test_utils::WindowedTabAddedNotificationObserver new_tab_observer((
+ content::Source<content::WebContentsDelegate>(browser())));
+ bool success = false;
+ EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ opener_contents->GetRenderViewHost(), L"",
+ L"window.domAutomationController.send(clickSameSiteTargetedLink());",
+ &success));
+ EXPECT_TRUE(success);
+ new_tab_observer.Wait();
+
+ // Wait for the navigation in the new tab to finish, if it hasn't, then
+ // send it to post_message.html on a different site.
+ content::WebContents* foo_contents = browser()->GetSelectedWebContents();
+ ui_test_utils::WaitForLoadStop(foo_contents);
+ EXPECT_EQ("/files/navigate_opener.html", foo_contents->GetURL().path());
+ EXPECT_EQ(1, browser()->active_index());
+ ui_test_utils::NavigateToURL(browser(),
+ https_server.GetURL("files/post_message.html"));
+ scoped_refptr<SiteInstance> foo_site_instance(
+ foo_contents->GetSiteInstance());
+ EXPECT_NE(orig_site_instance, foo_site_instance);
+
+ // Second, a target=_blank window.
+ browser()->ActivateTabAt(0, true);
+ ui_test_utils::WindowedTabAddedNotificationObserver new_tab_observer2((
+ content::Source<content::WebContentsDelegate>(browser())));
+ EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ browser()->GetSelectedWebContents()->GetRenderViewHost(), L"",
+ L"window.domAutomationController.send(clickSameSiteTargetBlankLink());",
+ &success));
+ EXPECT_TRUE(success);
+ new_tab_observer2.Wait();
+
+ // Wait for the navigation in the new tab to finish, if it hasn't, then
+ // send it to post_message.html on the original site.
+ content::WebContents* new_contents = browser()->GetSelectedWebContents();
+ ui_test_utils::WaitForLoadStop(new_contents);
+ EXPECT_EQ("/files/title2.html", new_contents->GetURL().path());
+ EXPECT_EQ(1, browser()->active_index());
+ ui_test_utils::NavigateToURL(
+ browser(), test_server()->GetURL("files/post_message.html"));
+ EXPECT_EQ(orig_site_instance, new_contents->GetSiteInstance());
+ RenderViewHostManager* new_manager =
+ static_cast<WebContentsImpl*>(new_contents)->GetRenderManagerForTesting();
+
+ // We now have three windows. The opener should have a swapped out RVH
+ // for the new SiteInstance, but the _blank window should not.
+ EXPECT_EQ(3, browser()->tab_count());
+ EXPECT_TRUE(opener_manager->GetSwappedOutRenderViewHost(foo_site_instance));
+ EXPECT_FALSE(new_manager->GetSwappedOutRenderViewHost(foo_site_instance));
+
+ // 2) Fail to post a message from the foo window to the opener if the target
+ // origin is wrong. We won't see an error, but we can check for the right
+ // number of received messages below.
+ EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ foo_contents->GetRenderViewHost(), L"",
+ L"window.domAutomationController.send(postToOpener('msg',"
+ L"'http://google.com'));",
+ &success));
+ EXPECT_TRUE(success);
+
+ // 3) Post a message from the foo window to the opener. The opener will
+ // reply, causing the foo window to update its own title.
+ ui_test_utils::WindowedNotificationObserver title_observer(
+ content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
+ content::Source<content::WebContents>(foo_contents));
+ EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ foo_contents->GetRenderViewHost(), L"",
+ L"window.domAutomationController.send(postToOpener('msg','*'));",
+ &success));
+ EXPECT_TRUE(success);
+ title_observer.Wait();
+
+ // We should have received only 1 message in the opener and "foo" tabs,
+ // and updated the title.
+ int opener_received_messages = 0;
+ EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractInt(
+ opener_contents->GetRenderViewHost(), L"",
+ L"window.domAutomationController.send(window.receivedMessages);",
+ &opener_received_messages));
+ int foo_received_messages = 0;
+ EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractInt(
+ foo_contents->GetRenderViewHost(), L"",
+ L"window.domAutomationController.send(window.receivedMessages);",
+ &foo_received_messages));
+ EXPECT_EQ(1, foo_received_messages);
+ EXPECT_EQ(1, opener_received_messages);
+ EXPECT_EQ(ASCIIToUTF16("msg"), foo_contents->GetTitle());
+
+ // 4) Now post a message from the _blank window to the foo window. The
+ // foo window will update its title and will not reply.
+ ui_test_utils::WindowedNotificationObserver title_observer2(
+ content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
+ content::Source<content::WebContents>(foo_contents));
+ EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ new_contents->GetRenderViewHost(), L"",
+ L"window.domAutomationController.send(postToFoo('msg2'));",
+ &success));
+ EXPECT_TRUE(success);
+ title_observer2.Wait();
+ EXPECT_EQ(ASCIIToUTF16("msg2"), foo_contents->GetTitle());
+
+ // This postMessage should have created a swapped out RVH for the new
+ // SiteInstance in the target=_blank window.
+ EXPECT_TRUE(new_manager->GetSwappedOutRenderViewHost(foo_site_instance));
+}
+
// Test for crbug.com/116192. Navigations to a window's opener should
// still work after a process swap.
IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 5330389..0e963c9 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2427,6 +2427,46 @@ void WebContentsImpl::RouteCloseEvent(RenderViewHost* rvh) {
GetRenderViewHost()->ClosePage();
}
+void WebContentsImpl::RouteMessageEvent(
+ RenderViewHost* rvh,
+ const ViewMsg_PostMessage_Params& params) {
+ // Only deliver the message to the active RenderViewHost if the request
+ // came from a RenderViewHost in the same BrowsingInstance.
+ if (!rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()))
+ return;
+
+ ViewMsg_PostMessage_Params new_params(params);
+
+ // If there is a source_routing_id, translate it to the routing ID for
+ // the equivalent swapped out RVH in the target process. If we need
+ // to create a swapped out RVH for the source tab, we create its opener
+ // chain as well, since those will also be accessible to the target page.
+ if (new_params.source_routing_id != MSG_ROUTING_NONE) {
+ // Try to look up the WebContents for the source page.
+ WebContentsImpl* source_contents = NULL;
+ RenderViewHostImpl* source_rvh = RenderViewHostImpl::FromID(
+ rvh->GetProcess()->GetID(), params.source_routing_id);
+ if (source_rvh) {
+ source_contents = static_cast<WebContentsImpl*>(
+ source_rvh->GetDelegate()->GetAsWebContents());
+ }
+
+ if (source_contents) {
+ new_params.source_routing_id =
+ source_contents->CreateOpenerRenderViews(GetSiteInstance());
+ } else {
+ // We couldn't find it, so don't pass a source frame.
+ new_params.source_routing_id = MSG_ROUTING_NONE;
+ }
+ }
+
+ // In most cases, we receive this from a swapped out RenderViewHost.
+ // It is possible to receive it from one that has just been swapped in,
+ // in which case we might as well deliver the message anyway.
+ GetRenderViewHost()->Send(new ViewMsg_PostMessageEvent(
+ GetRenderViewHost()->GetRoutingID(), new_params));
+}
+
void WebContentsImpl::RunJavaScriptMessage(
RenderViewHost* rvh,
const string16& message,
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 5242ef9..57dc19b 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -35,6 +35,7 @@
class InterstitialPageImpl;
class SavePackage;
class SessionStorageNamespaceImpl;
+struct ViewMsg_PostMessage_Params;
namespace content {
class ColorChooser;
@@ -311,6 +312,9 @@ class CONTENT_EXPORT WebContentsImpl
int64 source_frame_id,
const content::GlobalRequestID& transferred_global_request_id) OVERRIDE;
virtual void RouteCloseEvent(content::RenderViewHost* rvh) OVERRIDE;
+ virtual void RouteMessageEvent(
+ content::RenderViewHost* rvh,
+ const ViewMsg_PostMessage_Params& params) OVERRIDE;
virtual void RunJavaScriptMessage(content::RenderViewHost* rvh,
const string16& message,
const string16& default_prompt,
diff --git a/content/common/swapped_out_messages.cc b/content/common/swapped_out_messages.cc
index 1e0b667..83fc394 100644
--- a/content/common/swapped_out_messages.cc
+++ b/content/common/swapped_out_messages.cc
@@ -30,6 +30,7 @@ bool SwappedOutMessages::CanSendWhileSwappedOut(const IPC::Message* msg) {
case ViewHostMsg_DomOperationResponse::ID:
// Allow cross-process JavaScript calls.
case ViewHostMsg_RouteCloseEvent::ID:
+ case ViewHostMsg_RouteMessageEvent::ID:
return true;
default:
break;
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 5045b17..e5e9e38 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -524,6 +524,23 @@ IPC_STRUCT_BEGIN(ViewHostMsg_UpdateRect_Params)
IPC_STRUCT_MEMBER(bool, needs_ack)
IPC_STRUCT_END()
+IPC_STRUCT_BEGIN(ViewMsg_PostMessage_Params)
+ // The serialized script value.
+ IPC_STRUCT_MEMBER(string16, data)
+
+ // When sent to the browser, this is the routing ID of the source frame in
+ // the source process. The browser replaces it with the routing ID of the
+ // equivalent (swapped out) frame in the destination process. Set to
+ // MSG_ROUTING_NONE if the source frame isn't supported (e.g., subframes).
+ IPC_STRUCT_MEMBER(int, source_routing_id)
+
+ // The origin of the source frame.
+ IPC_STRUCT_MEMBER(string16, source_origin)
+
+ // The origin for the message's target.
+ IPC_STRUCT_MEMBER(string16, target_origin)
+IPC_STRUCT_END()
+
IPC_STRUCT_BEGIN(ViewHostMsg_DidFailProvisionalLoadWithError_Params)
// The frame ID for the failure report.
IPC_STRUCT_MEMBER(int64, frame_id)
@@ -927,6 +944,10 @@ IPC_MESSAGE_ROUTED4(ViewMsg_ScriptEvalRequest,
int, /* ID */
bool /* If true, result is sent back. */)
+// Posts a message from a frame in another process to the current renderer.
+IPC_MESSAGE_ROUTED1(ViewMsg_PostMessageEvent,
+ ViewMsg_PostMessage_Params)
+
// Request for the renderer to evaluate an xpath to a frame and insert css
// into that frame's document. See ViewMsg_ScriptEvalRequest for details on
// allowed xpath expressions.
@@ -1616,6 +1637,11 @@ IPC_MESSAGE_ROUTED1(ViewHostMsg_GoToEntryAtOffset,
// renderer, instructing it to close.
IPC_MESSAGE_ROUTED0(ViewHostMsg_RouteCloseEvent)
+// Sent to the browser from an inactive renderer to post a message to the
+// active renderer.
+IPC_MESSAGE_ROUTED1(ViewHostMsg_RouteMessageEvent,
+ ViewMsg_PostMessage_Params)
+
IPC_SYNC_MESSAGE_ROUTED4_2(ViewHostMsg_RunJavaScriptMessage,
string16 /* in - alert message */,
string16 /* in - default prompt */,
diff --git a/content/public/browser/render_view_host_delegate.h b/content/public/browser/render_view_host_delegate.h
index 17a4dc9..e74c1b1 100644
--- a/content/public/browser/render_view_host_delegate.h
+++ b/content/public/browser/render_view_host_delegate.h
@@ -30,6 +30,7 @@ struct NativeWebKeyboardEvent;
struct ViewHostMsg_CreateWindow_Params;
struct ViewHostMsg_DidFailProvisionalLoadWithError_Params;
struct ViewHostMsg_FrameNavigate_Params;
+struct ViewMsg_PostMessage_Params;
struct WebDropData;
struct WebMenuItem;
@@ -330,6 +331,11 @@ class CONTENT_EXPORT RenderViewHostDelegate : public IPC::Channel::Listener {
// The page wants to close the active view in this tab.
virtual void RouteCloseEvent(RenderViewHost* rvh) {}
+ // The page wants to post a message to the active view in this tab.
+ virtual void RouteMessageEvent(
+ RenderViewHost* rvh,
+ const ViewMsg_PostMessage_Params& params) {}
+
// A javascript message, confirmation or prompt should be shown.
virtual void RunJavaScriptMessage(RenderViewHost* rvh,
const string16& message,
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index ff7c1e9..5a35235 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -102,6 +102,8 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityObject.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDOMEvent.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDOMMessageEvent.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileChooserParams.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystemCallbacks.h"
@@ -143,6 +145,7 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPeerConnectionHandlerClient.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPoint.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSerializedScriptValue.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSocketStreamHandle.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
@@ -204,6 +207,8 @@ using WebKit::WebCookieJar;
using WebKit::WebData;
using WebKit::WebDataSource;
using WebKit::WebDocument;
+using WebKit::WebDOMEvent;
+using WebKit::WebDOMMessageEvent;
using WebKit::WebDragData;
using WebKit::WebDragOperation;
using WebKit::WebDragOperationsMask;
@@ -252,6 +257,7 @@ using WebKit::WebScriptSource;
using WebKit::WebSearchableFormData;
using WebKit::WebSecurityOrigin;
using WebKit::WebSecurityPolicy;
+using WebKit::WebSerializedScriptValue;
using WebKit::WebSettings;
using WebKit::WebSharedWorker;
using WebKit::WebSize;
@@ -315,6 +321,11 @@ static const float kScalingIncrement = 0.1f;
static const float kScalingIncrementForGesture = 0.01f;
+static RenderViewImpl* FromRoutingID(int32 routing_id) {
+ return static_cast<RenderViewImpl*>(
+ ChildThread::current()->ResolveRoute(routing_id));
+}
+
static void GetRedirectChain(WebDataSource* ds, std::vector<GURL>* result) {
WebVector<WebURL> urls;
ds->redirectChain(urls);
@@ -575,9 +586,9 @@ RenderViewImpl::RenderViewImpl(
// it's the browser asking us to set our opener to another RenderView.
// TODO(creis): This doesn't yet handle openers that are subframes.
if (opener_id != MSG_ROUTING_NONE && !is_renderer_created) {
- RenderViewImpl* opener_view = static_cast<RenderViewImpl*>(
- ChildThread::current()->ResolveRoute(opener_id));
- webview()->mainFrame()->setOpener(opener_view->webview()->mainFrame());
+ RenderViewImpl* opener_view = FromRoutingID(opener_id);
+ if (opener_view)
+ webview()->mainFrame()->setOpener(opener_view->webview()->mainFrame());
}
// If we are initially swapped out, navigate to kSwappedOutURL.
@@ -805,6 +816,7 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_ResetPageEncodingToDefault,
OnResetPageEncodingToDefault)
IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest)
+ IPC_MESSAGE_HANDLER(ViewMsg_PostMessageEvent, OnPostMessageEvent)
IPC_MESSAGE_HANDLER(ViewMsg_CSSInsertRequest, OnCSSInsertRequest)
IPC_MESSAGE_HANDLER(DragMsg_TargetDragEnter, OnDragTargetDragEnter)
IPC_MESSAGE_HANDLER(DragMsg_TargetDragOver, OnDragTargetDragOver)
@@ -3520,6 +3532,32 @@ void RenderViewImpl::dispatchIntent(
routing_id_, intent_data, id));
}
+bool RenderViewImpl::willCheckAndDispatchMessageEvent(
+ WebKit::WebFrame* source,
+ WebKit::WebSecurityOrigin target_origin,
+ WebKit::WebDOMMessageEvent event) {
+ if (!is_swapped_out_)
+ return false;
+
+ ViewMsg_PostMessage_Params params;
+ params.data = event.data().toString();
+ params.source_origin = event.origin();
+ if (!target_origin.isNull())
+ params.target_origin = target_origin.toString();
+
+ // Include the routing ID for the source frame, which the browser process
+ // will translate into the routing ID for the equivalent frame in the target
+ // process.
+ // TODO(creis): Support source subframes.
+ params.source_routing_id = MSG_ROUTING_NONE;
+ RenderViewImpl* source_view = FromWebView(source->view());
+ if (source_view)
+ params.source_routing_id = source_view->routing_id();
+
+ Send(new ViewHostMsg_RouteMessageEvent(routing_id_, params));
+ return true;
+}
+
void RenderViewImpl::willOpenSocketStream(
WebSocketStreamHandle* handle) {
SocketStreamHandleData::AddToHandle(handle, routing_id_);
@@ -4192,6 +4230,40 @@ void RenderViewImpl::OnScriptEvalRequest(const string16& frame_xpath,
EvaluateScript(frame_xpath, jscript, id, notify_result);
}
+void RenderViewImpl::OnPostMessageEvent(
+ const ViewMsg_PostMessage_Params& params) {
+ // TODO(creis): Support sending to subframes.
+ WebFrame *frame = webview()->mainFrame();
+
+ // Find the source frame if it exists.
+ // TODO(creis): Support source subframes.
+ WebFrame* source_frame = NULL;
+ if (params.source_routing_id != MSG_ROUTING_NONE) {
+ RenderViewImpl* source_view = FromRoutingID(params.source_routing_id);
+ if (source_view)
+ source_frame = source_view->webview()->mainFrame();
+ }
+
+ // Create an event with the message. The final 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,
+ WebSerializedScriptValue::fromString(params.data),
+ params.source_origin, source_frame, "");
+
+ // 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);
+}
+
void RenderViewImpl::OnCSSInsertRequest(const string16& frame_xpath,
const std::string& css) {
WebFrame* frame = GetChildFrame(frame_xpath);
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index ea4e728..54945e2 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -43,6 +43,7 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPageSerializerClient.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPageVisibilityState.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextDirection.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebViewClient.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebFileSystem.h"
@@ -81,6 +82,7 @@ class RendererWebColorChooserImpl;
class SkBitmap;
class InputTagSpeechDispatcher;
struct ViewMsg_Navigate_Params;
+struct ViewMsg_PostMessage_Params;
struct ViewMsg_StopFinding_Params;
struct ViewMsg_SwapOut_Params;
struct WebDropData;
@@ -120,6 +122,7 @@ class ResourceFetcher;
namespace WebKit {
class WebApplicationCacheHost;
class WebApplicationCacheHostClient;
+class WebDOMMessageEvent;
class WebDataSource;
class WebDragData;
class WebGeolocationClient;
@@ -593,6 +596,10 @@ class RenderViewImpl : public RenderWidget,
const WebKit::WebIntentRequest& intentRequest);
virtual void willOpenSocketStream(
WebKit::WebSocketStreamHandle* handle);
+ virtual bool willCheckAndDispatchMessageEvent(
+ WebKit::WebFrame* source,
+ WebKit::WebSecurityOrigin targetOrigin,
+ WebKit::WebDOMMessageEvent event) OVERRIDE;
// WebKit::WebPageSerializerClient implementation ----------------------------
@@ -869,6 +876,7 @@ class RenderViewImpl : public RenderWidget,
#if defined(OS_MACOSX)
void OnPluginImeCompositionCompleted(const string16& text, int plugin_id);
#endif
+ void OnPostMessageEvent(const ViewMsg_PostMessage_Params& params);
void OnRedo();
void OnReloadFrame();
void OnReplace(const string16& text);