-- v4: mshtml: Implement contentType for XDomainRequest. mshtml: Implement timeout for XDomainRequest. mshtml: Implement XDomainRequest.open(). mshtml: Add XDomainRequest factory implementation. mshtml: Factor out XMLHttpRequest's send. mshtml: Factor out XMLHttpRequest's open. mshtml: Factor out XMLHttpRequest's abort. mshtml: Factor out XMLHttpRequest's get_responseText. mshtml: Separate the ifaces and the other XHR fields. mshtml: Factor out XMLHttpRequest constructor init. mshtml: Factor out XMLHttpRequest creation.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
So it can be shared with XDomainRequest constructors.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/xmlhttprequest.c | 43 ++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 16 deletions(-)
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index e6029b85bb2..5f4d16fba1d 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -1503,19 +1503,16 @@ static inline struct constructor *impl_from_IHTMLXMLHttpRequestFactory(IHTMLXMLH DISPEX_IDISPATCH_IMPL(HTMLXMLHttpRequestFactory, IHTMLXMLHttpRequestFactory, impl_from_IHTMLXMLHttpRequestFactory(iface)->dispex)
-static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactory *iface, IHTMLXMLHttpRequest **p) +static HRESULT create_xhr(HTMLInnerWindow *window, dispex_static_data_t *dispex, HTMLXMLHttpRequest **p) { - struct constructor *This = impl_from_IHTMLXMLHttpRequestFactory(iface); - HTMLXMLHttpRequest *ret; - nsIXMLHttpRequest *nsxhr; - nsIDOMEventTarget *nstarget; - XMLHttpReqEventListener *event_listener; + XMLHttpReqEventListener *event_listener; + nsIDOMEventTarget *nstarget; + nsIXMLHttpRequest *nsxhr; + HTMLXMLHttpRequest *ret; nsresult nsres; unsigned i;
- TRACE("(%p)->(%p)\n", This, p); - - nsxhr = create_nsxhr(This->window->dom_window); + nsxhr = create_nsxhr(window->dom_window); if(!nsxhr) return E_FAIL;
@@ -1533,15 +1530,15 @@ static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactor }
ret->nsxhr = nsxhr; - ret->window = This->window; + ret->window = window; ret->task_magic = get_task_target_magic(); - IHTMLWindow2_AddRef(&This->window->base.IHTMLWindow2_iface); + IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
ret->IHTMLXMLHttpRequest_iface.lpVtbl = &HTMLXMLHttpRequestVtbl; ret->IHTMLXMLHttpRequest2_iface.lpVtbl = &HTMLXMLHttpRequest2Vtbl; ret->IWineXMLHttpRequestPrivate_iface.lpVtbl = &WineXMLHttpRequestPrivateVtbl; ret->IProvideClassInfo2_iface.lpVtbl = &ProvideClassInfo2Vtbl; - init_event_target(&ret->event_target, &XMLHttpRequest_dispex, This->window); + init_event_target(&ret->event_target, dispex, window);
/* Always register the handlers because we need them to track state */ event_listener->nsIDOMEventListener_iface.lpVtbl = &XMLHttpReqEventListenerVtbl; @@ -1567,10 +1564,24 @@ static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactor } nsIDOMEventTarget_Release(nstarget);
- *p = &ret->IHTMLXMLHttpRequest_iface; + *p = ret; return S_OK; }
+static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactory *iface, IHTMLXMLHttpRequest **p) +{ + struct constructor *This = impl_from_IHTMLXMLHttpRequestFactory(iface); + HTMLXMLHttpRequest *xhr; + HRESULT hres; + + TRACE("(%p)->(%p)\n", This, p); + + hres = create_xhr(This->window, &XMLHttpRequest_dispex, &xhr); + if(SUCCEEDED(hres)) + *p = &xhr->IHTMLXMLHttpRequest_iface; + return hres; +} + static const IHTMLXMLHttpRequestFactoryVtbl HTMLXMLHttpRequestFactoryVtbl = { HTMLXMLHttpRequestFactory_QueryInterface, HTMLXMLHttpRequestFactory_AddRef, @@ -1596,7 +1607,7 @@ static HRESULT HTMLXMLHttpRequestFactory_value(DispatchEx *iface, LCID lcid, WOR VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { struct constructor *This = constructor_from_DispatchEx(iface); - IHTMLXMLHttpRequest *xhr; + HTMLXMLHttpRequest *xhr; HRESULT hres;
TRACE("\n"); @@ -1606,12 +1617,12 @@ static HRESULT HTMLXMLHttpRequestFactory_value(DispatchEx *iface, LCID lcid, WOR return E_NOTIMPL; }
- hres = IHTMLXMLHttpRequestFactory_create((IHTMLXMLHttpRequestFactory*)&This->iface, &xhr); + hres = create_xhr(This->window, &XMLHttpRequest_dispex, &xhr); if(FAILED(hres)) return hres;
V_VT(res) = VT_DISPATCH; - V_DISPATCH(res) = (IDispatch*)xhr; + V_DISPATCH(res) = (IDispatch*)&xhr->IHTMLXMLHttpRequest_iface; return S_OK; }
From: Gabriel Ivăncescu gabrielopcode@gmail.com
So it can be shared with XDomainRequest constructors.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/xmlhttprequest.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index 5f4d16fba1d..3dd4561e6ff 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -1646,14 +1646,13 @@ static dispex_static_data_t HTMLXMLHttpRequestFactory_dispex = { .iface_tids = HTMLXMLHttpRequestFactory_iface_tids, };
-static HRESULT HTMLXMLHttpRequestFactory_init(struct constructor *constr) +static HRESULT init_constructor(struct constructor *constr, dispex_static_data_t *dispex, const void *vtbl) { struct constructor *create; HRESULT hres;
- constr->iface.lpVtbl = (const IUnknownVtbl*)&HTMLXMLHttpRequestFactoryVtbl; - init_dispatch(&constr->dispex, &HTMLXMLHttpRequestFactory_dispex, constr->window, - dispex_compat_mode(&constr->window->event_target.dispex)); + constr->iface.lpVtbl = vtbl; + init_dispatch(&constr->dispex, dispex, constr->window, dispex_compat_mode(&constr->window->event_target.dispex));
if(!constr->window->jscript) return S_OK; @@ -1679,6 +1678,11 @@ static HRESULT HTMLXMLHttpRequestFactory_init(struct constructor *constr) return hres; }
+static HRESULT HTMLXMLHttpRequestFactory_init(struct constructor *constr) +{ + return init_constructor(constr, &HTMLXMLHttpRequestFactory_dispex, &HTMLXMLHttpRequestFactoryVtbl); +} + static const tid_t HTMLXMLHttpRequest_iface_tids[] = { IHTMLXMLHttpRequest2_tid, 0
From: Gabriel Ivăncescu gabrielopcode@gmail.com
So it can be shared with XDomainRequests.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/xmlhttprequest.c | 277 +++++++++++++++++++---------------- 1 file changed, 149 insertions(+), 128 deletions(-)
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index 3dd4561e6ff..a75a8552ddc 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -127,15 +127,11 @@ static const struct { typedef struct { nsIDOMEventListener nsIDOMEventListener_iface; LONG ref; - HTMLXMLHttpRequest *xhr; + struct xhr *xhr; } XMLHttpReqEventListener;
-struct HTMLXMLHttpRequest { +struct xhr { EventTarget event_target; - IHTMLXMLHttpRequest IHTMLXMLHttpRequest_iface; - IHTMLXMLHttpRequest2 IHTMLXMLHttpRequest2_iface; - IWineXMLHttpRequestPrivate IWineXMLHttpRequestPrivate_iface; - IProvideClassInfo2 IProvideClassInfo2_iface; LONG task_magic; LONG ready_state; response_type_t response_type; @@ -148,6 +144,14 @@ struct HTMLXMLHttpRequest { DOMEvent *pending_progress_event; };
+struct HTMLXMLHttpRequest { + struct xhr xhr; + IHTMLXMLHttpRequest IHTMLXMLHttpRequest_iface; + IHTMLXMLHttpRequest2 IHTMLXMLHttpRequest2_iface; + IWineXMLHttpRequestPrivate IWineXMLHttpRequestPrivate_iface; + IProvideClassInfo2 IProvideClassInfo2_iface; +}; + static void detach_xhr_event_listener(XMLHttpReqEventListener *event_listener) { nsIDOMEventTarget *event_target; @@ -171,7 +175,7 @@ static void detach_xhr_event_listener(XMLHttpReqEventListener *event_listener) nsIDOMEventListener_Release(&event_listener->nsIDOMEventListener_iface); }
-static void synthesize_pending_events(HTMLXMLHttpRequest *xhr) +static void synthesize_pending_events(struct xhr *xhr) { DWORD magic = xhr->pending_events_magic; UINT16 ready_state = xhr->ready_state; @@ -199,7 +203,7 @@ static void synthesize_pending_events(HTMLXMLHttpRequest *xhr) xhr->ready_state = max(xhr->ready_state, READYSTATE_INTERACTIVE); }
- IHTMLXMLHttpRequest_AddRef(&xhr->IHTMLXMLHttpRequest_iface); + IWineJSDispatchHost_AddRef(&xhr->event_target.dispex.IWineJSDispatchHost_iface);
send_loadend = send_load = (xhr->ready_state != ready_state && ready_state == READYSTATE_COMPLETE); for(;;) { @@ -254,14 +258,14 @@ static void synthesize_pending_events(HTMLXMLHttpRequest *xhr) }
ret: - IHTMLXMLHttpRequest_Release(&xhr->IHTMLXMLHttpRequest_iface); + IWineJSDispatchHost_Release(&xhr->event_target.dispex.IWineJSDispatchHost_iface); }
-static nsresult sync_xhr_send(HTMLXMLHttpRequest *xhr, nsIVariant *nsbody) +static nsresult sync_xhr_send(struct xhr *xhr, nsIVariant *nsbody) { thread_data_t *thread_data = get_thread_data(TRUE); - HTMLXMLHttpRequest *prev_blocking_xhr; HTMLInnerWindow *window = xhr->window; + struct xhr *prev_blocking_xhr; unsigned prev_tasks_locked; nsresult nsres;
@@ -321,7 +325,7 @@ static nsresult sync_xhr_send(HTMLXMLHttpRequest *xhr, nsIVariant *nsbody)
struct pending_xhr_events_task { event_task_t header; - HTMLXMLHttpRequest *xhr; + struct xhr *xhr; };
static void pending_xhr_events_proc(event_task_t *_task) @@ -389,7 +393,7 @@ static nsrefcnt NSAPI XMLHttpReqEventListener_Release(nsIDOMEventListener *iface static nsresult NSAPI XMLHttpReqEventListener_HandleEvent(nsIDOMEventListener *iface, nsIDOMEvent *nsevent) { XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface); - HTMLXMLHttpRequest *blocking_xhr = NULL; + struct xhr *blocking_xhr = NULL; thread_data_t *thread_data; compat_mode_t compat_mode; LONG ready_state; @@ -517,7 +521,7 @@ static inline HTMLXMLHttpRequest *impl_from_IHTMLXMLHttpRequest(IHTMLXMLHttpRequ }
DISPEX_IDISPATCH_IMPL(HTMLXMLHttpRequest, IHTMLXMLHttpRequest, - impl_from_IHTMLXMLHttpRequest(iface)->event_target.dispex) + impl_from_IHTMLXMLHttpRequest(iface)->xhr.event_target.dispex)
static HRESULT WINAPI HTMLXMLHttpRequest_get_readyState(IHTMLXMLHttpRequest *iface, LONG *p) { @@ -527,7 +531,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_get_readyState(IHTMLXMLHttpRequest *ifa
if(!p) return E_POINTER; - *p = This->ready_state; + *p = This->xhr.ready_state; return S_OK; }
@@ -549,13 +553,13 @@ static HRESULT WINAPI HTMLXMLHttpRequest_get_responseText(IHTMLXMLHttpRequest *i if(!p) return E_POINTER;
- if(This->ready_state < READYSTATE_INTERACTIVE) { + if(This->xhr.ready_state < READYSTATE_INTERACTIVE) { *p = NULL; return S_OK; }
nsAString_Init(&nsstr, NULL); - nsres = nsIXMLHttpRequest_GetResponseText(This->nsxhr, &nsstr); + nsres = nsIXMLHttpRequest_GetResponseText(This->xhr.nsxhr, &nsstr); return return_nsstr(nsres, &nsstr, p); }
@@ -570,17 +574,17 @@ static HRESULT WINAPI HTMLXMLHttpRequest_get_responseXML(IHTMLXMLHttpRequest *if
TRACE("(%p)->(%p)\n", This, p);
- if(This->ready_state < READYSTATE_COMPLETE) { + if(This->xhr.ready_state < READYSTATE_COMPLETE) { *p = NULL; return S_OK; }
- if(dispex_compat_mode(&This->event_target.dispex) >= COMPAT_MODE_IE10) { + if(dispex_compat_mode(&This->xhr.event_target.dispex) >= COMPAT_MODE_IE10) { HTMLDocumentNode *doc; nsIDOMDocument *nsdoc; nsresult nsres;
- nsres = nsIXMLHttpRequest_GetResponseXML(This->nsxhr, &nsdoc); + nsres = nsIXMLHttpRequest_GetResponseXML(This->xhr.nsxhr, &nsdoc); if(NS_FAILED(nsres)) return map_nsresult(nsres); if(!nsdoc) { @@ -588,11 +592,11 @@ static HRESULT WINAPI HTMLXMLHttpRequest_get_responseXML(IHTMLXMLHttpRequest *if return S_OK; }
- if(!This->window->base.outer_window || !This->window->base.outer_window->browser) + if(!This->xhr.window->base.outer_window || !This->xhr.window->base.outer_window->browser) hres = E_UNEXPECTED; else - hres = create_document_node(nsdoc, This->window->base.outer_window->browser, NULL, This->window, - dispex_compat_mode(&This->window->event_target.dispex), &doc); + hres = create_document_node(nsdoc, This->xhr.window->base.outer_window->browser, NULL, This->xhr.window, + dispex_compat_mode(&This->xhr.window->event_target.dispex), &doc); nsIDOMDocument_Release(nsdoc); if(FAILED(hres)) return hres; @@ -641,12 +645,12 @@ static HRESULT WINAPI HTMLXMLHttpRequest_get_status(IHTMLXMLHttpRequest *iface, if(!p) return E_POINTER;
- if(This->ready_state < READYSTATE_LOADED) { + if(This->xhr.ready_state < READYSTATE_LOADED) { *p = 0; return E_FAIL; }
- nsres = nsIXMLHttpRequest_GetStatus(This->nsxhr, &val); + nsres = nsIXMLHttpRequest_GetStatus(This->xhr.nsxhr, &val); if(NS_FAILED(nsres)) { ERR("nsIXMLHttpRequest_GetStatus failed: %08lx\n", nsres); return E_FAIL; @@ -669,13 +673,13 @@ static HRESULT WINAPI HTMLXMLHttpRequest_get_statusText(IHTMLXMLHttpRequest *ifa if(!p) return E_POINTER;
- if(This->ready_state < READYSTATE_LOADED) { + if(This->xhr.ready_state < READYSTATE_LOADED) { *p = NULL; return E_FAIL; }
nsACString_Init(&nscstr, NULL); - nsres = nsIXMLHttpRequest_GetStatusText(This->nsxhr, &nscstr); + nsres = nsIXMLHttpRequest_GetStatusText(This->xhr.nsxhr, &nscstr); return return_nscstr(nsres, &nscstr, p); }
@@ -685,7 +689,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_put_onreadystatechange(IHTMLXMLHttpRequ
TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
- return set_event_handler(&This->event_target, EVENTID_READYSTATECHANGE, &v); + return set_event_handler(&This->xhr.event_target, EVENTID_READYSTATECHANGE, &v); }
static HRESULT WINAPI HTMLXMLHttpRequest_get_onreadystatechange(IHTMLXMLHttpRequest *iface, VARIANT *p) @@ -694,30 +698,30 @@ static HRESULT WINAPI HTMLXMLHttpRequest_get_onreadystatechange(IHTMLXMLHttpRequ
TRACE("(%p)->(%p)\n", This, p);
- return get_event_handler(&This->event_target, EVENTID_READYSTATECHANGE, p); + return get_event_handler(&This->xhr.event_target, EVENTID_READYSTATECHANGE, p); }
static HRESULT WINAPI HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest *iface) { HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface); - DWORD prev_magic = This->magic; + DWORD prev_magic = This->xhr.magic; UINT16 ready_state; nsresult nsres;
TRACE("(%p)->()\n", This);
- This->magic++; - nsres = nsIXMLHttpRequest_SlowAbort(This->nsxhr); + This->xhr.magic++; + nsres = nsIXMLHttpRequest_SlowAbort(This->xhr.nsxhr); if(NS_FAILED(nsres)) { ERR("nsIXMLHttpRequest_SlowAbort failed: %08lx\n", nsres); - This->magic = prev_magic; + This->xhr.magic = prev_magic; return E_FAIL; }
/* Gecko changed to READYSTATE_UNINITIALIZED if it did abort */ - nsres = nsIXMLHttpRequest_GetReadyState(This->nsxhr, &ready_state); + nsres = nsIXMLHttpRequest_GetReadyState(This->xhr.nsxhr, &ready_state); if(NS_SUCCEEDED(nsres)) - This->ready_state = ready_state; + This->xhr.ready_state = ready_state; return S_OK; }
@@ -789,16 +793,16 @@ static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR b }
/* Set this here, Gecko dispatches nested sync XHR readyState changes for OPENED (see HandleEvent) */ - prev_magic = This->magic; - prev_synchronous = This->synchronous; - This->synchronous = !V_BOOL(&varAsync); - This->magic++; + prev_magic = This->xhr.magic; + prev_synchronous = This->xhr.synchronous; + This->xhr.synchronous = !V_BOOL(&varAsync); + This->xhr.magic++;
if(V_VT(&varPassword) != VT_EMPTY && V_VT(&varPassword) != VT_ERROR) opt_argc += 2; else if(V_VT(&varUser) != VT_EMPTY && V_VT(&varUser) != VT_ERROR) opt_argc += 1; - nsres = nsIXMLHttpRequest_Open(This->nsxhr, &method, &url, !!V_BOOL(&varAsync), &user, &password, opt_argc); + nsres = nsIXMLHttpRequest_Open(This->xhr.nsxhr, &method, &url, !!V_BOOL(&varAsync), &user, &password, opt_argc);
nsACString_Finish(&method); nsACString_Finish(&url); @@ -807,8 +811,8 @@ static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR b
if(NS_FAILED(nsres)) { ERR("nsIXMLHttpRequest_Open failed: %08lx\n", nsres); - This->magic = prev_magic; - This->synchronous = prev_synchronous; + This->xhr.magic = prev_magic; + This->xhr.synchronous = prev_synchronous; return E_FAIL; }
@@ -846,10 +850,10 @@ static HRESULT WINAPI HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest *iface, VARIAN }
if(NS_SUCCEEDED(nsres)) { - if(This->synchronous) - nsres = sync_xhr_send(This, (nsIVariant*)nsbody); + if(This->xhr.synchronous) + nsres = sync_xhr_send(&This->xhr, (nsIVariant*)nsbody); else - nsres = nsIXMLHttpRequest_Send(This->nsxhr, (nsIVariant*)nsbody); + nsres = nsIXMLHttpRequest_Send(This->xhr.nsxhr, (nsIVariant*)nsbody); }
if(nsbody) @@ -873,13 +877,13 @@ static HRESULT WINAPI HTMLXMLHttpRequest_getAllResponseHeaders(IHTMLXMLHttpReque if(!p) return E_POINTER;
- if(This->ready_state < READYSTATE_LOADED) { + if(This->xhr.ready_state < READYSTATE_LOADED) { *p = NULL; return E_FAIL; }
nsACString_Init(&nscstr, NULL); - nsres = nsIXMLHttpRequest_GetAllResponseHeaders(This->nsxhr, &nscstr); + nsres = nsIXMLHttpRequest_GetAllResponseHeaders(This->xhr.nsxhr, &nscstr); return return_nscstr(nsres, &nscstr, p); }
@@ -896,7 +900,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_getResponseHeader(IHTMLXMLHttpRequest * if(!bstrHeader) return E_INVALIDARG;
- if(This->ready_state < READYSTATE_LOADED) { + if(This->xhr.ready_state < READYSTATE_LOADED) { *p = NULL; return E_FAIL; } @@ -905,7 +909,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_getResponseHeader(IHTMLXMLHttpRequest * nsACString_InitDepend(&header, cstr); nsACString_Init(&ret, NULL);
- nsres = nsIXMLHttpRequest_GetResponseHeader(This->nsxhr, &header, &ret); + nsres = nsIXMLHttpRequest_GetResponseHeader(This->xhr.nsxhr, &header, &ret);
nsACString_Finish(&header); free(cstr); @@ -933,7 +937,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_setRequestHeader(IHTMLXMLHttpRequest *i
nsACString_InitDepend(&header, header_u); nsACString_InitDepend(&value, value_u); - nsres = nsIXMLHttpRequest_SetRequestHeader(This->nsxhr, &header, &value); + nsres = nsIXMLHttpRequest_SetRequestHeader(This->xhr.nsxhr, &header, &value); nsACString_Finish(&header); nsACString_Finish(&value); free(header_u); @@ -976,7 +980,7 @@ static inline HTMLXMLHttpRequest *impl_from_IHTMLXMLHttpRequest2(IHTMLXMLHttpReq }
DISPEX_IDISPATCH_IMPL(HTMLXMLHttpRequest2, IHTMLXMLHttpRequest2, - impl_from_IHTMLXMLHttpRequest2(iface)->event_target.dispex) + impl_from_IHTMLXMLHttpRequest2(iface)->xhr.event_target.dispex)
static HRESULT WINAPI HTMLXMLHttpRequest2_put_timeout(IHTMLXMLHttpRequest2 *iface, LONG v) { @@ -986,7 +990,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest2_put_timeout(IHTMLXMLHttpRequest2 *ifac
if(v < 0) return E_INVALIDARG; - return map_nsresult(nsIXMLHttpRequest_SetTimeout(This->nsxhr, v)); + return map_nsresult(nsIXMLHttpRequest_SetTimeout(This->xhr.nsxhr, v)); }
static HRESULT WINAPI HTMLXMLHttpRequest2_get_timeout(IHTMLXMLHttpRequest2 *iface, LONG *p) @@ -1000,7 +1004,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest2_get_timeout(IHTMLXMLHttpRequest2 *ifac if(!p) return E_POINTER;
- nsres = nsIXMLHttpRequest_GetTimeout(This->nsxhr, &timeout); + nsres = nsIXMLHttpRequest_GetTimeout(This->xhr.nsxhr, &timeout); *p = timeout; return map_nsresult(nsres); } @@ -1011,7 +1015,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest2_put_ontimeout(IHTMLXMLHttpRequest2 *if
TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
- return set_event_handler(&This->event_target, EVENTID_TIMEOUT, &v); + return set_event_handler(&This->xhr.event_target, EVENTID_TIMEOUT, &v); }
static HRESULT WINAPI HTMLXMLHttpRequest2_get_ontimeout(IHTMLXMLHttpRequest2 *iface, VARIANT *p) @@ -1020,7 +1024,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest2_get_ontimeout(IHTMLXMLHttpRequest2 *if
TRACE("(%p)->(%p)\n", This, p);
- return get_event_handler(&This->event_target, EVENTID_TIMEOUT, p); + return get_event_handler(&This->xhr.event_target, EVENTID_TIMEOUT, p); }
static const IHTMLXMLHttpRequest2Vtbl HTMLXMLHttpRequest2Vtbl = { @@ -1043,7 +1047,7 @@ static inline HTMLXMLHttpRequest *impl_from_IWineXMLHttpRequestPrivate(IWineXMLH }
DISPEX_IDISPATCH_IMPL(HTMLXMLHttpRequest_private, IWineXMLHttpRequestPrivate, - impl_from_IWineXMLHttpRequestPrivate(iface)->event_target.dispex) + impl_from_IWineXMLHttpRequestPrivate(iface)->xhr.event_target.dispex)
static HRESULT WINAPI HTMLXMLHttpRequest_private_get_response(IWineXMLHttpRequestPrivate *iface, VARIANT *p) { @@ -1052,7 +1056,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_get_response(IWineXMLHttpReques
TRACE("(%p)->(%p)\n", This, p);
- switch(This->response_type) { + switch(This->xhr.response_type) { case response_type_empty: case response_type_text: hres = IHTMLXMLHttpRequest_get_responseText(&This->IHTMLXMLHttpRequest_iface, &V_BSTR(p)); @@ -1066,11 +1070,11 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_get_response(IWineXMLHttpReques
case response_type_arraybuf: case response_type_blob: - if(This->ready_state < READYSTATE_COMPLETE) { + if(This->xhr.ready_state < READYSTATE_COMPLETE) { V_VT(p) = VT_EMPTY; break; } - if(This->response_type == response_type_arraybuf) { + if(This->xhr.response_type == response_type_arraybuf) { FIXME("response_type_arraybuf\n"); return E_NOTIMPL; } @@ -1097,7 +1101,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_put_responseType(IWineXMLHttpRe
TRACE("(%p)->(%s)\n", This, debugstr_w(v));
- if(This->ready_state < READYSTATE_LOADING || This->ready_state > READYSTATE_INTERACTIVE) { + if(This->xhr.ready_state < READYSTATE_LOADING || This->xhr.ready_state > READYSTATE_INTERACTIVE) { /* FIXME: Return InvalidStateError */ return E_FAIL; } @@ -1109,12 +1113,12 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_put_responseType(IWineXMLHttpRe return S_OK;
nsAString_InitDepend(&nsstr, response_type_desc[i].nsxhr_str); - nsres = nsIXMLHttpRequest_SetResponseType(This->nsxhr, &nsstr); + nsres = nsIXMLHttpRequest_SetResponseType(This->xhr.nsxhr, &nsstr); nsAString_Finish(&nsstr); if(NS_FAILED(nsres)) return map_nsresult(nsres);
- This->response_type = i; + This->xhr.response_type = i; return S_OK; }
@@ -1124,7 +1128,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_get_responseType(IWineXMLHttpRe
TRACE("(%p)->(%p)\n", This, p);
- *p = SysAllocString(response_type_desc[This->response_type].str); + *p = SysAllocString(response_type_desc[This->xhr.response_type].str); return *p ? S_OK : E_OUTOFMEMORY; }
@@ -1143,7 +1147,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_put_withCredentials(IWineXMLHtt
TRACE("(%p)->(%x)\n", This, v);
- return map_nsresult(nsIXMLHttpRequest_SetWithCredentials(This->nsxhr, !!v)); + return map_nsresult(nsIXMLHttpRequest_SetWithCredentials(This->xhr.nsxhr, !!v)); }
static HRESULT WINAPI HTMLXMLHttpRequest_private_get_withCredentials(IWineXMLHttpRequestPrivate *iface, VARIANT_BOOL *p) @@ -1154,7 +1158,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_get_withCredentials(IWineXMLHtt
TRACE("(%p)->(%p)\n", This, p);
- nsres = nsIXMLHttpRequest_GetWithCredentials(This->nsxhr, &b); + nsres = nsIXMLHttpRequest_GetWithCredentials(This->xhr.nsxhr, &b); if(NS_FAILED(nsres)) return map_nsresult(nsres); *p = b ? VARIANT_TRUE : VARIANT_FALSE; @@ -1183,7 +1187,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_overrideMimeType(IWineXMLHttpRe }
nsAString_InitDepend(&nsstr, type); - nsres = nsIXMLHttpRequest_SlowOverrideMimeType(This->nsxhr, &nsstr); + nsres = nsIXMLHttpRequest_SlowOverrideMimeType(This->xhr.nsxhr, &nsstr); nsAString_Finish(&nsstr); free(lowercase); return map_nsresult(nsres); @@ -1195,7 +1199,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onerror(IWineXMLHttpRequest
TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
- return set_event_handler(&This->event_target, EVENTID_ERROR, &v); + return set_event_handler(&This->xhr.event_target, EVENTID_ERROR, &v); }
static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onerror(IWineXMLHttpRequestPrivate *iface, VARIANT *p) @@ -1204,7 +1208,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onerror(IWineXMLHttpRequest
TRACE("(%p)->(%p)\n", This, p);
- return get_event_handler(&This->event_target, EVENTID_ERROR, p); + return get_event_handler(&This->xhr.event_target, EVENTID_ERROR, p); }
static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onabort(IWineXMLHttpRequestPrivate *iface, VARIANT v) @@ -1213,7 +1217,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onabort(IWineXMLHttpRequest
TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
- return set_event_handler(&This->event_target, EVENTID_ABORT, &v); + return set_event_handler(&This->xhr.event_target, EVENTID_ABORT, &v); }
static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onabort(IWineXMLHttpRequestPrivate *iface, VARIANT *p) @@ -1222,7 +1226,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onabort(IWineXMLHttpRequest
TRACE("(%p)->(%p)\n", This, p);
- return get_event_handler(&This->event_target, EVENTID_ABORT, p); + return get_event_handler(&This->xhr.event_target, EVENTID_ABORT, p); }
static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onprogress(IWineXMLHttpRequestPrivate *iface, VARIANT v) @@ -1231,7 +1235,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onprogress(IWineXMLHttpRequ
TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
- return set_event_handler(&This->event_target, EVENTID_PROGRESS, &v); + return set_event_handler(&This->xhr.event_target, EVENTID_PROGRESS, &v); }
static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onprogress(IWineXMLHttpRequestPrivate *iface, VARIANT *p) @@ -1240,7 +1244,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onprogress(IWineXMLHttpRequ
TRACE("(%p)->(%p)\n", This, p);
- return get_event_handler(&This->event_target, EVENTID_PROGRESS, p); + return get_event_handler(&This->xhr.event_target, EVENTID_PROGRESS, p); }
static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onloadstart(IWineXMLHttpRequestPrivate *iface, VARIANT v) @@ -1249,7 +1253,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onloadstart(IWineXMLHttpReq
TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
- return set_event_handler(&This->event_target, EVENTID_LOADSTART, &v); + return set_event_handler(&This->xhr.event_target, EVENTID_LOADSTART, &v); }
static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onloadstart(IWineXMLHttpRequestPrivate *iface, VARIANT *p) @@ -1258,7 +1262,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onloadstart(IWineXMLHttpReq
TRACE("(%p)->(%p)\n", This, p);
- return get_event_handler(&This->event_target, EVENTID_LOADSTART, p); + return get_event_handler(&This->xhr.event_target, EVENTID_LOADSTART, p); }
static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onloadend(IWineXMLHttpRequestPrivate *iface, VARIANT v) @@ -1267,7 +1271,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onloadend(IWineXMLHttpReque
TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
- return set_event_handler(&This->event_target, EVENTID_LOADEND, &v); + return set_event_handler(&This->xhr.event_target, EVENTID_LOADEND, &v); }
static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onloadend(IWineXMLHttpRequestPrivate *iface, VARIANT *p) @@ -1276,7 +1280,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onloadend(IWineXMLHttpReque
TRACE("(%p)->(%p)\n", This, p);
- return get_event_handler(&This->event_target, EVENTID_LOADEND, p); + return get_event_handler(&This->xhr.event_target, EVENTID_LOADEND, p); }
static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onload(IWineXMLHttpRequestPrivate *iface, VARIANT v) @@ -1285,7 +1289,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onload(IWineXMLHttpRequestP
TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
- return set_event_handler(&This->event_target, EVENTID_LOAD, &v); + return set_event_handler(&This->xhr.event_target, EVENTID_LOAD, &v); }
static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onload(IWineXMLHttpRequestPrivate *iface, VARIANT *p) @@ -1294,7 +1298,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onload(IWineXMLHttpRequestP
TRACE("(%p)->(%p)\n", This, p);
- return get_event_handler(&This->event_target, EVENTID_LOAD, p); + return get_event_handler(&This->xhr.event_target, EVENTID_LOAD, p); }
static const IWineXMLHttpRequestPrivateVtbl WineXMLHttpRequestPrivateVtbl = { @@ -1373,7 +1377,12 @@ static const IProvideClassInfo2Vtbl ProvideClassInfo2Vtbl = {
static inline HTMLXMLHttpRequest *impl_from_DispatchEx(DispatchEx *iface) { - return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, event_target.dispex); + return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, xhr.event_target.dispex); +} + +static inline struct xhr *xhr_from_DispatchEx(DispatchEx *iface) +{ + return CONTAINING_RECORD(iface, struct xhr, event_target.dispex); }
static void *HTMLXMLHttpRequest_query_interface(DispatchEx *dispex, REFIID riid) @@ -1391,62 +1400,62 @@ static void *HTMLXMLHttpRequest_query_interface(DispatchEx *dispex, REFIID riid) if(IsEqualGUID(&IID_IProvideClassInfo2, riid)) return &This->IProvideClassInfo2_iface;
- return EventTarget_query_interface(&This->event_target, riid); + return EventTarget_query_interface(&This->xhr.event_target, riid); }
-static void HTMLXMLHttpRequest_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb) +static void xhr_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb) { - HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex); - if(This->window) - note_cc_edge((nsISupports*)&This->window->base.IHTMLWindow2_iface, "window", cb); - if(This->pending_progress_event) - note_cc_edge((nsISupports*)&This->pending_progress_event->IDOMEvent_iface, "pending_progress_event", cb); - if(This->nsxhr) - note_cc_edge((nsISupports*)This->nsxhr, "nsxhr", cb); - traverse_event_target(&This->event_target, cb); + struct xhr *xhr = xhr_from_DispatchEx(dispex); + if(xhr->window) + note_cc_edge((nsISupports*)&xhr->window->base.IHTMLWindow2_iface, "window", cb); + if(xhr->pending_progress_event) + note_cc_edge((nsISupports*)&xhr->pending_progress_event->IDOMEvent_iface, "pending_progress_event", cb); + if(xhr->nsxhr) + note_cc_edge((nsISupports*)xhr->nsxhr, "nsxhr", cb); + traverse_event_target(&xhr->event_target, cb); }
-static void HTMLXMLHttpRequest_unlink(DispatchEx *dispex) +static void xhr_unlink(DispatchEx *dispex) { - HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex); - if(This->event_listener) { - XMLHttpReqEventListener *event_listener = This->event_listener; - This->event_listener = NULL; + struct xhr *xhr = xhr_from_DispatchEx(dispex); + if(xhr->event_listener) { + XMLHttpReqEventListener *event_listener = xhr->event_listener; + xhr->event_listener = NULL; detach_xhr_event_listener(event_listener); } - if(This->window) { - HTMLInnerWindow *window = This->window; - This->window = NULL; + if(xhr->window) { + HTMLInnerWindow *window = xhr->window; + xhr->window = NULL; IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); } - if(This->pending_progress_event) { - DOMEvent *pending_progress_event = This->pending_progress_event; - This->pending_progress_event = NULL; + if(xhr->pending_progress_event) { + DOMEvent *pending_progress_event = xhr->pending_progress_event; + xhr->pending_progress_event = NULL; IDOMEvent_Release(&pending_progress_event->IDOMEvent_iface); } - unlink_ref(&This->nsxhr); - release_event_target(&This->event_target); + unlink_ref(&xhr->nsxhr); + release_event_target(&xhr->event_target); }
-static void HTMLXMLHttpRequest_destructor(DispatchEx *dispex) +static void xhr_destructor(DispatchEx *dispex) { - HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex); - free(This); + struct xhr *xhr = xhr_from_DispatchEx(dispex); + free(xhr); }
-static void HTMLXMLHttpRequest_last_release(DispatchEx *dispex) +static void xhr_last_release(DispatchEx *dispex) { - HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex); - remove_target_tasks(This->task_magic); + struct xhr *xhr = xhr_from_DispatchEx(dispex); + remove_target_tasks(xhr->task_magic); }
-static nsISupports *HTMLXMLHttpRequest_get_gecko_target(DispatchEx *dispex) +static nsISupports *xhr_get_gecko_target(DispatchEx *dispex) { - HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex); - return (nsISupports*)This->nsxhr; + struct xhr *xhr = xhr_from_DispatchEx(dispex); + return (nsISupports*)xhr->nsxhr; }
-static void HTMLXMLHttpRequest_bind_event(DispatchEx *dispex, eventid_t eid) +static void xhr_bind_event(DispatchEx *dispex, eventid_t eid) { /* Do nothing. To be able to track state and queue events manually, when blocked * by sync XHRs in their send() event loop, we always register the handlers. */ @@ -1485,13 +1494,13 @@ static void HTMLXMLHttpRequest_init_dispex_info(dispex_data_t *info, compat_mode static const event_target_vtbl_t HTMLXMLHttpRequest_event_target_vtbl = { { .query_interface = HTMLXMLHttpRequest_query_interface, - .destructor = HTMLXMLHttpRequest_destructor, - .traverse = HTMLXMLHttpRequest_traverse, - .unlink = HTMLXMLHttpRequest_unlink, - .last_release = HTMLXMLHttpRequest_last_release + .destructor = xhr_destructor, + .traverse = xhr_traverse, + .unlink = xhr_unlink, + .last_release = xhr_last_release }, - .get_gecko_target = HTMLXMLHttpRequest_get_gecko_target, - .bind_event = HTMLXMLHttpRequest_bind_event + .get_gecko_target = xhr_get_gecko_target, + .bind_event = xhr_bind_event };
/* IHTMLXMLHttpRequestFactory */ @@ -1503,12 +1512,12 @@ static inline struct constructor *impl_from_IHTMLXMLHttpRequestFactory(IHTMLXMLH DISPEX_IDISPATCH_IMPL(HTMLXMLHttpRequestFactory, IHTMLXMLHttpRequestFactory, impl_from_IHTMLXMLHttpRequestFactory(iface)->dispex)
-static HRESULT create_xhr(HTMLInnerWindow *window, dispex_static_data_t *dispex, HTMLXMLHttpRequest **p) +static HRESULT alloc_xhr(HTMLInnerWindow *window, dispex_static_data_t *dispex, unsigned size, void **p) { XMLHttpReqEventListener *event_listener; nsIDOMEventTarget *nstarget; nsIXMLHttpRequest *nsxhr; - HTMLXMLHttpRequest *ret; + struct xhr *ret; nsresult nsres; unsigned i;
@@ -1516,7 +1525,7 @@ static HRESULT create_xhr(HTMLInnerWindow *window, dispex_static_data_t *dispex, if(!nsxhr) return E_FAIL;
- ret = calloc(1, sizeof(*ret)); + ret = calloc(1, size); if(!ret) { nsIXMLHttpRequest_Release(nsxhr); return E_OUTOFMEMORY; @@ -1534,10 +1543,6 @@ static HRESULT create_xhr(HTMLInnerWindow *window, dispex_static_data_t *dispex, ret->task_magic = get_task_target_magic(); IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
- ret->IHTMLXMLHttpRequest_iface.lpVtbl = &HTMLXMLHttpRequestVtbl; - ret->IHTMLXMLHttpRequest2_iface.lpVtbl = &HTMLXMLHttpRequest2Vtbl; - ret->IWineXMLHttpRequestPrivate_iface.lpVtbl = &WineXMLHttpRequestPrivateVtbl; - ret->IProvideClassInfo2_iface.lpVtbl = &ProvideClassInfo2Vtbl; init_event_target(&ret->event_target, dispex, window);
/* Always register the handlers because we need them to track state */ @@ -1558,7 +1563,7 @@ static HRESULT create_xhr(HTMLInnerWindow *window, dispex_static_data_t *dispex, nsAString_Finish(&type_str); if(NS_FAILED(nsres)) { WARN("AddEventListener(%s) failed: %08lx\n", debugstr_w(name), nsres); - IHTMLXMLHttpRequest_Release(&ret->IHTMLXMLHttpRequest_iface); + IWineJSDispatchHost_Release(&ret->event_target.dispex.IWineJSDispatchHost_iface); return map_nsresult(nsres); } } @@ -1568,6 +1573,22 @@ static HRESULT create_xhr(HTMLInnerWindow *window, dispex_static_data_t *dispex, return S_OK; }
+static HRESULT create_xhr(HTMLInnerWindow *window, HTMLXMLHttpRequest **p) +{ + HTMLXMLHttpRequest *ret; + HRESULT hres; + + hres = alloc_xhr(window, &XMLHttpRequest_dispex, sizeof(*ret), (void**)&ret); + if(SUCCEEDED(hres)) { + ret->IHTMLXMLHttpRequest_iface.lpVtbl = &HTMLXMLHttpRequestVtbl; + ret->IHTMLXMLHttpRequest2_iface.lpVtbl = &HTMLXMLHttpRequest2Vtbl; + ret->IWineXMLHttpRequestPrivate_iface.lpVtbl = &WineXMLHttpRequestPrivateVtbl; + ret->IProvideClassInfo2_iface.lpVtbl = &ProvideClassInfo2Vtbl; + *p = ret; + } + return hres; +} + static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactory *iface, IHTMLXMLHttpRequest **p) { struct constructor *This = impl_from_IHTMLXMLHttpRequestFactory(iface); @@ -1576,7 +1597,7 @@ static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactor
TRACE("(%p)->(%p)\n", This, p);
- hres = create_xhr(This->window, &XMLHttpRequest_dispex, &xhr); + hres = create_xhr(This->window, &xhr); if(SUCCEEDED(hres)) *p = &xhr->IHTMLXMLHttpRequest_iface; return hres; @@ -1617,7 +1638,7 @@ static HRESULT HTMLXMLHttpRequestFactory_value(DispatchEx *iface, LCID lcid, WOR return E_NOTIMPL; }
- hres = create_xhr(This->window, &XMLHttpRequest_dispex, &xhr); + hres = create_xhr(This->window, &xhr); if(FAILED(hres)) return hres;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/xmlhttprequest.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index a75a8552ddc..f86cd14393b 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -542,27 +542,33 @@ static HRESULT WINAPI HTMLXMLHttpRequest_get_responseBody(IHTMLXMLHttpRequest *i return E_NOTIMPL; }
-static HRESULT WINAPI HTMLXMLHttpRequest_get_responseText(IHTMLXMLHttpRequest *iface, BSTR *p) +static HRESULT WINAPI get_response_text(struct xhr *xhr, BSTR *p) { - HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface); nsAString nsstr; nsresult nsres;
- TRACE("(%p)->(%p)\n", This, p); - if(!p) return E_POINTER;
- if(This->xhr.ready_state < READYSTATE_INTERACTIVE) { + if(xhr->ready_state < READYSTATE_INTERACTIVE) { *p = NULL; return S_OK; }
nsAString_Init(&nsstr, NULL); - nsres = nsIXMLHttpRequest_GetResponseText(This->xhr.nsxhr, &nsstr); + nsres = nsIXMLHttpRequest_GetResponseText(xhr->nsxhr, &nsstr); return return_nsstr(nsres, &nsstr, p); }
+static HRESULT WINAPI HTMLXMLHttpRequest_get_responseText(IHTMLXMLHttpRequest *iface, BSTR *p) +{ + HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface); + + TRACE("(%p)->(%p)\n", This, p); + + return get_response_text(&This->xhr, p); +} + static HRESULT WINAPI HTMLXMLHttpRequest_get_responseXML(IHTMLXMLHttpRequest *iface, IDispatch **p) { HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/xmlhttprequest.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index f86cd14393b..cb668f52686 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -707,30 +707,36 @@ static HRESULT WINAPI HTMLXMLHttpRequest_get_onreadystatechange(IHTMLXMLHttpRequ return get_event_handler(&This->xhr.event_target, EVENTID_READYSTATECHANGE, p); }
-static HRESULT WINAPI HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest *iface) +static HRESULT WINAPI xhr_abort(struct xhr *xhr) { - HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface); - DWORD prev_magic = This->xhr.magic; + DWORD prev_magic = xhr->magic; UINT16 ready_state; nsresult nsres;
- TRACE("(%p)->()\n", This); - - This->xhr.magic++; - nsres = nsIXMLHttpRequest_SlowAbort(This->xhr.nsxhr); + xhr->magic++; + nsres = nsIXMLHttpRequest_SlowAbort(xhr->nsxhr); if(NS_FAILED(nsres)) { ERR("nsIXMLHttpRequest_SlowAbort failed: %08lx\n", nsres); - This->xhr.magic = prev_magic; + xhr->magic = prev_magic; return E_FAIL; }
/* Gecko changed to READYSTATE_UNINITIALIZED if it did abort */ - nsres = nsIXMLHttpRequest_GetReadyState(This->xhr.nsxhr, &ready_state); + nsres = nsIXMLHttpRequest_GetReadyState(xhr->nsxhr, &ready_state); if(NS_SUCCEEDED(nsres)) - This->xhr.ready_state = ready_state; + xhr->ready_state = ready_state; return S_OK; }
+static HRESULT WINAPI HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest *iface) +{ + HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface); + + TRACE("(%p)->()\n", This); + + return xhr_abort(&This->xhr); +} + static HRESULT HTMLXMLHttpRequest_open_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/xmlhttprequest.c | 76 +++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 36 deletions(-)
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index cb668f52686..99cc0c4ee99 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -737,6 +737,44 @@ static HRESULT WINAPI HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest *iface) return xhr_abort(&This->xhr); }
+static HRESULT WINAPI xhr_open(struct xhr *xhr, BSTR bstrMethod, BSTR bstrUrl, BOOL async, nsAString *user, nsAString *password, unsigned opt_argc) +{ + BOOLEAN prev_synchronous; + nsACString method, url; + DWORD prev_magic; + nsresult nsres; + HRESULT hres; + + hres = bstr_to_nsacstr(bstrMethod, &method); + if(FAILED(hres)) + return hres; + hres = bstr_to_nsacstr(bstrUrl, &url); + if(FAILED(hres)) { + nsACString_Finish(&method); + return hres; + } + + /* Set this here, Gecko dispatches nested sync XHR readyState changes for OPENED (see HandleEvent) */ + prev_magic = xhr->magic; + prev_synchronous = xhr->synchronous; + xhr->synchronous = !async; + xhr->magic++; + + nsres = nsIXMLHttpRequest_Open(xhr->nsxhr, &method, &url, async, user, password, opt_argc); + + nsACString_Finish(&method); + nsACString_Finish(&url); + + if(NS_FAILED(nsres)) { + ERR("nsIXMLHttpRequest_Open failed: %08lx\n", nsres); + xhr->magic = prev_magic; + xhr->synchronous = prev_synchronous; + return E_FAIL; + } + + return S_OK; +} + static HRESULT HTMLXMLHttpRequest_open_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -762,12 +800,8 @@ static HRESULT HTMLXMLHttpRequest_open_hook(DispatchEx *dispex, WORD flags, static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR bstrMethod, BSTR bstrUrl, VARIANT varAsync, VARIANT varUser, VARIANT varPassword) { HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface); - BOOLEAN prev_synchronous; nsAString user, password; - nsACString method, url; unsigned opt_argc = 1; - DWORD prev_magic; - nsresult nsres; HRESULT hres;
TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(bstrMethod), debugstr_w(bstrUrl), debugstr_variant(&varAsync), debugstr_variant(&varUser), debugstr_variant(&varPassword)); @@ -790,45 +824,15 @@ static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR b return hres; }
- hres = bstr_to_nsacstr(bstrMethod, &method); - if(FAILED(hres)) { - nsAString_Finish(&user); - nsAString_Finish(&password); - return hres; - } - hres = bstr_to_nsacstr(bstrUrl, &url); - if(FAILED(hres)) { - nsAString_Finish(&user); - nsAString_Finish(&password); - nsACString_Finish(&method); - return hres; - } - - /* Set this here, Gecko dispatches nested sync XHR readyState changes for OPENED (see HandleEvent) */ - prev_magic = This->xhr.magic; - prev_synchronous = This->xhr.synchronous; - This->xhr.synchronous = !V_BOOL(&varAsync); - This->xhr.magic++; - if(V_VT(&varPassword) != VT_EMPTY && V_VT(&varPassword) != VT_ERROR) opt_argc += 2; else if(V_VT(&varUser) != VT_EMPTY && V_VT(&varUser) != VT_ERROR) opt_argc += 1; - nsres = nsIXMLHttpRequest_Open(This->xhr.nsxhr, &method, &url, !!V_BOOL(&varAsync), &user, &password, opt_argc);
- nsACString_Finish(&method); - nsACString_Finish(&url); + hres = xhr_open(&This->xhr, bstrMethod, bstrUrl, !!V_BOOL(&varAsync), &user, &password, opt_argc); nsAString_Finish(&user); nsAString_Finish(&password); - - if(NS_FAILED(nsres)) { - ERR("nsIXMLHttpRequest_Open failed: %08lx\n", nsres); - This->xhr.magic = prev_magic; - This->xhr.synchronous = prev_synchronous; - return E_FAIL; - } - - return S_OK; + return hres; }
static HRESULT WINAPI HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest *iface, VARIANT varBody)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/xmlhttprequest.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index 99cc0c4ee99..4b6c52d5388 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -835,14 +835,11 @@ static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR b return hres; }
-static HRESULT WINAPI HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest *iface, VARIANT varBody) +static HRESULT WINAPI xhr_send(struct xhr *xhr, VARIANT varBody) { - HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface); nsIWritableVariant *nsbody = NULL; nsresult nsres = NS_OK;
- TRACE("(%p)->(%s)\n", This, debugstr_variant(&varBody)); - switch(V_VT(&varBody)) { case VT_NULL: case VT_EMPTY: @@ -866,10 +863,10 @@ static HRESULT WINAPI HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest *iface, VARIAN }
if(NS_SUCCEEDED(nsres)) { - if(This->xhr.synchronous) - nsres = sync_xhr_send(&This->xhr, (nsIVariant*)nsbody); + if(xhr->synchronous) + nsres = sync_xhr_send(xhr, (nsIVariant*)nsbody); else - nsres = nsIXMLHttpRequest_Send(This->xhr.nsxhr, (nsIVariant*)nsbody); + nsres = nsIXMLHttpRequest_Send(xhr->nsxhr, (nsIVariant*)nsbody); }
if(nsbody) @@ -882,6 +879,15 @@ static HRESULT WINAPI HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest *iface, VARIAN return S_OK; }
+static HRESULT WINAPI HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest *iface, VARIANT varBody) +{ + HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface); + + TRACE("(%p)->(%s)\n", This, debugstr_variant(&varBody)); + + return xhr_send(&This->xhr, varBody); +} + static HRESULT WINAPI HTMLXMLHttpRequest_getAllResponseHeaders(IHTMLXMLHttpRequest *iface, BSTR *p) { HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlwindow.c | 30 ++- dlls/mshtml/mshtml_private.h | 4 + dlls/mshtml/tests/documentmode.js | 20 +- dlls/mshtml/tests/dom.c | 127 +++++++++++- dlls/mshtml/tests/events.c | 19 ++ dlls/mshtml/xmlhttprequest.c | 308 ++++++++++++++++++++++++++++++ 6 files changed, 501 insertions(+), 7 deletions(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index e5e2481299a..edd0de177bd 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -1974,8 +1974,26 @@ static HRESULT WINAPI HTMLWindow6_put_XDomainRequest(IHTMLWindow6 *iface, VARIAN static HRESULT WINAPI HTMLWindow6_get_XDomainRequest(IHTMLWindow6 *iface, VARIANT *p) { HTMLWindow *This = impl_from_IHTMLWindow6(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + HTMLInnerWindow *window = This->inner_window; + DispatchEx *constr; + HRESULT hres; + + TRACE("(%p)->(%p)\n", This, p); + + if(This->outer_window->readystate == READYSTATE_UNINITIALIZED) { + V_VT(p) = VT_EMPTY; + return S_OK; + } + + hres = get_constructor(window, OBJID_XDomainRequest, &constr); + if(FAILED(hres)) + return hres; + + V_VT(p) = VT_DISPATCH; + V_DISPATCH(p) = (IDispatch*)&constr->IWineJSDispatchHost_iface; + IDispatch_AddRef(V_DISPATCH(p)); + + return S_OK; }
static HRESULT WINAPI HTMLWindow6_get_sessionStorage(IHTMLWindow6 *iface, IHTMLStorage **p) @@ -4212,10 +4230,14 @@ 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[] = { + static const dispex_hook_t window6_ie9_hooks[] = { + {DISPID_IHTMLWINDOW6_XDOMAINREQUEST}, + + /* Common for all modes */ {DISPID_IHTMLWINDOW6_POSTMESSAGE, IHTMLWindow6_postMessage_hook}, {DISPID_UNKNOWN} }; + const dispex_hook_t *const window6_hooks = window6_ie9_hooks + 1;
if(compat_mode >= COMPAT_MODE_IE9) dispex_info_add_interface(info, IHTMLWindow7_tid, NULL); @@ -4224,7 +4246,7 @@ static void HTMLWindow_init_dispex_info(dispex_data_t *info, compat_mode_t compa if(compat_mode >= COMPAT_MODE_IE10) dispex_info_add_interface(info, IWineHTMLWindowPrivate_tid, NULL);
- dispex_info_add_interface(info, IHTMLWindow6_tid, window6_hooks); + dispex_info_add_interface(info, IHTMLWindow6_tid, compat_mode >= COMPAT_MODE_IE9 ? window6_ie9_hooks : window6_hooks); if(compat_mode < COMPAT_MODE_IE9) dispex_info_add_interface(info, IHTMLWindow5_tid, NULL); dispex_info_add_interface(info, IHTMLWindow4_tid, compat_mode >= COMPAT_MODE_IE11 ? window4_ie11_hooks : NULL); diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index d014c34ba7c..6e4a58aee55 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -159,6 +159,7 @@ struct constructor; XDIID(DispHTMLW3CComputedStyle) \ XDIID(DispHTMLWindow2) \ XDIID(DispHTMLXMLHttpRequest) \ + XDIID(DispXDomainRequest) \ XDIID(DispSVGCircleElement) \ XDIID(DispSVGSVGElement) \ XDIID(DispSVGTSpanElement) \ @@ -295,6 +296,8 @@ struct constructor; XIID(IHTMLXMLHttpRequest) \ XIID(IHTMLXMLHttpRequest2) \ XIID(IHTMLXMLHttpRequestFactory) \ + XIID(IHTMLXDomainRequest) \ + XIID(IHTMLXDomainRequestFactory) \ XIID(IOmHistory) \ XIID(IOmNavigator) \ XIID(ISVGCircleElement) \ @@ -511,6 +514,7 @@ typedef struct { X(TextRange) \ X(UIEvent) \ X(Window) \ + X(XDomainRequest) \ X(XMLDocument) \ X(XMLHttpRequest)
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index faac18c45a3..acee34c8bc1 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -329,6 +329,7 @@ sync_test("builtin_toString", function() { if(v < 11) { test("eventObject", document.createEventObject(), "MSEventObj"); test("selection", document.selection, "MSSelection"); + test("XDomainRequest", new XDomainRequest(), "XDomainRequest"); } if(v >= 9) { test("computedStyle", window.getComputedStyle(e), "CSSStyleDeclaration"); @@ -986,6 +987,7 @@ sync_test("window_props", function() { test_exposed("HTMLDocument", v === 8 || v >= 11, v === 8); test_exposed("XMLDocument", v >= 11); test_exposed("DOMParser", v >= 9); + test_exposed("XDomainRequest", v < 11); test_exposed("MutationObserver", v >= 11); test_exposed("PageTransitionEvent", v >= 11); test_exposed("ProgressEvent", v >= 10); @@ -1260,6 +1262,7 @@ sync_test("constructor props", function() { test_exposed(XMLHttpRequest, "create", true); if(v >= 9) test_exposed(DOMParser, "create", false); if(v >= 11) test_exposed(MutationObserver, "create", false); + if(v < 11) test_exposed(XDomainRequest, "create", true); });
sync_test("createElement_inline_attr", function() { @@ -3931,6 +3934,11 @@ sync_test("prototypes", function() { check(new XMLHttpRequest(), XMLHttpRequest.prototype, "xhr"); check(XMLHttpRequest.prototype, Object.prototype, "xhr prototype"); check(XMLHttpRequest, Function.prototype, "xhr constructor"); + if(v < 11) { + check(new XDomainRequest(), XDomainRequest.prototype, "xdr"); + check(XDomainRequest.prototype, Object.prototype, "xdr prototype"); + check(XDomainRequest, Function.prototype, "xdr constructor"); + } check(document.createElement("img"), HTMLImageElement.prototype, "img elem"); check(HTMLImageElement.prototype, HTMLElement.prototype, "img elem prototype"); check(Image, Function.prototype, "Image constructor"); @@ -4481,8 +4489,16 @@ sync_test("prototype props", function() { check(StyleSheet, [ "disabled", "href", "media", "ownerNode", "parentStyleSheet", "title", "type" ]); check(Text, [ "removeNode", "replaceNode", "replaceWholeText", "splitText", "swapNode", "wholeText" ], [ "replaceWholeText", "wholeText" ]); check(UIEvent, [ "detail", "initUIEvent", "view" ], null, [ "deviceSessionId" ]); + if(v < 11) + check(XDomainRequest, [ "abort", "contentType", "onerror", "onload", "onprogress", "ontimeout", "open", "responseText", "send", "timeout" ]); if(v >= 11) check(XMLDocument, []); + check(XMLHttpRequest, [ + "DONE", "HEADERS_RECEIVED", "LOADING", "OPENED", "UNSENT", "abort", "addEventListener", "dispatchEvent", "getAllResponseHeaders", "getResponseHeader", ["msCaching",11], + ["msCachingEnabled",11], ["onabort",10], ["onerror",10], "onload", ["onloadend",10], ["onloadstart",10], ["onprogress",10], "onreadystatechange", "ontimeout", "open", + ["overrideMimeType",11], "readyState", "removeEventListener", ["response",10], "responseBody", "responseText", ["responseType",10], "responseXML", "send", + "setRequestHeader", "status", "statusText", "timeout", ["upload",10], ["withCredentials",10] + ], [ "DONE", "HEADERS_RECEIVED", "LOADING", "OPENED", "UNSENT", ["msCaching",11], ["msCachingEnabled",11] ]); });
sync_test("constructors", function() { @@ -4491,6 +4507,8 @@ sync_test("constructors", function() { return;
var ctors = [ "DOMParser", "Image", "Option", "XMLHttpRequest" ]; + if (v < 11) + ctors.push("XDomainRequest"); if (v >= 11) ctors.push("MutationObserver"); for(i = 0; i < ctors.length; i++) { @@ -4658,7 +4676,7 @@ async_test("window own props", function() { ["Uint8Array",10], ["Uint8ClampedArray",11], ["URL",10], ["ValidityState",10], ["VideoPlaybackQuality",11], ["WebGLActiveInfo",11], ["WebGLBuffer",11], ["WebGLContextEvent",11], ["WebGLFramebuffer",11], ["WebGLObject",11], ["WebGLProgram",11], ["WebGLRenderbuffer",11], ["WebGLRenderingContext",11], ["WebGLShader",11], ["WebGLShaderPrecisionFormat",11], ["WebGLTexture",11], ["WebGLUniformLocation",11], ["WEBGL_compressed_texture_s3tc",11], ["WEBGL_debug_renderer_info",11], ["WebSocket",10], "WheelEvent", ["Worker",10], - ["XDomainRequest",9,10], ["XMLHttpRequestEventTarget",10], "XMLSerializer" + ["XMLHttpRequestEventTarget",10], "XMLSerializer" ]); next_test(); } diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 7250ffea636..f3aec7d9046 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -2277,6 +2277,47 @@ static void _set_object_name(unsigned line, IHTMLElement *elem, const WCHAR *nam _test_object_name(line, elem, name); }
+static void test_factory(void *window, void *factory, const WCHAR *name, const WCHAR *value) +{ + IDispatch *disp, *disp2, *window_disp = window; + DISPPARAMS dp = { NULL, NULL, 0, 0 }; + BSTR bstr = SysAllocString(name); + VARIANT var, val; + DISPID dispid; + HRESULT hres; + + hres = IDispatch_GetIDsOfNames(window_disp, &IID_NULL, &bstr, 1, 0, &dispid); + SysFreeString(bstr); + ok(hres == S_OK, "GetIDsOfNames(%s) failed: %08lx\n", wine_dbgstr_w(name), hres); + + hres = IDispatch_Invoke(window_disp, dispid, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dp, &var, NULL, NULL); + ok(hres == S_OK, "Invoke(%s) failed: %08lx\n", wine_dbgstr_w(name), hres); + ok(V_VT(&var) == VT_DISPATCH, "VT(%s) = %d\n", wine_dbgstr_w(name), V_VT(&var)); + + hres = IUnknown_QueryInterface((IUnknown*)factory, &IID_IDispatch, (void**)&disp); + ok(hres == S_OK, "Could not get IDispatch from %s factory: %08lx\n", wine_dbgstr_w(name), hres); + hres = IUnknown_QueryInterface(V_DISPATCH(&var), &IID_IDispatch, (void**)&disp2); + ok(hres == S_OK, "Could not get IDispatch from window.%s factory: %08lx\n", wine_dbgstr_w(name), hres); + todo_wine + ok(disp != disp2, "window.%s and the builtin getter returned same dispatch\n", wine_dbgstr_w(name)); + IDispatch_Release(disp2); + + hres = IDispatch_Invoke(disp, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dp, &val, NULL, NULL); + IDispatch_Release(disp); + ok(hres == S_OK, "Invoke(DISPID_VALUE) for %s builtin getter returned: %08lx\n", wine_dbgstr_w(name), hres); + ok(V_VT(&val) == VT_BSTR, "V_VT(value) for %s builtin getter = %d\n", wine_dbgstr_w(name), V_VT(&val)); + ok(!lstrcmpW(V_BSTR(&val), L"[object]"), "value for %s builtin getter = %s\n", wine_dbgstr_w(name), wine_dbgstr_w(V_BSTR(&val))); + VariantClear(&val); + + hres = IDispatch_Invoke(V_DISPATCH(&var), DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dp, &val, NULL, NULL); + VariantClear(&var); + ok(hres == S_OK, "Invoke(DISPID_VALUE) for %s: %08lx\n", wine_dbgstr_w(name), hres); + ok(V_VT(&val) == VT_BSTR, "V_VT(value) for %s = %d\n", wine_dbgstr_w(name), V_VT(&val)); + todo_wine + ok(!lstrcmpW(V_BSTR(&val), value), "value for %s = %s\n", wine_dbgstr_w(name), wine_dbgstr_w(V_BSTR(&val))); + VariantClear(&val); +} + #define create_option_elem(d,t,v) _create_option_elem(__LINE__,d,t,v) static IHTMLOptionElement *_create_option_elem(unsigned line, IHTMLDocument2 *doc, const WCHAR *txt, const WCHAR *val) @@ -2293,10 +2334,11 @@ static IHTMLOptionElement *_create_option_elem(unsigned line, IHTMLDocument2 *do ok_(__FILE__,line) (hres == S_OK, "get_parentElement failed: %08lx\n", hres);
hres = IHTMLWindow2_get_Option(window, &factory); - IHTMLWindow2_Release(window); ok_(__FILE__,line) (hres == S_OK, "get_Option failed: %08lx\n", hres);
+ test_factory(window, factory, L"Option", L"[object HTMLOptionElement]"); test_disp((IUnknown*)factory, &IID_IHTMLOptionElementFactory, NULL, L"[object]"); + IHTMLWindow2_Release(window);
V_VT(&text) = VT_BSTR; V_BSTR(&text) = SysAllocString(txt); @@ -2395,11 +2437,12 @@ static IHTMLImgElement *_create_img_elem(unsigned line, IHTMLDocument2 *doc, ok_(__FILE__,line) (hres == S_OK, "get_parentElement failed: %08lx\n", hres);
hres = IHTMLWindow2_get_Image(window, &factory); - IHTMLWindow2_Release(window); ok_(__FILE__,line) (hres == S_OK, "get_Image failed: %08lx\n", hres);
test_ifaces((IUnknown*)factory, img_factory_iids); + test_factory(window, factory, L"Image", L"[object HTMLImageElement]"); test_disp((IUnknown*)factory, &IID_IHTMLImageElementFactory, NULL, L"[object]"); + IHTMLWindow2_Release(window);
if(wdth >= 0){ wsprintfW(buf, L"%d", wdth); @@ -7987,6 +8030,8 @@ static void test_xmlhttprequest(IHTMLWindow5 *window) ok(hres == S_OK, "QueryInterface(&IID_IHTMLXMLHttpRequestFactory) failed: %08lx\n", hres); ok(factory != NULL, "factory == NULL\n");
+ test_factory(window, factory, L"XMLHttpRequest", L"[object XMLHttpRequest]"); + xml = NULL; hres = IHTMLXMLHttpRequestFactory_create(factory, &xml); ok(hres == S_OK, "create failed: %08lx\n", hres); @@ -7999,6 +8044,41 @@ static void test_xmlhttprequest(IHTMLWindow5 *window) VariantClear(&var); }
+static void test_xdomainrequest(IHTMLWindow6 *window) +{ + IHTMLXDomainRequestFactory *factory; + IHTMLXDomainRequest *xdr; + HRESULT hres; + VARIANT var; + + hres = IHTMLWindow6_get_XDomainRequest(window, &var); + ok(hres == S_OK, "get_XDomainRequest failed: %08lx\n", hres); + ok(V_VT(&var) == VT_DISPATCH || broken(V_VT(&var) == VT_EMPTY), "expect VT_DISPATCH, got %s\n", debugstr_variant(&var)); + + if(V_VT(&var) == VT_EMPTY) { + win_skip("Native XDomainRequest support is missing or disabled.\n"); + return; + } + + factory = NULL; + hres = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IHTMLXDomainRequestFactory, (void**)&factory); + ok(hres == S_OK, "QueryInterface(&IID_IHTMLXDomainRequestFactory) failed: %08lx\n", hres); + ok(factory != NULL, "factory == NULL\n"); + + test_factory(window, factory, L"XDomainRequest", L"[object XDomainRequest]"); + + xdr = NULL; + hres = IHTMLXDomainRequestFactory_create(factory, &xdr); + ok(hres == S_OK, "create failed: %08lx\n", hres); + ok(xdr != NULL, "xdr == NULL\n"); + if(is_ie9plus) + test_disp((IUnknown*)xdr, &DIID_DispXDomainRequest, NULL, L"[object]"); + + IHTMLXDomainRequest_Release(xdr); + IHTMLXDomainRequestFactory_Release(factory); + VariantClear(&var); +} + static void test_read_only_style(IHTMLCSSStyleDeclaration *style) { BSTR none = SysAllocString(L"none"), display = SysAllocString(L"display"), str; @@ -8024,6 +8104,7 @@ static void test_window(IHTMLDocument2 *doc) { IHTMLWindow2 *window, *window2, *self, *parent; IHTMLWindow5 *window5; + IHTMLWindow6 *window6; IHTMLWindow7 *window7; IHTMLDocument2 *doc2 = NULL; IDispatch *disp; @@ -8128,6 +8209,15 @@ static void test_window(IHTMLDocument2 *doc) win_skip("IHTMLWindow5 not supported!\n"); }
+ hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow6, (void**)&window6); + if(SUCCEEDED(hres)) { + ok(window6 != NULL, "window6 == NULL\n"); + test_xdomainrequest(window6); + IHTMLWindow6_Release(window6); + }else { + win_skip("IHTMLWindow6 not supported!\n"); + } + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow7, (void**)&window7); if(SUCCEEDED(hres)) { IHTMLCSSStyleDeclaration *computed_style; @@ -8353,6 +8443,29 @@ static void test_xhr(IHTMLDocument2 *doc) IDispatchEx_Release(dispex); }
+static void test_xdr(IHTMLDocument2 *doc) +{ + IHTMLWindow2 *window; + IDispatchEx *dispex; + DISPID id; + BSTR str; + HRESULT hres; + + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx iface: %08lx\n", hres); + + str = SysAllocString(L"XDomainRequest"); + hres = IDispatchEx_GetDispID(dispex, str, 0, &id); + ok(hres == S_OK, "GetDispID failed: %08lx\n", hres); + SysFreeString(str); + + IHTMLWindow2_Release(window); + IDispatchEx_Release(dispex); +} + static void test_defaults(IHTMLDocument2 *doc) { IHTMLStyleSheetsCollection *stylesheetcol; @@ -8426,6 +8539,7 @@ static void test_defaults(IHTMLDocument2 *doc) }
test_xhr(doc); + test_xdr(doc);
hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLBodyElement, (void**)&body); ok(hres == S_OK, "Could not get IHTMBodyElement: %08lx\n", hres); @@ -13104,6 +13218,7 @@ static void test_document_mode_lock(void) IEventTarget *event_target; IPersistStreamInit *init; IHTMLWindow7 *window7; + IHTMLWindow6 *window6; IHTMLWindow5 *window5; IHTMLWindow2 *window; IDispatchEx *dispex; @@ -13157,6 +13272,14 @@ static void test_document_mode_lock(void) ok(V_VT(&var) == VT_EMPTY, "V_VT(XMLHttpRequest) = %d\n", V_VT(&var)); IHTMLWindow5_Release(window5);
+ V_VT(&var) = VT_NULL; + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow6, (void**)&window6); + ok(hres == S_OK, "Could not get IHTMLWindow6: %08lx\n", hres); + hres = IHTMLWindow6_get_XDomainRequest(window6, &var); + ok(hres == S_OK, "get_XDomainRequest failed: %08lx\n", hres); + ok(V_VT(&var) == VT_EMPTY, "V_VT(XDomainRequest) = %d\n", V_VT(&var)); + IHTMLWindow6_Release(window6); + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow7, (void**)&window7); ok(hres == S_OK, "Could not get IHTMLWindow7: %08lx\n", hres); hres = IHTMLWindow7_get_performance(window7, &var); diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index bdfbb6c6b78..fbb5a9535ee 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -4149,6 +4149,7 @@ static void test_doc_obj(IHTMLDocument2 *doc) IHTMLOptionElementFactory *option, *option2; IHTMLImageElementFactory *image, *image2; IHTMLXMLHttpRequestFactory *xhr, *xhr2; + IHTMLXDomainRequestFactory *xdr, *xdr2; IHTMLDocument2 *doc_node, *doc_node2; IOmNavigator *navigator, *navigator2; IHTMLLocation *location, *location2; @@ -4307,7 +4308,14 @@ static void test_doc_obj(IHTMLDocument2 *doc) ok(hres == S_OK, "Could not get IHTMLWindow6: %08lx\n", hres); hres = IHTMLWindow6_get_sessionStorage(window6, &storage); ok(hres == S_OK, "get_sessionStorage failed: %08lx\n", hres); + + hres = IHTMLWindow6_get_XDomainRequest(window6, &res); + ok(hres == S_OK, "get_XDomainRequest failed: %08lx\n", hres); + ok(V_VT(&res) == VT_DISPATCH, "V_VT(XDomainRequest) = %d\n", V_VT(&res)); + hres = IDispatch_QueryInterface(V_DISPATCH(&res), &IID_IHTMLXDomainRequestFactory, (void**)&xdr); + ok(hres == S_OK, "Could not get IHTMLXDomainRequestFactory: %08lx\n", hres); IHTMLWindow6_Release(window6); + VariantClear(&res);
hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow7, (void**)&window7); ok(hres == S_OK, "Could not get IHTMLWindow7: %08lx\n", hres); @@ -4491,7 +4499,18 @@ static void test_doc_obj(IHTMLDocument2 *doc) ok(storage != storage2, "storage == storage2\n"); IHTMLStorage_Release(storage2); IHTMLStorage_Release(storage); + + ok(hres == S_OK, "Could not get IHTMLWindow6: %08lx\n", hres); + hres = IHTMLWindow6_get_XDomainRequest(window6, &res); + ok(hres == S_OK, "get_XDomainRequest failed: %08lx\n", hres); + ok(V_VT(&res) == VT_DISPATCH, "V_VT(XDomainRequest) = %d\n", V_VT(&res)); + hres = IDispatch_QueryInterface(V_DISPATCH(&res), &IID_IHTMLXDomainRequestFactory, (void**)&xdr2); + ok(hres == S_OK, "Could not get IHTMLXDomainRequestFactory: %08lx\n", hres); + ok(xdr != xdr2, "xdr == xdr2\n"); + IHTMLXDomainRequestFactory_Release(xdr2); + IHTMLXDomainRequestFactory_Release(xdr); IHTMLWindow6_Release(window6); + VariantClear(&res);
hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow7, (void**)&window7); ok(hres == S_OK, "Could not get IHTMLWindow7: %08lx\n", hres); diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index 4b6c52d5388..2a72abd38dd 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -152,6 +152,11 @@ struct HTMLXMLHttpRequest { IProvideClassInfo2 IProvideClassInfo2_iface; };
+typedef struct { + struct xhr xhr; + IHTMLXDomainRequest IHTMLXDomainRequest_iface; +} HTMLXDomainRequest; + static void detach_xhr_event_listener(XMLHttpReqEventListener *event_listener) { nsIDOMEventTarget *event_target; @@ -1738,3 +1743,306 @@ dispex_static_data_t XMLHttpRequest_dispex = { .iface_tids = HTMLXMLHttpRequest_iface_tids, .init_info = HTMLXMLHttpRequest_init_dispex_info, }; + + + +/* IHTMLXDomainRequest */ +static inline HTMLXDomainRequest *impl_from_IHTMLXDomainRequest(IHTMLXDomainRequest *iface) +{ + return CONTAINING_RECORD(iface, HTMLXDomainRequest, IHTMLXDomainRequest_iface); +} + +DISPEX_IDISPATCH_IMPL(HTMLXDomainRequest, IHTMLXDomainRequest, + impl_from_IHTMLXDomainRequest(iface)->xhr.event_target.dispex) + +static HRESULT WINAPI HTMLXDomainRequest_get_responseText(IHTMLXDomainRequest *iface, BSTR *p) +{ + HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + + return get_response_text(&This->xhr, p); +} + +static HRESULT WINAPI HTMLXDomainRequest_put_timeout(IHTMLXDomainRequest *iface, LONG v) +{ + HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + + FIXME("(%p)->(%ld)\n", This, v); + + return E_NOTIMPL; +} + +static HRESULT WINAPI HTMLXDomainRequest_get_timeout(IHTMLXDomainRequest *iface, LONG *p) +{ + HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + + FIXME("(%p)->(%p)\n", This, p); + + return E_NOTIMPL; +} + +static HRESULT WINAPI HTMLXDomainRequest_get_contentType(IHTMLXDomainRequest *iface, BSTR *p) +{ + HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + + FIXME("(%p)->(%p)\n", This, p); + + return E_NOTIMPL; +} + +static HRESULT WINAPI HTMLXDomainRequest_put_onprogress(IHTMLXDomainRequest *iface, VARIANT v) +{ + HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + + TRACE("(%p)->(%s)\n", This, debugstr_variant(&v)); + + return set_event_handler(&This->xhr.event_target, EVENTID_PROGRESS, &v); +} + +static HRESULT WINAPI HTMLXDomainRequest_get_onprogress(IHTMLXDomainRequest *iface, VARIANT *p) +{ + HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + + TRACE("(%p)->(%p)\n", This, p); + + return get_event_handler(&This->xhr.event_target, EVENTID_PROGRESS, p); +} + +static HRESULT WINAPI HTMLXDomainRequest_put_onerror(IHTMLXDomainRequest *iface, VARIANT v) +{ + HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + + TRACE("(%p)->(%s)\n", This, debugstr_variant(&v)); + + return set_event_handler(&This->xhr.event_target, EVENTID_ERROR, &v); +} + +static HRESULT WINAPI HTMLXDomainRequest_get_onerror(IHTMLXDomainRequest *iface, VARIANT *p) +{ + HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + + TRACE("(%p)->(%p)\n", This, p); + + return get_event_handler(&This->xhr.event_target, EVENTID_ERROR, p); +} + +static HRESULT WINAPI HTMLXDomainRequest_put_ontimeout(IHTMLXDomainRequest *iface, VARIANT v) +{ + HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + + TRACE("(%p)->(%s)\n", This, debugstr_variant(&v)); + + return set_event_handler(&This->xhr.event_target, EVENTID_TIMEOUT, &v); +} + +static HRESULT WINAPI HTMLXDomainRequest_get_ontimeout(IHTMLXDomainRequest *iface, VARIANT *p) +{ + HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + + TRACE("(%p)->(%p)\n", This, p); + + return get_event_handler(&This->xhr.event_target, EVENTID_TIMEOUT, p); +} + +static HRESULT WINAPI HTMLXDomainRequest_put_onload(IHTMLXDomainRequest *iface, VARIANT v) +{ + HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + + TRACE("(%p)->(%s)\n", This, debugstr_variant(&v)); + + return set_event_handler(&This->xhr.event_target, EVENTID_LOAD, &v); +} + +static HRESULT WINAPI HTMLXDomainRequest_get_onload(IHTMLXDomainRequest *iface, VARIANT *p) +{ + HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + + TRACE("(%p)->(%p)\n", This, p); + + return get_event_handler(&This->xhr.event_target, EVENTID_LOAD, p); +} + +static HRESULT WINAPI HTMLXDomainRequest_abort(IHTMLXDomainRequest *iface) +{ + HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + + return xhr_abort(&This->xhr); +} + +static HRESULT WINAPI HTMLXDomainRequest_open(IHTMLXDomainRequest *iface, BSTR bstrMethod, BSTR bstrUrl) +{ + HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + + FIXME("(%p)->(%s %s)\n", This, debugstr_w(bstrMethod), debugstr_w(bstrUrl)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI HTMLXDomainRequest_send(IHTMLXDomainRequest *iface, VARIANT varBody) +{ + HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + + return xhr_send(&This->xhr, varBody); +} + +static const IHTMLXDomainRequestVtbl HTMLXDomainRequestVtbl = { + HTMLXDomainRequest_QueryInterface, + HTMLXDomainRequest_AddRef, + HTMLXDomainRequest_Release, + HTMLXDomainRequest_GetTypeInfoCount, + HTMLXDomainRequest_GetTypeInfo, + HTMLXDomainRequest_GetIDsOfNames, + HTMLXDomainRequest_Invoke, + HTMLXDomainRequest_get_responseText, + HTMLXDomainRequest_put_timeout, + HTMLXDomainRequest_get_timeout, + HTMLXDomainRequest_get_contentType, + HTMLXDomainRequest_put_onprogress, + HTMLXDomainRequest_get_onprogress, + HTMLXDomainRequest_put_onerror, + HTMLXDomainRequest_get_onerror, + HTMLXDomainRequest_put_ontimeout, + HTMLXDomainRequest_get_ontimeout, + HTMLXDomainRequest_put_onload, + HTMLXDomainRequest_get_onload, + HTMLXDomainRequest_abort, + HTMLXDomainRequest_open, + HTMLXDomainRequest_send +}; + +static inline HTMLXDomainRequest *HTMLXDomainRequest_from_DispatchEx(DispatchEx *iface) +{ + return CONTAINING_RECORD(iface, HTMLXDomainRequest, xhr.event_target.dispex); +} + +static void *HTMLXDomainRequest_query_interface(DispatchEx *dispex, REFIID riid) +{ + HTMLXDomainRequest *This = HTMLXDomainRequest_from_DispatchEx(dispex); + + if(IsEqualGUID(&IID_IHTMLXDomainRequest, riid)) + return &This->IHTMLXDomainRequest_iface; + + return EventTarget_query_interface(&This->xhr.event_target, riid); +} + +static const event_target_vtbl_t HTMLXDomainRequest_event_target_vtbl = { + { + .query_interface = HTMLXDomainRequest_query_interface, + .destructor = xhr_destructor, + .traverse = xhr_traverse, + .unlink = xhr_unlink, + .last_release = xhr_last_release + }, + .get_gecko_target = xhr_get_gecko_target, + .bind_event = xhr_bind_event +}; + +static void HTMLXDomainRequest_init_dispex_info(dispex_data_t *info, compat_mode_t compat_mode) +{ + dispex_info_add_interface(info, IHTMLXDomainRequest_tid, NULL); +} + + +/* IHTMLXDomainRequestFactory */ +static inline struct constructor *impl_from_IHTMLXDomainRequestFactory(IHTMLXDomainRequestFactory *iface) +{ + return CONTAINING_RECORD(iface, struct constructor, iface); +} + +DISPEX_IDISPATCH_IMPL(HTMLXDomainRequestFactory, IHTMLXDomainRequestFactory, + impl_from_IHTMLXDomainRequestFactory(iface)->dispex) + +static HRESULT WINAPI HTMLXDomainRequestFactory_create(IHTMLXDomainRequestFactory *iface, IHTMLXDomainRequest **p) +{ + struct constructor *This = impl_from_IHTMLXDomainRequestFactory(iface); + HTMLXDomainRequest *xdr; + HRESULT hres; + + TRACE("(%p)->(%p)\n", This, p); + + hres = alloc_xhr(This->window, &XDomainRequest_dispex, sizeof(*xdr), (void**)&xdr); + if(FAILED(hres)) + return hres; + + xdr->IHTMLXDomainRequest_iface.lpVtbl = &HTMLXDomainRequestVtbl; + + *p = &xdr->IHTMLXDomainRequest_iface; + return hres; +} + +static const IHTMLXDomainRequestFactoryVtbl HTMLXDomainRequestFactoryVtbl = { + HTMLXDomainRequestFactory_QueryInterface, + HTMLXDomainRequestFactory_AddRef, + HTMLXDomainRequestFactory_Release, + HTMLXDomainRequestFactory_GetTypeInfoCount, + HTMLXDomainRequestFactory_GetTypeInfo, + HTMLXDomainRequestFactory_GetIDsOfNames, + HTMLXDomainRequestFactory_Invoke, + HTMLXDomainRequestFactory_create +}; + +static void *HTMLXDomainRequestFactory_query_interface(DispatchEx *dispex, REFIID riid) +{ + struct constructor *This = constructor_from_DispatchEx(dispex); + + if(IsEqualGUID(&IID_IHTMLXDomainRequestFactory, riid)) + return &This->iface; + + return NULL; +} + +static HRESULT HTMLXDomainRequestFactory_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *params, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +{ + struct constructor *This = constructor_from_DispatchEx(dispex); + IHTMLXDomainRequest *xdr; + HRESULT hres; + + TRACE("\n"); + + if(flags != DISPATCH_CONSTRUCT) { + FIXME("flags %x not supported\n", flags); + return E_NOTIMPL; + } + + hres = HTMLXDomainRequestFactory_create((IHTMLXDomainRequestFactory*)&This->iface, &xdr); + if(FAILED(hres)) + return hres; + + V_VT(res) = VT_DISPATCH; + V_DISPATCH(res) = (IDispatch*)xdr; + return hres; +} + +static const dispex_static_data_vtbl_t HTMLXDomainRequestFactory_dispex_vtbl = { + .query_interface = HTMLXDomainRequestFactory_query_interface, + .destructor = constructor_destructor, + .traverse = constructor_traverse, + .unlink = constructor_unlink, + .value = HTMLXDomainRequestFactory_value, +}; + +static const tid_t HTMLXDomainRequestFactory_iface_tids[] = { + IHTMLXDomainRequestFactory_tid, + 0 +}; +static dispex_static_data_t HTMLXDomainRequestFactory_dispex = { + .name = "XDomainRequest", + .constructor_id = OBJID_XDomainRequest, + .vtbl = &HTMLXDomainRequestFactory_dispex_vtbl, + .disp_tid = IHTMLXDomainRequestFactory_tid, + .iface_tids = HTMLXDomainRequestFactory_iface_tids, +}; + +static HRESULT HTMLXDomainRequestFactory_init(struct constructor *constr) +{ + return init_constructor(constr, &HTMLXDomainRequestFactory_dispex, &HTMLXDomainRequestFactoryVtbl); +} + +dispex_static_data_t XDomainRequest_dispex = { + .id = OBJID_XDomainRequest, + .init_constructor = &HTMLXDomainRequestFactory_init, + .vtbl = &HTMLXDomainRequest_event_target_vtbl.dispex_vtbl, + .disp_tid = DispXDomainRequest_tid, + .init_info = HTMLXDomainRequest_init_dispex_info, + .max_compat_mode = COMPAT_MODE_IE10 +};
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/tests/xhr.js | 22 +++++ dlls/mshtml/tests/xmlhttprequest.c | 137 +++++++++++++++++++++++++++++ dlls/mshtml/xmlhttprequest.c | 41 ++++++++- 3 files changed, 198 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/tests/xhr.js b/dlls/mshtml/tests/xhr.js index 7685a5a8486..8de2b01545d 100644 --- a/dlls/mshtml/tests/xhr.js +++ b/dlls/mshtml/tests/xhr.js @@ -238,6 +238,28 @@ async_test("sync_xhr", function() { }, 0); });
+sync_test("xdr", function() { + if(!window.XDomainRequest) return; + + var xdr = new XDomainRequest(); + xdr.open("POST", "echo.php"); + // send() on native aborts with custom pluggable protocol handler even with the right + // response headers (`XDomainRequestAllowed: 1` and `Access-Control-Allow-Origin: *`). + + // Only http/https schemes are allowed, and it must match with the origin's scheme + xdr = new XDomainRequest(); + xdr.open("GET", "http://www.winehq.org/"); + + xdr = new XDomainRequest(); + try { + xdr.open("GET", "https://www.winehq.org/"); + ok(false, "xdr scheme mismatch did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === 0x80070005, "xdr scheme mismatch threw " + n); + } +}); + async_test("content_types", function() { var xhr = new XMLHttpRequest(), types, i = 0, override = false; var v = document.documentMode; diff --git a/dlls/mshtml/tests/xmlhttprequest.c b/dlls/mshtml/tests/xmlhttprequest.c index 44132160520..903b2218380 100644 --- a/dlls/mshtml/tests/xmlhttprequest.c +++ b/dlls/mshtml/tests/xmlhttprequest.c @@ -63,6 +63,7 @@ DEFINE_EXPECT(xmlhttprequest_onreadystatechange_opened); DEFINE_EXPECT(xmlhttprequest_onreadystatechange_headers_received); DEFINE_EXPECT(xmlhttprequest_onreadystatechange_loading); DEFINE_EXPECT(xmlhttprequest_onreadystatechange_done); +DEFINE_EXPECT(xdomainrequest_onload);
#define test_disp(u,id) _test_disp(__LINE__,u,id) static void _test_disp(unsigned line, IUnknown *unk, const IID *diid, const IID *broken_diid) @@ -266,6 +267,58 @@ static IDispatchExVtbl xmlhttprequest_onreadystatechangeFuncVtbl = { }; static IDispatchEx xmlhttprequest_onreadystatechange_obj = { &xmlhttprequest_onreadystatechangeFuncVtbl };
+static HRESULT WINAPI xdomainrequest_onload(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + test_event_args(&DIID_DispXDomainRequest, &IID_IHTMLXDomainRequest, id, wFlags, pdp, pvarRes, pei, pspCaller); + CHECK_EXPECT(xdomainrequest_onload); + return S_OK; +} + +static IDispatchExVtbl xdomainrequest_onloadFuncVtbl = { + DispatchEx_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + DispatchEx_GetDispID, + xdomainrequest_onload, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; +static IDispatchEx xdomainrequest_onload_obj = { &xdomainrequest_onloadFuncVtbl }; + +static HRESULT WINAPI xdomainrequest_ignore(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + return S_OK; +} + +static IDispatchExVtbl xdomainrequest_ignoreFuncVtbl = { + DispatchEx_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + DispatchEx_GetDispID, + xdomainrequest_ignore, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; +static IDispatchEx xdomainrequest_ignore_obj = { &xdomainrequest_ignoreFuncVtbl }; + static BOOL doc_complete; static IHTMLDocument2 *notif_doc;
@@ -1081,6 +1134,89 @@ static void test_timeout(IHTMLDocument2 *doc) IHTMLXMLHttpRequest2_Release(xhr2); }
+static void test_xdr(IHTMLDocument2 *doc) +{ + IHTMLXDomainRequestFactory *factory; + IHTMLXDomainRequest *xdr; + IHTMLWindow6 *window6; + IHTMLWindow2 *window; + BSTR bstr, url; + HRESULT hres; + VARIANT v; + + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + ok(window != NULL, "window == NULL\n"); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow6, (void**)&window6); + IHTMLWindow2_Release(window); + if(FAILED(hres)) { + win_skip("IHTMLWindow6 not supported\n"); + return; + } + + VariantInit(&v); + hres = IHTMLWindow6_get_XDomainRequest(window6, &v); + IHTMLWindow6_Release(window6); + ok(hres == S_OK, "get_XDomainRequest failed: %08lx\n", hres); + ok(V_VT(&v) == VT_DISPATCH, "V_VT(&v) is %08x, expected VT_DISPATCH\n", V_VT(&v)); + + hres = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IHTMLXDomainRequestFactory, (void**)&factory); + VariantClear(&v); + ok(hres == S_OK, "QueryInterface(IID_IXDomainRequestFactory) failed: %08lx\n", hres); + ok(factory != NULL, "factory == NULL\n"); + + hres = IHTMLXDomainRequestFactory_create(factory, &xdr); + IHTMLXDomainRequestFactory_Release(factory); + ok(hres == S_OK, "create failed: %08lx\n", hres); + ok(xdr != NULL, "xdr == NULL\n"); + + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)&xdomainrequest_onload_obj; + hres = IHTMLXDomainRequest_put_onload(xdr, v); + ok(hres == S_OK, "put_onload failed: %08lx\n", hres); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLXDomainRequest_get_onload(xdr, &v); + ok(hres == S_OK, "get_onload failed: %08lx\n", hres); + ok(V_VT(&v) == VT_DISPATCH, "V_VT(onload) = %d\n", V_VT(&v)); + ok(V_DISPATCH(&v) == (IDispatch*)&xdomainrequest_onload_obj, "unexpected onload value\n"); + VariantClear(&v); + + /* Native IE9 sometimes (rarely) aborts if the other handlers are not set */ + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)&xdomainrequest_ignore_obj; + hres = IHTMLXDomainRequest_put_onerror(xdr, v); + ok(hres == S_OK, "put_onerror failed: %08lx\n", hres); + hres = IHTMLXDomainRequest_put_onprogress(xdr, v); + ok(hres == S_OK, "put_onprogress failed: %08lx\n", hres); + hres = IHTMLXDomainRequest_put_ontimeout(xdr, v); + ok(hres == S_OK, "put_ontimeout failed: %08lx\n", hres); + + bstr = SysAllocString(L"GET"); + url = SysAllocString(L"http://test.winehq.org/tests/cors.html"); + hres = IHTMLXDomainRequest_open(xdr, bstr, url); + ok(hres == S_OK, "open failed: %08lx\n", hres); + SysFreeString(bstr); + SysFreeString(url); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = SysAllocString(L"test"); + SET_EXPECT(xdomainrequest_onload); + hres = IHTMLXDomainRequest_send(xdr, v); + ok(hres == S_OK, "send failed: %08lx\n", hres); + if(SUCCEEDED(hres)) + pump_msgs(&called_xdomainrequest_onload); + CHECK_CALLED(xdomainrequest_onload); + + hres = IHTMLXDomainRequest_get_responseText(xdr, &bstr); + ok(hres == S_OK, "get_responseText returned %08lx\n", hres); + ok(!lstrcmpW(bstr, L"<html><body>test</body></html>\n"), "responseText = %s\n", debugstr_w(bstr)); + SysFreeString(bstr); + + IHTMLXDomainRequest_Release(xdr); +} + static IHTMLDocument2 *create_doc_from_url(const WCHAR *start_url) { BSTR url; @@ -1147,6 +1283,7 @@ START_TEST(xmlhttprequest) test_async_xhr_abort(doc, large_page_url); test_xhr_post(doc); test_timeout(doc); + test_xdr(doc); IHTMLDocument2_Release(doc); } SysFreeString(content_type); diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index 2a72abd38dd..00a850d7e34 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -29,6 +29,7 @@
#include "mshtml_private.h" #include "htmlevent.h" +#include "binding.h" #include "mshtmdid.h" #include "initguid.h" #include "msxml6.h" @@ -1871,10 +1872,46 @@ static HRESULT WINAPI HTMLXDomainRequest_abort(IHTMLXDomainRequest *iface) static HRESULT WINAPI HTMLXDomainRequest_open(IHTMLXDomainRequest *iface, BSTR bstrMethod, BSTR bstrUrl) { HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + HTMLOuterWindow *outer_window = This->xhr.window->base.outer_window; + BSTR bstr, bstr2; + nsAString nsstr; + HRESULT hres; + IUri *uri;
- FIXME("(%p)->(%s %s)\n", This, debugstr_w(bstrMethod), debugstr_w(bstrUrl)); + TRACE("(%p)->(%s %s)\n", This, debugstr_w(bstrMethod), debugstr_w(bstrUrl));
- return E_NOTIMPL; + if(!outer_window || !outer_window->uri) + return E_ACCESSDENIED; + + hres = create_relative_uri(outer_window, bstrUrl, &uri); + if(FAILED(hres)) + return hres; + + hres = IUri_GetSchemeName(outer_window->uri, &bstr); + if(hres == S_OK) { + hres = IUri_GetSchemeName(uri, &bstr2); + if(hres == S_OK) { + if(wcsicmp(bstr, bstr2)) + hres = E_ACCESSDENIED; + SysFreeString(bstr2); + } + SysFreeString(bstr); + } + IUri_Release(uri); + if(hres != S_OK) + return E_ACCESSDENIED; + + hres = xhr_open(&This->xhr, bstrMethod, bstrUrl, TRUE, NULL, NULL, 1); + if(FAILED(hres)) + return hres; + + /* Prevent Gecko from parsing responseXML for no reason */ + nsAString_InitDepend(&nsstr, L"text"); + nsIXMLHttpRequest_SetResponseType(This->xhr.nsxhr, &nsstr); + nsAString_Finish(&nsstr); + + /* IE always adds Origin header, even from same origin, but Gecko doesn't allow us to alter it. */ + return S_OK; }
static HRESULT WINAPI HTMLXDomainRequest_send(IHTMLXDomainRequest *iface, VARIANT varBody)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/tests/xmlhttprequest.c | 15 +++++++++++++++ dlls/mshtml/xmlhttprequest.c | 17 +++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/dlls/mshtml/tests/xmlhttprequest.c b/dlls/mshtml/tests/xmlhttprequest.c index 903b2218380..23a871f2991 100644 --- a/dlls/mshtml/tests/xmlhttprequest.c +++ b/dlls/mshtml/tests/xmlhttprequest.c @@ -1142,6 +1142,7 @@ static void test_xdr(IHTMLDocument2 *doc) IHTMLWindow2 *window; BSTR bstr, url; HRESULT hres; + LONG timeout; VARIANT v;
hres = IHTMLDocument2_get_parentWindow(doc, &window); @@ -1200,6 +1201,20 @@ static void test_xdr(IHTMLDocument2 *doc) SysFreeString(bstr); SysFreeString(url);
+ hres = IHTMLXDomainRequest_get_timeout(xdr, NULL); + ok(hres == E_INVALIDARG, "get_timeout returned %08lx\n", hres); + hres = IHTMLXDomainRequest_get_timeout(xdr, &timeout); + ok(hres == S_OK, "get_timeout returned %08lx\n", hres); + ok(timeout == -1, "timeout = %ld\n", timeout); + + hres = IHTMLXDomainRequest_put_timeout(xdr, -1); + ok(hres == E_INVALIDARG || broken(hres == E_FAIL), "put_timeout returned %08lx\n", hres); + hres = IHTMLXDomainRequest_put_timeout(xdr, 1337); + ok(hres == S_OK, "put_timeout returned %08lx\n", hres); + hres = IHTMLXDomainRequest_get_timeout(xdr, &timeout); + ok(hres == S_OK, "get_timeout returned %08lx\n", hres); + ok(timeout == 1337, "timeout = %ld\n", timeout); + V_VT(&v) = VT_BSTR; V_BSTR(&v) = SysAllocString(L"test"); SET_EXPECT(xdomainrequest_onload); diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index 00a850d7e34..ab8c7c9dca3 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -1767,18 +1767,27 @@ static HRESULT WINAPI HTMLXDomainRequest_put_timeout(IHTMLXDomainRequest *iface, { HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface);
- FIXME("(%p)->(%ld)\n", This, v); + TRACE("(%p)->(%ld)\n", This, v);
- return E_NOTIMPL; + if(v < 0) + return E_INVALIDARG; + return map_nsresult(nsIXMLHttpRequest_SetTimeout(This->xhr.nsxhr, v)); }
static HRESULT WINAPI HTMLXDomainRequest_get_timeout(IHTMLXDomainRequest *iface, LONG *p) { HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + nsresult nsres; + UINT32 timeout;
- FIXME("(%p)->(%p)\n", This, p); + TRACE("(%p)->(%p)\n", This, p);
- return E_NOTIMPL; + if(!p) + return E_INVALIDARG; + + nsres = nsIXMLHttpRequest_GetTimeout(This->xhr.nsxhr, &timeout); + *p = timeout ? timeout : -1; + return map_nsresult(nsres); }
static HRESULT WINAPI HTMLXDomainRequest_get_contentType(IHTMLXDomainRequest *iface, BSTR *p)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/tests/dom.c | 5 +++++ dlls/mshtml/tests/xmlhttprequest.c | 13 ++++++++++++ dlls/mshtml/xmlhttprequest.c | 34 ++++++++++++++++++++++++++++-- 3 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index f3aec7d9046..3235cbbaca5 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -8050,6 +8050,7 @@ static void test_xdomainrequest(IHTMLWindow6 *window) IHTMLXDomainRequest *xdr; HRESULT hres; VARIANT var; + BSTR bstr;
hres = IHTMLWindow6_get_XDomainRequest(window, &var); ok(hres == S_OK, "get_XDomainRequest failed: %08lx\n", hres); @@ -8074,6 +8075,10 @@ static void test_xdomainrequest(IHTMLWindow6 *window) if(is_ie9plus) test_disp((IUnknown*)xdr, &DIID_DispXDomainRequest, NULL, L"[object]");
+ hres = IHTMLXDomainRequest_get_contentType(xdr, &bstr); + ok(hres == S_OK, "get_contentType returned %08lx\n", hres); + ok(bstr == NULL, "contentType = %s\n", debugstr_w(bstr)); + IHTMLXDomainRequest_Release(xdr); IHTMLXDomainRequestFactory_Release(factory); VariantClear(&var); diff --git a/dlls/mshtml/tests/xmlhttprequest.c b/dlls/mshtml/tests/xmlhttprequest.c index 23a871f2991..5a2afd4e1cc 100644 --- a/dlls/mshtml/tests/xmlhttprequest.c +++ b/dlls/mshtml/tests/xmlhttprequest.c @@ -1194,6 +1194,10 @@ static void test_xdr(IHTMLDocument2 *doc) hres = IHTMLXDomainRequest_put_ontimeout(xdr, v); ok(hres == S_OK, "put_ontimeout failed: %08lx\n", hres);
+ hres = IHTMLXDomainRequest_get_contentType(xdr, &bstr); + ok(hres == S_OK, "get_contentType returned %08lx\n", hres); + ok(bstr == NULL, "contentType = %s\n", debugstr_w(bstr)); + bstr = SysAllocString(L"GET"); url = SysAllocString(L"http://test.winehq.org/tests/cors.html"); hres = IHTMLXDomainRequest_open(xdr, bstr, url); @@ -1201,6 +1205,10 @@ static void test_xdr(IHTMLDocument2 *doc) SysFreeString(bstr); SysFreeString(url);
+ hres = IHTMLXDomainRequest_get_contentType(xdr, &bstr); + ok(hres == S_OK, "get_contentType returned %08lx\n", hres); + ok(bstr == NULL, "contentType = %s\n", debugstr_w(bstr)); + hres = IHTMLXDomainRequest_get_timeout(xdr, NULL); ok(hres == E_INVALIDARG, "get_timeout returned %08lx\n", hres); hres = IHTMLXDomainRequest_get_timeout(xdr, &timeout); @@ -1229,6 +1237,11 @@ static void test_xdr(IHTMLDocument2 *doc) ok(!lstrcmpW(bstr, L"<html><body>test</body></html>\n"), "responseText = %s\n", debugstr_w(bstr)); SysFreeString(bstr);
+ hres = IHTMLXDomainRequest_get_contentType(xdr, &bstr); + ok(hres == S_OK, "get_contentType returned %08lx\n", hres); + ok(!lstrcmpW(bstr, L"text/html"), "contentType = %s\n", debugstr_w(bstr)); + SysFreeString(bstr); + IHTMLXDomainRequest_Release(xdr); }
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index ab8c7c9dca3..11c20d75dc1 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -1793,10 +1793,40 @@ static HRESULT WINAPI HTMLXDomainRequest_get_timeout(IHTMLXDomainRequest *iface, static HRESULT WINAPI HTMLXDomainRequest_get_contentType(IHTMLXDomainRequest *iface, BSTR *p) { HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + const char *content_type = "text/plain"; + nsIChannel *nschannel; + HRESULT hres = S_OK; + nsACString nsstr; + nsresult nsres; + int len;
- FIXME("(%p)->(%p)\n", This, p); + TRACE("(%p)->(%p)\n", This, p);
- return E_NOTIMPL; + if(!p) + return E_POINTER; + + if(This->xhr.ready_state < READYSTATE_LOADED) { + *p = NULL; + return S_OK; + } + + nsACString_Init(&nsstr, NULL); + + nsres = nsIXMLHttpRequest_GetChannel(This->xhr.nsxhr, &nschannel); + if(NS_SUCCEEDED(nsres)) { + nsres = nsIChannel_GetContentType(nschannel, &nsstr); + if(NS_SUCCEEDED(nsres)) + nsACString_GetData(&nsstr, &content_type); + } + + len = MultiByteToWideChar(CP_UTF8, 0, content_type, -1, NULL, 0); + if(!(*p = SysAllocStringLen(NULL, len - 1))) + hres = E_OUTOFMEMORY; + else + MultiByteToWideChar(CP_UTF8, 0, content_type, -1, *p, len); + + nsACString_Finish(&nsstr); + return hres; }
static HRESULT WINAPI HTMLXDomainRequest_put_onprogress(IHTMLXDomainRequest *iface, VARIANT v)
Jacek Caban (@jacek) commented about dlls/mshtml/xmlhttprequest.c:
return hres;
}
-static HRESULT WINAPI HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest *iface, VARIANT varBody) +static HRESULT WINAPI xhr_send(struct xhr *xhr, VARIANT varBody)
Please pass `VARIANT` by pointer internally.
Jacek Caban (@jacek) commented about dlls/mshtml/xmlhttprequest.c:
- nsAString nsstr;
- HRESULT hres;
- IUri *uri;
- FIXME("(%p)->(%s %s)\n", This, debugstr_w(bstrMethod), debugstr_w(bstrUrl));
- TRACE("(%p)->(%s %s)\n", This, debugstr_w(bstrMethod), debugstr_w(bstrUrl));
- return E_NOTIMPL;
- if(!outer_window || !outer_window->uri)
return E_ACCESSDENIED;
- hres = create_relative_uri(outer_window, bstrUrl, &uri);
- if(FAILED(hres))
return hres;
- hres = IUri_GetSchemeName(outer_window->uri, &bstr);
If it's restricted to http(s) anyway, you could just use `GetScheme` here.