Gabriel Ivăncescu : mshtml: Implement targetOrigin for postMessage.

Alexandre Julliard julliard at winehq.org
Wed Aug 10 14:53:21 CDT 2022


Module: wine
Branch: master
Commit: 5b07fb4d568e2cba4c224ad5f62ba5332dd66c7b
URL:    https://gitlab.winehq.org/wine/wine/-/commit/5b07fb4d568e2cba4c224ad5f62ba5332dd66c7b

Author: Gabriel Ivăncescu <gabrielopcode at gmail.com>
Date:   Wed Aug 10 18:07:38 2022 +0300

mshtml: Implement targetOrigin for postMessage.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>

---

 dlls/mshtml/htmlwindow.c          | 70 ++++++++++++++++++++++++++++++++++++++-
 dlls/mshtml/tests/documentmode.js | 53 +++++++++++++++++++++++++++--
 dlls/mshtml/tests/events.js       |  2 +-
 3 files changed, 120 insertions(+), 5 deletions(-)

diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c
index 75f211e4cac..3ab42af0fa4 100644
--- a/dlls/mshtml/htmlwindow.c
+++ b/dlls/mshtml/htmlwindow.c
@@ -25,6 +25,7 @@
 #include "winuser.h"
 #include "ole2.h"
 #include "mshtmdid.h"
+#include "wininet.h"
 #include "shlguid.h"
 #include "shobjidl.h"
 #include "exdispid.h"
