From: Zhenbo Li Subject: [PATCH 2/2] mshtml: Add IHTMLXMLHttpRequest:open() method implementation. Message-Id: <559251CD.5060501@gmail.com> Date: Tue, 30 Jun 2015 16:22:37 +0800 --- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/nsembed.c | 2 +- dlls/mshtml/tests/xmlhttprequest.c | 28 ++++++++---- dlls/mshtml/xmlhttprequest.c | 87 +++++++++++++++++++++++++++++++++++++- 4 files changed, 107 insertions(+), 11 deletions(-) diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index ca021ba..87e4154 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -855,6 +855,7 @@ HRESULT call_set_active_object(IOleInPlaceUIWindow*,IOleInPlaceActiveObject*) DE void *nsalloc(size_t) __WINE_ALLOC_SIZE(1) DECLSPEC_HIDDEN; void nsfree(void*) DECLSPEC_HIDDEN; +BOOL nsACString_Init(nsACString *str, const char *data) DECLSPEC_HIDDEN; void nsACString_InitDepend(nsACString*,const char*) DECLSPEC_HIDDEN; void nsACString_SetData(nsACString*,const char*) DECLSPEC_HIDDEN; UINT32 nsACString_GetData(const nsACString*,const char**) DECLSPEC_HIDDEN; diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c index 7055635..07eae09 100644 --- a/dlls/mshtml/nsembed.c +++ b/dlls/mshtml/nsembed.c @@ -795,7 +795,7 @@ void nsfree(void *mem) NS_Free(mem); } -static BOOL nsACString_Init(nsACString *str, const char *data) +BOOL nsACString_Init(nsACString *str, const char *data) { return NS_SUCCEEDED(NS_CStringContainerInit2(str, data, PR_UINT32_MAX, 0)); } diff --git a/dlls/mshtml/tests/xmlhttprequest.c b/dlls/mshtml/tests/xmlhttprequest.c index abfba57..56b89da 100644 --- a/dlls/mshtml/tests/xmlhttprequest.c +++ b/dlls/mshtml/tests/xmlhttprequest.c @@ -70,6 +70,9 @@ static int strcmp_wa(LPCWSTR strw, const char *stra) expect_ ## func = called_ ## func = FALSE; \ }while(0) +#define CLEAR_CALLED(func) \ + expect_ ## func = called_ ## func = FALSE + static IHTMLXMLHttpRequest *xhr = NULL; DEFINE_EXPECT(xmlhttprequest_onreadystatechange_opened); @@ -503,7 +506,7 @@ static void test_async_xhr(IHTMLDocument2 *doc, const char *xml_url) SET_EXPECT(xmlhttprequest_onreadystatechange_opened); hres = IHTMLXMLHttpRequest_open(xhr, method, url, vbool, vempty, vempty); - todo_wine ok(hres == S_OK, "open failed: %08x\n", hres); + ok(hres == S_OK, "open failed: %08x\n", hres); todo_wine CHECK_CALLED(xmlhttprequest_onreadystatechange_opened); SysFreeString(method); @@ -517,24 +520,33 @@ static void test_async_xhr(IHTMLDocument2 *doc, const char *xml_url) val = 0xdeadbeef; hres = IHTMLXMLHttpRequest_get_status(xhr, &val); - ok(hres == E_FAIL, "Expect E_FAIL, got: %08x\n", hres); - ok(val == 0, "Expect 0, got %d\n", val); + todo_wine ok(hres == E_FAIL, "Expect E_FAIL, got: %08x\n", hres); + todo_wine ok(val == 0, "Expect 0, got %d\n", val); hres = IHTMLXMLHttpRequest_get_statusText(xhr, &text); - ok(hres == E_FAIL, "Expect E_FAIL, got: %08x\n", hres); - ok(text == NULL, "Expect NULL, got %p\n", text); + todo_wine ok(hres == E_FAIL, "Expect E_FAIL, got: %08x\n", hres); + todo_wine ok(text == NULL, "Expect NULL, got %p\n", text); val = 0xdeadbeef; hres = IHTMLXMLHttpRequest_get_readyState(xhr, &val); - ok(hres == S_OK, "get_readyState failed: %08x\n", hres); - ok(val == 1, "Expect OPENED, got %d\n", val); + todo_wine ok(hres == S_OK, "get_readyState failed: %08x\n", hres); + todo_wine ok(val == 1, "Expect OPENED, got %d\n", val); SET_EXPECT(xmlhttprequest_onreadystatechange_opened); SET_EXPECT(xmlhttprequest_onreadystatechange_headers_received); SET_EXPECT(xmlhttprequest_onreadystatechange_loading); SET_EXPECT(xmlhttprequest_onreadystatechange_done); hres = IHTMLXMLHttpRequest_send(xhr, vempty); - ok(hres == S_OK, "send failed: %08x\n", hres); + todo_wine ok(hres == S_OK, "send failed: %08x\n", hres); + if(FAILED(hres)) { + CLEAR_CALLED(xmlhttprequest_onreadystatechange_opened); + CLEAR_CALLED(xmlhttprequest_onreadystatechange_headers_received); + CLEAR_CALLED(xmlhttprequest_onreadystatechange_loading); + CLEAR_CALLED(xmlhttprequest_onreadystatechange_done); + IHTMLXMLHttpRequest_Release(xhr); + xhr = NULL; + return; + } pump_msgs(&called_xmlhttprequest_onreadystatechange_done); todo_wine CHECK_CALLED(xmlhttprequest_onreadystatechange_opened); diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index 0f7bc9a..e77b0ee 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -33,6 +33,33 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml); +static HRESULT bstr_to_nsacstr(BSTR bstr, nsACString *str) +{ + char *cstr = heap_strdupWtoU(bstr); + if(!cstr) + return E_OUTOFMEMORY; + nsACString_Init(str, cstr); + heap_free(cstr); + return S_OK; +} + +static HRESULT variant_to_nsastr(VARIANT var, nsAString *ret) +{ + switch(V_VT(&var)) { + case VT_NULL: + case VT_ERROR: + case VT_EMPTY: + nsAString_Init(ret, NULL); + return S_OK; + case VT_BSTR: + nsAString_InitDepend(ret, V_BSTR(&var)); + return S_OK; + default: + FIXME("Unsupported VARIANT: %s\n", debugstr_variant(&var)); + return E_INVALIDARG; + } +} + /* IHTMLXMLHttpRequest */ typedef struct { EventTarget event_target; @@ -197,8 +224,64 @@ static HRESULT WINAPI HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest *iface) static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR bstrMethod, BSTR bstrUrl, VARIANT varAsync, VARIANT varUser, VARIANT varPassword) { HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface); - FIXME("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(bstrMethod), debugstr_w(bstrUrl), debugstr_variant(&varAsync), debugstr_variant(&varUser), debugstr_variant(&varPassword)); - return E_NOTIMPL; + nsACString method, url; + nsAString user, password; + 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) { + FIXME("varAsync not supported: %s\n", debugstr_variant(&varAsync)); + return E_FAIL; + } + + /* Note: Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), + * synchronous requests on the main thread have been deprecated due to the negative + * effects to the user experience. + */ + if(!V_BOOL(&varAsync)) { + FIXME("Synchronous request is not supported yet\n"); + return E_FAIL; + } + + hres = variant_to_nsastr(varUser, &user); + if(FAILED(hres)) + return hres; + hres = variant_to_nsastr(varPassword, &password); + if(FAILED(hres)) { + nsAString_Finish(&user); + return hres; + } + + hres = bstr_to_nsacstr(bstrMethod, &method); + if(FAILED(hres)) { + nsAString_Finish(&user); + nsAString_Finish(&password); + return hres; + } + hres = bstr_to_nsacstr(bstrUrl, &url); + if(FAILED(hres)) { + nsAString_Finish(&user); + nsAString_Finish(&password); + nsACString_Finish(&method); + return hres; + } + + nsres = nsIXMLHttpRequest_Open(This->nsxhr, &method, &url, TRUE, + &user, &password, 0); + + nsACString_Finish(&method); + nsACString_Finish(&url); + nsAString_Finish(&user); + nsAString_Finish(&password); + + if(NS_FAILED(nsres)) { + ERR("nsIXMLHttpRequest_Open failed: %08x\n", nsres); + return E_FAIL; + } + + return S_OK; } static HRESULT WINAPI HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest *iface, VARIANT varBody)