From 485d8c9acd4acac2c6d994b87f05963c893ad394 Mon Sep 17 00:00:00 2001 From: "commit-queue@webkit.org" Date: Wed, 4 Jan 2012 04:38:42 +0000 Subject: [PATCH] Give embedders a chance to handle postMessage calls https://bugs.webkit.org/show_bug.cgi?id=73883 Source/WebCore: To support cross-process postMessage calls in Chromium (bug 73337), we need to intercept postMessage calls to proxy windows. Originally we were just going to add a native event listener on the Chromium side, but that required more changes to WebKit and was a bit of a hack. See bug 73359 for a discuss about moving to this approach. Patch by Karl Koscher on 2012-01-03 Reviewed by Adam Barth. Test: platform/chromium/fast/events/intercept-postmessage.html * loader/FrameLoaderClient.h: (WebCore::FrameLoaderClient::willCheckAndDispatchPostMessage): new method to allow the embedder to intercept postMessage calls * page/DOMWindow.cpp: (WebCore::DOMWindow::postMessageTimerFired): add a call to FrameLoaderClient::willCheckAndDispatchPostMessage Source/WebKit/chromium: Patch by Karl Koscher on 2012-01-03 Reviewed by Adam Barth. * public/WebFrameClient.h: (WebKit::WebFrameClient::willCheckAndDispatchMessageEvent): interface to give the embedder a chance to handle this postMessage call * src/FrameLoaderClientImpl.cpp: (WebKit::FrameLoaderClientImpl::willCheckAndDispatchMessageEvent): Call willCheckAndDispatchMessageEvent on WebFrameClient * src/FrameLoaderClientImpl.h: git-svn-id: http://svn.webkit.org/repository/webkit/trunk@104005 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- .../fast/events/intercept-postmessage-expected.txt | 7 +++ .../fast/events/intercept-postmessage.html | 50 ++++++++++++++++++++++ Source/WebCore/ChangeLog | 21 +++++++++ Source/WebCore/loader/FrameLoaderClient.h | 4 ++ Source/WebCore/page/DOMWindow.cpp | 13 +++++- Source/WebKit/chromium/ChangeLog | 15 +++++++ Source/WebKit/chromium/public/WebDOMMessageEvent.h | 7 ++- Source/WebKit/chromium/public/WebFrameClient.h | 14 +++++- .../WebKit/chromium/src/FrameLoaderClientImpl.cpp | 12 ++++++ Source/WebKit/chromium/src/FrameLoaderClientImpl.h | 1 + .../chromium/LayoutTestController.cpp | 2 + .../DumpRenderTree/chromium/LayoutTestController.h | 8 ++++ Tools/DumpRenderTree/chromium/WebViewHost.cpp | 11 +++++ Tools/DumpRenderTree/chromium/WebViewHost.h | 1 + 14 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 LayoutTests/platform/chromium/fast/events/intercept-postmessage-expected.txt create mode 100644 LayoutTests/platform/chromium/fast/events/intercept-postmessage.html diff --git a/LayoutTests/platform/chromium/fast/events/intercept-postmessage-expected.txt b/LayoutTests/platform/chromium/fast/events/intercept-postmessage-expected.txt new file mode 100644 index 0000000..a12078d --- /dev/null +++ b/LayoutTests/platform/chromium/fast/events/intercept-postmessage-expected.txt @@ -0,0 +1,7 @@ +main frame - didFinishDocumentLoadForFrame +main frame - didHandleOnloadEventsForFrame +main frame - didFinishLoadForFrame +intercepted postMessage +intercepted postMessage +RECV1 + diff --git a/LayoutTests/platform/chromium/fast/events/intercept-postmessage.html b/LayoutTests/platform/chromium/fast/events/intercept-postmessage.html new file mode 100644 index 0000000..4db0ab6 --- /dev/null +++ b/LayoutTests/platform/chromium/fast/events/intercept-postmessage.html @@ -0,0 +1,50 @@ + + + + +

