mshtml: Added support for binding XHR events.
This commit is contained in:
parent
7a3c9889e3
commit
8d85da757a
|
@ -256,7 +256,7 @@ static eventid_t attr_to_eid(LPCWSTR str)
|
||||||
return EVENTID_LAST;
|
return EVENTID_LAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
struct HTMLEventObj {
|
||||||
DispatchEx dispex;
|
DispatchEx dispex;
|
||||||
IHTMLEventObj IHTMLEventObj_iface;
|
IHTMLEventObj IHTMLEventObj_iface;
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ typedef struct {
|
||||||
VARIANT return_value;
|
VARIANT return_value;
|
||||||
BOOL prevent_default;
|
BOOL prevent_default;
|
||||||
BOOL cancel_bubble;
|
BOOL cancel_bubble;
|
||||||
} HTMLEventObj;
|
};
|
||||||
|
|
||||||
static inline HTMLEventObj *impl_from_IHTMLEventObj(IHTMLEventObj *iface)
|
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;
|
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)
|
ConnectionPointContainer *cp_container, eventid_t eid, IDispatch *this_obj)
|
||||||
{
|
{
|
||||||
event_target_t *data = get_event_target_data(event_target, FALSE);
|
event_target_t *data = get_event_target_data(event_target, FALSE);
|
||||||
|
|
|
@ -67,6 +67,9 @@ HRESULT create_event_obj(IHTMLEventObj**) DECLSPEC_HIDDEN;
|
||||||
void bind_target_event(HTMLDocumentNode*,EventTarget*,const WCHAR*,IDispatch*) DECLSPEC_HIDDEN;
|
void bind_target_event(HTMLDocumentNode*,EventTarget*,const WCHAR*,IDispatch*) DECLSPEC_HIDDEN;
|
||||||
HRESULT ensure_doc_nsevent_handler(HTMLDocumentNode*,eventid_t) 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 init_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN;
|
||||||
void release_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN;
|
void release_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN;
|
||||||
void add_nsevent_listener(HTMLDocumentNode*,nsIDOMNode*,LPCWSTR) DECLSPEC_HIDDEN;
|
void add_nsevent_listener(HTMLDocumentNode*,nsIDOMNode*,LPCWSTR) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -504,7 +504,7 @@ static void test_async_xhr(IHTMLDocument2 *doc, const char *xml_url)
|
||||||
SET_EXPECT(xmlhttprequest_onreadystatechange_opened);
|
SET_EXPECT(xmlhttprequest_onreadystatechange_opened);
|
||||||
hres = IHTMLXMLHttpRequest_open(xhr, method, url, vbool, vempty, vempty);
|
hres = IHTMLXMLHttpRequest_open(xhr, method, url, vbool, vempty, vempty);
|
||||||
ok(hres == S_OK, "open failed: %08x\n", hres);
|
ok(hres == S_OK, "open failed: %08x\n", hres);
|
||||||
todo_wine CHECK_CALLED(xmlhttprequest_onreadystatechange_opened);
|
CHECK_CALLED(xmlhttprequest_onreadystatechange_opened);
|
||||||
|
|
||||||
SysFreeString(method);
|
SysFreeString(method);
|
||||||
SysFreeString(url);
|
SysFreeString(url);
|
||||||
|
|
|
@ -60,14 +60,117 @@ static HRESULT variant_to_nsastr(VARIANT var, nsAString *ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IHTMLXMLHttpRequest */
|
typedef struct XMLHttpReqEventListener XMLHttpReqEventListener;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
EventTarget event_target;
|
EventTarget event_target;
|
||||||
IHTMLXMLHttpRequest IHTMLXMLHttpRequest_iface;
|
IHTMLXMLHttpRequest IHTMLXMLHttpRequest_iface;
|
||||||
LONG ref;
|
LONG ref;
|
||||||
nsIXMLHttpRequest *nsxhr;
|
nsIXMLHttpRequest *nsxhr;
|
||||||
|
XMLHttpReqEventListener *event_listener;
|
||||||
} HTMLXMLHttpRequest;
|
} 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)
|
static inline HTMLXMLHttpRequest *impl_from_IHTMLXMLHttpRequest(IHTMLXMLHttpRequest *iface)
|
||||||
{
|
{
|
||||||
return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, 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);
|
TRACE("(%p) ref=%d\n", This, ref);
|
||||||
|
|
||||||
if(!ref) {
|
if(!ref) {
|
||||||
|
if(This->event_listener)
|
||||||
|
detach_xhr_event_listener(This->event_listener);
|
||||||
release_dispex(&This->event_target.dispex);
|
release_dispex(&This->event_target.dispex);
|
||||||
nsIXMLHttpRequest_Release(This->nsxhr);
|
nsIXMLHttpRequest_Release(This->nsxhr);
|
||||||
heap_free(This);
|
heap_free(This);
|
||||||
|
@ -357,10 +462,36 @@ static inline HTMLXMLHttpRequest *impl_from_DispatchEx(DispatchEx *iface)
|
||||||
static void HTMLXMLHttpRequest_bind_event(DispatchEx *dispex, int eid)
|
static void HTMLXMLHttpRequest_bind_event(DispatchEx *dispex, int eid)
|
||||||
{
|
{
|
||||||
HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex);
|
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);
|
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 = {
|
static dispex_static_data_vtbl_t HTMLXMLHttpRequest_dispex_vtbl = {
|
||||||
|
|
Loading…
Reference in New Issue