diff options
author | creis@chromium.org <creis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-15 00:03:49 +0000 |
---|---|---|
committer | creis@chromium.org <creis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-15 00:03:49 +0000 |
commit | f546640b585b15e0fb4275dbe5b763b20d207a15 (patch) | |
tree | 44f425de9139c3686c7880210b15a75a4abea63a /content | |
parent | 4a372b9ac4db91e367754c930f396b2905830074 (diff) | |
download | chromium_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.cc | 7 | ||||
-rw-r--r-- | content/browser/renderer_host/render_view_host_impl.h | 2 | ||||
-rw-r--r-- | content/browser/renderer_host/render_view_host_manager_browsertest.cc | 149 | ||||
-rw-r--r-- | content/browser/web_contents/web_contents_impl.cc | 40 | ||||
-rw-r--r-- | content/browser/web_contents/web_contents_impl.h | 4 | ||||
-rw-r--r-- | content/common/swapped_out_messages.cc | 1 | ||||
-rw-r--r-- | content/common/view_messages.h | 26 | ||||
-rw-r--r-- | content/public/browser/render_view_host_delegate.h | 6 | ||||
-rw-r--r-- | content/renderer/render_view_impl.cc | 78 | ||||
-rw-r--r-- | content/renderer/render_view_impl.h | 8 |
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); |