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