Commit b90c5379 authored by Gabriel Ivăncescu's avatar Gabriel Ivăncescu Committed by Alexandre Julliard

mshtml: Implement ontimeout event for XMLHttpRequest.

parent 519ef7c5
......@@ -67,6 +67,7 @@ typedef enum {
EVENT_TYPE_FOCUS,
EVENT_TYPE_DRAG,
EVENT_TYPE_MESSAGE,
EVENT_TYPE_PROGRESS,
EVENT_TYPE_CLIPBOARD
} event_type_t;
......@@ -78,6 +79,7 @@ static const WCHAR *event_types[] = {
L"Event", /* FIXME */
L"Event", /* FIXME */
L"Event", /* FIXME */
L"ProgressEvent",
L"Event" /* FIXME */
};
......@@ -185,6 +187,8 @@ static const event_info_t event_info[] = {
EVENT_FIXME | EVENT_BUBBLES | EVENT_CANCELABLE},
{L"submit", EVENT_TYPE_EVENT, DISPID_EVMETH_ONSUBMIT,
EVENT_DEFAULTLISTENER | EVENT_HASDEFAULTHANDLERS | EVENT_BUBBLES | EVENT_CANCELABLE},
{L"timeout", EVENT_TYPE_PROGRESS, DISPID_EVPROP_TIMEOUT,
EVENT_BIND_TO_TARGET},
{L"unload", EVENT_TYPE_UIEVENT, DISPID_EVMETH_ONUNLOAD,
EVENT_FIXME}
};
......@@ -2286,6 +2290,122 @@ static void DOMMessageEvent_destroy(DOMEvent *event)
heap_free(message_event->data);
}
typedef struct {
DOMEvent event;
IDOMProgressEvent IDOMProgressEvent_iface;
} DOMProgressEvent;
static inline DOMProgressEvent *impl_from_IDOMProgressEvent(IDOMProgressEvent *iface)
{
return CONTAINING_RECORD(iface, DOMProgressEvent, IDOMProgressEvent_iface);
}
static HRESULT WINAPI DOMProgressEvent_QueryInterface(IDOMProgressEvent *iface, REFIID riid, void **ppv)
{
DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
}
static ULONG WINAPI DOMProgressEvent_AddRef(IDOMProgressEvent *iface)
{
DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
}
static ULONG WINAPI DOMProgressEvent_Release(IDOMProgressEvent *iface)
{
DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
return IDOMEvent_Release(&This->event.IDOMEvent_iface);
}
static HRESULT WINAPI DOMProgressEvent_GetTypeInfoCount(IDOMProgressEvent *iface, UINT *pctinfo)
{
DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
}
static HRESULT WINAPI DOMProgressEvent_GetTypeInfo(IDOMProgressEvent *iface, UINT iTInfo,
LCID lcid, ITypeInfo **ppTInfo)
{
DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
}
static HRESULT WINAPI DOMProgressEvent_GetIDsOfNames(IDOMProgressEvent *iface, REFIID riid,
LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
{
DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
lcid, rgDispId);
}
static HRESULT WINAPI DOMProgressEvent_Invoke(IDOMProgressEvent *iface, DISPID dispIdMember,
REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
}
static HRESULT WINAPI DOMProgressEvent_get_lengthComputable(IDOMProgressEvent *iface, VARIANT_BOOL *p)
{
DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
FIXME("(%p)->(%p)\n", This, p);
return E_NOTIMPL;
}
static HRESULT WINAPI DOMProgressEvent_get_loaded(IDOMProgressEvent *iface, ULONGLONG *p)
{
DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
FIXME("(%p)->(%p)\n", This, p);
return E_NOTIMPL;
}
static HRESULT WINAPI DOMProgressEvent_get_total(IDOMProgressEvent *iface, ULONGLONG *p)
{
DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
FIXME("(%p)->(%p)\n", This, p);
return E_NOTIMPL;
}
static HRESULT WINAPI DOMProgressEvent_initProgressEvent(IDOMProgressEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
VARIANT_BOOL cancelable, VARIANT_BOOL lengthComputable,
ULONGLONG loaded, ULONGLONG total)
{
DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
FIXME("(%p)->(%s %x %x %x %s %s)\n", This, debugstr_w(type), can_bubble, cancelable, lengthComputable,
wine_dbgstr_longlong(loaded), wine_dbgstr_longlong(total));
return E_NOTIMPL;
}
static const IDOMProgressEventVtbl DOMProgressEventVtbl = {
DOMProgressEvent_QueryInterface,
DOMProgressEvent_AddRef,
DOMProgressEvent_Release,
DOMProgressEvent_GetTypeInfoCount,
DOMProgressEvent_GetTypeInfo,
DOMProgressEvent_GetIDsOfNames,
DOMProgressEvent_Invoke,
DOMProgressEvent_get_lengthComputable,
DOMProgressEvent_get_loaded,
DOMProgressEvent_get_total,
DOMProgressEvent_initProgressEvent
};
static DOMProgressEvent *DOMProgressEvent_from_DOMEvent(DOMEvent *event)
{
return CONTAINING_RECORD(event, DOMProgressEvent, event);
}
static void *DOMProgressEvent_query_interface(DOMEvent *event, REFIID riid)
{
DOMProgressEvent *This = DOMProgressEvent_from_DOMEvent(event);
if(IsEqualGUID(&IID_IDOMProgressEvent, riid))
return &This->IDOMProgressEvent_iface;
return NULL;
}
static const tid_t DOMEvent_iface_tids[] = {
IDOMEvent_tid,
0
......@@ -2365,6 +2485,19 @@ dispex_static_data_t DOMMessageEvent_dispex = {
DOMMessageEvent_iface_tids
};
static const tid_t DOMProgressEvent_iface_tids[] = {
IDOMEvent_tid,
IDOMProgressEvent_tid,
0
};
dispex_static_data_t DOMProgressEvent_dispex = {
L"ProgressEvent",
NULL,
DispDOMProgressEvent_tid,
DOMProgressEvent_iface_tids
};
static BOOL check_event_iface(nsIDOMEvent *event, REFIID riid)
{
nsISupports *iface;
......@@ -2404,6 +2537,15 @@ static DOMEvent *alloc_event(nsIDOMEvent *nsevent, compat_mode_t compat_mode, ev
message_event->event.destroy = DOMMessageEvent_destroy;
event = &message_event->event;
dispex_data = &DOMMessageEvent_dispex;
}else if(event_info[event_id].type == EVENT_TYPE_PROGRESS && compat_mode >= COMPAT_MODE_IE10) {
DOMProgressEvent *progress_event = heap_alloc_zero(sizeof(*progress_event));
if(!progress_event)
return NULL;
progress_event->IDOMProgressEvent_iface.lpVtbl = &DOMProgressEventVtbl;
progress_event->event.query_interface = DOMProgressEvent_query_interface;
event = &progress_event->event;
dispex_data = &DOMProgressEvent_dispex;
}else {
event = heap_alloc_zero(sizeof(*event));
if(!event)
......
......@@ -56,6 +56,7 @@ typedef enum {
EVENTID_SELECTIONCHANGE,
EVENTID_SELECTSTART,
EVENTID_SUBMIT,
EVENTID_TIMEOUT,
EVENTID_UNLOAD,
EVENTID_LAST
} eventid_t;
......
......@@ -89,6 +89,7 @@ typedef struct EventTarget EventTarget;
XDIID(DispDOMKeyboardEvent) \
XDIID(DispDOMMessageEvent) \
XDIID(DispDOMMouseEvent) \
XDIID(DispDOMProgressEvent) \
XDIID(DispDOMUIEvent) \
XDIID(DispHTMLAnchorElement) \
XDIID(DispHTMLAreaElement) \
......@@ -150,6 +151,7 @@ typedef struct EventTarget EventTarget;
XIID(IDOMKeyboardEvent) \
XIID(IDOMMessageEvent) \
XIID(IDOMMouseEvent) \
XIID(IDOMProgressEvent) \
XIID(IDOMUIEvent) \
XIID(IDocumentEvent) \
XIID(IDocumentRange) \
......
......@@ -3046,11 +3046,23 @@ typedef struct {
IStream *stream;
char *data;
ULONG size;
LONG delay;
char *ptr;
IUri *uri;
} ProtocolHandler;
static DWORD WINAPI delay_proc(void *arg)
{
PROTOCOLDATA protocol_data = {PI_FORCE_ASYNC};
ProtocolHandler *protocol_handler = arg;
Sleep(protocol_handler->delay);
protocol_handler->delay = -1;
IInternetProtocolSink_Switch(protocol_handler->sink, &protocol_data);
return 0;
}
static void report_data(ProtocolHandler *This)
{
IServiceProvider *service_provider;
......@@ -3061,27 +3073,36 @@ static void report_data(ProtocolHandler *This)
static const WCHAR emptyW[] = {0};
hres = IInternetProtocolSink_QueryInterface(This->sink, &IID_IServiceProvider, (void**)&service_provider);
ok(hres == S_OK, "Could not get IServiceProvider iface: %08lx\n", hres);
if(This->delay >= 0) {
hres = IInternetProtocolSink_QueryInterface(This->sink, &IID_IServiceProvider, (void**)&service_provider);
ok(hres == S_OK, "Could not get IServiceProvider iface: %08lx\n", hres);
hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate, &IID_IHttpNegotiate, (void**)&http_negotiate);
IServiceProvider_Release(service_provider);
ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08lx\n", hres);
hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate, &IID_IHttpNegotiate, (void**)&http_negotiate);
IServiceProvider_Release(service_provider);
ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08lx\n", hres);
hres = IUri_GetDisplayUri(This->uri, &url);
ok(hres == S_OK, "Failed to get display uri: %08lx\n", hres);
hres = IHttpNegotiate_BeginningTransaction(http_negotiate, url, emptyW, 0, &addl_headers);
ok(hres == S_OK, "BeginningTransaction failed: %08lx\n", hres);
SysFreeString(url);
hres = IUri_GetDisplayUri(This->uri, &url);
ok(hres == S_OK, "Failed to get display uri: %08lx\n", hres);
hres = IHttpNegotiate_BeginningTransaction(http_negotiate, url, emptyW, 0, &addl_headers);
ok(hres == S_OK, "BeginningTransaction failed: %08lx\n", hres);
SysFreeString(url);
CoTaskMemFree(addl_headers);
CoTaskMemFree(addl_headers);
headers = SysAllocString(L"HTTP/1.1 200 OK\r\n\r\n");
hres = IHttpNegotiate_OnResponse(http_negotiate, 200, headers, NULL, NULL);
ok(hres == S_OK, "OnResponse failed: %08lx\n", hres);
SysFreeString(headers);
headers = SysAllocString(L"HTTP/1.1 200 OK\r\n\r\n");
hres = IHttpNegotiate_OnResponse(http_negotiate, 200, headers, NULL, NULL);
ok(hres == S_OK, "OnResponse failed: %08lx\n", hres);
SysFreeString(headers);
IHttpNegotiate_Release(http_negotiate);
IHttpNegotiate_Release(http_negotiate);
if(This->delay) {
IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
QueueUserWorkItem(delay_proc, This, 0);
return;
}
}
This->delay = 0;
hres = IInternetProtocolSink_ReportData(This->sink, BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION,
This->size, This->size);
......@@ -3250,6 +3271,12 @@ static HRESULT WINAPI Protocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA
static HRESULT WINAPI Protocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason, DWORD dwOptions)
{
ProtocolHandler *This = impl_from_IInternetProtocolEx(iface);
if(This->delay > 0) {
ok(hrReason == E_ABORT, "Abort hrReason = %08lx\n", hrReason);
ok(dwOptions == 0, "Abort dwOptions = %lx\n", dwOptions);
return S_OK;
}
trace("Abort(%08lx %lx)\n", hrReason, dwOptions);
return E_NOTIMPL;
}
......@@ -3322,8 +3349,8 @@ static HRESULT WINAPI ProtocolEx_StartEx(IInternetProtocolEx *iface, IUri *uri,
{
ProtocolHandler *This = impl_from_IInternetProtocolEx(iface);
BOOL block = FALSE;
BSTR path, query;
DWORD bindf;
BSTR path;
HRSRC src;
HRESULT hres;
......@@ -3391,6 +3418,13 @@ static HRESULT WINAPI ProtocolEx_StartEx(IInternetProtocolEx *iface, IUri *uri,
if(FAILED(hres))
return hres;
hres = IUri_GetQuery(uri, &query);
if(SUCCEEDED(hres)) {
if(!lstrcmpW(query, L"?delay"))
This->delay = 1000;
SysFreeString(query);
}
IInternetProtocolSink_AddRef(This->sink = pOIProtSink);
IUri_AddRef(This->uri = uri);
......@@ -3723,6 +3757,7 @@ static void run_js_tests(void)
init_protocol_handler();
run_script_as_http_with_mode("xhr.js", NULL, "9");
run_script_as_http_with_mode("xhr.js", NULL, "10");
run_script_as_http_with_mode("xhr.js", NULL, "11");
run_script_as_http_with_mode("dom.js", NULL, "11");
run_script_as_http_with_mode("es5.js", NULL, "11");
......
......@@ -28,6 +28,7 @@ function test_xhr() {
if(complete_cnt++)
next_test();
}
xhr.ontimeout = function() { ok(false, "ontimeout called"); }
var onload_func = xhr.onload = function() {
ok(xhr.statusText === "OK", "statusText = " + xhr.statusText);
if(complete_cnt++)
......@@ -40,6 +41,38 @@ function test_xhr() {
xhr.send("Testing...");
}
function test_timeout() {
var xhr = new XMLHttpRequest();
var v = document.documentMode;
xhr.onreadystatechange = function() {
if(xhr.readyState != 4)
return;
todo_wine_if(v < 10).
ok(v >= 10, "onreadystatechange called");
}
xhr.onload = function() { ok(false, "onload called"); }
xhr.ontimeout = function(e) {
var r = Object.prototype.toString.call(e);
todo_wine.
ok(r === ("[object " + (v < 10 ? "Event" : "ProgressEvent") + "]"), "Object.toString = " + r);
var props = [ "initProgressEvent", "lengthComputable", "loaded", "total" ];
for(r = 0; r < props.length; r++) {
if(v < 10)
ok(!(props[r] in e), props[r] + " is available");
else
ok(props[r] in e, props[r] + " not available");
}
next_test();
}
xhr.open("POST", "echo.php?delay", true);
xhr.setRequestHeader("X-Test", "True");
xhr.timeout = 10;
xhr.send("Timeout Test");
}
var tests = [
test_xhr
test_xhr,
test_timeout
];
......@@ -97,6 +97,7 @@ static HRESULT return_nscstr(nsresult nsres, nsACString *nscstr, BSTR *p)
static const eventid_t events[] = {
EVENTID_READYSTATECHANGE,
EVENTID_LOAD,
EVENTID_TIMEOUT,
};
typedef struct {
......@@ -812,18 +813,18 @@ static HRESULT WINAPI HTMLXMLHttpRequest2_put_ontimeout(IHTMLXMLHttpRequest2 *if
{
HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest2(iface);
FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
return E_NOTIMPL;
return set_event_handler(&This->event_target, EVENTID_TIMEOUT, &v);
}
static HRESULT WINAPI HTMLXMLHttpRequest2_get_ontimeout(IHTMLXMLHttpRequest2 *iface, VARIANT *p)
{
HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest2(iface);
FIXME("(%p)->(%p)\n", This, p);
TRACE("(%p)->(%p)\n", This, p);
return E_NOTIMPL;
return get_event_handler(&This->event_target, EVENTID_TIMEOUT, p);
}
static const IHTMLXMLHttpRequest2Vtbl HTMLXMLHttpRequest2Vtbl = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment