mshtml: Added handling of right and left arrow keys in editing mode.
[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         break;
534     }
535     default:
536         FIXME("Unhandled type %u\n", type);
537     }
538
539     if(has_children) {
540         PRUint32 child_cnt, i;
541         nsIDOMNode *child_node;
542
543         nsIDOMNode_GetChildNodes(nsnode, &node_list);
544         nsIDOMNodeList_GetLength(node_list, &child_cnt);
545
546         for(i=0; i<child_cnt; i++) {
547             nsres = nsIDOMNodeList_Item(node_list, i, &child_node);
548             if(NS_SUCCEEDED(nsres)) {
549                 nsnode_to_nsstring_rec(serializer, child_node, str);
550                 nsIDOMNode_Release(child_node);
551             }else {
552                 ERR("Item failed: %08x\n", nsres);
553             }
554         }
555
556         nsIDOMNodeList_Release(node_list);
557     }
558
559     if(type == ELEMENT_NODE) {
560         nsIDOMElement *nselem;
561         nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMElement, (void**)&nselem);
562         nsIContentSerializer_AppendElementEnd(serializer, nselem, str);
563         nsIDOMElement_Release(nselem);
564     }
565 }
566
567 void nsnode_to_nsstring(nsIDOMNode *nsdoc, nsAString *str)
568 {
569     nsIContentSerializer *serializer;
570     nsIDOMNode *nsnode;
571     nsresult nsres;
572
573     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
574             NS_HTMLSERIALIZER_CONTRACTID, NULL, &IID_nsIContentSerializer,
575             (void**)&serializer);
576     if(NS_FAILED(nsres)) {
577         ERR("Could not get nsIContentSerializer: %08x\n", nsres);
578         return;
579     }
580
581     nsres = nsIContentSerializer_Init(serializer, 0, 100, NULL, FALSE);
582     if(NS_FAILED(nsres))
583         ERR("Init failed: %08x\n", nsres);
584
585     nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMNode, (void**)&nsnode);
586     nsnode_to_nsstring_rec(serializer, nsnode, str);
587     nsIDOMNode_Release(nsnode);
588
589     nsres = nsIContentSerializer_Flush(serializer, str);
590     if(NS_FAILED(nsres))
591         ERR("Flush failed: %08x\n", nsres);
592
593     nsIContentSerializer_Release(serializer);
594 }
595
596 void close_gecko()
597 {
598     TRACE("()\n");
599
600     if(pCompMgr)
601         nsIComponentManager_Release(pCompMgr);
602
603     if(pServMgr)
604         nsIServiceManager_Release(pServMgr);
605
606     if(nsmem)
607         nsIMemory_Release(nsmem);
608
609     if(hXPCOM)
610         FreeLibrary(hXPCOM);
611 }
612
613 /**********************************************************
614  *      nsIWebBrowserChrome interface
615  */
616
617 #define NSWBCHROME_THIS(iface) DEFINE_THIS(NSContainer, WebBrowserChrome, iface)
618
619 static nsresult NSAPI nsWebBrowserChrome_QueryInterface(nsIWebBrowserChrome *iface,
620         nsIIDRef riid, nsQIResult result)
621 {
622     NSContainer *This = NSWBCHROME_THIS(iface);
623
624     *result = NULL;
625     if(IsEqualGUID(&IID_nsISupports, riid)) {
626         TRACE("(%p)->(IID_nsISupports, %p)\n", This, result);
627         *result = NSWBCHROME(This);
628     }else if(IsEqualGUID(&IID_nsIWebBrowserChrome, riid)) {
629         TRACE("(%p)->(IID_nsIWebBrowserChrome, %p)\n", This, result);
630         *result = NSWBCHROME(This);
631     }else if(IsEqualGUID(&IID_nsIContextMenuListener, riid)) {
632         TRACE("(%p)->(IID_nsIContextMenuListener, %p)\n", This, result);
633         *result = NSCML(This);
634     }else if(IsEqualGUID(&IID_nsIURIContentListener, riid)) {
635         TRACE("(%p)->(IID_nsIURIContentListener %p)\n", This, result);
636         *result = NSURICL(This);
637     }else if(IsEqualGUID(&IID_nsIEmbeddingSiteWindow, riid)) {
638         TRACE("(%p)->(IID_nsIEmbeddingSiteWindow %p)\n", This, result);
639         *result = NSEMBWNDS(This);
640     }else if(IsEqualGUID(&IID_nsITooltipListener, riid)) {
641         TRACE("(%p)->(IID_nsITooltipListener %p)\n", This, result);
642         *result = NSTOOLTIP(This);
643     }else if(IsEqualGUID(&IID_nsIDOMEventListener, riid)) {
644         TRACE("(%p)->(IID_nsIDOMEventListener %p)\n", This, result);
645         *result = NSEVENTLIST(This);
646     }else if(IsEqualGUID(&IID_nsIInterfaceRequestor, riid)) {
647         TRACE("(%p)->(IID_nsIInterfaceRequestor %p)\n", This, result);
648         *result = NSIFACEREQ(This);
649     }else if(IsEqualGUID(&IID_nsIWeakReference, riid)) {
650         TRACE("(%p)->(IID_nsIWeakReference %p)\n", This, result);
651         *result = NSWEAKREF(This);
652     }else if(IsEqualGUID(&IID_nsISupportsWeakReference, riid)) {
653         TRACE("(%p)->(IID_nsISupportsWeakReference %p)\n", This, result);
654         *result = NSSUPWEAKREF(This);
655     }
656
657     if(*result) {
658         nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
659         return NS_OK;
660     }
661
662     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
663     return NS_NOINTERFACE;
664 }
665
666 static nsrefcnt NSAPI nsWebBrowserChrome_AddRef(nsIWebBrowserChrome *iface)
667 {
668     NSContainer *This = NSWBCHROME_THIS(iface);
669     LONG ref = InterlockedIncrement(&This->ref);
670
671     TRACE("(%p) ref=%d\n", This, ref);
672
673     return ref;
674 }
675
676 static nsrefcnt NSAPI nsWebBrowserChrome_Release(nsIWebBrowserChrome *iface)
677 {
678     NSContainer *This = NSWBCHROME_THIS(iface);
679     LONG ref = InterlockedDecrement(&This->ref);
680
681     TRACE("(%p) ref=%d\n", This, ref);
682
683     if(!ref) {
684         if(This->parent)
685             nsIWebBrowserChrome_Release(NSWBCHROME(This->parent));
686         mshtml_free(This);
687     }
688
689     return ref;
690 }
691
692 static nsresult NSAPI nsWebBrowserChrome_SetStatus(nsIWebBrowserChrome *iface,
693         PRUint32 statusType, const PRUnichar *status)
694 {
695     NSContainer *This = NSWBCHROME_THIS(iface);
696     TRACE("(%p)->(%d %s)\n", This, statusType, debugstr_w(status));
697     return NS_ERROR_NOT_IMPLEMENTED;
698 }
699
700 static nsresult NSAPI nsWebBrowserChrome_GetWebBrowser(nsIWebBrowserChrome *iface,
701         nsIWebBrowser **aWebBrowser)
702 {
703     NSContainer *This = NSWBCHROME_THIS(iface);
704
705     TRACE("(%p)->(%p)\n", This, aWebBrowser);
706
707     if(!aWebBrowser)
708         return NS_ERROR_INVALID_ARG;
709
710     if(This->webbrowser)
711         nsIWebBrowser_AddRef(This->webbrowser);
712     *aWebBrowser = This->webbrowser;
713     return S_OK;
714 }
715
716 static nsresult NSAPI nsWebBrowserChrome_SetWebBrowser(nsIWebBrowserChrome *iface,
717         nsIWebBrowser *aWebBrowser)
718 {
719     NSContainer *This = NSWBCHROME_THIS(iface);
720
721     TRACE("(%p)->(%p)\n", This, aWebBrowser);
722
723     if(aWebBrowser != This->webbrowser)
724         ERR("Wrong nsWebBrowser!\n");
725
726     return NS_OK;
727 }
728
729 static nsresult NSAPI nsWebBrowserChrome_GetChromeFlags(nsIWebBrowserChrome *iface,
730         PRUint32 *aChromeFlags)
731 {
732     NSContainer *This = NSWBCHROME_THIS(iface);
733     WARN("(%p)->(%p)\n", This, aChromeFlags);
734     return NS_ERROR_NOT_IMPLEMENTED;
735 }
736
737 static nsresult NSAPI nsWebBrowserChrome_SetChromeFlags(nsIWebBrowserChrome *iface,
738         PRUint32 aChromeFlags)
739 {
740     NSContainer *This = NSWBCHROME_THIS(iface);
741     WARN("(%p)->(%08x)\n", This, aChromeFlags);
742     return NS_ERROR_NOT_IMPLEMENTED;
743 }
744
745 static nsresult NSAPI nsWebBrowserChrome_DestroyBrowserWindow(nsIWebBrowserChrome *iface)
746 {
747     NSContainer *This = NSWBCHROME_THIS(iface);
748     TRACE("(%p)\n", This);
749     return NS_ERROR_NOT_IMPLEMENTED;
750 }
751
752 static nsresult NSAPI nsWebBrowserChrome_SizeBrowserTo(nsIWebBrowserChrome *iface,
753         PRInt32 aCX, PRInt32 aCY)
754 {
755     NSContainer *This = NSWBCHROME_THIS(iface);
756     WARN("(%p)->(%d %d)\n", This, aCX, aCY);
757     return NS_ERROR_NOT_IMPLEMENTED;
758 }
759
760 static nsresult NSAPI nsWebBrowserChrome_ShowAsModal(nsIWebBrowserChrome *iface)
761 {
762     NSContainer *This = NSWBCHROME_THIS(iface);
763     WARN("(%p)\n", This);
764     return NS_ERROR_NOT_IMPLEMENTED;
765 }
766
767 static nsresult NSAPI nsWebBrowserChrome_IsWindowModal(nsIWebBrowserChrome *iface, PRBool *_retval)
768 {
769     NSContainer *This = NSWBCHROME_THIS(iface);
770     WARN("(%p)->(%p)\n", This, _retval);
771     return NS_ERROR_NOT_IMPLEMENTED;
772 }
773
774 static nsresult NSAPI nsWebBrowserChrome_ExitModalEventLoop(nsIWebBrowserChrome *iface,
775         nsresult aStatus)
776 {
777     NSContainer *This = NSWBCHROME_THIS(iface);
778     WARN("(%p)->(%08x)\n", This, aStatus);
779     return NS_ERROR_NOT_IMPLEMENTED;
780 }
781
782 #undef NSWBCHROME_THIS
783
784 static const nsIWebBrowserChromeVtbl nsWebBrowserChromeVtbl = {
785     nsWebBrowserChrome_QueryInterface,
786     nsWebBrowserChrome_AddRef,
787     nsWebBrowserChrome_Release,
788     nsWebBrowserChrome_SetStatus,
789     nsWebBrowserChrome_GetWebBrowser,
790     nsWebBrowserChrome_SetWebBrowser,
791     nsWebBrowserChrome_GetChromeFlags,
792     nsWebBrowserChrome_SetChromeFlags,
793     nsWebBrowserChrome_DestroyBrowserWindow,
794     nsWebBrowserChrome_SizeBrowserTo,
795     nsWebBrowserChrome_ShowAsModal,
796     nsWebBrowserChrome_IsWindowModal,
797     nsWebBrowserChrome_ExitModalEventLoop
798 };
799
800 /**********************************************************
801  *      nsIContextMenuListener interface
802  */
803
804 #define NSCML_THIS(iface) DEFINE_THIS(NSContainer, ContextMenuListener, iface)
805
806 static nsresult NSAPI nsContextMenuListener_QueryInterface(nsIContextMenuListener *iface,
807         nsIIDRef riid, nsQIResult result)
808 {
809     NSContainer *This = NSCML_THIS(iface);
810     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
811 }
812
813 static nsrefcnt NSAPI nsContextMenuListener_AddRef(nsIContextMenuListener *iface)
814 {
815     NSContainer *This = NSCML_THIS(iface);
816     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
817 }
818
819 static nsrefcnt NSAPI nsContextMenuListener_Release(nsIContextMenuListener *iface)
820 {
821     NSContainer *This = NSCML_THIS(iface);
822     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
823 }
824
825 static nsresult NSAPI nsContextMenuListener_OnShowContextMenu(nsIContextMenuListener *iface,
826         PRUint32 aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode)
827 {
828     NSContainer *This = NSCML_THIS(iface);
829     nsIDOMMouseEvent *event;
830     POINT pt;
831     DWORD dwID = CONTEXT_MENU_DEFAULT;
832     nsresult nsres;
833
834     TRACE("(%p)->(%08x %p %p)\n", This, aContextFlags, aEvent, aNode);
835
836     nsres = nsIDOMEvent_QueryInterface(aEvent, &IID_nsIDOMMouseEvent, (void**)&event);
837     if(NS_FAILED(nsres)) {
838         ERR("Could not get nsIDOMMouseEvent interface: %08x\n", nsres);
839         return nsres;
840     }
841
842     nsIDOMMouseEvent_GetScreenX(event, &pt.x);
843     nsIDOMMouseEvent_GetScreenY(event, &pt.y);
844     nsIDOMMouseEvent_Release(event);
845
846     switch(aContextFlags) {
847     case CONTEXT_NONE:
848     case CONTEXT_DOCUMENT:
849     case CONTEXT_TEXT:
850         dwID = CONTEXT_MENU_DEFAULT;
851         break;
852     case CONTEXT_IMAGE:
853     case CONTEXT_IMAGE|CONTEXT_LINK:
854         dwID = CONTEXT_MENU_IMAGE;
855         break;
856     case CONTEXT_LINK:
857         dwID = CONTEXT_MENU_ANCHOR;
858         break;
859     case CONTEXT_INPUT:
860         dwID = CONTEXT_MENU_CONTROL;
861         break;
862     default:
863         FIXME("aContextFlags=%08x\n", aContextFlags);
864     };
865
866     HTMLDocument_ShowContextMenu(This->doc, dwID, &pt);
867
868     return NS_OK;
869 }
870
871 #undef NSCML_THIS
872
873 static const nsIContextMenuListenerVtbl nsContextMenuListenerVtbl = {
874     nsContextMenuListener_QueryInterface,
875     nsContextMenuListener_AddRef,
876     nsContextMenuListener_Release,
877     nsContextMenuListener_OnShowContextMenu
878 };
879
880 /**********************************************************
881  *      nsIURIContentListener interface
882  */
883
884 #define NSURICL_THIS(iface) DEFINE_THIS(NSContainer, URIContentListener, iface)
885
886 static nsresult NSAPI nsURIContentListener_QueryInterface(nsIURIContentListener *iface,
887         nsIIDRef riid, nsQIResult result)
888 {
889     NSContainer *This = NSURICL_THIS(iface);
890     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
891 }
892
893 static nsrefcnt NSAPI nsURIContentListener_AddRef(nsIURIContentListener *iface)
894 {
895     NSContainer *This = NSURICL_THIS(iface);
896     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
897 }
898
899 static nsrefcnt NSAPI nsURIContentListener_Release(nsIURIContentListener *iface)
900 {
901     NSContainer *This = NSURICL_THIS(iface);
902     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
903 }
904
905 static nsresult NSAPI nsURIContentListener_OnStartURIOpen(nsIURIContentListener *iface,
906                                                           nsIURI *aURI, PRBool *_retval)
907 {
908     NSContainer *This = NSURICL_THIS(iface);
909     nsIWineURI *wine_uri;
910     nsACString spec_str;
911     const char *spec;
912     nsresult nsres;
913
914     nsACString_Init(&spec_str, NULL);
915     nsIURI_GetSpec(aURI, &spec_str);
916     nsACString_GetData(&spec_str, &spec, NULL);
917
918     TRACE("(%p)->(%p(%s) %p)\n", This, aURI, debugstr_a(spec), _retval);
919
920     nsACString_Finish(&spec_str);
921
922     nsres = nsIURI_QueryInterface(aURI, &IID_nsIWineURI, (void**)&wine_uri);
923     if(NS_FAILED(nsres)) {
924         WARN("Could not get nsIWineURI interface: %08x\n", nsres);
925         return NS_ERROR_NOT_IMPLEMENTED;
926     }
927
928     nsIWineURI_SetNSContainer(wine_uri, This);
929
930     if(This->bscallback && This->bscallback->mon) {
931         LPWSTR url = NULL;
932         HRESULT hres;
933
934         hres = IMoniker_GetDisplayName(This->bscallback->mon, NULL, 0, &url);
935         if(SUCCEEDED(hres)) {
936             IMoniker *mon = NULL;
937
938             hres = CreateURLMoniker(NULL, url, &mon);
939             if(SUCCEEDED(hres)) {
940                 nsIWineURI_SetMoniker(wine_uri, mon);
941                 IMoniker_Release(mon);
942             }else {
943                 WARN("CreateURLMoniker failed: %08x\n", hres);
944             }
945         }else {
946             WARN("GetDisplayName failed: %08x\n", hres);
947         }
948     }
949
950     nsIWineURI_Release(wine_uri);
951
952     *_retval = FALSE;
953     return This->content_listener
954         ? nsIURIContentListener_OnStartURIOpen(This->content_listener, aURI, _retval)
955         : NS_OK;
956 }
957
958 static nsresult NSAPI nsURIContentListener_DoContent(nsIURIContentListener *iface,
959         const char *aContentType, PRBool aIsContentPreferred, nsIRequest *aRequest,
960         nsIStreamListener **aContentHandler, PRBool *_retval)
961 {
962     NSContainer *This = NSURICL_THIS(iface);
963
964     TRACE("(%p)->(%s %x %p %p %p)\n", This, debugstr_a(aContentType), aIsContentPreferred,
965             aRequest, aContentHandler, _retval);
966
967     return This->content_listener
968         ? nsIURIContentListener_DoContent(This->content_listener, aContentType,
969                   aIsContentPreferred, aRequest, aContentHandler, _retval)
970         : NS_ERROR_NOT_IMPLEMENTED;
971 }
972
973 static nsresult NSAPI nsURIContentListener_IsPreferred(nsIURIContentListener *iface,
974         const char *aContentType, char **aDesiredContentType, PRBool *_retval)
975 {
976     NSContainer *This = NSURICL_THIS(iface);
977
978     TRACE("(%p)->(%s %p %p)\n", This, debugstr_a(aContentType), aDesiredContentType, _retval);
979
980     /* FIXME: Should we do something here? */
981     *_retval = TRUE; 
982
983     return This->content_listener
984         ? nsIURIContentListener_IsPreferred(This->content_listener, aContentType,
985                   aDesiredContentType, _retval)
986         : NS_OK;
987 }
988
989 static nsresult NSAPI nsURIContentListener_CanHandleContent(nsIURIContentListener *iface,
990         const char *aContentType, PRBool aIsContentPreferred, char **aDesiredContentType,
991         PRBool *_retval)
992 {
993     NSContainer *This = NSURICL_THIS(iface);
994
995     TRACE("(%p)->(%s %x %p %p)\n", This, debugstr_a(aContentType), aIsContentPreferred,
996             aDesiredContentType, _retval);
997
998     return This->content_listener
999         ? nsIURIContentListener_CanHandleContent(This->content_listener, aContentType,
1000                 aIsContentPreferred, aDesiredContentType, _retval)
1001         : NS_ERROR_NOT_IMPLEMENTED;
1002 }
1003
1004 static nsresult NSAPI nsURIContentListener_GetLoadCookie(nsIURIContentListener *iface,
1005         nsISupports **aLoadCookie)
1006 {
1007     NSContainer *This = NSURICL_THIS(iface);
1008
1009     WARN("(%p)->(%p)\n", This, aLoadCookie);
1010
1011     return This->content_listener
1012         ? nsIURIContentListener_GetLoadCookie(This->content_listener, aLoadCookie)
1013         : NS_ERROR_NOT_IMPLEMENTED;
1014 }
1015
1016 static nsresult NSAPI nsURIContentListener_SetLoadCookie(nsIURIContentListener *iface,
1017         nsISupports *aLoadCookie)
1018 {
1019     NSContainer *This = NSURICL_THIS(iface);
1020
1021     WARN("(%p)->(%p)\n", This, aLoadCookie);
1022
1023     return This->content_listener
1024         ? nsIURIContentListener_SetLoadCookie(This->content_listener, aLoadCookie)
1025         : NS_ERROR_NOT_IMPLEMENTED;
1026 }
1027
1028 static nsresult NSAPI nsURIContentListener_GetParentContentListener(nsIURIContentListener *iface,
1029         nsIURIContentListener **aParentContentListener)
1030 {
1031     NSContainer *This = NSURICL_THIS(iface);
1032
1033     TRACE("(%p)->(%p)\n", This, aParentContentListener);
1034
1035     if(This->content_listener)
1036         nsIURIContentListener_AddRef(This->content_listener);
1037
1038     *aParentContentListener = This->content_listener;
1039     return NS_OK;
1040 }
1041
1042 static nsresult NSAPI nsURIContentListener_SetParentContentListener(nsIURIContentListener *iface,
1043         nsIURIContentListener *aParentContentListener)
1044 {
1045     NSContainer *This = NSURICL_THIS(iface);
1046
1047     TRACE("(%p)->(%p)\n", This, aParentContentListener);
1048
1049     if(aParentContentListener == NSURICL(This))
1050         return NS_OK;
1051
1052     if(This->content_listener)
1053         nsIURIContentListener_Release(This->content_listener);
1054
1055     This->content_listener = aParentContentListener;
1056     if(This->content_listener)
1057         nsIURIContentListener_AddRef(This->content_listener);
1058
1059     return NS_OK;
1060 }
1061
1062 #undef NSURICL_THIS
1063
1064 static const nsIURIContentListenerVtbl nsURIContentListenerVtbl = {
1065     nsURIContentListener_QueryInterface,
1066     nsURIContentListener_AddRef,
1067     nsURIContentListener_Release,
1068     nsURIContentListener_OnStartURIOpen,
1069     nsURIContentListener_DoContent,
1070     nsURIContentListener_IsPreferred,
1071     nsURIContentListener_CanHandleContent,
1072     nsURIContentListener_GetLoadCookie,
1073     nsURIContentListener_SetLoadCookie,
1074     nsURIContentListener_GetParentContentListener,
1075     nsURIContentListener_SetParentContentListener
1076 };
1077
1078 /**********************************************************
1079  *      nsIEmbeddinSiteWindow interface
1080  */
1081
1082 #define NSEMBWNDS_THIS(iface) DEFINE_THIS(NSContainer, EmbeddingSiteWindow, iface)
1083
1084 static nsresult NSAPI nsEmbeddingSiteWindow_QueryInterface(nsIEmbeddingSiteWindow *iface,
1085         nsIIDRef riid, nsQIResult result)
1086 {
1087     NSContainer *This = NSEMBWNDS_THIS(iface);
1088     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1089 }
1090
1091 static nsrefcnt NSAPI nsEmbeddingSiteWindow_AddRef(nsIEmbeddingSiteWindow *iface)
1092 {
1093     NSContainer *This = NSEMBWNDS_THIS(iface);
1094     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1095 }
1096
1097 static nsrefcnt NSAPI nsEmbeddingSiteWindow_Release(nsIEmbeddingSiteWindow *iface)
1098 {
1099     NSContainer *This = NSEMBWNDS_THIS(iface);
1100     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1101 }
1102
1103 static nsresult NSAPI nsEmbeddingSiteWindow_SetDimensions(nsIEmbeddingSiteWindow *iface,
1104         PRUint32 flags, PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy)
1105 {
1106     NSContainer *This = NSEMBWNDS_THIS(iface);
1107     WARN("(%p)->(%08x %d %d %d %d)\n", This, flags, x, y, cx, cy);
1108     return NS_ERROR_NOT_IMPLEMENTED;
1109 }
1110
1111 static nsresult NSAPI nsEmbeddingSiteWindow_GetDimensions(nsIEmbeddingSiteWindow *iface,
1112         PRUint32 flags, PRInt32 *x, PRInt32 *y, PRInt32 *cx, PRInt32 *cy)
1113 {
1114     NSContainer *This = NSEMBWNDS_THIS(iface);
1115     WARN("(%p)->(%08x %p %p %p %p)\n", This, flags, x, y, cx, cy);
1116     return NS_ERROR_NOT_IMPLEMENTED;
1117 }
1118
1119 static nsresult NSAPI nsEmbeddingSiteWindow_SetFocus(nsIEmbeddingSiteWindow *iface)
1120 {
1121     NSContainer *This = NSEMBWNDS_THIS(iface);
1122     WARN("(%p)\n", This);
1123     return NS_ERROR_NOT_IMPLEMENTED;
1124 }
1125
1126 static nsresult NSAPI nsEmbeddingSiteWindow_GetVisibility(nsIEmbeddingSiteWindow *iface,
1127         PRBool *aVisibility)
1128 {
1129     NSContainer *This = NSEMBWNDS_THIS(iface);
1130     WARN("(%p)->(%p)\n", This, aVisibility);
1131     return NS_ERROR_NOT_IMPLEMENTED;
1132 }
1133
1134 static nsresult NSAPI nsEmbeddingSiteWindow_SetVisibility(nsIEmbeddingSiteWindow *iface,
1135         PRBool aVisibility)
1136 {
1137     NSContainer *This = NSEMBWNDS_THIS(iface);
1138     WARN("(%p)->(%x)\n", This, aVisibility);
1139     return NS_ERROR_NOT_IMPLEMENTED;
1140 }
1141
1142 static nsresult NSAPI nsEmbeddingSiteWindow_GetTitle(nsIEmbeddingSiteWindow *iface,
1143         PRUnichar **aTitle)
1144 {
1145     NSContainer *This = NSEMBWNDS_THIS(iface);
1146     WARN("(%p)->(%p)\n", This, aTitle);
1147     return NS_ERROR_NOT_IMPLEMENTED;
1148 }
1149
1150 static nsresult NSAPI nsEmbeddingSiteWindow_SetTitle(nsIEmbeddingSiteWindow *iface,
1151         const PRUnichar *aTitle)
1152 {
1153     NSContainer *This = NSEMBWNDS_THIS(iface);
1154     WARN("(%p)->(%s)\n", This, debugstr_w(aTitle));
1155     return NS_ERROR_NOT_IMPLEMENTED;
1156 }
1157
1158 static nsresult NSAPI nsEmbeddingSiteWindow_GetSiteWindow(nsIEmbeddingSiteWindow *iface,
1159         void **aSiteWindow)
1160 {
1161     NSContainer *This = NSEMBWNDS_THIS(iface);
1162
1163     TRACE("(%p)->(%p)\n", This, aSiteWindow);
1164
1165     *aSiteWindow = This->hwnd;
1166     return NS_OK;
1167 }
1168
1169 static const nsIEmbeddingSiteWindowVtbl nsEmbeddingSiteWindowVtbl = {
1170     nsEmbeddingSiteWindow_QueryInterface,
1171     nsEmbeddingSiteWindow_AddRef,
1172     nsEmbeddingSiteWindow_Release,
1173     nsEmbeddingSiteWindow_SetDimensions,
1174     nsEmbeddingSiteWindow_GetDimensions,
1175     nsEmbeddingSiteWindow_SetFocus,
1176     nsEmbeddingSiteWindow_GetVisibility,
1177     nsEmbeddingSiteWindow_SetVisibility,
1178     nsEmbeddingSiteWindow_GetTitle,
1179     nsEmbeddingSiteWindow_SetTitle,
1180     nsEmbeddingSiteWindow_GetSiteWindow
1181 };
1182
1183 #define NSTOOLTIP_THIS(iface) DEFINE_THIS(NSContainer, TooltipListener, iface)
1184
1185 static nsresult NSAPI nsTooltipListener_QueryInterface(nsITooltipListener *iface, nsIIDRef riid,
1186                                                        nsQIResult result)
1187 {
1188     NSContainer *This = NSTOOLTIP_THIS(iface);
1189     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1190 }
1191
1192 static nsrefcnt NSAPI nsTooltipListener_AddRef(nsITooltipListener *iface)
1193 {
1194     NSContainer *This = NSTOOLTIP_THIS(iface);
1195     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1196 }
1197
1198 static nsrefcnt NSAPI nsTooltipListener_Release(nsITooltipListener *iface)
1199 {
1200     NSContainer *This = NSTOOLTIP_THIS(iface);
1201     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1202 }
1203
1204 static nsresult NSAPI nsTooltipListener_OnShowTooltip(nsITooltipListener *iface,
1205         PRInt32 aXCoord, PRInt32 aYCoord, const PRUnichar *aTipText)
1206 {
1207     NSContainer *This = NSTOOLTIP_THIS(iface);
1208
1209     show_tooltip(This->doc, aXCoord, aYCoord, aTipText);
1210
1211     return NS_OK;
1212 }
1213
1214 static nsresult NSAPI nsTooltipListener_OnHideTooltip(nsITooltipListener *iface)
1215 {
1216     NSContainer *This = NSTOOLTIP_THIS(iface);
1217
1218     hide_tooltip(This->doc);
1219
1220     return NS_OK;
1221 }
1222
1223 #undef NSTOOLTIM_THIS
1224
1225 static const nsITooltipListenerVtbl nsTooltipListenerVtbl = {
1226     nsTooltipListener_QueryInterface,
1227     nsTooltipListener_AddRef,
1228     nsTooltipListener_Release,
1229     nsTooltipListener_OnShowTooltip,
1230     nsTooltipListener_OnHideTooltip
1231 };
1232
1233 #define NSEVENTLIST_THIS(iface) DEFINE_THIS(NSContainer, DOMEventListener, iface)
1234
1235 static nsresult NSAPI nsDOMEventListener_QueryInterface(nsIDOMEventListener *iface,
1236                                                         nsIIDRef riid, nsQIResult result)
1237 {
1238     NSContainer *This = NSEVENTLIST_THIS(iface);
1239     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1240 }
1241
1242 static nsrefcnt NSAPI nsDOMEventListener_AddRef(nsIDOMEventListener *iface)
1243 {
1244     NSContainer *This = NSEVENTLIST_THIS(iface);
1245     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1246 }
1247
1248 static nsrefcnt NSAPI nsDOMEventListener_Release(nsIDOMEventListener *iface)
1249 {
1250     NSContainer *This = NSEVENTLIST_THIS(iface);
1251     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1252 }
1253
1254 static nsresult NSAPI nsDOMEventListener_HandleEvent(nsIDOMEventListener *iface, nsIDOMEvent *event)
1255 {
1256     NSContainer *This = NSEVENTLIST_THIS(iface);
1257
1258     TRACE("(%p)->(%p)\n", This, event);
1259
1260     if(This->doc->usermode == EDITMODE)
1261         handle_edit_event(This->doc, event);
1262
1263     return NS_OK;
1264 }
1265
1266 #undef NSEVENTLIST_THIS
1267
1268 static const nsIDOMEventListenerVtbl nsDOMEventListenerVtbl = {
1269     nsDOMEventListener_QueryInterface,
1270     nsDOMEventListener_AddRef,
1271     nsDOMEventListener_Release,
1272     nsDOMEventListener_HandleEvent
1273 };
1274
1275 #define NSIFACEREQ_THIS(iface) DEFINE_THIS(NSContainer, InterfaceRequestor, iface)
1276
1277 static nsresult NSAPI nsInterfaceRequestor_QueryInterface(nsIInterfaceRequestor *iface,
1278                                                           nsIIDRef riid, nsQIResult result)
1279 {
1280     NSContainer *This = NSIFACEREQ_THIS(iface);
1281     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1282 }
1283
1284 static nsrefcnt NSAPI nsInterfaceRequestor_AddRef(nsIInterfaceRequestor *iface)
1285 {
1286     NSContainer *This = NSIFACEREQ_THIS(iface);
1287     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1288 }
1289
1290 static nsrefcnt NSAPI nsInterfaceRequestor_Release(nsIInterfaceRequestor *iface)
1291 {
1292     NSContainer *This = NSIFACEREQ_THIS(iface);
1293     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1294 }
1295
1296 static nsresult NSAPI nsInterfaceRequestor_GetInterface(nsIInterfaceRequestor *iface,
1297                                                         nsIIDRef riid, nsQIResult result)
1298 {
1299     NSContainer *This = NSIFACEREQ_THIS(iface);
1300
1301     if(IsEqualGUID(&IID_nsIDOMWindow, riid)) {
1302         TRACE("(%p)->(IID_nsIDOMWindow %p)\n", This, result);
1303         return nsIWebBrowser_GetContentDOMWindow(This->webbrowser, (nsIDOMWindow**)result);
1304     }
1305
1306     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1307 }
1308
1309 #undef NSIFACEREQ_THIS
1310
1311 static const nsIInterfaceRequestorVtbl nsInterfaceRequestorVtbl = {
1312     nsInterfaceRequestor_QueryInterface,
1313     nsInterfaceRequestor_AddRef,
1314     nsInterfaceRequestor_Release,
1315     nsInterfaceRequestor_GetInterface
1316 };
1317
1318 #define NSWEAKREF_THIS(iface) DEFINE_THIS(NSContainer, WeakReference, iface)
1319
1320 static nsresult NSAPI nsWeakReference_QueryInterface(nsIWeakReference *iface,
1321         nsIIDRef riid, nsQIResult result)
1322 {
1323     NSContainer *This = NSWEAKREF_THIS(iface);
1324     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1325 }
1326
1327 static nsrefcnt NSAPI nsWeakReference_AddRef(nsIWeakReference *iface)
1328 {
1329     NSContainer *This = NSWEAKREF_THIS(iface);
1330     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1331 }
1332
1333 static nsrefcnt NSAPI nsWeakReference_Release(nsIWeakReference *iface)
1334 {
1335     NSContainer *This = NSWEAKREF_THIS(iface);
1336     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1337 }
1338
1339 static nsresult NSAPI nsWeakReference_QueryReferent(nsIWeakReference *iface,
1340         const nsIID *riid, void **result)
1341 {
1342     NSContainer *This = NSWEAKREF_THIS(iface);
1343     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1344 }
1345
1346 #undef NSWEAKREF_THIS
1347
1348 static const nsIWeakReferenceVtbl nsWeakReferenceVtbl = {
1349     nsWeakReference_QueryInterface,
1350     nsWeakReference_AddRef,
1351     nsWeakReference_Release,
1352     nsWeakReference_QueryReferent
1353 };
1354
1355 #define NSSUPWEAKREF_THIS(iface) DEFINE_THIS(NSContainer, SupportsWeakReference, iface)
1356
1357 static nsresult NSAPI nsSupportsWeakReference_QueryInterface(nsISupportsWeakReference *iface,
1358         nsIIDRef riid, nsQIResult result)
1359 {
1360     NSContainer *This = NSSUPWEAKREF_THIS(iface);
1361     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1362 }
1363
1364 static nsrefcnt NSAPI nsSupportsWeakReference_AddRef(nsISupportsWeakReference *iface)
1365 {
1366     NSContainer *This = NSSUPWEAKREF_THIS(iface);
1367     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1368 }
1369
1370 static nsrefcnt NSAPI nsSupportsWeakReference_Release(nsISupportsWeakReference *iface)
1371 {
1372     NSContainer *This = NSSUPWEAKREF_THIS(iface);
1373     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1374 }
1375
1376 static nsresult NSAPI nsSupportsWeakReference_GetWeakReference(nsISupportsWeakReference *iface,
1377         nsIWeakReference **_retval)
1378 {
1379     NSContainer *This = NSSUPWEAKREF_THIS(iface);
1380
1381     TRACE("(%p)->(%p)\n", This, _retval);
1382
1383     nsIWeakReference_AddRef(NSWEAKREF(This));
1384     *_retval = NSWEAKREF(This);
1385     return NS_OK;
1386 }
1387
1388 #undef NSWEAKREF_THIS
1389
1390 const nsISupportsWeakReferenceVtbl nsSupportsWeakReferenceVtbl = {
1391     nsSupportsWeakReference_QueryInterface,
1392     nsSupportsWeakReference_AddRef,
1393     nsSupportsWeakReference_Release,
1394     nsSupportsWeakReference_GetWeakReference
1395 };
1396
1397
1398 NSContainer *NSContainer_Create(HTMLDocument *doc, NSContainer *parent)
1399 {
1400     nsIDOMWindow *dom_window;
1401     nsIWebBrowserSetup *wbsetup;
1402     NSContainer *ret;
1403     nsresult nsres;
1404
1405     if(!load_gecko())
1406         return NULL;
1407
1408     ret = mshtml_alloc(sizeof(NSContainer));
1409
1410     ret->lpWebBrowserChromeVtbl      = &nsWebBrowserChromeVtbl;
1411     ret->lpContextMenuListenerVtbl   = &nsContextMenuListenerVtbl;
1412     ret->lpURIContentListenerVtbl    = &nsURIContentListenerVtbl;
1413     ret->lpEmbeddingSiteWindowVtbl   = &nsEmbeddingSiteWindowVtbl;
1414     ret->lpTooltipListenerVtbl       = &nsTooltipListenerVtbl;
1415     ret->lpInterfaceRequestorVtbl    = &nsInterfaceRequestorVtbl;
1416     ret->lpWeakReferenceVtbl         = &nsWeakReferenceVtbl;
1417     ret->lpSupportsWeakReferenceVtbl = &nsSupportsWeakReferenceVtbl;
1418     ret->lpDOMEventListenerVtbl      = &nsDOMEventListenerVtbl;
1419
1420     ret->doc = doc;
1421     ret->ref = 1;
1422     ret->bscallback = NULL;
1423     ret->content_listener = NULL;
1424
1425     if(parent)
1426         nsIWebBrowserChrome_AddRef(NSWBCHROME(parent));
1427     ret->parent = parent;
1428
1429     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_WEBBROWSER_CONTRACTID,
1430             NULL, &IID_nsIWebBrowser, (void**)&ret->webbrowser);
1431     if(NS_FAILED(nsres))
1432         ERR("Creating WebBrowser failed: %08x\n", nsres);
1433
1434     nsres = nsIWebBrowser_SetContainerWindow(ret->webbrowser, NSWBCHROME(ret));
1435     if(NS_FAILED(nsres))
1436         ERR("SetContainerWindow failed: %08x\n", nsres);
1437
1438     nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIBaseWindow,
1439             (void**)&ret->window);
1440     if(NS_FAILED(nsres))
1441         ERR("Could not get nsIBaseWindow interface: %08x\n", nsres);
1442
1443     nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIWebBrowserSetup,
1444                                          (void**)&wbsetup);
1445     if(NS_SUCCEEDED(nsres)) {
1446         nsres = nsIWebBrowserSetup_SetProperty(wbsetup, SETUP_IS_CHROME_WRAPPER, TRUE);
1447         nsIWebBrowserSetup_Release(wbsetup);
1448         if(NS_FAILED(nsres))
1449             ERR("SetProperty(SETUP_IS_CHROME_WRAPPER) failed: %08x\n", nsres);
1450     }else {
1451         ERR("Could not get nsIWebBrowserSetup interface\n");
1452     }
1453
1454     nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIWebNavigation,
1455             (void**)&ret->navigation);
1456     if(NS_FAILED(nsres))
1457         ERR("Could not get nsIWebNavigation interface: %08x\n", nsres);
1458
1459     nsres = nsIWebBrowserFocus_QueryInterface(ret->webbrowser, &IID_nsIWebBrowserFocus,
1460             (void**)&ret->focus);
1461     if(NS_FAILED(nsres))
1462         ERR("Could not get nsIWebBrowserFocus interface: %08x\n", nsres);
1463
1464     if(!nscontainer_class)
1465         register_nscontainer_class();
1466
1467     ret->hwnd = CreateWindowExW(0, wszNsContainer, NULL,
1468             WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, 100, 100,
1469             GetDesktopWindow(), NULL, hInst, ret);
1470
1471     nsres = nsIBaseWindow_InitWindow(ret->window, ret->hwnd, NULL, 0, 0, 100, 100);
1472     if(NS_SUCCEEDED(nsres)) {
1473         nsres = nsIBaseWindow_Create(ret->window);
1474         if(NS_FAILED(nsres))
1475             WARN("Creating window failed: %08x\n", nsres);
1476
1477         nsIBaseWindow_SetVisibility(ret->window, FALSE);
1478         nsIBaseWindow_SetEnabled(ret->window, FALSE);
1479     }else {
1480         ERR("InitWindow failed: %08x\n", nsres);
1481     }
1482
1483     nsres = nsIWebBrowser_SetParentURIContentListener(ret->webbrowser, NSURICL(ret));
1484     if(NS_FAILED(nsres))
1485         ERR("SetParentURIContentListener failed: %08x\n", nsres);
1486
1487     nsres = nsIWebBrowser_GetContentDOMWindow(ret->webbrowser, &dom_window);
1488     if(NS_SUCCEEDED(nsres)) {
1489         nsIDOMEventTarget *target;
1490         nsres = nsIDOMWindow_QueryInterface(dom_window, &IID_nsIDOMEventTarget, (void**)&target);
1491         nsIDOMWindow_Release(dom_window);
1492         if(NS_SUCCEEDED(nsres)) {
1493             nsAString keypress_str;
1494             static const PRUnichar wsz_keypress[] = {'k','e','y','p','r','e','s','s',0};
1495             nsAString_Init(&keypress_str, wsz_keypress);
1496             nsres = nsIDOMEventTarget_AddEventListener(target, &keypress_str, NSEVENTLIST(ret), TRUE);
1497             nsAString_Finish(&keypress_str);
1498             nsIDOMEventTarget_Release(target);
1499             if(NS_FAILED(nsres))
1500                 ERR("AddEventTarget failed: %08x\n", nsres);
1501         }else {
1502             ERR("Could not get nsIDOMEventTarget interface: %08x\n", nsres);
1503         }
1504     }else {
1505         ERR("GetContentDOMWindow failed: %08x\n", nsres);
1506     }
1507
1508
1509     return ret;
1510 }
1511
1512 void NSContainer_Release(NSContainer *This)
1513 {
1514     TRACE("(%p)\n", This);
1515
1516     ShowWindow(This->hwnd, SW_HIDE);
1517     SetParent(This->hwnd, NULL);
1518
1519     nsIBaseWindow_SetVisibility(This->window, FALSE);
1520     nsIBaseWindow_Destroy(This->window);
1521
1522     nsIWebBrowser_SetContainerWindow(This->webbrowser, NULL);
1523
1524     nsIWebBrowser_Release(This->webbrowser);
1525     This->webbrowser = NULL;
1526
1527     nsIWebNavigation_Release(This->navigation);
1528     This->navigation = NULL;
1529
1530     nsIBaseWindow_Release(This->window);
1531     This->window = NULL;
1532
1533     nsIWebBrowserFocus_Release(This->focus);
1534     This->focus = NULL;
1535
1536     if(This->content_listener) {
1537         nsIURIContentListener_Release(This->content_listener);
1538         This->content_listener = NULL;
1539     }
1540
1541     if(This->hwnd) {
1542         DestroyWindow(This->hwnd);
1543         This->hwnd = NULL;
1544     }
1545
1546     nsIWebBrowserChrome_Release(NSWBCHROME(This));
1547 }