mshtml: Added support for binding XHR events.

This commit is contained in:
Jacek Caban 2015-07-01 17:38:17 +02:00 committed by Alexandre Julliard
parent 7a3c9889e3
commit 8d85da757a
4 changed files with 140 additions and 6 deletions

View File

@ -256,7 +256,7 @@ static eventid_t attr_to_eid(LPCWSTR str)
return EVENTID_LAST;
}
typedef struct {
struct HTMLEventObj {
DispatchEx dispex;
IHTMLEventObj IHTMLEventObj_iface;
@ -268,7 +268,7 @@ typedef struct {
VARIANT return_value;
BOOL prevent_default;
BOOL cancel_bubble;
} HTMLEventObj;
};
static inline HTMLEventObj *impl_from_IHTMLEventObj(IHTMLEventObj *iface)
{
@ -966,7 +966,7 @@ static BOOL is_cp_event(cp_static_data_t *data, DISPID dispid)
return FALSE;
}
static void call_event_handlers(HTMLDocumentNode *doc, HTMLEventObj *event_obj, EventTarget *event_target,
void call_event_handlers(HTMLDocumentNode *doc, HTMLEventObj *event_obj, EventTarget *event_target,
ConnectionPointContainer *cp_container, eventid_t eid, IDispatch *this_obj)
{
event_target_t *data = get_event_target_data(event_target, FALSE);

View File

@ -67,6 +67,9 @@ HRESULT create_event_obj(IHTMLEventObj**) DECLSPEC_HIDDEN;
void bind_target_event(HTMLDocumentNode*,EventTarget*,const WCHAR*,IDispatch*) DECLSPEC_HIDDEN;
HRESULT ensure_doc_nsevent_handler(HTMLDocumentNode*,eventid_t) DECLSPEC_HIDDEN;
typedef struct HTMLEventObj HTMLEventObj;
void call_event_handlers(HTMLDocumentNode*,HTMLEventObj*,EventTarget*,ConnectionPointContainer*,eventid_t,IDispatch*);
void init_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN;
void release_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN;
void add_nsevent_listener(HTMLDocumentNode*,nsIDOMNode*,LPCWSTR) DECLSPEC_HIDDEN;

View File

@ -504,7 +504,7 @@ static void test_async_xhr(IHTMLDocument2 *doc, const char *xml_url)
SET_EXPECT(xmlhttprequest_onreadystatechange_opened);
hres = IHTMLXMLHttpRequest_open(xhr, method, url, vbool, vempty, vempty);
ok(hres == S_OK, "open failed: %08x\n", hres);
todo_wine CHECK_CALLED(xmlhttprequest_onreadystatechange_opened);
CHECK_CALLED(xmlhttprequest_onreadystatechange_opened);
SysFreeString(method);
SysFreeString(url);

View File

@ -60,14 +60,117 @@ static HRESULT variant_to_nsastr(VARIANT var, nsAString *ret)
}
}
/* IHTMLXMLHttpRequest */
typedef struct XMLHttpReqEventListener XMLHttpReqEventListener;
typedef struct {
EventTarget event_target;
IHTMLXMLHttpRequest IHTMLXMLHttpRequest_iface;
LONG ref;
nsIXMLHttpRequest *nsxhr;
XMLHttpReqEventListener *event_listener;
} HTMLXMLHttpRequest;
struct XMLHttpReqEventListener {
nsIDOMEventListener nsIDOMEventListener_iface;
LONG ref;
HTMLXMLHttpRequest *xhr;
};
static void detach_xhr_event_listener(XMLHttpReqEventListener *event_listener)
{
nsIDOMEventTarget *event_target;
nsAString str;
nsresult nsres;
static const WCHAR readystatechangeW[] =
{'o','n','r','e','a','d','y','s','t','a','t','e','c','h','a','n','g','e',0};
nsres = nsIXMLHttpRequest_QueryInterface(event_listener->xhr->nsxhr, &IID_nsIDOMEventTarget, (void**)&event_target);
assert(nsres == NS_OK);
nsAString_InitDepend(&str, readystatechangeW);
nsres = nsIDOMEventTarget_RemoveEventListener(event_target, &str, &event_listener->nsIDOMEventListener_iface, FALSE);
nsAString_Finish(&str);
nsIDOMEventTarget_Release(event_target);
event_listener->xhr->event_listener = NULL;
event_listener->xhr = NULL;
nsIDOMEventListener_Release(&event_listener->nsIDOMEventListener_iface);
}
static inline XMLHttpReqEventListener *impl_from_nsIDOMEventListener(nsIDOMEventListener *iface)
{
return CONTAINING_RECORD(iface, XMLHttpReqEventListener, nsIDOMEventListener_iface);
}
static nsresult NSAPI XMLHttpReqEventListener_QueryInterface(nsIDOMEventListener *iface,
nsIIDRef riid, void **result)
{
XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
if(IsEqualGUID(&IID_nsISupports, riid)) {
TRACE("(%p)->(IID_nsISupports, %p)\n", This, result);
*result = &This->nsIDOMEventListener_iface;
}else if(IsEqualGUID(&IID_nsIDOMEventListener, riid)) {
TRACE("(%p)->(IID_nsIDOMEventListener %p)\n", This, result);
*result = &This->nsIDOMEventListener_iface;
}else {
*result = NULL;
TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
return NS_NOINTERFACE;
}
nsIDOMEventListener_AddRef(&This->nsIDOMEventListener_iface);
return NS_OK;
}
static nsrefcnt NSAPI XMLHttpReqEventListener_AddRef(nsIDOMEventListener *iface)
{
XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
return ref;
}
static nsrefcnt NSAPI XMLHttpReqEventListener_Release(nsIDOMEventListener *iface)
{
XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
if(!ref) {
assert(!This->xhr);
heap_free(This);
}
return ref;
}
static nsresult NSAPI XMLHttpReqEventListener_HandleEvent(nsIDOMEventListener *iface, nsIDOMEvent *event)
{
XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
TRACE("(%p)\n", This);
if(!This->xhr)
return NS_OK;
call_event_handlers(NULL, NULL, &This->xhr->event_target, NULL, EVENTID_READYSTATECHANGE,
(IDispatch*)&This->xhr->IHTMLXMLHttpRequest_iface);
return NS_OK;
}
static const nsIDOMEventListenerVtbl XMLHttpReqEventListenerVtbl = {
XMLHttpReqEventListener_QueryInterface,
XMLHttpReqEventListener_AddRef,
XMLHttpReqEventListener_Release,
XMLHttpReqEventListener_HandleEvent
};
static inline HTMLXMLHttpRequest *impl_from_IHTMLXMLHttpRequest(IHTMLXMLHttpRequest *iface)
{
return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IHTMLXMLHttpRequest_iface);
@ -115,6 +218,8 @@ static ULONG WINAPI HTMLXMLHttpRequest_Release(IHTMLXMLHttpRequest *iface)
TRACE("(%p) ref=%d\n", This, ref);
if(!ref) {
if(This->event_listener)
detach_xhr_event_listener(This->event_listener);
release_dispex(&This->event_target.dispex);
nsIXMLHttpRequest_Release(This->nsxhr);
heap_free(This);
@ -357,10 +462,36 @@ static inline HTMLXMLHttpRequest *impl_from_DispatchEx(DispatchEx *iface)
static void HTMLXMLHttpRequest_bind_event(DispatchEx *dispex, int eid)
{
HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex);
nsIDOMEventTarget *nstarget;
nsAString type_str;
nsresult nsres;
FIXME("(%p)\n", This);
static const WCHAR readystatechangeW[] = {'r','e','a','d','y','s','t','a','t','e','c','h','a','n','g','e',0};
TRACE("(%p)\n", This);
assert(eid == EVENTID_READYSTATECHANGE);
if(This->event_listener)
return;
This->event_listener = heap_alloc(sizeof(*This->event_listener));
if(!This->event_listener)
return;
This->event_listener->nsIDOMEventListener_iface.lpVtbl = &XMLHttpReqEventListenerVtbl;
This->event_listener->ref = 1;
This->event_listener->xhr = This;
nsres = nsIXMLHttpRequest_QueryInterface(This->nsxhr, &IID_nsIDOMEventTarget, (void**)&nstarget);
assert(nsres == NS_OK);
nsAString_InitDepend(&type_str, readystatechangeW);
nsres = nsIDOMEventTarget_AddEventListener(nstarget, &type_str, &This->event_listener->nsIDOMEventListener_iface, FALSE, TRUE, 2);
nsAString_Finish(&type_str);
nsIDOMEventTarget_Release(nstarget);
if(NS_FAILED(nsres))
ERR("AddEventListener failed: %08x\n", nsres);
}
static dispex_static_data_vtbl_t HTMLXMLHttpRequest_dispex_vtbl = {