+
+
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 0696d82..195988f 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,24 @@
+2012-01-03  Karl Koscher  
+
+        Give embedders a chance to handle postMessage calls
+        https://bugs.webkit.org/show_bug.cgi?id=73883
+
+        To support cross-process postMessage calls in Chromium (bug 73337), we need to intercept 
+        postMessage calls to proxy windows. Originally we were just going to add a native event
+        listener on the Chromium side, but that required more changes to WebKit and was a bit of
+        a hack. See bug 73359 for a discuss about moving to this approach.
+
+        Reviewed by Adam Barth.
+
+        Test: platform/chromium/fast/events/intercept-postmessage.html
+
+        * loader/FrameLoaderClient.h:
+        (WebCore::FrameLoaderClient::willCheckAndDispatchPostMessage): new method to allow the
+            embedder to intercept postMessage calls
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::postMessageTimerFired): add a call to
+            FrameLoaderClient::willCheckAndDispatchPostMessage
+
 2012-01-03  Eric Penner  
 
         [chromium] Prevent crashing due to NULL texture updater.
diff --git a/Source/WebCore/loader/FrameLoaderClient.h b/Source/WebCore/loader/FrameLoaderClient.h
index 4517b36..28aa6d6 100644
--- a/Source/WebCore/loader/FrameLoaderClient.h
+++ b/Source/WebCore/loader/FrameLoaderClient.h
@@ -79,6 +79,7 @@ namespace WebCore {
     class HTMLPlugInElement;
     class IntSize;
     class KURL;
+    class MessageEvent;
     class NavigationAction;
     class Page;
     class ProtectionSpace;
@@ -319,6 +320,9 @@ namespace WebCore {
         virtual PassRefPtr createNetworkingContext() = 0;
 
         virtual bool shouldPaintBrokenImage(const KURL&) const { return true; }
+
+        // Returns true if the embedder intercepted the postMessage call
+        virtual bool willCheckAndDispatchMessageEvent(SecurityOrigin* /*target*/, MessageEvent*) const { return false; }
     };
 
 } // namespace WebCore
diff --git a/Source/WebCore/page/DOMWindow.cpp b/Source/WebCore/page/DOMWindow.cpp
index a3e0591..346eb96 100644
--- a/Source/WebCore/page/DOMWindow.cpp
+++ b/Source/WebCore/page/DOMWindow.cpp
@@ -60,6 +60,7 @@
 #include "Frame.h"
 #include "FrameLoadRequest.h"
 #include "FrameLoader.h"
+#include "FrameLoaderClient.h"
 #include "FrameTree.h"
 #include "FrameView.h"
 #include "HTMLFrameOwnerElement.h"
@@ -910,8 +911,16 @@ void DOMWindow::postMessageTimerFired(PassOwnPtr t)
     if (!document())
         return;
 
+    RefPtr event = timer->event(document());
+
+    // Give the embedder a chance to intercept this postMessage because this
+    // DOMWindow might be a proxy for another in browsers that support
+    // postMessage calls across WebKit instances.
+    if (isCurrentlyDisplayedInFrame() && m_frame->loader()->client()->willCheckAndDispatchMessageEvent(timer->targetOrigin(), PassRefPtr(event).leakRef()))
+        return;
+
     if (timer->targetOrigin()) {
-        // Check target origin now since the target document may have changed since the simer was scheduled.
+        // Check target origin now since the target document may have changed since the timer was scheduled.
         if (!timer->targetOrigin()->isSameSchemeHostPort(document()->securityOrigin())) {
             String message = "Unable to post message to " + timer->targetOrigin()->toString() +
                              ". Recipient has origin " + document()->securityOrigin()->toString() + ".\n";
@@ -920,7 +929,7 @@ void DOMWindow::postMessageTimerFired(PassOwnPtr t)
         }
     }
 
