2 * Copyright 2015 Zhenbo Li
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "wine/debug.h"
31 #include "mshtml_private.h"
32 #include "htmlevent.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(mshtml
);
40 #define MSHTML_DISPID_HTMLXMLHTTPREQUEST_ONLOAD MSHTML_DISPID_CUSTOM_MIN
42 static HRESULT
bstr_to_nsacstr(BSTR bstr
, nsACString
*str
)
44 char *cstr
= heap_strdupWtoU(bstr
);
47 nsACString_Init(str
, cstr
);
52 static HRESULT
variant_to_nsastr(VARIANT var
, nsAString
*ret
)
58 nsAString_Init(ret
, NULL
);
61 nsAString_InitDepend(ret
, V_BSTR(&var
));
64 FIXME("Unsupported VARIANT: %s\n", debugstr_variant(&var
));
69 static HRESULT
return_nscstr(nsresult nsres
, nsACString
*nscstr
, BSTR
*p
)
74 if(NS_FAILED(nsres
)) {
75 ERR("failed: %08x\n", nsres
);
76 nsACString_Finish(nscstr
);
80 nsACString_GetData(nscstr
, &str
);
83 len
= MultiByteToWideChar(CP_UTF8
, 0, str
, -1, NULL
, 0);
84 *p
= SysAllocStringLen(NULL
, len
- 1);
86 nsACString_Finish(nscstr
);
89 MultiByteToWideChar(CP_UTF8
, 0, str
, -1, *p
, len
);
94 nsACString_Finish(nscstr
);
99 nsIDOMEventListener nsIDOMEventListener_iface
;
101 HTMLXMLHttpRequest
*xhr
;
102 BOOL readystatechange_event
;
104 } XMLHttpReqEventListener
;
106 struct HTMLXMLHttpRequest
{
107 EventTarget event_target
;
108 IHTMLXMLHttpRequest IHTMLXMLHttpRequest_iface
;
109 IProvideClassInfo2 IProvideClassInfo2_iface
;
111 nsIXMLHttpRequest
*nsxhr
;
112 XMLHttpReqEventListener
*event_listener
;
115 static void detach_xhr_event_listener(XMLHttpReqEventListener
*event_listener
)
117 nsIDOMEventTarget
*event_target
;
121 nsres
= nsIXMLHttpRequest_QueryInterface(event_listener
->xhr
->nsxhr
, &IID_nsIDOMEventTarget
, (void**)&event_target
);
122 assert(nsres
== NS_OK
);
124 if(event_listener
->readystatechange_event
) {
125 nsAString_InitDepend(&str
, L
"onreadystatechange");
126 nsres
= nsIDOMEventTarget_RemoveEventListener(event_target
, &str
, &event_listener
->nsIDOMEventListener_iface
, FALSE
);
127 nsAString_Finish(&str
);
128 assert(nsres
== NS_OK
);
131 if(event_listener
->load_event
) {
132 nsAString_InitDepend(&str
, L
"load");
133 nsres
= nsIDOMEventTarget_RemoveEventListener(event_target
, &str
, &event_listener
->nsIDOMEventListener_iface
, FALSE
);
134 nsAString_Finish(&str
);
135 assert(nsres
== NS_OK
);
138 nsIDOMEventTarget_Release(event_target
);
140 event_listener
->xhr
->event_listener
= NULL
;
141 event_listener
->xhr
= NULL
;
142 nsIDOMEventListener_Release(&event_listener
->nsIDOMEventListener_iface
);
146 static inline XMLHttpReqEventListener
*impl_from_nsIDOMEventListener(nsIDOMEventListener
*iface
)
148 return CONTAINING_RECORD(iface
, XMLHttpReqEventListener
, nsIDOMEventListener_iface
);
151 static nsresult NSAPI
XMLHttpReqEventListener_QueryInterface(nsIDOMEventListener
*iface
,
152 nsIIDRef riid
, void **result
)
154 XMLHttpReqEventListener
*This
= impl_from_nsIDOMEventListener(iface
);
156 if(IsEqualGUID(&IID_nsISupports
, riid
)) {
157 TRACE("(%p)->(IID_nsISupports, %p)\n", This
, result
);
158 *result
= &This
->nsIDOMEventListener_iface
;
159 }else if(IsEqualGUID(&IID_nsIDOMEventListener
, riid
)) {
160 TRACE("(%p)->(IID_nsIDOMEventListener %p)\n", This
, result
);
161 *result
= &This
->nsIDOMEventListener_iface
;
164 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), result
);
165 return NS_NOINTERFACE
;
168 nsIDOMEventListener_AddRef(&This
->nsIDOMEventListener_iface
);
172 static nsrefcnt NSAPI
XMLHttpReqEventListener_AddRef(nsIDOMEventListener
*iface
)
174 XMLHttpReqEventListener
*This
= impl_from_nsIDOMEventListener(iface
);
175 LONG ref
= InterlockedIncrement(&This
->ref
);
177 TRACE("(%p) ref=%d\n", This
, ref
);
182 static nsrefcnt NSAPI
XMLHttpReqEventListener_Release(nsIDOMEventListener
*iface
)
184 XMLHttpReqEventListener
*This
= impl_from_nsIDOMEventListener(iface
);
185 LONG ref
= InterlockedDecrement(&This
->ref
);
187 TRACE("(%p) ref=%d\n", This
, ref
);
197 static nsresult NSAPI
XMLHttpReqEventListener_HandleEvent(nsIDOMEventListener
*iface
, nsIDOMEvent
*nsevent
)
199 XMLHttpReqEventListener
*This
= impl_from_nsIDOMEventListener(iface
);
203 TRACE("(%p)\n", This
);
208 hres
= create_event_from_nsevent(nsevent
, dispex_compat_mode(&This
->xhr
->event_target
.dispex
), &event
);
209 if(SUCCEEDED(hres
) ){
210 dispatch_event(&This
->xhr
->event_target
, event
);
211 IDOMEvent_Release(&event
->IDOMEvent_iface
);
216 static const nsIDOMEventListenerVtbl XMLHttpReqEventListenerVtbl
= {
217 XMLHttpReqEventListener_QueryInterface
,
218 XMLHttpReqEventListener_AddRef
,
219 XMLHttpReqEventListener_Release
,
220 XMLHttpReqEventListener_HandleEvent
223 static inline HTMLXMLHttpRequest
*impl_from_IHTMLXMLHttpRequest(IHTMLXMLHttpRequest
*iface
)
225 return CONTAINING_RECORD(iface
, HTMLXMLHttpRequest
, IHTMLXMLHttpRequest_iface
);
228 static HRESULT WINAPI
HTMLXMLHttpRequest_QueryInterface(IHTMLXMLHttpRequest
*iface
, REFIID riid
, void **ppv
)
230 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
232 TRACE("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
234 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
235 *ppv
= &This
->IHTMLXMLHttpRequest_iface
;
236 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
237 *ppv
= &This
->IHTMLXMLHttpRequest_iface
;
238 }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequest
, riid
)) {
239 *ppv
= &This
->IHTMLXMLHttpRequest_iface
;
240 }else if(IsEqualGUID(&IID_IProvideClassInfo
, riid
)) {
241 *ppv
= &This
->IProvideClassInfo2_iface
;
242 }else if(IsEqualGUID(&IID_IProvideClassInfo2
, riid
)) {
243 *ppv
= &This
->IProvideClassInfo2_iface
;
245 return EventTarget_QI(&This
->event_target
, riid
, ppv
);
248 IUnknown_AddRef((IUnknown
*)*ppv
);
252 static ULONG WINAPI
HTMLXMLHttpRequest_AddRef(IHTMLXMLHttpRequest
*iface
)
254 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
255 LONG ref
= InterlockedIncrement(&This
->ref
);
257 TRACE("(%p) ref=%d\n", This
, ref
);
262 static ULONG WINAPI
HTMLXMLHttpRequest_Release(IHTMLXMLHttpRequest
*iface
)
264 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
265 LONG ref
= InterlockedDecrement(&This
->ref
);
267 TRACE("(%p) ref=%d\n", This
, ref
);
270 if(This
->event_listener
)
271 detach_xhr_event_listener(This
->event_listener
);
272 release_event_target(&This
->event_target
);
273 release_dispex(&This
->event_target
.dispex
);
274 nsIXMLHttpRequest_Release(This
->nsxhr
);
281 static HRESULT WINAPI
HTMLXMLHttpRequest_GetTypeInfoCount(IHTMLXMLHttpRequest
*iface
, UINT
*pctinfo
)
283 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
284 return IDispatchEx_GetTypeInfoCount(&This
->event_target
.dispex
.IDispatchEx_iface
, pctinfo
);
287 static HRESULT WINAPI
HTMLXMLHttpRequest_GetTypeInfo(IHTMLXMLHttpRequest
*iface
, UINT iTInfo
,
288 LCID lcid
, ITypeInfo
**ppTInfo
)
290 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
292 return IDispatchEx_GetTypeInfo(&This
->event_target
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
295 static HRESULT WINAPI
HTMLXMLHttpRequest_GetIDsOfNames(IHTMLXMLHttpRequest
*iface
, REFIID riid
, LPOLESTR
*rgszNames
, UINT cNames
,
296 LCID lcid
, DISPID
*rgDispId
)
298 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
300 return IDispatchEx_GetIDsOfNames(&This
->event_target
.dispex
.IDispatchEx_iface
, riid
, rgszNames
, cNames
,
304 static HRESULT WINAPI
HTMLXMLHttpRequest_Invoke(IHTMLXMLHttpRequest
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
305 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
307 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
309 return IDispatchEx_Invoke(&This
->event_target
.dispex
.IDispatchEx_iface
, dispIdMember
, riid
, lcid
, wFlags
,
310 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
313 static HRESULT WINAPI
HTMLXMLHttpRequest_get_readyState(IHTMLXMLHttpRequest
*iface
, LONG
*p
)
315 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
319 TRACE("(%p)->(%p)\n", This
, p
);
323 nsres
= nsIXMLHttpRequest_GetReadyState(This
->nsxhr
, &val
);
324 if(NS_FAILED(nsres
)) {
325 ERR("nsIXMLHttpRequest_GetReadyState failed: %08x\n", nsres
);
332 static HRESULT WINAPI
HTMLXMLHttpRequest_get_responseBody(IHTMLXMLHttpRequest
*iface
, VARIANT
*p
)
334 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
335 FIXME("(%p)->(%p)\n", This
, p
);
339 static HRESULT WINAPI
HTMLXMLHttpRequest_get_responseText(IHTMLXMLHttpRequest
*iface
, BSTR
*p
)
341 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
345 TRACE("(%p)->(%p)\n", This
, p
);
350 nsAString_Init(&nsstr
, NULL
);
351 nsres
= nsIXMLHttpRequest_GetResponseText(This
->nsxhr
, &nsstr
);
352 return return_nsstr(nsres
, &nsstr
, p
);
355 static HRESULT WINAPI
HTMLXMLHttpRequest_get_responseXML(IHTMLXMLHttpRequest
*iface
, IDispatch
**p
)
357 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
358 IXMLDOMDocument
*xmldoc
= NULL
;
362 IObjectSafety
*safety
;
364 TRACE("(%p)->(%p)\n", This
, p
);
366 hres
= CoCreateInstance(&CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IXMLDOMDocument
, (void**)&xmldoc
);
368 ERR("CoCreateInstance failed: %08x\n", hres
);
372 hres
= IHTMLXMLHttpRequest_get_responseText(iface
, &str
);
374 IXMLDOMDocument_Release(xmldoc
);
375 ERR("get_responseText failed: %08x\n", hres
);
379 hres
= IXMLDOMDocument_loadXML(xmldoc
, str
, &vbool
);
381 if(hres
!= S_OK
|| vbool
!= VARIANT_TRUE
)
382 WARN("loadXML failed: %08x, returning an empty xmldoc\n", hres
);
384 hres
= IXMLDOMDocument_QueryInterface(xmldoc
, &IID_IObjectSafety
, (void**)&safety
);
385 assert(SUCCEEDED(hres
));
386 hres
= IObjectSafety_SetInterfaceSafetyOptions(safety
, NULL
,
387 INTERFACESAFE_FOR_UNTRUSTED_CALLER
| INTERFACESAFE_FOR_UNTRUSTED_DATA
| INTERFACE_USES_SECURITY_MANAGER
,
388 INTERFACESAFE_FOR_UNTRUSTED_CALLER
| INTERFACESAFE_FOR_UNTRUSTED_DATA
| INTERFACE_USES_SECURITY_MANAGER
);
389 assert(SUCCEEDED(hres
));
390 IObjectSafety_Release(safety
);
392 *p
= (IDispatch
*)xmldoc
;
396 static HRESULT WINAPI
HTMLXMLHttpRequest_get_status(IHTMLXMLHttpRequest
*iface
, LONG
*p
)
398 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
401 TRACE("(%p)->(%p)\n", This
, p
);
406 nsres
= nsIXMLHttpRequest_GetStatus(This
->nsxhr
, &val
);
407 if(NS_FAILED(nsres
)) {
408 ERR("nsIXMLHttpRequest_GetStatus failed: %08x\n", nsres
);
413 return E_FAIL
; /* WinAPI thinks this is an error */
418 static HRESULT WINAPI
HTMLXMLHttpRequest_get_statusText(IHTMLXMLHttpRequest
*iface
, BSTR
*p
)
420 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
426 TRACE("(%p)->(%p)\n", This
, p
);
431 hres
= IHTMLXMLHttpRequest_get_readyState(iface
, &state
);
440 nsACString_Init(&nscstr
, NULL
);
441 nsres
= nsIXMLHttpRequest_GetStatusText(This
->nsxhr
, &nscstr
);
442 return return_nscstr(nsres
, &nscstr
, p
);
445 static HRESULT WINAPI
HTMLXMLHttpRequest_put_onreadystatechange(IHTMLXMLHttpRequest
*iface
, VARIANT v
)
447 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
449 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&v
));
451 return set_event_handler(&This
->event_target
, EVENTID_READYSTATECHANGE
, &v
);
454 static HRESULT WINAPI
HTMLXMLHttpRequest_get_onreadystatechange(IHTMLXMLHttpRequest
*iface
, VARIANT
*p
)
456 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
458 TRACE("(%p)->(%p)\n", This
, p
);
460 return get_event_handler(&This
->event_target
, EVENTID_READYSTATECHANGE
, p
);
463 static HRESULT WINAPI
HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest
*iface
)
465 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
468 TRACE("(%p)->()\n", This
);
470 nsres
= nsIXMLHttpRequest_SlowAbort(This
->nsxhr
);
471 if(NS_FAILED(nsres
)) {
472 ERR("nsIXMLHttpRequest_SlowAbort failed: %08x\n", nsres
);
479 static HRESULT
HTMLXMLHttpRequest_open_hook(DispatchEx
*dispex
, LCID lcid
, WORD flags
,
480 DISPPARAMS
*dp
, VARIANT
*res
, EXCEPINFO
*ei
, IServiceProvider
*caller
)
482 /* If only two arguments were given, implicitly set async to false */
483 if((flags
& DISPATCH_METHOD
) && dp
->cArgs
== 2 && !dp
->cNamedArgs
) {
485 DISPPARAMS new_dp
= {args
, NULL
, ARRAY_SIZE(args
), 0};
486 V_VT(args
) = VT_EMPTY
;
487 V_VT(args
+1) = VT_EMPTY
;
488 V_VT(args
+2) = VT_BOOL
;
489 V_BOOL(args
+2) = VARIANT_TRUE
;
490 args
[3] = dp
->rgvarg
[0];
491 args
[4] = dp
->rgvarg
[1];
493 TRACE("implicit async\n");
495 return IDispatchEx_InvokeEx(&dispex
->IDispatchEx_iface
, DISPID_IHTMLXMLHTTPREQUEST_OPEN
,
496 lcid
, flags
, &new_dp
, res
, ei
, caller
);
499 return S_FALSE
; /* fallback to default */
502 static HRESULT WINAPI
HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest
*iface
, BSTR bstrMethod
, BSTR bstrUrl
, VARIANT varAsync
, VARIANT varUser
, VARIANT varPassword
)
504 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
505 nsACString method
, url
;
506 nsAString user
, password
;
510 TRACE("(%p)->(%s %s %s %s %s)\n", This
, debugstr_w(bstrMethod
), debugstr_w(bstrUrl
), debugstr_variant(&varAsync
), debugstr_variant(&varUser
), debugstr_variant(&varPassword
));
512 if(V_VT(&varAsync
) != VT_BOOL
) {
513 FIXME("varAsync not supported: %s\n", debugstr_variant(&varAsync
));
517 /* Note: Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27),
518 * synchronous requests on the main thread have been deprecated due to the negative
519 * effects to the user experience.
521 if(!V_BOOL(&varAsync
)) {
522 FIXME("Synchronous request is not supported yet\n");
526 hres
= variant_to_nsastr(varUser
, &user
);
529 hres
= variant_to_nsastr(varPassword
, &password
);
531 nsAString_Finish(&user
);
535 hres
= bstr_to_nsacstr(bstrMethod
, &method
);
537 nsAString_Finish(&user
);
538 nsAString_Finish(&password
);
541 hres
= bstr_to_nsacstr(bstrUrl
, &url
);
543 nsAString_Finish(&user
);
544 nsAString_Finish(&password
);
545 nsACString_Finish(&method
);
549 nsres
= nsIXMLHttpRequest_Open(This
->nsxhr
, &method
, &url
, TRUE
,
550 &user
, &password
, 0);
552 nsACString_Finish(&method
);
553 nsACString_Finish(&url
);
554 nsAString_Finish(&user
);
555 nsAString_Finish(&password
);
557 if(NS_FAILED(nsres
)) {
558 ERR("nsIXMLHttpRequest_Open failed: %08x\n", nsres
);
565 static HRESULT WINAPI
HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest
*iface
, VARIANT varBody
)
567 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
568 nsIWritableVariant
*nsbody
= NULL
;
569 nsresult nsres
= NS_OK
;
571 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&varBody
));
573 switch(V_VT(&varBody
)) {
581 nsbody
= create_nsvariant();
583 return E_OUTOFMEMORY
;
585 nsAString_InitDepend(&nsstr
, V_BSTR(&varBody
));
586 nsres
= nsIWritableVariant_SetAsAString(nsbody
, &nsstr
);
587 nsAString_Finish(&nsstr
);
591 FIXME("unsupported body type %s\n", debugstr_variant(&varBody
));
595 if(NS_SUCCEEDED(nsres
))
596 nsres
= nsIXMLHttpRequest_Send(This
->nsxhr
, (nsIVariant
*)nsbody
);
598 nsIWritableVariant_Release(nsbody
);
599 if(NS_FAILED(nsres
)) {
600 ERR("nsIXMLHttpRequest_Send failed: %08x\n", nsres
);
607 static HRESULT WINAPI
HTMLXMLHttpRequest_getAllResponseHeaders(IHTMLXMLHttpRequest
*iface
, BSTR
*p
)
609 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
615 TRACE("(%p)->(%p)\n", This
, p
);
620 hres
= IHTMLXMLHttpRequest_get_readyState(iface
, &state
);
629 nsACString_Init(&nscstr
, NULL
);
630 nsres
= nsIXMLHttpRequest_GetAllResponseHeaders(This
->nsxhr
, &nscstr
);
631 return return_nscstr(nsres
, &nscstr
, p
);
634 static HRESULT WINAPI
HTMLXMLHttpRequest_getResponseHeader(IHTMLXMLHttpRequest
*iface
, BSTR bstrHeader
, BSTR
*p
)
636 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
637 nsACString header
, ret
;
642 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(bstrHeader
), p
);
649 hres
= IHTMLXMLHttpRequest_get_readyState(iface
, &state
);
658 cstr
= heap_strdupWtoU(bstrHeader
);
659 nsACString_InitDepend(&header
, cstr
);
660 nsACString_Init(&ret
, NULL
);
662 nsres
= nsIXMLHttpRequest_GetResponseHeader(This
->nsxhr
, &header
, &ret
);
664 nsACString_Finish(&header
);
666 return return_nscstr(nsres
, &ret
, p
);
669 static HRESULT WINAPI
HTMLXMLHttpRequest_setRequestHeader(IHTMLXMLHttpRequest
*iface
, BSTR bstrHeader
, BSTR bstrValue
)
671 HTMLXMLHttpRequest
*This
= impl_from_IHTMLXMLHttpRequest(iface
);
672 char *header_u
, *value_u
;
673 nsACString header
, value
;
676 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(bstrHeader
), debugstr_w(bstrValue
));
678 header_u
= heap_strdupWtoU(bstrHeader
);
679 if(bstrHeader
&& !header_u
)
680 return E_OUTOFMEMORY
;
682 value_u
= heap_strdupWtoU(bstrValue
);
683 if(bstrValue
&& !value_u
) {
685 return E_OUTOFMEMORY
;
688 nsACString_InitDepend(&header
, header_u
);
689 nsACString_InitDepend(&value
, value_u
);
690 nsres
= nsIXMLHttpRequest_SetRequestHeader(This
->nsxhr
, &header
, &value
);
691 nsACString_Finish(&header
);
692 nsACString_Finish(&value
);
695 if(NS_FAILED(nsres
)) {
696 ERR("SetRequestHeader failed: %08x\n", nsres
);
703 static const IHTMLXMLHttpRequestVtbl HTMLXMLHttpRequestVtbl
= {
704 HTMLXMLHttpRequest_QueryInterface
,
705 HTMLXMLHttpRequest_AddRef
,
706 HTMLXMLHttpRequest_Release
,
707 HTMLXMLHttpRequest_GetTypeInfoCount
,
708 HTMLXMLHttpRequest_GetTypeInfo
,
709 HTMLXMLHttpRequest_GetIDsOfNames
,
710 HTMLXMLHttpRequest_Invoke
,
711 HTMLXMLHttpRequest_get_readyState
,
712 HTMLXMLHttpRequest_get_responseBody
,
713 HTMLXMLHttpRequest_get_responseText
,
714 HTMLXMLHttpRequest_get_responseXML
,
715 HTMLXMLHttpRequest_get_status
,
716 HTMLXMLHttpRequest_get_statusText
,
717 HTMLXMLHttpRequest_put_onreadystatechange
,
718 HTMLXMLHttpRequest_get_onreadystatechange
,
719 HTMLXMLHttpRequest_abort
,
720 HTMLXMLHttpRequest_open
,
721 HTMLXMLHttpRequest_send
,
722 HTMLXMLHttpRequest_getAllResponseHeaders
,
723 HTMLXMLHttpRequest_getResponseHeader
,
724 HTMLXMLHttpRequest_setRequestHeader
727 static inline HTMLXMLHttpRequest
*impl_from_IProvideClassInfo2(IProvideClassInfo2
*iface
)
729 return CONTAINING_RECORD(iface
, HTMLXMLHttpRequest
, IProvideClassInfo2_iface
);
732 static HRESULT WINAPI
ProvideClassInfo_QueryInterface(IProvideClassInfo2
*iface
, REFIID riid
, void **ppv
)
734 HTMLXMLHttpRequest
*This
= impl_from_IProvideClassInfo2(iface
);
735 return IHTMLXMLHttpRequest_QueryInterface(&This
->IHTMLXMLHttpRequest_iface
, riid
, ppv
);
738 static ULONG WINAPI
ProvideClassInfo_AddRef(IProvideClassInfo2
*iface
)
740 HTMLXMLHttpRequest
*This
= impl_from_IProvideClassInfo2(iface
);
741 return IHTMLXMLHttpRequest_AddRef(&This
->IHTMLXMLHttpRequest_iface
);
744 static ULONG WINAPI
ProvideClassInfo_Release(IProvideClassInfo2
*iface
)
746 HTMLXMLHttpRequest
*This
= impl_from_IProvideClassInfo2(iface
);
747 return IHTMLXMLHttpRequest_Release(&This
->IHTMLXMLHttpRequest_iface
);
750 static HRESULT WINAPI
ProvideClassInfo_GetClassInfo(IProvideClassInfo2
*iface
, ITypeInfo
**ppTI
)
752 HTMLXMLHttpRequest
*This
= impl_from_IProvideClassInfo2(iface
);
753 TRACE("(%p)->(%p)\n", This
, ppTI
);
754 return get_class_typeinfo(&CLSID_HTMLXMLHttpRequest
, ppTI
);
757 static HRESULT WINAPI
ProvideClassInfo2_GetGUID(IProvideClassInfo2
*iface
, DWORD dwGuidKind
, GUID
*pGUID
)
759 HTMLXMLHttpRequest
*This
= impl_from_IProvideClassInfo2(iface
);
760 FIXME("(%p)->(%u %p)\n", This
, dwGuidKind
, pGUID
);
764 static const IProvideClassInfo2Vtbl ProvideClassInfo2Vtbl
= {
765 ProvideClassInfo_QueryInterface
,
766 ProvideClassInfo_AddRef
,
767 ProvideClassInfo_Release
,
768 ProvideClassInfo_GetClassInfo
,
769 ProvideClassInfo2_GetGUID
,
772 static inline HTMLXMLHttpRequest
*impl_from_DispatchEx(DispatchEx
*iface
)
774 return CONTAINING_RECORD(iface
, HTMLXMLHttpRequest
, event_target
.dispex
);
777 static HRESULT
HTMLXMLHttpRequest_get_dispid(DispatchEx
*dispex
, BSTR name
, DWORD flags
, DISPID
*dispid
)
779 /* onload event handler property is supported, but not exposed by any interface. We implement as a custom property. */
780 if(!wcscmp(L
"onload", name
)) {
781 *dispid
= MSHTML_DISPID_HTMLXMLHTTPREQUEST_ONLOAD
;
785 return DISP_E_UNKNOWNNAME
;
788 static HRESULT
HTMLXMLHttpRequest_invoke(DispatchEx
*dispex
, DISPID id
, LCID lcid
, WORD flags
, DISPPARAMS
*params
,
789 VARIANT
*res
, EXCEPINFO
*ei
, IServiceProvider
*caller
)
791 HTMLXMLHttpRequest
*This
= impl_from_DispatchEx(dispex
);
793 if(id
== MSHTML_DISPID_HTMLXMLHTTPREQUEST_ONLOAD
) {
795 case DISPATCH_PROPERTYGET
:
796 TRACE("(%p) get onload\n", This
);
797 return get_event_handler(&This
->event_target
, EVENTID_LOAD
, res
);
799 case DISPATCH_PROPERTYPUT
:
800 if(params
->cArgs
!= 1 || (params
->cNamedArgs
== 1 && *params
->rgdispidNamedArgs
!= DISPID_PROPERTYPUT
)
801 || params
->cNamedArgs
> 1) {
802 FIXME("invalid args\n");
806 TRACE("(%p)->(%p) set onload\n", This
, params
->rgvarg
);
807 return set_event_handler(&This
->event_target
, EVENTID_LOAD
, params
->rgvarg
);
810 FIXME("Unimplemented flags %x\n", flags
);
815 return DISP_E_UNKNOWNNAME
;
818 static nsISupports
*HTMLXMLHttpRequest_get_gecko_target(DispatchEx
*dispex
)
820 HTMLXMLHttpRequest
*This
= impl_from_DispatchEx(dispex
);
821 return (nsISupports
*)This
->nsxhr
;
824 static void HTMLXMLHttpRequest_bind_event(DispatchEx
*dispex
, eventid_t eid
)
826 HTMLXMLHttpRequest
*This
= impl_from_DispatchEx(dispex
);
827 nsIDOMEventTarget
*nstarget
;
828 const WCHAR
*type_name
;
832 TRACE("(%p)\n", This
);
835 case EVENTID_READYSTATECHANGE
:
836 type_name
= L
"readystatechange";
845 if(!This
->event_listener
) {
846 This
->event_listener
= heap_alloc(sizeof(*This
->event_listener
));
847 if(!This
->event_listener
)
850 This
->event_listener
->nsIDOMEventListener_iface
.lpVtbl
= &XMLHttpReqEventListenerVtbl
;
851 This
->event_listener
->ref
= 1;
852 This
->event_listener
->xhr
= This
;
853 This
->event_listener
->readystatechange_event
= FALSE
;
854 This
->event_listener
->load_event
= FALSE
;
857 nsres
= nsIXMLHttpRequest_QueryInterface(This
->nsxhr
, &IID_nsIDOMEventTarget
, (void**)&nstarget
);
858 assert(nsres
== NS_OK
);
860 nsAString_InitDepend(&type_str
, type_name
);
861 nsres
= nsIDOMEventTarget_AddEventListener(nstarget
, &type_str
, &This
->event_listener
->nsIDOMEventListener_iface
, FALSE
, TRUE
, 2);
862 nsAString_Finish(&type_str
);
864 ERR("AddEventListener(%s) failed: %08x\n", debugstr_w(type_name
), nsres
);
866 nsIDOMEventTarget_Release(nstarget
);
868 if(eid
== EVENTID_READYSTATECHANGE
)
869 This
->event_listener
->readystatechange_event
= TRUE
;
871 This
->event_listener
->load_event
= TRUE
;
874 static void HTMLXMLHttpRequest_init_dispex_info(dispex_data_t
*info
, compat_mode_t compat_mode
)
876 static const dispex_hook_t xhr_hooks
[] = {
877 {DISPID_IHTMLXMLHTTPREQUEST_OPEN
, HTMLXMLHttpRequest_open_hook
},
881 EventTarget_init_dispex_info(info
, compat_mode
);
882 dispex_info_add_interface(info
, IHTMLXMLHttpRequest_tid
, compat_mode
>= COMPAT_MODE_IE10
? xhr_hooks
: NULL
);
885 static event_target_vtbl_t HTMLXMLHttpRequest_event_target_vtbl
= {
888 HTMLXMLHttpRequest_get_dispid
,
889 HTMLXMLHttpRequest_invoke
891 HTMLXMLHttpRequest_get_gecko_target
,
892 HTMLXMLHttpRequest_bind_event
895 static const tid_t HTMLXMLHttpRequest_iface_tids
[] = {
898 static dispex_static_data_t HTMLXMLHttpRequest_dispex
= {
899 &HTMLXMLHttpRequest_event_target_vtbl
.dispex_vtbl
,
900 DispHTMLXMLHttpRequest_tid
,
901 HTMLXMLHttpRequest_iface_tids
,
902 HTMLXMLHttpRequest_init_dispex_info
906 /* IHTMLXMLHttpRequestFactory */
907 static inline HTMLXMLHttpRequestFactory
*impl_from_IHTMLXMLHttpRequestFactory(IHTMLXMLHttpRequestFactory
*iface
)
909 return CONTAINING_RECORD(iface
, HTMLXMLHttpRequestFactory
, IHTMLXMLHttpRequestFactory_iface
);
912 static HRESULT WINAPI
HTMLXMLHttpRequestFactory_QueryInterface(IHTMLXMLHttpRequestFactory
*iface
, REFIID riid
, void **ppv
)
914 HTMLXMLHttpRequestFactory
*This
= impl_from_IHTMLXMLHttpRequestFactory(iface
);
916 TRACE("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
918 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
919 *ppv
= &This
->IHTMLXMLHttpRequestFactory_iface
;
920 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
921 *ppv
= &This
->IHTMLXMLHttpRequestFactory_iface
;
922 }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequestFactory
, riid
)) {
923 *ppv
= &This
->IHTMLXMLHttpRequestFactory_iface
;
924 }else if(dispex_query_interface(&This
->dispex
, riid
, ppv
)) {
925 return *ppv
? S_OK
: E_NOINTERFACE
;
928 WARN("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
929 return E_NOINTERFACE
;
932 IUnknown_AddRef((IUnknown
*)*ppv
);
936 static ULONG WINAPI
HTMLXMLHttpRequestFactory_AddRef(IHTMLXMLHttpRequestFactory
*iface
)
938 HTMLXMLHttpRequestFactory
*This
= impl_from_IHTMLXMLHttpRequestFactory(iface
);
939 LONG ref
= InterlockedIncrement(&This
->ref
);
941 TRACE("(%p) ref=%d\n", This
, ref
);
946 static ULONG WINAPI
HTMLXMLHttpRequestFactory_Release(IHTMLXMLHttpRequestFactory
*iface
)
948 HTMLXMLHttpRequestFactory
*This
= impl_from_IHTMLXMLHttpRequestFactory(iface
);
949 LONG ref
= InterlockedDecrement(&This
->ref
);
951 TRACE("(%p) ref=%d\n", This
, ref
);
954 release_dispex(&This
->dispex
);
961 static HRESULT WINAPI
HTMLXMLHttpRequestFactory_GetTypeInfoCount(IHTMLXMLHttpRequestFactory
*iface
, UINT
*pctinfo
)
963 HTMLXMLHttpRequestFactory
*This
= impl_from_IHTMLXMLHttpRequestFactory(iface
);
964 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
967 static HRESULT WINAPI
HTMLXMLHttpRequestFactory_GetTypeInfo(IHTMLXMLHttpRequestFactory
*iface
, UINT iTInfo
,
968 LCID lcid
, ITypeInfo
**ppTInfo
)
970 HTMLXMLHttpRequestFactory
*This
= impl_from_IHTMLXMLHttpRequestFactory(iface
);
972 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
975 static HRESULT WINAPI
HTMLXMLHttpRequestFactory_GetIDsOfNames(IHTMLXMLHttpRequestFactory
*iface
, REFIID riid
, LPOLESTR
*rgszNames
, UINT cNames
,
976 LCID lcid
, DISPID
*rgDispId
)
978 HTMLXMLHttpRequestFactory
*This
= impl_from_IHTMLXMLHttpRequestFactory(iface
);
980 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
, riid
, rgszNames
, cNames
,
984 static HRESULT WINAPI
HTMLXMLHttpRequestFactory_Invoke(IHTMLXMLHttpRequestFactory
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
985 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
987 HTMLXMLHttpRequestFactory
*This
= impl_from_IHTMLXMLHttpRequestFactory(iface
);
989 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
, dispIdMember
, riid
, lcid
, wFlags
,
990 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
993 static HRESULT WINAPI
HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactory
*iface
, IHTMLXMLHttpRequest
**p
)
995 HTMLXMLHttpRequestFactory
*This
= impl_from_IHTMLXMLHttpRequestFactory(iface
);
996 HTMLXMLHttpRequest
*ret
;
997 nsIXMLHttpRequest
*nsxhr
;
999 TRACE("(%p)->(%p)\n", This
, p
);
1001 nsxhr
= create_nsxhr(This
->window
->base
.outer_window
->nswindow
);
1005 ret
= heap_alloc_zero(sizeof(*ret
));
1007 nsIXMLHttpRequest_Release(nsxhr
);
1008 return E_OUTOFMEMORY
;
1012 ret
->IHTMLXMLHttpRequest_iface
.lpVtbl
= &HTMLXMLHttpRequestVtbl
;
1013 ret
->IProvideClassInfo2_iface
.lpVtbl
= &ProvideClassInfo2Vtbl
;
1014 EventTarget_Init(&ret
->event_target
, (IUnknown
*)&ret
->IHTMLXMLHttpRequest_iface
,
1015 &HTMLXMLHttpRequest_dispex
, This
->window
->doc
->document_mode
);
1018 *p
= &ret
->IHTMLXMLHttpRequest_iface
;
1022 static const IHTMLXMLHttpRequestFactoryVtbl HTMLXMLHttpRequestFactoryVtbl
= {
1023 HTMLXMLHttpRequestFactory_QueryInterface
,
1024 HTMLXMLHttpRequestFactory_AddRef
,
1025 HTMLXMLHttpRequestFactory_Release
,
1026 HTMLXMLHttpRequestFactory_GetTypeInfoCount
,
1027 HTMLXMLHttpRequestFactory_GetTypeInfo
,
1028 HTMLXMLHttpRequestFactory_GetIDsOfNames
,
1029 HTMLXMLHttpRequestFactory_Invoke
,
1030 HTMLXMLHttpRequestFactory_create
1033 static inline HTMLXMLHttpRequestFactory
*factory_from_DispatchEx(DispatchEx
*iface
)
1035 return CONTAINING_RECORD(iface
, HTMLXMLHttpRequestFactory
, dispex
);
1038 static HRESULT
HTMLXMLHttpRequestFactory_value(DispatchEx
*iface
, LCID lcid
, WORD flags
, DISPPARAMS
*params
,
1039 VARIANT
*res
, EXCEPINFO
*ei
, IServiceProvider
*caller
)
1041 HTMLXMLHttpRequestFactory
*This
= factory_from_DispatchEx(iface
);
1042 IHTMLXMLHttpRequest
*xhr
;
1047 if(flags
!= DISPATCH_CONSTRUCT
) {
1048 FIXME("flags %x not supported\n", flags
);
1052 hres
= IHTMLXMLHttpRequestFactory_create(&This
->IHTMLXMLHttpRequestFactory_iface
, &xhr
);
1056 V_VT(res
) = VT_DISPATCH
;
1057 V_DISPATCH(res
) = (IDispatch
*)xhr
;
1061 static const dispex_static_data_vtbl_t HTMLXMLHttpRequestFactory_dispex_vtbl
= {
1062 HTMLXMLHttpRequestFactory_value
1065 static const tid_t HTMLXMLHttpRequestFactory_iface_tids
[] = {
1066 IHTMLXMLHttpRequestFactory_tid
,
1069 static dispex_static_data_t HTMLXMLHttpRequestFactory_dispex
= {
1070 &HTMLXMLHttpRequestFactory_dispex_vtbl
,
1071 IHTMLXMLHttpRequestFactory_tid
,
1072 HTMLXMLHttpRequestFactory_iface_tids
1075 HRESULT
HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow
* window
, HTMLXMLHttpRequestFactory
**ret_ptr
)
1077 HTMLXMLHttpRequestFactory
*ret
;
1079 ret
= heap_alloc(sizeof(*ret
));
1081 return E_OUTOFMEMORY
;
1083 ret
->IHTMLXMLHttpRequestFactory_iface
.lpVtbl
= &HTMLXMLHttpRequestFactoryVtbl
;
1085 ret
->window
= window
;
1087 init_dispatch(&ret
->dispex
, (IUnknown
*)&ret
->IHTMLXMLHttpRequestFactory_iface
,
1088 &HTMLXMLHttpRequestFactory_dispex
, dispex_compat_mode(&window
->event_target
.dispex
));