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