Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
Needed by 3rd patch.
dlls/mshtml/navigate.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index e6f2035..5d74cc1 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -708,12 +708,26 @@ HRESULT read_stream(BSCallback *This, IStream *stream, void *buf, DWORD size, DW
static void parse_content_type(nsChannelBSC *This, const WCHAR *value) { - const WCHAR *ptr; - size_t len; + const WCHAR *ptr, *beg, *end; + size_t len = wcslen(value); + char *content_type;
static const WCHAR charsetW[] = {'c','h','a','r','s','e','t','='};
ptr = wcschr(value, ';'); + for(end = ptr ? ptr : value + len; end > value; end--) + if(!iswspace(end[-1])) + break; + for(beg = value; beg < end; beg++) + if(!iswspace(*beg)) + break; + + if((content_type = heap_strndupWtoU(beg, end - beg))) { + heap_free(This->nschannel->content_type); + This->nschannel->content_type = content_type; + strlwr(content_type); + } + if(!ptr) return;
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
Needed by next patch.
dlls/mshtml/navigate.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 5d74cc1..94ad0ea 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1668,10 +1668,9 @@ static HRESULT nsChannelBSC_on_progress(BSCallback *bsc, ULONG status_code, LPCW This->nschannel = NULL; }
- if(!This->nschannel) + if(!This->nschannel || This->nschannel->content_type) return S_OK;
- heap_free(This->nschannel->content_type); This->nschannel->content_type = heap_strdupWtoA(status_text); break; case BINDSTATUS_REDIRECTING:
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/tests/script.c | 10 ++++++- dlls/mshtml/tests/xhr.js | 57 ++++++++++++++++++++++++++++++++++-- dlls/mshtml/xmlhttprequest.c | 14 +++++++++ 3 files changed, 78 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/tests/script.c b/dlls/mshtml/tests/script.c index e368824..efd161d 100644 --- a/dlls/mshtml/tests/script.c +++ b/dlls/mshtml/tests/script.c @@ -3043,6 +3043,7 @@ typedef struct { IInternetProtocolSink *sink; BINDINFO bind_info;
+ BSTR content_type; IStream *stream; char *data; ULONG size; @@ -3068,6 +3069,7 @@ static void report_data(ProtocolHandler *This) IServiceProvider *service_provider; IHttpNegotiate *http_negotiate; WCHAR *addl_headers = NULL; + WCHAR headers_buf[128]; BSTR headers, url; HRESULT hres;
@@ -3091,7 +3093,10 @@ static void report_data(ProtocolHandler *This)
CoTaskMemFree(addl_headers);
- headers = SysAllocString(L"HTTP/1.1 200 OK\r\n\r\n"); + if(This->content_type) + swprintf(headers_buf, ARRAY_SIZE(headers_buf), L"HTTP/1.1 200 OK\r\nContent-Type: %s\r\n", This->content_type); + + headers = SysAllocString(This->content_type ? headers_buf : 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); @@ -3250,6 +3255,7 @@ static ULONG WINAPI Protocol_Release(IInternetProtocolEx *iface) if(This->uri) IUri_Release(This->uri); ReleaseBindInfo(&This->bind_info); + SysFreeString(This->content_type); HeapFree(GetProcessHeap(), 0, This); }
@@ -3424,6 +3430,8 @@ static HRESULT WINAPI ProtocolEx_StartEx(IInternetProtocolEx *iface, IUri *uri, if(SUCCEEDED(hres)) { if(!lstrcmpW(query, L"?delay")) This->delay = 1000; + else if(!wcsncmp(query, L"?content-type=", sizeof("?content-type=")-1)) + This->content_type = SysAllocString(query + sizeof("?content-type=")-1); SysFreeString(query); }
diff --git a/dlls/mshtml/tests/xhr.js b/dlls/mshtml/tests/xhr.js index c450384..303c4ad 100644 --- a/dlls/mshtml/tests/xhr.js +++ b/dlls/mshtml/tests/xhr.js @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+var xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<a name="test">wine</a>"; + function test_xhr() { var xhr = new XMLHttpRequest(); var complete_cnt = 0, loadstart = false; @@ -24,7 +26,9 @@ function test_xhr() { if(xhr.readyState != 4) return;
- ok(xhr.responseText === "Testing...", "unexpected responseText " + xhr.responseText); + ok(xhr.responseText === xml, "unexpected responseText " + xhr.responseText); + ok(xhr.responseXML !== null, "unexpected null responseXML"); + if(complete_cnt++ && !("onloadend" in xhr)) next_test(); } @@ -63,7 +67,55 @@ function test_xhr() { ok(xhr.withCredentials === true, "withCredentials = " + xhr.withCredentials); xhr.withCredentials = false; } - xhr.send("Testing..."); + xhr.send(xml); +} + +function test_content_types() { + var xhr = new XMLHttpRequest(), types, i = 0; + var v = document.documentMode; + + var types = [ + "", + "text/plain", + "text/html", + "wine/xml", + "xml" + ]; + var xml_types = [ + "text/xmL", + "apPliCation/xml", + "image/SvG+xml", + "Wine/Test+xml", + "++Xml", + "+xMl" + ]; + + function onload() { + ok(xhr.responseText === xml, "unexpected responseText " + xhr.responseText); + if(v < 10 || types === xml_types) + ok(xhr.responseXML !== null, "unexpected null responseXML for " + types[i]); + else + ok(xhr.responseXML === null, "unexpected non-null responseXML for " + types[i]); + + if(++i >= types.length) { + if(types === xml_types) { + next_test(); + return; + } + types = xml_types; + i = 0; + } + xhr = new XMLHttpRequest(); + xhr.onload = onload; + xhr.open("POST", "echo.php?content-type=" + types[i], true); + xhr.setRequestHeader("X-Test", "True"); + xhr.send(xml); + } + + xhr.onload = onload; + xhr.open("POST", "echo.php?content-type=" + types[i], true); + xhr.setRequestHeader("X-Test", "True"); + xhr.send(xml); }
function test_abort() { @@ -118,6 +170,7 @@ function test_timeout() {
var tests = [ test_xhr, + test_content_types, test_abort, test_timeout ]; diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index 8fa91e9..c165218 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -374,6 +374,20 @@ static HRESULT WINAPI HTMLXMLHttpRequest_get_responseXML(IHTMLXMLHttpRequest *if
TRACE("(%p)->(%p)\n", This, p);
+ if(dispex_compat_mode(&This->event_target.dispex) >= COMPAT_MODE_IE10) { + nsIDOMDocument *nsdoc; + nsresult nsres; + + nsres = nsIXMLHttpRequest_GetResponseXML(This->nsxhr, &nsdoc); + if(NS_FAILED(nsres)) + return map_nsresult(nsres); + if(!nsdoc) { + *p = NULL; + return S_OK; + } + nsIDOMDocument_Release(nsdoc); + } + hres = CoCreateInstance(&CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&xmldoc); if(FAILED(hres)) { ERR("CoCreateInstance failed: %08lx\n", hres);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=116488
Your paranoid android.
=== w10pro64 (32 bit report) ===
mshtml: htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS
=== w10pro64 (64 bit report) ===
mshtml: script.c:3119: Test failed: ReportResult failed: 80ef0001
=== w10pro64_ja (64 bit report) ===
mshtml: script.c:3119: Test failed: ReportResult failed: 80ef0001
We have to special case empty string since Gecko special cases them, but IE does not.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/tests/xhr.js | 16 ++++++++++++++-- dlls/mshtml/xmlhttprequest.c | 23 +++++++++++++++++++++-- 2 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/dlls/mshtml/tests/xhr.js b/dlls/mshtml/tests/xhr.js index 303c4ad..8d9af26 100644 --- a/dlls/mshtml/tests/xhr.js +++ b/dlls/mshtml/tests/xhr.js @@ -71,7 +71,7 @@ function test_xhr() { }
function test_content_types() { - var xhr = new XMLHttpRequest(), types, i = 0; + var xhr = new XMLHttpRequest(), types, i = 0, override = false; var v = document.documentMode;
var types = [ @@ -95,7 +95,19 @@ function test_content_types() { if(v < 10 || types === xml_types) ok(xhr.responseXML !== null, "unexpected null responseXML for " + types[i]); else - ok(xhr.responseXML === null, "unexpected non-null responseXML for " + types[i]); + ok(xhr.responseXML === null, "unexpected non-null responseXML for " + (override ? "overriden " : "") + types[i]); + + if(("overrideMimeType" in xhr) && !override) { + override = true; + xhr = new XMLHttpRequest(); + xhr.onload = onload; + xhr.open("POST", "echo.php", true); + xhr.setRequestHeader("X-Test", "True"); + xhr.overrideMimeType(types[i]); + xhr.send(xml); + return; + } + override = false;
if(++i >= types.length) { if(types === xml_types) { diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index c165218..f21114a 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -978,10 +978,29 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_get_withCredentials(IWineXMLHtt static HRESULT WINAPI HTMLXMLHttpRequest_private_overrideMimeType(IWineXMLHttpRequestPrivate *iface, BSTR mimeType) { HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface); + static const WCHAR generic_type[] = L"application/octet-stream"; + const WCHAR *type = NULL; + WCHAR *lowercase = NULL; + nsAString nsstr; + nsresult nsres;
- FIXME("(%p)->(%s)\n", This, debugstr_w(mimeType)); + TRACE("(%p)->(%s)\n", This, debugstr_w(mimeType));
- return E_NOTIMPL; + if(mimeType) { + if(mimeType[0]) { + if(!(lowercase = heap_strdupW(mimeType))) + return E_OUTOFMEMORY; + _wcslwr(lowercase); + type = lowercase; + }else + type = generic_type; + } + + nsAString_InitDepend(&nsstr, type); + nsres = nsIXMLHttpRequest_SlowOverrideMimeType(This->nsxhr, &nsstr); + nsAString_Finish(&nsstr); + heap_free(lowercase); + return map_nsresult(nsres); }
static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onerror(IWineXMLHttpRequestPrivate *iface, VARIANT v)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=116489
Your paranoid android.
=== w10pro64_ar (64 bit report) ===
mshtml: htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS
Rather than hacking a custom prop.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private_iface.idl | 20 +++++-- dlls/mshtml/xmlhttprequest.c | 86 ++++++++++++---------------- 2 files changed, 51 insertions(+), 55 deletions(-)
diff --git a/dlls/mshtml/mshtml_private_iface.idl b/dlls/mshtml/mshtml_private_iface.idl index 972f9b3..8e9e386 100644 --- a/dlls/mshtml/mshtml_private_iface.idl +++ b/dlls/mshtml/mshtml_private_iface.idl @@ -139,6 +139,10 @@ interface IWineDOMTokenList : IDispatch HRESULT toString([retval, out] BSTR *String); }
+const long DISPID_IWINEXMLHTTPREQUESTPRIVATE_RESPONSE = 1; +const long DISPID_IWINEXMLHTTPREQUESTPRIVATE_RESPONSETYPE = 2; +const long DISPID_IWINEXMLHTTPREQUESTPRIVATE_UPLOAD = 3; +const long DISPID_IWINEXMLHTTPREQUESTPRIVATE_WITHCREDENTIALS = 4; const long DISPID_IWINEXMLHTTPREQUESTPRIVATE_OVERRIDEMIMETYPE = 5; [ odl, @@ -149,17 +153,17 @@ const long DISPID_IWINEXMLHTTPREQUESTPRIVATE_OVERRIDEMIMETYPE = 5; ] interface IWineXMLHttpRequestPrivate : IDispatch { - [propget, id(1)] + [propget, id(DISPID_IWINEXMLHTTPREQUESTPRIVATE_RESPONSE)] HRESULT response([retval, out] VARIANT *p); - [propput, id(2)] + [propput, id(DISPID_IWINEXMLHTTPREQUESTPRIVATE_RESPONSETYPE)] HRESULT responseType([in] BSTR v); - [propget, id(2)] + [propget, id(DISPID_IWINEXMLHTTPREQUESTPRIVATE_RESPONSETYPE)] HRESULT responseType([retval, out] BSTR *p); - [propget, id(3)] + [propget, id(DISPID_IWINEXMLHTTPREQUESTPRIVATE_UPLOAD)] HRESULT upload([retval, out] IDispatch **p); - [propput, id(4)] + [propput, id(DISPID_IWINEXMLHTTPREQUESTPRIVATE_WITHCREDENTIALS)] HRESULT withCredentials([in] VARIANT_BOOL v); - [propget, id(4)] + [propget, id(DISPID_IWINEXMLHTTPREQUESTPRIVATE_WITHCREDENTIALS)] HRESULT withCredentials([retval, out] VARIANT_BOOL *p); [id(DISPID_IWINEXMLHTTPREQUESTPRIVATE_OVERRIDEMIMETYPE)] HRESULT overrideMimeType([in] BSTR mimeType); @@ -183,6 +187,10 @@ interface IWineXMLHttpRequestPrivate : IDispatch HRESULT onloadend([in] VARIANT v); [propget, id(DISPID_EVPROP_LOADEND)] HRESULT onloadend([retval, out] VARIANT *p); + [propput, id(DISPID_EVPROP_ONLOAD)] + HRESULT onload([in] VARIANT v); + [propget, id(DISPID_EVPROP_ONLOAD)] + HRESULT onload([retval, out] VARIANT *p); }
} /* library MSHTML_private */ diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index f21114a..b17fa41 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -36,8 +36,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
-#define MSHTML_DISPID_HTMLXMLHTTPREQUEST_ONLOAD MSHTML_DISPID_CUSTOM_MIN - static HRESULT bstr_to_nsacstr(BSTR bstr, nsACString *str) { char *cstr = heap_strdupWtoU(bstr); @@ -1093,6 +1091,24 @@ static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onloadend(IWineXMLHttpReque return get_event_handler(&This->event_target, EVENTID_LOADEND, p); }
+static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onload(IWineXMLHttpRequestPrivate *iface, VARIANT v) +{ + HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface); + + TRACE("(%p)->(%s)\n", This, debugstr_variant(&v)); + + return set_event_handler(&This->event_target, EVENTID_LOAD, &v); +} + +static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onload(IWineXMLHttpRequestPrivate *iface, VARIANT *p) +{ + HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface); + + TRACE("(%p)->(%p)\n", This, p); + + return get_event_handler(&This->event_target, EVENTID_LOAD, p); +} + static const IWineXMLHttpRequestPrivateVtbl WineXMLHttpRequestPrivateVtbl = { HTMLXMLHttpRequest_private_QueryInterface, HTMLXMLHttpRequest_private_AddRef, @@ -1117,7 +1133,9 @@ static const IWineXMLHttpRequestPrivateVtbl WineXMLHttpRequestPrivateVtbl = { HTMLXMLHttpRequest_private_put_onloadstart, HTMLXMLHttpRequest_private_get_onloadstart, HTMLXMLHttpRequest_private_put_onloadend, - HTMLXMLHttpRequest_private_get_onloadend + HTMLXMLHttpRequest_private_get_onloadend, + HTMLXMLHttpRequest_private_put_onload, + HTMLXMLHttpRequest_private_get_onload };
static inline HTMLXMLHttpRequest *impl_from_IProvideClassInfo2(IProvideClassInfo2 *iface) @@ -1170,47 +1188,6 @@ static inline HTMLXMLHttpRequest *impl_from_DispatchEx(DispatchEx *iface) return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, event_target.dispex); }
-static HRESULT HTMLXMLHttpRequest_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid) -{ - /* onload event handler property is supported, but not exposed by any interface. We implement as a custom property. */ - if(!wcscmp(L"onload", name)) { - *dispid = MSHTML_DISPID_HTMLXMLHTTPREQUEST_ONLOAD; - return S_OK; - } - - return DISP_E_UNKNOWNNAME; -} - -static HRESULT HTMLXMLHttpRequest_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, - VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) -{ - HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex); - - if(id == MSHTML_DISPID_HTMLXMLHTTPREQUEST_ONLOAD) { - switch(flags) { - case DISPATCH_PROPERTYGET: - TRACE("(%p) get onload\n", This); - return get_event_handler(&This->event_target, EVENTID_LOAD, res); - - case DISPATCH_PROPERTYPUT: - if(params->cArgs != 1 || (params->cNamedArgs == 1 && *params->rgdispidNamedArgs != DISPID_PROPERTYPUT) - || params->cNamedArgs > 1) { - FIXME("invalid args\n"); - return E_INVALIDARG; - } - - TRACE("(%p)->(%p) set onload\n", This, params->rgvarg); - return set_event_handler(&This->event_target, EVENTID_LOAD, params->rgvarg); - - default: - FIXME("Unimplemented flags %x\n", flags); - return E_NOTIMPL; - } - } - - return DISP_E_UNKNOWNNAME; -} - static nsISupports *HTMLXMLHttpRequest_get_gecko_target(DispatchEx *dispex) { HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex); @@ -1266,22 +1243,33 @@ static void HTMLXMLHttpRequest_init_dispex_info(dispex_data_t *info, compat_mode {DISPID_IHTMLXMLHTTPREQUEST_OPEN, HTMLXMLHttpRequest_open_hook}, {DISPID_UNKNOWN} }; - static const dispex_hook_t private_ie10_hooks[] = { + static const dispex_hook_t private_hooks[] = { + {DISPID_IWINEXMLHTTPREQUESTPRIVATE_RESPONSE}, + {DISPID_IWINEXMLHTTPREQUESTPRIVATE_RESPONSETYPE}, + {DISPID_IWINEXMLHTTPREQUESTPRIVATE_UPLOAD}, + {DISPID_IWINEXMLHTTPREQUESTPRIVATE_WITHCREDENTIALS}, + {DISPID_EVPROP_ONERROR}, + {DISPID_EVPROP_ONABORT}, + {DISPID_EVPROP_PROGRESS}, + {DISPID_EVPROP_LOADSTART}, + {DISPID_EVPROP_LOADEND}, + + /* IE10 only */ {DISPID_IWINEXMLHTTPREQUESTPRIVATE_OVERRIDEMIMETYPE}, {DISPID_UNKNOWN} }; + const dispex_hook_t *const private_ie10_hooks = private_hooks + ARRAY_SIZE(private_hooks) - 2;
EventTarget_init_dispex_info(info, compat_mode); dispex_info_add_interface(info, IHTMLXMLHttpRequest_tid, compat_mode >= COMPAT_MODE_IE10 ? xhr_hooks : NULL); - if(compat_mode >= COMPAT_MODE_IE10) - dispex_info_add_interface(info, IWineXMLHttpRequestPrivate_tid, compat_mode == COMPAT_MODE_IE10 ? private_ie10_hooks : NULL); + dispex_info_add_interface(info, IWineXMLHttpRequestPrivate_tid, + compat_mode < COMPAT_MODE_IE10 ? private_hooks : + compat_mode < COMPAT_MODE_IE11 ? private_ie10_hooks : NULL); }
static event_target_vtbl_t HTMLXMLHttpRequest_event_target_vtbl = { { NULL, - HTMLXMLHttpRequest_get_dispid, - HTMLXMLHttpRequest_invoke }, HTMLXMLHttpRequest_get_gecko_target, HTMLXMLHttpRequest_bind_event