Commit b9e4680d authored by Gabriel Ivăncescu's avatar Gabriel Ivăncescu Committed by Alexandre Julliard

mshtml: Implement `source` prop for MessageEvents.

parent 22214ec3
......@@ -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;
}
......
......@@ -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*);
......
......@@ -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;
......
......@@ -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();
}
}
......
......@@ -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");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment