mshtml: Move mime to HTMLDocumentObj.
[wine] / dlls / mshtml / nsio.c
1 /*
2  * Copyright 2006-2007 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20
21 #include <stdarg.h>
22
23 #define COBJMACROS
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "winreg.h"
29 #include "ole2.h"
30 #include "shlguid.h"
31 #include "wininet.h"
32 #include "shlwapi.h"
33
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
36
37 #include "mshtml_private.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
40
41 #define LOAD_INITIAL_DOCUMENT_URI 0x80000
42
43 #define NS_IOSERVICE_CLASSNAME "nsIOService"
44 #define NS_IOSERVICE_CONTRACTID "@mozilla.org/network/io-service;1"
45
46 static const IID NS_IOSERVICE_CID =
47     {0x9ac9e770, 0x18bc, 0x11d3, {0x93, 0x37, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40}};
48
49 static nsIIOService *nsio = NULL;
50 static nsINetUtil *net_util;
51
52 static const WCHAR about_blankW[] = {'a','b','o','u','t',':','b','l','a','n','k',0};
53
54 typedef struct {
55     const nsIWineURIVtbl *lpWineURIVtbl;
56
57     LONG ref;
58
59     nsIURI *uri;
60     nsIURL *nsurl;
61     NSContainer *container;
62     LPWSTR wine_url;
63     PRBool is_doc_uri;
64     BOOL use_wine_url;
65 } nsURI;
66
67 #define NSURI(x)         ((nsIURI*)            &(x)->lpWineURIVtbl)
68 #define NSWINEURI(x)     ((nsIWineURI*)        &(x)->lpWineURIVtbl)
69
70 static nsresult create_uri(nsIURI*,NSContainer*,nsIWineURI**);
71
72 static const char *debugstr_nsacstr(const nsACString *nsstr)
73 {
74     const char *data;
75
76     nsACString_GetData(nsstr, &data);
77     return debugstr_a(data);
78 }
79
80 HRESULT nsuri_to_url(LPCWSTR nsuri, BOOL ret_empty, BSTR *ret)
81 {
82     const WCHAR *ptr = nsuri;
83
84     static const WCHAR wine_prefixW[] = {'w','i','n','e',':'};
85
86     if(!strncmpW(nsuri, wine_prefixW, sizeof(wine_prefixW)/sizeof(WCHAR)))
87         ptr += sizeof(wine_prefixW)/sizeof(WCHAR);
88
89     if(*ptr || ret_empty) {
90         *ret = SysAllocString(ptr);
91         if(!*ret)
92             return E_OUTOFMEMORY;
93     }else {
94         *ret = NULL;
95     }
96
97     TRACE("%s -> %s\n", debugstr_w(nsuri), debugstr_w(*ret));
98     return S_OK;
99 }
100
101 static BOOL exec_shldocvw_67(HTMLDocumentObj *doc, LPCWSTR url)
102 {
103     IOleCommandTarget *cmdtrg = NULL;
104     HRESULT hres;
105
106     hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&cmdtrg);
107     if(SUCCEEDED(hres)) {
108         VARIANT varUrl, varRes;
109
110         V_VT(&varUrl) = VT_BSTR;
111         V_BSTR(&varUrl) = SysAllocString(url);
112         V_VT(&varRes) = VT_BOOL;
113
114         hres = IOleCommandTarget_Exec(cmdtrg, &CGID_ShellDocView, 67, 0, &varUrl, &varRes);
115
116         IOleCommandTarget_Release(cmdtrg);
117         SysFreeString(V_BSTR(&varUrl));
118
119         if(SUCCEEDED(hres) && !V_BOOL(&varRes)) {
120             TRACE("got VARIANT_FALSE, do not load\n");
121             return FALSE;
122         }
123     }
124
125     return TRUE;
126 }
127
128 static BOOL before_async_open(nsChannel *channel, NSContainer *container)
129 {
130     HTMLDocumentObj *doc = container->doc;
131     IServiceProvider *service_provider;
132     DWORD hlnf = 0;
133     LPCWSTR uri;
134     HRESULT hres;
135
136     nsIWineURI_GetWineURL(channel->uri, &uri);
137     if(!uri) {
138         ERR("GetWineURL returned NULL\n");
139         return TRUE;
140     }
141
142     if(!doc) {
143         NSContainer *container_iter = container;
144
145         hlnf = HLNF_OPENINNEWWINDOW;
146         while(!container_iter->doc)
147             container_iter = container_iter->parent;
148         doc = container_iter->doc;
149     }
150
151     if(!doc->client)
152         return TRUE;
153
154     if(!hlnf && !exec_shldocvw_67(doc, uri))
155         return FALSE;
156
157     hres = IOleClientSite_QueryInterface(doc->client, &IID_IServiceProvider,
158                                          (void**)&service_provider);
159     if(SUCCEEDED(hres)) {
160         IHlinkFrame *hlink_frame;
161
162         hres = IServiceProvider_QueryService(service_provider, &IID_IHlinkFrame,
163                                              &IID_IHlinkFrame, (void**)&hlink_frame);
164         IServiceProvider_Release(service_provider);
165         if(SUCCEEDED(hres)) {
166             hlink_frame_navigate(&doc->basedoc, hlink_frame, uri, channel->post_data_stream, hlnf);
167             IHlinkFrame_Release(hlink_frame);
168
169             return FALSE;
170         }
171     }
172
173     return TRUE;
174 }
175
176 #define NSCHANNEL_THIS(iface) DEFINE_THIS(nsChannel, HttpChannel, iface)
177
178 static nsresult NSAPI nsChannel_QueryInterface(nsIHttpChannel *iface, nsIIDRef riid, nsQIResult result)
179 {
180     nsChannel *This = NSCHANNEL_THIS(iface);
181
182     if(IsEqualGUID(&IID_nsISupports, riid)) {
183         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
184         *result = NSCHANNEL(This);
185     }else if(IsEqualGUID(&IID_nsIRequest, riid)) {
186         TRACE("(%p)->(IID_nsIRequest %p)\n", This, result);
187         *result = NSCHANNEL(This);
188     }else if(IsEqualGUID(&IID_nsIChannel, riid)) {
189         TRACE("(%p)->(IID_nsIChannel %p)\n", This, result);
190         *result = NSCHANNEL(This);
191     }else if(IsEqualGUID(&IID_nsIHttpChannel, riid)) {
192         TRACE("(%p)->(IID_nsIHttpChannel %p)\n", This, result);
193         *result = This->http_channel ? NSHTTPCHANNEL(This) : NULL;
194     }else if(IsEqualGUID(&IID_nsIUploadChannel, riid)) {
195         TRACE("(%p)->(IID_nsIUploadChannel %p)\n", This, result);
196         *result = NSUPCHANNEL(This);
197     }else if(IsEqualGUID(&IID_nsIHttpChannelInternal, riid)) {
198         TRACE("(%p)->(IID_nsIHttpChannelInternal %p)\n", This, result);
199         *result = This->http_channel_internal ? NSHTTPINTERNAL(This) : NULL;
200     }else {
201         TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
202         *result = NULL;
203     }
204
205     if(*result) {
206         nsIChannel_AddRef(NSCHANNEL(This));
207         return NS_OK;
208     }
209
210     return NS_NOINTERFACE;
211 }
212
213 static nsrefcnt NSAPI nsChannel_AddRef(nsIHttpChannel *iface)
214 {
215     nsChannel *This = NSCHANNEL_THIS(iface);
216     nsrefcnt ref = InterlockedIncrement(&This->ref);
217
218     TRACE("(%p) ref=%d\n", This, ref);
219
220     return ref;
221 }
222
223 static nsrefcnt NSAPI nsChannel_Release(nsIHttpChannel *iface)
224 {
225     nsChannel *This = NSCHANNEL_THIS(iface);
226     LONG ref = InterlockedDecrement(&This->ref);
227
228     if(!ref) {
229         nsIWineURI_Release(This->uri);
230         if(This->channel)
231             nsIChannel_Release(This->channel);
232         if(This->http_channel)
233             nsIHttpChannel_Release(This->http_channel);
234         if(This->http_channel_internal)
235             nsIHttpChannel_Release(This->http_channel_internal);
236         if(This->owner)
237             nsISupports_Release(This->owner);
238         if(This->post_data_stream)
239             nsIInputStream_Release(This->post_data_stream);
240         if(This->load_group)
241             nsILoadGroup_Release(This->load_group);
242         if(This->notif_callback)
243             nsIInterfaceRequestor_Release(This->notif_callback);
244         if(This->original_uri)
245             nsIURI_Release(This->original_uri);
246         heap_free(This->content_type);
247         heap_free(This->charset);
248         heap_free(This);
249     }
250
251     return ref;
252 }
253
254 static nsresult NSAPI nsChannel_GetName(nsIHttpChannel *iface, nsACString *aName)
255 {
256     nsChannel *This = NSCHANNEL_THIS(iface);
257
258     TRACE("(%p)->(%p)\n", This, aName);
259
260     if(This->channel)
261         return nsIChannel_GetName(This->channel, aName);
262
263     return NS_ERROR_NOT_IMPLEMENTED;
264 }
265
266 static nsresult NSAPI nsChannel_IsPending(nsIHttpChannel *iface, PRBool *_retval)
267 {
268     nsChannel *This = NSCHANNEL_THIS(iface);
269
270     TRACE("(%p)->(%p)\n", This, _retval);
271
272     if(This->channel)
273         return nsIChannel_IsPending(This->channel, _retval);
274
275     FIXME("default action not implemented\n");
276     return NS_ERROR_NOT_IMPLEMENTED;
277 }
278
279 static nsresult NSAPI nsChannel_GetStatus(nsIHttpChannel *iface, nsresult *aStatus)
280 {
281     nsChannel *This = NSCHANNEL_THIS(iface);
282
283     TRACE("(%p)->(%p)\n", This, aStatus);
284
285     if(This->channel)
286         return nsIChannel_GetStatus(This->channel, aStatus);
287
288     TRACE("returning NS_OK\n");
289     return *aStatus = NS_OK;
290 }
291
292 static nsresult NSAPI nsChannel_Cancel(nsIHttpChannel *iface, nsresult aStatus)
293 {
294     nsChannel *This = NSCHANNEL_THIS(iface);
295
296     TRACE("(%p)->(%08x)\n", This, aStatus);
297
298     if(This->channel)
299         return nsIChannel_Cancel(This->channel, aStatus);
300
301     FIXME("default action not implemented\n");
302     return NS_ERROR_NOT_IMPLEMENTED;
303 }
304
305 static nsresult NSAPI nsChannel_Suspend(nsIHttpChannel *iface)
306 {
307     nsChannel *This = NSCHANNEL_THIS(iface);
308
309     TRACE("(%p)\n", This);
310
311     if(This->channel)
312         return nsIChannel_Suspend(This->channel);
313
314     FIXME("default action not implemented\n");
315     return NS_ERROR_NOT_IMPLEMENTED;
316 }
317
318 static nsresult NSAPI nsChannel_Resume(nsIHttpChannel *iface)
319 {
320     nsChannel *This = NSCHANNEL_THIS(iface);
321
322     TRACE("(%p)\n", This);
323
324     if(This->channel)
325         return nsIChannel_Resume(This->channel);
326
327     FIXME("default action not implemented\n");
328     return NS_ERROR_NOT_IMPLEMENTED;
329 }
330
331 static nsresult NSAPI nsChannel_GetLoadGroup(nsIHttpChannel *iface, nsILoadGroup **aLoadGroup)
332 {
333     nsChannel *This = NSCHANNEL_THIS(iface);
334
335     TRACE("(%p)->(%p)\n", This, aLoadGroup);
336
337     if(This->load_group)
338         nsILoadGroup_AddRef(This->load_group);
339
340     *aLoadGroup = This->load_group;
341     return NS_OK;
342 }
343
344 static nsresult NSAPI nsChannel_SetLoadGroup(nsIHttpChannel *iface, nsILoadGroup *aLoadGroup)
345 {
346     nsChannel *This = NSCHANNEL_THIS(iface);
347
348     TRACE("(%p)->(%p)\n", This, aLoadGroup);
349
350     if(This->load_group)
351         nsILoadGroup_Release(This->load_group);
352     if(aLoadGroup)
353         nsILoadGroup_AddRef(aLoadGroup);
354
355     This->load_group = aLoadGroup;
356
357     if(This->channel)
358         return nsIChannel_SetLoadGroup(This->channel, aLoadGroup);
359     return NS_OK;
360 }
361
362 static nsresult NSAPI nsChannel_GetLoadFlags(nsIHttpChannel *iface, nsLoadFlags *aLoadFlags)
363 {
364     nsChannel *This = NSCHANNEL_THIS(iface);
365
366     TRACE("(%p)->(%p)\n", This, aLoadFlags);
367
368     *aLoadFlags = This->load_flags;
369     return NS_OK;
370 }
371
372 static nsresult NSAPI nsChannel_SetLoadFlags(nsIHttpChannel *iface, nsLoadFlags aLoadFlags)
373 {
374     nsChannel *This = NSCHANNEL_THIS(iface);
375
376     TRACE("(%p)->(%08x)\n", This, aLoadFlags);
377
378     This->load_flags = aLoadFlags;
379
380     if(This->channel)
381         return nsIChannel_SetLoadFlags(This->channel, aLoadFlags);
382     return NS_OK;
383 }
384
385 static nsresult NSAPI nsChannel_GetOriginalURI(nsIHttpChannel *iface, nsIURI **aOriginalURI)
386 {
387     nsChannel *This = NSCHANNEL_THIS(iface);
388
389     TRACE("(%p)->(%p)\n", This, aOriginalURI);
390
391     if(This->original_uri)
392         nsIURI_AddRef(This->original_uri);
393
394     *aOriginalURI = This->original_uri;
395     return NS_OK;
396 }
397
398 static nsresult NSAPI nsChannel_SetOriginalURI(nsIHttpChannel *iface, nsIURI *aOriginalURI)
399 {
400     nsChannel *This = NSCHANNEL_THIS(iface);
401
402     TRACE("(%p)->(%p)\n", This, aOriginalURI);
403
404     if(This->original_uri)
405         nsIURI_Release(This->original_uri);
406
407     nsIURI_AddRef(aOriginalURI);
408     This->original_uri = aOriginalURI;
409
410     if(This->channel)
411         return nsIChannel_SetOriginalURI(This->channel, aOriginalURI);
412     return NS_OK;
413 }
414
415 static nsresult NSAPI nsChannel_GetURI(nsIHttpChannel *iface, nsIURI **aURI)
416 {
417     nsChannel *This = NSCHANNEL_THIS(iface);
418
419     TRACE("(%p)->(%p)\n", This, aURI);
420
421     nsIWineURI_AddRef(This->uri);
422     *aURI = (nsIURI*)This->uri;
423
424     return NS_OK;
425 }
426
427 static nsresult NSAPI nsChannel_GetOwner(nsIHttpChannel *iface, nsISupports **aOwner)
428 {
429     nsChannel *This = NSCHANNEL_THIS(iface);
430
431     TRACE("(%p)->(%p)\n", This, aOwner);
432
433     if(This->channel)
434         return nsIChannel_GetOwner(This->channel, aOwner);
435
436     if(This->owner)
437         nsISupports_AddRef(This->owner);
438     *aOwner = This->owner;
439
440     return NS_OK;
441 }
442
443 static nsresult NSAPI nsChannel_SetOwner(nsIHttpChannel *iface, nsISupports *aOwner)
444 {
445     nsChannel *This = NSCHANNEL_THIS(iface);
446
447     TRACE("(%p)->(%p)\n", This, aOwner);
448
449     if(This->channel)
450         return nsIChannel_SetOwner(This->channel, aOwner);
451
452     if(aOwner)
453         nsISupports_AddRef(aOwner);
454     if(This->owner)
455         nsISupports_Release(This->owner);
456     This->owner = aOwner;
457
458     return NS_OK;
459 }
460
461 static nsresult NSAPI nsChannel_GetNotificationCallbacks(nsIHttpChannel *iface,
462         nsIInterfaceRequestor **aNotificationCallbacks)
463 {
464     nsChannel *This = NSCHANNEL_THIS(iface);
465
466     TRACE("(%p)->(%p)\n", This, aNotificationCallbacks);
467
468     if(This->notif_callback)
469         nsIInterfaceRequestor_AddRef(This->notif_callback);
470     *aNotificationCallbacks = This->notif_callback;
471
472     return NS_OK;
473 }
474
475 static nsresult NSAPI nsChannel_SetNotificationCallbacks(nsIHttpChannel *iface,
476         nsIInterfaceRequestor *aNotificationCallbacks)
477 {
478     nsChannel *This = NSCHANNEL_THIS(iface);
479
480     TRACE("(%p)->(%p)\n", This, aNotificationCallbacks);
481
482     if(This->notif_callback)
483         nsIInterfaceRequestor_Release(This->notif_callback);
484     if(aNotificationCallbacks)
485         nsIInterfaceRequestor_AddRef(aNotificationCallbacks);
486
487     This->notif_callback = aNotificationCallbacks;
488
489     if(This->channel)
490         return nsIChannel_SetNotificationCallbacks(This->channel, aNotificationCallbacks);
491     return NS_OK;
492 }
493
494 static nsresult NSAPI nsChannel_GetSecurityInfo(nsIHttpChannel *iface, nsISupports **aSecurityInfo)
495 {
496     nsChannel *This = NSCHANNEL_THIS(iface);
497
498     TRACE("(%p)->(%p)\n", This, aSecurityInfo);
499
500     if(This->channel)
501         return nsIChannel_GetSecurityInfo(This->channel, aSecurityInfo);
502
503     FIXME("default action not implemented\n");
504     return NS_ERROR_NOT_IMPLEMENTED;
505 }
506
507 static nsresult NSAPI nsChannel_GetContentType(nsIHttpChannel *iface, nsACString *aContentType)
508 {
509     nsChannel *This = NSCHANNEL_THIS(iface);
510
511     TRACE("(%p)->(%p)\n", This, aContentType);
512
513     if(This->content_type) {
514         nsACString_SetData(aContentType, This->content_type);
515         return S_OK;
516     }
517
518     if(This->channel)
519         return nsIChannel_GetContentType(This->channel, aContentType);
520
521     TRACE("returning default text/html\n");
522     nsACString_SetData(aContentType, "text/html");
523     return NS_OK;
524 }
525
526 static nsresult NSAPI nsChannel_SetContentType(nsIHttpChannel *iface,
527                                                const nsACString *aContentType)
528 {
529     nsChannel *This = NSCHANNEL_THIS(iface);
530     const char *content_type;
531
532     TRACE("(%p)->(%p)\n", This, aContentType);
533
534     nsACString_GetData(aContentType, &content_type);
535
536     TRACE("content_type %s\n", content_type);
537
538     heap_free(This->content_type);
539     This->content_type = heap_strdupA(content_type);
540
541     if(This->channel)
542         return nsIChannel_SetContentType(This->channel, aContentType);
543
544     return NS_OK;
545 }
546
547 static nsresult NSAPI nsChannel_GetContentCharset(nsIHttpChannel *iface,
548                                                   nsACString *aContentCharset)
549 {
550     nsChannel *This = NSCHANNEL_THIS(iface);
551
552     TRACE("(%p)->(%p)\n", This, aContentCharset);
553
554     if(This->charset) {
555         nsACString_SetData(aContentCharset, This->charset);
556         return NS_OK;
557     }
558
559     if(This->channel) {
560         nsresult nsres = nsIChannel_GetContentCharset(This->channel, aContentCharset);
561         const char *ch;
562         nsACString_GetData(aContentCharset, &ch);
563         return nsres;
564     }
565
566     nsACString_SetData(aContentCharset, "");
567     return NS_OK;
568 }
569
570 static nsresult NSAPI nsChannel_SetContentCharset(nsIHttpChannel *iface,
571                                                   const nsACString *aContentCharset)
572 {
573     nsChannel *This = NSCHANNEL_THIS(iface);
574
575     TRACE("(%p)->(%p)\n", This, aContentCharset);
576
577     if(This->channel)
578         return nsIChannel_SetContentCharset(This->channel, aContentCharset);
579
580     FIXME("default action not implemented\n");
581     return NS_ERROR_NOT_IMPLEMENTED;
582 }
583
584 static nsresult NSAPI nsChannel_GetContentLength(nsIHttpChannel *iface, PRInt32 *aContentLength)
585 {
586     nsChannel *This = NSCHANNEL_THIS(iface);
587
588     TRACE("(%p)->(%p)\n", This, aContentLength);
589
590     if(This->channel)
591         return nsIChannel_GetContentLength(This->channel, aContentLength);
592
593     FIXME("default action not implemented\n");
594     return NS_ERROR_NOT_IMPLEMENTED;
595 }
596
597 static nsresult NSAPI nsChannel_SetContentLength(nsIHttpChannel *iface, PRInt32 aContentLength)
598 {
599     nsChannel *This = NSCHANNEL_THIS(iface);
600
601     TRACE("(%p)->(%d)\n", This, aContentLength);
602
603     if(This->channel)
604         return nsIChannel_SetContentLength(This->channel, aContentLength);
605
606     FIXME("default action not implemented\n");
607     return NS_ERROR_NOT_IMPLEMENTED;
608 }
609
610 static nsresult NSAPI nsChannel_Open(nsIHttpChannel *iface, nsIInputStream **_retval)
611 {
612     nsChannel *This = NSCHANNEL_THIS(iface);
613
614     TRACE("(%p)->(%p)\n", This, _retval);
615
616     if(This->channel)
617         return nsIChannel_Open(This->channel, _retval);
618
619     FIXME("default action not implemented\n");
620     return NS_ERROR_NOT_IMPLEMENTED;
621 }
622
623 static HRESULT create_mon_for_nschannel(nsChannel *channel, IMoniker **mon)
624 {
625     nsIWineURI *wine_uri;
626     LPCWSTR wine_url;
627     nsresult nsres;
628     HRESULT hres;
629
630     if(!channel->original_uri) {
631         ERR("original_uri == NULL\n");
632         return E_FAIL;
633     }
634
635     nsres = nsIURI_QueryInterface(channel->original_uri, &IID_nsIWineURI, (void**)&wine_uri);
636     if(NS_FAILED(nsres)) {
637         ERR("Could not get nsIWineURI: %08x\n", nsres);
638         return E_FAIL;
639     }
640
641     nsIWineURI_GetWineURL(wine_uri, &wine_url);
642     nsIWineURI_Release(wine_uri);
643     if(!wine_url) {
644         TRACE("wine_url == NULL\n");
645         return E_FAIL;
646     }
647
648     hres = CreateURLMoniker(NULL, wine_url, mon);
649     if(FAILED(hres))
650         WARN("CreateURLMonikrer failed: %08x\n", hres);
651
652     return hres;
653 }
654
655 static NSContainer *get_nscontainer_from_load_group(nsChannel *This)
656 {
657     NSContainer *container;
658     nsIChannel *channel;
659     nsIRequest *req;
660     nsIWineURI *wine_uri;
661     nsIURI *uri;
662     nsresult nsres;
663
664     nsres = nsILoadGroup_GetDefaultLoadRequest(This->load_group, &req);
665     if(NS_FAILED(nsres)) {
666         ERR("GetDefaultLoadRequest failed: %08x\n", nsres);
667         return NULL;
668     }
669
670     if(!req)
671         return NULL;
672
673     nsres = nsIRequest_QueryInterface(req, &IID_nsIChannel, (void**)&channel);
674     nsIRequest_Release(req);
675     if(NS_FAILED(nsres)) {
676         WARN("Could not get nsIChannel interface: %08x\n", nsres);
677         return NULL;
678     }
679
680     nsres = nsIChannel_GetURI(channel, &uri);
681     nsIChannel_Release(channel);
682     if(NS_FAILED(nsres)) {
683         ERR("GetURI failed: %08x\n", nsres);
684         return NULL;
685     }
686
687     nsres = nsIURI_QueryInterface(uri, &IID_nsIWineURI, (void**)&wine_uri);
688     nsIURI_Release(uri);
689     if(NS_FAILED(nsres)) {
690         TRACE("Could not get nsIWineURI: %08x\n", nsres);
691         return NULL;
692     }
693
694     nsIWineURI_GetNSContainer(wine_uri, &container);
695     nsIWineURI_Release(wine_uri);
696
697     return container;
698 }
699
700 static nsresult async_open_doc_uri(nsChannel *This, NSContainer *container,
701         nsIStreamListener *listener, nsISupports *context, BOOL *open)
702 {
703     IMoniker *mon;
704     HRESULT hres;
705
706     *open = FALSE;
707
708     if(container->bscallback) {
709         channelbsc_set_channel(container->bscallback, This, listener, context);
710
711         if(container->doc && container->doc->mime) {
712             heap_free(This->content_type);
713             This->content_type = heap_strdupWtoA(container->doc->mime);
714         }
715
716         return NS_OK;
717     }else  {
718         BOOL cont = before_async_open(This, container);
719
720         if(!cont) {
721             TRACE("canceled\n");
722             return NS_ERROR_UNEXPECTED;
723         }
724
725         if(!container->doc) {
726             return This->channel
727                 ?  nsIChannel_AsyncOpen(This->channel, listener, context)
728                 : NS_ERROR_UNEXPECTED;
729         }
730
731         hres = create_mon_for_nschannel(This, &mon);
732         if(FAILED(hres)) {
733             return NS_ERROR_UNEXPECTED;
734         }
735         set_current_mon(&container->doc->basedoc, mon);
736     }
737
738     *open = TRUE;
739     return NS_OK;
740 }
741
742 static nsresult async_open(nsChannel *This, NSContainer *container, nsIStreamListener *listener,
743         nsISupports *context)
744 {
745     nsChannelBSC *bscallback;
746     IMoniker *mon = NULL;
747     task_t *task;
748     HRESULT hres;
749
750     hres = create_mon_for_nschannel(This, &mon);
751     if(FAILED(hres))
752         return NS_ERROR_UNEXPECTED;
753
754     bscallback = create_channelbsc(mon);
755     IMoniker_Release(mon);
756
757     channelbsc_set_channel(bscallback, This, listener, context);
758
759     task = heap_alloc(sizeof(task_t));
760
761     task->doc = &container->doc->basedoc;
762     task->task_id = TASK_START_BINDING;
763     task->next = NULL;
764     task->bscallback = bscallback;
765
766     push_task(task);
767
768     return NS_OK;
769 }
770
771 static nsresult NSAPI nsChannel_AsyncOpen(nsIHttpChannel *iface, nsIStreamListener *aListener,
772                                           nsISupports *aContext)
773 {
774     nsChannel *This = NSCHANNEL_THIS(iface);
775     NSContainer *container;
776     PRBool is_doc_uri;
777     BOOL open = TRUE;
778     nsresult nsres = NS_OK;
779
780     TRACE("(%p)->(%p %p)\n", This, aListener, aContext);
781
782     nsIWineURI_GetNSContainer(This->uri, &container);
783
784     if(!container && This->load_group) {
785         container = get_nscontainer_from_load_group(This);
786         if(container)
787             nsIWineURI_SetNSContainer(This->uri, container);
788     }
789
790     if(!container) {
791         TRACE("container = NULL\n");
792         return This->channel
793             ? nsIChannel_AsyncOpen(This->channel, aListener, aContext)
794             : NS_ERROR_UNEXPECTED;
795     }
796
797     nsIWineURI_GetIsDocumentURI(This->uri, &is_doc_uri);
798
799     if(is_doc_uri && (This->load_flags & LOAD_INITIAL_DOCUMENT_URI))
800         nsres = async_open_doc_uri(This, container, aListener, aContext, &open);
801
802     if(open)
803         nsres = async_open(This, container, aListener, aContext);
804
805     nsIWebBrowserChrome_Release(NSWBCHROME(container));
806     return nsres;
807 }
808
809 static nsresult NSAPI nsChannel_GetRequestMethod(nsIHttpChannel *iface, nsACString *aRequestMethod)
810 {
811     nsChannel *This = NSCHANNEL_THIS(iface);
812
813     TRACE("(%p)->(%p)\n", This, aRequestMethod);
814
815     if(This->http_channel)
816         return nsIHttpChannel_GetRequestMethod(This->http_channel, aRequestMethod);
817
818     return NS_ERROR_NOT_IMPLEMENTED;
819 }
820
821 static nsresult NSAPI nsChannel_SetRequestMethod(nsIHttpChannel *iface,
822                                                  const nsACString *aRequestMethod)
823 {
824     nsChannel *This = NSCHANNEL_THIS(iface);
825
826     TRACE("(%p)->(%p)\n", This, aRequestMethod);
827
828     if(This->http_channel)
829         return nsIHttpChannel_SetRequestMethod(This->http_channel, aRequestMethod);
830
831     return NS_ERROR_NOT_IMPLEMENTED;
832 }
833
834 static nsresult NSAPI nsChannel_GetReferrer(nsIHttpChannel *iface, nsIURI **aReferrer)
835 {
836     nsChannel *This = NSCHANNEL_THIS(iface);
837
838     TRACE("(%p)->(%p)\n", This, aReferrer);
839
840     if(This->http_channel)
841         return nsIHttpChannel_GetReferrer(This->http_channel, aReferrer);
842
843     return NS_ERROR_NOT_IMPLEMENTED;
844 }
845
846 static nsresult NSAPI nsChannel_SetReferrer(nsIHttpChannel *iface, nsIURI *aReferrer)
847 {
848     nsChannel *This = NSCHANNEL_THIS(iface);
849
850     TRACE("(%p)->(%p)\n", This, aReferrer);
851
852     if(This->http_channel)
853         return nsIHttpChannel_SetReferrer(This->http_channel, aReferrer);
854
855     return NS_ERROR_NOT_IMPLEMENTED;
856 }
857
858 static nsresult NSAPI nsChannel_GetRequestHeader(nsIHttpChannel *iface,
859          const nsACString *aHeader, nsACString *_retval)
860 {
861     nsChannel *This = NSCHANNEL_THIS(iface);
862
863     TRACE("(%p)->(%p %p)\n", This, aHeader, _retval);
864
865     if(This->http_channel)
866         return nsIHttpChannel_GetRequestHeader(This->http_channel, aHeader, _retval);
867
868     return NS_ERROR_NOT_IMPLEMENTED;
869 }
870
871 static nsresult NSAPI nsChannel_SetRequestHeader(nsIHttpChannel *iface,
872          const nsACString *aHeader, const nsACString *aValue, PRBool aMerge)
873 {
874     nsChannel *This = NSCHANNEL_THIS(iface);
875
876     TRACE("(%p)->(%p %p %x)\n", This, aHeader, aValue, aMerge);
877
878     if(This->http_channel)
879         return nsIHttpChannel_SetRequestHeader(This->http_channel, aHeader, aValue, aMerge);
880
881     return NS_ERROR_NOT_IMPLEMENTED;
882 }
883
884 static nsresult NSAPI nsChannel_VisitRequestHeaders(nsIHttpChannel *iface,
885                                                     nsIHttpHeaderVisitor *aVisitor)
886 {
887     nsChannel *This = NSCHANNEL_THIS(iface);
888
889     TRACE("(%p)->(%p)\n", This, aVisitor);
890
891     if(This->http_channel)
892         return nsIHttpChannel_VisitRequestHeaders(This->http_channel, aVisitor);
893
894     return NS_ERROR_NOT_IMPLEMENTED;
895 }
896
897 static nsresult NSAPI nsChannel_GetAllowPipelining(nsIHttpChannel *iface, PRBool *aAllowPipelining)
898 {
899     nsChannel *This = NSCHANNEL_THIS(iface);
900
901     TRACE("(%p)->(%p)\n", This, aAllowPipelining);
902
903     if(This->http_channel)
904         return nsIHttpChannel_GetAllowPipelining(This->http_channel, aAllowPipelining);
905
906     return NS_ERROR_NOT_IMPLEMENTED;
907 }
908
909 static nsresult NSAPI nsChannel_SetAllowPipelining(nsIHttpChannel *iface, PRBool aAllowPipelining)
910 {
911     nsChannel *This = NSCHANNEL_THIS(iface);
912
913     TRACE("(%p)->(%x)\n", This, aAllowPipelining);
914
915     if(This->http_channel)
916         return nsIHttpChannel_SetAllowPipelining(This->http_channel, aAllowPipelining);
917
918     return NS_ERROR_NOT_IMPLEMENTED;
919 }
920
921 static nsresult NSAPI nsChannel_GetRedirectionLimit(nsIHttpChannel *iface, PRUint32 *aRedirectionLimit)
922 {
923     nsChannel *This = NSCHANNEL_THIS(iface);
924
925     TRACE("(%p)->(%p)\n", This, aRedirectionLimit);
926
927     if(This->http_channel)
928         return nsIHttpChannel_GetRedirectionLimit(This->http_channel, aRedirectionLimit);
929
930     return NS_ERROR_NOT_IMPLEMENTED;
931 }
932
933 static nsresult NSAPI nsChannel_SetRedirectionLimit(nsIHttpChannel *iface, PRUint32 aRedirectionLimit)
934 {
935     nsChannel *This = NSCHANNEL_THIS(iface);
936
937     TRACE("(%p)->(%u)\n", This, aRedirectionLimit);
938
939     if(This->http_channel)
940         return nsIHttpChannel_SetRedirectionLimit(This->http_channel, aRedirectionLimit);
941
942     return NS_ERROR_NOT_IMPLEMENTED;
943 }
944
945 static nsresult NSAPI nsChannel_GetResponseStatus(nsIHttpChannel *iface, PRUint32 *aResponseStatus)
946 {
947     nsChannel *This = NSCHANNEL_THIS(iface);
948
949     TRACE("(%p)->(%p)\n", This, aResponseStatus);
950
951     if(This->response_status) {
952         *aResponseStatus = This->response_status;
953         return NS_OK;
954     }
955
956     if(This->http_channel)
957         return nsIHttpChannel_GetResponseStatus(This->http_channel, aResponseStatus);
958
959     return NS_ERROR_UNEXPECTED;
960 }
961
962 static nsresult NSAPI nsChannel_GetResponseStatusText(nsIHttpChannel *iface,
963                                                       nsACString *aResponseStatusText)
964 {
965     nsChannel *This = NSCHANNEL_THIS(iface);
966
967     TRACE("(%p)->(%p)\n", This, aResponseStatusText);
968
969     if(This->http_channel)
970         return nsIHttpChannel_GetResponseStatusText(This->http_channel, aResponseStatusText);
971
972     return NS_ERROR_NOT_IMPLEMENTED;
973 }
974
975 static nsresult NSAPI nsChannel_GetRequestSucceeded(nsIHttpChannel *iface,
976                                                     PRBool *aRequestSucceeded)
977 {
978     nsChannel *This = NSCHANNEL_THIS(iface);
979
980     TRACE("(%p)->(%p)\n", This, aRequestSucceeded);
981
982     if(This->http_channel)
983         return nsIHttpChannel_GetRequestSucceeded(This->http_channel, aRequestSucceeded);
984
985     return NS_ERROR_NOT_IMPLEMENTED;
986 }
987
988 static nsresult NSAPI nsChannel_GetResponseHeader(nsIHttpChannel *iface,
989          const nsACString *header, nsACString *_retval)
990 {
991     nsChannel *This = NSCHANNEL_THIS(iface);
992
993     TRACE("(%p)->(%p %p)\n", This, header, _retval);
994
995     if(This->http_channel)
996         return nsIHttpChannel_GetResponseHeader(This->http_channel, header, _retval);
997
998     return NS_ERROR_NOT_IMPLEMENTED;
999 }
1000
1001 static nsresult NSAPI nsChannel_SetResponseHeader(nsIHttpChannel *iface,
1002         const nsACString *header, const nsACString *value, PRBool merge)
1003 {
1004     nsChannel *This = NSCHANNEL_THIS(iface);
1005
1006     TRACE("(%p)->(%p %p %x)\n", This, header, value, merge);
1007
1008     if(This->http_channel)
1009         return nsIHttpChannel_SetResponseHeader(This->http_channel, header, value, merge);
1010
1011     return NS_ERROR_NOT_IMPLEMENTED;
1012 }
1013
1014 static nsresult NSAPI nsChannel_VisitResponseHeaders(nsIHttpChannel *iface,
1015         nsIHttpHeaderVisitor *aVisitor)
1016 {
1017     nsChannel *This = NSCHANNEL_THIS(iface);
1018
1019     TRACE("(%p)->(%p)\n", This, aVisitor);
1020
1021     if(This->http_channel)
1022         return nsIHttpChannel_VisitResponseHeaders(This->http_channel, aVisitor);
1023
1024     return NS_ERROR_NOT_IMPLEMENTED;
1025 }
1026
1027 static nsresult NSAPI nsChannel_IsNoStoreResponse(nsIHttpChannel *iface, PRBool *_retval)
1028 {
1029     nsChannel *This = NSCHANNEL_THIS(iface);
1030
1031     TRACE("(%p)->(%p)\n", This, _retval);
1032
1033     if(This->http_channel)
1034         return nsIHttpChannel_IsNoStoreResponse(This->http_channel, _retval);
1035
1036     return NS_ERROR_NOT_IMPLEMENTED;
1037 }
1038
1039 static nsresult NSAPI nsChannel_IsNoCacheResponse(nsIHttpChannel *iface, PRBool *_retval)
1040 {
1041     nsChannel *This = NSCHANNEL_THIS(iface);
1042
1043     TRACE("(%p)->(%p)\n", This, _retval);
1044
1045     if(This->http_channel)
1046         return nsIHttpChannel_IsNoCacheResponse(This->http_channel, _retval);
1047
1048     return NS_ERROR_NOT_IMPLEMENTED;
1049 }
1050
1051 #undef NSCHANNEL_THIS
1052
1053 static const nsIHttpChannelVtbl nsChannelVtbl = {
1054     nsChannel_QueryInterface,
1055     nsChannel_AddRef,
1056     nsChannel_Release,
1057     nsChannel_GetName,
1058     nsChannel_IsPending,
1059     nsChannel_GetStatus,
1060     nsChannel_Cancel,
1061     nsChannel_Suspend,
1062     nsChannel_Resume,
1063     nsChannel_GetLoadGroup,
1064     nsChannel_SetLoadGroup,
1065     nsChannel_GetLoadFlags,
1066     nsChannel_SetLoadFlags,
1067     nsChannel_GetOriginalURI,
1068     nsChannel_SetOriginalURI,
1069     nsChannel_GetURI,
1070     nsChannel_GetOwner,
1071     nsChannel_SetOwner,
1072     nsChannel_GetNotificationCallbacks,
1073     nsChannel_SetNotificationCallbacks,
1074     nsChannel_GetSecurityInfo,
1075     nsChannel_GetContentType,
1076     nsChannel_SetContentType,
1077     nsChannel_GetContentCharset,
1078     nsChannel_SetContentCharset,
1079     nsChannel_GetContentLength,
1080     nsChannel_SetContentLength,
1081     nsChannel_Open,
1082     nsChannel_AsyncOpen,
1083     nsChannel_GetRequestMethod,
1084     nsChannel_SetRequestMethod,
1085     nsChannel_GetReferrer,
1086     nsChannel_SetReferrer,
1087     nsChannel_GetRequestHeader,
1088     nsChannel_SetRequestHeader,
1089     nsChannel_VisitRequestHeaders,
1090     nsChannel_GetAllowPipelining,
1091     nsChannel_SetAllowPipelining,
1092     nsChannel_GetRedirectionLimit,
1093     nsChannel_SetRedirectionLimit,
1094     nsChannel_GetResponseStatus,
1095     nsChannel_GetResponseStatusText,
1096     nsChannel_GetRequestSucceeded,
1097     nsChannel_GetResponseHeader,
1098     nsChannel_SetResponseHeader,
1099     nsChannel_VisitResponseHeaders,
1100     nsChannel_IsNoStoreResponse,
1101     nsChannel_IsNoCacheResponse
1102 };
1103
1104 #define NSUPCHANNEL_THIS(iface) DEFINE_THIS(nsChannel, UploadChannel, iface)
1105
1106 static nsresult NSAPI nsUploadChannel_QueryInterface(nsIUploadChannel *iface, nsIIDRef riid,
1107                                                      nsQIResult result)
1108 {
1109     nsChannel *This = NSUPCHANNEL_THIS(iface);
1110     return nsIChannel_QueryInterface(NSCHANNEL(This), riid, result);
1111 }
1112
1113 static nsrefcnt NSAPI nsUploadChannel_AddRef(nsIUploadChannel *iface)
1114 {
1115     nsChannel *This = NSUPCHANNEL_THIS(iface);
1116     return nsIChannel_AddRef(NSCHANNEL(This));
1117 }
1118
1119 static nsrefcnt NSAPI nsUploadChannel_Release(nsIUploadChannel *iface)
1120 {
1121     nsChannel *This = NSUPCHANNEL_THIS(iface);
1122     return nsIChannel_Release(NSCHANNEL(This));
1123 }
1124
1125 static nsresult NSAPI nsUploadChannel_SetUploadStream(nsIUploadChannel *iface,
1126         nsIInputStream *aStream, const nsACString *aContentType, PRInt32 aContentLength)
1127 {
1128     nsChannel *This = NSUPCHANNEL_THIS(iface);
1129     const char *content_type;
1130     nsresult nsres;
1131
1132     TRACE("(%p)->(%p %p %d)\n", This, aStream, aContentType, aContentLength);
1133
1134     if(This->post_data_stream)
1135         nsIInputStream_Release(This->post_data_stream);
1136
1137     if(aContentType) {
1138         nsACString_GetData(aContentType, &content_type);
1139         if(*content_type)
1140             FIXME("Unsupported aContentType argument: %s\n", debugstr_a(content_type));
1141     }
1142
1143     if(aContentLength != -1)
1144         FIXME("Unsupported acontentLength = %d\n", aContentLength);
1145
1146     if(This->post_data_stream)
1147         nsIInputStream_Release(This->post_data_stream);
1148     This->post_data_stream = aStream;
1149     if(aStream)
1150         nsIInputStream_AddRef(aStream);
1151
1152     if(This->post_data_stream) {
1153         nsIUploadChannel *upload_channel;
1154
1155         nsres = nsIChannel_QueryInterface(This->channel, &IID_nsIUploadChannel,
1156                 (void**)&upload_channel);
1157         if(NS_SUCCEEDED(nsres)) {
1158             nsres = nsIUploadChannel_SetUploadStream(upload_channel, aStream, aContentType, aContentLength);
1159             nsIUploadChannel_Release(upload_channel);
1160             if(NS_FAILED(nsres))
1161                 WARN("SetUploadStream failed: %08x\n", nsres);
1162
1163         }
1164     }
1165
1166     return NS_OK;
1167 }
1168
1169 static nsresult NSAPI nsUploadChannel_GetUploadStream(nsIUploadChannel *iface,
1170         nsIInputStream **aUploadStream)
1171 {
1172     nsChannel *This = NSUPCHANNEL_THIS(iface);
1173
1174     TRACE("(%p)->(%p)\n", This, aUploadStream);
1175
1176     if(This->post_data_stream)
1177         nsIInputStream_AddRef(This->post_data_stream);
1178
1179     *aUploadStream = This->post_data_stream;
1180     return NS_OK;
1181 }
1182
1183 #undef NSUPCHANNEL_THIS
1184
1185 static const nsIUploadChannelVtbl nsUploadChannelVtbl = {
1186     nsUploadChannel_QueryInterface,
1187     nsUploadChannel_AddRef,
1188     nsUploadChannel_Release,
1189     nsUploadChannel_SetUploadStream,
1190     nsUploadChannel_GetUploadStream
1191 };
1192
1193 #define NSHTTPINTERNAL_THIS(iface) DEFINE_THIS(nsChannel, IHttpChannelInternal, iface)
1194
1195 static nsresult NSAPI nsHttpChannelInternal_QueryInterface(nsIHttpChannelInternal *iface, nsIIDRef riid,
1196         nsQIResult result)
1197 {
1198     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1199     return nsIChannel_QueryInterface(NSCHANNEL(This), riid, result);
1200 }
1201
1202 static nsrefcnt NSAPI nsHttpChannelInternal_AddRef(nsIHttpChannelInternal *iface)
1203 {
1204     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1205     return nsIChannel_AddRef(NSCHANNEL(This));
1206 }
1207
1208 static nsrefcnt NSAPI nsHttpChannelInternal_Release(nsIHttpChannelInternal *iface)
1209 {
1210     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1211     return nsIChannel_Release(NSCHANNEL(This));
1212 }
1213
1214 static nsresult NSAPI nsHttpChannelInternal_GetDocumentURI(nsIHttpChannelInternal *iface, nsIURI **aDocumentURI)
1215 {
1216     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1217
1218     TRACE("(%p)->()\n", This);
1219
1220     if(This->http_channel_internal)
1221         return nsIHttpChannelInternal_GetDocumentURI(This->http_channel_internal, aDocumentURI);
1222     return NS_ERROR_NOT_IMPLEMENTED;
1223 }
1224
1225 static nsresult NSAPI nsHttpChannelInternal_SetDocumentURI(nsIHttpChannelInternal *iface, nsIURI *aDocumentURI)
1226 {
1227     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1228
1229     TRACE("(%p)->()\n", This);
1230
1231     if(This->http_channel_internal)
1232         return nsIHttpChannelInternal_SetDocumentURI(This->http_channel_internal, aDocumentURI);
1233     return NS_ERROR_NOT_IMPLEMENTED;
1234 }
1235
1236 static nsresult NSAPI nsHttpChannelInternal_GetRequestVersion(nsIHttpChannelInternal *iface, PRUint32 *major, PRUint32 *minor)
1237 {
1238     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1239
1240     TRACE("(%p)->()\n", This);
1241
1242     if(This->http_channel_internal)
1243         return nsIHttpChannelInternal_GetRequestVersion(This->http_channel_internal, major, minor);
1244     return NS_ERROR_NOT_IMPLEMENTED;
1245 }
1246
1247 static nsresult NSAPI nsHttpChannelInternal_GetResponseVersion(nsIHttpChannelInternal *iface, PRUint32 *major, PRUint32 *minor)
1248 {
1249     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1250
1251     TRACE("(%p)->()\n", This);
1252
1253     if(This->http_channel_internal)
1254         return nsIHttpChannelInternal_GetResponseVersion(This->http_channel_internal, major, minor);
1255     return NS_ERROR_NOT_IMPLEMENTED;
1256 }
1257
1258 static nsresult NSAPI nsHttpChannelInternal_SetCookie(nsIHttpChannelInternal *iface, const char *aCookieHeader)
1259 {
1260     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1261
1262     TRACE("(%p)->()\n", This);
1263
1264     if(This->http_channel_internal)
1265         return nsIHttpChannelInternal_SetCookie(This->http_channel_internal, aCookieHeader);
1266     return NS_ERROR_NOT_IMPLEMENTED;
1267 }
1268
1269 static nsresult NSAPI nsHttpChannelInternal_SetupFallbackChannel(nsIHttpChannelInternal *iface, const char *aFallbackKey)
1270 {
1271     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1272
1273     TRACE("(%p)->()\n", This);
1274
1275     if(This->http_channel_internal)
1276         return nsIHttpChannelInternal_SetupFallbackChannel(This->http_channel_internal, aFallbackKey);
1277     return NS_ERROR_NOT_IMPLEMENTED;
1278 }
1279
1280 static nsresult NSAPI nsHttpChannelInternal_GetForceAllowThirdPartyCookie(nsIHttpChannelInternal *iface, PRBool *aForceThirdPartyCookie)
1281 {
1282     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1283
1284     TRACE("(%p)->()\n", This);
1285
1286     if(This->http_channel_internal)
1287         return nsIHttpChannelInternal_GetForceAllowThirdPartyCookie(This->http_channel_internal, aForceThirdPartyCookie);
1288     return NS_ERROR_NOT_IMPLEMENTED;
1289 }
1290
1291 static nsresult NSAPI nsHttpChannelInternal_SetForceAllowThirdPartyCookie(nsIHttpChannelInternal *iface, PRBool aForceThirdPartyCookie)
1292 {
1293     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1294
1295     TRACE("(%p)->()\n", This);
1296
1297     if(This->http_channel_internal)
1298         return nsIHttpChannelInternal_SetForceAllowThirdPartyCookie(This->http_channel_internal, aForceThirdPartyCookie);
1299     return NS_ERROR_NOT_IMPLEMENTED;
1300 }
1301
1302 #undef NSHTTPINTERNAL_THIS
1303
1304 static const nsIHttpChannelInternalVtbl nsHttpChannelInternalVtbl = {
1305     nsHttpChannelInternal_QueryInterface,
1306     nsHttpChannelInternal_AddRef,
1307     nsHttpChannelInternal_Release,
1308     nsHttpChannelInternal_GetDocumentURI,
1309     nsHttpChannelInternal_SetDocumentURI,
1310     nsHttpChannelInternal_GetRequestVersion,
1311     nsHttpChannelInternal_GetResponseVersion,
1312     nsHttpChannelInternal_SetCookie,
1313     nsHttpChannelInternal_SetupFallbackChannel,
1314     nsHttpChannelInternal_GetForceAllowThirdPartyCookie,
1315     nsHttpChannelInternal_SetForceAllowThirdPartyCookie
1316 };
1317
1318 #define NSURI_THIS(iface) DEFINE_THIS(nsURI, WineURI, iface)
1319
1320 static nsresult NSAPI nsURI_QueryInterface(nsIWineURI *iface, nsIIDRef riid, nsQIResult result)
1321 {
1322     nsURI *This = NSURI_THIS(iface);
1323
1324     *result = NULL;
1325
1326     if(IsEqualGUID(&IID_nsISupports, riid)) {
1327         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
1328         *result = NSURI(This);
1329     }else if(IsEqualGUID(&IID_nsIURI, riid)) {
1330         TRACE("(%p)->(IID_nsIURI %p)\n", This, result);
1331         *result = NSURI(This);
1332     }else if(IsEqualGUID(&IID_nsIURL, riid)) {
1333         TRACE("(%p)->(IID_nsIURL %p)\n", This, result);
1334         *result = NSURI(This);
1335     }else if(IsEqualGUID(&IID_nsIWineURI, riid)) {
1336         TRACE("(%p)->(IID_nsIWineURI %p)\n", This, result);
1337         *result = NSURI(This);
1338     }
1339
1340     if(*result) {
1341         nsIURI_AddRef(NSURI(This));
1342         return NS_OK;
1343     }
1344
1345     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
1346     return This->uri ? nsIURI_QueryInterface(This->uri, riid, result) : NS_NOINTERFACE;
1347 }
1348
1349 static nsrefcnt NSAPI nsURI_AddRef(nsIWineURI *iface)
1350 {
1351     nsURI *This = NSURI_THIS(iface);
1352     LONG ref = InterlockedIncrement(&This->ref);
1353
1354     TRACE("(%p) ref=%d\n", This, ref);
1355
1356     return ref;
1357 }
1358
1359 static nsrefcnt NSAPI nsURI_Release(nsIWineURI *iface)
1360 {
1361     nsURI *This = NSURI_THIS(iface);
1362     LONG ref = InterlockedDecrement(&This->ref);
1363
1364     TRACE("(%p) ref=%d\n", This, ref);
1365
1366     if(!ref) {
1367         if(This->container)
1368             nsIWebBrowserChrome_Release(NSWBCHROME(This->container));
1369         if(This->nsurl)
1370             nsIURL_Release(This->nsurl);
1371         if(This->uri)
1372             nsIURI_Release(This->uri);
1373         heap_free(This->wine_url);
1374         heap_free(This);
1375     }
1376
1377     return ref;
1378 }
1379
1380 static nsresult NSAPI nsURI_GetSpec(nsIWineURI *iface, nsACString *aSpec)
1381 {
1382     nsURI *This = NSURI_THIS(iface);
1383
1384     TRACE("(%p)->(%p)\n", This, aSpec);
1385
1386     if(This->use_wine_url) {
1387         char speca[INTERNET_MAX_URL_LENGTH] = "wine:";
1388         WideCharToMultiByte(CP_ACP, 0, This->wine_url, -1, speca+5, sizeof(speca)-5, NULL, NULL);
1389         nsACString_SetData(aSpec, speca);
1390
1391         return NS_OK;
1392     }
1393
1394     if(This->uri)
1395         return nsIURI_GetSpec(This->uri, aSpec);
1396
1397     TRACE("returning error\n");
1398     return NS_ERROR_NOT_IMPLEMENTED;
1399
1400 }
1401
1402 static nsresult NSAPI nsURI_SetSpec(nsIWineURI *iface, const nsACString *aSpec)
1403 {
1404     nsURI *This = NSURI_THIS(iface);
1405
1406     TRACE("(%p)->(%p)\n", This, aSpec);
1407
1408     if(This->uri)
1409         return nsIURI_SetSpec(This->uri, aSpec);
1410
1411     FIXME("default action not implemented\n");
1412     return NS_ERROR_NOT_IMPLEMENTED;
1413 }
1414
1415 static nsresult NSAPI nsURI_GetPrePath(nsIWineURI *iface, nsACString *aPrePath)
1416 {
1417     nsURI *This = NSURI_THIS(iface);
1418
1419     TRACE("(%p)->(%p)\n", This, aPrePath);
1420
1421     if(This->uri)
1422         return nsIURI_GetPrePath(This->uri, aPrePath);
1423
1424     FIXME("default action not implemented\n");
1425     return NS_ERROR_NOT_IMPLEMENTED;
1426 }
1427
1428 static nsresult NSAPI nsURI_GetScheme(nsIWineURI *iface, nsACString *aScheme)
1429 {
1430     nsURI *This = NSURI_THIS(iface);
1431
1432     TRACE("(%p)->(%p)\n", This, aScheme);
1433
1434     if(This->use_wine_url && strcmpW(This->wine_url, about_blankW)) {
1435         /*
1436          * For Gecko we set scheme to unknown so it won't be handled
1437          * as any special case.
1438          */
1439         nsACString_SetData(aScheme, "wine");
1440         return NS_OK;
1441     }
1442
1443     if(This->uri)
1444         return nsIURI_GetScheme(This->uri, aScheme);
1445
1446     TRACE("returning error\n");
1447     return NS_ERROR_NOT_IMPLEMENTED;
1448 }
1449
1450 static nsresult NSAPI nsURI_SetScheme(nsIWineURI *iface, const nsACString *aScheme)
1451 {
1452     nsURI *This = NSURI_THIS(iface);
1453
1454     TRACE("(%p)->(%p)\n", This, aScheme);
1455
1456     if(This->uri)
1457         return nsIURI_SetScheme(This->uri, aScheme);
1458
1459     FIXME("default action not implemented\n");
1460     return NS_ERROR_NOT_IMPLEMENTED;
1461 }
1462
1463 static nsresult NSAPI nsURI_GetUserPass(nsIWineURI *iface, nsACString *aUserPass)
1464 {
1465     nsURI *This = NSURI_THIS(iface);
1466
1467     TRACE("(%p)->(%p)\n", This, aUserPass);
1468
1469     if(This->uri)
1470         return nsIURI_GetUserPass(This->uri, aUserPass);
1471
1472     FIXME("default action not implemented\n");
1473     return NS_ERROR_NOT_IMPLEMENTED;
1474 }
1475
1476 static nsresult NSAPI nsURI_SetUserPass(nsIWineURI *iface, const nsACString *aUserPass)
1477 {
1478     nsURI *This = NSURI_THIS(iface);
1479
1480     TRACE("(%p)->(%p)\n", This, aUserPass);
1481
1482     if(This->uri)
1483         return nsIURI_SetUserPass(This->uri, aUserPass);
1484
1485     FIXME("default action not implemented\n");
1486     return NS_ERROR_NOT_IMPLEMENTED;
1487 }
1488
1489 static nsresult NSAPI nsURI_GetUsername(nsIWineURI *iface, nsACString *aUsername)
1490 {
1491     nsURI *This = NSURI_THIS(iface);
1492
1493     TRACE("(%p)->(%p)\n", This, aUsername);
1494
1495     if(This->uri)
1496         return nsIURI_GetUsername(This->uri, aUsername);
1497
1498     FIXME("default action not implemented\n");
1499     return NS_ERROR_NOT_IMPLEMENTED;
1500 }
1501
1502 static nsresult NSAPI nsURI_SetUsername(nsIWineURI *iface, const nsACString *aUsername)
1503 {
1504     nsURI *This = NSURI_THIS(iface);
1505
1506     TRACE("(%p)->(%p)\n", This, aUsername);
1507
1508     if(This->uri)
1509         return nsIURI_SetUsername(This->uri, aUsername);
1510
1511     FIXME("default action not implemented\n");
1512     return NS_ERROR_NOT_IMPLEMENTED;
1513 }
1514
1515 static nsresult NSAPI nsURI_GetPassword(nsIWineURI *iface, nsACString *aPassword)
1516 {
1517     nsURI *This = NSURI_THIS(iface);
1518
1519     TRACE("(%p)->(%p)\n", This, aPassword);
1520
1521     if(This->uri)
1522         return nsIURI_GetPassword(This->uri, aPassword);
1523
1524     FIXME("default action not implemented\n");
1525     return NS_ERROR_NOT_IMPLEMENTED;
1526 }
1527
1528 static nsresult NSAPI nsURI_SetPassword(nsIWineURI *iface, const nsACString *aPassword)
1529 {
1530     nsURI *This = NSURI_THIS(iface);
1531
1532     TRACE("(%p)->(%p)\n", This, aPassword);
1533
1534     if(This->uri)
1535         return nsIURI_SetPassword(This->uri, aPassword);
1536
1537     FIXME("default action not implemented\n");
1538     return NS_ERROR_NOT_IMPLEMENTED;
1539 }
1540
1541 static nsresult NSAPI nsURI_GetHostPort(nsIWineURI *iface, nsACString *aHostPort)
1542 {
1543     nsURI *This = NSURI_THIS(iface);
1544
1545     TRACE("(%p)->(%p)\n", This, aHostPort);
1546
1547     if(This->uri)
1548         return nsIURI_GetHostPort(This->uri, aHostPort);
1549
1550     FIXME("default action not implemented\n");
1551     return NS_ERROR_NOT_IMPLEMENTED;
1552 }
1553
1554 static nsresult NSAPI nsURI_SetHostPort(nsIWineURI *iface, const nsACString *aHostPort)
1555 {
1556     nsURI *This = NSURI_THIS(iface);
1557
1558     TRACE("(%p)->(%p)\n", This, aHostPort);
1559
1560     if(This->uri)
1561         return nsIURI_SetHostPort(This->uri, aHostPort);
1562
1563     FIXME("default action not implemented\n");
1564     return NS_ERROR_NOT_IMPLEMENTED;
1565 }
1566
1567 static nsresult NSAPI nsURI_GetHost(nsIWineURI *iface, nsACString *aHost)
1568 {
1569     nsURI *This = NSURI_THIS(iface);
1570
1571     TRACE("(%p)->(%p)\n", This, aHost);
1572
1573     if(This->uri)
1574         return nsIURI_GetHost(This->uri, aHost);
1575
1576     FIXME("default action not implemented\n");
1577     return NS_ERROR_NOT_IMPLEMENTED;
1578 }
1579
1580 static nsresult NSAPI nsURI_SetHost(nsIWineURI *iface, const nsACString *aHost)
1581 {
1582     nsURI *This = NSURI_THIS(iface);
1583
1584     TRACE("(%p)->(%p)\n", This, aHost);
1585
1586     if(This->uri)
1587         return nsIURI_SetHost(This->uri, aHost);
1588
1589     FIXME("default action not implemented\n");
1590     return NS_ERROR_NOT_IMPLEMENTED;
1591 }
1592
1593 static nsresult NSAPI nsURI_GetPort(nsIWineURI *iface, PRInt32 *aPort)
1594 {
1595     nsURI *This = NSURI_THIS(iface);
1596
1597     TRACE("(%p)->(%p)\n", This, aPort);
1598
1599     if(This->uri)
1600         return nsIURI_GetPort(This->uri, aPort);
1601
1602     FIXME("default action not implemented\n");
1603     return NS_ERROR_NOT_IMPLEMENTED;
1604 }
1605
1606 static nsresult NSAPI nsURI_SetPort(nsIWineURI *iface, PRInt32 aPort)
1607 {
1608     nsURI *This = NSURI_THIS(iface);
1609
1610     TRACE("(%p)->(%d)\n", This, aPort);
1611
1612     if(This->uri)
1613         return nsIURI_SetPort(This->uri, aPort);
1614
1615     FIXME("default action not implemented\n");
1616     return NS_ERROR_NOT_IMPLEMENTED;
1617 }
1618
1619 static nsresult NSAPI nsURI_GetPath(nsIWineURI *iface, nsACString *aPath)
1620 {
1621     nsURI *This = NSURI_THIS(iface);
1622
1623     TRACE("(%p)->(%p)\n", This, aPath);
1624
1625     if(This->uri)
1626         return nsIURI_GetPath(This->uri, aPath);
1627
1628     FIXME("default action not implemented\n");
1629     return NS_ERROR_NOT_IMPLEMENTED;
1630 }
1631
1632 static nsresult NSAPI nsURI_SetPath(nsIWineURI *iface, const nsACString *aPath)
1633 {
1634     nsURI *This = NSURI_THIS(iface);
1635     const char *path;
1636
1637     nsACString_GetData(aPath, &path);
1638     TRACE("(%p)->(%p(%s))\n", This, aPath, debugstr_a(path));
1639
1640
1641     if(This->wine_url) {
1642         WCHAR new_url[INTERNET_MAX_URL_LENGTH];
1643         DWORD size = sizeof(new_url)/sizeof(WCHAR);
1644         LPWSTR pathw;
1645         HRESULT hres;
1646
1647         pathw = heap_strdupAtoW(path);
1648         hres = UrlCombineW(This->wine_url, pathw, new_url, &size, 0);
1649         heap_free(pathw);
1650         if(SUCCEEDED(hres))
1651             nsIWineURI_SetWineURL(NSWINEURI(This), new_url);
1652         else
1653             WARN("UrlCombine failed: %08x\n", hres);
1654     }
1655
1656     if(!This->uri)
1657         return NS_OK;
1658
1659     return nsIURI_SetPath(This->uri, aPath);
1660 }
1661
1662 static nsresult NSAPI nsURI_Equals(nsIWineURI *iface, nsIURI *other, PRBool *_retval)
1663 {
1664     nsURI *This = NSURI_THIS(iface);
1665     nsIWineURI *wine_uri;
1666     LPCWSTR other_url = NULL;
1667     nsresult nsres;
1668
1669     TRACE("(%p)->(%p %p)\n", This, other, _retval);
1670
1671     if(This->uri)
1672         return nsIURI_Equals(This->uri, other, _retval);
1673
1674     nsres = nsIURI_QueryInterface(other, &IID_nsIWineURI, (void**)&wine_uri);
1675     if(NS_FAILED(nsres)) {
1676         TRACE("Could not get nsIWineURI interface\n");
1677         *_retval = FALSE;
1678         return NS_OK;
1679     }
1680
1681     nsIWineURI_GetWineURL(wine_uri, &other_url);
1682     *_retval = !UrlCompareW(This->wine_url, other_url, TRUE);
1683     nsIWineURI_Release(wine_uri);
1684
1685     return NS_OK;
1686 }
1687
1688 static nsresult NSAPI nsURI_SchemeIs(nsIWineURI *iface, const char *scheme, PRBool *_retval)
1689 {
1690     nsURI *This = NSURI_THIS(iface);
1691
1692     TRACE("(%p)->(%s %p)\n", This, debugstr_a(scheme), _retval);
1693
1694     if(This->use_wine_url) {
1695         WCHAR buf[INTERNET_MAX_SCHEME_LENGTH];
1696         int len = MultiByteToWideChar(CP_ACP, 0, scheme, -1, buf, sizeof(buf)/sizeof(WCHAR))-1;
1697
1698         *_retval = lstrlenW(This->wine_url) > len
1699             && This->wine_url[len] == ':'
1700             && !memcmp(buf, This->wine_url, len*sizeof(WCHAR));
1701         return NS_OK;
1702     }
1703
1704     if(This->uri)
1705         return nsIURI_SchemeIs(This->uri, scheme, _retval);
1706
1707     TRACE("returning error\n");
1708     return NS_ERROR_NOT_IMPLEMENTED;
1709 }
1710
1711 static nsresult NSAPI nsURI_Clone(nsIWineURI *iface, nsIURI **_retval)
1712 {
1713     nsURI *This = NSURI_THIS(iface);
1714     nsIURI *nsuri = NULL;
1715     nsIWineURI *wine_uri;
1716     nsresult nsres;
1717
1718     TRACE("(%p)->(%p)\n", This, _retval);
1719
1720     if(This->uri) {
1721         nsres = nsIURI_Clone(This->uri, &nsuri);
1722         if(NS_FAILED(nsres)) {
1723             WARN("Clone failed: %08x\n", nsres);
1724             return nsres;
1725         }
1726     }
1727
1728     nsres = create_uri(nsuri, This->container, &wine_uri);
1729     if(NS_FAILED(nsres)) {
1730         WARN("create_uri failed: %08x\n", nsres);
1731         return nsres;
1732     }
1733
1734     *_retval = (nsIURI*)wine_uri;
1735     return nsIWineURI_SetWineURL(wine_uri, This->wine_url);
1736 }
1737
1738 static nsresult NSAPI nsURI_Resolve(nsIWineURI *iface, const nsACString *arelativePath,
1739         nsACString *_retval)
1740 {
1741     nsURI *This = NSURI_THIS(iface);
1742
1743     TRACE("(%p)->(%p %p)\n", This, arelativePath, _retval);
1744
1745     if(This->uri)
1746         return nsIURI_Resolve(This->uri, arelativePath, _retval);
1747
1748     FIXME("default action not implemented\n");
1749     return NS_ERROR_NOT_IMPLEMENTED;
1750 }
1751
1752 static nsresult NSAPI nsURI_GetAsciiSpec(nsIWineURI *iface, nsACString *aAsciiSpec)
1753 {
1754     nsURI *This = NSURI_THIS(iface);
1755
1756     TRACE("(%p)->(%p)\n", This, aAsciiSpec);
1757
1758     if(This->use_wine_url)
1759         return nsIURI_GetSpec(NSURI(This), aAsciiSpec);
1760
1761     if(This->uri)
1762         return nsIURI_GetAsciiSpec(This->uri, aAsciiSpec);
1763
1764     TRACE("returning error\n");
1765     return NS_ERROR_NOT_IMPLEMENTED;
1766 }
1767
1768 static nsresult NSAPI nsURI_GetAsciiHost(nsIWineURI *iface, nsACString *aAsciiHost)
1769 {
1770     nsURI *This = NSURI_THIS(iface);
1771
1772     TRACE("(%p)->(%p)\n", This, aAsciiHost);
1773
1774     if(This->uri)
1775         return nsIURI_GetAsciiHost(This->uri, aAsciiHost);
1776
1777     FIXME("default action not implemented\n");
1778     return NS_ERROR_NOT_IMPLEMENTED;
1779 }
1780
1781 static nsresult NSAPI nsURI_GetOriginCharset(nsIWineURI *iface, nsACString *aOriginCharset)
1782 {
1783     nsURI *This = NSURI_THIS(iface);
1784
1785     TRACE("(%p)->(%p)\n", This, aOriginCharset);
1786
1787     if(This->uri)
1788         return nsIURI_GetOriginCharset(This->uri, aOriginCharset);
1789
1790     FIXME("default action not implemented\n");
1791     return NS_ERROR_NOT_IMPLEMENTED;
1792 }
1793
1794 static nsresult NSAPI nsURL_GetFilePath(nsIWineURI *iface, nsACString *aFilePath)
1795 {
1796     nsURI *This = NSURI_THIS(iface);
1797
1798     TRACE("(%p)->(%p)\n", This, aFilePath);
1799
1800     if(This->nsurl)
1801         return nsIURL_GetFilePath(This->nsurl, aFilePath);
1802
1803     FIXME("default action not implemented\n");
1804     return NS_ERROR_NOT_IMPLEMENTED;
1805 }
1806
1807 static nsresult NSAPI nsURL_SetFilePath(nsIWineURI *iface, const nsACString *aFilePath)
1808 {
1809     nsURI *This = NSURI_THIS(iface);
1810
1811     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFilePath));
1812
1813     if(This->nsurl)
1814         return nsIURL_SetFilePath(This->nsurl, aFilePath);
1815
1816     FIXME("default action not implemented\n");
1817     return NS_ERROR_NOT_IMPLEMENTED;
1818 }
1819
1820 static nsresult NSAPI nsURL_GetParam(nsIWineURI *iface, nsACString *aParam)
1821 {
1822     nsURI *This = NSURI_THIS(iface);
1823
1824     TRACE("(%p)->(%p)\n", This, aParam);
1825
1826     if(This->nsurl)
1827         return nsIURL_GetParam(This->nsurl, aParam);
1828
1829     FIXME("default action not implemented\n");
1830     return NS_ERROR_NOT_IMPLEMENTED;
1831 }
1832
1833 static nsresult NSAPI nsURL_SetParam(nsIWineURI *iface, const nsACString *aParam)
1834 {
1835     nsURI *This = NSURI_THIS(iface);
1836
1837     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aParam));
1838
1839     if(This->nsurl)
1840         return nsIURL_SetParam(This->nsurl, aParam);
1841
1842     FIXME("default action not implemented\n");
1843     return NS_ERROR_NOT_IMPLEMENTED;
1844 }
1845
1846 static nsresult NSAPI nsURL_GetQuery(nsIWineURI *iface, nsACString *aQuery)
1847 {
1848     nsURI *This = NSURI_THIS(iface);
1849
1850     TRACE("(%p)->(%p)\n", This, aQuery);
1851
1852     if(This->nsurl)
1853         return nsIURL_GetQuery(This->nsurl, aQuery);
1854
1855     FIXME("default action not implemented\n");
1856     return NS_ERROR_NOT_IMPLEMENTED;
1857 }
1858
1859 static nsresult NSAPI nsURL_SetQuery(nsIWineURI *iface, const nsACString *aQuery)
1860 {
1861     nsURI *This = NSURI_THIS(iface);
1862     const WCHAR *ptr1, *ptr2;
1863     const char *query;
1864     WCHAR *new_url, *ptr;
1865     DWORD len, size;
1866
1867     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aQuery));
1868
1869     if(This->nsurl)
1870         nsIURL_SetQuery(This->nsurl, aQuery);
1871
1872     if(!This->wine_url)
1873         return NS_OK;
1874
1875     nsACString_GetData(aQuery, &query);
1876     size = len = MultiByteToWideChar(CP_ACP, 0, query, -1, NULL, 0);
1877     ptr1 = strchrW(This->wine_url, '?');
1878     if(ptr1) {
1879         size += ptr1-This->wine_url;
1880         ptr2 = strchrW(ptr1, '#');
1881         if(ptr2)
1882             size += strlenW(ptr2);
1883     }else {
1884         ptr1 = This->wine_url + strlenW(This->wine_url);
1885         ptr2 = NULL;
1886         size += strlenW(This->wine_url);
1887     }
1888
1889     if(*query)
1890         size++;
1891
1892     new_url = heap_alloc(size*sizeof(WCHAR));
1893     memcpy(new_url, This->wine_url, (ptr1-This->wine_url)*sizeof(WCHAR));
1894     ptr = new_url + (ptr1-This->wine_url);
1895     if(*query) {
1896         *ptr++ = '?';
1897         MultiByteToWideChar(CP_ACP, 0, query, -1, ptr, len);
1898         ptr += len-1;
1899     }
1900     if(ptr2)
1901         strcpyW(ptr, ptr2);
1902     else
1903         *ptr = 0;
1904
1905     TRACE("setting %s\n", debugstr_w(new_url));
1906
1907     heap_free(This->wine_url);
1908     This->wine_url = new_url;
1909     return NS_OK;
1910 }
1911
1912 static nsresult NSAPI nsURL_GetRef(nsIWineURI *iface, nsACString *aRef)
1913 {
1914     nsURI *This = NSURI_THIS(iface);
1915
1916     TRACE("(%p)->(%p)\n", This, aRef);
1917
1918     if(This->nsurl)
1919         return nsIURL_GetRef(This->nsurl, aRef);
1920
1921     FIXME("default action not implemented\n");
1922     return NS_ERROR_NOT_IMPLEMENTED;
1923 }
1924
1925 static nsresult NSAPI nsURL_SetRef(nsIWineURI *iface, const nsACString *aRef)
1926 {
1927     nsURI *This = NSURI_THIS(iface);
1928
1929     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aRef));
1930
1931     if(This->nsurl)
1932         return nsIURL_SetRef(This->nsurl, aRef);
1933
1934     FIXME("default action not implemented\n");
1935     return NS_ERROR_NOT_IMPLEMENTED;
1936 }
1937
1938 static nsresult NSAPI nsURL_GetDirectory(nsIWineURI *iface, nsACString *aDirectory)
1939 {
1940     nsURI *This = NSURI_THIS(iface);
1941
1942     TRACE("(%p)->(%p)\n", This, aDirectory);
1943
1944     if(This->nsurl)
1945         return nsIURL_GetDirectory(This->nsurl, aDirectory);
1946
1947     FIXME("default action not implemented\n");
1948     return NS_ERROR_NOT_IMPLEMENTED;
1949 }
1950
1951 static nsresult NSAPI nsURL_SetDirectory(nsIWineURI *iface, const nsACString *aDirectory)
1952 {
1953     nsURI *This = NSURI_THIS(iface);
1954
1955     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aDirectory));
1956
1957     if(This->nsurl)
1958         return nsIURL_SetDirectory(This->nsurl, aDirectory);
1959
1960     FIXME("default action not implemented\n");
1961     return NS_ERROR_NOT_IMPLEMENTED;
1962 }
1963
1964 static nsresult NSAPI nsURL_GetFileName(nsIWineURI *iface, nsACString *aFileName)
1965 {
1966     nsURI *This = NSURI_THIS(iface);
1967
1968     TRACE("(%p)->(%p)\n", This, aFileName);
1969
1970     if(This->nsurl)
1971         return nsIURL_GetFileName(This->nsurl, aFileName);
1972
1973     FIXME("default action not implemented\n");
1974     return NS_ERROR_NOT_IMPLEMENTED;
1975 }
1976
1977 static nsresult NSAPI nsURL_SetFileName(nsIWineURI *iface, const nsACString *aFileName)
1978 {
1979     nsURI *This = NSURI_THIS(iface);
1980
1981     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileName));
1982
1983     if(This->nsurl)
1984         return nsIURL_SetFileName(This->nsurl, aFileName);
1985
1986     FIXME("default action not implemented\n");
1987     return NS_ERROR_NOT_IMPLEMENTED;
1988 }
1989
1990 static nsresult NSAPI nsURL_GetFileBaseName(nsIWineURI *iface, nsACString *aFileBaseName)
1991 {
1992     nsURI *This = NSURI_THIS(iface);
1993
1994     TRACE("(%p)->(%p)\n", This, aFileBaseName);
1995
1996     if(This->nsurl)
1997         return nsIURL_GetFileBaseName(This->nsurl, aFileBaseName);
1998
1999     FIXME("default action not implemented\n");
2000     return NS_ERROR_NOT_IMPLEMENTED;
2001 }
2002
2003 static nsresult NSAPI nsURL_SetFileBaseName(nsIWineURI *iface, const nsACString *aFileBaseName)
2004 {
2005     nsURI *This = NSURI_THIS(iface);
2006
2007     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileBaseName));
2008
2009     if(This->nsurl)
2010         return nsIURL_SetFileBaseName(This->nsurl, aFileBaseName);
2011
2012     FIXME("default action not implemented\n");
2013     return NS_ERROR_NOT_IMPLEMENTED;
2014 }
2015
2016 static nsresult NSAPI nsURL_GetFileExtension(nsIWineURI *iface, nsACString *aFileExtension)
2017 {
2018     nsURI *This = NSURI_THIS(iface);
2019
2020     TRACE("(%p)->(%p)\n", This, aFileExtension);
2021
2022     if(This->nsurl)
2023         return nsIURL_GetFileExtension(This->nsurl, aFileExtension);
2024
2025     FIXME("default action not implemented\n");
2026     return NS_ERROR_NOT_IMPLEMENTED;
2027 }
2028
2029 static nsresult NSAPI nsURL_SetFileExtension(nsIWineURI *iface, const nsACString *aFileExtension)
2030 {
2031     nsURI *This = NSURI_THIS(iface);
2032
2033     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileExtension));
2034
2035     if(This->nsurl)
2036         return nsIURL_SetFileExtension(This->nsurl, aFileExtension);
2037
2038     FIXME("default action not implemented\n");
2039     return NS_ERROR_NOT_IMPLEMENTED;
2040 }
2041
2042 static nsresult NSAPI nsURL_GetCommonBaseSpec(nsIWineURI *iface, nsIURI *aURIToCompare, nsACString *_retval)
2043 {
2044     nsURI *This = NSURI_THIS(iface);
2045
2046     TRACE("(%p)->(%p %p)\n", This, aURIToCompare, _retval);
2047
2048     if(This->nsurl)
2049         return nsIURL_GetCommonBaseSpec(This->nsurl, aURIToCompare, _retval);
2050
2051     FIXME("default action not implemented\n");
2052     return NS_ERROR_NOT_IMPLEMENTED;
2053 }
2054
2055 static nsresult NSAPI nsURL_GetRelativeSpec(nsIWineURI *iface, nsIURI *aURIToCompare, nsACString *_retval)
2056 {
2057     nsURI *This = NSURI_THIS(iface);
2058
2059     TRACE("(%p)->(%p %p)\n", This, aURIToCompare, _retval);
2060
2061     if(This->nsurl)
2062         return nsIURL_GetRelativeSpec(This->nsurl, aURIToCompare, _retval);
2063
2064     FIXME("default action not implemented\n");
2065     return NS_ERROR_NOT_IMPLEMENTED;
2066 }
2067
2068 static nsresult NSAPI nsURI_GetNSContainer(nsIWineURI *iface, NSContainer **aContainer)
2069 {
2070     nsURI *This = NSURI_THIS(iface);
2071
2072     TRACE("(%p)->(%p)\n", This, aContainer);
2073
2074     if(This->container)
2075         nsIWebBrowserChrome_AddRef(NSWBCHROME(This->container));
2076     *aContainer = This->container;
2077
2078     return NS_OK;
2079 }
2080
2081 static nsresult NSAPI nsURI_SetNSContainer(nsIWineURI *iface, NSContainer *aContainer)
2082 {
2083     nsURI *This = NSURI_THIS(iface);
2084
2085     TRACE("(%p)->(%p)\n", This, aContainer);
2086
2087     if(This->container) {
2088         if(This->container == aContainer)
2089             return NS_OK;
2090         TRACE("Changing %p -> %p\n", This->container, aContainer);
2091         nsIWebBrowserChrome_Release(NSWBCHROME(This->container));
2092     }
2093
2094     if(aContainer)
2095         nsIWebBrowserChrome_AddRef(NSWBCHROME(aContainer));
2096     This->container = aContainer;
2097
2098     return NS_OK;
2099 }
2100
2101 static nsresult NSAPI nsURI_GetIsDocumentURI(nsIWineURI *iface, PRBool *aIsDocumentURI)
2102 {
2103     nsURI *This = NSURI_THIS(iface);
2104
2105     TRACE("(%p)->(%p)\n", This, aIsDocumentURI);
2106
2107     *aIsDocumentURI = This->is_doc_uri;
2108     return NS_OK;
2109 }
2110
2111 static nsresult NSAPI nsURI_SetIsDocumentURI(nsIWineURI *iface, PRBool aIsDocumentURI)
2112 {
2113     nsURI *This = NSURI_THIS(iface);
2114
2115     TRACE("(%p)->(%x)\n", This, aIsDocumentURI);
2116
2117     This->is_doc_uri = aIsDocumentURI;
2118     return NS_OK;
2119 }
2120
2121 static nsresult NSAPI nsURI_GetWineURL(nsIWineURI *iface, LPCWSTR *aURL)
2122 {
2123     nsURI *This = NSURI_THIS(iface);
2124
2125     TRACE("(%p)->(%p)\n", This, aURL);
2126
2127     *aURL = This->wine_url;
2128     return NS_OK;
2129 }
2130
2131 static nsresult NSAPI nsURI_SetWineURL(nsIWineURI *iface, LPCWSTR aURL)
2132 {
2133     nsURI *This = NSURI_THIS(iface);
2134
2135     static const WCHAR wszFtp[]   = {'f','t','p',':'};
2136     static const WCHAR wszHttp[]  = {'h','t','t','p',':'};
2137     static const WCHAR wszHttps[] = {'h','t','t','p','s',':'};
2138
2139     TRACE("(%p)->(%s)\n", This, debugstr_w(aURL));
2140
2141     heap_free(This->wine_url);
2142
2143     if(aURL) {
2144         int len = strlenW(aURL)+1;
2145         This->wine_url = heap_alloc(len*sizeof(WCHAR));
2146         memcpy(This->wine_url, aURL, len*sizeof(WCHAR));
2147
2148         /* FIXME: Always use wine url */
2149         This->use_wine_url =
2150                strncmpW(aURL, wszFtp,   sizeof(wszFtp)/sizeof(WCHAR))
2151             && strncmpW(aURL, wszHttp,  sizeof(wszHttp)/sizeof(WCHAR))
2152             && strncmpW(aURL, wszHttps, sizeof(wszHttps)/sizeof(WCHAR));
2153     }else {
2154         This->wine_url = NULL;
2155         This->use_wine_url = FALSE;
2156     }
2157
2158     return NS_OK;
2159 }
2160
2161 #undef NSURI_THIS
2162
2163 static const nsIWineURIVtbl nsWineURIVtbl = {
2164     nsURI_QueryInterface,
2165     nsURI_AddRef,
2166     nsURI_Release,
2167     nsURI_GetSpec,
2168     nsURI_SetSpec,
2169     nsURI_GetPrePath,
2170     nsURI_GetScheme,
2171     nsURI_SetScheme,
2172     nsURI_GetUserPass,
2173     nsURI_SetUserPass,
2174     nsURI_GetUsername,
2175     nsURI_SetUsername,
2176     nsURI_GetPassword,
2177     nsURI_SetPassword,
2178     nsURI_GetHostPort,
2179     nsURI_SetHostPort,
2180     nsURI_GetHost,
2181     nsURI_SetHost,
2182     nsURI_GetPort,
2183     nsURI_SetPort,
2184     nsURI_GetPath,
2185     nsURI_SetPath,
2186     nsURI_Equals,
2187     nsURI_SchemeIs,
2188     nsURI_Clone,
2189     nsURI_Resolve,
2190     nsURI_GetAsciiSpec,
2191     nsURI_GetAsciiHost,
2192     nsURI_GetOriginCharset,
2193     nsURL_GetFilePath,
2194     nsURL_SetFilePath,
2195     nsURL_GetParam,
2196     nsURL_SetParam,
2197     nsURL_GetQuery,
2198     nsURL_SetQuery,
2199     nsURL_GetRef,
2200     nsURL_SetRef,
2201     nsURL_GetDirectory,
2202     nsURL_SetDirectory,
2203     nsURL_GetFileName,
2204     nsURL_SetFileName,
2205     nsURL_GetFileBaseName,
2206     nsURL_SetFileBaseName,
2207     nsURL_GetFileExtension,
2208     nsURL_SetFileExtension,
2209     nsURL_GetCommonBaseSpec,
2210     nsURL_GetRelativeSpec,
2211     nsURI_GetNSContainer,
2212     nsURI_SetNSContainer,
2213     nsURI_GetIsDocumentURI,
2214     nsURI_SetIsDocumentURI,
2215     nsURI_GetWineURL,
2216     nsURI_SetWineURL
2217 };
2218
2219 static nsresult create_uri(nsIURI *uri, NSContainer *container, nsIWineURI **_retval)
2220 {
2221     nsURI *ret = heap_alloc(sizeof(nsURI));
2222
2223     ret->lpWineURIVtbl = &nsWineURIVtbl;
2224     ret->ref = 1;
2225     ret->uri = uri;
2226     ret->container = container;
2227     ret->wine_url = NULL;
2228     ret->is_doc_uri = FALSE;
2229     ret->use_wine_url = FALSE;
2230
2231     if(container)
2232         nsIWebBrowserChrome_AddRef(NSWBCHROME(container));
2233
2234     if(uri)
2235         nsIURI_QueryInterface(uri, &IID_nsIURL, (void**)&ret->nsurl);
2236     else
2237         ret->nsurl = NULL;
2238
2239     TRACE("retval=%p\n", ret);
2240     *_retval = NSWINEURI(ret);
2241     return NS_OK;
2242 }
2243
2244 typedef struct {
2245     const nsIProtocolHandlerVtbl  *lpProtocolHandlerVtbl;
2246
2247     LONG ref;
2248
2249     nsIProtocolHandler *nshandler;
2250 } nsProtocolHandler;
2251
2252 #define NSPROTHANDLER(x)  ((nsIProtocolHandler*)  &(x)->lpProtocolHandlerVtbl)
2253
2254 #define NSPROTHANDLER_THIS(iface) DEFINE_THIS(nsProtocolHandler, ProtocolHandler, iface)
2255
2256 static nsresult NSAPI nsProtocolHandler_QueryInterface(nsIProtocolHandler *iface, nsIIDRef riid,
2257         nsQIResult result)
2258 {
2259     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2260
2261     *result = NULL;
2262
2263     if(IsEqualGUID(&IID_nsISupports, riid)) {
2264         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
2265         *result = NSPROTHANDLER(This);
2266     }else if(IsEqualGUID(&IID_nsIProtocolHandler, riid)) {
2267         TRACE("(%p)->(IID_nsIProtocolHandler %p)\n", This, result);
2268         *result = NSPROTHANDLER(This);
2269     }else if(IsEqualGUID(&IID_nsIExternalProtocolHandler, riid)) {
2270         TRACE("(%p)->(IID_nsIExternalProtocolHandler %p), returning NULL\n", This, result);
2271         return NS_NOINTERFACE;
2272     }
2273
2274     if(*result) {
2275         nsISupports_AddRef((nsISupports*)*result);
2276         return NS_OK;
2277     }
2278
2279     WARN("(%s %p)\n", debugstr_guid(riid), result);
2280     return NS_NOINTERFACE;
2281 }
2282
2283 static nsrefcnt NSAPI nsProtocolHandler_AddRef(nsIProtocolHandler *iface)
2284 {
2285     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2286     LONG ref = InterlockedIncrement(&This->ref);
2287
2288     TRACE("(%p) ref=%d\n", This, ref);
2289
2290     return ref;
2291 }
2292
2293 static nsrefcnt NSAPI nsProtocolHandler_Release(nsIProtocolHandler *iface)
2294 {
2295     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2296     LONG ref = InterlockedDecrement(&This->ref);
2297
2298     TRACE("(%p) ref=%d\n", This, ref);
2299
2300     if(!ref) {
2301         if(This->nshandler)
2302             nsIProtocolHandler_Release(This->nshandler);
2303         heap_free(This);
2304     }
2305
2306     return ref;
2307 }
2308
2309 static nsresult NSAPI nsProtocolHandler_GetScheme(nsIProtocolHandler *iface, nsACString *aScheme)
2310 {
2311     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2312
2313     TRACE("(%p)->(%p)\n", This, aScheme);
2314
2315     if(This->nshandler)
2316         return nsIProtocolHandler_GetScheme(This->nshandler, aScheme);
2317     return NS_ERROR_NOT_IMPLEMENTED;
2318 }
2319
2320 static nsresult NSAPI nsProtocolHandler_GetDefaultPort(nsIProtocolHandler *iface,
2321         PRInt32 *aDefaultPort)
2322 {
2323     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2324
2325     TRACE("(%p)->(%p)\n", This, aDefaultPort);
2326
2327     if(This->nshandler)
2328         return nsIProtocolHandler_GetDefaultPort(This->nshandler, aDefaultPort);
2329     return NS_ERROR_NOT_IMPLEMENTED;
2330 }
2331
2332 static nsresult NSAPI nsProtocolHandler_GetProtocolFlags(nsIProtocolHandler *iface,
2333                                                          PRUint32 *aProtocolFlags)
2334 {
2335     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2336
2337     TRACE("(%p)->(%p)\n", This, aProtocolFlags);
2338
2339     if(This->nshandler)
2340         return nsIProtocolHandler_GetProtocolFlags(This->nshandler, aProtocolFlags);
2341     return NS_ERROR_NOT_IMPLEMENTED;
2342 }
2343
2344 static nsresult NSAPI nsProtocolHandler_NewURI(nsIProtocolHandler *iface,
2345         const nsACString *aSpec, const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval)
2346 {
2347     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2348
2349     TRACE("((%p)->%p %s %p %p)\n", This, aSpec, debugstr_a(aOriginCharset), aBaseURI, _retval);
2350
2351     if(This->nshandler)
2352         return nsIProtocolHandler_NewURI(This->nshandler, aSpec, aOriginCharset, aBaseURI, _retval);
2353     return NS_ERROR_NOT_IMPLEMENTED;
2354 }
2355
2356 static nsresult NSAPI nsProtocolHandler_NewChannel(nsIProtocolHandler *iface,
2357         nsIURI *aURI, nsIChannel **_retval)
2358 {
2359     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2360
2361     TRACE("(%p)->(%p %p)\n", This, aURI, _retval);
2362
2363     if(This->nshandler)
2364         return nsIProtocolHandler_NewChannel(This->nshandler, aURI, _retval);
2365     return NS_ERROR_NOT_IMPLEMENTED;
2366 }
2367
2368 static nsresult NSAPI nsProtocolHandler_AllowPort(nsIProtocolHandler *iface,
2369         PRInt32 port, const char *scheme, PRBool *_retval)
2370 {
2371     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2372
2373     TRACE("(%p)->(%d %s %p)\n", This, port, debugstr_a(scheme), _retval);
2374
2375     if(This->nshandler)
2376         return nsIProtocolHandler_AllowPort(This->nshandler, port, scheme, _retval);
2377     return NS_ERROR_NOT_IMPLEMENTED;
2378 }
2379
2380 #undef NSPROTHANDLER_THIS
2381
2382 static const nsIProtocolHandlerVtbl nsProtocolHandlerVtbl = {
2383     nsProtocolHandler_QueryInterface,
2384     nsProtocolHandler_AddRef,
2385     nsProtocolHandler_Release,
2386     nsProtocolHandler_GetScheme,
2387     nsProtocolHandler_GetDefaultPort,
2388     nsProtocolHandler_GetProtocolFlags,
2389     nsProtocolHandler_NewURI,
2390     nsProtocolHandler_NewChannel,
2391     nsProtocolHandler_AllowPort
2392 };
2393
2394 static nsIProtocolHandler *create_protocol_handler(nsIProtocolHandler *nshandler)
2395 {
2396     nsProtocolHandler *ret = heap_alloc(sizeof(nsProtocolHandler));
2397
2398     ret->lpProtocolHandlerVtbl = &nsProtocolHandlerVtbl;
2399     ret->ref = 1;
2400     ret->nshandler = nshandler;
2401
2402     return NSPROTHANDLER(ret);
2403 }
2404
2405 static nsresult NSAPI nsIOService_QueryInterface(nsIIOService*,nsIIDRef,nsQIResult);
2406
2407 static nsrefcnt NSAPI nsIOService_AddRef(nsIIOService *iface)
2408 {
2409     return 2;
2410 }
2411
2412 static nsrefcnt NSAPI nsIOService_Release(nsIIOService *iface)
2413 {
2414     return 1;
2415 }
2416
2417 static nsresult NSAPI nsIOService_GetProtocolHandler(nsIIOService *iface, const char *aScheme,
2418                                                      nsIProtocolHandler **_retval)
2419 {
2420     nsIExternalProtocolHandler *nsexthandler;
2421     nsIProtocolHandler *nshandler;
2422     nsresult nsres;
2423
2424     TRACE("(%s %p)\n", debugstr_a(aScheme), _retval);
2425
2426     nsres = nsIIOService_GetProtocolHandler(nsio, aScheme, &nshandler);
2427     if(NS_FAILED(nsres)) {
2428         WARN("GetProtocolHandler failed: %08x\n", nsres);
2429         return nsres;
2430     }
2431
2432     nsres = nsIProtocolHandler_QueryInterface(nshandler, &IID_nsIExternalProtocolHandler,
2433                                               (void**)&nsexthandler);
2434     if(NS_FAILED(nsres)) {
2435         *_retval = nshandler;
2436         return NS_OK;
2437     }
2438
2439     nsIExternalProtocolHandler_Release(nsexthandler);
2440     *_retval = create_protocol_handler(nshandler);
2441     TRACE("return %p\n", *_retval);
2442     return NS_OK;
2443 }
2444
2445 static nsresult NSAPI nsIOService_GetProtocolFlags(nsIIOService *iface, const char *aScheme,
2446                                                     PRUint32 *_retval)
2447 {
2448     TRACE("(%s %p)\n", debugstr_a(aScheme), _retval);
2449     return nsIIOService_GetProtocolFlags(nsio, aScheme, _retval);
2450 }
2451
2452 static BOOL is_gecko_special_uri(const char *spec)
2453 {
2454     static const char *special_schemes[] = {"chrome:", "jar:", "resource:", "javascript:", "wyciwyg:"};
2455     int i;
2456
2457     for(i=0; i < sizeof(special_schemes)/sizeof(*special_schemes); i++) {
2458         if(!strncasecmp(spec, special_schemes[i], strlen(special_schemes[i])))
2459             return TRUE;
2460     }
2461
2462     return FALSE;
2463 }
2464
2465 static nsresult NSAPI nsIOService_NewURI(nsIIOService *iface, const nsACString *aSpec,
2466         const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval)
2467 {
2468     const char *spec = NULL;
2469     NSContainer *nscontainer = NULL;
2470     nsIURI *uri = NULL;
2471     LPCWSTR base_wine_url = NULL;
2472     nsIWineURI *base_wine_uri = NULL, *wine_uri;
2473     BOOL is_wine_uri = FALSE;
2474     nsresult nsres;
2475
2476     nsACString_GetData(aSpec, &spec);
2477
2478     TRACE("(%p(%s) %s %p %p)\n", aSpec, debugstr_a(spec), debugstr_a(aOriginCharset),
2479           aBaseURI, _retval);
2480
2481     if(is_gecko_special_uri(spec))
2482         return nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
2483
2484     if(!strncmp(spec, "wine:", 5)) {
2485         spec += 5;
2486         is_wine_uri = TRUE;
2487     }
2488
2489     if(aBaseURI) {
2490         nsACString base_uri_str;
2491         const char *base_uri = NULL;
2492
2493         nsACString_Init(&base_uri_str, NULL);
2494
2495         nsres = nsIURI_GetSpec(aBaseURI, &base_uri_str);
2496         if(NS_SUCCEEDED(nsres)) {
2497             nsACString_GetData(&base_uri_str, &base_uri);
2498             TRACE("base_uri=%s\n", debugstr_a(base_uri));
2499         }else {
2500             ERR("GetSpec failed: %08x\n", nsres);
2501         }
2502
2503         nsACString_Finish(&base_uri_str);
2504     }
2505
2506     nsres = nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, &uri);
2507     if(NS_FAILED(nsres))
2508         TRACE("NewURI failed: %08x\n", nsres);
2509
2510     if(aBaseURI) {
2511         nsres = nsIURI_QueryInterface(aBaseURI, &IID_nsIWineURI, (void**)&base_wine_uri);
2512         if(NS_SUCCEEDED(nsres)) {
2513             nsIWineURI_GetNSContainer(base_wine_uri, &nscontainer);
2514             nsIWineURI_GetWineURL(base_wine_uri, &base_wine_url);
2515         }else {
2516             TRACE("Could not get base nsIWineURI: %08x\n", nsres);
2517         }
2518     }
2519
2520     TRACE("nscontainer = %p\n", nscontainer);
2521
2522     nsres = create_uri(uri, nscontainer, &wine_uri);
2523     *_retval = (nsIURI*)wine_uri;
2524
2525     if(nscontainer)
2526         nsIWebBrowserChrome_Release(NSWBCHROME(nscontainer));
2527
2528     if(base_wine_url) {
2529         WCHAR url[INTERNET_MAX_URL_LENGTH], rel_url[INTERNET_MAX_URL_LENGTH];
2530         DWORD len;
2531         HRESULT hres;
2532
2533         MultiByteToWideChar(CP_ACP, 0, spec, -1, rel_url, sizeof(rel_url)/sizeof(WCHAR));
2534
2535         hres = CoInternetCombineUrl(base_wine_url, rel_url,
2536                                     URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO,
2537                                     url, sizeof(url)/sizeof(WCHAR), &len, 0);
2538         if(SUCCEEDED(hres))
2539             nsIWineURI_SetWineURL(wine_uri, url);
2540         else
2541              WARN("CoCombineUrl failed: %08x\n", hres);
2542     }else if(is_wine_uri) {
2543         WCHAR url[INTERNET_MAX_URL_LENGTH];
2544
2545         MultiByteToWideChar(CP_ACP, 0, spec, -1, url, sizeof(url)/sizeof(WCHAR));
2546         nsIWineURI_SetWineURL(wine_uri, url);
2547     }
2548
2549     if(base_wine_uri)
2550         nsIWineURI_Release(base_wine_uri);
2551
2552     return nsres;
2553 }
2554
2555 static nsresult NSAPI nsIOService_NewFileURI(nsIIOService *iface, nsIFile *aFile,
2556                                              nsIURI **_retval)
2557 {
2558     TRACE("(%p %p)\n", aFile, _retval);
2559     return nsIIOService_NewFileURI(nsio, aFile, _retval);
2560 }
2561
2562 static nsresult NSAPI nsIOService_NewChannelFromURI(nsIIOService *iface, nsIURI *aURI,
2563                                                      nsIChannel **_retval)
2564 {
2565     nsIChannel *channel = NULL;
2566     nsChannel *ret;
2567     nsIWineURI *wine_uri;
2568     nsresult nsres;
2569
2570     TRACE("(%p %p)\n", aURI, _retval);
2571
2572     nsres = nsIIOService_NewChannelFromURI(nsio, aURI, &channel);
2573     if(NS_FAILED(nsres) && nsres != NS_ERROR_UNKNOWN_PROTOCOL) {
2574         WARN("NewChannelFromURI failed: %08x\n", nsres);
2575         *_retval = channel;
2576         return nsres;
2577     }
2578
2579     nsres = nsIURI_QueryInterface(aURI, &IID_nsIWineURI, (void**)&wine_uri);
2580     if(NS_FAILED(nsres)) {
2581         WARN("Could not get nsIWineURI: %08x\n", nsres);
2582         *_retval = channel;
2583         return channel ? NS_OK : NS_ERROR_UNEXPECTED;
2584     }
2585
2586     ret = heap_alloc_zero(sizeof(nsChannel));
2587
2588     ret->lpHttpChannelVtbl = &nsChannelVtbl;
2589     ret->lpUploadChannelVtbl = &nsUploadChannelVtbl;
2590     ret->lpIHttpChannelInternalVtbl = &nsHttpChannelInternalVtbl;
2591     ret->ref = 1;
2592     ret->channel = channel;
2593     ret->uri = wine_uri;
2594
2595     nsIURI_AddRef(aURI);
2596     ret->original_uri = aURI;
2597
2598     if(channel) {
2599         nsIChannel_QueryInterface(channel, &IID_nsIHttpChannel, (void**)&ret->http_channel);
2600         nsIChannel_QueryInterface(channel, &IID_nsIHttpChannelInternal, (void**)&ret->http_channel_internal);
2601     }
2602
2603     *_retval = NSCHANNEL(ret);
2604     return NS_OK;
2605 }
2606
2607 static nsresult NSAPI nsIOService_NewChannel(nsIIOService *iface, const nsACString *aSpec,
2608         const char *aOriginCharset, nsIURI *aBaseURI, nsIChannel **_retval)
2609 {
2610     TRACE("(%p %s %p %p)\n", aSpec, debugstr_a(aOriginCharset), aBaseURI, _retval);
2611     return nsIIOService_NewChannel(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
2612 }
2613
2614 static nsresult NSAPI nsIOService_GetOffline(nsIIOService *iface, PRBool *aOffline)
2615 {
2616     TRACE("(%p)\n", aOffline);
2617     return nsIIOService_GetOffline(nsio, aOffline);
2618 }
2619
2620 static nsresult NSAPI nsIOService_SetOffline(nsIIOService *iface, PRBool aOffline)
2621 {
2622     TRACE("(%x)\n", aOffline);
2623     return nsIIOService_SetOffline(nsio, aOffline);
2624 }
2625
2626 static nsresult NSAPI nsIOService_AllowPort(nsIIOService *iface, PRInt32 aPort,
2627                                              const char *aScheme, PRBool *_retval)
2628 {
2629     TRACE("(%d %s %p)\n", aPort, debugstr_a(aScheme), _retval);
2630     return nsIIOService_AllowPort(nsio, aPort, debugstr_a(aScheme), _retval);
2631 }
2632
2633 static nsresult NSAPI nsIOService_ExtractScheme(nsIIOService *iface, const nsACString *urlString,
2634                                                  nsACString * _retval)
2635 {
2636     TRACE("(%p %p)\n", urlString, _retval);
2637     return nsIIOService_ExtractScheme(nsio, urlString, _retval);
2638 }
2639
2640 static const nsIIOServiceVtbl nsIOServiceVtbl = {
2641     nsIOService_QueryInterface,
2642     nsIOService_AddRef,
2643     nsIOService_Release,
2644     nsIOService_GetProtocolHandler,
2645     nsIOService_GetProtocolFlags,
2646     nsIOService_NewURI,
2647     nsIOService_NewFileURI,
2648     nsIOService_NewChannelFromURI,
2649     nsIOService_NewChannel,
2650     nsIOService_GetOffline,
2651     nsIOService_SetOffline,
2652     nsIOService_AllowPort,
2653     nsIOService_ExtractScheme
2654 };
2655
2656 static nsIIOService nsIOService = { &nsIOServiceVtbl };
2657
2658 static nsresult NSAPI nsNetUtil_QueryInterface(nsINetUtil *iface, nsIIDRef riid,
2659                                                nsQIResult result)
2660 {
2661     return nsIIOService_QueryInterface(&nsIOService, riid, result);
2662 }
2663
2664 static nsrefcnt NSAPI nsNetUtil_AddRef(nsINetUtil *iface)
2665 {
2666     return 2;
2667 }
2668
2669 static nsrefcnt NSAPI nsNetUtil_Release(nsINetUtil *iface)
2670 {
2671     return 1;
2672 }
2673
2674 static nsresult NSAPI nsNetUtil_ParseContentType(nsINetUtil *iface, const nsACString *aTypeHeader,
2675         nsACString *aCharset, PRBool *aHadCharset, nsACString *aContentType)
2676 {
2677     TRACE("(%p %p %p %p)\n", aTypeHeader, aCharset, aHadCharset, aContentType);
2678
2679     return nsINetUtil_ParseContentType(net_util, aTypeHeader, aCharset, aHadCharset, aContentType);
2680 }
2681
2682 static nsresult NSAPI nsNetUtil_ProtocolHasFlags(nsINetUtil *iface, nsIURI *aURI, PRUint32 aFlags, PRBool *_retval)
2683 {
2684     TRACE("()\n");
2685
2686     return nsINetUtil_ProtocolHasFlags(net_util, aURI, aFlags, _retval);
2687 }
2688
2689 static nsresult NSAPI nsNetUtil_URIChainHasFlags(nsINetUtil *iface, nsIURI *aURI, PRUint32 aFlags, PRBool *_retval)
2690 {
2691     TRACE("(%p %08x %p)\n", aURI, aFlags, _retval);
2692
2693     if(aFlags == (1<<11)) {
2694         *_retval = FALSE;
2695         return NS_OK;
2696     }
2697
2698     return nsINetUtil_URIChainHasFlags(net_util, aURI, aFlags, _retval);
2699 }
2700
2701 static nsresult NSAPI nsNetUtil_ToImmutableURI(nsINetUtil *iface, nsIURI *aURI, nsIURI **_retval)
2702 {
2703     TRACE("(%p %p)\n", aURI, _retval);
2704
2705     return nsINetUtil_ToImmutableURI(net_util, aURI, _retval);
2706 }
2707
2708 static nsresult NSAPI nsNetUtil_EscapeString(nsINetUtil *iface, const nsACString *aString,
2709                                              PRUint32 aEscapeType, nsACString *_retval)
2710 {
2711     TRACE("(%p %x %p)\n", aString, aEscapeType, _retval);
2712
2713     return nsINetUtil_EscapeString(net_util, aString, aEscapeType, _retval);
2714 }
2715
2716 static nsresult NSAPI nsNetUtil_EscapeURL(nsINetUtil *iface, const nsACString *aStr, PRUint32 aFlags,
2717                                           nsACString *_retval)
2718 {
2719     TRACE("(%p %08x %p)\n", aStr, aFlags, _retval);
2720
2721     return nsINetUtil_EscapeURL(net_util, aStr, aFlags, _retval);
2722 }
2723
2724 static nsresult NSAPI nsNetUtil_UnescapeString(nsINetUtil *iface, const nsACString *aStr,
2725                                                PRUint32 aFlags, nsACString *_retval)
2726 {
2727     TRACE("(%p %08x %p)\n", aStr, aFlags, _retval);
2728
2729     return nsINetUtil_UnescapeString(net_util, aStr, aFlags, _retval);
2730 }
2731
2732 static nsresult NSAPI nsNetUtil_ExtractCharsetFromContentType(nsINetUtil *iface, const nsACString *aTypeHeader,
2733         nsACString *aCharset, PRInt32 *aCharsetStart, PRInt32 *aCharsetEnd, PRBool *_retval)
2734 {
2735     TRACE("(%p %p %p %p %p)\n", aTypeHeader, aCharset, aCharsetStart, aCharsetEnd, _retval);
2736
2737     return nsINetUtil_ExtractCharsetFromContentType(net_util, aTypeHeader, aCharset, aCharsetStart, aCharsetEnd, _retval);
2738 }
2739
2740 static const nsINetUtilVtbl nsNetUtilVtbl = {
2741     nsNetUtil_QueryInterface,
2742     nsNetUtil_AddRef,
2743     nsNetUtil_Release,
2744     nsNetUtil_ParseContentType,
2745     nsNetUtil_ProtocolHasFlags,
2746     nsNetUtil_URIChainHasFlags,
2747     nsNetUtil_ToImmutableURI,
2748     nsNetUtil_EscapeString,
2749     nsNetUtil_EscapeURL,
2750     nsNetUtil_UnescapeString,
2751     nsNetUtil_ExtractCharsetFromContentType
2752 };
2753
2754 static nsINetUtil nsNetUtil = { &nsNetUtilVtbl };
2755
2756 static nsresult NSAPI nsIOService_QueryInterface(nsIIOService *iface, nsIIDRef riid,
2757                                                  nsQIResult result)
2758 {
2759     *result = NULL;
2760
2761     if(IsEqualGUID(&IID_nsISupports, riid))
2762         *result = &nsIOService;
2763     else if(IsEqualGUID(&IID_nsIIOService, riid))
2764         *result = &nsIOService;
2765     else if(IsEqualGUID(&IID_nsINetUtil, riid))
2766         *result = &nsNetUtil;
2767
2768     if(*result) {
2769         nsISupports_AddRef((nsISupports*)*result);
2770         return NS_OK;
2771     }
2772
2773     FIXME("(%s %p)\n", debugstr_guid(riid), result);
2774     return NS_NOINTERFACE;
2775 }
2776
2777 static nsresult NSAPI nsIOServiceFactory_QueryInterface(nsIFactory *iface, nsIIDRef riid,
2778                                                         nsQIResult result)
2779 {
2780     *result = NULL;
2781
2782     if(IsEqualGUID(&IID_nsISupports, riid)) {
2783         TRACE("(IID_nsISupports %p)\n", result);
2784         *result = iface;
2785     }else if(IsEqualGUID(&IID_nsIFactory, riid)) {
2786         TRACE("(IID_nsIFactory %p)\n", result);
2787         *result = iface;
2788     }
2789
2790     if(*result) {
2791         nsIFactory_AddRef(iface);
2792         return NS_OK;
2793     }
2794
2795     WARN("(%s %p)\n", debugstr_guid(riid), result);
2796     return NS_NOINTERFACE;
2797 }
2798
2799 static nsrefcnt NSAPI nsIOServiceFactory_AddRef(nsIFactory *iface)
2800 {
2801     return 2;
2802 }
2803
2804 static nsrefcnt NSAPI nsIOServiceFactory_Release(nsIFactory *iface)
2805 {
2806     return 1;
2807 }
2808
2809 static nsresult NSAPI nsIOServiceFactory_CreateInstance(nsIFactory *iface,
2810         nsISupports *aOuter, const nsIID *iid, void **result)
2811 {
2812     return nsIIOService_QueryInterface(&nsIOService, iid, result);
2813 }
2814
2815 static nsresult NSAPI nsIOServiceFactory_LockFactory(nsIFactory *iface, PRBool lock)
2816 {
2817     WARN("(%x)\n", lock);
2818     return NS_OK;
2819 }
2820
2821 static const nsIFactoryVtbl nsIOServiceFactoryVtbl = {
2822     nsIOServiceFactory_QueryInterface,
2823     nsIOServiceFactory_AddRef,
2824     nsIOServiceFactory_Release,
2825     nsIOServiceFactory_CreateInstance,
2826     nsIOServiceFactory_LockFactory
2827 };
2828
2829 static nsIFactory nsIOServiceFactory = { &nsIOServiceFactoryVtbl };
2830
2831 void init_nsio(nsIComponentManager *component_manager, nsIComponentRegistrar *registrar)
2832 {
2833     nsIFactory *old_factory = NULL;
2834     nsresult nsres;
2835
2836     nsres = nsIComponentManager_GetClassObject(component_manager, &NS_IOSERVICE_CID,
2837                                                &IID_nsIFactory, (void**)&old_factory);
2838     if(NS_FAILED(nsres)) {
2839         ERR("Could not get factory: %08x\n", nsres);
2840         return;
2841     }
2842
2843     nsres = nsIFactory_CreateInstance(old_factory, NULL, &IID_nsIIOService, (void**)&nsio);
2844     if(NS_FAILED(nsres)) {
2845         ERR("Couldn not create nsIOService instance %08x\n", nsres);
2846         nsIFactory_Release(old_factory);
2847         return;
2848     }
2849
2850     nsres = nsIIOService_QueryInterface(nsio, &IID_nsINetUtil, (void**)&net_util);
2851     if(NS_FAILED(nsres)) {
2852         WARN("Could not get nsINetUtil interface: %08x\n", nsres);
2853         nsIIOService_Release(nsio);
2854         return;
2855     }
2856
2857     nsres = nsIComponentRegistrar_UnregisterFactory(registrar, &NS_IOSERVICE_CID, old_factory);
2858     nsIFactory_Release(old_factory);
2859     if(NS_FAILED(nsres))
2860         ERR("UnregisterFactory failed: %08x\n", nsres);
2861
2862     nsres = nsIComponentRegistrar_RegisterFactory(registrar, &NS_IOSERVICE_CID,
2863             NS_IOSERVICE_CLASSNAME, NS_IOSERVICE_CONTRACTID, &nsIOServiceFactory);
2864     if(NS_FAILED(nsres))
2865         ERR("RegisterFactory failed: %08x\n", nsres);
2866 }
2867
2868 void release_nsio(void)
2869 {
2870     if(net_util) {
2871         nsINetUtil_Release(net_util);
2872         net_util = NULL;
2873     }
2874
2875     if(nsio) {
2876         nsIIOService_Release(nsio);
2877         nsio = NULL;
2878     }
2879 }