mshtml: Added IDM_UNDERLINE implementation.
[wine] / dlls / mshtml / nsembed.c
1 /*
2  * Copyright 2005-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., 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
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 NS_APPSTARTUPNOTIFIER_CONTRACTID "@mozilla.org/embedcomp/appstartup-notifier;1"
39 #define NS_WEBBROWSER_CONTRACTID "@mozilla.org/embedding/browser/nsWebBrowser;1"
40 #define NS_PROFILE_CONTRACTID "@mozilla.org/profile/manager;1"
41 #define NS_MEMORY_CONTRACTID "@mozilla.org/xpcom/memory-service;1"
42 #define NS_STRINGSTREAM_CONTRACTID "@mozilla.org/io/string-input-stream;1"
43 #define NS_COMMANDPARAMS_CONTRACTID "@mozilla.org/embedcomp/command-params;1"
44
45 #define APPSTARTUP_TOPIC "app-startup"
46
47 #define PR_UINT32_MAX 0xffffffff
48
49 struct nsCStringContainer {
50     void *v;
51     void *d1;
52     PRUint32 d2;
53     void *d3;
54 };
55
56 static nsresult (*NS_InitXPCOM2)(nsIServiceManager**,void*,void*);
57 static nsresult (*NS_ShutdownXPCOM)(nsIServiceManager*);
58 static nsresult (*NS_GetComponentRegistrar)(nsIComponentRegistrar**);
59 static nsresult (*NS_StringContainerInit)(nsStringContainer*);
60 static nsresult (*NS_CStringContainerInit)(nsCStringContainer*);
61 static nsresult (*NS_StringContainerFinish)(nsStringContainer*);
62 static nsresult (*NS_CStringContainerFinish)(nsCStringContainer*);
63 static nsresult (*NS_StringSetData)(nsAString*,const PRUnichar*,PRUint32);
64 static nsresult (*NS_CStringSetData)(nsACString*,const char*,PRUint32);
65 static nsresult (*NS_NewLocalFile)(const nsAString*,PRBool,nsIFile**);
66 static PRUint32 (*NS_StringGetData)(const nsAString*,const PRUnichar **,PRBool*);
67 static PRUint32 (*NS_CStringGetData)(const nsACString*,const char**,PRBool*);
68
69 static HINSTANCE hXPCOM = NULL;
70
71 static nsIServiceManager *pServMgr = NULL;
72 static nsIComponentManager *pCompMgr = NULL;
73 static nsIMemory *nsmem = NULL;
74
75 static const WCHAR wszNsContainer[] = {'N','s','C','o','n','t','a','i','n','e','r',0};
76
77 static ATOM nscontainer_class;
78
79 static LRESULT WINAPI nsembed_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
80 {
81     NSContainer *This;
82     nsresult nsres;
83
84     static const WCHAR wszTHIS[] = {'T','H','I','S',0};
85
86     if(msg == WM_CREATE) {
87         This = *(NSContainer**)lParam;
88         SetPropW(hwnd, wszTHIS, This);
89     }else {
90         This = (NSContainer*)GetPropW(hwnd, wszTHIS);
91     }
92
93     switch(msg) {
94         case WM_SIZE:
95             TRACE("(%p)->(WM_SIZE)\n", This);
96
97             nsres = nsIBaseWindow_SetSize(This->window,
98                     LOWORD(lParam), HIWORD(lParam), TRUE);
99             if(NS_FAILED(nsres))
100                 WARN("SetSize failed: %08lx\n", nsres);
101     }
102
103     return DefWindowProcW(hwnd, msg, wParam, lParam);
104 }
105
106
107 static void register_nscontainer_class(void)
108 {
109     static WNDCLASSEXW wndclass = {
110         sizeof(WNDCLASSEXW),
111         CS_DBLCLKS,
112         nsembed_proc,
113         0, 0, NULL, NULL, NULL, NULL, NULL,
114         wszNsContainer,
115         NULL,
116     };
117     wndclass.hInstance = hInst;
118     nscontainer_class = RegisterClassExW(&wndclass);
119 }
120
121 static BOOL load_xpcom(PRUnichar *gre_path)
122 {
123     WCHAR path_env[MAX_PATH];
124     int len;
125
126     static const WCHAR wszPATH[] = {'P','A','T','H',0};
127     static const WCHAR strXPCOM[] = {'x','p','c','o','m','.','d','l','l',0};
128
129     TRACE("(%s)\n", debugstr_w(gre_path));
130
131     /* We have to modify PATH as XPCOM loads other DLLs from this directory. */
132     GetEnvironmentVariableW(wszPATH, path_env, sizeof(path_env)/sizeof(WCHAR));
133     len = strlenW(path_env);
134     path_env[len++] = ';';
135     strcpyW(path_env+len, gre_path);
136     SetEnvironmentVariableW(wszPATH, path_env);
137
138     hXPCOM = LoadLibraryW(strXPCOM);
139     if(!hXPCOM) {
140         WARN("Could not load XPCOM: %ld\n", GetLastError());
141         return FALSE;
142     }
143
144 #define NS_DLSYM(func) \
145     func = (typeof(func))GetProcAddress(hXPCOM, #func); \
146     if(!func) \
147         ERR("Could not GetProcAddress(" #func ") failed\n")
148
149     NS_DLSYM(NS_InitXPCOM2);
150     NS_DLSYM(NS_ShutdownXPCOM);
151     NS_DLSYM(NS_GetComponentRegistrar);
152     NS_DLSYM(NS_StringContainerInit);
153     NS_DLSYM(NS_CStringContainerInit);
154     NS_DLSYM(NS_StringContainerFinish);
155     NS_DLSYM(NS_CStringContainerFinish);
156     NS_DLSYM(NS_StringSetData);
157     NS_DLSYM(NS_CStringSetData);
158     NS_DLSYM(NS_NewLocalFile);
159     NS_DLSYM(NS_StringGetData);
160     NS_DLSYM(NS_CStringGetData);
161
162 #undef NS_DLSYM
163
164     return TRUE;
165 }
166
167 static BOOL load_mozilla(PRUnichar *gre_path)
168 {
169     DWORD res, type, i, size = MAX_PATH;
170     HKEY mozilla_key, hkey;
171     WCHAR key_name[100];
172     BOOL ret = FALSE;
173
174     static const WCHAR wszGreKey[] =
175         {'S','o','f','t','w','a','r','e','\\',
176             'm','o','z','i','l','l','a','.','o','r','g','\\',
177                 'G','R','E',0};
178
179     static const WCHAR wszGreHome[] = {'G','r','e','H','o','m','e',0};
180
181     res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszGreKey, &mozilla_key);
182     if(res != ERROR_SUCCESS) {
183         TRACE("Could not open key %s\n", debugstr_w(wszGreKey));
184         return FALSE;
185     }
186
187     for(i=0; !ret && RegEnumKeyW(mozilla_key, i, key_name, sizeof(key_name)/sizeof(WCHAR)) == ERROR_SUCCESS; i++) {
188         RegOpenKeyW(mozilla_key, key_name, &hkey);
189         res = RegQueryValueExW(hkey, wszGreHome, NULL, &type, (LPBYTE)gre_path, &size);
190         if(res == ERROR_SUCCESS)
191             ret = TRUE;
192         RegCloseKey(hkey);
193     }
194
195     RegCloseKey(mozilla_key);
196     return ret ? load_xpcom(gre_path) : FALSE;
197 }
198
199 static BOOL load_mozctl(PRUnichar *gre_path)
200 {
201     HKEY hkey;
202     DWORD res, type, size = MAX_PATH;
203
204     static const WCHAR wszMozCtlKey[] =
205         {'S','o','f','t','w','a','r','e','\\','M','o','z','i','l','l','a',0};
206     static const WCHAR wszBinDirectoryPath[] =
207         {'B','i','n','D','i','r','e','c','t','o','r','y','P','a','t','h',0};
208     static const WCHAR wszMozCtlClsidKey[] =
209         {'C','L','S','I','D','\\',
210          '{','1','3','3','9','B','5','4','C','-','3','4','5','3','-','1','1','D','2',
211          '-','9','3','B','9','-','0','0','0','0','0','0','0','0','0','0','0','0','}','\\',
212          'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
213
214     res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszMozCtlKey, &hkey);
215     if(res == ERROR_SUCCESS) {
216         res = RegQueryValueExW(hkey, wszBinDirectoryPath, NULL, &type, (LPBYTE)gre_path, &size);
217         if(res == ERROR_SUCCESS)
218             return load_xpcom(gre_path);
219         else
220             ERR("Could not get value %s\n", debugstr_w(wszBinDirectoryPath));
221     }
222
223     res = RegOpenKeyW(HKEY_CLASSES_ROOT, wszMozCtlClsidKey, &hkey);
224     if(res == ERROR_SUCCESS) {
225         res = RegQueryValueExW(hkey, NULL, NULL, &type, (LPBYTE)gre_path, &size);
226         if(res == ERROR_SUCCESS) {
227             WCHAR *ptr;
228             if((ptr = strrchrW(gre_path, '\\')))
229                 ptr[1] = 0;
230             load_xpcom(gre_path);
231         }else {
232             ERR("Could not get value of %s\n", debugstr_w(wszMozCtlClsidKey));
233         }
234     }
235
236     TRACE("Could not find Mozilla ActiveX Control\n");
237
238     return FALSE;
239 }
240
241 static BOOL load_wine_gecko(PRUnichar *gre_path)
242 {
243     HKEY hkey;
244     DWORD res, type, size = MAX_PATH;
245
246     static const WCHAR wszMshtmlKey[] = {
247         'S','o','f','t','w','a','r','e','\\','W','i','n','e',
248         '\\','M','S','H','T','M','L',0};
249     static const WCHAR wszGeckoPath[] =
250         {'G','e','c','k','o','P','a','t','h',0};
251
252     /* @@ Wine registry key: HKCU\Software\Wine\MSHTML */
253     res = RegOpenKeyW(HKEY_CURRENT_USER, wszMshtmlKey, &hkey);
254     if(res != ERROR_SUCCESS)
255         return FALSE;
256
257     res = RegQueryValueExW(hkey, wszGeckoPath, NULL, &type, (LPBYTE)gre_path, &size);
258     if(res != ERROR_SUCCESS || type != REG_SZ)
259         return FALSE;
260
261     return load_xpcom(gre_path);
262 }
263
264 static void set_profile(void)
265 {
266     nsIProfile *profile;
267     PRBool exists = FALSE;
268     nsresult nsres;
269
270     static const WCHAR wszMSHTML[] = {'M','S','H','T','M','L',0};
271
272     nsres = nsIServiceManager_GetServiceByContactID(pServMgr, NS_PROFILE_CONTRACTID,
273                                          &IID_nsIProfile, (void**)&profile);
274     if(NS_FAILED(nsres)) {
275         ERR("Could not get profile service: %08lx\n", nsres);
276         return;
277     }
278
279     nsres = nsIProfile_ProfileExists(profile, wszMSHTML, &exists);
280     if(!exists) {
281         nsres = nsIProfile_CreateNewProfile(profile, wszMSHTML, NULL, NULL, FALSE);
282         if(NS_FAILED(nsres))
283             ERR("CreateNewProfile failed: %08lx\n", nsres);
284     }
285
286     nsres = nsIProfile_SetCurrentProfile(profile, wszMSHTML);
287     if(NS_FAILED(nsres))
288         ERR("SetCurrentProfile failed: %08lx\n", nsres);
289
290     nsIProfile_Release(profile);
291 }
292
293 static BOOL load_gecko(void)
294 {
295     nsresult nsres;
296     nsIObserver *pStartNotif;
297     nsIComponentRegistrar *registrar = NULL;
298     nsAString path;
299     nsIFile *gre_dir;
300     PRUnichar gre_path[MAX_PATH];
301
302     static BOOL tried_load = FALSE;
303
304     TRACE("()\n");
305
306     if(tried_load)
307         return pCompMgr != NULL;
308     tried_load = TRUE;
309
310     if(!load_wine_gecko(gre_path) && !load_mozctl(gre_path) && !load_mozilla(gre_path)) {
311         install_wine_gecko();
312         if(!load_wine_gecko(gre_path)) {
313             MESSAGE("Could not load Mozilla. HTML rendering will be disabled.\n");
314             return FALSE;
315         }
316     }
317
318     NS_StringContainerInit(&path);
319     NS_StringSetData(&path, gre_path, PR_UINT32_MAX);
320     nsres = NS_NewLocalFile(&path, FALSE, &gre_dir);
321     NS_StringContainerFinish(&path);
322     if(NS_FAILED(nsres)) {
323         ERR("NS_NewLocalFile failed: %08lx\n", nsres);
324         FreeLibrary(hXPCOM);
325         return FALSE;
326     }
327
328     nsres = NS_InitXPCOM2(&pServMgr, gre_dir, NULL);
329     if(NS_FAILED(nsres)) {
330         ERR("NS_InitXPCOM2 failed: %08lx\n", nsres);
331         FreeLibrary(hXPCOM);
332         return FALSE;
333     }
334
335     nsres = nsIServiceManager_QueryInterface(pServMgr, &IID_nsIComponentManager, (void**)&pCompMgr);
336     if(NS_FAILED(nsres))
337         ERR("Could not get nsIComponentManager: %08lx\n", nsres);
338
339     nsres = NS_GetComponentRegistrar(&registrar);
340     if(NS_SUCCEEDED(nsres)) {
341         nsres = nsIComponentRegistrar_AutoRegister(registrar, NULL);
342         if(NS_FAILED(nsres))
343             ERR("AutoRegister(NULL) failed: %08lx\n", nsres);
344
345         nsres = nsIComponentRegistrar_AutoRegister(registrar, gre_dir);
346         if(NS_FAILED(nsres))
347             ERR("AutoRegister(gre_dir) failed: %08lx\n", nsres);
348
349         init_nsio(pCompMgr, registrar);
350     }else {
351         ERR("NS_GetComponentRegistrar failed: %08lx\n", nsres);
352     }
353
354     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_APPSTARTUPNOTIFIER_CONTRACTID,
355             NULL, &IID_nsIObserver, (void**)&pStartNotif);
356     if(NS_SUCCEEDED(nsres)) {
357         nsres = nsIObserver_Observe(pStartNotif, NULL, APPSTARTUP_TOPIC, NULL);
358         if(NS_FAILED(nsres))
359             ERR("Observe failed: %08lx\n", nsres);
360
361         nsIObserver_Release(pStartNotif);
362     }else {
363         ERR("could not get appstartup-notifier: %08lx\n", nsres);
364     }
365
366     set_profile();
367
368     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_MEMORY_CONTRACTID,
369             NULL, &IID_nsIMemory, (void**)&nsmem);
370     if(NS_FAILED(nsres))
371         ERR("Could not get nsIMemory: %08lx\n", nsres);
372
373     if(registrar) {
374         register_nsservice(registrar, pServMgr);
375         nsIComponentRegistrar_Release(registrar);
376     }
377
378     return TRUE;
379 }
380
381 void *nsalloc(size_t size)
382 {
383     return nsIMemory_Alloc(nsmem, size);
384 }
385
386 void nsfree(void *mem)
387 {
388     nsIMemory_Free(nsmem, mem);
389 }
390
391 void nsACString_Init(nsACString *str, const char *data)
392 {
393     NS_CStringContainerInit(str);
394     if(data)
395         NS_CStringSetData(str, data, PR_UINT32_MAX);
396 }
397
398 PRUint32 nsACString_GetData(const nsACString *str, const char **data, PRBool *termited)
399 {
400     return NS_CStringGetData(str, data, termited);
401 }
402
403 void nsACString_Finish(nsACString *str)
404 {
405     NS_CStringContainerFinish(str);
406 }
407
408 void nsAString_Init(nsAString *str, const PRUnichar *data)
409 {
410     NS_StringContainerInit(str);
411     if(data)
412         NS_StringSetData(str, data, PR_UINT32_MAX);
413 }
414
415 PRUint32 nsAString_GetData(const nsAString *str, const PRUnichar **data, PRBool *termited)
416 {
417     return NS_StringGetData(str, data, termited);
418 }
419
420 void nsAString_Finish(nsAString *str)
421 {
422     NS_StringContainerFinish(str);
423 }
424
425 nsIInputStream *create_nsstream(const char *data, PRInt32 data_len)
426 {
427     nsIStringInputStream *ret;
428     nsresult nsres;
429
430     if(!pCompMgr)
431         return NULL;
432
433     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
434             NS_STRINGSTREAM_CONTRACTID, NULL, &IID_nsIStringInputStream,
435             (void**)&ret);
436     if(NS_FAILED(nsres)) {
437         ERR("Could not get nsIStringInputStream\n");
438         return NULL;
439     }
440
441     nsres = nsIStringInputStream_SetData(ret, data, data_len);
442     if(NS_FAILED(nsres)) {
443         ERR("AdoptData failed: %08lx\n", nsres);
444         nsIStringInputStream_Release(ret);
445         return NULL;
446     }
447
448     return (nsIInputStream*)ret;
449 }
450
451 nsICommandParams *create_nscommand_params(void)
452 {
453     nsICommandParams *ret = NULL;
454     nsresult nsres;
455
456     if(!pCompMgr)
457         return NULL;
458
459     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
460             NS_COMMANDPARAMS_CONTRACTID, NULL, &IID_nsICommandParams,
461             (void**)&ret);
462     if(NS_FAILED(nsres))
463         ERR("Could not get nsICommandParams\n");
464
465     return ret;
466 }
467
468 void close_gecko()
469 {
470     TRACE("()\n");
471
472     if(pCompMgr)
473         nsIComponentManager_Release(pCompMgr);
474
475     if(pServMgr)
476         nsIServiceManager_Release(pServMgr);
477
478     if(nsmem)
479         nsIMemory_Release(nsmem);
480
481     if(hXPCOM)
482         FreeLibrary(hXPCOM);
483 }
484
485 /**********************************************************
486  *      nsIWebBrowserChrome interface
487  */
488
489 #define NSWBCHROME_THIS(iface) DEFINE_THIS(NSContainer, WebBrowserChrome, iface)
490
491 static nsresult NSAPI nsWebBrowserChrome_QueryInterface(nsIWebBrowserChrome *iface,
492         nsIIDRef riid, nsQIResult result)
493 {
494     NSContainer *This = NSWBCHROME_THIS(iface);
495
496     *result = NULL;
497     if(IsEqualGUID(&IID_nsISupports, riid)) {
498         TRACE("(%p)->(IID_nsISupports, %p)\n", This, result);
499         *result = NSWBCHROME(This);
500     }else if(IsEqualGUID(&IID_nsIWebBrowserChrome, riid)) {
501         TRACE("(%p)->(IID_nsIWebBrowserChrome, %p)\n", This, result);
502         *result = NSWBCHROME(This);
503     }else if(IsEqualGUID(&IID_nsIContextMenuListener, riid)) {
504         TRACE("(%p)->(IID_nsIContextMenuListener, %p)\n", This, result);
505         *result = NSCML(This);
506     }else if(IsEqualGUID(&IID_nsIURIContentListener, riid)) {
507         TRACE("(%p)->(IID_nsIURIContentListener %p)\n", This, result);
508         *result = NSURICL(This);
509     }else if(IsEqualGUID(&IID_nsIEmbeddingSiteWindow, riid)) {
510         TRACE("(%p)->(IID_nsIEmbeddingSiteWindow %p)\n", This, result);
511         *result = NSEMBWNDS(This);
512     }else if(IsEqualGUID(&IID_nsITooltipListener, riid)) {
513         TRACE("(%p)->(IID_nsITooltipListener %p)\n", This, result);
514         *result = NSTOOLTIP(This);
515     }else if(IsEqualGUID(&IID_nsIInterfaceRequestor, riid)) {
516         TRACE("(%p)->(IID_nsIInterfaceRequestor %p)\n", This, result);
517         *result = NSIFACEREQ(This);
518     }else if(IsEqualGUID(&IID_nsIWeakReference, riid)) {
519         TRACE("(%p)->(IID_nsIWeakReference %p)\n", This, result);
520         *result = NSWEAKREF(This);
521     }else if(IsEqualGUID(&IID_nsISupportsWeakReference, riid)) {
522         TRACE("(%p)->(IID_nsISupportsWeakReference %p)\n", This, result);
523         *result = NSSUPWEAKREF(This);
524     }
525
526     if(*result) {
527         nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
528         return NS_OK;
529     }
530
531     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
532     return NS_NOINTERFACE;
533 }
534
535 static nsrefcnt NSAPI nsWebBrowserChrome_AddRef(nsIWebBrowserChrome *iface)
536 {
537     NSContainer *This = NSWBCHROME_THIS(iface);
538     LONG ref = InterlockedIncrement(&This->ref);
539
540     TRACE("(%p) ref=%ld\n", This, ref);
541
542     return ref;
543 }
544
545 static nsrefcnt NSAPI nsWebBrowserChrome_Release(nsIWebBrowserChrome *iface)
546 {
547     NSContainer *This = NSWBCHROME_THIS(iface);
548     LONG ref = InterlockedDecrement(&This->ref);
549
550     TRACE("(%p) ref=%ld\n", This, ref);
551
552     if(!ref) {
553         if(This->parent)
554             nsIWebBrowserChrome_Release(NSWBCHROME(This->parent));
555         mshtml_free(This);
556     }
557
558     return ref;
559 }
560
561 static nsresult NSAPI nsWebBrowserChrome_SetStatus(nsIWebBrowserChrome *iface,
562         PRUint32 statusType, const PRUnichar *status)
563 {
564     NSContainer *This = NSWBCHROME_THIS(iface);
565     TRACE("(%p)->(%ld %s)\n", This, statusType, debugstr_w(status));
566     return NS_ERROR_NOT_IMPLEMENTED;
567 }
568
569 static nsresult NSAPI nsWebBrowserChrome_GetWebBrowser(nsIWebBrowserChrome *iface,
570         nsIWebBrowser **aWebBrowser)
571 {
572     NSContainer *This = NSWBCHROME_THIS(iface);
573
574     TRACE("(%p)->(%p)\n", This, aWebBrowser);
575
576     if(!aWebBrowser)
577         return NS_ERROR_INVALID_ARG;
578
579     if(This->webbrowser)
580         nsIWebBrowser_AddRef(This->webbrowser);
581     *aWebBrowser = This->webbrowser;
582     return S_OK;
583 }
584
585 static nsresult NSAPI nsWebBrowserChrome_SetWebBrowser(nsIWebBrowserChrome *iface,
586         nsIWebBrowser *aWebBrowser)
587 {
588     NSContainer *This = NSWBCHROME_THIS(iface);
589
590     TRACE("(%p)->(%p)\n", This, aWebBrowser);
591
592     if(aWebBrowser != This->webbrowser)
593         ERR("Wrong nsWebBrowser!\n");
594
595     return NS_OK;
596 }
597
598 static nsresult NSAPI nsWebBrowserChrome_GetChromeFlags(nsIWebBrowserChrome *iface,
599         PRUint32 *aChromeFlags)
600 {
601     NSContainer *This = NSWBCHROME_THIS(iface);
602     WARN("(%p)->(%p)\n", This, aChromeFlags);
603     return NS_ERROR_NOT_IMPLEMENTED;
604 }
605
606 static nsresult NSAPI nsWebBrowserChrome_SetChromeFlags(nsIWebBrowserChrome *iface,
607         PRUint32 aChromeFlags)
608 {
609     NSContainer *This = NSWBCHROME_THIS(iface);
610     WARN("(%p)->(%08lx)\n", This, aChromeFlags);
611     return NS_ERROR_NOT_IMPLEMENTED;
612 }
613
614 static nsresult NSAPI nsWebBrowserChrome_DestroyBrowserWindow(nsIWebBrowserChrome *iface)
615 {
616     NSContainer *This = NSWBCHROME_THIS(iface);
617     TRACE("(%p)\n", This);
618     return NS_ERROR_NOT_IMPLEMENTED;
619 }
620
621 static nsresult NSAPI nsWebBrowserChrome_SizeBrowserTo(nsIWebBrowserChrome *iface,
622         PRInt32 aCX, PRInt32 aCY)
623 {
624     NSContainer *This = NSWBCHROME_THIS(iface);
625     WARN("(%p)->(%ld %ld)\n", This, aCX, aCY);
626     return NS_ERROR_NOT_IMPLEMENTED;
627 }
628
629 static nsresult NSAPI nsWebBrowserChrome_ShowAsModal(nsIWebBrowserChrome *iface)
630 {
631     NSContainer *This = NSWBCHROME_THIS(iface);
632     WARN("(%p)\n", This);
633     return NS_ERROR_NOT_IMPLEMENTED;
634 }
635
636 static nsresult NSAPI nsWebBrowserChrome_IsWindowModal(nsIWebBrowserChrome *iface, PRBool *_retval)
637 {
638     NSContainer *This = NSWBCHROME_THIS(iface);
639     WARN("(%p)->(%p)\n", This, _retval);
640     return NS_ERROR_NOT_IMPLEMENTED;
641 }
642
643 static nsresult NSAPI nsWebBrowserChrome_ExitModalEventLoop(nsIWebBrowserChrome *iface,
644         nsresult aStatus)
645 {
646     NSContainer *This = NSWBCHROME_THIS(iface);
647     WARN("(%p)->(%08lx)\n", This, aStatus);
648     return NS_ERROR_NOT_IMPLEMENTED;
649 }
650
651 #undef NSWBCHROME_THIS
652
653 static const nsIWebBrowserChromeVtbl nsWebBrowserChromeVtbl = {
654     nsWebBrowserChrome_QueryInterface,
655     nsWebBrowserChrome_AddRef,
656     nsWebBrowserChrome_Release,
657     nsWebBrowserChrome_SetStatus,
658     nsWebBrowserChrome_GetWebBrowser,
659     nsWebBrowserChrome_SetWebBrowser,
660     nsWebBrowserChrome_GetChromeFlags,
661     nsWebBrowserChrome_SetChromeFlags,
662     nsWebBrowserChrome_DestroyBrowserWindow,
663     nsWebBrowserChrome_SizeBrowserTo,
664     nsWebBrowserChrome_ShowAsModal,
665     nsWebBrowserChrome_IsWindowModal,
666     nsWebBrowserChrome_ExitModalEventLoop
667 };
668
669 /**********************************************************
670  *      nsIContextMenuListener interface
671  */
672
673 #define NSCML_THIS(iface) DEFINE_THIS(NSContainer, ContextMenuListener, iface)
674
675 static nsresult NSAPI nsContextMenuListener_QueryInterface(nsIContextMenuListener *iface,
676         nsIIDRef riid, nsQIResult result)
677 {
678     NSContainer *This = NSCML_THIS(iface);
679     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
680 }
681
682 static nsrefcnt NSAPI nsContextMenuListener_AddRef(nsIContextMenuListener *iface)
683 {
684     NSContainer *This = NSCML_THIS(iface);
685     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
686 }
687
688 static nsrefcnt NSAPI nsContextMenuListener_Release(nsIContextMenuListener *iface)
689 {
690     NSContainer *This = NSCML_THIS(iface);
691     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
692 }
693
694 static nsresult NSAPI nsContextMenuListener_OnShowContextMenu(nsIContextMenuListener *iface,
695         PRUint32 aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode)
696 {
697     NSContainer *This = NSCML_THIS(iface);
698     nsIDOMMouseEvent *event;
699     POINT pt;
700     DWORD dwID = CONTEXT_MENU_DEFAULT;
701     nsresult nsres;
702
703     TRACE("(%p)->(%08lx %p %p)\n", This, aContextFlags, aEvent, aNode);
704
705     nsres = nsIDOMEvent_QueryInterface(aEvent, &IID_nsIDOMMouseEvent, (void**)&event);
706     if(NS_FAILED(nsres)) {
707         ERR("Could not get nsIDOMMouseEvent interface: %08lx\n", nsres);
708         return nsres;
709     }
710
711     nsIDOMMouseEvent_GetScreenX(event, &pt.x);
712     nsIDOMMouseEvent_GetScreenY(event, &pt.y);
713     nsIDOMMouseEvent_Release(event);
714
715     switch(aContextFlags) {
716     case CONTEXT_NONE:
717     case CONTEXT_DOCUMENT:
718     case CONTEXT_TEXT:
719         dwID = CONTEXT_MENU_DEFAULT;
720         break;
721     case CONTEXT_IMAGE:
722     case CONTEXT_IMAGE|CONTEXT_LINK:
723         dwID = CONTEXT_MENU_IMAGE;
724         break;
725     case CONTEXT_LINK:
726         dwID = CONTEXT_MENU_ANCHOR;
727         break;
728     case CONTEXT_INPUT:
729         dwID = CONTEXT_MENU_CONTROL;
730         break;
731     default:
732         FIXME("aContextFlags=%08lx\n", aContextFlags);
733     };
734
735     HTMLDocument_ShowContextMenu(This->doc, dwID, &pt);
736
737     return NS_OK;
738 }
739
740 #undef NSCML_THIS
741
742 static const nsIContextMenuListenerVtbl nsContextMenuListenerVtbl = {
743     nsContextMenuListener_QueryInterface,
744     nsContextMenuListener_AddRef,
745     nsContextMenuListener_Release,
746     nsContextMenuListener_OnShowContextMenu
747 };
748
749 /**********************************************************
750  *      nsIURIContentListener interface
751  */
752
753 #define NSURICL_THIS(iface) DEFINE_THIS(NSContainer, URIContentListener, iface)
754
755 static nsresult NSAPI nsURIContentListener_QueryInterface(nsIURIContentListener *iface,
756         nsIIDRef riid, nsQIResult result)
757 {
758     NSContainer *This = NSURICL_THIS(iface);
759     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
760 }
761
762 static nsrefcnt NSAPI nsURIContentListener_AddRef(nsIURIContentListener *iface)
763 {
764     NSContainer *This = NSURICL_THIS(iface);
765     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
766 }
767
768 static nsrefcnt NSAPI nsURIContentListener_Release(nsIURIContentListener *iface)
769 {
770     NSContainer *This = NSURICL_THIS(iface);
771     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
772 }
773
774 static nsresult NSAPI nsURIContentListener_OnStartURIOpen(nsIURIContentListener *iface,
775                                                           nsIURI *aURI, PRBool *_retval)
776 {
777     NSContainer *This = NSURICL_THIS(iface);
778     nsIWineURI *wine_uri;
779     nsACString spec_str;
780     const char *spec;
781     nsresult nsres;
782
783     nsACString_Init(&spec_str, NULL);
784     nsIURI_GetSpec(aURI, &spec_str);
785     nsACString_GetData(&spec_str, &spec, NULL);
786
787     TRACE("(%p)->(%p(%s) %p)\n", This, aURI, debugstr_a(spec), _retval);
788
789     nsACString_Finish(&spec_str);
790
791     nsres = nsIURI_QueryInterface(aURI, &IID_nsIWineURI, (void**)&wine_uri);
792     if(NS_FAILED(nsres)) {
793         WARN("Could not get nsIWineURI interface: %08lx\n", nsres);
794         return NS_ERROR_NOT_IMPLEMENTED;
795     }
796
797     nsIWineURI_SetNSContainer(wine_uri, This);
798
799     if(This->bscallback && This->bscallback->mon) {
800         LPWSTR url;
801         HRESULT hres;
802
803         hres = IMoniker_GetDisplayName(This->bscallback->mon, NULL, 0, &url);
804         if(SUCCEEDED(hres)) {
805             IMoniker *mon = NULL;
806
807             hres = CreateURLMoniker(NULL, url, &mon);
808             if(SUCCEEDED(hres)) {
809                 nsIWineURI_SetMoniker(wine_uri, mon);
810                 IMoniker_Release(mon);
811             }else {
812                 WARN("CreateURLMoniker failed: %08lx\n", hres);
813             }
814         }else {
815             WARN("GetDisplayName failed: %08lx\n", hres);
816         }
817     }
818
819     nsIWineURI_Release(wine_uri);
820
821     *_retval = FALSE;
822     return This->content_listener
823         ? nsIURIContentListener_OnStartURIOpen(This->content_listener, aURI, _retval)
824         : NS_OK;
825 }
826
827 static nsresult NSAPI nsURIContentListener_DoContent(nsIURIContentListener *iface,
828         const char *aContentType, PRBool aIsContentPreferred, nsIRequest *aRequest,
829         nsIStreamListener **aContentHandler, PRBool *_retval)
830 {
831     NSContainer *This = NSURICL_THIS(iface);
832
833     TRACE("(%p)->(%s %x %p %p %p)\n", This, debugstr_a(aContentType), aIsContentPreferred,
834             aRequest, aContentHandler, _retval);
835
836     return This->content_listener
837         ? nsIURIContentListener_DoContent(This->content_listener, aContentType,
838                   aIsContentPreferred, aRequest, aContentHandler, _retval)
839         : NS_ERROR_NOT_IMPLEMENTED;
840 }
841
842 static nsresult NSAPI nsURIContentListener_IsPreferred(nsIURIContentListener *iface,
843         const char *aContentType, char **aDesiredContentType, PRBool *_retval)
844 {
845     NSContainer *This = NSURICL_THIS(iface);
846
847     TRACE("(%p)->(%s %p %p)\n", This, debugstr_a(aContentType), aDesiredContentType, _retval);
848
849     /* FIXME: Should we do something here? */
850     *_retval = TRUE; 
851
852     return This->content_listener
853         ? nsIURIContentListener_IsPreferred(This->content_listener, aContentType,
854                   aDesiredContentType, _retval)
855         : NS_OK;
856 }
857
858 static nsresult NSAPI nsURIContentListener_CanHandleContent(nsIURIContentListener *iface,
859         const char *aContentType, PRBool aIsContentPreferred, char **aDesiredContentType,
860         PRBool *_retval)
861 {
862     NSContainer *This = NSURICL_THIS(iface);
863
864     TRACE("(%p)->(%s %x %p %p)\n", This, debugstr_a(aContentType), aIsContentPreferred,
865             aDesiredContentType, _retval);
866
867     return This->content_listener
868         ? nsIURIContentListener_CanHandleContent(This->content_listener, aContentType,
869                 aIsContentPreferred, aDesiredContentType, _retval)
870         : NS_ERROR_NOT_IMPLEMENTED;
871 }
872
873 static nsresult NSAPI nsURIContentListener_GetLoadCookie(nsIURIContentListener *iface,
874         nsISupports **aLoadCookie)
875 {
876     NSContainer *This = NSURICL_THIS(iface);
877
878     WARN("(%p)->(%p)\n", This, aLoadCookie);
879
880     return This->content_listener
881         ? nsIURIContentListener_GetLoadCookie(This->content_listener, aLoadCookie)
882         : NS_ERROR_NOT_IMPLEMENTED;
883 }
884
885 static nsresult NSAPI nsURIContentListener_SetLoadCookie(nsIURIContentListener *iface,
886         nsISupports *aLoadCookie)
887 {
888     NSContainer *This = NSURICL_THIS(iface);
889
890     WARN("(%p)->(%p)\n", This, aLoadCookie);
891
892     return This->content_listener
893         ? nsIURIContentListener_SetLoadCookie(This->content_listener, aLoadCookie)
894         : NS_ERROR_NOT_IMPLEMENTED;
895 }
896
897 static nsresult NSAPI nsURIContentListener_GetParentContentListener(nsIURIContentListener *iface,
898         nsIURIContentListener **aParentContentListener)
899 {
900     NSContainer *This = NSURICL_THIS(iface);
901
902     TRACE("(%p)->(%p)\n", This, aParentContentListener);
903
904     if(This->content_listener)
905         nsIURIContentListener_AddRef(This->content_listener);
906
907     *aParentContentListener = This->content_listener;
908     return NS_OK;
909 }
910
911 static nsresult NSAPI nsURIContentListener_SetParentContentListener(nsIURIContentListener *iface,
912         nsIURIContentListener *aParentContentListener)
913 {
914     NSContainer *This = NSURICL_THIS(iface);
915
916     TRACE("(%p)->(%p)\n", This, aParentContentListener);
917
918     if(aParentContentListener == NSURICL(This))
919         return NS_OK;
920
921     if(This->content_listener)
922         nsIURIContentListener_Release(This->content_listener);
923
924     This->content_listener = aParentContentListener;
925     if(This->content_listener)
926         nsIURIContentListener_AddRef(This->content_listener);
927
928     return NS_OK;
929 }
930
931 #undef NSURICL_THIS
932
933 static const nsIURIContentListenerVtbl nsURIContentListenerVtbl = {
934     nsURIContentListener_QueryInterface,
935     nsURIContentListener_AddRef,
936     nsURIContentListener_Release,
937     nsURIContentListener_OnStartURIOpen,
938     nsURIContentListener_DoContent,
939     nsURIContentListener_IsPreferred,
940     nsURIContentListener_CanHandleContent,
941     nsURIContentListener_GetLoadCookie,
942     nsURIContentListener_SetLoadCookie,
943     nsURIContentListener_GetParentContentListener,
944     nsURIContentListener_SetParentContentListener
945 };
946
947 /**********************************************************
948  *      nsIEmbeddinSiteWindow interface
949  */
950
951 #define NSEMBWNDS_THIS(iface) DEFINE_THIS(NSContainer, EmbeddingSiteWindow, iface)
952
953 static nsresult NSAPI nsEmbeddingSiteWindow_QueryInterface(nsIEmbeddingSiteWindow *iface,
954         nsIIDRef riid, nsQIResult result)
955 {
956     NSContainer *This = NSEMBWNDS_THIS(iface);
957     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
958 }
959
960 static nsrefcnt NSAPI nsEmbeddingSiteWindow_AddRef(nsIEmbeddingSiteWindow *iface)
961 {
962     NSContainer *This = NSEMBWNDS_THIS(iface);
963     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
964 }
965
966 static nsrefcnt NSAPI nsEmbeddingSiteWindow_Release(nsIEmbeddingSiteWindow *iface)
967 {
968     NSContainer *This = NSEMBWNDS_THIS(iface);
969     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
970 }
971
972 static nsresult NSAPI nsEmbeddingSiteWindow_SetDimensions(nsIEmbeddingSiteWindow *iface,
973         PRUint32 flags, PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy)
974 {
975     NSContainer *This = NSEMBWNDS_THIS(iface);
976     WARN("(%p)->(%08lx %ld %ld %ld %ld)\n", This, flags, x, y, cx, cy);
977     return NS_ERROR_NOT_IMPLEMENTED;
978 }
979
980 static nsresult NSAPI nsEmbeddingSiteWindow_GetDimensions(nsIEmbeddingSiteWindow *iface,
981         PRUint32 flags, PRInt32 *x, PRInt32 *y, PRInt32 *cx, PRInt32 *cy)
982 {
983     NSContainer *This = NSEMBWNDS_THIS(iface);
984     WARN("(%p)->(%08lx %p %p %p %p)\n", This, flags, x, y, cx, cy);
985     return NS_ERROR_NOT_IMPLEMENTED;
986 }
987
988 static nsresult NSAPI nsEmbeddingSiteWindow_SetFocus(nsIEmbeddingSiteWindow *iface)
989 {
990     NSContainer *This = NSEMBWNDS_THIS(iface);
991     WARN("(%p)\n", This);
992     return NS_ERROR_NOT_IMPLEMENTED;
993 }
994
995 static nsresult NSAPI nsEmbeddingSiteWindow_GetVisibility(nsIEmbeddingSiteWindow *iface,
996         PRBool *aVisibility)
997 {
998     NSContainer *This = NSEMBWNDS_THIS(iface);
999     WARN("(%p)->(%p)\n", This, aVisibility);
1000     return NS_ERROR_NOT_IMPLEMENTED;
1001 }
1002
1003 static nsresult NSAPI nsEmbeddingSiteWindow_SetVisibility(nsIEmbeddingSiteWindow *iface,
1004         PRBool aVisibility)
1005 {
1006     NSContainer *This = NSEMBWNDS_THIS(iface);
1007     WARN("(%p)->(%x)\n", This, aVisibility);
1008     return NS_ERROR_NOT_IMPLEMENTED;
1009 }
1010
1011 static nsresult NSAPI nsEmbeddingSiteWindow_GetTitle(nsIEmbeddingSiteWindow *iface,
1012         PRUnichar **aTitle)
1013 {
1014     NSContainer *This = NSEMBWNDS_THIS(iface);
1015     WARN("(%p)->(%p)\n", This, aTitle);
1016     return NS_ERROR_NOT_IMPLEMENTED;
1017 }
1018
1019 static nsresult NSAPI nsEmbeddingSiteWindow_SetTitle(nsIEmbeddingSiteWindow *iface,
1020         const PRUnichar *aTitle)
1021 {
1022     NSContainer *This = NSEMBWNDS_THIS(iface);
1023     WARN("(%p)->(%s)\n", This, debugstr_w(aTitle));
1024     return NS_ERROR_NOT_IMPLEMENTED;
1025 }
1026
1027 static nsresult NSAPI nsEmbeddingSiteWindow_GetSiteWindow(nsIEmbeddingSiteWindow *iface,
1028         void **aSiteWindow)
1029 {
1030     NSContainer *This = NSEMBWNDS_THIS(iface);
1031
1032     TRACE("(%p)->(%p)\n", This, aSiteWindow);
1033
1034     *aSiteWindow = This->hwnd;
1035     return NS_OK;
1036 }
1037
1038 static const nsIEmbeddingSiteWindowVtbl nsEmbeddingSiteWindowVtbl = {
1039     nsEmbeddingSiteWindow_QueryInterface,
1040     nsEmbeddingSiteWindow_AddRef,
1041     nsEmbeddingSiteWindow_Release,
1042     nsEmbeddingSiteWindow_SetDimensions,
1043     nsEmbeddingSiteWindow_GetDimensions,
1044     nsEmbeddingSiteWindow_SetFocus,
1045     nsEmbeddingSiteWindow_GetVisibility,
1046     nsEmbeddingSiteWindow_SetVisibility,
1047     nsEmbeddingSiteWindow_GetTitle,
1048     nsEmbeddingSiteWindow_SetTitle,
1049     nsEmbeddingSiteWindow_GetSiteWindow
1050 };
1051
1052 #define NSTOOLTIP_THIS(iface) DEFINE_THIS(NSContainer, TooltipListener, iface)
1053
1054 static nsresult NSAPI nsTooltipListener_QueryInterface(nsITooltipListener *iface, nsIIDRef riid,
1055                                                        nsQIResult result)
1056 {
1057     NSContainer *This = NSTOOLTIP_THIS(iface);
1058     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1059 }
1060
1061 static nsrefcnt NSAPI nsTooltipListener_AddRef(nsITooltipListener *iface)
1062 {
1063     NSContainer *This = NSTOOLTIP_THIS(iface);
1064     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1065 }
1066
1067 static nsrefcnt NSAPI nsTooltipListener_Release(nsITooltipListener *iface)
1068 {
1069     NSContainer *This = NSTOOLTIP_THIS(iface);
1070     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1071 }
1072
1073 static nsresult NSAPI nsTooltipListener_OnShowTooltip(nsITooltipListener *iface,
1074         PRInt32 aXCoord, PRInt32 aYCoord, const PRUnichar *aTipText)
1075 {
1076     NSContainer *This = NSTOOLTIP_THIS(iface);
1077
1078     show_tooltip(This->doc, aXCoord, aYCoord, aTipText);
1079
1080     return NS_OK;
1081 }
1082
1083 static nsresult NSAPI nsTooltipListener_OnHideTooltip(nsITooltipListener *iface)
1084 {
1085     NSContainer *This = NSTOOLTIP_THIS(iface);
1086
1087     hide_tooltip(This->doc);
1088
1089     return NS_OK;
1090 }
1091
1092 #undef NSTOOLTIM_THIS
1093
1094 static const nsITooltipListenerVtbl nsTooltipListenerVtbl = {
1095     nsTooltipListener_QueryInterface,
1096     nsTooltipListener_AddRef,
1097     nsTooltipListener_Release,
1098     nsTooltipListener_OnShowTooltip,
1099     nsTooltipListener_OnHideTooltip
1100 };
1101
1102 #define NSIFACEREQ_THIS(iface) DEFINE_THIS(NSContainer, InterfaceRequestor, iface)
1103
1104 static nsresult NSAPI nsInterfaceRequestor_QueryInterface(nsIInterfaceRequestor *iface,
1105                                                           nsIIDRef riid, nsQIResult result)
1106 {
1107     NSContainer *This = NSIFACEREQ_THIS(iface);
1108     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1109 }
1110
1111 static nsrefcnt NSAPI nsInterfaceRequestor_AddRef(nsIInterfaceRequestor *iface)
1112 {
1113     NSContainer *This = NSIFACEREQ_THIS(iface);
1114     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1115 }
1116
1117 static nsrefcnt NSAPI nsInterfaceRequestor_Release(nsIInterfaceRequestor *iface)
1118 {
1119     NSContainer *This = NSIFACEREQ_THIS(iface);
1120     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1121 }
1122
1123 static nsresult NSAPI nsInterfaceRequestor_GetInterface(nsIInterfaceRequestor *iface,
1124                                                         nsIIDRef riid, nsQIResult result)
1125 {
1126     NSContainer *This = NSIFACEREQ_THIS(iface);
1127
1128     if(IsEqualGUID(&IID_nsIDOMWindow, riid)) {
1129         TRACE("(%p)->(IID_nsIDOMWindow %p)\n", This, result);
1130         return nsIWebBrowser_GetContentDOMWindow(This->webbrowser, (nsIDOMWindow**)result);
1131     }
1132
1133     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1134 }
1135
1136 #undef NSIFACEREQ_THIS
1137
1138 static const nsIInterfaceRequestorVtbl nsInterfaceRequestorVtbl = {
1139     nsInterfaceRequestor_QueryInterface,
1140     nsInterfaceRequestor_AddRef,
1141     nsInterfaceRequestor_Release,
1142     nsInterfaceRequestor_GetInterface
1143 };
1144
1145 #define NSWEAKREF_THIS(iface) DEFINE_THIS(NSContainer, WeakReference, iface)
1146
1147 static nsresult NSAPI nsWeakReference_QueryInterface(nsIWeakReference *iface,
1148         nsIIDRef riid, nsQIResult result)
1149 {
1150     NSContainer *This = NSWEAKREF_THIS(iface);
1151     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1152 }
1153
1154 static nsrefcnt NSAPI nsWeakReference_AddRef(nsIWeakReference *iface)
1155 {
1156     NSContainer *This = NSWEAKREF_THIS(iface);
1157     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1158 }
1159
1160 static nsrefcnt NSAPI nsWeakReference_Release(nsIWeakReference *iface)
1161 {
1162     NSContainer *This = NSWEAKREF_THIS(iface);
1163     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1164 }
1165
1166 static nsresult NSAPI nsWeakReference_QueryReferent(nsIWeakReference *iface,
1167         const nsIID *riid, void **result)
1168 {
1169     NSContainer *This = NSWEAKREF_THIS(iface);
1170     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1171 }
1172
1173 #undef NSWEAKREF_THIS
1174
1175 static const nsIWeakReferenceVtbl nsWeakReferenceVtbl = {
1176     nsWeakReference_QueryInterface,
1177     nsWeakReference_AddRef,
1178     nsWeakReference_Release,
1179     nsWeakReference_QueryReferent
1180 };
1181
1182 #define NSSUPWEAKREF_THIS(iface) DEFINE_THIS(NSContainer, SupportsWeakReference, iface)
1183
1184 static nsresult NSAPI nsSupportsWeakReference_QueryInterface(nsISupportsWeakReference *iface,
1185         nsIIDRef riid, nsQIResult result)
1186 {
1187     NSContainer *This = NSSUPWEAKREF_THIS(iface);
1188     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1189 }
1190
1191 static nsrefcnt NSAPI nsSupportsWeakReference_AddRef(nsISupportsWeakReference *iface)
1192 {
1193     NSContainer *This = NSSUPWEAKREF_THIS(iface);
1194     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1195 }
1196
1197 static nsrefcnt NSAPI nsSupportsWeakReference_Release(nsISupportsWeakReference *iface)
1198 {
1199     NSContainer *This = NSSUPWEAKREF_THIS(iface);
1200     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1201 }
1202
1203 static nsresult NSAPI nsSupportsWeakReference_GetWeakReference(nsISupportsWeakReference *iface,
1204         nsIWeakReference **_retval)
1205 {
1206     NSContainer *This = NSSUPWEAKREF_THIS(iface);
1207
1208     TRACE("(%p)->(%p)\n", This, _retval);
1209
1210     nsIWeakReference_AddRef(NSWEAKREF(This));
1211     *_retval = NSWEAKREF(This);
1212     return NS_OK;
1213 }
1214
1215 #undef NSWEAKREF_THIS
1216
1217 const nsISupportsWeakReferenceVtbl nsSupportsWeakReferenceVtbl = {
1218     nsSupportsWeakReference_QueryInterface,
1219     nsSupportsWeakReference_AddRef,
1220     nsSupportsWeakReference_Release,
1221     nsSupportsWeakReference_GetWeakReference
1222 };
1223
1224
1225 NSContainer *NSContainer_Create(HTMLDocument *doc, NSContainer *parent)
1226 {
1227     nsIWebBrowserSetup *wbsetup;
1228     NSContainer *ret;
1229     nsresult nsres;
1230
1231     if(!load_gecko())
1232         return NULL;
1233
1234     ret = mshtml_alloc(sizeof(NSContainer));
1235
1236     ret->lpWebBrowserChromeVtbl      = &nsWebBrowserChromeVtbl;
1237     ret->lpContextMenuListenerVtbl   = &nsContextMenuListenerVtbl;
1238     ret->lpURIContentListenerVtbl    = &nsURIContentListenerVtbl;
1239     ret->lpEmbeddingSiteWindowVtbl   = &nsEmbeddingSiteWindowVtbl;
1240     ret->lpTooltipListenerVtbl       = &nsTooltipListenerVtbl;
1241     ret->lpInterfaceRequestorVtbl    = &nsInterfaceRequestorVtbl;
1242     ret->lpWeakReferenceVtbl         = &nsWeakReferenceVtbl;
1243     ret->lpSupportsWeakReferenceVtbl = &nsSupportsWeakReferenceVtbl;
1244
1245
1246     ret->doc = doc;
1247     ret->ref = 1;
1248     ret->bscallback = NULL;
1249     ret->content_listener = NULL;
1250
1251     if(parent)
1252         nsIWebBrowserChrome_AddRef(NSWBCHROME(parent));
1253     ret->parent = parent;
1254
1255     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_WEBBROWSER_CONTRACTID,
1256             NULL, &IID_nsIWebBrowser, (void**)&ret->webbrowser);
1257     if(NS_FAILED(nsres))
1258         ERR("Creating WebBrowser failed: %08lx\n", nsres);
1259
1260     nsres = nsIWebBrowser_SetContainerWindow(ret->webbrowser, NSWBCHROME(ret));
1261     if(NS_FAILED(nsres))
1262         ERR("SetContainerWindow failed: %08lx\n", nsres);
1263
1264     nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIBaseWindow,
1265             (void**)&ret->window);
1266     if(NS_FAILED(nsres))
1267         ERR("Could not get nsIBaseWindow interface: %08lx\n", nsres);
1268
1269     nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIWebBrowserSetup,
1270                                          (void**)&wbsetup);
1271     if(NS_SUCCEEDED(nsres)) {
1272         nsres = nsIWebBrowserSetup_SetProperty(wbsetup, SETUP_IS_CHROME_WRAPPER, TRUE);
1273         nsIWebBrowserSetup_Release(wbsetup);
1274         if(NS_FAILED(nsres))
1275             ERR("SetProperty(SETUP_IS_CHROME_WRAPPER) failed: %08lx\n", nsres);
1276     }else {
1277         ERR("Could not get nsIWebBrowserSetup interface\n");
1278     }
1279
1280     nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIWebNavigation,
1281             (void**)&ret->navigation);
1282     if(NS_FAILED(nsres))
1283         ERR("Could not get nsIWebNavigation interface: %08lx\n", nsres);
1284
1285     nsres = nsIWebBrowserFocus_QueryInterface(ret->webbrowser, &IID_nsIWebBrowserFocus,
1286             (void**)&ret->focus);
1287     if(NS_FAILED(nsres))
1288         ERR("Could not get nsIWebBrowserFocus interface: %08lx\n", nsres);
1289
1290     if(!nscontainer_class)
1291         register_nscontainer_class();
1292
1293     ret->hwnd = CreateWindowExW(0, wszNsContainer, NULL,
1294             WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, 100, 100,
1295             GetDesktopWindow(), NULL, hInst, ret);
1296
1297     nsres = nsIBaseWindow_InitWindow(ret->window, ret->hwnd, NULL, 0, 0, 100, 100);
1298     if(NS_SUCCEEDED(nsres)) {
1299         nsres = nsIBaseWindow_Create(ret->window);
1300         if(NS_FAILED(nsres))
1301             WARN("Creating window failed: %08lx\n", nsres);
1302
1303         nsIBaseWindow_SetVisibility(ret->window, FALSE);
1304         nsIBaseWindow_SetEnabled(ret->window, FALSE);
1305     }else {
1306         ERR("InitWindow failed: %08lx\n", nsres);
1307     }
1308
1309     nsres = nsIWebBrowser_SetParentURIContentListener(ret->webbrowser, NSURICL(ret));
1310     if(NS_FAILED(nsres))
1311         ERR("SetParentURIContentListener failed: %08lx\n", nsres);
1312
1313     return ret;
1314 }
1315
1316 void NSContainer_Release(NSContainer *This)
1317 {
1318     TRACE("(%p)\n", This);
1319
1320     ShowWindow(This->hwnd, SW_HIDE);
1321     SetParent(This->hwnd, NULL);
1322
1323     nsIBaseWindow_SetVisibility(This->window, FALSE);
1324     nsIBaseWindow_Destroy(This->window);
1325
1326     nsIWebBrowser_SetContainerWindow(This->webbrowser, NULL);
1327
1328     nsIWebBrowser_Release(This->webbrowser);
1329     This->webbrowser = NULL;
1330
1331     nsIWebNavigation_Release(This->navigation);
1332     This->navigation = NULL;
1333
1334     nsIBaseWindow_Release(This->window);
1335     This->window = NULL;
1336
1337     nsIWebBrowserFocus_Release(This->focus);
1338     This->focus = NULL;
1339
1340     if(This->content_listener) {
1341         nsIURIContentListener_Release(This->content_listener);
1342         This->content_listener = NULL;
1343     }
1344
1345     if(This->hwnd) {
1346         DestroyWindow(This->hwnd);
1347         This->hwnd = NULL;
1348     }
1349
1350     nsIWebBrowserChrome_Release(NSWBCHROME(This));
1351 }