From: Gabriel Ivăncescu gabrielopcode@gmail.com
We need the caller ServiceProvider to obtain the source.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlwindow.c | 373 +++++++++++++++------------ dlls/mshtml/mshtml_private_iface.idl | 2 - 2 files changed, 211 insertions(+), 164 deletions(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index fa99c453989..8cefa5e6e6d 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -2234,6 +2234,87 @@ static HRESULT WINAPI HTMLWindow6_get_maxConnectionsPerServer(IHTMLWindow6 *ifac return E_NOTIMPL; }
+static HRESULT check_target_origin(HTMLInnerWindow *window, const WCHAR *target_origin) +{ + BOOL no_port = FALSE; + 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; + } + + bstr = NULL; + hres = IUri_GetSchemeName(uri, &bstr); + if(hres != S_OK) { + SysFreeString(bstr); + goto done; + } + hres = IUri_GetSchemeName(target, &bstr2); + if(SUCCEEDED(hres)) { + if(hres == S_OK && wcsicmp(bstr, bstr2)) + hres = S_FALSE; + SysFreeString(bstr2); + } + SysFreeString(bstr); + if(hres != S_OK) + goto done; + + bstr = NULL; + hres = IUri_GetHost(uri, &bstr); + if(hres != S_OK) { + SysFreeString(bstr); + goto done; + } + hres = IUri_GetHost(target, &bstr2); + if(SUCCEEDED(hres)) { + if(hres == S_OK && wcsicmp(bstr, bstr2)) + hres = 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(hres != S_OK) { + if(FAILED(hres)) + goto done; + no_port = TRUE; /* some protocols don't have ports (e.g. res) */ + } + hres = IUri_GetPort(target, &port2); + if(hres != S_OK) { + if(FAILED(hres)) + goto done; + if(no_port) + hres = S_OK; + }else if(no_port || port != port2) { + hres = S_FALSE; + } + +done: + IUri_Release(target); + return hres; +} + struct post_message_task { event_task_t header; DOMEvent *event; @@ -2251,6 +2332,77 @@ static void post_message_destr(event_task_t *_task) IDOMEvent_Release(&task->event->IDOMEvent_iface); }
+static HRESULT post_message(HTMLInnerWindow *window, VARIANT msg, BSTR targetOrigin, VARIANT transfer, + IServiceProvider *caller, compat_mode_t compat_mode) +{ + DOMEvent *event; + HRESULT hres; + + if(V_VT(&transfer) != VT_EMPTY && V_VT(&transfer) != VT_ERROR) + 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: + case VT_VOID: + case VT_I1: + case VT_I2: + case VT_I4: + case VT_I8: + case VT_UI1: + case VT_UI2: + case VT_UI4: + case VT_UI8: + case VT_INT: + case VT_UINT: + case VT_R4: + case VT_R8: + case VT_BOOL: + case VT_BSTR: + case VT_CY: + case VT_DATE: + case VT_DECIMAL: + case VT_HRESULT: + break; + case VT_ERROR: + V_VT(&msg) = VT_EMPTY; + break; + default: + FIXME("Unsupported vt %d\n", V_VT(&msg)); + return E_NOTIMPL; + } + + if(!window->doc) { + FIXME("No document\n"); + return E_FAIL; + } + + hres = create_message_event(window->doc, &msg, &event); + if(FAILED(hres)) + return hres; + + if(compat_mode >= COMPAT_MODE_IE9) { + struct post_message_task *task; + if(!(task = malloc(sizeof(*task)))) { + IDOMEvent_Release(&event->IDOMEvent_iface); + return E_OUTOFMEMORY; + } + + /* Because message events can be sent to different windows, they get blocked by any context */ + task->header.thread_blocked = TRUE; + task->event = event; + return push_event_task(&task->header, window, post_message_proc, post_message_destr, window->task_magic); + } + + dispatch_event(&window->event_target, event); + IDOMEvent_Release(&event->IDOMEvent_iface); + return S_OK; +} + static HRESULT WINAPI HTMLWindow6_postMessage(IHTMLWindow6 *iface, BSTR msg, VARIANT targetOrigin) { HTMLWindow *This = impl_from_IHTMLWindow6(iface); @@ -2264,7 +2416,8 @@ static HRESULT WINAPI HTMLWindow6_postMessage(IHTMLWindow6 *iface, BSTR msg, VAR V_VT(&var) = VT_BSTR; V_BSTR(&var) = msg; V_VT(&transfer) = VT_EMPTY; - return IWineHTMLWindowPrivate_postMessage(&This->IWineHTMLWindowPrivate_iface, var, V_BSTR(&targetOrigin), transfer); + return post_message(This->inner_window, var, V_BSTR(&targetOrigin), transfer, NULL, + dispex_compat_mode(&This->inner_window->event_target.dispex)); }
static HRESULT WINAPI HTMLWindow6_toStaticHTML(IHTMLWindow6 *iface, BSTR bstrHTML, BSTR *pbstrStaticHTML) @@ -3197,162 +3350,6 @@ 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) -{ - BOOL no_port = FALSE; - 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; - } - - bstr = NULL; - hres = IUri_GetSchemeName(uri, &bstr); - if(hres != S_OK) { - SysFreeString(bstr); - goto done; - } - hres = IUri_GetSchemeName(target, &bstr2); - if(SUCCEEDED(hres)) { - if(hres == S_OK && wcsicmp(bstr, bstr2)) - hres = S_FALSE; - SysFreeString(bstr2); - } - SysFreeString(bstr); - if(hres != S_OK) - goto done; - - bstr = NULL; - hres = IUri_GetHost(uri, &bstr); - if(hres != S_OK) { - SysFreeString(bstr); - goto done; - } - hres = IUri_GetHost(target, &bstr2); - if(SUCCEEDED(hres)) { - if(hres == S_OK && wcsicmp(bstr, bstr2)) - hres = 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(hres != S_OK) { - if(FAILED(hres)) - goto done; - no_port = TRUE; /* some protocols don't have ports (e.g. res) */ - } - hres = IUri_GetPort(target, &port2); - if(hres != S_OK) { - if(FAILED(hres)) - goto done; - if(no_port) - hres = S_OK; - }else if(no_port || port != port2) { - hres = 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); - HTMLInnerWindow *window = This->inner_window; - DOMEvent *event; - HRESULT hres; - - TRACE("iface %p, msg %s, targetOrigin %s, transfer %s\n", iface, debugstr_variant(&msg), - debugstr_w(targetOrigin), debugstr_variant(&transfer)); - - if(V_VT(&transfer) != VT_EMPTY && V_VT(&transfer) != VT_ERROR) - 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: - case VT_VOID: - case VT_I1: - case VT_I2: - case VT_I4: - case VT_I8: - case VT_UI1: - case VT_UI2: - case VT_UI4: - case VT_UI8: - case VT_INT: - case VT_UINT: - case VT_R4: - case VT_R8: - case VT_BOOL: - case VT_BSTR: - case VT_CY: - case VT_DATE: - case VT_DECIMAL: - case VT_HRESULT: - break; - case VT_ERROR: - V_VT(&msg) = VT_EMPTY; - break; - default: - FIXME("Unsupported vt %d\n", V_VT(&msg)); - return E_NOTIMPL; - } - - if(!window->doc) { - FIXME("No document\n"); - return E_FAIL; - } - - hres = create_message_event(window->doc, &msg, &event); - if(FAILED(hres)) - return hres; - - if(dispex_compat_mode(&window->event_target.dispex) >= COMPAT_MODE_IE9) { - struct post_message_task *task; - if(!(task = malloc(sizeof(*task)))) { - IDOMEvent_Release(&event->IDOMEvent_iface); - return E_OUTOFMEMORY; - } - - /* Because message events can be sent to different windows, they get blocked by any context */ - task->header.thread_blocked = TRUE; - task->event = event; - return push_event_task(&task->header, window, post_message_proc, post_message_destr, window->task_magic); - } - - dispatch_event(&window->event_target, event); - IDOMEvent_Release(&event->IDOMEvent_iface); - return S_OK; -} - static HRESULT WINAPI window_private_get_console(IWineHTMLWindowPrivate *iface, IDispatch **console) { HTMLWindow *This = impl_from_IWineHTMLWindowPrivateVtbl(iface); @@ -3401,7 +3398,6 @@ static const IWineHTMLWindowPrivateVtbl WineHTMLWindowPrivateVtbl = { window_private_cancelAnimationFrame, window_private_get_console, window_private_matchMedia, - window_private_postMessage, window_private_get_MutationObserver };
@@ -4219,6 +4215,57 @@ static HRESULT IHTMLWindow3_setTimeout_hook(DispatchEx *dispex, WORD flags, DISP return dispex_call_builtin(dispex, DISPID_IHTMLWINDOW3_SETTIMEOUT, &new_dp, res, ei, caller); }
+static HRESULT IHTMLWindow6_postMessage_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res, + EXCEPINFO *ei, IServiceProvider *caller) +{ + HTMLInnerWindow *This = impl_from_DispatchEx(dispex); + BSTR targetOrigin, converted_msg = NULL; + VARIANT msg, transfer, converted; + compat_mode_t compat_mode; + HRESULT hres; + + if(!(flags & DISPATCH_METHOD) || dp->cArgs < 2 || dp->cNamedArgs) + return S_FALSE; + compat_mode = dispex_compat_mode(&This->event_target.dispex); + + msg = dp->rgvarg[dp->cArgs - 1]; + V_VT(&transfer) = VT_EMPTY; + if(compat_mode >= COMPAT_MODE_IE10 && dp->cArgs > 2) + transfer = dp->rgvarg[dp->cArgs - 3]; + + TRACE("(%p)->(msg %s, targetOrigin %s, transfer %s)\n", This, debugstr_variant(&msg), + debugstr_variant(&dp->rgvarg[dp->cArgs - 2]), debugstr_variant(&transfer)); + + if(compat_mode < COMPAT_MODE_IE10 && V_VT(&msg) != VT_BSTR) { + hres = change_type(&msg, &dp->rgvarg[dp->cArgs - 1], VT_BSTR, caller); + if(FAILED(hres)) + return hres; + converted_msg = V_BSTR(&msg); + } + + if(V_VT(&dp->rgvarg[dp->cArgs - 2]) == VT_BSTR) { + targetOrigin = V_BSTR(&dp->rgvarg[dp->cArgs - 2]); + V_BSTR(&converted) = NULL; + }else { + if(compat_mode < COMPAT_MODE_IE10) { + SysFreeString(converted_msg); + return E_INVALIDARG; + } + hres = change_type(&converted, &dp->rgvarg[dp->cArgs - 2], VT_BSTR, caller); + if(FAILED(hres)) { + SysFreeString(converted_msg); + return hres; + } + targetOrigin = V_BSTR(&converted); + } + + hres = post_message(This, msg, targetOrigin, transfer, caller, compat_mode); + + SysFreeString(V_BSTR(&converted)); + SysFreeString(converted_msg); + return hres; +} + static void HTMLWindow_init_dispex_info(dispex_data_t *info, compat_mode_t compat_mode) { static const dispex_hook_t window2_hooks[] = { @@ -4244,6 +4291,10 @@ static void HTMLWindow_init_dispex_info(dispex_data_t *info, compat_mode_t compa {DISPID_IHTMLWINDOW4_CREATEPOPUP, NULL}, {DISPID_UNKNOWN} }; + static const dispex_hook_t window6_hooks[] = { + {DISPID_IHTMLWINDOW6_POSTMESSAGE, IHTMLWindow6_postMessage_hook}, + {DISPID_UNKNOWN} + };
/* Hide props not available in IE10 */ static const dispex_hook_t private_ie10_hooks[] = { @@ -4259,6 +4310,7 @@ static void HTMLWindow_init_dispex_info(dispex_data_t *info, compat_mode_t compa dispex_info_add_interface(info, IWineHTMLWindowPrivate_tid, compat_mode >= COMPAT_MODE_IE11 ? NULL : private_ie10_hooks);
+ dispex_info_add_interface(info, IHTMLWindow6_tid, window6_hooks); dispex_info_add_interface(info, IHTMLWindow5_tid, NULL); dispex_info_add_interface(info, IHTMLWindow4_tid, compat_mode >= COMPAT_MODE_IE11 ? window4_ie11_hooks : NULL); dispex_info_add_interface(info, IHTMLWindow3_tid, compat_mode >= COMPAT_MODE_IE11 ? window3_ie11_hooks : window3_hooks); @@ -4290,10 +4342,7 @@ static const event_target_vtbl_t HTMLWindow_event_target_vtbl = { .set_current_event = HTMLWindow_set_current_event };
-static const tid_t HTMLWindow_iface_tids[] = { - IHTMLWindow6_tid, - 0 -}; +static const tid_t HTMLWindow_iface_tids[] = { 0 };
static dispex_static_data_t HTMLWindow_dispex = { "Window", diff --git a/dlls/mshtml/mshtml_private_iface.idl b/dlls/mshtml/mshtml_private_iface.idl index e4d97361ce1..503593d1c25 100644 --- a/dlls/mshtml/mshtml_private_iface.idl +++ b/dlls/mshtml/mshtml_private_iface.idl @@ -131,8 +131,6 @@ interface IWineHTMLWindowPrivate : IDispatch HRESULT console([retval, out] IDispatch **console); [id(53)] HRESULT matchMedia([in] BSTR media_query, [retval, out] IDispatch **media_query_list); - [id(54)] - HRESULT postMessage([in] VARIANT msg, [in] BSTR targetOrigin, [in, optional] VARIANT transfer); [propget, id(DISPID_IWINEHTMLWINDOWPRIVATE_MUTATIONOBSERVER)] HRESULT MutationObserver([retval, out] IDispatch **observer_ctor); }
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlevent.c | 31 +- dlls/mshtml/htmlevent.h | 2 +- dlls/mshtml/htmlwindow.c | 77 +++- dlls/mshtml/tests/documentmode.js | 1 + dlls/mshtml/tests/events.c | 604 ++++++++++++++++++++++++++++++ dlls/mshtml/tests/events.js | 14 +- 6 files changed, 713 insertions(+), 16 deletions(-)
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index 36a7fa6c83c..4e1cfd2b695 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -1841,11 +1841,19 @@ static HRESULT WINAPI HTMLEventObj5_get_data(IHTMLEventObj5 *iface, BSTR *p) static HRESULT WINAPI HTMLEventObj5_get_source(IHTMLEventObj5 *iface, IDispatch **p) { HTMLEventObj *This = impl_from_IHTMLEventObj5(iface); + IDOMMessageEvent *message_event; + HRESULT hres;
- FIXME("(%p)->(%p)\n", This, p); + TRACE("(%p)->(%p)\n", This, p);
- *p = NULL; - return S_OK; + if(!This->event || FAILED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMessageEvent, (void**)&message_event))) { + *p = NULL; + return S_OK; + } + + hres = IDOMMessageEvent_get_source(message_event, (IHTMLWindow2**)p); + IDOMMessageEvent_Release(message_event); + return hres; }
static HRESULT WINAPI HTMLEventObj5_put_origin(IHTMLEventObj5 *iface, BSTR v) @@ -3652,6 +3660,7 @@ static void DOMCustomEvent_destructor(DispatchEx *dispex) typedef struct { DOMEvent event; IDOMMessageEvent IDOMMessageEvent_iface; + IHTMLWindow2 *source; VARIANT data; } DOMMessageEvent;
@@ -3746,8 +3755,12 @@ static HRESULT WINAPI DOMMessageEvent_get_origin(IDOMMessageEvent *iface, BSTR * static HRESULT WINAPI DOMMessageEvent_get_source(IDOMMessageEvent *iface, IHTMLWindow2 **p) { DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, p); + + if((*p = This->source)) + IHTMLWindow2_AddRef(This->source); + return S_OK; }
static HRESULT WINAPI DOMMessageEvent_initMessageEvent(IDOMMessageEvent *iface, BSTR type, VARIANT_BOOL can_bubble, @@ -3793,6 +3806,8 @@ static void DOMMessageEvent_traverse(DispatchEx *dispex, nsCycleCollectionTraver DOMMessageEvent *message_event = DOMMessageEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex)); DOMEvent_traverse(&message_event->event.dispex, cb); traverse_variant(&message_event->data, "data", cb); + if(message_event->source) + note_cc_edge((nsISupports*)message_event->source, "MessageEvent.source", cb); }
static void DOMMessageEvent_unlink(DispatchEx *dispex) @@ -3800,6 +3815,7 @@ static void DOMMessageEvent_unlink(DispatchEx *dispex) DOMMessageEvent *message_event = DOMMessageEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex)); DOMEvent_unlink(&message_event->event.dispex); unlink_variant(&message_event->data); + unlink_ref(&message_event->source); }
static void DOMMessageEvent_destructor(DispatchEx *dispex) @@ -4575,7 +4591,7 @@ HRESULT create_document_event(HTMLDocumentNode *doc, eventid_t event_id, DOMEven return S_OK; }
-HRESULT create_message_event(HTMLDocumentNode *doc, VARIANT *data, DOMEvent **ret) +HRESULT create_message_event(HTMLDocumentNode *doc, IHTMLWindow2 *source, VARIANT *data, DOMEvent **ret) { DOMMessageEvent *message_event; DOMEvent *event; @@ -4593,6 +4609,9 @@ HRESULT create_message_event(HTMLDocumentNode *doc, VARIANT *data, DOMEvent **re return hres; }
+ message_event->source = source; + IHTMLWindow2_AddRef(message_event->source); + *ret = event; return S_OK; } diff --git a/dlls/mshtml/htmlevent.h b/dlls/mshtml/htmlevent.h index 2d86ba08782..645e99a4c19 100644 --- a/dlls/mshtml/htmlevent.h +++ b/dlls/mshtml/htmlevent.h @@ -116,7 +116,7 @@ void dispatch_event(EventTarget*,DOMEvent*); HRESULT create_document_event(HTMLDocumentNode*,eventid_t,DOMEvent**); HRESULT create_document_event_str(HTMLDocumentNode*,const WCHAR*,IDOMEvent**); HRESULT create_event_from_nsevent(nsIDOMEvent*,compat_mode_t,DOMEvent**); -HRESULT create_message_event(HTMLDocumentNode*,VARIANT*,DOMEvent**); +HRESULT create_message_event(HTMLDocumentNode*,IHTMLWindow2*,VARIANT*,DOMEvent**); HRESULT create_storage_event(HTMLDocumentNode*,BSTR,BSTR,BSTR,const WCHAR*,BOOL,DOMEvent**);
void init_nsevents(HTMLDocumentNode*); diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 8cefa5e6e6d..5a4707153e5 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -28,6 +28,7 @@ #include "wininet.h" #include "shlguid.h" #include "shobjidl.h" +#include "activscp.h" #include "exdispid.h"
#define NO_SHLWAPI_REG @@ -2315,6 +2316,61 @@ done: return hres; }
+static IHTMLWindow2 *get_source_window(IServiceProvider *caller, compat_mode_t compat_mode) +{ + IOleCommandTarget *cmdtarget, *parent_cmdtarget; + IServiceProvider *parent; + IHTMLWindow2 *source; + HRESULT hres; + VARIANT var; + + if(!caller) + return NULL; + + hres = IServiceProvider_QueryService(caller, &IID_IActiveScriptSite, &IID_IOleCommandTarget, (void**)&cmdtarget); + if(hres != S_OK) + cmdtarget = NULL; + + if(compat_mode < COMPAT_MODE_IE9) { + /* Legacy modes query caller unconditionally, and use it instead, if it has a command target */ + hres = IServiceProvider_QueryService(caller, &SID_GetCaller, &IID_IServiceProvider, (void**)&parent); + if(hres == S_OK && parent) { + hres = IServiceProvider_QueryService(parent, &IID_IActiveScriptSite, &IID_IOleCommandTarget, (void**)&parent_cmdtarget); + IServiceProvider_Release(parent); + if(hres == S_OK && parent_cmdtarget) { + if(cmdtarget) + IOleCommandTarget_Release(cmdtarget); + cmdtarget = parent_cmdtarget; + } + } + } + + if(!cmdtarget) + return NULL; + + V_VT(&var) = VT_EMPTY; + hres = IOleCommandTarget_Exec(cmdtarget, &CGID_ScriptSite, CMDID_SCRIPTSITE_SECURITY_WINDOW, 0, NULL, &var); + IOleCommandTarget_Release(cmdtarget); + if(hres != S_OK) + return NULL; + + /* Native assumes it's VT_DISPATCH and doesn't check it */ + hres = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IHTMLWindow2, (void**)&source); + IDispatch_Release(V_DISPATCH(&var)); + if(hres != S_OK) + return NULL; + + if(compat_mode < COMPAT_MODE_IE9) { + IHTMLWindow2 *tmp; + hres = IHTMLWindow2_get_self(source, &tmp); + if(hres == S_OK) { + IHTMLWindow2_Release(source); + source = tmp; + } + } + return source; +} + struct post_message_task { event_task_t header; DOMEvent *event; @@ -2335,6 +2391,7 @@ static void post_message_destr(event_task_t *_task) static HRESULT post_message(HTMLInnerWindow *window, VARIANT msg, BSTR targetOrigin, VARIANT transfer, IServiceProvider *caller, compat_mode_t compat_mode) { + IHTMLWindow2 *source; DOMEvent *event; HRESULT hres;
@@ -2345,6 +2402,13 @@ static HRESULT post_message(HTMLInnerWindow *window, VARIANT msg, BSTR targetOri if(hres != S_OK) return SUCCEEDED(hres) ? S_OK : hres;
+ source = get_source_window(caller, compat_mode); + if(!source) { + if(compat_mode < COMPAT_MODE_IE9) + return E_ABORT; + IHTMLWindow2_AddRef(source = &window->base.outer_window->base.IHTMLWindow2_iface); + } + switch(V_VT(&msg)) { case VT_EMPTY: case VT_NULL: @@ -2373,15 +2437,18 @@ static HRESULT post_message(HTMLInnerWindow *window, VARIANT msg, BSTR targetOri break; default: FIXME("Unsupported vt %d\n", V_VT(&msg)); + IHTMLWindow2_Release(source); return E_NOTIMPL; }
if(!window->doc) { FIXME("No document\n"); + IHTMLWindow2_Release(source); return E_FAIL; }
- hres = create_message_event(window->doc, &msg, &event); + hres = create_message_event(window->doc, source, &msg, &event); + IHTMLWindow2_Release(source); if(FAILED(hres)) return hres;
@@ -2406,18 +2473,14 @@ static HRESULT post_message(HTMLInnerWindow *window, VARIANT msg, BSTR targetOri static HRESULT WINAPI HTMLWindow6_postMessage(IHTMLWindow6 *iface, BSTR msg, VARIANT targetOrigin) { HTMLWindow *This = impl_from_IHTMLWindow6(iface); - VARIANT var, transfer;
TRACE("(%p)->(%s %s)\n", This, debugstr_w(msg), debugstr_variant(&targetOrigin));
if(V_VT(&targetOrigin) != VT_BSTR) return E_INVALIDARG;
- V_VT(&var) = VT_BSTR; - V_BSTR(&var) = msg; - V_VT(&transfer) = VT_EMPTY; - return post_message(This->inner_window, var, V_BSTR(&targetOrigin), transfer, NULL, - dispex_compat_mode(&This->inner_window->event_target.dispex)); + /* This can't obtain the source, and never works even in IE9+ modes... */ + return E_ABORT; }
static HRESULT WINAPI HTMLWindow6_toStaticHTML(IHTMLWindow6 *iface, BSTR bstrHTML, BSTR *pbstrStaticHTML) diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 9f46de12466..bec247b42d1 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -2928,6 +2928,7 @@ async_test("postMessage", function() { ok(e === undefined, "e = " + e); else { ok(e.data === (v < 10 ? "10" : 10), "e.data = " + e.data); + ok(e.source === window, "e.source = " + e.source); next_test(); } } diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index bea5e1598a8..aa1a60365f2 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -26,6 +26,7 @@ #include "windef.h" #include "winbase.h" #include "ole2.h" +#include "activscp.h" #include "mshtml.h" #include "mshtmdid.h" #include "mshtmhst.h" @@ -100,6 +101,7 @@ DEFINE_EXPECT(submit_onclick_attached_check_cancel); DEFINE_EXPECT(submit_onclick_setret); DEFINE_EXPECT(elem2_cp_onclick); DEFINE_EXPECT(iframe_onload); +DEFINE_EXPECT(onmessage); DEFINE_EXPECT(visibilitychange); DEFINE_EXPECT(onbeforeunload); DEFINE_EXPECT(iframe_onbeforeunload); @@ -115,6 +117,15 @@ DEFINE_EXPECT(doc2_onstoragecommit); DEFINE_EXPECT(window2_onstorage); DEFINE_EXPECT(async_xhr_done); DEFINE_EXPECT(sync_xhr_done); +DEFINE_EXPECT(QS_IActiveScriptSite); +DEFINE_EXPECT(QS_IActiveScriptSite_parent); +DEFINE_EXPECT(QS_IActiveScriptSite_parent2); +DEFINE_EXPECT(QS_IActiveScriptSite_parent3); +DEFINE_EXPECT(QS_IActiveScriptSite_parent4); +DEFINE_EXPECT(QS_GetCaller); +DEFINE_EXPECT(QS_GetCaller_parent2); +DEFINE_EXPECT(QS_GetCaller_parent3); +DEFINE_EXPECT(cmdtarget_Exec);
static HWND container_hwnd = NULL; static IHTMLWindow2 *window; @@ -173,6 +184,14 @@ static const char input_doc_str[] = static const char iframe_doc_str[] = "<html><body><iframe id="ifr">Testing</iframe></body></html>";
+static const char iframe_doc_ie9_str[] = + "<html><head><meta http-equiv="x-ua-compatible" content="IE=9" /></head>" + "<body><iframe id="ifr">Testing</iframe></body></html>"; + +static const char iframe_doc_ie11_str[] = + "<html><head><meta http-equiv="x-ua-compatible" content="IE=11" /></head>" + "<body><iframe id="ifr">Testing</iframe></body></html>"; + static void navigate(IHTMLDocument2*,const WCHAR*);
static BOOL iface_cmp(void *iface1, void *iface2) @@ -1486,6 +1505,80 @@ static HRESULT WINAPI iframe_onreadystatechange(IDispatchEx *iface, DISPID id, L
EVENT_HANDLER_FUNC_OBJ(iframe_onreadystatechange);
+static IHTMLWindow2 *onmessage_source; + +static HRESULT WINAPI onmessage(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + IHTMLWindow2 *source, *self; + HRESULT hres; + BSTR bstr; + + CHECK_EXPECT(onmessage); + + if(document_mode < 9) { + IHTMLEventObj5 *event_obj5; + IHTMLEventObj *event_obj; + IDispatch *disp; + + hres = IHTMLWindow2_get_event(window, &event_obj); + ok(hres == S_OK, "get_event failed: %08lx\n", hres); + + hres = IHTMLEventObj_get_type(event_obj, &bstr); + ok(hres == S_OK, "get_type failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"message"), "event type = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + hres = IHTMLEventObj_QueryInterface(event_obj, &IID_IHTMLEventObj5, (void**)&event_obj5); + ok(hres == S_OK, "Could not get IHTMLEventObj5: %08lx\n", hres); + IHTMLEventObj_Release(event_obj); + + hres = IHTMLEventObj5_get_url(event_obj5, &bstr); + ok(hres == S_OK, "get_url failed: %08lx\n", hres); + ok(!bstr, "url = %s\n", wine_dbgstr_w(bstr)); + + hres = IHTMLEventObj5_get_source(event_obj5, &disp); + ok(hres == S_OK, "get_source failed: %08lx\n", hres); + + hres = IDispatch_QueryInterface(disp, &IID_IHTMLWindow2, (void**)&source); + ok(hres == S_OK, "Could not get IHTMLWindow2: %08lx\n", hres); + IDispatch_Release(disp); + + hres = IHTMLWindow2_get_self(onmessage_source, &self); + ok(hres == S_OK, "get_self failed: %08lx\n", hres); + ok(source == self, "source != onmessage_source.self\n"); + IHTMLWindow2_Release(source); + IHTMLWindow2_Release(self); + + bstr = SysAllocString(L"foobar"); + hres = IHTMLEventObj5_put_url(event_obj5, bstr); + ok(hres == DISP_E_MEMBERNOTFOUND, "put_url returned: %08lx\n", hres); + SysFreeString(bstr); + + IHTMLEventObj5_Release(event_obj5); + }else { + IDOMMessageEvent *msg; + + hres = IDispatch_QueryInterface(V_DISPATCH(&pdp->rgvarg[1]), &IID_IDOMMessageEvent, (void**)&msg); + ok(hres == S_OK, "Could not get IDOMMessageEvent: %08lx\n", hres); + + hres = IDOMMessageEvent_get_data(msg, &bstr); + ok(hres == S_OK, "get_data failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"foobar"), "data = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + hres = IDOMMessageEvent_get_source(msg, &source); + ok(hres == S_OK, "get_source failed: %08lx\n", hres); + ok(source == onmessage_source, "source != onmessage_source\n"); + IHTMLWindow2_Release(source); + + IDOMMessageEvent_Release(msg); + } + return S_OK; +} + +EVENT_HANDLER_FUNC_OBJ(onmessage); + static HRESULT WINAPI onvisibilitychange(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { @@ -1891,6 +1984,359 @@ static void pump_msgs(BOOL *b) } }
+static IOleCommandTarget cmdtarget, cmdtarget_stub; + +static HRESULT WINAPI cmdtarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IOleCommandTarget)) + *ppv = &cmdtarget; + else { + ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + return S_OK; +} + +static ULONG WINAPI cmdtarget_AddRef(IOleCommandTarget *iface) +{ + return 2; +} + +static ULONG WINAPI cmdtarget_Release(IOleCommandTarget *iface) +{ + return 1; +} + +static HRESULT WINAPI cmdtarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup, + ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText) +{ + ok(0, "unexpected call\n"); + return OLECMDERR_E_UNKNOWNGROUP; +} + +static HRESULT WINAPI cmdtarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup, + DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) +{ + CHECK_EXPECT2(cmdtarget_Exec); + ok(pguidCmdGroup && IsEqualGUID(pguidCmdGroup, &CGID_ScriptSite), "pguidCmdGroup = %s\n", wine_dbgstr_guid(pguidCmdGroup)); + ok(nCmdID == CMDID_SCRIPTSITE_SECURITY_WINDOW, "nCmdID = %lu\n", nCmdID); + ok(!nCmdexecopt, "nCmdexecopt = %lu\n", nCmdexecopt); + ok(!pvaIn, "pvaIn != NULL\n"); + ok(pvaOut != NULL, "pvaOut = NULL\n"); + + /* Native ignores the VT and assumes VT_DISPATCH, and releases it + without VariantClear, since it crashes without AddRef below... */ + V_VT(pvaOut) = VT_NULL; + V_DISPATCH(pvaOut) = (IDispatch*)onmessage_source; + IDispatch_AddRef(V_DISPATCH(pvaOut)); + return S_OK; +} + +static const IOleCommandTargetVtbl cmdtarget_vtbl = { + cmdtarget_QueryInterface, + cmdtarget_AddRef, + cmdtarget_Release, + cmdtarget_QueryStatus, + cmdtarget_Exec +}; + +static IOleCommandTarget cmdtarget = { &cmdtarget_vtbl }; + +static HRESULT WINAPI cmdtarget_stub_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IOleCommandTarget)) + *ppv = &cmdtarget_stub; + else { + ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + return S_OK; +} + +static HRESULT WINAPI cmdtarget_stub_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup, + ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText) +{ + ok(0, "unexpected call\n"); + return OLECMDERR_E_UNKNOWNGROUP; +} + +static HRESULT WINAPI cmdtarget_stub_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup, + DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) +{ + ok(0, "unexpected call\n"); + return OLECMDERR_E_UNKNOWNGROUP; +} + +static const IOleCommandTargetVtbl cmdtarget_stub_vtbl = { + cmdtarget_stub_QueryInterface, + cmdtarget_AddRef, + cmdtarget_Release, + cmdtarget_stub_QueryStatus, + cmdtarget_stub_Exec +}; + +static IOleCommandTarget cmdtarget_stub = { &cmdtarget_stub_vtbl }; + +static IServiceProvider caller_sp, caller_sp_parent, caller_sp_stub, caller_sp2, caller_sp2_parent, caller_sp2_parent3; + +static HRESULT WINAPI caller_sp_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IServiceProvider)) + *ppv = &caller_sp; + else { + ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + return S_OK; +} + +static ULONG WINAPI caller_sp_AddRef(IServiceProvider *iface) +{ + return 2; +} + +static ULONG WINAPI caller_sp_Release(IServiceProvider *iface) +{ + return 1; +} + +static HRESULT WINAPI caller_sp_QueryService(IServiceProvider *iface, REFGUID guidService, + REFIID riid, void **ppv) +{ + if(IsEqualGUID(guidService, &IID_IActiveScriptSite)) { + CHECK_EXPECT2(QS_IActiveScriptSite); + ok(IsEqualGUID(riid, &IID_IOleCommandTarget), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = (document_mode < 9) ? NULL : &cmdtarget; + return (document_mode < 9) ? E_NOINTERFACE : S_OK; + } + + if(IsEqualGUID(guidService, &SID_GetCaller)) { + CHECK_EXPECT(QS_GetCaller); + SET_EXPECT(QS_IActiveScriptSite_parent); + ok(IsEqualGUID(riid, &IID_IServiceProvider), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = &caller_sp_parent; + return S_OK; + } + + ok(0, "unexpected service %s\n", wine_dbgstr_guid(guidService)); + *ppv = NULL; + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl caller_sp_vtbl = { + caller_sp_QueryInterface, + caller_sp_AddRef, + caller_sp_Release, + caller_sp_QueryService +}; + +static IServiceProvider caller_sp = { &caller_sp_vtbl }; + +static HRESULT WINAPI caller_sp_parent_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IServiceProvider)) + *ppv = &caller_sp_parent; + else { + ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + return S_OK; +} + +static HRESULT WINAPI caller_sp_parent_QueryService(IServiceProvider *iface, REFGUID guidService, + REFIID riid, void **ppv) +{ + if(IsEqualGUID(guidService, &IID_IActiveScriptSite)) { + CHECK_EXPECT(QS_IActiveScriptSite_parent); + ok(IsEqualGUID(riid, &IID_IOleCommandTarget), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + + ok(0, "unexpected service %s\n", wine_dbgstr_guid(guidService)); + *ppv = NULL; + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl caller_sp_parent_vtbl = { + caller_sp_parent_QueryInterface, + caller_sp_AddRef, + caller_sp_Release, + caller_sp_parent_QueryService +}; + +static IServiceProvider caller_sp_parent = { &caller_sp_parent_vtbl }; + +static HRESULT WINAPI caller_sp_stub_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IServiceProvider)) + *ppv = &caller_sp_stub; + else { + ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + return S_OK; +} + +static HRESULT WINAPI caller_sp_stub_QueryService(IServiceProvider *iface, REFGUID guidService, + REFIID riid, void **ppv) +{ + if(IsEqualGUID(guidService, &IID_IActiveScriptSite)) { + CHECK_EXPECT2(QS_IActiveScriptSite); + *ppv = NULL; + return E_NOINTERFACE; + } + + if(IsEqualGUID(guidService, &SID_GetCaller)) { + CHECK_EXPECT(QS_GetCaller); + ok(IsEqualGUID(riid, &IID_IServiceProvider), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return S_OK; + } + + ok(0, "unexpected service %s\n", wine_dbgstr_guid(guidService)); + *ppv = NULL; + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl caller_sp_stub_vtbl = { + caller_sp_stub_QueryInterface, + caller_sp_AddRef, + caller_sp_Release, + caller_sp_stub_QueryService +}; + +static IServiceProvider caller_sp_stub = { &caller_sp_stub_vtbl }; + +static HRESULT WINAPI caller_sp2_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IServiceProvider)) + *ppv = &caller_sp2; + else { + ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + return S_OK; +} + +static HRESULT WINAPI caller_sp2_QueryService(IServiceProvider *iface, REFGUID guidService, + REFIID riid, void **ppv) +{ + if(IsEqualGUID(guidService, &IID_IActiveScriptSite)) { + CHECK_EXPECT2(QS_IActiveScriptSite_parent2); + ok(IsEqualGUID(riid, &IID_IOleCommandTarget), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = (document_mode < 9) ? &cmdtarget_stub : &cmdtarget; + return S_OK; + } + + if(IsEqualGUID(guidService, &SID_GetCaller)) { + CHECK_EXPECT(QS_GetCaller_parent2); + SET_EXPECT(QS_IActiveScriptSite_parent3); + ok(IsEqualGUID(riid, &IID_IServiceProvider), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = &caller_sp2_parent; + return S_OK; + } + + ok(0, "unexpected service %s\n", wine_dbgstr_guid(guidService)); + *ppv = NULL; + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl caller_sp2_vtbl = { + caller_sp2_QueryInterface, + caller_sp_AddRef, + caller_sp_Release, + caller_sp2_QueryService +}; + +static IServiceProvider caller_sp2 = { &caller_sp2_vtbl }; + +static HRESULT WINAPI caller_sp2_parent_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IServiceProvider)) + *ppv = &caller_sp2_parent; + else { + ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + return S_OK; +} + +static HRESULT WINAPI caller_sp2_parent_QueryService(IServiceProvider *iface, REFGUID guidService, + REFIID riid, void **ppv) +{ + if(IsEqualGUID(guidService, &IID_IActiveScriptSite)) { + CHECK_EXPECT2(QS_IActiveScriptSite_parent3); + ok(IsEqualGUID(riid, &IID_IOleCommandTarget), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = &cmdtarget; + return S_OK; + } + + if(IsEqualGUID(guidService, &SID_GetCaller)) { + CHECK_EXPECT(QS_GetCaller_parent3); + SET_EXPECT(QS_IActiveScriptSite_parent4); + ok(IsEqualGUID(riid, &IID_IServiceProvider), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = &caller_sp2_parent3; + return S_OK; + } + + ok(0, "unexpected service %s\n", wine_dbgstr_guid(guidService)); + *ppv = NULL; + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl caller_sp2_parent_vtbl = { + caller_sp2_parent_QueryInterface, + caller_sp_AddRef, + caller_sp_Release, + caller_sp2_parent_QueryService +}; + +static IServiceProvider caller_sp2_parent = { &caller_sp2_parent_vtbl }; + +static HRESULT WINAPI caller_sp2_parent3_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IServiceProvider)) + *ppv = &caller_sp2_parent3; + else { + ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + return S_OK; +} + +static HRESULT WINAPI caller_sp2_parent3_QueryService(IServiceProvider *iface, REFGUID guidService, + REFIID riid, void **ppv) +{ + if(IsEqualGUID(guidService, &IID_IActiveScriptSite)) { + CHECK_EXPECT(QS_IActiveScriptSite_parent4); + ok(IsEqualGUID(riid, &IID_IOleCommandTarget), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return S_OK; + } + + ok(0, "unexpected service %s\n", wine_dbgstr_guid(guidService)); + *ppv = NULL; + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl caller_sp2_parent3_vtbl = { + caller_sp2_parent3_QueryInterface, + caller_sp_AddRef, + caller_sp_Release, + caller_sp2_parent3_QueryService +}; + +static IServiceProvider caller_sp2_parent3 = { &caller_sp2_parent3_vtbl }; + static IConnectionPoint *get_cp(IUnknown *unk, REFIID riid) { IConnectionPointContainer *cp_container; @@ -2728,6 +3174,161 @@ static void test_focus(IHTMLDocument2 *doc) IHTMLElement4_Release(div); }
+static void test_message_event(IHTMLDocument2 *doc) +{ + IHTMLFrameBase2 *iframe; + DISPPARAMS dp = { 0 }; + IHTMLWindow6 *window6; + IHTMLDocument6 *doc6; + IHTMLElement2 *elem; + IHTMLWindow2 *child; + IDispatchEx *dispex; + DISPID dispid; + HRESULT hres; + VARIANT v[2]; + BSTR bstr; + + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow6, (void**)&window6); + ok(hres == S_OK, "Could not get IHTMLWindow6 iface: %08lx\n", hres); + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument6, (void**)&doc6); + ok(hres == S_OK, "Could not get IHTMLDocument6 iface: %08lx\n", hres); + bstr = SysAllocString(L"ifr"); + hres = IHTMLDocument6_getElementById(doc6, bstr, &elem); + ok(hres == S_OK, "getElementById failed: %08lx\n", hres); + IHTMLDocument6_Release(doc6); + SysFreeString(bstr); + + hres = IHTMLElement2_QueryInterface(elem, &IID_IHTMLFrameBase2, (void**)&iframe); + ok(hres == S_OK, "Could not get IHTMLFrameBase2 iface: %08lx\n", hres); + IHTMLElement2_Release(elem); + hres = IHTMLFrameBase2_get_contentWindow(iframe, &child); + ok(hres == S_OK, "get_contentWindow failed: %08lx\n", hres); + IHTMLFrameBase2_Release(iframe); + + dp.cArgs = 2; + dp.rgvarg = v; + V_VT(&v[0]) = VT_DISPATCH; + V_DISPATCH(&v[0]) = (IDispatch*)&onmessage_obj; + hres = IHTMLWindow6_put_onmessage(window6, v[0]); + ok(hres == S_OK, "put_onmessage failed: %08lx\n", hres); + + V_VT(&v[0]) = VT_EMPTY; + hres = IHTMLWindow6_get_onmessage(window6, &v[0]); + ok(hres == S_OK, "get_onmessage failed: %08lx\n", hres); + ok(V_VT(&v[0]) == VT_DISPATCH, "V_VT(onmessage) = %d\n", V_VT(&v[0])); + ok(V_DISPATCH(&v[0]) == (IDispatch*)&onmessage_obj, "V_DISPATCH(onmessage) = %p\n", V_DISPATCH(&v[0])); + + if(document_mode >= 9) + add_event_listener((IUnknown*)doc, L"message", (IDispatch*)&onmessage_obj, VARIANT_TRUE); + + V_VT(&v[1]) = VT_BSTR; + V_BSTR(&v[1]) = SysAllocString(L"foobar"); + V_VT(&v[0]) = VT_BSTR; + V_BSTR(&v[0]) = SysAllocString(L"*"); + bstr = SysAllocString(L"foobar"); + hres = IHTMLWindow6_postMessage(window6, V_BSTR(&v[1]), v[0]); + ok(hres == E_ABORT, "postMessage returned: %08lx\n", hres); + IHTMLWindow6_Release(window6); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx iface: %08lx\n", hres); + + bstr = SysAllocString(L"postMessage"); + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &dispid); + ok(hres == S_OK, "GetDispID(postMessage) failed: %08lx\n", hres); + SysFreeString(bstr); + + onmessage_source = window; + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_METHOD, &dp, NULL, NULL, NULL); + ok(hres == (document_mode < 9 ? E_ABORT : S_OK), "InvokeEx(postMessage) returned: %08lx\n", hres); + if(hres == S_OK) { + SET_EXPECT(onmessage); + pump_msgs(&called_onmessage); + CHECK_CALLED(onmessage); + } + + if(document_mode < 9) + SET_EXPECT(QS_GetCaller); + SET_EXPECT(QS_IActiveScriptSite); + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_METHOD, &dp, NULL, NULL, &caller_sp_stub); + ok(hres == (document_mode < 9 ? E_ABORT : S_OK), "InvokeEx(postMessage) returned: %08lx\n", hres); + CHECK_CALLED(QS_IActiveScriptSite); + if(document_mode < 9) + CHECK_CALLED(QS_GetCaller); + else { + SET_EXPECT(onmessage); + pump_msgs(&called_onmessage); + CHECK_CALLED(onmessage); + } + + onmessage_source = child; + if(document_mode < 9) { + SET_EXPECT(QS_GetCaller); + SET_EXPECT(QS_IActiveScriptSite_parent); + }else { + SET_EXPECT(cmdtarget_Exec); + } + SET_EXPECT(QS_IActiveScriptSite); + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_METHOD, &dp, NULL, NULL, &caller_sp); + ok(hres == (document_mode < 9 ? E_ABORT : S_OK), "InvokeEx(postMessage) failed: %08lx\n", hres); + CHECK_CALLED(QS_IActiveScriptSite); + if(hres == S_OK) { + CHECK_CALLED(cmdtarget_Exec); + SET_EXPECT(onmessage); + pump_msgs(&called_onmessage); + CHECK_CALLED(onmessage); + } + + if(document_mode < 9) { + SET_EXPECT(QS_GetCaller_parent2); + SET_EXPECT(onmessage); + } + SET_EXPECT(QS_IActiveScriptSite_parent2); + SET_EXPECT(cmdtarget_Exec); + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_METHOD, &dp, NULL, NULL, &caller_sp2); + ok(hres == S_OK, "InvokeEx(postMessage) failed: %08lx\n", hres); + CHECK_CALLED(cmdtarget_Exec); + CHECK_CALLED(QS_IActiveScriptSite_parent2); + if(document_mode < 9) { + CHECK_CALLED(QS_IActiveScriptSite_parent3); + CHECK_CALLED(QS_GetCaller_parent2); + CHECK_CALLED(onmessage); + pump_msgs(NULL); + }else { + SET_EXPECT(onmessage); + pump_msgs(&called_onmessage); + CHECK_CALLED(onmessage); + } + + if(document_mode < 9) { + SET_EXPECT(QS_GetCaller_parent3); + SET_EXPECT(onmessage); + } + SET_EXPECT(QS_IActiveScriptSite_parent3); + SET_EXPECT(cmdtarget_Exec); + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_METHOD, &dp, NULL, NULL, &caller_sp2_parent); + ok(hres == S_OK, "InvokeEx(postMessage) failed: %08lx\n", hres); + CHECK_CALLED(cmdtarget_Exec); + CHECK_CALLED(QS_IActiveScriptSite_parent3); + if(document_mode < 9) { + CHECK_CALLED(QS_IActiveScriptSite_parent4); + CHECK_CALLED(QS_GetCaller_parent3); + CHECK_CALLED(onmessage); + pump_msgs(NULL); + }else { + SET_EXPECT(onmessage); + pump_msgs(&called_onmessage); + CHECK_CALLED(onmessage); + } + + onmessage_source = NULL; + VariantClear(&v[0]); + VariantClear(&v[1]); + IHTMLWindow2_Release(child); + IDispatchEx_Release(dispex); +} + static void test_visibilitychange(IHTMLDocument2 *doc) { if(!winetest_interactive) { @@ -6746,10 +7347,13 @@ START_TEST(events) run_test(input_doc_str, test_focus); run_test(empty_doc_str, test_submit); run_test(empty_doc_ie9_str, test_submit); + run_test(iframe_doc_str, test_message_event); run_test(iframe_doc_str, test_iframe_connections); if(is_ie9plus) { run_test_from_res(L"doc_with_prop.html", test_doc_obj); run_test_from_res(L"doc_with_prop_ie9.html", test_doc_obj); + run_test(iframe_doc_ie9_str, test_message_event); + run_test(iframe_doc_ie11_str, test_message_event); run_test_from_res(L"doc_with_prop_ie9.html", test_visibilitychange); run_test_from_res(L"blank_ie10.html", test_visibilitychange); run_test_from_res(L"iframe.html", test_unload_event); diff --git a/dlls/mshtml/tests/events.js b/dlls/mshtml/tests/events.js index 3b29798e9a1..a5f66a2f031 100644 --- a/dlls/mshtml/tests/events.js +++ b/dlls/mshtml/tests/events.js @@ -824,14 +824,24 @@ async_test("img_wrong_content_type", function() { });
async_test("message event", function() { - var listener_called = false; + var listener_called = false, iframe = document.createElement("iframe");
window.addEventListener("message", function(e) { + if(listener_called) { + ok(e.data === "echo", "e.data (diff origin) = " + e.data); + ok(e.source === iframe.contentWindow, "e.source (diff origin) not iframe.contentWindow"); + next_test(); + return; + } listener_called = true; ok(e.data === "test", "e.data = " + e.data); ok(e.bubbles === false, "bubbles = " + e.bubbles); ok(e.cancelable === false, "cancelable = " + e.cancelable); - next_test(); + ok(e.source === window, "e.source = " + e.source); + + iframe.onload = function() { iframe.contentWindow.postMessage("echo", "hTtP://WinEtesT.difFerent.ORG:1234"); } + iframe.src = "http://winetest.different.org:1234/xhr_iframe.html"; + document.body.appendChild(iframe); });
window.postMessage("test", "httP://wineTest.example.org");
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlevent.c | 14 +++++++++++--- dlls/mshtml/tests/events.c | 5 +++++ 2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index 4e1cfd2b695..adf5422c995 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -1831,11 +1831,19 @@ static HRESULT WINAPI HTMLEventObj5_put_data(IHTMLEventObj5 *iface, BSTR v) static HRESULT WINAPI HTMLEventObj5_get_data(IHTMLEventObj5 *iface, BSTR *p) { HTMLEventObj *This = impl_from_IHTMLEventObj5(iface); + IDOMMessageEvent *message_event; + HRESULT hres;
- FIXME("(%p)->(%p)\n", This, p); + TRACE("(%p)->(%p)\n", This, p);
- *p = NULL; - return S_OK; + if(!This->event || FAILED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMessageEvent, (void**)&message_event))) { + *p = NULL; + return S_OK; + } + + hres = IDOMMessageEvent_get_data(message_event, p); + IDOMMessageEvent_Release(message_event); + return hres; }
static HRESULT WINAPI HTMLEventObj5_get_source(IHTMLEventObj5 *iface, IDispatch **p) diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index aa1a60365f2..8641a2aae7d 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -1537,6 +1537,11 @@ static HRESULT WINAPI onmessage(IDispatchEx *iface, DISPID id, LCID lcid, WORD w ok(hres == S_OK, "get_url failed: %08lx\n", hres); ok(!bstr, "url = %s\n", wine_dbgstr_w(bstr));
+ hres = IHTMLEventObj5_get_data(event_obj5, &bstr); + ok(hres == S_OK, "get_data failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"foobar"), "data = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + hres = IHTMLEventObj5_get_source(event_obj5, &disp); ok(hres == S_OK, "get_source failed: %08lx\n", hres);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlevent.c | 63 ++++++++++++++++++++++++++++--- dlls/mshtml/tests/documentmode.js | 1 + dlls/mshtml/tests/events.c | 13 +++++++ dlls/mshtml/tests/events.js | 2 + 4 files changed, 73 insertions(+), 6 deletions(-)
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index adf5422c995..9df40510860 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -1876,11 +1876,19 @@ static HRESULT WINAPI HTMLEventObj5_put_origin(IHTMLEventObj5 *iface, BSTR v) static HRESULT WINAPI HTMLEventObj5_get_origin(IHTMLEventObj5 *iface, BSTR *p) { HTMLEventObj *This = impl_from_IHTMLEventObj5(iface); + IDOMMessageEvent *message_event; + HRESULT hres;
- FIXME("(%p)->(%p)\n", This, p); + TRACE("(%p)->(%p)\n", This, p);
- *p = NULL; - return S_OK; + if(!This->event || FAILED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMessageEvent, (void**)&message_event))) { + *p = NULL; + return S_OK; + } + + hres = IDOMMessageEvent_get_origin(message_event, p); + IDOMMessageEvent_Release(message_event); + return hres; }
static HRESULT WINAPI HTMLEventObj5_put_issession(IHTMLEventObj5 *iface, VARIANT_BOOL v) @@ -3669,6 +3677,7 @@ typedef struct { DOMEvent event; IDOMMessageEvent IDOMMessageEvent_iface; IHTMLWindow2 *source; + BSTR origin; VARIANT data; } DOMMessageEvent;
@@ -3756,8 +3765,14 @@ static HRESULT DOMMessageEvent_get_data_hook(DispatchEx *dispex, WORD flags, DIS static HRESULT WINAPI DOMMessageEvent_get_origin(IDOMMessageEvent *iface, BSTR *p) { DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, p); + + if(This->origin) + return (*p = SysAllocStringLen(This->origin, SysStringLen(This->origin))) ? S_OK : E_OUTOFMEMORY; + + *p = NULL; + return S_OK; }
static HRESULT WINAPI DOMMessageEvent_get_source(IDOMMessageEvent *iface, IHTMLWindow2 **p) @@ -3829,6 +3844,7 @@ static void DOMMessageEvent_unlink(DispatchEx *dispex) static void DOMMessageEvent_destructor(DispatchEx *dispex) { DOMMessageEvent *message_event = DOMMessageEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex)); + SysFreeString(message_event->origin); VariantClear(&message_event->data); DOMEvent_destructor(dispex); } @@ -4602,21 +4618,56 @@ HRESULT create_document_event(HTMLDocumentNode *doc, eventid_t event_id, DOMEven HRESULT create_message_event(HTMLDocumentNode *doc, IHTMLWindow2 *source, VARIANT *data, DOMEvent **ret) { DOMMessageEvent *message_event; + BSTR bstr, origin = NULL; + IHTMLLocation *location; DOMEvent *event; HRESULT hres; + UINT len;
- hres = create_document_event(doc, EVENTID_MESSAGE, &event); + hres = IHTMLWindow2_get_location(source, &location); + if(FAILED(hres)) + return hres; + + hres = IHTMLLocation_get_protocol(location, &bstr); + if(FAILED(hres)) { + IHTMLLocation_Release(location); + return hres; + } + len = SysStringLen(bstr); + SysFreeString(bstr); + + hres = IHTMLLocation_get_href(location, &bstr); + IHTMLLocation_Release(location); if(FAILED(hres)) return hres; + if(bstr) { + static const WCHAR delims[] = L"/\"; + + if(bstr[len] == '/' && bstr[len + 1] == '/') + len += 2 + wcscspn(bstr + len + 2, delims); + + origin = SysAllocStringLen(bstr, len); + SysFreeString(bstr); + if(!origin) + return E_OUTOFMEMORY; + } + + hres = create_document_event(doc, EVENTID_MESSAGE, &event); + if(FAILED(hres)) { + SysFreeString(origin); + return hres; + } message_event = DOMMessageEvent_from_DOMEvent(event);
V_VT(&message_event->data) = VT_EMPTY; hres = VariantCopy(&message_event->data, data); if(FAILED(hres)) { IDOMEvent_Release(&event->IDOMEvent_iface); + SysFreeString(origin); return hres; }
+ message_event->origin = origin; message_event->source = source; IHTMLWindow2_AddRef(message_event->source);
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index bec247b42d1..94183ad015e 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -2929,6 +2929,7 @@ async_test("postMessage", function() { else { ok(e.data === (v < 10 ? "10" : 10), "e.data = " + e.data); ok(e.source === window, "e.source = " + e.source); + ok(e.origin === "http://winetest.example.org", "e.origin = " + e.origin); next_test(); } } diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index 8641a2aae7d..0dd622b15c3 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -1542,6 +1542,11 @@ static HRESULT WINAPI onmessage(IDispatchEx *iface, DISPID id, LCID lcid, WORD w ok(!wcscmp(bstr, L"foobar"), "data = %s\n", wine_dbgstr_w(bstr)); SysFreeString(bstr);
+ hres = IHTMLEventObj5_get_origin(event_obj5, &bstr); + ok(hres == S_OK, "get_origin failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"about:"), "origin = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + hres = IHTMLEventObj5_get_source(event_obj5, &disp); ok(hres == S_OK, "get_source failed: %08lx\n", hres);
@@ -1558,6 +1563,9 @@ static HRESULT WINAPI onmessage(IDispatchEx *iface, DISPID id, LCID lcid, WORD w bstr = SysAllocString(L"foobar"); hres = IHTMLEventObj5_put_url(event_obj5, bstr); ok(hres == DISP_E_MEMBERNOTFOUND, "put_url returned: %08lx\n", hres); + + hres = IHTMLEventObj5_put_origin(event_obj5, bstr); + ok(hres == DISP_E_MEMBERNOTFOUND, "put_origin returned: %08lx\n", hres); SysFreeString(bstr);
IHTMLEventObj5_Release(event_obj5); @@ -1572,6 +1580,11 @@ static HRESULT WINAPI onmessage(IDispatchEx *iface, DISPID id, LCID lcid, WORD w ok(!wcscmp(bstr, L"foobar"), "data = %s\n", wine_dbgstr_w(bstr)); SysFreeString(bstr);
+ hres = IDOMMessageEvent_get_origin(msg, &bstr); + ok(hres == S_OK, "get_origin failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"about:"), "origin = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + hres = IDOMMessageEvent_get_source(msg, &source); ok(hres == S_OK, "get_source failed: %08lx\n", hres); ok(source == onmessage_source, "source != onmessage_source\n"); diff --git a/dlls/mshtml/tests/events.js b/dlls/mshtml/tests/events.js index a5f66a2f031..a130917cfda 100644 --- a/dlls/mshtml/tests/events.js +++ b/dlls/mshtml/tests/events.js @@ -830,6 +830,7 @@ async_test("message event", function() { if(listener_called) { ok(e.data === "echo", "e.data (diff origin) = " + e.data); ok(e.source === iframe.contentWindow, "e.source (diff origin) not iframe.contentWindow"); + ok(e.origin === "http://winetest.different.org:1234", "e.origin (diff origin) = " + e.origin); next_test(); return; } @@ -838,6 +839,7 @@ async_test("message event", function() { ok(e.bubbles === false, "bubbles = " + e.bubbles); ok(e.cancelable === false, "cancelable = " + e.cancelable); ok(e.source === window, "e.source = " + e.source); + ok(e.origin === "http://winetest.example.org", "e.origin = " + e.origin);
iframe.onload = function() { iframe.contentWindow.postMessage("echo", "hTtP://WinEtesT.difFerent.ORG:1234"); } iframe.src = "http://winetest.different.org:1234/xhr_iframe.html";
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlevent.c | 48 ++++++++++- dlls/mshtml/tests/documentmode.js | 29 +++++++ dlls/mshtml/tests/events.c | 130 ++++++++++++++++++++++++++++++ dlls/mshtml/tests/events.js | 1 + 4 files changed, 206 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index 9df40510860..1f90248238e 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -3740,6 +3740,11 @@ static HRESULT WINAPI DOMMessageEvent_get_data(IDOMMessageEvent *iface, BSTR *p)
TRACE("(%p)->(%p)\n", This, p);
+ if(V_VT(&This->data) == VT_EMPTY) { + *p = SysAllocString(L""); + return S_OK; + } + if(V_VT(&This->data) != VT_BSTR) { FIXME("non-string data\n"); return E_NOTIMPL; @@ -3791,9 +3796,48 @@ static HRESULT WINAPI DOMMessageEvent_initMessageEvent(IDOMMessageEvent *iface, BSTR last_event_id, IHTMLWindow2 *source) { DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface); - FIXME("(%p)->(%s %x %x %s %s %s %p)\n", This, debugstr_w(type), can_bubble, cancelable, + BSTR new_origin = NULL; + BSTR new_data = NULL; + HRESULT hres; + + TRACE("(%p)->(%s %x %x %s %s %s %p)\n", This, debugstr_w(type), can_bubble, cancelable, debugstr_w(data), debugstr_w(origin), debugstr_w(last_event_id), source); - return E_NOTIMPL; + + if(This->event.target) { + TRACE("called on already dispatched event\n"); + return S_OK; + } + + if((data && !(new_data = SysAllocString(data))) || + (origin && !(new_origin = SysAllocString(origin)))) { + hres = E_OUTOFMEMORY; + goto fail; + } + + hres = IDOMEvent_initEvent(&This->event.IDOMEvent_iface, type, can_bubble, cancelable); + if(FAILED(hres)) + goto fail; + + if(new_data) { + VariantClear(&This->data); + V_VT(&This->data) = VT_BSTR; + V_BSTR(&This->data) = new_data; + } + if(new_origin) { + SysFreeString(This->origin); + This->origin = new_origin; + } + if(This->source) + IHTMLWindow2_Release(This->source); + This->source = source; + if(source) + IHTMLWindow2_AddRef(source); + return S_OK; + +fail: + SysFreeString(new_origin); + SysFreeString(new_data); + return hres; }
static const IDOMMessageEventVtbl DOMMessageEventVtbl = { diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 94183ad015e..5249e042182 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -2919,6 +2919,32 @@ sync_test("MutationObserver", function() { test_exposed("takeRecords"); });
+sync_test("initMessageEvent", function() { + var e, v = document.documentMode; + if(!document.createEvent) + return; + e = document.createEvent("MessageEvent"); + ok(e.data === (v < 10 ? "" : undefined), "e.data = " + e.data); + ok(e.bubbles === false, "bubbles = " + e.bubbles); + ok(e.cancelable === false, "cancelable = " + e.cancelable); + ok(e.source === null, "e.source = " + e.source); + ok(e.origin === "", "e.origin = " + e.origin); + + e.initMessageEvent("blah", true, true, 137, "wine", 1234, window); + ok(e.data === "137", "e.data = " + e.data); + ok(e.bubbles === true, "bubbles = " + e.bubbles); + ok(e.cancelable === true, "cancelable = " + e.cancelable); + ok(e.source === window, "e.source = " + e.source); + ok(e.origin === "wine", "e.origin = " + e.origin); + + e.initMessageEvent("abcd", false, false, "testdata", "origin", 42, null); + ok(e.data === "testdata", "e.data = " + e.data); + ok(e.bubbles === false, "bubbles = " + e.bubbles); + ok(e.cancelable === false, "cancelable = " + e.cancelable); + ok(e.source === null, "e.source = " + e.source); + ok(e.origin === "origin", "e.origin = " + e.origin); +}); + async_test("postMessage", function() { var v = document.documentMode; var onmessage_called = false; @@ -2930,6 +2956,9 @@ async_test("postMessage", function() { ok(e.data === (v < 10 ? "10" : 10), "e.data = " + e.data); ok(e.source === window, "e.source = " + e.source); ok(e.origin === "http://winetest.example.org", "e.origin = " + e.origin); + + e = document.createEvent("MessageEvent"); + ok(e.data === (v < 10 ? "" : undefined), "created e.data = " + e.data); next_test(); } } diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index 0dd622b15c3..9c3a6b471f1 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -3345,6 +3345,136 @@ static void test_message_event(IHTMLDocument2 *doc) VariantClear(&v[1]); IHTMLWindow2_Release(child); IDispatchEx_Release(dispex); + + if(document_mode >= 9) { + IDOMMessageEvent *msg_event = NULL; + IDocumentEvent *doc_event; + IHTMLWindow2 *source; + IDOMEvent *event; + UINT argerr; + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IDocumentEvent, (void**)&doc_event); + ok(hres == S_OK, "Could not get IDocumentEvent iface: %08lx\n", hres); + + bstr = SysAllocString(L"MessageEvent"); + hres = IDocumentEvent_createEvent(doc_event, bstr, &event); + ok(hres == S_OK, "createEvent failed: %08lx\n", hres); + IDocumentEvent_Release(doc_event); + SysFreeString(bstr); + + hres = IDOMEvent_QueryInterface(event, &IID_IDOMMessageEvent, (void**)&msg_event); + ok(hres == S_OK, "Could not get IDOMMessageEvent iface: %08lx\n", hres); + ok(msg_event != NULL, "msg_event = NULL\n"); + IDOMEvent_Release(event); + + hres = IDOMMessageEvent_get_source(msg_event, &source); + ok(hres == S_OK, "get_source failed: %08lx\n", hres); + ok(source == NULL, "uninitialized source != NULL\n"); + + hres = IDOMMessageEvent_get_origin(msg_event, &bstr); + ok(hres == S_OK, "get_origin failed: %08lx\n", hres); + ok(!bstr, "uninitialized origin = %s\n", wine_dbgstr_w(bstr)); + + /* IE10+ crash when using the get_data from the interface (because it's not a string yet?) */ + if(document_mode < 10) { + hres = IDOMMessageEvent_get_data(msg_event, &bstr); + ok(hres == S_OK, "get_data failed: %08lx\n", hres); + ok(!wcscmp(bstr, L""), "uninitialized data = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + bstr = SysAllocString(L"foobar"); + hres = IDOMMessageEvent_initMessageEvent(msg_event, bstr, VARIANT_FALSE, VARIANT_FALSE, bstr, bstr, NULL, window); + ok(hres == S_OK, "initMessageEvent failed: %08lx\n", hres); + SysFreeString(bstr); + + hres = IDOMMessageEvent_get_data(msg_event, &bstr); + ok(hres == S_OK, "get_data failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"foobar"), "data = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + hres = IDOMMessageEvent_get_source(msg_event, &source); + ok(hres == S_OK, "get_source failed: %08lx\n", hres); + ok(source == window, "source != window\n"); + IHTMLWindow2_Release(source); + + hres = IDOMMessageEvent_get_origin(msg_event, &bstr); + ok(hres == S_OK, "get_origin failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"foobar"), "origin = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + bstr = SysAllocString(L"barfoo"); + hres = IDOMMessageEvent_initMessageEvent(msg_event, bstr, VARIANT_FALSE, VARIANT_FALSE, NULL, NULL, NULL, NULL); + ok(hres == S_OK, "initMessageEvent failed: %08lx\n", hres); + SysFreeString(bstr); + + hres = IDOMMessageEvent_get_data(msg_event, &bstr); + ok(hres == S_OK, "get_data failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"foobar"), "data = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + hres = IDOMMessageEvent_get_source(msg_event, &source); + ok(hres == S_OK, "get_source failed: %08lx\n", hres); + ok(source == NULL, "source != NULL\n"); + + hres = IDOMMessageEvent_get_origin(msg_event, &bstr); + ok(hres == S_OK, "get_origin failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"foobar"), "origin = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + }else { + bstr = SysAllocString(L"data"); + hres = IDOMMessageEvent_GetIDsOfNames(msg_event, &IID_NULL, &bstr, 1, 0, &dispid); + ok(hres == S_OK, "GetIDsOfNames(data) failed: %08lx\n", hres); + SysFreeString(bstr); + + dp.cArgs = 0; + dp.rgvarg = NULL; + hres = IDOMMessageEvent_Invoke(msg_event, dispid, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dp, &v[0], NULL, &argerr); + ok(hres == S_OK, "Invoke(data) failed: %08lx\n", hres); + ok(V_VT(&v[0]) == VT_EMPTY, "V_VT(uninitialized data) = %d\n", V_VT(&v[0])); + + bstr = SysAllocString(L"foobar"); + hres = IDOMMessageEvent_initMessageEvent(msg_event, bstr, VARIANT_FALSE, VARIANT_FALSE, bstr, bstr, NULL, window); + ok(hres == S_OK, "initMessageEvent failed: %08lx\n", hres); + SysFreeString(bstr); + + hres = IDOMMessageEvent_Invoke(msg_event, dispid, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dp, &v[0], NULL, &argerr); + ok(hres == S_OK, "Invoke(data) failed: %08lx\n", hres); + ok(V_VT(&v[0]) == VT_BSTR, "V_VT(data) = %d\n", V_VT(&v[0])); + ok(!wcscmp(V_BSTR(&v[0]), L"foobar"), "V_BSTR(data) = %s\n", wine_dbgstr_w(V_BSTR(&v[0]))); + VariantClear(&v[0]); + + hres = IDOMMessageEvent_get_source(msg_event, &source); + ok(hres == S_OK, "get_source failed: %08lx\n", hres); + ok(source == window, "source != window\n"); + IHTMLWindow2_Release(source); + + hres = IDOMMessageEvent_get_origin(msg_event, &bstr); + ok(hres == S_OK, "get_origin failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"foobar"), "origin = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + bstr = SysAllocString(L"barfoo"); + hres = IDOMMessageEvent_initMessageEvent(msg_event, bstr, VARIANT_FALSE, VARIANT_FALSE, NULL, NULL, NULL, NULL); + ok(hres == S_OK, "initMessageEvent failed: %08lx\n", hres); + SysFreeString(bstr); + + hres = IDOMMessageEvent_Invoke(msg_event, dispid, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dp, &v[0], NULL, &argerr); + ok(hres == S_OK, "Invoke(data) failed: %08lx\n", hres); + ok(V_VT(&v[0]) == VT_BSTR, "V_VT(data) = %d\n", V_VT(&v[0])); + ok(!wcscmp(V_BSTR(&v[0]), L"foobar"), "V_BSTR(data) = %s\n", wine_dbgstr_w(V_BSTR(&v[0]))); + + hres = IDOMMessageEvent_get_source(msg_event, &source); + ok(hres == S_OK, "get_source failed: %08lx\n", hres); + ok(source == NULL, "source != NULL\n"); + + hres = IDOMMessageEvent_get_origin(msg_event, &bstr); + ok(hres == S_OK, "get_origin failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"foobar"), "origin = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + } + + IDOMMessageEvent_Release(msg_event); + } }
static void test_visibilitychange(IHTMLDocument2 *doc) diff --git a/dlls/mshtml/tests/events.js b/dlls/mshtml/tests/events.js index a130917cfda..9282d48bacc 100644 --- a/dlls/mshtml/tests/events.js +++ b/dlls/mshtml/tests/events.js @@ -835,6 +835,7 @@ async_test("message event", function() { return; } listener_called = true; + e.initMessageEvent("blah", true, true, "barfoo", "wine", 1234, window); ok(e.data === "test", "e.data = " + e.data); ok(e.bubbles === false, "bubbles = " + e.bubbles); ok(e.cancelable === false, "cancelable = " + e.cancelable);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
It's mostly implemented, and issession isn't even exposed.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlevent.c | 1 + dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/tests/events.html | 7 ++++++- 3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index 1f90248238e..28af7f4ed51 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -2064,6 +2064,7 @@ static const dispex_static_data_vtbl_t HTMLEventObj_dispex_vtbl = { };
static const tid_t HTMLEventObj_iface_tids[] = { + IHTMLEventObj5_tid, IHTMLEventObj_tid, 0 }; diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index db37375c089..9609fb5edcb 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -208,6 +208,7 @@ typedef struct EventTarget EventTarget; XIID(IHTMLElementCollection) \ XIID(IHTMLEmbedElement) \ XIID(IHTMLEventObj) \ + XIID(IHTMLEventObj5) \ XIID(IHTMLFiltersCollection) \ XIID(IHTMLFormElement) \ XIID(IHTMLFrameBase) \ diff --git a/dlls/mshtml/tests/events.html b/dlls/mshtml/tests/events.html index 6f9b3dacbbc..76473277e3c 100644 --- a/dlls/mshtml/tests/events.html +++ b/dlls/mshtml/tests/events.html @@ -284,7 +284,12 @@ function test_attach_in_attach() { }
function test_event_obj_props(e) { - var i, props; + var i, props = [ + "altKey", "button", "cancelBubble", "clientX", "clientY", "ctrlKey", "data", "fromElement", "keyCode", "offsetX", "offsetY", + "origin", "qualifier", "reason", "returnValue", "screenX", "screenY", "shiftKey", "source", "srcElement", "srcFilter", + "toElement", "type", "url", "x", "y" ]; + for(i = 0; i < props.length; i++) + ok(props[i] in e, props[i] + " not in event obj");
props = [ "imeCompositionChange", "imeNotifyCommand", "imeNotifyData", "imeRequest", "imeRequestData", "issession", "keyboardLayout" ]; for(i = 0; i < props.length; i++)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/tests/script.c | 146 +++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+)
diff --git a/dlls/mshtml/tests/script.c b/dlls/mshtml/tests/script.c index 5c969e4a3d9..e6acf5ae5b1 100644 --- a/dlls/mshtml/tests/script.c +++ b/dlls/mshtml/tests/script.c @@ -147,8 +147,11 @@ DEFINE_EXPECT(external_success); DEFINE_EXPECT(QS_VariantConversion); DEFINE_EXPECT(QS_IActiveScriptSite); DEFINE_EXPECT(QS_GetCaller); +DEFINE_EXPECT(QS_IActiveScriptSite2); +DEFINE_EXPECT(QS_GetCaller2); DEFINE_EXPECT(ChangeType_bstr); DEFINE_EXPECT(ChangeType_dispatch); +DEFINE_EXPECT(cmdtarget_Exec); DEFINE_EXPECT(GetTypeInfo);
#define TESTACTIVEX_CLSID "{178fc163-f585-4e24-9c13-4bb7faf80646}" @@ -489,6 +492,8 @@ static IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
static IPropertyNotifySink PropertyNotifySink = { &PropertyNotifySinkVtbl };
+static IOleCommandTarget cmdtarget; + static HRESULT WINAPI VariantChangeType_QueryInterface(IVariantChangeType *iface, REFIID riid, void **ppv) { ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid)); @@ -595,6 +600,52 @@ static const IServiceProviderVtbl ServiceProviderVtbl = {
static IServiceProvider caller_sp = { &ServiceProviderVtbl };
+static HRESULT WINAPI ServiceProvider2_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + ok(0, "unexpected call\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI ServiceProvider2_AddRef(IServiceProvider *iface) +{ + return 2; +} + +static ULONG WINAPI ServiceProvider2_Release(IServiceProvider *iface) +{ + return 1; +} + +static HRESULT WINAPI ServiceProvider2_QueryService(IServiceProvider *iface, REFGUID guidService, + REFIID riid, void **ppv) +{ + if(IsEqualGUID(guidService, &IID_IActiveScriptSite)) { + CHECK_EXPECT(QS_IActiveScriptSite2); + ok(IsEqualGUID(riid, &IID_IOleCommandTarget), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = &cmdtarget; + return S_OK; + } + + if(IsEqualGUID(guidService, &SID_GetCaller)) { + CHECK_EXPECT(QS_GetCaller2); + ok(IsEqualGUID(riid, &IID_IServiceProvider), "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return S_OK; + } + + ok(0, "unexpected service %s\n", wine_dbgstr_guid(guidService)); + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl ServiceProvider2Vtbl = { + ServiceProvider2_QueryInterface, + ServiceProvider2_AddRef, + ServiceProvider2_Release, + ServiceProvider2_QueryService +}; + +static IServiceProvider caller_sp2 = { &ServiceProvider2Vtbl }; + static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) { *ppv = NULL; @@ -1465,6 +1516,88 @@ static IDispatchExVtbl externalDispVtbl = {
static IDispatchEx externalDisp = { &externalDispVtbl };
+static HRESULT WINAPI DispatchExStub_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) +{ + ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid)); + return E_NOINTERFACE; +} + +static IDispatchExVtbl DispatchExStubVtbl = { + DispatchExStub_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + DispatchEx_GetDispID, + DispatchEx_InvokeEx, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; + +static IDispatchEx DispatchExStub = { &DispatchExStubVtbl }; + +static HRESULT WINAPI cmdtarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IOleCommandTarget)) + *ppv = &cmdtarget; + else { + ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + return S_OK; +} + +static ULONG WINAPI cmdtarget_AddRef(IOleCommandTarget *iface) +{ + return 2; +} + +static ULONG WINAPI cmdtarget_Release(IOleCommandTarget *iface) +{ + return 1; +} + +static HRESULT WINAPI cmdtarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup, + ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText) +{ + ok(0, "unexpected call\n"); + return OLECMDERR_E_UNKNOWNGROUP; +} + +static HRESULT WINAPI cmdtarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup, + DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) +{ + CHECK_EXPECT2(cmdtarget_Exec); + ok(pguidCmdGroup && IsEqualGUID(pguidCmdGroup, &CGID_ScriptSite), "pguidCmdGroup = %s\n", wine_dbgstr_guid(pguidCmdGroup)); + ok(nCmdID == CMDID_SCRIPTSITE_SECURITY_WINDOW, "nCmdID = %lu\n", nCmdID); + ok(!nCmdexecopt, "nCmdexecopt = %lu\n", nCmdexecopt); + ok(!pvaIn, "pvaIn != NULL\n"); + ok(pvaOut != NULL, "pvaOut = NULL\n"); + + /* Looks like native just uses this for some sort of hardcoded security check + * without actually using the IDispatchEx interface or QI? (for ACCESSDENIED) */ + V_VT(pvaOut) = VT_DISPATCH; + V_DISPATCH(pvaOut) = (IDispatch*)&DispatchExStub; + return S_OK; +} + +static const IOleCommandTargetVtbl cmdtarget_vtbl = { + cmdtarget_QueryInterface, + cmdtarget_AddRef, + cmdtarget_Release, + cmdtarget_QueryStatus, + cmdtarget_Exec +}; + +static IOleCommandTarget cmdtarget = { &cmdtarget_vtbl }; + static HRESULT QueryInterface(REFIID,void**);
static HRESULT WINAPI DocHostUIHandler_QueryInterface(IDocHostUIHandler2 *iface, REFIID riid, void **ppv) @@ -2740,6 +2873,19 @@ static void test_func(IDispatchEx *obj) todo_wine CHECK_CALLED(QS_IActiveScriptSite); todo_wine CHECK_CALLED(QS_GetCaller);
+ SET_EXPECT(QS_IActiveScriptSite2); + SET_EXPECT(QS_GetCaller2); + SET_EXPECT(cmdtarget_Exec); + hres = dispex_propget(dispex, DISPID_VALUE, &var, &caller_sp2); + ok(hres == S_OK, "InvokeEx returned: %08lx, expected S_OK\n", hres); + ok(V_VT(&var) == VT_BSTR, "V_VT(var) = %d\n", V_VT(&var)); + ok(!lstrcmpW(V_BSTR(&var), L"\nfunction toString() {\n [native code]\n}\n"), + "V_BSTR(var) = %s\n", wine_dbgstr_w(V_BSTR(&var))); + VariantClear(&var); + todo_wine CHECK_CALLED(QS_IActiveScriptSite2); + todo_wine CHECK_CALLED(QS_GetCaller2); + todo_wine CHECK_CALLED(cmdtarget_Exec); + IDispatchEx_Release(dispex); }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=142638
Your paranoid android.
=== w1064v1809 (32 bit report) ===
mshtml: 1e28:events: unhandled exception c0000005 at 76B2B6F0
=== w1064_tsign (32 bit report) ===
mshtml: 05d4:events: unhandled exception c0000005 at 7526A280
=== w10pro64 (32 bit report) ===
mshtml: 2228:events: unhandled exception c0000005 at 7518A280
=== w10pro64_en_AE_u8 (32 bit report) ===
mshtml: 2124:events: unhandled exception c0000005 at 779CA280
=== w11pro64 (32 bit report) ===
mshtml: 0708:events: unhandled exception c0000005 at 7674C860
=== w1064v1809 (64 bit report) ===
mshtml: 1de8:events: unhandled exception c0000005 at 00007FFFC309E393
=== w1064_2qxl (64 bit report) ===
mshtml: 1e00:events: unhandled exception c0000005 at 00007FFFFB9BDF63
=== w1064_adm (64 bit report) ===
mshtml: 1c68:events: unhandled exception c0000005 at 00007FFA5593DF63
=== w1064_tsign (64 bit report) ===
mshtml: 1b7c:events: unhandled exception c0000005 at 00007FF8EDC5DF63
=== w10pro64 (64 bit report) ===
mshtml: 2088:events: unhandled exception c0000005 at 00007FFF2D0FDF63
=== w10pro64_ar (64 bit report) ===
mshtml: 2124:events: unhandled exception c0000005 at 00007FFA095FDF63
=== w10pro64_ja (64 bit report) ===
mshtml: 1f10:events: unhandled exception c0000005 at 00007FF97016DF63
=== w10pro64_zh_CN (64 bit report) ===
mshtml: 2358:events: unhandled exception c0000005 at 00007FF8B5EADF63
=== w11pro64_amd (64 bit report) ===
mshtml: 203c:events: unhandled exception c0000005 at 00007FFB1DA316A3
=== w7pro64 (64 bit report) ===
mshtml: script.c:1223: Test failed: L"/index.html?dom.js:document_lastModified: lastModified too far from navigationStart: 1012"