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