-    dispatchEvent(timer->event(document()));
+    dispatchEvent(event);
 }
 
 DOMSelection* DOMWindow::getSelection()
diff --git a/Source/WebKit/chromium/ChangeLog b/Source/WebKit/chromium/ChangeLog
index 6f575aa..a460de6 100644
--- a/Source/WebKit/chromium/ChangeLog
+++ b/Source/WebKit/chromium/ChangeLog
@@ -1,3 +1,18 @@
+2012-01-03  Karl Koscher  
+
+        Give embedders a chance to handle postMessage calls
+        https://bugs.webkit.org/show_bug.cgi?id=73883
+
+        Reviewed by Adam Barth.
+
+        * public/WebFrameClient.h:
+        (WebKit::WebFrameClient::willCheckAndDispatchMessageEvent): 
+            interface to give the embedder a chance to handle this postMessage call
+        * src/FrameLoaderClientImpl.cpp:
+        (WebKit::FrameLoaderClientImpl::willCheckAndDispatchMessageEvent): Call 
+            willCheckAndDispatchMessageEvent on WebFrameClient
+        * src/FrameLoaderClientImpl.h:
+
 2012-01-03  Shawn Singh  
 
         [chromium] CCLayerSorter accidentally reverses order of some layers.
diff --git a/Source/WebKit/chromium/public/WebDOMMessageEvent.h b/Source/WebKit/chromium/public/WebDOMMessageEvent.h
index fa7eb6d..355b737 100644
--- a/Source/WebKit/chromium/public/WebDOMMessageEvent.h
+++ b/Source/WebKit/chromium/public/WebDOMMessageEvent.h
@@ -35,7 +35,8 @@
 #include "platform/WebSerializedScriptValue.h"
 
 #if WEBKIT_IMPLEMENTATION
-namespace WebCore { class Event; }
+#include "Event.h"
+#include "MessageEvent.h"
 #endif
 
 namespace WebKit {
@@ -49,6 +50,10 @@ public:
 
     WEBKIT_EXPORT WebSerializedScriptValue data() const;
     WEBKIT_EXPORT WebString origin() const;
+
+#if WEBKIT_IMPLEMENTATION
+    explicit WebDOMMessageEvent(const WTF::PassRefPtr& e) : WebDOMEvent(e) { }
+#endif
 };
 
 } // namespace WebKit
diff --git a/Source/WebKit/chromium/public/WebFrameClient.h b/Source/WebKit/chromium/public/WebFrameClient.h
index 0bf3057..94abe83 100644
--- a/Source/WebKit/chromium/public/WebFrameClient.h
+++ b/Source/WebKit/chromium/public/WebFrameClient.h
@@ -31,9 +31,11 @@
 #ifndef WebFrameClient_h
 #define WebFrameClient_h
 
+#include "WebDOMMessageEvent.h"
 #include "WebIconURL.h"
 #include "WebNavigationPolicy.h"
 #include "WebNavigationType.h"
+#include "WebSecurityOrigin.h"
 #include "WebStorageQuotaType.h"
 #include "WebTextDirection.h"
 #include "platform/WebCommon.h"
@@ -50,6 +52,7 @@ class WebApplicationCacheHost;
 class WebApplicationCacheHostClient;
 class WebCookieJar;
 class WebDataSource;
+class WebDOMEvent;
 class WebFormElement;
 class WebFrame;
 class WebIntentServiceInfo;
@@ -58,7 +61,6 @@ class WebMediaPlayer;
 class WebMediaPlayerClient;
 class WebNode;
 class WebPlugin;
-class WebSecurityOrigin;
 class WebSharedWorker;
 class WebStorageQuotaCallbacks;
 class WebString;
@@ -385,6 +387,16 @@ public:
     // the WebFrame starting the activity.
     virtual void dispatchIntent(WebFrame*, const WebIntent&) { }
 
