-- v3: 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 | 72 +++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 33 deletions(-)
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index cb668f52686..db6cd0782eb 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -737,31 +737,8 @@ static HRESULT WINAPI HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest *iface) return xhr_abort(&This->xhr); }
-static HRESULT HTMLXMLHttpRequest_open_hook(DispatchEx *dispex, WORD flags, - DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +static HRESULT WINAPI xhr_open(struct xhr *xhr, BSTR bstrMethod, BSTR bstrUrl, VARIANT varAsync, VARIANT varUser, VARIANT varPassword) { - /* If only two arguments were given, implicitly set async to false */ - if((flags & DISPATCH_METHOD) && dp->cArgs == 2 && !dp->cNamedArgs) { - VARIANT args[5]; - DISPPARAMS new_dp = {args, NULL, ARRAY_SIZE(args), 0}; - V_VT(args) = VT_EMPTY; - V_VT(args+1) = VT_EMPTY; - V_VT(args+2) = VT_BOOL; - V_BOOL(args+2) = VARIANT_TRUE; - args[3] = dp->rgvarg[0]; - args[4] = dp->rgvarg[1]; - - TRACE("implicit async\n"); - - return dispex_call_builtin(dispex, DISPID_IHTMLXMLHTTPREQUEST_OPEN, &new_dp, res, ei, caller); - } - - return S_FALSE; /* fallback to default */ -} - -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; @@ -770,8 +747,6 @@ static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR b 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)); - if(V_VT(&varAsync) != VT_BOOL) { LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT); hres = VariantChangeTypeEx(&varAsync, &varAsync, lcid, 0, VT_BOOL); @@ -805,16 +780,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->xhr.magic; - prev_synchronous = This->xhr.synchronous; - This->xhr.synchronous = !V_BOOL(&varAsync); - This->xhr.magic++; + prev_magic = xhr->magic; + prev_synchronous = xhr->synchronous; + xhr->synchronous = !V_BOOL(&varAsync); + 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); + nsres = nsIXMLHttpRequest_Open(xhr->nsxhr, &method, &url, !!V_BOOL(&varAsync), &user, &password, opt_argc);
nsACString_Finish(&method); nsACString_Finish(&url); @@ -823,14 +798,45 @@ static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR b
if(NS_FAILED(nsres)) { ERR("nsIXMLHttpRequest_Open failed: %08lx\n", nsres); - This->xhr.magic = prev_magic; - This->xhr.synchronous = prev_synchronous; + 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) +{ + /* If only two arguments were given, implicitly set async to false */ + if((flags & DISPATCH_METHOD) && dp->cArgs == 2 && !dp->cNamedArgs) { + VARIANT args[5]; + DISPPARAMS new_dp = {args, NULL, ARRAY_SIZE(args), 0}; + V_VT(args) = VT_EMPTY; + V_VT(args+1) = VT_EMPTY; + V_VT(args+2) = VT_BOOL; + V_BOOL(args+2) = VARIANT_TRUE; + args[3] = dp->rgvarg[0]; + args[4] = dp->rgvarg[1]; + + TRACE("implicit async\n"); + + return dispex_call_builtin(dispex, DISPID_IHTMLXMLHTTPREQUEST_OPEN, &new_dp, res, ei, caller); + } + + return S_FALSE; /* fallback to default */ +} + +static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR bstrMethod, BSTR bstrUrl, VARIANT varAsync, VARIANT varUser, VARIANT varPassword) +{ + HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface); + + TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(bstrMethod), debugstr_w(bstrUrl), debugstr_variant(&varAsync), debugstr_variant(&varUser), debugstr_variant(&varPassword)); + + return xhr_open(&This->xhr, bstrMethod, bstrUrl, varAsync, varUser, varPassword); +} + static HRESULT WINAPI HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest *iface, VARIANT varBody) { 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 | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index db6cd0782eb..cd74589e006 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -837,14 +837,11 @@ static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR b return xhr_open(&This->xhr, bstrMethod, bstrUrl, varAsync, varUser, varPassword); }
-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: @@ -868,10 +865,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) @@ -884,6 +881,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 cd74589e006..d5d0a3627df 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; @@ -1740,3 +1745,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 | 39 +++++++- 3 files changed, 196 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 d5d0a3627df..1bc79fce610 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -1873,10 +1873,45 @@ static HRESULT WINAPI HTMLXDomainRequest_abort(IHTMLXDomainRequest *iface) static HRESULT WINAPI HTMLXDomainRequest_open(IHTMLXDomainRequest *iface, BSTR bstrMethod, BSTR bstrUrl) { HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface); + VARIANT vtrue, vempty; + nsAString nsstr; + HRESULT hres; + WCHAR *p;
- 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((p = wcschr(bstrUrl, ':')) && p[1] == '/' && p[2] == '/') { + size_t len = p - bstrUrl; + BSTR bstr; + + /* Native only allows http and https, and the scheme must match */ + if(len < 4 || len > 5 || wcsnicmp(bstrUrl, L"https", len) || !This->xhr.window->base.outer_window || !This->xhr.window->base.outer_window->uri) + return E_ACCESSDENIED; + + hres = IUri_GetSchemeName(This->xhr.window->base.outer_window->uri, &bstr); + if(FAILED(hres)) + return hres; + if(SysStringLen(bstr) != len || wcsnicmp(bstr, bstrUrl, len)) + hres = E_ACCESSDENIED; + SysFreeString(bstr); + if(FAILED(hres)) + return hres; + } + + V_VT(&vtrue) = VT_BOOL; + V_BOOL(&vtrue) = VARIANT_TRUE; + V_VT(&vempty) = VT_EMPTY; + hres = xhr_open(&This->xhr, bstrMethod, bstrUrl, vtrue, vempty, vempty); + 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 1bc79fce610..faf82808c56 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -1768,18 +1768,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 faf82808c56..abc7bb41270 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -1794,10 +1794,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)
Ok, I actually don't know why the tests time out on Windows CI (can't repro on my local VM), do you have any ideas or a way to try debug?
Jacek Caban (@jacek) commented about dlls/mshtml/xmlhttprequest.c:
return xhr_abort(&This->xhr);
}
-static HRESULT HTMLXMLHttpRequest_open_hook(DispatchEx *dispex, WORD flags,
DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
+static HRESULT WINAPI xhr_open(struct xhr *xhr, BSTR bstrMethod, BSTR bstrUrl, VARIANT varAsync, VARIANT varUser, VARIANT varPassword)
I think it would be nicer to leave `VARIANT` conversion to callers and use bool and string types here. It's specific to XHR, so we can keep it there.
Jacek Caban (@jacek) commented about dlls/mshtml/xmlhttprequest.c:
static HRESULT WINAPI HTMLXDomainRequest_open(IHTMLXDomainRequest *iface, BSTR bstrMethod, BSTR bstrUrl) { HTMLXDomainRequest *This = impl_from_IHTMLXDomainRequest(iface);
- VARIANT vtrue, vempty;
- nsAString nsstr;
- HRESULT hres;
- WCHAR *p;
- 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((p = wcschr(bstrUrl, ':')) && p[1] == '/' && p[2] == '/') {
This seems fragile. I think this is meant to check if URL is not relative? If yes, then what if it's relative but the document is not http?
Is it even specific to XDR and doesn't apply to XHR? Could we just remove that check?
On Wed Sep 17 14:59:40 2025 +0000, Jacek Caban wrote:
This seems fragile. I think this is meant to check if URL is not relative? If yes, then what if it's relative but the document is not http? Is it even specific to XDR and doesn't apply to XHR? Could we just remove that check?
Yeah, it's supposed to only allow http URLs. I also skipped relative URLs since I wasn't sure how to handle them.
And yes it's specific to XDR, IIRC rationale given on some Microsoft blog was that it needs the response headers to see if it allows cross origin and that's http specific. (obviously this was before XHR supported cross-domain requests)
Note that if I remove it, one of the tests will have to be turned into todo.
On Wed Sep 17 18:59:45 2025 +0000, Gabriel Ivăncescu wrote:
Yeah, it's supposed to only allow http URLs. I also skipped relative URLs since I wasn't sure how to handle them. And yes it's specific to XDR, IIRC rationale given on some Microsoft blog was that it needs the response headers to see if it allows cross origin and that's http specific. (obviously this was before XHR supported cross-domain requests) Note that if I remove it, one of the tests will have to be turned into todo.
The quoted rationale would explain why it would be allowed only on http document URLs, but here you check request URL, so I don't see how it's relevant.
Ad-hoc parsing or comparing URLs is rarely a good idea. A valid absolute URL may have "//" part missing or a relative URL may have "://" as part of the query. We'd probably need to use `IUri` interface to combine URLs and then perform checks on it if we really need them.
The rest of the logic seems questionable. Are you sure we don't want to allow https XDRs from http documents? We don't want to allow things like file protocol, but that's not specific to XDR.