| /* |
| * Copyright 2006-2010 Jacek Caban for CodeWeavers |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include "config.h" |
| |
| #include <stdarg.h> |
| #include <assert.h> |
| |
| #define COBJMACROS |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "winuser.h" |
| #include "winreg.h" |
| #include "ole2.h" |
| #include "shlguid.h" |
| #include "wininet.h" |
| #include "shlwapi.h" |
| |
| #include "wine/debug.h" |
| |
| #include "mshtml_private.h" |
| #include "binding.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(mshtml); |
| |
| #define NS_IOSERVICE_CLASSNAME "nsIOService" |
| #define NS_IOSERVICE_CONTRACTID "@mozilla.org/network/io-service;1" |
| |
| static const IID NS_IOSERVICE_CID = |
| {0x9ac9e770, 0x18bc, 0x11d3, {0x93, 0x37, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40}}; |
| static const IID IID_nsWineURI = |
| {0x5088272e, 0x900b, 0x11da, {0xc6,0x87, 0x00,0x0f,0xea,0x57,0xf2,0x1a}}; |
| |
| static nsIIOService *nsio = NULL; |
| static nsINetUtil *net_util; |
| |
| static const char *request_method_strings[] = {"GET", "PUT", "POST"}; |
| |
| struct nsWineURI { |
| nsIURL nsIURL_iface; |
| nsIStandardURL nsIStandardURL_iface; |
| |
| LONG ref; |
| |
| NSContainer *container; |
| windowref_t *window_ref; |
| nsChannelBSC *channel_bsc; |
| IUri *uri; |
| IUriBuilder *uri_builder; |
| BOOL is_doc_uri; |
| BOOL is_mutable; |
| }; |
| |
| static BOOL ensure_uri(nsWineURI *This) |
| { |
| HRESULT hres; |
| |
| assert(This->uri || This->uri_builder); |
| |
| if(!This->uri) { |
| hres = IUriBuilder_CreateUriSimple(This->uri_builder, 0, 0, &This->uri); |
| if(FAILED(hres)) { |
| WARN("CreateUriSimple failed: %08x\n", hres); |
| return FALSE; |
| } |
| } |
| |
| return TRUE; |
| } |
| |
| IUri *nsuri_get_uri(nsWineURI *nsuri) |
| { |
| if(!ensure_uri(nsuri)) |
| return NULL; |
| |
| IUri_AddRef(nsuri->uri); |
| return nsuri->uri; |
| } |
| |
| static IUri *get_uri_nofrag(IUri *uri) |
| { |
| IUriBuilder *uri_builder; |
| IUri *ret; |
| BOOL b; |
| HRESULT hres; |
| |
| hres = IUri_HasProperty(uri, Uri_PROPERTY_FRAGMENT, &b); |
| if(SUCCEEDED(hres) && !b) { |
| IUri_AddRef(uri); |
| return uri; |
| } |
| |
| hres = CreateIUriBuilder(uri, 0, 0, &uri_builder); |
| if(FAILED(hres)) |
| return NULL; |
| |
| hres = IUriBuilder_RemoveProperties(uri_builder, Uri_HAS_FRAGMENT); |
| if(SUCCEEDED(hres)) |
| hres = IUriBuilder_CreateUriSimple(uri_builder, 0, 0, &ret); |
| IUriBuilder_Release(uri_builder); |
| if(FAILED(hres)) |
| return NULL; |
| |
| return ret; |
| } |
| |
| BOOL compare_ignoring_frag(IUri *uri1, IUri *uri2) |
| { |
| IUri *uri_nofrag1, *uri_nofrag2; |
| BOOL ret = FALSE; |
| |
| uri_nofrag1 = get_uri_nofrag(uri1); |
| if(!uri_nofrag1) |
| return FALSE; |
| |
| uri_nofrag2 = get_uri_nofrag(uri2); |
| if(uri_nofrag2) { |
| IUri_IsEqual(uri_nofrag1, uri_nofrag2, &ret); |
| IUri_Release(uri_nofrag2); |
| } |
| |
| IUri_Release(uri_nofrag1); |
| return ret; |
| } |
| |
| static nsresult create_nsuri(IUri*,HTMLOuterWindow*,NSContainer*,nsWineURI**); |
| |
| static const char *debugstr_nsacstr(const nsACString *nsstr) |
| { |
| const char *data; |
| |
| nsACString_GetData(nsstr, &data); |
| return debugstr_a(data); |
| } |
| |
| static nsresult return_wstr_nsacstr(nsACString *ret_str, const WCHAR *str, int len) |
| { |
| char *stra; |
| int lena; |
| |
| TRACE("returning %s\n", debugstr_wn(str, len)); |
| |
| if(!*str) { |
| nsACString_SetData(ret_str, ""); |
| return NS_OK; |
| } |
| |
| lena = WideCharToMultiByte(CP_ACP, 0, str, len, NULL, 0, NULL, NULL); |
| stra = heap_alloc(lena+1); |
| if(!stra) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| WideCharToMultiByte(CP_ACP, 0, str, len, stra, lena, NULL, NULL); |
| stra[lena] = 0; |
| |
| nsACString_SetData(ret_str, stra); |
| heap_free(stra); |
| return NS_OK; |
| } |
| |
| HRESULT nsuri_to_url(LPCWSTR nsuri, BOOL ret_empty, BSTR *ret) |
| { |
| const WCHAR *ptr = nsuri; |
| |
| static const WCHAR wine_prefixW[] = {'w','i','n','e',':'}; |
| |
| if(!strncmpW(nsuri, wine_prefixW, sizeof(wine_prefixW)/sizeof(WCHAR))) |
| ptr += sizeof(wine_prefixW)/sizeof(WCHAR); |
| |
| if(*ptr || ret_empty) { |
| *ret = SysAllocString(ptr); |
| if(!*ret) |
| return E_OUTOFMEMORY; |
| }else { |
| *ret = NULL; |
| } |
| |
| TRACE("%s -> %s\n", debugstr_w(nsuri), debugstr_w(*ret)); |
| return S_OK; |
| } |
| |
| static BOOL exec_shldocvw_67(HTMLDocumentObj *doc, BSTR url) |
| { |
| IOleCommandTarget *cmdtrg = NULL; |
| HRESULT hres; |
| |
| hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&cmdtrg); |
| if(SUCCEEDED(hres)) { |
| VARIANT varUrl, varRes; |
| |
| V_VT(&varUrl) = VT_BSTR; |
| V_BSTR(&varUrl) = url; |
| V_VT(&varRes) = VT_BOOL; |
| |
| hres = IOleCommandTarget_Exec(cmdtrg, &CGID_ShellDocView, 67, 0, &varUrl, &varRes); |
| |
| IOleCommandTarget_Release(cmdtrg); |
| |
| if(SUCCEEDED(hres) && !V_BOOL(&varRes)) { |
| TRACE("got VARIANT_FALSE, do not load\n"); |
| return FALSE; |
| } |
| } |
| |
| return TRUE; |
| } |
| |
| static nsresult before_async_open(nsChannel *channel, NSContainer *container, BOOL *cancel) |
| { |
| HTMLDocumentObj *doc = container->doc; |
| BSTR display_uri; |
| HRESULT hres; |
| |
| if(!doc->client) { |
| *cancel = TRUE; |
| return NS_OK; |
| } |
| |
| hres = IUri_GetDisplayUri(channel->uri->uri, &display_uri); |
| if(FAILED(hres)) |
| return NS_ERROR_FAILURE; |
| |
| if(!exec_shldocvw_67(doc, display_uri)) { |
| SysFreeString(display_uri); |
| *cancel = FALSE; |
| return NS_OK; |
| } |
| |
| hres = hlink_frame_navigate(&doc->basedoc, display_uri, channel, 0, cancel); |
| SysFreeString(display_uri); |
| if(FAILED(hres)) |
| *cancel = TRUE; |
| return NS_OK; |
| } |
| |
| HRESULT load_nsuri(HTMLOuterWindow *window, nsWineURI *uri, nsChannelBSC *channelbsc, DWORD flags) |
| { |
| nsIWebNavigation *web_navigation; |
| nsIDocShell *doc_shell; |
| HTMLDocumentNode *doc; |
| nsresult nsres; |
| |
| nsres = get_nsinterface((nsISupports*)window->nswindow, &IID_nsIWebNavigation, (void**)&web_navigation); |
| if(NS_FAILED(nsres)) { |
| ERR("Could not get nsIWebNavigation interface: %08x\n", nsres); |
| return E_FAIL; |
| } |
| |
| nsres = nsIWebNavigation_QueryInterface(web_navigation, &IID_nsIDocShell, (void**)&doc_shell); |
| nsIWebNavigation_Release(web_navigation); |
| if(NS_FAILED(nsres)) { |
| ERR("Could not get nsIDocShell: %08x\n", nsres); |
| return E_FAIL; |
| } |
| |
| uri->channel_bsc = channelbsc; |
| doc = window->base.inner_window->doc; |
| doc->skip_mutation_notif = TRUE; |
| nsres = nsIDocShell_LoadURI(doc_shell, (nsIURI*)&uri->nsIURL_iface, NULL, flags, FALSE); |
| if(doc == window->base.inner_window->doc) |
| doc->skip_mutation_notif = FALSE; |
| uri->channel_bsc = NULL; |
| nsIDocShell_Release(doc_shell); |
| if(NS_FAILED(nsres)) { |
| WARN("LoadURI failed: %08x\n", nsres); |
| return E_FAIL; |
| } |
| |
| return S_OK; |
| } |
| |
| static void set_uri_nscontainer(nsWineURI *This, NSContainer *nscontainer) |
| { |
| if(This->container) { |
| if(This->container == nscontainer) |
| return; |
| TRACE("Changing %p -> %p\n", This->container, nscontainer); |
| nsIWebBrowserChrome_Release(&This->container->nsIWebBrowserChrome_iface); |
| } |
| |
| if(nscontainer) |
| nsIWebBrowserChrome_AddRef(&nscontainer->nsIWebBrowserChrome_iface); |
| This->container = nscontainer; |
| } |
| |
| static void set_uri_window(nsWineURI *This, HTMLOuterWindow *window) |
| { |
| if(This->window_ref) { |
| if(This->window_ref->window == window) |
| return; |
| TRACE("Changing %p -> %p\n", This->window_ref->window, window); |
| windowref_release(This->window_ref); |
| } |
| |
| if(window) { |
| windowref_addref(window->window_ref); |
| This->window_ref = window->window_ref; |
| |
| if(window->doc_obj) |
| set_uri_nscontainer(This, window->doc_obj->nscontainer); |
| }else { |
| This->window_ref = NULL; |
| } |
| } |
| |
| static inline BOOL is_http_channel(nsChannel *This) |
| { |
| return This->url_scheme == URL_SCHEME_HTTP || This->url_scheme == URL_SCHEME_HTTPS; |
| } |
| |
| static http_header_t *find_http_header(struct list *headers, const WCHAR *name, int len) |
| { |
| http_header_t *iter; |
| |
| LIST_FOR_EACH_ENTRY(iter, headers, http_header_t, entry) { |
| if(!strcmpiW(iter->header, name)) |
| return iter; |
| } |
| |
| return NULL; |
| } |
| |
| static nsresult get_channel_http_header(struct list *headers, const nsACString *header_name_str, |
| nsACString *_retval) |
| { |
| const char *header_namea; |
| http_header_t *header; |
| WCHAR *header_name; |
| char *data; |
| |
| nsACString_GetData(header_name_str, &header_namea); |
| header_name = heap_strdupAtoW(header_namea); |
| if(!header_name) |
| return NS_ERROR_UNEXPECTED; |
| |
| header = find_http_header(headers, header_name, strlenW(header_name)); |
| heap_free(header_name); |
| if(!header) |
| return NS_ERROR_NOT_AVAILABLE; |
| |
| data = heap_strdupWtoA(header->data); |
| if(!data) |
| return NS_ERROR_UNEXPECTED; |
| |
| TRACE("%s -> %s\n", debugstr_a(header_namea), debugstr_a(data)); |
| nsACString_SetData(_retval, data); |
| heap_free(data); |
| return NS_OK; |
| } |
| |
| HRESULT set_http_header(struct list *headers, const WCHAR *name, int name_len, |
| const WCHAR *value, int value_len) |
| { |
| http_header_t *header; |
| |
| TRACE("%s: %s\n", debugstr_wn(name, name_len), debugstr_wn(value, value_len)); |
| |
| header = find_http_header(headers, name, name_len); |
| if(header) { |
| WCHAR *new_data; |
| |
| new_data = heap_strndupW(value, value_len); |
| if(!new_data) |
| return E_OUTOFMEMORY; |
| |
| heap_free(header->data); |
| header->data = new_data; |
| }else { |
| header = heap_alloc(sizeof(http_header_t)); |
| if(!header) |
| return E_OUTOFMEMORY; |
| |
| header->header = heap_strndupW(name, name_len); |
| header->data = heap_strndupW(value, value_len); |
| if(!header->header || !header->data) { |
| heap_free(header->header); |
| heap_free(header->data); |
| heap_free(header); |
| return E_OUTOFMEMORY; |
| } |
| |
| list_add_tail(headers, &header->entry); |
| } |
| |
| return S_OK; |
| } |
| |
| static nsresult set_channel_http_header(struct list *headers, const nsACString *name_str, |
| const nsACString *value_str) |
| { |
| const char *namea, *valuea; |
| WCHAR *name, *value; |
| HRESULT hres; |
| |
| nsACString_GetData(name_str, &namea); |
| name = heap_strdupAtoW(namea); |
| if(!name) |
| return NS_ERROR_UNEXPECTED; |
| |
| nsACString_GetData(value_str, &valuea); |
| value = heap_strdupAtoW(valuea); |
| if(!value) { |
| heap_free(name); |
| return NS_ERROR_UNEXPECTED; |
| } |
| |
| hres = set_http_header(headers, name, strlenW(name), value, strlenW(value)); |
| |
| heap_free(name); |
| heap_free(value); |
| return SUCCEEDED(hres) ? NS_OK : NS_ERROR_UNEXPECTED; |
| } |
| |
| static nsresult visit_http_headers(struct list *headers, nsIHttpHeaderVisitor *visitor) |
| { |
| nsACString header_str, value_str; |
| char *header, *value; |
| http_header_t *iter; |
| nsresult nsres; |
| |
| LIST_FOR_EACH_ENTRY(iter, headers, http_header_t, entry) { |
| header = heap_strdupWtoA(iter->header); |
| if(!header) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| value = heap_strdupWtoA(iter->data); |
| if(!value) { |
| heap_free(header); |
| return NS_ERROR_OUT_OF_MEMORY; |
| } |
| |
| nsACString_InitDepend(&header_str, header); |
| nsACString_InitDepend(&value_str, value); |
| nsres = nsIHttpHeaderVisitor_VisitHeader(visitor, &header_str, &value_str); |
| nsACString_Finish(&header_str); |
| nsACString_Finish(&value_str); |
| heap_free(header); |
| heap_free(value); |
| if(NS_FAILED(nsres)) |
| break; |
| } |
| |
| return NS_OK; |
| } |
| |
| static void free_http_headers(struct list *list) |
| { |
| http_header_t *iter, *iter_next; |
| |
| LIST_FOR_EACH_ENTRY_SAFE(iter, iter_next, list, http_header_t, entry) { |
| list_remove(&iter->entry); |
| heap_free(iter->header); |
| heap_free(iter->data); |
| heap_free(iter); |
| } |
| } |
| |
| static inline nsChannel *impl_from_nsIHttpChannel(nsIHttpChannel *iface) |
| { |
| return CONTAINING_RECORD(iface, nsChannel, nsIHttpChannel_iface); |
| } |
| |
| static nsresult NSAPI nsChannel_QueryInterface(nsIHttpChannel *iface, nsIIDRef riid, void **result) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| if(IsEqualGUID(&IID_nsISupports, riid)) { |
| TRACE("(%p)->(IID_nsISupports %p)\n", This, result); |
| *result = &This->nsIHttpChannel_iface; |
| }else if(IsEqualGUID(&IID_nsIRequest, riid)) { |
| TRACE("(%p)->(IID_nsIRequest %p)\n", This, result); |
| *result = &This->nsIHttpChannel_iface; |
| }else if(IsEqualGUID(&IID_nsIChannel, riid)) { |
| TRACE("(%p)->(IID_nsIChannel %p)\n", This, result); |
| *result = &This->nsIHttpChannel_iface; |
| }else if(IsEqualGUID(&IID_nsIHttpChannel, riid)) { |
| TRACE("(%p)->(IID_nsIHttpChannel %p)\n", This, result); |
| *result = is_http_channel(This) ? &This->nsIHttpChannel_iface : NULL; |
| }else if(IsEqualGUID(&IID_nsIUploadChannel, riid)) { |
| TRACE("(%p)->(IID_nsIUploadChannel %p)\n", This, result); |
| *result = &This->nsIUploadChannel_iface; |
| }else if(IsEqualGUID(&IID_nsIHttpChannelInternal, riid)) { |
| TRACE("(%p)->(IID_nsIHttpChannelInternal %p)\n", This, result); |
| *result = is_http_channel(This) ? &This->nsIHttpChannelInternal_iface : NULL; |
| }else { |
| TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result); |
| *result = NULL; |
| } |
| |
| if(*result) { |
| nsIChannel_AddRef(&This->nsIHttpChannel_iface); |
| return NS_OK; |
| } |
| |
| return NS_NOINTERFACE; |
| } |
| |
| static nsrefcnt NSAPI nsChannel_AddRef(nsIHttpChannel *iface) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| nsrefcnt ref = InterlockedIncrement(&This->ref); |
| |
| TRACE("(%p) ref=%d\n", This, ref); |
| |
| return ref; |
| } |
| |
| static nsrefcnt NSAPI nsChannel_Release(nsIHttpChannel *iface) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| LONG ref = InterlockedDecrement(&This->ref); |
| |
| if(!ref) { |
| nsIURI_Release(&This->uri->nsIURL_iface); |
| if(This->owner) |
| nsISupports_Release(This->owner); |
| if(This->post_data_stream) |
| nsIInputStream_Release(This->post_data_stream); |
| if(This->load_group) |
| nsILoadGroup_Release(This->load_group); |
| if(This->notif_callback) |
| nsIInterfaceRequestor_Release(This->notif_callback); |
| if(This->original_uri) |
| nsIURI_Release(This->original_uri); |
| if(This->referrer) |
| nsIURI_Release(This->referrer); |
| |
| free_http_headers(&This->response_headers); |
| free_http_headers(&This->request_headers); |
| |
| heap_free(This->content_type); |
| heap_free(This->charset); |
| heap_free(This); |
| } |
| |
| return ref; |
| } |
| |
| static nsresult NSAPI nsChannel_GetName(nsIHttpChannel *iface, nsACString *aName) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aName); |
| |
| return nsIURI_GetSpec(&This->uri->nsIURL_iface, aName); |
| } |
| |
| static nsresult NSAPI nsChannel_IsPending(nsIHttpChannel *iface, cpp_bool *_retval) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| FIXME("(%p)->(%p)\n", This, _retval); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_GetStatus(nsIHttpChannel *iface, nsresult *aStatus) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| WARN("(%p)->(%p) returning NS_OK\n", This, aStatus); |
| |
| return *aStatus = NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_Cancel(nsIHttpChannel *iface, nsresult aStatus) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| FIXME("(%p)->(%08x)\n", This, aStatus); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_Suspend(nsIHttpChannel *iface) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| FIXME("(%p)\n", This); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_Resume(nsIHttpChannel *iface) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| FIXME("(%p)\n", This); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_GetLoadGroup(nsIHttpChannel *iface, nsILoadGroup **aLoadGroup) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aLoadGroup); |
| |
| if(This->load_group) |
| nsILoadGroup_AddRef(This->load_group); |
| |
| *aLoadGroup = This->load_group; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_SetLoadGroup(nsIHttpChannel *iface, nsILoadGroup *aLoadGroup) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aLoadGroup); |
| |
| if(This->load_group) |
| nsILoadGroup_Release(This->load_group); |
| if(aLoadGroup) |
| nsILoadGroup_AddRef(aLoadGroup); |
| This->load_group = aLoadGroup; |
| |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_GetLoadFlags(nsIHttpChannel *iface, nsLoadFlags *aLoadFlags) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aLoadFlags); |
| |
| *aLoadFlags = This->load_flags; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_SetLoadFlags(nsIHttpChannel *iface, nsLoadFlags aLoadFlags) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%08x)\n", This, aLoadFlags); |
| |
| This->load_flags = aLoadFlags; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_GetOriginalURI(nsIHttpChannel *iface, nsIURI **aOriginalURI) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aOriginalURI); |
| |
| if(This->original_uri) |
| nsIURI_AddRef(This->original_uri); |
| |
| *aOriginalURI = This->original_uri; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_SetOriginalURI(nsIHttpChannel *iface, nsIURI *aOriginalURI) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aOriginalURI); |
| |
| if(This->original_uri) |
| nsIURI_Release(This->original_uri); |
| |
| nsIURI_AddRef(aOriginalURI); |
| This->original_uri = aOriginalURI; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_GetURI(nsIHttpChannel *iface, nsIURI **aURI) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aURI); |
| |
| nsIURI_AddRef(&This->uri->nsIURL_iface); |
| *aURI = (nsIURI*)This->uri; |
| |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_GetOwner(nsIHttpChannel *iface, nsISupports **aOwner) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aOwner); |
| |
| if(This->owner) |
| nsISupports_AddRef(This->owner); |
| *aOwner = This->owner; |
| |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_SetOwner(nsIHttpChannel *iface, nsISupports *aOwner) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aOwner); |
| |
| if(aOwner) |
| nsISupports_AddRef(aOwner); |
| if(This->owner) |
| nsISupports_Release(This->owner); |
| This->owner = aOwner; |
| |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_GetNotificationCallbacks(nsIHttpChannel *iface, |
| nsIInterfaceRequestor **aNotificationCallbacks) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aNotificationCallbacks); |
| |
| if(This->notif_callback) |
| nsIInterfaceRequestor_AddRef(This->notif_callback); |
| *aNotificationCallbacks = This->notif_callback; |
| |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_SetNotificationCallbacks(nsIHttpChannel *iface, |
| nsIInterfaceRequestor *aNotificationCallbacks) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aNotificationCallbacks); |
| |
| if(This->notif_callback) |
| nsIInterfaceRequestor_Release(This->notif_callback); |
| if(aNotificationCallbacks) |
| nsIInterfaceRequestor_AddRef(aNotificationCallbacks); |
| |
| This->notif_callback = aNotificationCallbacks; |
| |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_GetSecurityInfo(nsIHttpChannel *iface, nsISupports **aSecurityInfo) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aSecurityInfo); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_GetContentType(nsIHttpChannel *iface, nsACString *aContentType) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aContentType); |
| |
| if(This->content_type) { |
| nsACString_SetData(aContentType, This->content_type); |
| return S_OK; |
| } |
| |
| if(This->uri->is_doc_uri) { |
| WARN("Document channel with no MIME set. Assuming text/html\n"); |
| nsACString_SetData(aContentType, "text/html"); |
| return S_OK; |
| } |
| |
| WARN("unknown type\n"); |
| return NS_ERROR_FAILURE; |
| } |
| |
| static nsresult NSAPI nsChannel_SetContentType(nsIHttpChannel *iface, |
| const nsACString *aContentType) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| const char *content_type; |
| |
| TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aContentType)); |
| |
| nsACString_GetData(aContentType, &content_type); |
| heap_free(This->content_type); |
| This->content_type = heap_strdupA(content_type); |
| |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_GetContentCharset(nsIHttpChannel *iface, |
| nsACString *aContentCharset) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aContentCharset); |
| |
| if(This->charset) { |
| nsACString_SetData(aContentCharset, This->charset); |
| return NS_OK; |
| } |
| |
| nsACString_SetData(aContentCharset, ""); |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_SetContentCharset(nsIHttpChannel *iface, |
| const nsACString *aContentCharset) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| const char *data; |
| char *charset; |
| |
| TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aContentCharset)); |
| |
| nsACString_GetData(aContentCharset, &data); |
| charset = heap_strdupA(data); |
| if(!charset) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| heap_free(This->charset); |
| This->charset = charset; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_GetContentLength(nsIHttpChannel *iface, PRInt32 *aContentLength) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| FIXME("(%p)->(%p)\n", This, aContentLength); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_SetContentLength(nsIHttpChannel *iface, PRInt32 aContentLength) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| FIXME("(%p)->(%d)\n", This, aContentLength); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_Open(nsIHttpChannel *iface, nsIInputStream **_retval) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| FIXME("(%p)->(%p)\n", This, _retval); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static HTMLOuterWindow *get_window_from_load_group(nsChannel *This) |
| { |
| HTMLOuterWindow *window; |
| nsIChannel *channel; |
| nsIRequest *req; |
| nsWineURI *wine_uri; |
| nsIURI *uri; |
| nsresult nsres; |
| |
| nsres = nsILoadGroup_GetDefaultLoadRequest(This->load_group, &req); |
| if(NS_FAILED(nsres)) { |
| ERR("GetDefaultLoadRequest failed: %08x\n", nsres); |
| return NULL; |
| } |
| |
| if(!req) |
| return NULL; |
| |
| nsres = nsIRequest_QueryInterface(req, &IID_nsIChannel, (void**)&channel); |
| nsIRequest_Release(req); |
| if(NS_FAILED(nsres)) { |
| WARN("Could not get nsIChannel interface: %08x\n", nsres); |
| return NULL; |
| } |
| |
| nsres = nsIChannel_GetURI(channel, &uri); |
| nsIChannel_Release(channel); |
| if(NS_FAILED(nsres)) { |
| ERR("GetURI failed: %08x\n", nsres); |
| return NULL; |
| } |
| |
| nsres = nsIURI_QueryInterface(uri, &IID_nsWineURI, (void**)&wine_uri); |
| nsIURI_Release(uri); |
| if(NS_FAILED(nsres)) { |
| TRACE("Could not get nsWineURI: %08x\n", nsres); |
| return NULL; |
| } |
| |
| window = wine_uri->window_ref ? wine_uri->window_ref->window : NULL; |
| if(window) |
| IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); |
| nsIURI_Release(&wine_uri->nsIURL_iface); |
| |
| return window; |
| } |
| |
| static HTMLOuterWindow *get_channel_window(nsChannel *This) |
| { |
| nsIWebProgress *web_progress; |
| nsIDOMWindow *nswindow; |
| HTMLOuterWindow *window; |
| nsresult nsres; |
| |
| if(This->load_group) { |
| nsIRequestObserver *req_observer; |
| |
| nsres = nsILoadGroup_GetGroupObserver(This->load_group, &req_observer); |
| if(NS_FAILED(nsres) || !req_observer) { |
| ERR("GetGroupObserver failed: %08x\n", nsres); |
| return NULL; |
| } |
| |
| nsres = nsIRequestObserver_QueryInterface(req_observer, &IID_nsIWebProgress, (void**)&web_progress); |
| nsIRequestObserver_Release(req_observer); |
| if(NS_FAILED(nsres)) { |
| ERR("Could not get nsIWebProgress iface: %08x\n", nsres); |
| return NULL; |
| } |
| }else if(This->notif_callback) { |
| nsres = nsIInterfaceRequestor_GetInterface(This->notif_callback, &IID_nsIWebProgress, (void**)&web_progress); |
| if(NS_FAILED(nsres)) { |
| ERR("GetInterface(IID_nsIWebProgress failed: %08x\n", nsres); |
| return NULL; |
| } |
| }else { |
| ERR("no load group nor notif callback\n"); |
| return NULL; |
| } |
| |
| nsres = nsIWebProgress_GetDOMWindow(web_progress, &nswindow); |
| nsIWebProgress_Release(web_progress); |
| if(NS_FAILED(nsres) || !nswindow) { |
| ERR("GetDOMWindow failed: %08x\n", nsres); |
| return NULL; |
| } |
| |
| window = nswindow_to_window(nswindow); |
| nsIDOMWindow_Release(nswindow); |
| |
| if(window) |
| IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); |
| else |
| FIXME("NULL window for %p\n", nswindow); |
| return window; |
| } |
| |
| typedef struct { |
| task_t header; |
| HTMLInnerWindow *window; |
| nsChannelBSC *bscallback; |
| } start_binding_task_t; |
| |
| static void start_binding_proc(task_t *_task) |
| { |
| start_binding_task_t *task = (start_binding_task_t*)_task; |
| |
| start_binding(task->window, (BSCallback*)task->bscallback, NULL); |
| } |
| |
| static void start_binding_task_destr(task_t *_task) |
| { |
| start_binding_task_t *task = (start_binding_task_t*)_task; |
| |
| IBindStatusCallback_Release(&task->bscallback->bsc.IBindStatusCallback_iface); |
| heap_free(task); |
| } |
| |
| static nsresult async_open(nsChannel *This, HTMLOuterWindow *window, BOOL is_doc_channel, nsIStreamListener *listener, |
| nsISupports *context) |
| { |
| nsChannelBSC *bscallback; |
| IMoniker *mon = NULL; |
| HRESULT hres; |
| |
| hres = CreateURLMonikerEx2(NULL, This->uri->uri, &mon, 0); |
| if(FAILED(hres)) { |
| WARN("CreateURLMoniker failed: %08x\n", hres); |
| return NS_ERROR_UNEXPECTED; |
| } |
| |
| if(is_doc_channel) |
| set_current_mon(window, mon); |
| |
| hres = create_channelbsc(mon, NULL, NULL, 0, is_doc_channel, &bscallback); |
| IMoniker_Release(mon); |
| if(FAILED(hres)) |
| return NS_ERROR_UNEXPECTED; |
| |
| channelbsc_set_channel(bscallback, This, listener, context); |
| |
| if(is_doc_channel) { |
| hres = create_pending_window(window, bscallback); |
| if(SUCCEEDED(hres)) |
| async_start_doc_binding(window, window->pending_window); |
| IUnknown_Release((IUnknown*)bscallback); |
| if(FAILED(hres)) |
| return NS_ERROR_UNEXPECTED; |
| }else { |
| start_binding_task_t *task = heap_alloc(sizeof(start_binding_task_t)); |
| |
| task->window = window->base.inner_window; |
| task->bscallback = bscallback; |
| push_task(&task->header, start_binding_proc, start_binding_task_destr, window->base.inner_window->task_magic); |
| } |
| |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_AsyncOpen(nsIHttpChannel *iface, nsIStreamListener *aListener, |
| nsISupports *aContext) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| HTMLOuterWindow *window = NULL; |
| BOOL cancel = FALSE; |
| nsresult nsres = NS_OK; |
| |
| TRACE("(%p)->(%p %p)\n", This, aListener, aContext); |
| |
| if(!ensure_uri(This->uri)) |
| return NS_ERROR_FAILURE; |
| |
| if(TRACE_ON(mshtml)) { |
| BSTR uri_str; |
| IUri_GetDisplayUri(This->uri->uri, &uri_str); |
| TRACE("opening %s\n", debugstr_w(uri_str)); |
| SysFreeString(uri_str); |
| } |
| |
| if(This->uri->is_doc_uri) { |
| window = get_channel_window(This); |
| if(window) { |
| set_uri_window(This->uri, window); |
| }else if(This->uri->container) { |
| BOOL b; |
| |
| /* nscontainer->doc should be NULL which means navigation to a new window */ |
| if(This->uri->container->doc) |
| FIXME("nscontainer->doc = %p\n", This->uri->container->doc); |
| |
| nsres = before_async_open(This, This->uri->container, &b); |
| if(NS_FAILED(nsres)) |
| return nsres; |
| if(b) |
| FIXME("Navigation not cancelled\n"); |
| return NS_ERROR_UNEXPECTED; |
| } |
| } |
| |
| if(!window) { |
| if(This->uri->window_ref && This->uri->window_ref->window) { |
| window = This->uri->window_ref->window; |
| IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); |
| }else { |
| /* FIXME: Analyze removing get_window_from_load_group call */ |
| if(This->load_group) |
| window = get_window_from_load_group(This); |
| if(!window) |
| window = get_channel_window(This); |
| if(window) |
| set_uri_window(This->uri, window); |
| } |
| } |
| |
| if(!window) { |
| ERR("window = NULL\n"); |
| return NS_ERROR_UNEXPECTED; |
| } |
| |
| if(This->uri->is_doc_uri && window == window->doc_obj->basedoc.window) { |
| if(This->uri->channel_bsc) { |
| channelbsc_set_channel(This->uri->channel_bsc, This, aListener, aContext); |
| |
| if(window->doc_obj->mime) { |
| heap_free(This->content_type); |
| This->content_type = heap_strdupWtoA(window->doc_obj->mime); |
| } |
| |
| cancel = TRUE; |
| }else { |
| nsres = before_async_open(This, window->doc_obj->nscontainer, &cancel); |
| if(NS_SUCCEEDED(nsres) && cancel) { |
| TRACE("canceled\n"); |
| nsres = NS_BINDING_ABORTED; |
| } |
| } |
| } |
| |
| if(!cancel) |
| nsres = async_open(This, window, This->uri->is_doc_uri, aListener, aContext); |
| |
| if(NS_SUCCEEDED(nsres) && This->load_group) { |
| nsres = nsILoadGroup_AddRequest(This->load_group, (nsIRequest*)&This->nsIHttpChannel_iface, |
| aContext); |
| if(NS_FAILED(nsres)) |
| ERR("AddRequest failed: %08x\n", nsres); |
| } |
| |
| IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); |
| return nsres; |
| } |
| |
| static nsresult NSAPI nsChannel_GetContentDisposition(nsIHttpChannel *iface, PRUint32 *aContentDisposition) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| FIXME("(%p)->(%p)\n", This, aContentDisposition); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_GetContentDispositionFilename(nsIHttpChannel *iface, nsAString *aContentDispositionFilename) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| FIXME("(%p)->(%p)\n", This, aContentDispositionFilename); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_GetContentDispositionHeader(nsIHttpChannel *iface, nsACString *aContentDispositionHeader) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| FIXME("(%p)->(%p)\n", This, aContentDispositionHeader); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_GetRequestMethod(nsIHttpChannel *iface, nsACString *aRequestMethod) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aRequestMethod); |
| |
| nsACString_SetData(aRequestMethod, request_method_strings[This->request_method]); |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_SetRequestMethod(nsIHttpChannel *iface, |
| const nsACString *aRequestMethod) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| const char *method; |
| unsigned i; |
| |
| TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aRequestMethod)); |
| |
| nsACString_GetData(aRequestMethod, &method); |
| for(i=0; i < sizeof(request_method_strings)/sizeof(*request_method_strings); i++) { |
| if(!strcasecmp(method, request_method_strings[i])) { |
| This->request_method = i; |
| return NS_OK; |
| } |
| } |
| |
| ERR("Invalid method %s\n", debugstr_a(method)); |
| return NS_ERROR_UNEXPECTED; |
| } |
| |
| static nsresult NSAPI nsChannel_GetReferrer(nsIHttpChannel *iface, nsIURI **aReferrer) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aReferrer); |
| |
| if(This->referrer) |
| nsIURI_AddRef(This->referrer); |
| *aReferrer = This->referrer; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_SetReferrer(nsIHttpChannel *iface, nsIURI *aReferrer) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aReferrer); |
| |
| if(aReferrer) |
| nsIURI_AddRef(aReferrer); |
| if(This->referrer) |
| nsIURI_Release(This->referrer); |
| This->referrer = aReferrer; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_GetRequestHeader(nsIHttpChannel *iface, |
| const nsACString *aHeader, nsACString *_retval) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%s %p)\n", This, debugstr_nsacstr(aHeader), _retval); |
| |
| return get_channel_http_header(&This->request_headers, aHeader, _retval); |
| } |
| |
| static nsresult NSAPI nsChannel_SetRequestHeader(nsIHttpChannel *iface, |
| const nsACString *aHeader, const nsACString *aValue, cpp_bool aMerge) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%s %s %x)\n", This, debugstr_nsacstr(aHeader), debugstr_nsacstr(aValue), aMerge); |
| |
| if(aMerge) |
| FIXME("aMerge not supported\n"); |
| |
| return set_channel_http_header(&This->request_headers, aHeader, aValue); |
| } |
| |
| static nsresult NSAPI nsChannel_VisitRequestHeaders(nsIHttpChannel *iface, |
| nsIHttpHeaderVisitor *aVisitor) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| FIXME("(%p)->(%p)\n", This, aVisitor); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_GetAllowPipelining(nsIHttpChannel *iface, cpp_bool *aAllowPipelining) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| FIXME("(%p)->(%p)\n", This, aAllowPipelining); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_SetAllowPipelining(nsIHttpChannel *iface, cpp_bool aAllowPipelining) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| FIXME("(%p)->(%x)\n", This, aAllowPipelining); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_GetRedirectionLimit(nsIHttpChannel *iface, PRUint32 *aRedirectionLimit) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| FIXME("(%p)->(%p)\n", This, aRedirectionLimit); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_SetRedirectionLimit(nsIHttpChannel *iface, PRUint32 aRedirectionLimit) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| FIXME("(%p)->(%u)\n", This, aRedirectionLimit); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_GetResponseStatus(nsIHttpChannel *iface, PRUint32 *aResponseStatus) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aResponseStatus); |
| |
| if(This->response_status) { |
| *aResponseStatus = This->response_status; |
| return NS_OK; |
| } |
| |
| WARN("No response status\n"); |
| return NS_ERROR_UNEXPECTED; |
| } |
| |
| static nsresult NSAPI nsChannel_GetResponseStatusText(nsIHttpChannel *iface, |
| nsACString *aResponseStatusText) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| FIXME("(%p)->(%p)\n", This, aResponseStatusText); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_GetRequestSucceeded(nsIHttpChannel *iface, |
| cpp_bool *aRequestSucceeded) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aRequestSucceeded); |
| |
| if(!This->response_status) |
| return NS_ERROR_NOT_AVAILABLE; |
| |
| *aRequestSucceeded = This->response_status/100 == 2; |
| |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_GetResponseHeader(nsIHttpChannel *iface, |
| const nsACString *header, nsACString *_retval) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%s %p)\n", This, debugstr_nsacstr(header), _retval); |
| |
| return get_channel_http_header(&This->response_headers, header, _retval); |
| } |
| |
| static nsresult NSAPI nsChannel_SetResponseHeader(nsIHttpChannel *iface, |
| const nsACString *header, const nsACString *value, cpp_bool merge) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| FIXME("(%p)->(%s %s %x)\n", This, debugstr_nsacstr(header), debugstr_nsacstr(value), merge); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsChannel_VisitResponseHeaders(nsIHttpChannel *iface, |
| nsIHttpHeaderVisitor *aVisitor) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aVisitor); |
| |
| return visit_http_headers(&This->response_headers, aVisitor); |
| } |
| |
| static nsresult NSAPI nsChannel_IsNoStoreResponse(nsIHttpChannel *iface, cpp_bool *_retval) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| http_header_t *header; |
| |
| static const WCHAR cache_controlW[] = {'C','a','c','h','e','-','C','o','n','t','r','o','l'}; |
| static const WCHAR no_storeW[] = {'n','o','-','s','t','o','r','e',0}; |
| |
| TRACE("(%p)->(%p)\n", This, _retval); |
| |
| header = find_http_header(&This->response_headers, cache_controlW, sizeof(cache_controlW)/sizeof(WCHAR)); |
| *_retval = header && !strcmpiW(header->data, no_storeW); |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsChannel_IsNoCacheResponse(nsIHttpChannel *iface, cpp_bool *_retval) |
| { |
| nsChannel *This = impl_from_nsIHttpChannel(iface); |
| |
| FIXME("(%p)->(%p)\n", This, _retval); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static const nsIHttpChannelVtbl nsChannelVtbl = { |
| nsChannel_QueryInterface, |
| nsChannel_AddRef, |
| nsChannel_Release, |
| nsChannel_GetName, |
| nsChannel_IsPending, |
| nsChannel_GetStatus, |
| nsChannel_Cancel, |
| nsChannel_Suspend, |
| nsChannel_Resume, |
| nsChannel_GetLoadGroup, |
| nsChannel_SetLoadGroup, |
| nsChannel_GetLoadFlags, |
| nsChannel_SetLoadFlags, |
| nsChannel_GetOriginalURI, |
| nsChannel_SetOriginalURI, |
| nsChannel_GetURI, |
| nsChannel_GetOwner, |
| nsChannel_SetOwner, |
| nsChannel_GetNotificationCallbacks, |
| nsChannel_SetNotificationCallbacks, |
| nsChannel_GetSecurityInfo, |
| nsChannel_GetContentType, |
| nsChannel_SetContentType, |
| nsChannel_GetContentCharset, |
| nsChannel_SetContentCharset, |
| nsChannel_GetContentLength, |
| nsChannel_SetContentLength, |
| nsChannel_Open, |
| nsChannel_AsyncOpen, |
| nsChannel_GetContentDisposition, |
| nsChannel_GetContentDispositionFilename, |
| nsChannel_GetContentDispositionHeader, |
| nsChannel_GetRequestMethod, |
| nsChannel_SetRequestMethod, |
| nsChannel_GetReferrer, |
| nsChannel_SetReferrer, |
| nsChannel_GetRequestHeader, |
| nsChannel_SetRequestHeader, |
| nsChannel_VisitRequestHeaders, |
| nsChannel_GetAllowPipelining, |
| nsChannel_SetAllowPipelining, |
| nsChannel_GetRedirectionLimit, |
| nsChannel_SetRedirectionLimit, |
| nsChannel_GetResponseStatus, |
| nsChannel_GetResponseStatusText, |
| nsChannel_GetRequestSucceeded, |
| nsChannel_GetResponseHeader, |
| nsChannel_SetResponseHeader, |
| nsChannel_VisitResponseHeaders, |
| nsChannel_IsNoStoreResponse, |
| nsChannel_IsNoCacheResponse |
| }; |
| |
| static inline nsChannel *impl_from_nsIUploadChannel(nsIUploadChannel *iface) |
| { |
| return CONTAINING_RECORD(iface, nsChannel, nsIUploadChannel_iface); |
| } |
| |
| static nsresult NSAPI nsUploadChannel_QueryInterface(nsIUploadChannel *iface, nsIIDRef riid, |
| void **result) |
| { |
| nsChannel *This = impl_from_nsIUploadChannel(iface); |
| return nsIChannel_QueryInterface(&This->nsIHttpChannel_iface, riid, result); |
| } |
| |
| static nsrefcnt NSAPI nsUploadChannel_AddRef(nsIUploadChannel *iface) |
| { |
| nsChannel *This = impl_from_nsIUploadChannel(iface); |
| return nsIChannel_AddRef(&This->nsIHttpChannel_iface); |
| } |
| |
| static nsrefcnt NSAPI nsUploadChannel_Release(nsIUploadChannel *iface) |
| { |
| nsChannel *This = impl_from_nsIUploadChannel(iface); |
| return nsIChannel_Release(&This->nsIHttpChannel_iface); |
| } |
| |
| static nsresult NSAPI nsUploadChannel_SetUploadStream(nsIUploadChannel *iface, |
| nsIInputStream *aStream, const nsACString *aContentType, PRInt32 aContentLength) |
| { |
| nsChannel *This = impl_from_nsIUploadChannel(iface); |
| const char *content_type; |
| |
| static const WCHAR content_typeW[] = |
| {'C','o','n','t','e','n','t','-','T','y','p','e',0}; |
| |
| TRACE("(%p)->(%p %s %d)\n", This, aStream, debugstr_nsacstr(aContentType), aContentLength); |
| |
| This->post_data_contains_headers = TRUE; |
| |
| if(aContentType) { |
| nsACString_GetData(aContentType, &content_type); |
| if(*content_type) { |
| WCHAR *ct; |
| |
| ct = heap_strdupAtoW(content_type); |
| if(!ct) |
| return NS_ERROR_UNEXPECTED; |
| |
| set_http_header(&This->request_headers, content_typeW, |
| sizeof(content_typeW)/sizeof(WCHAR), ct, strlenW(ct)); |
| heap_free(ct); |
| This->post_data_contains_headers = FALSE; |
| } |
| } |
| |
| if(This->post_data_stream) |
| nsIInputStream_Release(This->post_data_stream); |
| |
| if(aContentLength != -1) |
| FIXME("Unsupported acontentLength = %d\n", aContentLength); |
| |
| if(This->post_data_stream) |
| nsIInputStream_Release(This->post_data_stream); |
| This->post_data_stream = aStream; |
| if(aStream) |
| nsIInputStream_AddRef(aStream); |
| |
| This->request_method = METHOD_POST; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsUploadChannel_GetUploadStream(nsIUploadChannel *iface, |
| nsIInputStream **aUploadStream) |
| { |
| nsChannel *This = impl_from_nsIUploadChannel(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aUploadStream); |
| |
| if(This->post_data_stream) |
| nsIInputStream_AddRef(This->post_data_stream); |
| |
| *aUploadStream = This->post_data_stream; |
| return NS_OK; |
| } |
| |
| static const nsIUploadChannelVtbl nsUploadChannelVtbl = { |
| nsUploadChannel_QueryInterface, |
| nsUploadChannel_AddRef, |
| nsUploadChannel_Release, |
| nsUploadChannel_SetUploadStream, |
| nsUploadChannel_GetUploadStream |
| }; |
| |
| static inline nsChannel *impl_from_nsIHttpChannelInternal(nsIHttpChannelInternal *iface) |
| { |
| return CONTAINING_RECORD(iface, nsChannel, nsIHttpChannelInternal_iface); |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_QueryInterface(nsIHttpChannelInternal *iface, nsIIDRef riid, |
| void **result) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| return nsIChannel_QueryInterface(&This->nsIHttpChannel_iface, riid, result); |
| } |
| |
| static nsrefcnt NSAPI nsHttpChannelInternal_AddRef(nsIHttpChannelInternal *iface) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| return nsIChannel_AddRef(&This->nsIHttpChannel_iface); |
| } |
| |
| static nsrefcnt NSAPI nsHttpChannelInternal_Release(nsIHttpChannelInternal *iface) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| return nsIChannel_Release(&This->nsIHttpChannel_iface); |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_GetDocumentURI(nsIHttpChannelInternal *iface, nsIURI **aDocumentURI) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| |
| FIXME("(%p)->()\n", This); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_SetDocumentURI(nsIHttpChannelInternal *iface, nsIURI *aDocumentURI) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| |
| FIXME("(%p)->()\n", This); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_GetRequestVersion(nsIHttpChannelInternal *iface, PRUint32 *major, PRUint32 *minor) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| |
| FIXME("(%p)->()\n", This); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_GetResponseVersion(nsIHttpChannelInternal *iface, PRUint32 *major, PRUint32 *minor) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| |
| FIXME("(%p)->()\n", This); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_SetCookie(nsIHttpChannelInternal *iface, const char *aCookieHeader) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| |
| FIXME("(%p)->()\n", This); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_SetupFallbackChannel(nsIHttpChannelInternal *iface, const char *aFallbackKey) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| |
| FIXME("(%p)->()\n", This); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_GetForceAllowThirdPartyCookie(nsIHttpChannelInternal *iface, cpp_bool *aForceThirdPartyCookie) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| |
| FIXME("(%p)->()\n", This); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_SetForceAllowThirdPartyCookie(nsIHttpChannelInternal *iface, cpp_bool aForceThirdPartyCookie) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| |
| FIXME("(%p)->()\n", This); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_GetCanceled(nsIHttpChannelInternal *iface, cpp_bool *aCanceled) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| |
| FIXME("(%p)->(%p)\n", This, aCanceled); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_GetChannelIsForDownload(nsIHttpChannelInternal *iface, cpp_bool *aCanceled) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| |
| FIXME("(%p)->(%p)\n", This, aCanceled); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_SetChannelIsForDownload(nsIHttpChannelInternal *iface, cpp_bool aCanceled) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| |
| FIXME("(%p)->(%x)\n", This, aCanceled); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_GetLocalAddress(nsIHttpChannelInternal *iface, nsACString *aLocalAddress) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| |
| FIXME("(%p)->(%p)\n", This, aLocalAddress); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_GetLocalPort(nsIHttpChannelInternal *iface, PRInt32 *aLocalPort) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| |
| FIXME("(%p)->(%p)\n", This, aLocalPort); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_GetRemoteAddress(nsIHttpChannelInternal *iface, nsACString *aRemoteAddress) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| |
| FIXME("(%p)->(%p)\n", This, aRemoteAddress); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_GetRemotePort(nsIHttpChannelInternal *iface, PRInt32 *aRemotePort) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| |
| FIXME("(%p)->(%p)\n", This, aRemotePort); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_SetCacheKeysRedirectChain(nsIHttpChannelInternal *iface, void *cacheKeys) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| |
| FIXME("(%p)->(%p)\n", This, cacheKeys); |
| |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_HTTPUpgrade(nsIHttpChannelInternal *iface, |
| const nsACString *aProtocolName, nsIHttpUpgradeListener *aListener) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| FIXME("(%p)->(%s %p)\n", This, debugstr_nsacstr(aProtocolName), aListener); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_GetAllowSpdy(nsIHttpChannelInternal *iface, cpp_bool *aAllowSpdy) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| FIXME("(%p)->(%p)\n", This, aAllowSpdy); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsHttpChannelInternal_SetAllowSpdy(nsIHttpChannelInternal *iface, cpp_bool aAllowSpdy) |
| { |
| nsChannel *This = impl_from_nsIHttpChannelInternal(iface); |
| FIXME("(%p)->(%x)\n", This, aAllowSpdy); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static const nsIHttpChannelInternalVtbl nsHttpChannelInternalVtbl = { |
| nsHttpChannelInternal_QueryInterface, |
| nsHttpChannelInternal_AddRef, |
| nsHttpChannelInternal_Release, |
| nsHttpChannelInternal_GetDocumentURI, |
| nsHttpChannelInternal_SetDocumentURI, |
| nsHttpChannelInternal_GetRequestVersion, |
| nsHttpChannelInternal_GetResponseVersion, |
| nsHttpChannelInternal_SetCookie, |
| nsHttpChannelInternal_SetupFallbackChannel, |
| nsHttpChannelInternal_GetForceAllowThirdPartyCookie, |
| nsHttpChannelInternal_SetForceAllowThirdPartyCookie, |
| nsHttpChannelInternal_GetCanceled, |
| nsHttpChannelInternal_GetChannelIsForDownload, |
| nsHttpChannelInternal_SetChannelIsForDownload, |
| nsHttpChannelInternal_GetLocalAddress, |
| nsHttpChannelInternal_GetLocalPort, |
| nsHttpChannelInternal_GetRemoteAddress, |
| nsHttpChannelInternal_GetRemotePort, |
| nsHttpChannelInternal_SetCacheKeysRedirectChain, |
| nsHttpChannelInternal_HTTPUpgrade, |
| nsHttpChannelInternal_GetAllowSpdy, |
| nsHttpChannelInternal_SetAllowSpdy |
| }; |
| |
| |
| static void invalidate_uri(nsWineURI *This) |
| { |
| if(This->uri) { |
| IUri_Release(This->uri); |
| This->uri = NULL; |
| } |
| } |
| |
| static BOOL ensure_uri_builder(nsWineURI *This) |
| { |
| if(!This->is_mutable) { |
| WARN("Not mutable URI\n"); |
| return FALSE; |
| } |
| |
| if(!This->uri_builder) { |
| HRESULT hres; |
| |
| if(!ensure_uri(This)) |
| return FALSE; |
| |
| hres = CreateIUriBuilder(This->uri, 0, 0, &This->uri_builder); |
| if(FAILED(hres)) { |
| WARN("CreateIUriBuilder failed: %08x\n", hres); |
| return FALSE; |
| } |
| } |
| |
| invalidate_uri(This); |
| return TRUE; |
| } |
| |
| static nsresult get_uri_string(nsWineURI *This, Uri_PROPERTY prop, nsACString *ret) |
| { |
| char *vala; |
| BSTR val; |
| HRESULT hres; |
| |
| if(!ensure_uri(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| hres = IUri_GetPropertyBSTR(This->uri, prop, &val, 0); |
| if(FAILED(hres)) { |
| WARN("GetPropertyBSTR failed: %08x\n", hres); |
| return NS_ERROR_UNEXPECTED; |
| } |
| |
| vala = heap_strdupWtoA(val); |
| SysFreeString(val); |
| if(!vala) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| TRACE("ret %s\n", debugstr_a(vala)); |
| nsACString_SetData(ret, vala); |
| heap_free(vala); |
| return NS_OK; |
| } |
| |
| static inline nsWineURI *impl_from_nsIURL(nsIURL *iface) |
| { |
| return CONTAINING_RECORD(iface, nsWineURI, nsIURL_iface); |
| } |
| |
| static nsresult NSAPI nsURI_QueryInterface(nsIURL *iface, nsIIDRef riid, void **result) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| |
| *result = NULL; |
| |
| if(IsEqualGUID(&IID_nsISupports, riid)) { |
| TRACE("(%p)->(IID_nsISupports %p)\n", This, result); |
| *result = &This->nsIURL_iface; |
| }else if(IsEqualGUID(&IID_nsIURI, riid)) { |
| TRACE("(%p)->(IID_nsIURI %p)\n", This, result); |
| *result = &This->nsIURL_iface; |
| }else if(IsEqualGUID(&IID_nsIURL, riid)) { |
| TRACE("(%p)->(IID_nsIURL %p)\n", This, result); |
| *result = &This->nsIURL_iface; |
| }else if(IsEqualGUID(&IID_nsIMutable, riid)) { |
| TRACE("(%p)->(IID_nsIMutable %p)\n", This, result); |
| *result = &This->nsIStandardURL_iface; |
| }else if(IsEqualGUID(&IID_nsIStandardURL, riid)) { |
| TRACE("(%p)->(IID_nsIStandardURL %p)\n", This, result); |
| *result = &This->nsIStandardURL_iface; |
| }else if(IsEqualGUID(&IID_nsWineURI, riid)) { |
| TRACE("(%p)->(IID_nsWineURI %p)\n", This, result); |
| *result = This; |
| } |
| |
| if(*result) { |
| nsIURI_AddRef(&This->nsIURL_iface); |
| return NS_OK; |
| } |
| |
| TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result); |
| return NS_NOINTERFACE; |
| } |
| |
| static nsrefcnt NSAPI nsURI_AddRef(nsIURL *iface) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| LONG ref = InterlockedIncrement(&This->ref); |
| |
| TRACE("(%p) ref=%d\n", This, ref); |
| |
| return ref; |
| } |
| |
| static nsrefcnt NSAPI nsURI_Release(nsIURL *iface) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| LONG ref = InterlockedDecrement(&This->ref); |
| |
| TRACE("(%p) ref=%d\n", This, ref); |
| |
| if(!ref) { |
| if(This->window_ref) |
| windowref_release(This->window_ref); |
| if(This->container) |
| nsIWebBrowserChrome_Release(&This->container->nsIWebBrowserChrome_iface); |
| if(This->uri) |
| IUri_Release(This->uri); |
| heap_free(This); |
| } |
| |
| return ref; |
| } |
| |
| static nsresult NSAPI nsURI_GetSpec(nsIURL *iface, nsACString *aSpec) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aSpec); |
| |
| return get_uri_string(This, Uri_PROPERTY_DISPLAY_URI, aSpec); |
| } |
| |
| static nsresult NSAPI nsURI_SetSpec(nsIURL *iface, const nsACString *aSpec) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| const char *speca; |
| WCHAR *spec; |
| IUri *uri; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aSpec)); |
| |
| if(!This->is_mutable) |
| return NS_ERROR_UNEXPECTED; |
| |
| nsACString_GetData(aSpec, &speca); |
| spec = heap_strdupAtoW(speca); |
| if(!spec) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| hres = CreateUri(spec, 0, 0, &uri); |
| heap_free(spec); |
| if(FAILED(hres)) { |
| WARN("CreateUri failed: %08x\n", hres); |
| return NS_ERROR_FAILURE; |
| } |
| |
| invalidate_uri(This); |
| if(This->uri_builder) { |
| IUriBuilder_Release(This->uri_builder); |
| This->uri_builder = NULL; |
| } |
| |
| This->uri = uri; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURI_GetPrePath(nsIURL *iface, nsACString *aPrePath) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| FIXME("(%p)->(%p)\n", This, aPrePath); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsURI_GetScheme(nsIURL *iface, nsACString *aScheme) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| DWORD scheme; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%p)\n", This, aScheme); |
| |
| if(!ensure_uri(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| hres = IUri_GetScheme(This->uri, &scheme); |
| if(FAILED(hres)) { |
| WARN("GetScheme failed: %08x\n", hres); |
| return NS_ERROR_UNEXPECTED; |
| } |
| |
| if(scheme == URL_SCHEME_ABOUT) { |
| nsACString_SetData(aScheme, "wine"); |
| return NS_OK; |
| } |
| |
| return get_uri_string(This, Uri_PROPERTY_SCHEME_NAME, aScheme); |
| } |
| |
| static nsresult NSAPI nsURI_SetScheme(nsIURL *iface, const nsACString *aScheme) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| const char *schemea; |
| WCHAR *scheme; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aScheme)); |
| |
| if(!ensure_uri_builder(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| nsACString_GetData(aScheme, &schemea); |
| scheme = heap_strdupAtoW(schemea); |
| if(!scheme) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| hres = IUriBuilder_SetSchemeName(This->uri_builder, scheme); |
| heap_free(scheme); |
| if(FAILED(hres)) |
| return NS_ERROR_UNEXPECTED; |
| |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURI_GetUserPass(nsIURL *iface, nsACString *aUserPass) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| BSTR user, pass; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%p)\n", This, aUserPass); |
| |
| if(!ensure_uri(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| hres = IUri_GetUserName(This->uri, &user); |
| if(FAILED(hres)) |
| return NS_ERROR_FAILURE; |
| |
| hres = IUri_GetPassword(This->uri, &pass); |
| if(FAILED(hres)) { |
| SysFreeString(user); |
| return NS_ERROR_FAILURE; |
| } |
| |
| if(*user || *pass) { |
| FIXME("Construct user:pass string\n"); |
| }else { |
| nsACString_SetData(aUserPass, ""); |
| } |
| |
| SysFreeString(user); |
| SysFreeString(pass); |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURI_SetUserPass(nsIURL *iface, const nsACString *aUserPass) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| WCHAR *user = NULL, *pass = NULL, *buf = NULL; |
| const char *user_pass; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aUserPass)); |
| |
| if(!ensure_uri_builder(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| nsACString_GetData(aUserPass, &user_pass); |
| if(*user_pass) { |
| WCHAR *ptr; |
| |
| buf = heap_strdupAtoW(user_pass); |
| if(!buf) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| ptr = strchrW(buf, ':'); |
| if(!ptr) { |
| user = buf; |
| }else if(ptr != buf) { |
| *ptr++ = 0; |
| user = buf; |
| if(*ptr) |
| pass = ptr; |
| }else { |
| pass = buf+1; |
| } |
| } |
| |
| hres = IUriBuilder_SetUserName(This->uri_builder, user); |
| if(SUCCEEDED(hres)) |
| hres = IUriBuilder_SetPassword(This->uri_builder, pass); |
| |
| heap_free(buf); |
| return SUCCEEDED(hres) ? NS_OK : NS_ERROR_FAILURE; |
| } |
| |
| static nsresult NSAPI nsURI_GetUsername(nsIURL *iface, nsACString *aUsername) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aUsername); |
| |
| return get_uri_string(This, Uri_PROPERTY_USER_NAME, aUsername); |
| } |
| |
| static nsresult NSAPI nsURI_SetUsername(nsIURL *iface, const nsACString *aUsername) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| const char *usera; |
| WCHAR *user; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aUsername)); |
| |
| if(!ensure_uri_builder(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| nsACString_GetData(aUsername, &usera); |
| user = heap_strdupAtoW(usera); |
| if(!user) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| hres = IUriBuilder_SetUserName(This->uri_builder, user); |
| heap_free(user); |
| if(FAILED(hres)) |
| return NS_ERROR_UNEXPECTED; |
| |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURI_GetPassword(nsIURL *iface, nsACString *aPassword) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aPassword); |
| |
| return get_uri_string(This, Uri_PROPERTY_PASSWORD, aPassword); |
| } |
| |
| static nsresult NSAPI nsURI_SetPassword(nsIURL *iface, const nsACString *aPassword) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| const char *passa; |
| WCHAR *pass; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aPassword)); |
| |
| if(!ensure_uri_builder(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| nsACString_GetData(aPassword, &passa); |
| pass = heap_strdupAtoW(passa); |
| if(!pass) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| hres = IUriBuilder_SetPassword(This->uri_builder, pass); |
| heap_free(pass); |
| if(FAILED(hres)) |
| return NS_ERROR_UNEXPECTED; |
| |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURI_GetHostPort(nsIURL *iface, nsACString *aHostPort) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| const WCHAR *ptr; |
| char *vala; |
| BSTR val; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%p)\n", This, aHostPort); |
| |
| if(!ensure_uri(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| hres = IUri_GetAuthority(This->uri, &val); |
| if(FAILED(hres)) { |
| WARN("GetAuthority failed: %08x\n", hres); |
| return NS_ERROR_UNEXPECTED; |
| } |
| |
| ptr = strchrW(val, '@'); |
| if(!ptr) |
| ptr = val; |
| |
| vala = heap_strdupWtoA(ptr); |
| SysFreeString(val); |
| if(!vala) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| TRACE("ret %s\n", debugstr_a(vala)); |
| nsACString_SetData(aHostPort, vala); |
| heap_free(vala); |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURI_SetHostPort(nsIURL *iface, const nsACString *aHostPort) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| |
| WARN("(%p)->(%s)\n", This, debugstr_nsacstr(aHostPort)); |
| |
| /* Not implemented by Gecko */ |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsURI_GetHost(nsIURL *iface, nsACString *aHost) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aHost); |
| |
| return get_uri_string(This, Uri_PROPERTY_HOST, aHost); |
| } |
| |
| static nsresult NSAPI nsURI_SetHost(nsIURL *iface, const nsACString *aHost) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| const char *hosta; |
| WCHAR *host; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aHost)); |
| |
| if(!ensure_uri_builder(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| nsACString_GetData(aHost, &hosta); |
| host = heap_strdupAtoW(hosta); |
| if(!host) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| hres = IUriBuilder_SetHost(This->uri_builder, host); |
| heap_free(host); |
| if(FAILED(hres)) |
| return NS_ERROR_UNEXPECTED; |
| |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURI_GetPort(nsIURL *iface, PRInt32 *aPort) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| DWORD port; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%p)\n", This, aPort); |
| |
| if(!ensure_uri(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| hres = IUri_GetPort(This->uri, &port); |
| if(FAILED(hres)) { |
| WARN("GetPort failed: %08x\n", hres); |
| return NS_ERROR_UNEXPECTED; |
| } |
| |
| *aPort = port ? port : -1; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURI_SetPort(nsIURL *iface, PRInt32 aPort) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| HRESULT hres; |
| |
| TRACE("(%p)->(%d)\n", This, aPort); |
| |
| if(!ensure_uri_builder(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| hres = IUriBuilder_SetPort(This->uri_builder, aPort != -1, aPort); |
| return SUCCEEDED(hres) ? NS_OK : NS_ERROR_FAILURE; |
| } |
| |
| static nsresult NSAPI nsURI_GetPath(nsIURL *iface, nsACString *aPath) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aPath); |
| |
| return get_uri_string(This, Uri_PROPERTY_PATH, aPath); |
| } |
| |
| static nsresult NSAPI nsURI_SetPath(nsIURL *iface, const nsACString *aPath) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| const char *patha; |
| WCHAR *path; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aPath)); |
| |
| if(!ensure_uri_builder(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| nsACString_GetData(aPath, &patha); |
| path = heap_strdupAtoW(patha); |
| if(!path) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| hres = IUriBuilder_SetPath(This->uri_builder, path); |
| heap_free(path); |
| if(FAILED(hres)) |
| return NS_ERROR_UNEXPECTED; |
| |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURI_Equals(nsIURL *iface, nsIURI *other, cpp_bool *_retval) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| nsWineURI *other_obj; |
| nsresult nsres; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%p %p)\n", This, other, _retval); |
| |
| nsres = nsIURI_QueryInterface(other, &IID_nsWineURI, (void**)&other_obj); |
| if(NS_FAILED(nsres)) { |
| TRACE("Could not get nsWineURI interface\n"); |
| *_retval = FALSE; |
| return NS_OK; |
| } |
| |
| if(ensure_uri(This) && ensure_uri(other_obj)) { |
| BOOL b; |
| |
| hres = IUri_IsEqual(This->uri, other_obj->uri, &b); |
| if(SUCCEEDED(hres)) { |
| *_retval = b; |
| nsres = NS_OK; |
| }else { |
| nsres = NS_ERROR_FAILURE; |
| } |
| }else { |
| nsres = NS_ERROR_UNEXPECTED; |
| } |
| |
| nsIURI_Release(&other_obj->nsIURL_iface); |
| return nsres; |
| } |
| |
| static nsresult NSAPI nsURI_SchemeIs(nsIURL *iface, const char *scheme, cpp_bool *_retval) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| WCHAR buf[INTERNET_MAX_SCHEME_LENGTH]; |
| BSTR scheme_name; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%s %p)\n", This, debugstr_a(scheme), _retval); |
| |
| if(!ensure_uri(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| hres = IUri_GetSchemeName(This->uri, &scheme_name); |
| if(FAILED(hres)) |
| return NS_ERROR_UNEXPECTED; |
| |
| MultiByteToWideChar(CP_ACP, 0, scheme, -1, buf, sizeof(buf)/sizeof(WCHAR)); |
| *_retval = !strcmpW(scheme_name, buf); |
| SysFreeString(scheme_name); |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURI_Clone(nsIURL *iface, nsIURI **_retval) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| nsWineURI *wine_uri; |
| nsresult nsres; |
| |
| TRACE("(%p)->(%p)\n", This, _retval); |
| |
| if(!ensure_uri(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| nsres = create_nsuri(This->uri, This->window_ref ? This->window_ref->window : NULL, This->container, &wine_uri); |
| if(NS_FAILED(nsres)) { |
| WARN("create_nsuri failed: %08x\n", nsres); |
| return nsres; |
| } |
| |
| *_retval = (nsIURI*)&wine_uri->nsIURL_iface; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURI_Resolve(nsIURL *iface, const nsACString *aRelativePath, |
| nsACString *_retval) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| const char *patha; |
| IUri *new_uri; |
| WCHAR *path; |
| char *reta; |
| BSTR ret; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%s %p)\n", This, debugstr_nsacstr(aRelativePath), _retval); |
| |
| if(!ensure_uri(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| nsACString_GetData(aRelativePath, &patha); |
| path = heap_strdupAtoW(patha); |
| if(!path) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| hres = CoInternetCombineUrlEx(This->uri, path, URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO, &new_uri, 0); |
| heap_free(path); |
| if(FAILED(hres)) { |
| ERR("CoIntenetCombineUrlEx failed: %08x\n", hres); |
| return NS_ERROR_FAILURE; |
| } |
| |
| hres = IUri_GetDisplayUri(new_uri, &ret); |
| IUri_Release(new_uri); |
| if(FAILED(hres)) |
| return NS_ERROR_FAILURE; |
| |
| reta = heap_strdupWtoA(ret); |
| SysFreeString(ret); |
| if(!reta) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| TRACE("returning %s\n", debugstr_a(reta)); |
| nsACString_SetData(_retval, reta); |
| heap_free(reta); |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURI_GetAsciiSpec(nsIURL *iface, nsACString *aAsciiSpec) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aAsciiSpec); |
| |
| return nsIURI_GetSpec(&This->nsIURL_iface, aAsciiSpec); |
| } |
| |
| static nsresult NSAPI nsURI_GetAsciiHost(nsIURL *iface, nsACString *aAsciiHost) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| |
| WARN("(%p)->(%p) FIXME: Use Uri_PUNYCODE_IDN_HOST flag\n", This, aAsciiHost); |
| |
| return get_uri_string(This, Uri_PROPERTY_HOST, aAsciiHost); |
| } |
| |
| static nsresult NSAPI nsURI_GetOriginCharset(nsIURL *iface, nsACString *aOriginCharset) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| FIXME("(%p)->(%p)\n", This, aOriginCharset); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsURL_GetRef(nsIURL *iface, nsACString *aRef) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| char *refa = NULL; |
| BSTR ref; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%p)\n", This, aRef); |
| |
| if(!ensure_uri(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| hres = IUri_GetFragment(This->uri, &ref); |
| if(FAILED(hres)) |
| return NS_ERROR_UNEXPECTED; |
| |
| refa = heap_strdupWtoA(ref); |
| SysFreeString(ref); |
| if(ref && !refa) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| nsACString_SetData(aRef, refa && *refa == '#' ? refa+1 : refa); |
| heap_free(refa); |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURL_SetRef(nsIURL *iface, const nsACString *aRef) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| const char *refa; |
| WCHAR *ref; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aRef)); |
| |
| if(!ensure_uri_builder(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| nsACString_GetData(aRef, &refa); |
| ref = heap_strdupAtoW(refa); |
| if(!ref) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| hres = IUriBuilder_SetFragment(This->uri_builder, ref); |
| heap_free(ref); |
| if(FAILED(hres)) |
| return NS_ERROR_UNEXPECTED; |
| |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURI_EqualsExceptRef(nsIURL *iface, nsIURI *other, cpp_bool *_retval) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| nsWineURI *other_obj; |
| nsresult nsres; |
| |
| TRACE("(%p)->(%p %p)\n", This, other, _retval); |
| |
| nsres = nsIURI_QueryInterface(other, &IID_nsWineURI, (void**)&other_obj); |
| if(NS_FAILED(nsres)) { |
| TRACE("Could not get nsWineURI interface\n"); |
| *_retval = FALSE; |
| return NS_OK; |
| } |
| |
| if(ensure_uri(This) && ensure_uri(other_obj)) { |
| *_retval = compare_ignoring_frag(This->uri, other_obj->uri); |
| nsres = NS_OK; |
| }else { |
| nsres = NS_ERROR_UNEXPECTED; |
| } |
| |
| nsIURI_Release(&other_obj->nsIURL_iface); |
| return nsres; |
| } |
| |
| static nsresult NSAPI nsURI_CloneIgnoreRef(nsIURL *iface, nsIURI **_retval) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| nsWineURI *wine_uri; |
| IUri *uri; |
| nsresult nsres; |
| |
| TRACE("(%p)->(%p)\n", This, _retval); |
| |
| if(!ensure_uri(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| uri = get_uri_nofrag(This->uri); |
| if(!uri) |
| return NS_ERROR_FAILURE; |
| |
| nsres = create_nsuri(uri, This->window_ref ? This->window_ref->window : NULL, This->container, &wine_uri); |
| IUri_Release(uri); |
| if(NS_FAILED(nsres)) { |
| WARN("create_nsuri failed: %08x\n", nsres); |
| return nsres; |
| } |
| |
| *_retval = (nsIURI*)&wine_uri->nsIURL_iface; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURI_GetSpecIgnoringRef(nsIURL *iface, nsACString *aSpecIgnoringRef) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| |
| FIXME("(%p)->(%p)\n", This, aSpecIgnoringRef); |
| |
| return nsIURL_GetSpec(&This->nsIURL_iface, aSpecIgnoringRef); |
| } |
| |
| static nsresult NSAPI nsURI_GetHasRef(nsIURL *iface, cpp_bool *aHasRef) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| BOOL b; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%p)\n", This, aHasRef); |
| |
| if(!ensure_uri(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| hres = IUri_HasProperty(This->uri, Uri_PROPERTY_FRAGMENT, &b); |
| if(FAILED(hres)) |
| return NS_ERROR_FAILURE; |
| |
| *aHasRef = b; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURL_GetFilePath(nsIURL *iface, nsACString *aFilePath) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aFilePath); |
| |
| return nsIURL_GetPath(&This->nsIURL_iface, aFilePath); |
| } |
| |
| static nsresult NSAPI nsURL_SetFilePath(nsIURL *iface, const nsACString *aFilePath) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| |
| TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFilePath)); |
| |
| if(!This->is_mutable) |
| return NS_ERROR_UNEXPECTED; |
| |
| return nsIURL_SetPath(&This->nsIURL_iface, aFilePath); |
| } |
| |
| static nsresult NSAPI nsURL_GetQuery(nsIURL *iface, nsACString *aQuery) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aQuery); |
| |
| return get_uri_string(This, Uri_PROPERTY_QUERY, aQuery); |
| } |
| |
| static nsresult NSAPI nsURL_SetQuery(nsIURL *iface, const nsACString *aQuery) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| const char *querya; |
| WCHAR *query; |
| HRESULT hres; |
| |
| TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aQuery)); |
| |
| if(!ensure_uri_builder(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| nsACString_GetData(aQuery, &querya); |
| query = heap_strdupAtoW(querya); |
| if(!query) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| hres = IUriBuilder_SetQuery(This->uri_builder, query); |
| heap_free(query); |
| if(FAILED(hres)) |
| return NS_ERROR_UNEXPECTED; |
| |
| return NS_OK; |
| } |
| |
| static nsresult get_uri_path(nsWineURI *This, BSTR *path, const WCHAR **file, const WCHAR **ext) |
| { |
| const WCHAR *ptr; |
| HRESULT hres; |
| |
| if(!ensure_uri(This)) |
| return NS_ERROR_UNEXPECTED; |
| |
| hres = IUri_GetPath(This->uri, path); |
| if(FAILED(hres)) |
| return NS_ERROR_FAILURE; |
| |
| for(ptr = *path + SysStringLen(*path)-1; ptr > *path && *ptr != '/' && *ptr != '\\'; ptr--); |
| if(*ptr == '/' || *ptr == '\\') |
| ptr++; |
| *file = ptr; |
| |
| if(ext) { |
| ptr = strrchrW(ptr, '.'); |
| if(!ptr) |
| ptr = *path + SysStringLen(*path); |
| *ext = ptr; |
| } |
| |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsURL_GetDirectory(nsIURL *iface, nsACString *aDirectory) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| const WCHAR *file; |
| BSTR path; |
| nsresult nsres; |
| |
| TRACE("(%p)->(%p)\n", This, aDirectory); |
| |
| nsres = get_uri_path(This, &path, &file, NULL); |
| if(NS_FAILED(nsres)) |
| return nsres; |
| |
| nsres = return_wstr_nsacstr(aDirectory, path, file-path); |
| SysFreeString(path); |
| return nsres; |
| } |
| |
| static nsresult NSAPI nsURL_SetDirectory(nsIURL *iface, const nsACString *aDirectory) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| |
| WARN("(%p)->(%s)\n", This, debugstr_nsacstr(aDirectory)); |
| |
| /* Not implemented by Gecko */ |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsURL_GetFileName(nsIURL *iface, nsACString *aFileName) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| const WCHAR *file; |
| BSTR path; |
| nsresult nsres; |
| |
| TRACE("(%p)->(%p)\n", This, aFileName); |
| |
| nsres = get_uri_path(This, &path, &file, NULL); |
| if(NS_FAILED(nsres)) |
| return nsres; |
| |
| nsres = return_wstr_nsacstr(aFileName, file, -1); |
| SysFreeString(path); |
| return nsres; |
| } |
| |
| static nsresult NSAPI nsURL_SetFileName(nsIURL *iface, const nsACString *aFileName) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| FIXME("(%p)->(%s)\n", This, debugstr_nsacstr(aFileName)); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsURL_GetFileBaseName(nsIURL *iface, nsACString *aFileBaseName) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| const WCHAR *file, *ext; |
| BSTR path; |
| nsresult nsres; |
| |
| TRACE("(%p)->(%p)\n", This, aFileBaseName); |
| |
| nsres = get_uri_path(This, &path, &file, &ext); |
| if(NS_FAILED(nsres)) |
| return nsres; |
| |
| nsres = return_wstr_nsacstr(aFileBaseName, file, ext-file); |
| SysFreeString(path); |
| return nsres; |
| } |
| |
| static nsresult NSAPI nsURL_SetFileBaseName(nsIURL *iface, const nsACString *aFileBaseName) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| FIXME("(%p)->(%s)\n", This, debugstr_nsacstr(aFileBaseName)); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsURL_GetFileExtension(nsIURL *iface, nsACString *aFileExtension) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aFileExtension); |
| |
| return get_uri_string(This, Uri_PROPERTY_EXTENSION, aFileExtension); |
| } |
| |
| static nsresult NSAPI nsURL_SetFileExtension(nsIURL *iface, const nsACString *aFileExtension) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| FIXME("(%p)->(%s)\n", This, debugstr_nsacstr(aFileExtension)); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsURL_GetCommonBaseSpec(nsIURL *iface, nsIURI *aURIToCompare, nsACString *_retval) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| FIXME("(%p)->(%p %p)\n", This, aURIToCompare, _retval); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsURL_GetRelativeSpec(nsIURL *iface, nsIURI *aURIToCompare, nsACString *_retval) |
| { |
| nsWineURI *This = impl_from_nsIURL(iface); |
| FIXME("(%p)->(%p %p)\n", This, aURIToCompare, _retval); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static const nsIURLVtbl nsURLVtbl = { |
| nsURI_QueryInterface, |
| nsURI_AddRef, |
| nsURI_Release, |
| nsURI_GetSpec, |
| nsURI_SetSpec, |
| nsURI_GetPrePath, |
| nsURI_GetScheme, |
| nsURI_SetScheme, |
| nsURI_GetUserPass, |
| nsURI_SetUserPass, |
| nsURI_GetUsername, |
| nsURI_SetUsername, |
| nsURI_GetPassword, |
| nsURI_SetPassword, |
| nsURI_GetHostPort, |
| nsURI_SetHostPort, |
| nsURI_GetHost, |
| nsURI_SetHost, |
| nsURI_GetPort, |
| nsURI_SetPort, |
| nsURI_GetPath, |
| nsURI_SetPath, |
| nsURI_Equals, |
| nsURI_SchemeIs, |
| nsURI_Clone, |
| nsURI_Resolve, |
| nsURI_GetAsciiSpec, |
| nsURI_GetAsciiHost, |
| nsURI_GetOriginCharset, |
| nsURL_GetRef, |
| nsURL_SetRef, |
| nsURI_EqualsExceptRef, |
| nsURI_CloneIgnoreRef, |
| nsURI_GetSpecIgnoringRef, |
| nsURI_GetHasRef, |
| nsURL_GetFilePath, |
| nsURL_SetFilePath, |
| nsURL_GetQuery, |
| nsURL_SetQuery, |
| nsURL_GetDirectory, |
| nsURL_SetDirectory, |
| nsURL_GetFileName, |
| nsURL_SetFileName, |
| nsURL_GetFileBaseName, |
| nsURL_SetFileBaseName, |
| nsURL_GetFileExtension, |
| nsURL_SetFileExtension, |
| nsURL_GetCommonBaseSpec, |
| nsURL_GetRelativeSpec |
| }; |
| |
| static inline nsWineURI *impl_from_nsIStandardURL(nsIStandardURL *iface) |
| { |
| return CONTAINING_RECORD(iface, nsWineURI, nsIStandardURL_iface); |
| } |
| |
| static nsresult NSAPI nsStandardURL_QueryInterface(nsIStandardURL *iface, nsIIDRef riid, |
| void **result) |
| { |
| nsWineURI *This = impl_from_nsIStandardURL(iface); |
| return nsIURL_QueryInterface(&This->nsIURL_iface, riid, result); |
| } |
| |
| static nsrefcnt NSAPI nsStandardURL_AddRef(nsIStandardURL *iface) |
| { |
| nsWineURI *This = impl_from_nsIStandardURL(iface); |
| return nsIURL_AddRef(&This->nsIURL_iface); |
| } |
| |
| static nsrefcnt NSAPI nsStandardURL_Release(nsIStandardURL *iface) |
| { |
| nsWineURI *This = impl_from_nsIStandardURL(iface); |
| return nsIURL_Release(&This->nsIURL_iface); |
| } |
| |
| static nsresult NSAPI nsStandardURL_GetMutable(nsIStandardURL *iface, cpp_bool *aMutable) |
| { |
| nsWineURI *This = impl_from_nsIStandardURL(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aMutable); |
| |
| *aMutable = This->is_mutable; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsStandardURL_SetMutable(nsIStandardURL *iface, cpp_bool aMutable) |
| { |
| nsWineURI *This = impl_from_nsIStandardURL(iface); |
| |
| TRACE("(%p)->(%x)\n", This, aMutable); |
| |
| This->is_mutable = aMutable; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsStandardURL_Init(nsIStandardURL *iface, PRUint32 aUrlType, PRInt32 aDefaultPort, |
| const nsACString *aSpec, const char *aOriginCharset, nsIURI *aBaseURI) |
| { |
| nsWineURI *This = impl_from_nsIStandardURL(iface); |
| FIXME("(%p)->(%d %d %s %s %p)\n", This, aUrlType, aDefaultPort, debugstr_nsacstr(aSpec), debugstr_a(aOriginCharset), aBaseURI); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static const nsIStandardURLVtbl nsStandardURLVtbl = { |
| nsStandardURL_QueryInterface, |
| nsStandardURL_AddRef, |
| nsStandardURL_Release, |
| nsStandardURL_GetMutable, |
| nsStandardURL_SetMutable, |
| nsStandardURL_Init |
| }; |
| |
| static nsresult create_nsuri(IUri *iuri, HTMLOuterWindow *window, NSContainer *container, nsWineURI **_retval) |
| { |
| nsWineURI *ret = heap_alloc_zero(sizeof(nsWineURI)); |
| |
| ret->nsIURL_iface.lpVtbl = &nsURLVtbl; |
| ret->nsIStandardURL_iface.lpVtbl = &nsStandardURLVtbl; |
| ret->ref = 1; |
| ret->is_mutable = TRUE; |
| |
| set_uri_nscontainer(ret, container); |
| set_uri_window(ret, window); |
| |
| IUri_AddRef(iuri); |
| ret->uri = iuri; |
| |
| TRACE("retval=%p\n", ret); |
| *_retval = ret; |
| return NS_OK; |
| } |
| |
| HRESULT create_doc_uri(HTMLOuterWindow *window, WCHAR *url, nsWineURI **ret) |
| { |
| nsWineURI *uri; |
| IUri *iuri; |
| nsresult nsres; |
| HRESULT hres; |
| |
| hres = CreateUri(url, 0, 0, &iuri); |
| if(FAILED(hres)) |
| return hres; |
| |
| nsres = create_nsuri(iuri, window, window->doc_obj->nscontainer, &uri); |
| IUri_Release(iuri); |
| if(NS_FAILED(nsres)) |
| return E_FAIL; |
| |
| uri->is_doc_uri = TRUE; |
| |
| *ret = uri; |
| return S_OK; |
| } |
| |
| static nsresult create_nschannel(nsWineURI *uri, nsChannel **ret) |
| { |
| nsChannel *channel; |
| HRESULT hres; |
| |
| if(!ensure_uri(uri)) |
| return NS_ERROR_UNEXPECTED; |
| |
| channel = heap_alloc_zero(sizeof(nsChannel)); |
| if(!channel) |
| return NS_ERROR_OUT_OF_MEMORY; |
| |
| channel->nsIHttpChannel_iface.lpVtbl = &nsChannelVtbl; |
| channel->nsIUploadChannel_iface.lpVtbl = &nsUploadChannelVtbl; |
| channel->nsIHttpChannelInternal_iface.lpVtbl = &nsHttpChannelInternalVtbl; |
| channel->ref = 1; |
| channel->request_method = METHOD_GET; |
| list_init(&channel->response_headers); |
| list_init(&channel->request_headers); |
| |
| nsIURL_AddRef(&uri->nsIURL_iface); |
| channel->uri = uri; |
| |
| hres = IUri_GetScheme(uri->uri, &channel->url_scheme); |
| if(FAILED(hres)) |
| channel->url_scheme = URL_SCHEME_UNKNOWN; |
| |
| *ret = channel; |
| return NS_OK; |
| } |
| |
| HRESULT create_redirect_nschannel(const WCHAR *url, nsChannel *orig_channel, nsChannel **ret) |
| { |
| HTMLOuterWindow *window = NULL; |
| nsChannel *channel; |
| nsWineURI *uri; |
| IUri *iuri; |
| nsresult nsres; |
| HRESULT hres; |
| |
| hres = CreateUri(url, 0, 0, &iuri); |
| if(FAILED(hres)) |
| return hres; |
| |
| if(orig_channel->uri->window_ref) |
| window = orig_channel->uri->window_ref->window; |
| nsres = create_nsuri(iuri, window, NULL, &uri); |
| IUri_Release(iuri); |
| if(NS_FAILED(nsres)) |
| return E_FAIL; |
| |
| nsres = create_nschannel(uri, &channel); |
| nsIURL_Release(&uri->nsIURL_iface); |
| if(NS_FAILED(nsres)) |
| return E_FAIL; |
| |
| if(orig_channel->load_group) { |
| nsILoadGroup_AddRef(orig_channel->load_group); |
| channel->load_group = orig_channel->load_group; |
| } |
| |
| if(orig_channel->notif_callback) { |
| nsIInterfaceRequestor_AddRef(orig_channel->notif_callback); |
| channel->notif_callback = orig_channel->notif_callback; |
| } |
| |
| channel->load_flags = orig_channel->load_flags | LOAD_REPLACE; |
| |
| if(orig_channel->request_method == METHOD_POST) |
| FIXME("unsupported POST method\n"); |
| |
| if(orig_channel->original_uri) { |
| nsIURI_AddRef(orig_channel->original_uri); |
| channel->original_uri = orig_channel->original_uri; |
| } |
| |
| if(orig_channel->referrer) { |
| nsIURI_AddRef(orig_channel->referrer); |
| channel->referrer = orig_channel->referrer; |
| } |
| |
| *ret = channel; |
| return S_OK; |
| } |
| |
| typedef struct { |
| nsIProtocolHandler nsIProtocolHandler_iface; |
| |
| LONG ref; |
| |
| nsIProtocolHandler *nshandler; |
| } nsProtocolHandler; |
| |
| static inline nsProtocolHandler *impl_from_nsIProtocolHandler(nsIProtocolHandler *iface) |
| { |
| return CONTAINING_RECORD(iface, nsProtocolHandler, nsIProtocolHandler_iface); |
| } |
| |
| static nsresult NSAPI nsProtocolHandler_QueryInterface(nsIProtocolHandler *iface, nsIIDRef riid, |
| void **result) |
| { |
| nsProtocolHandler *This = impl_from_nsIProtocolHandler(iface); |
| |
| *result = NULL; |
| |
| if(IsEqualGUID(&IID_nsISupports, riid)) { |
| TRACE("(%p)->(IID_nsISupports %p)\n", This, result); |
| *result = &This->nsIProtocolHandler_iface; |
| }else if(IsEqualGUID(&IID_nsIProtocolHandler, riid)) { |
| TRACE("(%p)->(IID_nsIProtocolHandler %p)\n", This, result); |
| *result = &This->nsIProtocolHandler_iface; |
| }else if(IsEqualGUID(&IID_nsIExternalProtocolHandler, riid)) { |
| TRACE("(%p)->(IID_nsIExternalProtocolHandler %p), returning NULL\n", This, result); |
| return NS_NOINTERFACE; |
| } |
| |
| if(*result) { |
| nsISupports_AddRef((nsISupports*)*result); |
| return NS_OK; |
| } |
| |
| WARN("(%s %p)\n", debugstr_guid(riid), result); |
| return NS_NOINTERFACE; |
| } |
| |
| static nsrefcnt NSAPI nsProtocolHandler_AddRef(nsIProtocolHandler *iface) |
| { |
| nsProtocolHandler *This = impl_from_nsIProtocolHandler(iface); |
| LONG ref = InterlockedIncrement(&This->ref); |
| |
| TRACE("(%p) ref=%d\n", This, ref); |
| |
| return ref; |
| } |
| |
| static nsrefcnt NSAPI nsProtocolHandler_Release(nsIProtocolHandler *iface) |
| { |
| nsProtocolHandler *This = impl_from_nsIProtocolHandler(iface); |
| LONG ref = InterlockedDecrement(&This->ref); |
| |
| TRACE("(%p) ref=%d\n", This, ref); |
| |
| if(!ref) { |
| if(This->nshandler) |
| nsIProtocolHandler_Release(This->nshandler); |
| heap_free(This); |
| } |
| |
| return ref; |
| } |
| |
| static nsresult NSAPI nsProtocolHandler_GetScheme(nsIProtocolHandler *iface, nsACString *aScheme) |
| { |
| nsProtocolHandler *This = impl_from_nsIProtocolHandler(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aScheme); |
| |
| if(This->nshandler) |
| return nsIProtocolHandler_GetScheme(This->nshandler, aScheme); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsProtocolHandler_GetDefaultPort(nsIProtocolHandler *iface, |
| PRInt32 *aDefaultPort) |
| { |
| nsProtocolHandler *This = impl_from_nsIProtocolHandler(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aDefaultPort); |
| |
| if(This->nshandler) |
| return nsIProtocolHandler_GetDefaultPort(This->nshandler, aDefaultPort); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsProtocolHandler_GetProtocolFlags(nsIProtocolHandler *iface, |
| PRUint32 *aProtocolFlags) |
| { |
| nsProtocolHandler *This = impl_from_nsIProtocolHandler(iface); |
| |
| TRACE("(%p)->(%p)\n", This, aProtocolFlags); |
| |
| if(This->nshandler) |
| return nsIProtocolHandler_GetProtocolFlags(This->nshandler, aProtocolFlags); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsProtocolHandler_NewURI(nsIProtocolHandler *iface, |
| const nsACString *aSpec, const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval) |
| { |
| nsProtocolHandler *This = impl_from_nsIProtocolHandler(iface); |
| |
| TRACE("((%p)->%s %s %p %p)\n", This, debugstr_nsacstr(aSpec), debugstr_a(aOriginCharset), |
| aBaseURI, _retval); |
| |
| if(This->nshandler) |
| return nsIProtocolHandler_NewURI(This->nshandler, aSpec, aOriginCharset, aBaseURI, _retval); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsProtocolHandler_NewChannel(nsIProtocolHandler *iface, |
| nsIURI *aURI, nsIChannel **_retval) |
| { |
| nsProtocolHandler *This = impl_from_nsIProtocolHandler(iface); |
| |
| TRACE("(%p)->(%p %p)\n", This, aURI, _retval); |
| |
| if(This->nshandler) |
| return nsIProtocolHandler_NewChannel(This->nshandler, aURI, _retval); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static nsresult NSAPI nsProtocolHandler_AllowPort(nsIProtocolHandler *iface, |
| PRInt32 port, const char *scheme, cpp_bool *_retval) |
| { |
| nsProtocolHandler *This = impl_from_nsIProtocolHandler(iface); |
| |
| TRACE("(%p)->(%d %s %p)\n", This, port, debugstr_a(scheme), _retval); |
| |
| if(This->nshandler) |
| return nsIProtocolHandler_AllowPort(This->nshandler, port, scheme, _retval); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| static const nsIProtocolHandlerVtbl nsProtocolHandlerVtbl = { |
| nsProtocolHandler_QueryInterface, |
| nsProtocolHandler_AddRef, |
| nsProtocolHandler_Release, |
| nsProtocolHandler_GetScheme, |
| nsProtocolHandler_GetDefaultPort, |
| nsProtocolHandler_GetProtocolFlags, |
| nsProtocolHandler_NewURI, |
| nsProtocolHandler_NewChannel, |
| nsProtocolHandler_AllowPort |
| }; |
| |
| static nsIProtocolHandler *create_protocol_handler(nsIProtocolHandler *nshandler) |
| { |
| nsProtocolHandler *ret = heap_alloc(sizeof(nsProtocolHandler)); |
| |
| ret->nsIProtocolHandler_iface.lpVtbl = &nsProtocolHandlerVtbl; |
| ret->ref = 1; |
| ret->nshandler = nshandler; |
| |
| return &ret->nsIProtocolHandler_iface; |
| } |
| |
| static nsresult NSAPI nsIOService_QueryInterface(nsIIOService*,nsIIDRef,void**); |
| |
| static nsrefcnt NSAPI nsIOService_AddRef(nsIIOService *iface) |
| { |
| return 2; |
| } |
| |
| static nsrefcnt NSAPI nsIOService_Release(nsIIOService *iface) |
| { |
| return 1; |
| } |
| |
| static nsresult NSAPI nsIOService_GetProtocolHandler(nsIIOService *iface, const char *aScheme, |
| nsIProtocolHandler **_retval) |
| { |
| nsIExternalProtocolHandler *nsexthandler; |
| nsIProtocolHandler *nshandler; |
| nsresult nsres; |
| |
| TRACE("(%s %p)\n", debugstr_a(aScheme), _retval); |
| |
| nsres = nsIIOService_GetProtocolHandler(nsio, aScheme, &nshandler); |
| if(NS_FAILED(nsres)) { |
| WARN("GetProtocolHandler failed: %08x\n", nsres); |
| return nsres; |
| } |
| |
| nsres = nsIProtocolHandler_QueryInterface(nshandler, &IID_nsIExternalProtocolHandler, |
| (void**)&nsexthandler); |
| if(NS_FAILED(nsres)) { |
| *_retval = nshandler; |
| return NS_OK; |
| } |
| |
| nsIExternalProtocolHandler_Release(nsexthandler); |
| *_retval = create_protocol_handler(nshandler); |
| TRACE("return %p\n", *_retval); |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsIOService_GetProtocolFlags(nsIIOService *iface, const char *aScheme, |
| PRUint32 *_retval) |
| { |
| TRACE("(%s %p)\n", debugstr_a(aScheme), _retval); |
| return nsIIOService_GetProtocolFlags(nsio, aScheme, _retval); |
| } |
| |
| static BOOL is_gecko_special_uri(const char *spec) |
| { |
| static const char *special_schemes[] = {"chrome:", "jar:", "moz-safe-about", "resource:", "javascript:", "wyciwyg:"}; |
| int i; |
| |
| for(i=0; i < sizeof(special_schemes)/sizeof(*special_schemes); i++) { |
| if(!strncasecmp(spec, special_schemes[i], strlen(special_schemes[i]))) |
| return TRUE; |
| } |
| |
| if(!strncasecmp(spec, "file:", 5)) { |
| const char *ptr = spec+5; |
| while(*ptr == '/') |
| ptr++; |
| return is_gecko_path(ptr); |
| } |
| |
| return FALSE; |
| } |
| |
| static nsresult NSAPI nsIOService_NewURI(nsIIOService *iface, const nsACString *aSpec, |
| const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval) |
| { |
| nsWineURI *wine_uri, *base_wine_uri = NULL; |
| WCHAR new_spec[INTERNET_MAX_URL_LENGTH]; |
| HTMLOuterWindow *window = NULL; |
| const char *spec = NULL; |
| IUri *urlmon_uri; |
| nsresult nsres; |
| HRESULT hres; |
| |
| TRACE("(%s %s %p %p)\n", debugstr_nsacstr(aSpec), debugstr_a(aOriginCharset), |
| aBaseURI, _retval); |
| |
| nsACString_GetData(aSpec, &spec); |
| if(is_gecko_special_uri(spec)) |
| return nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, _retval); |
| |
| if(!strncmp(spec, "wine:", 5)) |
| spec += 5; |
| |
| if(aBaseURI) { |
| nsres = nsIURI_QueryInterface(aBaseURI, &IID_nsWineURI, (void**)&base_wine_uri); |
| if(NS_SUCCEEDED(nsres)) { |
| if(!ensure_uri(base_wine_uri)) |
| return NS_ERROR_UNEXPECTED; |
| if(base_wine_uri->window_ref) |
| window = base_wine_uri->window_ref->window; |
| }else { |
| WARN("Could not get base nsWineURI: %08x\n", nsres); |
| } |
| } |
| |
| MultiByteToWideChar(CP_ACP, 0, spec, -1, new_spec, sizeof(new_spec)/sizeof(WCHAR)); |
| |
| if(base_wine_uri) { |
| hres = CoInternetCombineUrlEx(base_wine_uri->uri, new_spec, URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO, |
| &urlmon_uri, 0); |
| if(FAILED(hres)) |
| WARN("CoInternetCombineUrlEx failed: %08x\n", hres); |
| }else { |
| hres = CreateUri(new_spec, 0, 0, &urlmon_uri); |
| if(FAILED(hres)) |
| WARN("CreateUri failed: %08x\n", hres); |
| } |
| |
| if(FAILED(hres)) |
| return nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, _retval); |
| |
| nsres = create_nsuri(urlmon_uri, window, NULL, &wine_uri); |
| IUri_Release(urlmon_uri); |
| if(base_wine_uri) |
| nsIURI_Release(&base_wine_uri->nsIURL_iface); |
| if(NS_FAILED(nsres)) |
| return nsres; |
| |
| *_retval = (nsIURI*)&wine_uri->nsIURL_iface; |
| return nsres; |
| } |
| |
| static nsresult NSAPI nsIOService_NewFileURI(nsIIOService *iface, nsIFile *aFile, |
| nsIURI **_retval) |
| { |
| TRACE("(%p %p)\n", aFile, _retval); |
| return nsIIOService_NewFileURI(nsio, aFile, _retval); |
| } |
| |
| static nsresult NSAPI nsIOService_NewChannelFromURI(nsIIOService *iface, nsIURI *aURI, |
| nsIChannel **_retval) |
| { |
| nsWineURI *wine_uri; |
| nsChannel *ret; |
| nsresult nsres; |
| |
| TRACE("(%p %p)\n", aURI, _retval); |
| |
| nsres = nsIURI_QueryInterface(aURI, &IID_nsWineURI, (void**)&wine_uri); |
| if(NS_FAILED(nsres)) { |
| TRACE("Could not get nsWineURI: %08x\n", nsres); |
| return nsIIOService_NewChannelFromURI(nsio, aURI, _retval); |
| } |
| |
| nsres = create_nschannel(wine_uri, &ret); |
| nsIURL_Release(&wine_uri->nsIURL_iface); |
| if(NS_FAILED(nsres)) |
| return nsres; |
| |
| nsIURI_AddRef(aURI); |
| ret->original_uri = aURI; |
| |
| *_retval = (nsIChannel*)&ret->nsIHttpChannel_iface; |
| return NS_OK; |
| } |
| |
| static nsresult NSAPI nsIOService_NewChannel(nsIIOService *iface, const nsACString *aSpec, |
| const char *aOriginCharset, nsIURI *aBaseURI, nsIChannel **_retval) |
| { |
| TRACE("(%s %s %p %p)\n", debugstr_nsacstr(aSpec), debugstr_a(aOriginCharset), aBaseURI, _retval); |
| return nsIIOService_NewChannel(nsio, aSpec, aOriginCharset, aBaseURI, _retval); |
| } |
| |
| static nsresult NSAPI nsIOService_GetOffline(nsIIOService *iface, cpp_bool *aOffline) |
| { |
| TRACE("(%p)\n", aOffline); |
| return nsIIOService_GetOffline(nsio, aOffline); |
| } |
| |
| static nsresult NSAPI nsIOService_SetOffline(nsIIOService *iface, cpp_bool aOffline) |
| { |
| TRACE("(%x)\n", aOffline); |
| return nsIIOService_SetOffline(nsio, aOffline); |
| } |
| |
| static nsresult NSAPI nsIOService_AllowPort(nsIIOService *iface, PRInt32 aPort, |
| const char *aScheme, cpp_bool *_retval) |
| { |
| TRACE("(%d %s %p)\n", aPort, debugstr_a(aScheme), _retval); |
| return nsIIOService_AllowPort(nsio, aPort, debugstr_a(aScheme), _retval); |
| } |
| |
| static nsresult NSAPI nsIOService_ExtractScheme(nsIIOService *iface, const nsACString *urlString, |
| nsACString * _retval) |
| { |
| TRACE("(%s %p)\n", debugstr_nsacstr(urlString), _retval); |
| return nsIIOService_ExtractScheme(nsio, urlString, _retval); |
| } |
| |
| static const nsIIOServiceVtbl nsIOServiceVtbl = { |
| nsIOService_QueryInterface, |
| nsIOService_AddRef, |
| nsIOService_Release, |
| nsIOService_GetProtocolHandler, |
| nsIOService_GetProtocolFlags, |
| nsIOService_NewURI, |
| nsIOService_NewFileURI, |
| nsIOService_NewChannelFromURI, |
| nsIOService_NewChannel, |
| nsIOService_GetOffline, |
| nsIOService_SetOffline, |
| nsIOService_AllowPort, |
| nsIOService_ExtractScheme |
| }; |
| |
| static nsIIOService nsIOService = { &nsIOServiceVtbl }; |
| |
| static nsresult NSAPI nsNetUtil_QueryInterface(nsINetUtil *iface, nsIIDRef riid, |
| void **result) |
| { |
| return nsIIOService_QueryInterface(&nsIOService, riid, result); |
| } |
| |
| static nsrefcnt NSAPI nsNetUtil_AddRef(nsINetUtil *iface) |
| { |
| return 2; |
| } |
| |
| static nsrefcnt NSAPI nsNetUtil_Release(nsINetUtil *iface) |
| { |
| return 1; |
| } |
| |
| static nsresult NSAPI nsNetUtil_ParseContentType(nsINetUtil *iface, const nsACString *aTypeHeader, |
| nsACString *aCharset, cpp_bool *aHadCharset, nsACString *aContentType) |
| { |
| TRACE("(%s %p %p %p)\n", debugstr_nsacstr(aTypeHeader), aCharset, aHadCharset, aContentType); |
| |
| return nsINetUtil_ParseContentType(net_util, aTypeHeader, aCharset, aHadCharset, aContentType); |
| } |
| |
| static nsresult NSAPI nsNetUtil_ProtocolHasFlags(nsINetUtil *iface, nsIURI *aURI, PRUint32 aFlags, cpp_bool *_retval) |
| { |
| TRACE("()\n"); |
| |
| return nsINetUtil_ProtocolHasFlags(net_util, aURI, aFlags, _retval); |
| } |
| |
| static nsresult NSAPI nsNetUtil_URIChainHasFlags(nsINetUtil *iface, nsIURI *aURI, PRUint32 aFlags, cpp_bool *_retval) |
| { |
| TRACE("(%p %08x %p)\n", aURI, aFlags, _retval); |
| |
| if(aFlags == (1<<11)) { |
| *_retval = FALSE; |
| return NS_OK; |
| } |
| |
| return nsINetUtil_URIChainHasFlags(net_util, aURI, aFlags, _retval); |
| } |
| |
| static nsresult NSAPI nsNetUtil_ToImmutableURI(nsINetUtil *iface, nsIURI *aURI, nsIURI **_retval) |
| { |
| TRACE("(%p %p)\n", aURI, _retval); |
| |
| return nsINetUtil_ToImmutableURI(net_util, aURI, _retval); |
| } |
| |
| static nsresult NSAPI nsNetUtil_NewSimpleNestedURI(nsINetUtil *iface, nsIURI *aURI, nsIURI **_retval) |
| { |
| TRACE("(%p %p)\n", aURI, _retval); |
| |
| return nsINetUtil_NewSimpleNestedURI(net_util, aURI, _retval); |
| } |
| |
| static nsresult NSAPI nsNetUtil_EscapeString(nsINetUtil *iface, const nsACString *aString, |
| PRUint32 aEscapeType, nsACString *_retval) |
| { |
| TRACE("(%s %x %p)\n", debugstr_nsacstr(aString), aEscapeType, _retval); |
| |
| return nsINetUtil_EscapeString(net_util, aString, aEscapeType, _retval); |
| } |
| |
| static nsresult NSAPI nsNetUtil_EscapeURL(nsINetUtil *iface, const nsACString *aStr, PRUint32 aFlags, |
| nsACString *_retval) |
| { |
| TRACE("(%s %08x %p)\n", debugstr_nsacstr(aStr), aFlags, _retval); |
| |
| return nsINetUtil_EscapeURL(net_util, aStr, aFlags, _retval); |
| } |
| |
| static nsresult NSAPI nsNetUtil_UnescapeString(nsINetUtil *iface, const nsACString *aStr, |
| PRUint32 aFlags, nsACString *_retval) |
| { |
| TRACE("(%s %08x %p)\n", debugstr_nsacstr(aStr), aFlags, _retval); |
| |
| return nsINetUtil_UnescapeString(net_util, aStr, aFlags, _retval); |
| } |
| |
| static nsresult NSAPI nsNetUtil_ExtractCharsetFromContentType(nsINetUtil *iface, const nsACString *aTypeHeader, |
| nsACString *aCharset, PRInt32 *aCharsetStart, PRInt32 *aCharsetEnd, cpp_bool *_retval) |
| { |
| TRACE("(%s %p %p %p %p)\n", debugstr_nsacstr(aTypeHeader), aCharset, aCharsetStart, |
| aCharsetEnd, _retval); |
| |
| return nsINetUtil_ExtractCharsetFromContentType(net_util, aTypeHeader, aCharset, aCharsetStart, aCharsetEnd, _retval); |
| } |
| |
| static const nsINetUtilVtbl nsNetUtilVtbl = { |
| nsNetUtil_QueryInterface, |
| nsNetUtil_AddRef, |
| nsNetUtil_Release, |
| nsNetUtil_ParseContentType, |
| nsNetUtil_ProtocolHasFlags, |
| nsNetUtil_URIChainHasFlags, |
| nsNetUtil_ToImmutableURI, |
| nsNetUtil_NewSimpleNestedURI, |
| nsNetUtil_EscapeString, |
| nsNetUtil_EscapeURL, |
| nsNetUtil_UnescapeString, |
| nsNetUtil_ExtractCharsetFromContentType |
| }; |
| |
| static nsINetUtil nsNetUtil = { &nsNetUtilVtbl }; |
| |
| static nsresult NSAPI nsIOService_QueryInterface(nsIIOService *iface, nsIIDRef riid, |
| void **result) |
| { |
| *result = NULL; |
| |
| if(IsEqualGUID(&IID_nsISupports, riid)) |
| *result = &nsIOService; |
| else if(IsEqualGUID(&IID_nsIIOService, riid)) |
| *result = &nsIOService; |
| else if(IsEqualGUID(&IID_nsINetUtil, riid)) |
| *result = &nsNetUtil; |
| |
| if(*result) { |
| nsISupports_AddRef((nsISupports*)*result); |
| return NS_OK; |
| } |
| |
| FIXME("(%s %p)\n", debugstr_guid(riid), result); |
| return NS_NOINTERFACE; |
| } |
| |
| static nsresult NSAPI nsIOServiceFactory_QueryInterface(nsIFactory *iface, nsIIDRef riid, |
| void **result) |
| { |
| *result = NULL; |
| |
| if(IsEqualGUID(&IID_nsISupports, riid)) { |
| TRACE("(IID_nsISupports %p)\n", result); |
| *result = iface; |
| }else if(IsEqualGUID(&IID_nsIFactory, riid)) { |
| TRACE("(IID_nsIFactory %p)\n", result); |
| *result = iface; |
| } |
| |
| if(*result) { |
| nsIFactory_AddRef(iface); |
| return NS_OK; |
| } |
| |
| WARN("(%s %p)\n", debugstr_guid(riid), result); |
| return NS_NOINTERFACE; |
| } |
| |
| static nsrefcnt NSAPI nsIOServiceFactory_AddRef(nsIFactory *iface) |
| { |
| return 2; |
| } |
| |
| static nsrefcnt NSAPI nsIOServiceFactory_Release(nsIFactory *iface) |
| { |
| return 1; |
| } |
| |
| static nsresult NSAPI nsIOServiceFactory_CreateInstance(nsIFactory *iface, |
| nsISupports *aOuter, const nsIID *iid, void **result) |
| { |
| return nsIIOService_QueryInterface(&nsIOService, iid, result); |
| } |
| |
| static nsresult NSAPI nsIOServiceFactory_LockFactory(nsIFactory *iface, cpp_bool lock) |
| { |
| WARN("(%x)\n", lock); |
| return NS_OK; |
| } |
| |
| static const nsIFactoryVtbl nsIOServiceFactoryVtbl = { |
| nsIOServiceFactory_QueryInterface, |
| nsIOServiceFactory_AddRef, |
| nsIOServiceFactory_Release, |
| nsIOServiceFactory_CreateInstance, |
| nsIOServiceFactory_LockFactory |
| }; |
| |
| static nsIFactory nsIOServiceFactory = { &nsIOServiceFactoryVtbl }; |
| |
| static BOOL translate_url(HTMLDocumentObj *doc, nsWineURI *uri) |
| { |
| OLECHAR *new_url = NULL; |
| WCHAR *url; |
| BOOL ret = FALSE; |
| HRESULT hres; |
| |
| if(!doc->hostui || !ensure_uri(uri)) |
| return FALSE; |
| |
| hres = IUri_GetDisplayUri(uri->uri, &url); |
| if(FAILED(hres)) |
| return FALSE; |
| |
| hres = IDocHostUIHandler_TranslateUrl(doc->hostui, 0, url, &new_url); |
| if(hres == S_OK && new_url) { |
| if(strcmpW(url, new_url)) { |
| FIXME("TranslateUrl returned new URL %s -> %s\n", debugstr_w(url), debugstr_w(new_url)); |
| ret = TRUE; |
| } |
| CoTaskMemFree(new_url); |
| } |
| |
| SysFreeString(url); |
| return ret; |
| } |
| |
| nsresult on_start_uri_open(NSContainer *nscontainer, nsIURI *uri, cpp_bool *_retval) |
| { |
| nsWineURI *wine_uri; |
| nsresult nsres; |
| |
| *_retval = FALSE; |
| |
| nsres = nsIURI_QueryInterface(uri, &IID_nsWineURI, (void**)&wine_uri); |
| if(NS_FAILED(nsres)) { |
| WARN("Could not get nsWineURI: %08x\n", nsres); |
| return NS_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| if(!wine_uri->is_doc_uri) { |
| wine_uri->is_doc_uri = TRUE; |
| |
| if(!wine_uri->container) { |
| nsIWebBrowserChrome_AddRef(&nscontainer->nsIWebBrowserChrome_iface); |
| wine_uri->container = nscontainer; |
| } |
| |
| if(nscontainer->doc) |
| *_retval = translate_url(nscontainer->doc, wine_uri); |
| } |
| |
| nsIURI_Release(&wine_uri->nsIURL_iface); |
| return NS_OK; |
| } |
| |
| void init_nsio(nsIComponentManager *component_manager, nsIComponentRegistrar *registrar) |
| { |
| nsIFactory *old_factory = NULL; |
| nsresult nsres; |
| |
| nsres = nsIComponentManager_GetClassObject(component_manager, &NS_IOSERVICE_CID, |
| &IID_nsIFactory, (void**)&old_factory); |
| if(NS_FAILED(nsres)) { |
| ERR("Could not get factory: %08x\n", nsres); |
| return; |
| } |
| |
| nsres = nsIFactory_CreateInstance(old_factory, NULL, &IID_nsIIOService, (void**)&nsio); |
| if(NS_FAILED(nsres)) { |
| ERR("Couldn not create nsIOService instance %08x\n", nsres); |
| nsIFactory_Release(old_factory); |
| return; |
| } |
| |
| nsres = nsIIOService_QueryInterface(nsio, &IID_nsINetUtil, (void**)&net_util); |
| if(NS_FAILED(nsres)) { |
| WARN("Could not get nsINetUtil interface: %08x\n", nsres); |
| nsIIOService_Release(nsio); |
| return; |
| } |
| |
| nsres = nsIComponentRegistrar_UnregisterFactory(registrar, &NS_IOSERVICE_CID, old_factory); |
| nsIFactory_Release(old_factory); |
| if(NS_FAILED(nsres)) |
| ERR("UnregisterFactory failed: %08x\n", nsres); |
| |
| nsres = nsIComponentRegistrar_RegisterFactory(registrar, &NS_IOSERVICE_CID, |
| NS_IOSERVICE_CLASSNAME, NS_IOSERVICE_CONTRACTID, &nsIOServiceFactory); |
| if(NS_FAILED(nsres)) |
| ERR("RegisterFactory failed: %08x\n", nsres); |
| } |
| |
| void release_nsio(void) |
| { |
| if(net_util) { |
| nsINetUtil_Release(net_util); |
| net_util = NULL; |
| } |
| |
| if(nsio) { |
| nsIIOService_Release(nsio); |
| nsio = NULL; |
| } |
| } |