+    // Messages ------------------------------------------------------
+
+    // Notifies the embedder that a postMessage was issued on this frame, and
+    // gives the embedder a chance to handle it instead of WebKit. Returns true
+    // if the embedder handled it.
+    virtual bool willCheckAndDispatchMessageEvent(
+        WebFrame* source,
+        WebSecurityOrigin target,
+        WebDOMMessageEvent) { return false; }
+
 protected:
     ~WebFrameClient() { }
 };
diff --git a/Source/WebKit/chromium/src/FrameLoaderClientImpl.cpp b/Source/WebKit/chromium/src/FrameLoaderClientImpl.cpp
index 905a377..46f96b5 100644
--- a/Source/WebKit/chromium/src/FrameLoaderClientImpl.cpp
+++ b/Source/WebKit/chromium/src/FrameLoaderClientImpl.cpp
@@ -47,6 +47,7 @@
 #include "HTMLAppletElement.h"
 #include "HTMLFormElement.h"  // needed by FormState.h
 #include "HTMLNames.h"
+#include "MessageEvent.h"
 #include "MIMETypeRegistry.h"
 #include "MouseEvent.h"
 #include "Page.h"
@@ -58,6 +59,7 @@
 #include "ResourceLoader.h"
 #include "Settings.h"
 #include "StringExtras.h"
+#include "WebDOMEvent.h"
 #include "WebDataSourceImpl.h"
 #include "WebDevToolsAgentPrivate.h"
 #include "WebDocument.h"
@@ -1617,4 +1619,14 @@ PassRefPtr FrameLoaderClientImpl::createNetworkingContex
     return FrameNetworkingContextImpl::create(m_webFrame->frame());
 }
 
+bool FrameLoaderClientImpl::willCheckAndDispatchMessageEvent(
+    SecurityOrigin* target, MessageEvent* event) const
+{
+    if (!m_webFrame->client())
+        return false;
+
+    return m_webFrame->client()->willCheckAndDispatchMessageEvent(
+        m_webFrame, WebSecurityOrigin(target), WebDOMMessageEvent(event));
+}
+
 } // namespace WebKit
diff --git a/Source/WebKit/chromium/src/FrameLoaderClientImpl.h b/Source/WebKit/chromium/src/FrameLoaderClientImpl.h
index 596b5f4..b1b85ba 100644
--- a/Source/WebKit/chromium/src/FrameLoaderClientImpl.h
+++ b/Source/WebKit/chromium/src/FrameLoaderClientImpl.h
@@ -206,6 +206,7 @@ public:
     virtual void didNotAllowPlugins();
 
     virtual PassRefPtr createNetworkingContext();
+    virtual bool willCheckAndDispatchMessageEvent(WebCore::SecurityOrigin* target, WebCore::MessageEvent*) const;
 
 private:
     void makeDocumentView();
diff --git a/Tools/DumpRenderTree/chromium/LayoutTestController.cpp b/Tools/DumpRenderTree/chromium/LayoutTestController.cpp
index f4baf82..7fc2136 100644
--- a/Tools/DumpRenderTree/chromium/LayoutTestController.cpp
+++ b/Tools/DumpRenderTree/chromium/LayoutTestController.cpp
@@ -250,6 +250,7 @@ LayoutTestController::LayoutTestController(TestShell* shell)
     bindProperty("webHistoryItemCount", &m_webHistoryItemCount);
     bindProperty("titleTextDirection", &m_titleTextDirection);
     bindProperty("platformName", &m_platformName);
+    bindProperty("interceptPostMessage", &m_interceptPostMessage);
 }
 
 LayoutTestController::~LayoutTestController()
@@ -637,6 +638,7 @@ void LayoutTestController::reset()
     m_webHistoryItemCount.set(0);
     m_titleTextDirection.set("ltr");
     m_platformName.set("chromium");
+    m_interceptPostMessage.set(false);
     m_userStyleSheetLocation = WebURL();
     m_isPrinting = false;
 
