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