@@ -2218,7 +2219,7 @@ static HRESULT WINAPI HTMLWindow6_postMessage(IHTMLWindow6 *iface, BSTR msg, VAR
     HTMLWindow *This = impl_from_IHTMLWindow6(iface);
     VARIANT var, transfer;
 
-    FIXME("(%p)->(%s %s) semi-stub\n", This, debugstr_w(msg), debugstr_variant(&targetOrigin));
+    TRACE("(%p)->(%s %s)\n", This, debugstr_w(msg), debugstr_variant(&targetOrigin));
 
     if(V_VT(&targetOrigin) != VT_BSTR)
         return E_INVALIDARG;
@@ -3155,6 +3156,69 @@ static HRESULT WINAPI window_private_matchMedia(IWineHTMLWindowPrivate *iface, B
     return create_media_query_list(This, media_query, media_query_list);
 }
 
+static HRESULT check_target_origin(HTMLInnerWindow *window, const WCHAR *target_origin)
+{
+    IUri *uri, *target;
+    DWORD port, port2;
+    BSTR bstr, bstr2;
+    HRESULT hres;
+
+    if(!target_origin)
+        return E_INVALIDARG;
+
+    if(!wcscmp(target_origin, L"*"))
+        return S_OK;
+
+    hres = create_uri(target_origin, Uri_CREATE_NOFRAG | Uri_CREATE_NO_DECODE_EXTRA_INFO, &target);
+    if(FAILED(hres))
+        return hres;
+
+    if(!(uri = window->base.outer_window->uri)) {
+        FIXME("window with no URI\n");
+        hres = S_FALSE;
+        goto done;
+    }
+
+    hres = IUri_GetSchemeName(uri, &bstr);
+    if(FAILED(hres))
+        goto done;
+    hres = IUri_GetSchemeName(target, &bstr2);
+    if(SUCCEEDED(hres)) {
+        hres = !wcsicmp(bstr, bstr2) ? S_OK : S_FALSE;
+        SysFreeString(bstr2);
+    }
+    SysFreeString(bstr);
+    if(hres != S_OK)
+        goto done;
+
+    hres = IUri_GetHost(uri, &bstr);
+    if(FAILED(hres))
+        goto done;
+    hres = IUri_GetHost(target, &bstr2);
+    if(SUCCEEDED(hres)) {
+        hres = !wcsicmp(bstr, bstr2) ? S_OK : S_FALSE;
+        SysFreeString(bstr2);
+    }
+    SysFreeString(bstr);
+    if(hres != S_OK)
+        goto done;
+
+    /* Legacy modes ignore port */
+    if(dispex_compat_mode(&window->event_target.dispex) < COMPAT_MODE_IE9)
+        goto done;
+
+    hres = IUri_GetPort(uri, &port);
+    if(FAILED(hres))
+        goto done;
+    hres = IUri_GetPort(target, &port2);
+    if(SUCCEEDED(hres))
+        hres = (port == port2) ? S_OK : S_FALSE;
+
+done:
+    IUri_Release(target);
+    return hres;
+}
+
 static HRESULT WINAPI window_private_postMessage(IWineHTMLWindowPrivate *iface, VARIANT msg, BSTR targetOrigin, VARIANT transfer)
 {
     HTMLWindow *This = impl_from_IWineHTMLWindowPrivateVtbl(iface);
@@ -3168,6 +3232,10 @@ static HRESULT WINAPI window_private_postMessage(IWineHTMLWindowPrivate *iface,
     if(V_VT(&transfer) != VT_EMPTY)
         FIXME("transfer not implemented, ignoring\n");
 
+    hres = check_target_origin(window, targetOrigin);
+    if(hres != S_OK)
+        return SUCCEEDED(hres) ? S_OK : hres;
+
     switch(V_VT(&msg)) {
         case VT_EMPTY:
         case VT_NULL:
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js
index 0ec4785450e..5b746598dba 100644
--- a/dlls/mshtml/tests/documentmode.js
+++ b/dlls/mshtml/tests/documentmode.js
@@ -2082,10 +2082,57 @@ async_test("postMessage", function() {
         onmessage_called = true;
         if(v < 9)
             ok(e === undefined, "e = " + e);
-        else
+        else {
             ok(e.data === (v < 10 ? "10" : 10), "e.data = " + e.data);
-        next_test();
+            next_test();
+        }
+    }
+
+    var invalid = [
+        v < 10 ? { toString: function() { return "http://winetest.example.org"; } } : null,
+        (function() { return "http://winetest.example.org"; }),
+        "winetest.example.org",
+        "example.org",
+        undefined
+    ];
+    for(var i = 0; i < invalid.length; i++) {
+        try {
+            window.postMessage("invalid " + i, invalid[i]);
+            ok(false, "expected exception with targetOrigin " + invalid[i]);
+        }catch(ex) {
+            var n = ex.number >>> 0;
+            todo_wine_if(v >= 10).
+            ok(n === (v < 10 ? 0x80070057 : 0), "postMessage with targetOrigin " + invalid[i] + " threw " + n);
+            if(v >= 10)
+                todo_wine.
+                ok(ex.name === "SyntaxError", "postMessage with targetOrigin " + invalid[i] + " threw " + ex.name);
+        }
     }
-    window.postMessage(10, "*");
+    try {
+        window.postMessage("invalid empty", "");
+        ok(false, "expected exception with empty targetOrigin");
+    }catch(ex) {
+        var n = ex.number >>> 0;
+        ok(n === 0x80070057, "postMessage with empty targetOrigin threw " + n);
+    }
+
+    window.postMessage("wrong port", "http://winetest.example.org:1234");
+    ok(onmessage_called == (v < 9 ? true : false), "onmessage not called with wrong port");
+    onmessage_called = false;
+
+    var not_sent = [
+        "http://winetest.example.com",
+        "ftp://winetest.example.org",
+        "http://wine.example.org",
+        "http://example.org"
+    ];
+    for(var i = 0; i < not_sent.length; i++) {
+        window.postMessage("not_sent " + i, not_sent[i]);
+        ok(onmessage_called == false, "onmessage called with targetOrigin " + not_sent[i]);
+        onmessage_called = false;
+    }
+
+    window.postMessage(10, (v < 10 ? "*" : { toString: function() { return "*"; } }));
     ok(onmessage_called == (v < 9 ? true : false), "onmessage not called");
+    if(v < 9) next_test();
 });
diff --git a/dlls/mshtml/tests/events.js b/dlls/mshtml/tests/events.js
index e67bf07d210..997e583ad20 100644
--- a/dlls/mshtml/tests/events.js
+++ b/dlls/mshtml/tests/events.js
@@ -818,6 +818,6 @@ async_test("message event", function() {
         next_test();
     });
 
-    window.postMessage("test", "http://winetest.example.org");
+    window.postMessage("test", "httP://wineTest.example.org");
     ok(listener_called == false, "listener already called");
 });




More information about the wine-cvs mailing list