1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00

mshtml: Implement source prop for MessageEvents.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
This commit is contained in:
Gabriel Ivăncescu 2024-02-05 16:15:23 +02:00 committed by Alexandre Julliard
parent 22214ec357
commit b9e4680dea
6 changed files with 708 additions and 10 deletions

View file

@ -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;
}

View file

@ -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*);

View file

@ -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;

View file

@ -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();
}
}

View file

@ -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,158 @@ 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]));
IHTMLWindow6_Release(window6);
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"*");
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 +7344,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);

View file

@ -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");