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