diff --git a/Tools/DumpRenderTree/chromium/LayoutTestController.h b/Tools/DumpRenderTree/chromium/LayoutTestController.h
index 4d6cd85..71b1b42 100644
--- a/Tools/DumpRenderTree/chromium/LayoutTestController.h
+++ b/Tools/DumpRenderTree/chromium/LayoutTestController.h
@@ -469,6 +469,11 @@ public:
         m_titleTextDirection.set(dir == WebKit::WebTextDirectionLeftToRight ? "ltr" : "rtl");
     }
 
+    bool shouldInterceptPostMessage()
+    {
+        return m_interceptPostMessage.isBool() && m_interceptPostMessage.toBoolean();
+    }
+
     void setIsPrinting(bool value) { m_isPrinting = value; }
     bool isPrinting() { return m_isPrinting; }
 
@@ -680,6 +685,9 @@ private:
     // Bound variable to return the name of this platform (chromium).
     CppVariant m_platformName;
 
+    // Bound variable to set whether postMessages should be intercepted or not
+    CppVariant m_interceptPostMessage;
+
     WebKit::WebURL m_userStyleSheetLocation;
 
     OwnPtr m_speechInputControllerMock;
diff --git a/Tools/DumpRenderTree/chromium/WebViewHost.cpp b/Tools/DumpRenderTree/chromium/WebViewHost.cpp
index 24bd48f..1b0687d 100644
--- a/Tools/DumpRenderTree/chromium/WebViewHost.cpp
+++ b/Tools/DumpRenderTree/chromium/WebViewHost.cpp
@@ -39,6 +39,7 @@
 #include "platform/WebCString.h"
 #include "WebConsoleMessage.h"
 #include "WebContextMenuData.h"
+#include "WebDOMMessageEvent.h"
 #include "WebDataSource.h"
 #include "WebDeviceOrientationClientMock.h"
 #include "platform/WebDragData.h"
@@ -1204,6 +1205,16 @@ void WebViewHost::openFileSystem(WebFrame* frame, WebFileSystem::Type type, long
     webkit_support::OpenFileSystem(frame, type, size, create, callbacks);
 }
 
+bool WebViewHost::willCheckAndDispatchMessageEvent(WebFrame* source, WebSecurityOrigin target, WebDOMMessageEvent event)
+{
+    if (m_shell->layoutTestController()->shouldInterceptPostMessage()) {
+        fputs("intercepted postMessage\n", stdout);
+        return true;
+    }
+
+    return false;
+}
+
 // Public functions -----------------------------------------------------------
 
 WebViewHost::WebViewHost(TestShell* shell)
diff --git a/Tools/DumpRenderTree/chromium/WebViewHost.h b/Tools/DumpRenderTree/chromium/WebViewHost.h
index a2f7bca..0bc4c38 100644
--- a/Tools/DumpRenderTree/chromium/WebViewHost.h
+++ b/Tools/DumpRenderTree/chromium/WebViewHost.h
@@ -214,6 +214,7 @@ class WebViewHost : public WebKit::WebSpellCheckClient, public WebKit::WebViewCl
     virtual void didRunInsecureContent(WebKit::WebFrame*, const WebKit::WebSecurityOrigin&, const WebKit::WebURL&);
     virtual void didDetectXSS(WebKit::WebFrame*, const WebKit::WebURL&, bool didBlockEntirePage);
     virtual void openFileSystem(WebKit::WebFrame*, WebKit::WebFileSystem::Type, long long size, bool create, WebKit::WebFileSystemCallbacks*);
+    virtual bool willCheckAndDispatchMessageEvent(WebKit::WebFrame* source, WebKit::WebSecurityOrigin target, WebKit::WebDOMMessageEvent);
 
     WebKit::WebDeviceOrientationClientMock* deviceOrientationClientMock();
     
-- 
2.7.4