mshtml: Get rid of HTMLDocument_OnLoad and move its job to AsyncOpen.
[wine] / dlls / mshtml / nsio.c
1 /*
2  * Copyright 2006 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 "ole2.h"
29 #include "shlguid.h"
30
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
33
34 #include "mshtml_private.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
37
38 #define LOAD_INITIAL_DOCUMENT_URI 0x80000
39
40 #define NS_IOSERVICE_CLASSNAME "nsIOService"
41 #define NS_IOSERVICE_CONTRACTID "@mozilla.org/network/io-service;1"
42
43 static IID NS_IOSERVICE_CID =
44     {0x9ac9e770, 0x18bc, 0x11d3, {0x93, 0x37, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40}};
45
46 static nsIIOService *nsio = NULL;
47
48 typedef struct {
49     const nsIHttpChannelVtbl *lpHttpChannelVtbl;
50
51     LONG ref;
52
53     nsIChannel *channel;
54     nsIHttpChannel *http_channel;
55     nsIWineURI *uri;
56 } nsChannel;
57
58 typedef struct {
59     const nsIWineURIVtbl *lpWineURIVtbl;
60
61     LONG ref;
62
63     nsIURI *uri;
64     NSContainer *container;
65 } nsURI;
66
67 #define NSCHANNEL(x)     ((nsIChannel*)        &(x)->lpHttpChannelVtbl)
68 #define NSHTTPCHANNEL(x) ((nsIHttpChannel*)    &(x)->lpHttpChannelVtbl)
69 #define NSURI(x)         ((nsIURI*)            &(x)->lpWineURIVtbl)
70
71 static BOOL exec_shldocvw_67(NSContainer *container, LPCWSTR url)
72 {
73     IOleCommandTarget *cmdtrg = NULL;
74     HRESULT hres;
75
76     hres = IOleClientSite_QueryInterface(container->doc->client, &IID_IOleCommandTarget,
77                                          (void**)&cmdtrg);
78     if(SUCCEEDED(hres)) {
79         VARIANT varUrl, varRes;
80
81         V_VT(&varUrl) = VT_BSTR;
82         V_BSTR(&varUrl) = SysAllocString(url);
83         V_VT(&varRes) = VT_BOOL;
84
85         hres = IOleCommandTarget_Exec(cmdtrg, &CGID_ShellDocView, 67, 0, &varUrl, &varRes);
86
87         IOleCommandTarget_Release(cmdtrg);
88         SysFreeString(V_BSTR(&varUrl));
89
90         if(SUCCEEDED(hres) && !V_BOOL(&varRes)) {
91             TRACE("got VARIANT_FALSE, do not load\n");
92             return FALSE;
93         }
94     }
95
96     return TRUE;
97 }
98
99 static BOOL before_async_open(nsChannel *This)
100 {
101     nsACString *uri_str;
102     NSContainer *container;
103     PRUint32 load_flags = 0;
104     const char *uria;
105     LPWSTR uri;
106     DWORD len;
107     BOOL ret = TRUE;
108
109     nsIChannel_GetLoadFlags(This->channel, &load_flags);
110     TRACE("load_flags = %08lx\n", load_flags);
111     if(!(load_flags & LOAD_INITIAL_DOCUMENT_URI))
112         return TRUE;
113
114     nsIWineURI_GetNSContainer(This->uri, &container);
115     if(!container) {
116         WARN("container = NULL\n");
117         return TRUE;
118     }
119
120     if(container->load_call) {
121         nsIWebBrowserChrome_Release(NSWBCHROME(container));
122         return TRUE;
123     }
124
125     uri_str = nsACString_Create();
126     nsIWineURI_GetSpec(This->uri, uri_str);
127     nsACString_GetData(uri_str, &uria, NULL);
128     len = MultiByteToWideChar(CP_ACP, 0, uria, -1, NULL, 0);
129     uri = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
130     MultiByteToWideChar(CP_ACP, 0, uria, -1, uri, len);
131     nsACString_Destroy(uri_str);
132
133     ret = exec_shldocvw_67(container, uri);
134
135     nsIWebBrowserChrome_Release(NSWBCHROME(container));
136     HeapFree(GetProcessHeap(), 0, uri);
137
138     return ret;
139 }
140
141 #define NSCHANNEL_THIS(iface) DEFINE_THIS(nsChannel, HttpChannel, iface)
142
143 static nsresult NSAPI nsChannel_QueryInterface(nsIHttpChannel *iface, nsIIDRef riid, nsQIResult result)
144 {
145     nsChannel *This = NSCHANNEL_THIS(iface);
146
147     *result = NULL;
148
149     if(IsEqualGUID(&IID_nsISupports, riid)) {
150         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
151         *result = NSCHANNEL(This);
152     }else if(IsEqualGUID(&IID_nsIRequest, riid)) {
153         TRACE("(%p)->(IID_nsIRequest %p)\n", This, result);
154         *result = NSCHANNEL(This);
155     }else if(IsEqualGUID(&IID_nsIChannel, riid)) {
156         TRACE("(%p)->(IID_nsIChannel %p)\n", This, result);
157         *result = NSCHANNEL(This);
158     }else if(This->http_channel && IsEqualGUID(&IID_nsIHttpChannel, riid)) {
159         TRACE("(%p)->(IID_nsIHttpChannel %p)\n", This, result);
160         *result = NSHTTPCHANNEL(This);
161     }
162
163     if(*result) {
164         nsIChannel_AddRef(NSCHANNEL(This));
165         return NS_OK;
166     }
167
168     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
169     return nsIChannel_QueryInterface(This->channel, riid, result);
170 }
171
172 static nsrefcnt NSAPI nsChannel_AddRef(nsIHttpChannel *iface)
173 {
174     nsChannel *This = NSCHANNEL_THIS(iface);
175     nsrefcnt ref = InterlockedIncrement(&This->ref);
176
177     TRACE("(%p) ref=%ld\n", This, ref);
178
179     return ref;
180 }
181
182 static nsrefcnt NSAPI nsChannel_Release(nsIHttpChannel *iface)
183 {
184     nsChannel *This = NSCHANNEL_THIS(iface);
185     LONG ref = InterlockedDecrement(&This->ref);
186
187     if(!ref) {
188         nsIChannel_Release(This->channel);
189         nsIWineURI_Release(This->uri);
190         if(This->http_channel)
191             nsIHttpChannel_Release(This->http_channel);
192         HeapFree(GetProcessHeap(), 0, This);
193     }
194
195     return ref;
196 }
197
198 static nsresult NSAPI nsChannel_GetName(nsIHttpChannel *iface, nsACString *aName)
199 {
200     nsChannel *This = NSCHANNEL_THIS(iface);
201     TRACE("(%p)->(%p)\n", This, aName);
202     return nsIChannel_GetName(This->channel, aName);
203 }
204
205 static nsresult NSAPI nsChannel_IsPending(nsIHttpChannel *iface, PRBool *_retval)
206 {
207     nsChannel *This = NSCHANNEL_THIS(iface);
208     TRACE("(%p)->(%p)\n", This, _retval);
209     return nsIChannel_IsPending(This->channel, _retval);
210 }
211
212 static nsresult NSAPI nsChannel_GetStatus(nsIHttpChannel *iface, nsresult *aStatus)
213 {
214     nsChannel *This = NSCHANNEL_THIS(iface);
215     TRACE("(%p)->(%p)\n", This, aStatus);
216     return nsIChannel_GetStatus(This->channel, aStatus);
217 }
218
219 static nsresult NSAPI nsChannel_Cancel(nsIHttpChannel *iface, nsresult aStatus)
220 {
221     nsChannel *This = NSCHANNEL_THIS(iface);
222     TRACE("(%p)->(%08lx)\n", This, aStatus);
223     return nsIChannel_Cancel(This->channel, aStatus);
224 }
225
226 static nsresult NSAPI nsChannel_Suspend(nsIHttpChannel *iface)
227 {
228     nsChannel *This = NSCHANNEL_THIS(iface);
229     TRACE("(%p)\n", This);
230     return nsIChannel_Suspend(This->channel);
231 }
232
233 static nsresult NSAPI nsChannel_Resume(nsIHttpChannel *iface)
234 {
235     nsChannel *This = NSCHANNEL_THIS(iface);
236     TRACE("(%p)\n", This);
237     return nsIChannel_Resume(This->channel);
238 }
239
240 static nsresult NSAPI nsChannel_GetLoadGroup(nsIHttpChannel *iface, nsILoadGroup **aLoadGroup)
241 {
242     nsChannel *This = NSCHANNEL_THIS(iface);
243     TRACE("(%p)->(%p)\n", This, aLoadGroup);
244     return nsIChannel_GetLoadGroup(This->channel, aLoadGroup);
245 }
246
247 static nsresult NSAPI nsChannel_SetLoadGroup(nsIHttpChannel *iface, nsILoadGroup *aLoadGroup)
248 {
249     nsChannel *This = NSCHANNEL_THIS(iface);
250     TRACE("(%p)->(%p)\n", This, aLoadGroup);
251     return nsIChannel_SetLoadGroup(This->channel, aLoadGroup);
252 }
253
254 static nsresult NSAPI nsChannel_GetLoadFlags(nsIHttpChannel *iface, nsLoadFlags *aLoadFlags)
255 {
256     nsChannel *This = NSCHANNEL_THIS(iface);
257     TRACE("(%p)->(%p)\n", This, aLoadFlags);
258     return nsIChannel_GetLoadFlags(This->channel, aLoadFlags);
259 }
260
261 static nsresult NSAPI nsChannel_SetLoadFlags(nsIHttpChannel *iface, nsLoadFlags aLoadFlags)
262 {
263     nsChannel *This = NSCHANNEL_THIS(iface);
264     TRACE("(%p)->(%08lx)\n", This, aLoadFlags);
265     return nsIChannel_SetLoadFlags(This->channel, aLoadFlags);
266 }
267
268 static nsresult NSAPI nsChannel_GetOriginalURI(nsIHttpChannel *iface, nsIURI **aOriginalURI)
269 {
270     nsChannel *This = NSCHANNEL_THIS(iface);
271     TRACE("(%p)->(%p)\n", This, aOriginalURI);
272     return nsIChannel_GetOriginalURI(This->channel, aOriginalURI);
273 }
274
275 static nsresult NSAPI nsChannel_SetOriginalURI(nsIHttpChannel *iface, nsIURI *aOriginalURI)
276 {
277     nsChannel *This = NSCHANNEL_THIS(iface);
278     TRACE("(%p)->(%p)\n", This, aOriginalURI);
279     return nsIChannel_SetOriginalURI(This->channel, aOriginalURI);
280 }
281
282 static nsresult NSAPI nsChannel_GetURI(nsIHttpChannel *iface, nsIURI **aURI)
283 {
284     nsChannel *This = NSCHANNEL_THIS(iface);
285
286     TRACE("(%p)->(%p)\n", This, aURI);
287
288     nsIWineURI_AddRef(This->uri);
289     *aURI = (nsIURI*)This->uri;
290
291     return NS_OK;
292 }
293
294 static nsresult NSAPI nsChannel_GetOwner(nsIHttpChannel *iface, nsISupports **aOwner)
295 {
296     nsChannel *This = NSCHANNEL_THIS(iface);
297     TRACE("(%p)->(%p)\n", This, aOwner);
298     return nsIChannel_GetOwner(This->channel, aOwner);
299 }
300
301 static nsresult NSAPI nsChannel_SetOwner(nsIHttpChannel *iface, nsISupports *aOwner)
302 {
303     nsChannel *This = NSCHANNEL_THIS(iface);
304     TRACE("(%p)->(%p)\n", This, aOwner);
305     return nsIChannel_SetOwner(This->channel, aOwner);
306 }
307
308 static nsresult NSAPI nsChannel_GetNotificationCallbacks(nsIHttpChannel *iface,
309         nsIInterfaceRequestor **aNotificationCallbacks)
310 {
311     nsChannel *This = NSCHANNEL_THIS(iface);
312     TRACE("(%p)->(%p)\n", This, aNotificationCallbacks);
313     return nsIChannel_GetNotificationCallbacks(This->channel, aNotificationCallbacks);
314 }
315
316 static nsresult NSAPI nsChannel_SetNotificationCallbacks(nsIHttpChannel *iface,
317         nsIInterfaceRequestor *aNotificationCallbacks)
318 {
319     nsChannel *This = NSCHANNEL_THIS(iface);
320     TRACE("(%p)->(%p)\n", This, aNotificationCallbacks);
321     return nsIChannel_SetNotificationCallbacks(This->channel, aNotificationCallbacks);
322 }
323
324 static nsresult NSAPI nsChannel_GetSecurityInfo(nsIHttpChannel *iface, nsISupports **aSecurityInfo)
325 {
326     nsChannel *This = NSCHANNEL_THIS(iface);
327     TRACE("(%p)->(%p)\n", This, aSecurityInfo);
328     return nsIChannel_GetSecurityInfo(This->channel, aSecurityInfo);
329 }
330
331 static nsresult NSAPI nsChannel_GetContentType(nsIHttpChannel *iface, nsACString *aContentType)
332 {
333     nsChannel *This = NSCHANNEL_THIS(iface);
334     TRACE("(%p)->(%p)\n", This, aContentType);
335     return nsIChannel_GetContentType(This->channel, aContentType);
336 }
337
338 static nsresult NSAPI nsChannel_SetContentType(nsIHttpChannel *iface,
339                                                const nsACString *aContentType)
340 {
341     nsChannel *This = NSCHANNEL_THIS(iface);
342     TRACE("(%p)->(%p)\n", This, aContentType);
343     return nsIChannel_SetContentType(This->channel, aContentType);
344 }
345
346 static nsresult NSAPI nsChannel_GetContentCharset(nsIHttpChannel *iface,
347                                                   nsACString *aContentCharset)
348 {
349     nsChannel *This = NSCHANNEL_THIS(iface);
350     TRACE("(%p)->(%p)\n", This, aContentCharset);
351     return nsIChannel_GetContentCharset(This->channel, aContentCharset);
352 }
353
354 static nsresult NSAPI nsChannel_SetContentCharset(nsIHttpChannel *iface,
355                                                   const nsACString *aContentCharset)
356 {
357     nsChannel *This = NSCHANNEL_THIS(iface);
358     TRACE("(%p)->(%p)\n", This, aContentCharset);
359     return nsIChannel_SetContentCharset(This->channel, aContentCharset);
360 }
361
362 static nsresult NSAPI nsChannel_GetContentLength(nsIHttpChannel *iface, PRInt32 *aContentLength)
363 {
364     nsChannel *This = NSCHANNEL_THIS(iface);
365     TRACE("(%p)->(%p)\n", This, aContentLength);
366     return nsIChannel_GetContentLength(This->channel, aContentLength);
367 }
368
369 static nsresult NSAPI nsChannel_SetContentLength(nsIHttpChannel *iface, PRInt32 aContentLength)
370 {
371     nsChannel *This = NSCHANNEL_THIS(iface);
372     TRACE("(%p)->(%ld)\n", This, aContentLength);
373     return nsIChannel_SetContentLength(This->channel, aContentLength);
374 }
375
376 static nsresult NSAPI nsChannel_Open(nsIHttpChannel *iface, nsIInputStream **_retval)
377 {
378     nsChannel *This = NSCHANNEL_THIS(iface);
379     TRACE("(%p)->(%p)\n", This, _retval);
380     return nsIChannel_Open(This->channel, _retval);
381 }
382
383 static nsresult NSAPI nsChannel_AsyncOpen(nsIHttpChannel *iface, nsIStreamListener *aListener,
384                                           nsISupports *aContext)
385 {
386     nsChannel *This = NSCHANNEL_THIS(iface);
387
388     TRACE("(%p)->(%p %p)\n", This, aListener, aContext);
389
390     if(!before_async_open(This)) {
391         TRACE("canceled\n");
392         return NS_ERROR_UNEXPECTED;
393     }
394
395     return nsIChannel_AsyncOpen(This->channel, aListener, aContext);
396 }
397
398 static nsresult NSAPI nsChannel_GetRequestMethod(nsIHttpChannel *iface, nsACString *aRequestMethod)
399 {
400     nsChannel *This = NSCHANNEL_THIS(iface);
401
402     TRACE("(%p)->(%p)\n", This, aRequestMethod);
403
404     if(This->http_channel)
405         return nsIHttpChannel_GetRequestMethod(This->http_channel, aRequestMethod);
406
407     return NS_ERROR_NOT_IMPLEMENTED;
408 }
409
410 static nsresult NSAPI nsChannel_SetRequestMethod(nsIHttpChannel *iface,
411                                                  const nsACString *aRequestMethod)
412 {
413     nsChannel *This = NSCHANNEL_THIS(iface);
414
415     TRACE("(%p)->(%p)\n", This, aRequestMethod);
416
417     if(This->http_channel)
418         return nsIHttpChannel_SetRequestMethod(This->http_channel, aRequestMethod);
419
420     return NS_ERROR_NOT_IMPLEMENTED;
421 }
422
423 static nsresult NSAPI nsChannel_GetReferrer(nsIHttpChannel *iface, nsIURI **aReferrer)
424 {
425     nsChannel *This = NSCHANNEL_THIS(iface);
426
427     TRACE("(%p)->(%p)\n", This, aReferrer);
428
429     if(This->http_channel)
430         return nsIHttpChannel_GetReferrer(This->http_channel, aReferrer);
431
432     return NS_ERROR_NOT_IMPLEMENTED;
433 }
434
435 static nsresult NSAPI nsChannel_SetReferrer(nsIHttpChannel *iface, nsIURI *aReferrer)
436 {
437     nsChannel *This = NSCHANNEL_THIS(iface);
438
439     TRACE("(%p)->(%p)\n", This, aReferrer);
440
441     if(This->http_channel)
442         return nsIHttpChannel_SetReferrer(This->http_channel, aReferrer);
443
444     return NS_ERROR_NOT_IMPLEMENTED;
445 }
446
447 static nsresult NSAPI nsChannel_GetRequestHeader(nsIHttpChannel *iface,
448          const nsACString *aHeader, nsACString *_retval)
449 {
450     nsChannel *This = NSCHANNEL_THIS(iface);
451
452     TRACE("(%p)->(%p %p)\n", This, aHeader, _retval);
453
454     if(This->http_channel)
455         return nsIHttpChannel_GetRequestHeader(This->http_channel, aHeader, _retval);
456
457     return NS_ERROR_NOT_IMPLEMENTED;
458 }
459
460 static nsresult NSAPI nsChannel_SetRequestHeader(nsIHttpChannel *iface,
461          const nsACString *aHeader, const nsACString *aValue, PRBool aMerge)
462 {
463     nsChannel *This = NSCHANNEL_THIS(iface);
464
465     TRACE("(%p)->(%p %p %x)\n", This, aHeader, aValue, aMerge);
466
467     if(This->http_channel)
468         return nsIHttpChannel_SetRequestHeader(This->http_channel, aHeader, aValue, aMerge);
469
470     return NS_ERROR_NOT_IMPLEMENTED;
471 }
472
473 static nsresult NSAPI nsChannel_VisitRequestHeaders(nsIHttpChannel *iface,
474                                                     nsIHttpHeaderVisitor *aVisitor)
475 {
476     nsChannel *This = NSCHANNEL_THIS(iface);
477
478     TRACE("(%p)->(%p)\n", This, aVisitor);
479
480     if(This->http_channel)
481         return nsIHttpChannel_VisitRequestHeaders(This->http_channel, aVisitor);
482
483     return NS_ERROR_NOT_IMPLEMENTED;
484 }
485
486 static nsresult NSAPI nsChannel_GetAllowPipelining(nsIHttpChannel *iface, PRBool *aAllowPipelining)
487 {
488     nsChannel *This = NSCHANNEL_THIS(iface);
489
490     TRACE("(%p)->(%p)\n", This, aAllowPipelining);
491
492     if(This->http_channel)
493         return nsIHttpChannel_GetAllowPipelining(This->http_channel, aAllowPipelining);
494
495     return NS_ERROR_NOT_IMPLEMENTED;
496 }
497
498 static nsresult NSAPI nsChannel_SetAllowPipelining(nsIHttpChannel *iface, PRBool aAllowPipelining)
499 {
500     nsChannel *This = NSCHANNEL_THIS(iface);
501
502     TRACE("(%p)->(%x)\n", This, aAllowPipelining);
503
504     if(This->http_channel)
505         return nsIHttpChannel_SetAllowPipelining(This->http_channel, aAllowPipelining);
506
507     return NS_ERROR_NOT_IMPLEMENTED;
508 }
509
510 static nsresult NSAPI nsChannel_GetRedirectionLimit(nsIHttpChannel *iface, PRUint32 *aRedirectionLimit)
511 {
512     nsChannel *This = NSCHANNEL_THIS(iface);
513
514     TRACE("(%p)->(%p)\n", This, aRedirectionLimit);
515
516     if(This->http_channel)
517         return nsIHttpChannel_GetRedirectionLimit(This->http_channel, aRedirectionLimit);
518
519     return NS_ERROR_NOT_IMPLEMENTED;
520 }
521
522 static nsresult NSAPI nsChannel_SetRedirectionLimit(nsIHttpChannel *iface, PRUint32 aRedirectionLimit)
523 {
524     nsChannel *This = NSCHANNEL_THIS(iface);
525
526     TRACE("(%p)->(%lu)\n", This, aRedirectionLimit);
527
528     if(This->http_channel)
529         return nsIHttpChannel_SetRedirectionLimit(This->http_channel, aRedirectionLimit);
530
531     return NS_ERROR_NOT_IMPLEMENTED;
532 }
533
534 static nsresult NSAPI nsChannel_GetResponseStatus(nsIHttpChannel *iface, PRUint32 *aResponseStatus)
535 {
536     nsChannel *This = NSCHANNEL_THIS(iface);
537
538     TRACE("(%p)->(%p)\n", This, aResponseStatus);
539
540     if(This->http_channel)
541         return nsIHttpChannel_GetResponseStatus(This->http_channel, aResponseStatus);
542
543     return NS_ERROR_NOT_IMPLEMENTED;
544 }
545
546 static nsresult NSAPI nsChannel_GetResponseStatusText(nsIHttpChannel *iface,
547                                                       nsACString *aResponseStatusText)
548 {
549     nsChannel *This = NSCHANNEL_THIS(iface);
550
551     TRACE("(%p)->(%p)\n", This, aResponseStatusText);
552
553     if(This->http_channel)
554         return nsIHttpChannel_GetResponseStatusText(This->http_channel, aResponseStatusText);
555
556     return NS_ERROR_NOT_IMPLEMENTED;
557 }
558
559 static nsresult NSAPI nsChannel_GetRequestSucceeded(nsIHttpChannel *iface,
560                                                     PRBool *aRequestSucceeded)
561 {
562     nsChannel *This = NSCHANNEL_THIS(iface);
563
564     TRACE("(%p)->(%p)\n", This, aRequestSucceeded);
565
566     if(This->http_channel)
567         return nsIHttpChannel_GetRequestSucceeded(This->http_channel, aRequestSucceeded);
568
569     return NS_ERROR_NOT_IMPLEMENTED;
570 }
571
572 static nsresult NSAPI nsChannel_GetResponseHeader(nsIHttpChannel *iface,
573          const nsACString *header, nsACString *_retval)
574 {
575     nsChannel *This = NSCHANNEL_THIS(iface);
576
577     TRACE("(%p)->(%p %p)\n", This, header, _retval);
578
579     if(This->http_channel)
580         return nsIHttpChannel_GetResponseHeader(This->http_channel, header, _retval);
581
582     return NS_ERROR_NOT_IMPLEMENTED;
583 }
584
585 static nsresult NSAPI nsChannel_SetResponseHeader(nsIHttpChannel *iface,
586         const nsACString *header, const nsACString *value, PRBool merge)
587 {
588     nsChannel *This = NSCHANNEL_THIS(iface);
589
590     TRACE("(%p)->(%p %p %x)\n", This, header, value, merge);
591
592     if(This->http_channel)
593         return nsIHttpChannel_SetResponseHeader(This->http_channel, header, value, merge);
594
595     return NS_ERROR_NOT_IMPLEMENTED;
596 }
597
598 static nsresult NSAPI nsChannel_VisitResponseHeaders(nsIHttpChannel *iface,
599         nsIHttpHeaderVisitor *aVisitor)
600 {
601     nsChannel *This = NSCHANNEL_THIS(iface);
602
603     TRACE("(%p)->(%p)\n", This, aVisitor);
604
605     if(This->http_channel)
606         return nsIHttpChannel_VisitResponseHeaders(This->http_channel, aVisitor);
607
608     return NS_ERROR_NOT_IMPLEMENTED;
609 }
610
611 static nsresult NSAPI nsChannel_IsNoStoreResponse(nsIHttpChannel *iface, PRBool *_retval)
612 {
613     nsChannel *This = NSCHANNEL_THIS(iface);
614
615     TRACE("(%p)->(%p)\n", This, _retval);
616
617     if(This->http_channel)
618         return nsIHttpChannel_IsNoStoreResponse(This->http_channel, _retval);
619
620     return NS_ERROR_NOT_IMPLEMENTED;
621 }
622
623 static nsresult NSAPI nsChannel_IsNoCacheResponse(nsIHttpChannel *iface, PRBool *_retval)
624 {
625     nsChannel *This = NSCHANNEL_THIS(iface);
626
627     TRACE("(%p)->(%p)\n", This, _retval);
628
629     if(This->http_channel)
630         return nsIHttpChannel_IsNoCacheResponse(This->http_channel, _retval);
631
632     return NS_ERROR_NOT_IMPLEMENTED;
633 }
634
635 #undef NSCHANNEL_THIS
636
637 static const nsIHttpChannelVtbl nsChannelVtbl = {
638     nsChannel_QueryInterface,
639     nsChannel_AddRef,
640     nsChannel_Release,
641     nsChannel_GetName,
642     nsChannel_IsPending,
643     nsChannel_GetStatus,
644     nsChannel_Cancel,
645     nsChannel_Suspend,
646     nsChannel_Resume,
647     nsChannel_GetLoadGroup,
648     nsChannel_SetLoadGroup,
649     nsChannel_GetLoadFlags,
650     nsChannel_SetLoadFlags,
651     nsChannel_GetOriginalURI,
652     nsChannel_SetOriginalURI,
653     nsChannel_GetURI,
654     nsChannel_GetOwner,
655     nsChannel_SetOwner,
656     nsChannel_GetNotificationCallbacks,
657     nsChannel_SetNotificationCallbacks,
658     nsChannel_GetSecurityInfo,
659     nsChannel_GetContentType,
660     nsChannel_SetContentType,
661     nsChannel_GetContentCharset,
662     nsChannel_SetContentCharset,
663     nsChannel_GetContentLength,
664     nsChannel_SetContentLength,
665     nsChannel_Open,
666     nsChannel_AsyncOpen,
667     nsChannel_GetRequestMethod,
668     nsChannel_SetRequestMethod,
669     nsChannel_GetReferrer,
670     nsChannel_SetReferrer,
671     nsChannel_GetRequestHeader,
672     nsChannel_SetRequestHeader,
673     nsChannel_VisitRequestHeaders,
674     nsChannel_GetAllowPipelining,
675     nsChannel_SetAllowPipelining,
676     nsChannel_GetRedirectionLimit,
677     nsChannel_SetRedirectionLimit,
678     nsChannel_GetResponseStatus,
679     nsChannel_GetResponseStatusText,
680     nsChannel_GetRequestSucceeded,
681     nsChannel_GetResponseHeader,
682     nsChannel_SetResponseHeader,
683     nsChannel_VisitResponseHeaders,
684     nsChannel_IsNoStoreResponse,
685     nsChannel_IsNoCacheResponse
686 };
687
688 #define NSURI_THIS(iface) DEFINE_THIS(nsURI, WineURI, iface)
689
690 static nsresult NSAPI nsURI_QueryInterface(nsIWineURI *iface, nsIIDRef riid, nsQIResult result)
691 {
692     nsURI *This = NSURI_THIS(iface);
693
694     *result = NULL;
695
696     if(IsEqualGUID(&IID_nsISupports, riid)) {
697         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
698         *result = NSURI(This);
699     }else if(IsEqualGUID(&IID_nsIURI, riid)) {
700         TRACE("(%p)->(IID_nsIURI %p)\n", This, result);
701         *result = NSURI(This);
702     }else if(IsEqualGUID(&IID_nsIWineURI, riid)) {
703         TRACE("(%p)->(IID_nsIWineURI %p)\n", This, result);
704         *result = NSURI(This);
705     }
706
707     if(*result) {
708         nsIURI_AddRef(NSURI(This));
709         return NS_OK;
710     }
711
712     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
713     return nsIURI_QueryInterface(This->uri, riid, result);
714 }
715
716 static nsrefcnt NSAPI nsURI_AddRef(nsIWineURI *iface)
717 {
718     nsURI *This = NSURI_THIS(iface);
719     LONG ref = InterlockedIncrement(&This->ref);
720
721     TRACE("(%p) ref=%ld\n", This, ref);
722
723     return ref;
724 }
725
726 static nsrefcnt NSAPI nsURI_Release(nsIWineURI *iface)
727 {
728     nsURI *This = NSURI_THIS(iface);
729     LONG ref = InterlockedDecrement(&This->ref);
730
731     TRACE("(%p) ref=%ld\n", This, ref);
732
733     if(!ref) {
734         nsIURI_Release(This->uri);
735         HeapFree(GetProcessHeap(), 0, This);
736     }
737
738     return ref;
739 }
740
741 static nsresult NSAPI nsURI_GetSpec(nsIWineURI *iface, nsACString *aSpec)
742 {
743     nsURI *This = NSURI_THIS(iface);
744     TRACE("(%p)->(%p)\n", This, aSpec);
745     return nsIURI_GetSpec(This->uri, aSpec);
746 }
747
748 static nsresult NSAPI nsURI_SetSpec(nsIWineURI *iface, const nsACString *aSpec)
749 {
750     nsURI *This = NSURI_THIS(iface);
751     TRACE("(%p)->(%p)\n", This, aSpec);
752     return nsIURI_SetSpec(This->uri, aSpec);
753 }
754
755 static nsresult NSAPI nsURI_GetPrePath(nsIWineURI *iface, nsACString *aPrePath)
756 {
757     nsURI *This = NSURI_THIS(iface);
758     TRACE("(%p)->(%p)\n", This, aPrePath);
759     return nsIURI_GetPrePath(This->uri, aPrePath);
760 }
761
762 static nsresult NSAPI nsURI_GetScheme(nsIWineURI *iface, nsACString *aScheme)
763 {
764     nsURI *This = NSURI_THIS(iface);
765     TRACE("(%p)->(%p)\n", This, aScheme);
766     return nsIURI_GetScheme(This->uri, aScheme);
767 }
768
769 static nsresult NSAPI nsURI_SetScheme(nsIWineURI *iface, const nsACString *aScheme)
770 {
771     nsURI *This = NSURI_THIS(iface);
772     TRACE("(%p)->(%p)\n", This, aScheme);
773     return nsIURI_SetScheme(This->uri, aScheme);
774 }
775
776 static nsresult NSAPI nsURI_GetUserPass(nsIWineURI *iface, nsACString *aUserPass)
777 {
778     nsURI *This = NSURI_THIS(iface);
779     TRACE("(%p)->(%p)\n", This, aUserPass);
780     return nsIURI_GetUserPass(This->uri, aUserPass);
781 }
782
783 static nsresult NSAPI nsURI_SetUserPass(nsIWineURI *iface, const nsACString *aUserPass)
784 {
785     nsURI *This = NSURI_THIS(iface);
786     TRACE("(%p)->(%p)\n", This, aUserPass);
787     return nsIURI_SetUserPass(This->uri, aUserPass);
788 }
789
790 static nsresult NSAPI nsURI_GetUsername(nsIWineURI *iface, nsACString *aUsername)
791 {
792     nsURI *This = NSURI_THIS(iface);
793     TRACE("(%p)->(%p)\n", This, aUsername);
794     return nsIURI_GetUsername(This->uri, aUsername);
795 }
796
797 static nsresult NSAPI nsURI_SetUsername(nsIWineURI *iface, const nsACString *aUsername)
798 {
799     nsURI *This = NSURI_THIS(iface);
800     TRACE("(%p)->(%p)\n", This, aUsername);
801     return nsIURI_SetUsername(This->uri, aUsername);
802 }
803
804 static nsresult NSAPI nsURI_GetPassword(nsIWineURI *iface, nsACString *aPassword)
805 {
806     nsURI *This = NSURI_THIS(iface);
807     TRACE("(%p)->(%p)\n", This, aPassword);
808     return nsIURI_GetPassword(This->uri, aPassword);
809 }
810
811 static nsresult NSAPI nsURI_SetPassword(nsIWineURI *iface, const nsACString *aPassword)
812 {
813     nsURI *This = NSURI_THIS(iface);
814     TRACE("(%p)->(%p)\n", This, aPassword);
815     return nsIURI_SetPassword(This->uri, aPassword);
816 }
817
818 static nsresult NSAPI nsURI_GetHostPort(nsIWineURI *iface, nsACString *aHostPort)
819 {
820     nsURI *This = NSURI_THIS(iface);
821     TRACE("(%p)->(%p)\n", This, aHostPort);
822     return nsIURI_GetHostPort(This->uri, aHostPort);
823 }
824
825 static nsresult NSAPI nsURI_SetHostPort(nsIWineURI *iface, const nsACString *aHostPort)
826 {
827     nsURI *This = NSURI_THIS(iface);
828     TRACE("(%p)->(%p)\n", This, aHostPort);
829     return nsIURI_SetHostPort(This->uri, aHostPort);
830 }
831
832 static nsresult NSAPI nsURI_GetHost(nsIWineURI *iface, nsACString *aHost)
833 {
834     nsURI *This = NSURI_THIS(iface);
835     TRACE("(%p)->(%p)\n", This, aHost);
836     return nsIURI_GetHost(This->uri, aHost);
837 }
838
839 static nsresult NSAPI nsURI_SetHost(nsIWineURI *iface, const nsACString *aHost)
840 {
841     nsURI *This = NSURI_THIS(iface);
842     TRACE("(%p)->(%p)\n", This, aHost);
843     return nsIURI_SetHost(This->uri, aHost);
844 }
845
846 static nsresult NSAPI nsURI_GetPort(nsIWineURI *iface, PRInt32 *aPort)
847 {
848     nsURI *This = NSURI_THIS(iface);
849     TRACE("(%p)->(%p)\n", This, aPort);
850     return nsIURI_GetPort(This->uri, aPort);
851 }
852
853 static nsresult NSAPI nsURI_SetPort(nsIWineURI *iface, PRInt32 aPort)
854 {
855     nsURI *This = NSURI_THIS(iface);
856     TRACE("(%p)->(%ld)\n", This, aPort);
857     return nsIURI_SetPort(This->uri, aPort);
858 }
859
860 static nsresult NSAPI nsURI_GetPath(nsIWineURI *iface, nsACString *aPath)
861 {
862     nsURI *This = NSURI_THIS(iface);
863     TRACE("(%p)->(%p)\n", This, aPath);
864     return nsIURI_GetPath(This->uri, aPath);
865 }
866
867 static nsresult NSAPI nsURI_SetPath(nsIWineURI *iface, const nsACString *aPath)
868 {
869     nsURI *This = NSURI_THIS(iface);
870     TRACE("(%p)->(%p)\n", This, aPath);
871     return nsIURI_SetPath(This->uri, aPath);
872 }
873
874 static nsresult NSAPI nsURI_Equals(nsIWineURI *iface, nsIURI *other, PRBool *_retval)
875 {
876     nsURI *This = NSURI_THIS(iface);
877     TRACE("(%p)->(%p %p)\n", This, other, _retval);
878     return nsIURI_Equals(This->uri, other, _retval);
879 }
880
881 static nsresult NSAPI nsURI_SchemeIs(nsIWineURI *iface, const char *scheme, PRBool *_retval)
882 {
883     nsURI *This = NSURI_THIS(iface);
884     TRACE("(%p)->(%s %p)\n", This, debugstr_a(scheme), _retval);
885     return nsIURI_SchemeIs(This->uri, scheme, _retval);
886 }
887
888 static nsresult NSAPI nsURI_Clone(nsIWineURI *iface, nsIURI **_retval)
889 {
890     nsURI *This = NSURI_THIS(iface);
891     TRACE("(%p)->(%p)\n", This, _retval);
892     return nsIURI_Clone(This->uri, _retval);
893 }
894
895 static nsresult NSAPI nsURI_Resolve(nsIWineURI *iface, const nsACString *arelativePath,
896         nsACString *_retval)
897 {
898     nsURI *This = NSURI_THIS(iface);
899     TRACE("(%p)->(%p %p)\n", This, arelativePath, _retval);
900     return nsIURI_Resolve(This->uri, arelativePath, _retval);
901 }
902
903 static nsresult NSAPI nsURI_GetAsciiSpec(nsIWineURI *iface, nsACString *aAsciiSpec)
904 {
905     nsURI *This = NSURI_THIS(iface);
906     TRACE("(%p)->(%p)\n", This, aAsciiSpec);
907     return nsIURI_GetAsciiSpec(This->uri, aAsciiSpec);
908 }
909
910 static nsresult NSAPI nsURI_GetAsciiHost(nsIWineURI *iface, nsACString *aAsciiHost)
911 {
912     nsURI *This = NSURI_THIS(iface);
913     TRACE("(%p)->(%p)\n", This, aAsciiHost);
914     return nsIURI_GetAsciiHost(This->uri, aAsciiHost);
915 }
916
917 static nsresult NSAPI nsURI_GetOriginCharset(nsIWineURI *iface, nsACString *aOriginCharset)
918 {
919     nsURI *This = NSURI_THIS(iface);
920     TRACE("(%p)->(%p)\n", This, aOriginCharset);
921     return nsIURI_GetOriginCharset(This->uri, aOriginCharset);
922 }
923
924 static nsresult NSAPI nsURI_GetNSContainer(nsIWineURI *iface, NSContainer **aContainer)
925 {
926     nsURI *This = NSURI_THIS(iface);
927
928     TRACE("(%p)->(%p)\n", This, aContainer);
929
930     if(This->container)
931         nsIWebBrowserChrome_AddRef(NSWBCHROME(This->container));
932     *aContainer = This->container;
933
934     return NS_OK;
935 }
936
937 static nsresult NSAPI nsURI_SetNSContainer(nsIWineURI *iface, NSContainer *aContainer)
938 {
939     nsURI *This = NSURI_THIS(iface);
940
941     TRACE("(%p)->(%p)\n", This, aContainer);
942
943     if(This->container) {
944         WARN("Container already set: %p\n", This->container);
945         nsIWebBrowserChrome_Release(NSWBCHROME(This->container));
946     }
947
948     if(aContainer)
949         nsIWebBrowserChrome_AddRef(NSWBCHROME(aContainer));
950     This->container = aContainer;
951
952     return NS_OK;
953 }
954
955 #undef NSURI_THIS
956
957 static const nsIWineURIVtbl nsWineURIVtbl = {
958     nsURI_QueryInterface,
959     nsURI_AddRef,
960     nsURI_Release,
961     nsURI_GetSpec,
962     nsURI_SetSpec,
963     nsURI_GetPrePath,
964     nsURI_GetScheme,
965     nsURI_SetScheme,
966     nsURI_GetUserPass,
967     nsURI_SetUserPass,
968     nsURI_GetUsername,
969     nsURI_SetUsername,
970     nsURI_GetPassword,
971     nsURI_SetPassword,
972     nsURI_GetHostPort,
973     nsURI_SetHostPort,
974     nsURI_GetHost,
975     nsURI_SetHost,
976     nsURI_GetPort,
977     nsURI_SetPort,
978     nsURI_GetPath,
979     nsURI_SetPath,
980     nsURI_Equals,
981     nsURI_SchemeIs,
982     nsURI_Clone,
983     nsURI_Resolve,
984     nsURI_GetAsciiSpec,
985     nsURI_GetAsciiHost,
986     nsURI_GetOriginCharset,
987     nsURI_GetNSContainer,
988     nsURI_SetNSContainer,
989 };
990
991 static nsresult NSAPI nsIOService_QueryInterface(nsIIOService *iface, nsIIDRef riid,
992                                                  nsQIResult result)
993 {
994     *result = NULL;
995
996     if(IsEqualGUID(&IID_nsISupports, riid)) {
997         TRACE("(IID_nsISupports %p)\n", result);
998         *result = iface;
999     }else if(IsEqualGUID(&IID_nsIIOService, riid)) {
1000         TRACE("(IID_nsIIOService %p)\n", result);
1001         *result = iface;
1002     }
1003
1004     if(*result) {
1005         nsIIOService_AddRef(iface);
1006         return S_OK;
1007     }
1008
1009     WARN("(%s %p)\n", debugstr_guid(riid), result);
1010     return NS_NOINTERFACE;
1011 }
1012
1013 static nsrefcnt NSAPI nsIOService_AddRef(nsIIOService *iface)
1014 {
1015     return 2;
1016 }
1017
1018 static nsrefcnt NSAPI nsIOService_Release(nsIIOService *iface)
1019 {
1020     return 1;
1021 }
1022
1023 static nsresult NSAPI nsIOService_GetProtocolHandler(nsIIOService *iface, const char *aScheme,
1024                                                      nsIProtocolHandler **_retval)
1025 {
1026     TRACE("(%s %p)\n", debugstr_a(aScheme), _retval);
1027     return nsIIOService_GetProtocolHandler(nsio, aScheme, _retval);
1028 }
1029
1030 static nsresult NSAPI nsIOService_GetProtocolFlags(nsIIOService *iface, const char *aScheme,
1031                                                     PRUint32 *_retval)
1032 {
1033     TRACE("(%s %p)\n", debugstr_a(aScheme), _retval);
1034     return nsIIOService_GetProtocolFlags(nsio, aScheme, _retval);
1035 }
1036
1037 static nsresult NSAPI nsIOService_NewURI(nsIIOService *iface, const nsACString *aSpec,
1038         const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval)
1039 {
1040     const char *spec = NULL;
1041     nsIURI *uri;
1042     nsURI *ret;
1043     PRBool is_javascript = FALSE;
1044     nsresult nsres;
1045
1046     nsACString_GetData(aSpec, &spec, NULL);
1047
1048     TRACE("(%p(%s) %s %p %p)\n", aSpec, debugstr_a(spec), debugstr_a(aOriginCharset),
1049           aBaseURI, _retval);
1050
1051     if(aBaseURI) {
1052         nsACString *base_uri_str = nsACString_Create();
1053         const char *base_uri = NULL;
1054
1055         nsres = nsIURI_GetSpec(aBaseURI, base_uri_str);
1056         if(NS_SUCCEEDED(nsres)) {
1057             nsACString_GetData(base_uri_str, &base_uri, NULL);
1058             TRACE("uri=%s\n", debugstr_a(base_uri));
1059         }else {
1060             ERR("GetSpec failed: %08lx\n", nsres);
1061         }
1062
1063         nsACString_Destroy(base_uri_str);
1064     }
1065
1066     nsres = nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, &uri);
1067     if(NS_FAILED(nsres)) {
1068         WARN("NewURI failed: %08lx\n", nsres);
1069         return nsres;
1070     }
1071
1072     nsIURI_SchemeIs(uri, "javascript", &is_javascript);
1073     if(is_javascript) {
1074         TRACE("returning javascript uri: %p\n", uri);
1075         *_retval = uri;
1076         return NS_OK;
1077     }
1078
1079     ret = HeapAlloc(GetProcessHeap(), 0, sizeof(nsURI));
1080
1081     ret->lpWineURIVtbl = &nsWineURIVtbl;
1082     ret->ref = 1;
1083     ret->uri = uri;
1084     ret->container = NULL;
1085
1086     TRACE("_retval = %p\n", ret);
1087     *_retval = NSURI(ret);
1088     return NS_OK;
1089 }
1090
1091 static nsresult NSAPI nsIOService_NewFileURI(nsIIOService *iface, nsIFile *aFile,
1092                                              nsIURI **_retval)
1093 {
1094     TRACE("(%p %p)\n", aFile, _retval);
1095     return nsIIOService_NewFileURI(nsio, aFile, _retval);
1096 }
1097
1098 static nsresult NSAPI nsIOService_NewChannelFromURI(nsIIOService *iface, nsIURI *aURI,
1099                                                      nsIChannel **_retval)
1100 {
1101     nsIChannel *channel = NULL;
1102     nsChannel *ret;
1103     nsIWineURI *wine_uri;
1104     nsresult nsres;
1105
1106     TRACE("(%p %p)\n", aURI, _retval);
1107
1108     nsres = nsIIOService_NewChannelFromURI(nsio, aURI, &channel);
1109     if(NS_FAILED(nsres)) {
1110         WARN("NewChannelFromURI failed: %08lx\n", nsres);
1111         *_retval = channel;
1112         return nsres;
1113     }
1114
1115     nsres = nsIURI_QueryInterface(aURI, &IID_nsIWineURI, (void**)&wine_uri);
1116     if(NS_FAILED(nsres)) {
1117         WARN("Could not get nsIWineURI: %08lx\n", nsres);
1118         *_retval = channel;
1119         return NS_OK;
1120     }
1121
1122     ret = HeapAlloc(GetProcessHeap(), 0, sizeof(nsChannel));
1123
1124     ret->lpHttpChannelVtbl = &nsChannelVtbl;
1125     ret->ref = 1;
1126     ret->channel = channel;
1127     ret->http_channel = NULL;
1128     ret->uri = wine_uri;
1129
1130     nsIChannel_QueryInterface(ret->channel, &IID_nsIHttpChannel, (void**)&ret->http_channel);
1131
1132     *_retval = NSCHANNEL(ret);
1133     return NS_OK;
1134 }
1135
1136 static nsresult NSAPI nsIOService_NewChannel(nsIIOService *iface, const nsACString *aSpec,
1137         const char *aOriginCharset, nsIURI *aBaseURI, nsIChannel **_retval)
1138 {
1139     TRACE("(%p %s %p %p)\n", aSpec, debugstr_a(aOriginCharset), aBaseURI, _retval);
1140     return nsIIOService_NewChannel(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
1141 }
1142
1143 static nsresult NSAPI nsIOService_GetOffline(nsIIOService *iface, PRBool *aOffline)
1144 {
1145     TRACE("(%p)\n", aOffline);
1146     return nsIIOService_GetOffline(nsio, aOffline);
1147 }
1148
1149 static nsresult NSAPI nsIOService_SetOffline(nsIIOService *iface, PRBool aOffline)
1150 {
1151     TRACE("(%x)\n", aOffline);
1152     return nsIIOService_SetOffline(nsio, aOffline);
1153 }
1154
1155 static nsresult NSAPI nsIOService_AllowPort(nsIIOService *iface, PRInt32 aPort,
1156                                              const char *aScheme, PRBool *_retval)
1157 {
1158     TRACE("(%ld %s %p)\n", aPort, debugstr_a(aScheme), _retval);
1159     return nsIIOService_AllowPort(nsio, aPort, debugstr_a(aScheme), _retval);
1160 }
1161
1162 static nsresult NSAPI nsIOService_ExtractScheme(nsIIOService *iface, const nsACString *urlString,
1163                                                  nsACString * _retval)
1164 {
1165     TRACE("(%p %p)\n", urlString, _retval);
1166     return nsIIOService_ExtractScheme(nsio, urlString, _retval);
1167 }
1168
1169 static const nsIIOServiceVtbl nsIOServiceVtbl = {
1170     nsIOService_QueryInterface,
1171     nsIOService_AddRef,
1172     nsIOService_Release,
1173     nsIOService_GetProtocolHandler,
1174     nsIOService_GetProtocolFlags,
1175     nsIOService_NewURI,
1176     nsIOService_NewFileURI,
1177     nsIOService_NewChannelFromURI,
1178     nsIOService_NewChannel,
1179     nsIOService_GetOffline,
1180     nsIOService_SetOffline,
1181     nsIOService_AllowPort,
1182     nsIOService_ExtractScheme
1183 };
1184
1185 static nsIIOService nsIOService = { &nsIOServiceVtbl };
1186
1187 static nsresult NSAPI nsIOServiceFactory_QueryInterface(nsIFactory *iface, nsIIDRef riid,
1188                                                         nsQIResult result)
1189 {
1190     *result = NULL;
1191
1192     if(IsEqualGUID(&IID_nsISupports, riid)) {
1193         TRACE("(IID_nsISupoprts %p)\n", result);
1194         *result = iface;
1195     }else if(IsEqualGUID(&IID_nsIFactory, riid)) {
1196         TRACE("(IID_nsIFactory %p)\n", result);
1197         *result = iface;
1198     }
1199
1200     if(*result) {
1201         nsIFactory_AddRef(iface);
1202         return NS_OK;
1203     }
1204
1205     WARN("(%s %p)\n", debugstr_guid(riid), result);
1206     return NS_NOINTERFACE;
1207 }
1208
1209 static nsrefcnt NSAPI nsIOServiceFactory_AddRef(nsIFactory *iface)
1210 {
1211     return 2;
1212 }
1213
1214 static nsrefcnt NSAPI nsIOServiceFactory_Release(nsIFactory *iface)
1215 {
1216     return 1;
1217 }
1218
1219 static nsresult NSAPI nsIOServiceFactory_CreateInstance(nsIFactory *iface,
1220         nsISupports *aOuter, const nsIID *iid, void **result)
1221 {
1222     return nsIIOService_QueryInterface(&nsIOService, iid, result);
1223 }
1224
1225 static nsresult NSAPI nsIOServiceFactory_LockFactory(nsIFactory *iface, PRBool lock)
1226 {
1227     WARN("(%x)\n", lock);
1228     return NS_OK;
1229 }
1230
1231 static const nsIFactoryVtbl nsIOServiceFactoryVtbl = {
1232     nsIOServiceFactory_QueryInterface,
1233     nsIOServiceFactory_AddRef,
1234     nsIOServiceFactory_Release,
1235     nsIOServiceFactory_CreateInstance,
1236     nsIOServiceFactory_LockFactory
1237 };
1238
1239 static nsIFactory nsIOServiceFactory = { &nsIOServiceFactoryVtbl };
1240
1241 void init_nsio(nsIComponentManager *component_manager, nsIComponentRegistrar *registrar)
1242 {
1243     nsIFactory *old_factory = NULL;
1244     nsresult nsres;
1245
1246     nsres = nsIComponentManager_GetClassObject(component_manager, &NS_IOSERVICE_CID,
1247                                                &IID_nsIFactory, (void**)&old_factory);
1248     if(NS_FAILED(nsres)) {
1249         ERR("Could not get factory: %08lx\n", nsres);
1250         nsIFactory_Release(old_factory);
1251         return;
1252     }
1253
1254     nsres = nsIFactory_CreateInstance(old_factory, NULL, &IID_nsIIOService, (void**)&nsio);
1255     if(NS_FAILED(nsres)) {
1256         ERR("Couldn not create nsIOService instance %08lx\n", nsres);
1257         nsIFactory_Release(old_factory);
1258         return;
1259     }
1260
1261     nsres = nsIComponentRegistrar_UnregisterFactory(registrar, &NS_IOSERVICE_CID, old_factory);
1262     nsIFactory_Release(old_factory);
1263     if(NS_FAILED(nsres))
1264         ERR("UnregisterFactory failed: %08lx\n", nsres);
1265
1266     nsres = nsIComponentRegistrar_RegisterFactory(registrar, &NS_IOSERVICE_CID,
1267             NS_IOSERVICE_CLASSNAME, NS_IOSERVICE_CONTRACTID, &nsIOServiceFactory);
1268     if(NS_FAILED(nsres))
1269         ERR("RegisterFactory failed: %08lx\n", nsres);
1270 }
1271
1272 nsIURI *get_nsIURI(LPCWSTR url)
1273 {
1274     nsIURI *ret;
1275     nsACString *acstr;
1276     nsresult nsres;
1277     char *urla;
1278     int len;
1279
1280     len = WideCharToMultiByte(CP_ACP, 0, url, -1, NULL, -1, NULL, NULL);
1281     urla = HeapAlloc(GetProcessHeap(), 0, len);
1282     WideCharToMultiByte(CP_ACP, 0, url, -1, urla, -1, NULL, NULL);
1283
1284     acstr = nsACString_Create();
1285     nsACString_SetData(acstr, urla);
1286
1287     nsres = nsIIOService_NewURI(nsio, acstr, NULL, NULL, &ret);
1288     if(NS_FAILED(nsres))
1289         FIXME("NewURI failed: %08lx\n", nsres);
1290
1291     nsACString_Destroy(acstr);
1292     HeapFree(GetProcessHeap(), 0, urla);
1293
1294     return ret;
1295 }