gdiplus: Implement GdipGetImageDecoders[Size].
[wine] / dlls / mshtml / nsembed.c
1 /*
2  * Copyright 2005-2007 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 WINE_DECLARE_DEBUG_CHANNEL(gecko);
38
39 #define NS_APPSTARTUPNOTIFIER_CONTRACTID "@mozilla.org/embedcomp/appstartup-notifier;1"
40 #define NS_WEBBROWSER_CONTRACTID "@mozilla.org/embedding/browser/nsWebBrowser;1"
41 #define NS_PROFILE_CONTRACTID "@mozilla.org/profile/manager;1"
42 #define NS_MEMORY_CONTRACTID "@mozilla.org/xpcom/memory-service;1"
43 #define NS_STRINGSTREAM_CONTRACTID "@mozilla.org/io/string-input-stream;1"
44 #define NS_COMMANDPARAMS_CONTRACTID "@mozilla.org/embedcomp/command-params;1"
45 #define NS_HTMLSERIALIZER_CONTRACTID "@mozilla.org/layout/contentserializer;1?mimetype=text/html"
46 #define NS_EDITORCONTROLLER_CONTRACTID "@mozilla.org/editor/editorcontroller;1"
47 #define NS_ARRAY_CONTRACTID "@mozilla.org/array;1"
48 #define NS_VARIANT_CONTRACTID "@mozilla.org/variant;1"
49 #define NS_PREFERENCES_CONTRACTID "@mozilla.org/preferences;1"
50
51 #define APPSTARTUP_TOPIC "app-startup"
52
53 #define PR_UINT32_MAX 0xffffffff
54
55 struct nsCStringContainer {
56     void *v;
57     void *d1;
58     PRUint32 d2;
59     void *d3;
60 };
61
62 static nsresult (*NS_InitXPCOM2)(nsIServiceManager**,void*,void*);
63 static nsresult (*NS_ShutdownXPCOM)(nsIServiceManager*);
64 static nsresult (*NS_GetComponentRegistrar)(nsIComponentRegistrar**);
65 static nsresult (*NS_StringContainerInit)(nsStringContainer*);
66 static nsresult (*NS_CStringContainerInit)(nsCStringContainer*);
67 static nsresult (*NS_StringContainerFinish)(nsStringContainer*);
68 static nsresult (*NS_CStringContainerFinish)(nsCStringContainer*);
69 static nsresult (*NS_StringSetData)(nsAString*,const PRUnichar*,PRUint32);
70 static nsresult (*NS_CStringSetData)(nsACString*,const char*,PRUint32);
71 static nsresult (*NS_NewLocalFile)(const nsAString*,PRBool,nsIFile**);
72 static PRUint32 (*NS_StringGetData)(const nsAString*,const PRUnichar **,PRBool*);
73 static PRUint32 (*NS_CStringGetData)(const nsACString*,const char**,PRBool*);
74
75 static HINSTANCE hXPCOM = NULL;
76
77 static nsIServiceManager *pServMgr = NULL;
78 static nsIComponentManager *pCompMgr = NULL;
79 static nsIMemory *nsmem = NULL;
80
81 static const WCHAR wszNsContainer[] = {'N','s','C','o','n','t','a','i','n','e','r',0};
82
83 static ATOM nscontainer_class;
84
85 #define WM_RESETFOCUS_HACK WM_USER+600
86
87 static LRESULT WINAPI nsembed_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
88 {
89     NSContainer *This;
90     nsresult nsres;
91
92     static const WCHAR wszTHIS[] = {'T','H','I','S',0};
93
94     if(msg == WM_CREATE) {
95         This = *(NSContainer**)lParam;
96         SetPropW(hwnd, wszTHIS, This);
97     }else {
98         This = GetPropW(hwnd, wszTHIS);
99     }
100
101     switch(msg) {
102     case WM_SIZE:
103         TRACE("(%p)->(WM_SIZE)\n", This);
104
105         nsres = nsIBaseWindow_SetSize(This->window,
106                 LOWORD(lParam), HIWORD(lParam), TRUE);
107         if(NS_FAILED(nsres))
108             WARN("SetSize failed: %08x\n", nsres);
109         break;
110
111     case WM_RESETFOCUS_HACK:
112         /*
113          * FIXME
114          * Gecko grabs focus in edit mode and some apps don't like it.
115          * We should somehow prevent grabbing focus.
116          */
117
118         TRACE("WM_RESETFOCUS_HACK\n");
119
120         if(This->reset_focus) {
121             SetFocus(This->reset_focus);
122             This->reset_focus = NULL;
123             if(This->doc)
124                 This->doc->focus = FALSE;
125         }
126     }
127
128     return DefWindowProcW(hwnd, msg, wParam, lParam);
129 }
130
131
132 static void register_nscontainer_class(void)
133 {
134     static WNDCLASSEXW wndclass = {
135         sizeof(WNDCLASSEXW),
136         CS_DBLCLKS,
137         nsembed_proc,
138         0, 0, NULL, NULL, NULL, NULL, NULL,
139         wszNsContainer,
140         NULL,
141     };
142     wndclass.hInstance = hInst;
143     nscontainer_class = RegisterClassExW(&wndclass);
144 }
145
146 static void set_environment(LPCWSTR gre_path)
147 {
148     WCHAR path_env[MAX_PATH], buf[20];
149     int len, debug_level = 0;
150
151     static const WCHAR pathW[] = {'P','A','T','H',0};
152     static const WCHAR warnW[] = {'w','a','r','n',0};
153     static const WCHAR xpcom_debug_breakW[] =
154         {'X','P','C','O','M','_','D','E','B','U','G','_','B','R','E','A','K',0};
155     static const WCHAR nspr_log_modulesW[] =
156         {'N','S','P','R','_','L','O','G','_','M','O','D','U','L','E','S',0};
157     static const WCHAR debug_formatW[] = {'a','l','l',':','%','d',0};
158
159     /* We have to modify PATH as XPCOM loads other DLLs from this directory. */
160     GetEnvironmentVariableW(pathW, path_env, sizeof(path_env)/sizeof(WCHAR));
161     len = strlenW(path_env);
162     path_env[len++] = ';';
163     strcpyW(path_env+len, gre_path);
164     SetEnvironmentVariableW(pathW, path_env);
165
166     SetEnvironmentVariableW(xpcom_debug_breakW, warnW);
167
168     if(TRACE_ON(gecko))
169         debug_level = 5;
170     else if(WARN_ON(gecko))
171         debug_level = 3;
172     else if(ERR_ON(gecko))
173         debug_level = 2;
174
175     sprintfW(buf, debug_formatW, debug_level);
176     SetEnvironmentVariableW(nspr_log_modulesW, buf);
177 }
178
179 static BOOL load_xpcom(const PRUnichar *gre_path)
180 {
181     static const WCHAR strXPCOM[] = {'x','p','c','o','m','.','d','l','l',0};
182
183     TRACE("(%s)\n", debugstr_w(gre_path));
184
185     set_environment(gre_path);
186
187     hXPCOM = LoadLibraryW(strXPCOM);
188     if(!hXPCOM) {
189         WARN("Could not load XPCOM: %d\n", GetLastError());
190         return FALSE;
191     }
192
193 #define NS_DLSYM(func) \
194     func = (void *)GetProcAddress(hXPCOM, #func); \
195     if(!func) \
196         ERR("Could not GetProcAddress(" #func ") failed\n")
197
198     NS_DLSYM(NS_InitXPCOM2);
199     NS_DLSYM(NS_ShutdownXPCOM);
200     NS_DLSYM(NS_GetComponentRegistrar);
201     NS_DLSYM(NS_StringContainerInit);
202     NS_DLSYM(NS_CStringContainerInit);
203     NS_DLSYM(NS_StringContainerFinish);
204     NS_DLSYM(NS_CStringContainerFinish);
205     NS_DLSYM(NS_StringSetData);
206     NS_DLSYM(NS_CStringSetData);
207     NS_DLSYM(NS_NewLocalFile);
208     NS_DLSYM(NS_StringGetData);
209     NS_DLSYM(NS_CStringGetData);
210
211 #undef NS_DLSYM
212
213     return TRUE;
214 }
215
216 static BOOL check_version(LPCWSTR gre_path, const char *version_string)
217 {
218     WCHAR file_name[MAX_PATH];
219     char version[128];
220     DWORD read=0;
221     HANDLE hfile;
222
223     static const WCHAR wszVersion[] = {'\\','V','E','R','S','I','O','N',0};
224
225     strcpyW(file_name, gre_path);
226     strcatW(file_name, wszVersion);
227
228     hfile = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL,
229                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
230     if(hfile == INVALID_HANDLE_VALUE) {
231         ERR("Could not open VERSION file\n");
232         return FALSE;
233     }
234
235     ReadFile(hfile, version, sizeof(version), &read, NULL);
236     version[read] = 0;
237     CloseHandle(hfile);
238
239     TRACE("%s\n", debugstr_a(version));
240
241     if(strcmp(version, version_string)) {
242         ERR("Unexpected version %s, expected %s\n", debugstr_a(version),
243             debugstr_a(version_string));
244         return FALSE;
245     }
246
247     return TRUE;
248 }
249
250 static BOOL load_wine_gecko_v(PRUnichar *gre_path, HKEY mshtml_key,
251         const char *version, const char *version_string)
252 {
253     DWORD res, type, size = MAX_PATH;
254     HKEY hkey = mshtml_key;
255
256     static const WCHAR wszGeckoPath[] =
257         {'G','e','c','k','o','P','a','t','h',0};
258
259     if(version) {
260         /* @@ Wine registry key: HKCU\Software\Wine\MSHTML\<version> */
261         res = RegOpenKeyA(mshtml_key, version, &hkey);
262         if(res != ERROR_SUCCESS)
263             return FALSE;
264     }
265
266     res = RegQueryValueExW(hkey, wszGeckoPath, NULL, &type, (LPBYTE)gre_path, &size);
267     if(hkey != mshtml_key)
268         RegCloseKey(hkey);
269     if(res != ERROR_SUCCESS || type != REG_SZ)
270         return FALSE;
271
272     if(!check_version(gre_path, version_string))
273         return FALSE;
274
275     return load_xpcom(gre_path);
276 }
277
278 static BOOL load_wine_gecko(PRUnichar *gre_path)
279 {
280     HKEY hkey;
281     DWORD res;
282     BOOL ret;
283
284     static const WCHAR wszMshtmlKey[] = {
285         'S','o','f','t','w','a','r','e','\\','W','i','n','e',
286         '\\','M','S','H','T','M','L',0};
287
288     /* @@ Wine registry key: HKCU\Software\Wine\MSHTML */
289     res = RegOpenKeyW(HKEY_CURRENT_USER, wszMshtmlKey, &hkey);
290     if(res != ERROR_SUCCESS)
291         return FALSE;
292
293     ret = load_wine_gecko_v(gre_path, hkey, GECKO_VERSION, GECKO_VERSION_STRING);
294
295     RegCloseKey(hkey);
296     return ret;
297 }
298
299 static void set_lang(nsIPrefBranch *pref)
300 {
301     char langs[100];
302     DWORD res, size, type;
303     HKEY hkey;
304     nsresult nsres;
305
306     static const WCHAR international_keyW[] =
307         {'S','o','f','t','w','a','r','e',
308          '\\','M','i','c','r','o','s','o','f','t',
309          '\\','I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r',
310          '\\','I','n','t','e','r','n','a','t','i','o','n','a','l',0};
311
312     res = RegOpenKeyW(HKEY_CURRENT_USER, international_keyW, &hkey);
313     if(res != ERROR_SUCCESS)
314         return;
315
316     size = sizeof(langs);
317     res = RegQueryValueExA(hkey, "AcceptLanguage", 0, &type, (LPBYTE)langs, &size);
318     RegCloseKey(hkey);
319     if(res != ERROR_SUCCESS || type != REG_SZ)
320         return;
321
322     TRACE("Setting lang %s\n", debugstr_a(langs));
323
324     nsres = nsIPrefBranch_SetCharPref(pref, "intl.accept_languages", langs);
325     if(NS_FAILED(nsres))
326         ERR("SetCharPref failed: %08x\n", nsres);
327 }
328
329 static void set_proxy(nsIPrefBranch *pref)
330 {
331     char proxy[512];
332     char * proxy_port;
333     int proxy_port_num;
334     DWORD enabled = 0, res, size, type;
335     HKEY hkey;
336     nsresult nsres;
337
338     static const WCHAR proxy_keyW[] =
339         {'S','o','f','t','w','a','r','e',
340          '\\','M','i','c','r','o','s','o','f','t',
341          '\\','W','i','n','d','o','w','s',
342          '\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n',
343          '\\','I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s',0};
344
345     res = RegOpenKeyW(HKEY_CURRENT_USER, proxy_keyW, &hkey);
346     if(res != ERROR_SUCCESS)
347         return;
348
349     size = sizeof(enabled);
350     res = RegQueryValueExA(hkey, "ProxyEnable", 0, &type, (LPBYTE)&enabled, &size);
351     if(res != ERROR_SUCCESS || type != REG_DWORD || enabled == 0)
352     {
353         RegCloseKey(hkey);
354         return;
355     }
356
357     size = sizeof(proxy);
358     res = RegQueryValueExA(hkey, "ProxyServer", 0, &type, (LPBYTE)proxy, &size);
359     RegCloseKey(hkey);
360     if(res != ERROR_SUCCESS || type != REG_SZ)
361         return;
362
363     proxy_port = strchr(proxy, ':');
364     if (!proxy_port)
365         return;
366
367     *proxy_port = 0;
368     proxy_port_num = atoi(proxy_port + 1);
369     TRACE("Setting proxy to %s, port %d\n", debugstr_a(proxy), proxy_port_num);
370
371     nsres = nsIPrefBranch_SetIntPref(pref, "network.proxy.type", 1);
372     if(NS_FAILED(nsres))
373         ERR("SetIntPref network.proxy.type failed: %08x\n", nsres);
374     nsres = nsIPrefBranch_SetCharPref(pref, "network.proxy.http", proxy);
375     if(NS_FAILED(nsres))
376         ERR("SetCharPref network.proxy.http failed: %08x\n", nsres);
377     nsres = nsIPrefBranch_SetIntPref(pref, "network.proxy.http_port", proxy_port_num);
378     if(NS_FAILED(nsres))
379         ERR("SetIntPref network.proxy.http_port failed: %08x\n", nsres);
380     nsres = nsIPrefBranch_SetCharPref(pref, "network.proxy.ssl", proxy);
381     if(NS_FAILED(nsres))
382         ERR("SetCharPref network.proxy.ssl failed: %08x\n", nsres);
383     nsres = nsIPrefBranch_SetIntPref(pref, "network.proxy.ssl_port", proxy_port_num);
384     if(NS_FAILED(nsres))
385         ERR("SetIntPref network.proxy.ssl_port failed: %08x\n", nsres);
386 }
387
388 static void set_bool_pref(nsIPrefBranch *pref, const char *pref_name, BOOL val)
389 {
390     nsresult nsres;
391
392     nsres = nsIPrefBranch_SetBoolPref(pref, pref_name, val);
393     if(NS_FAILED(nsres))
394         ERR("Could not set pref %s\n", debugstr_a(pref_name));
395 }
396
397 static void set_int_pref(nsIPrefBranch *pref, const char *pref_name, int val)
398 {
399     nsresult nsres;
400
401     nsres = nsIPrefBranch_SetIntPref(pref, pref_name, val);
402     if(NS_FAILED(nsres))
403         ERR("Could not set pref %s\n", debugstr_a(pref_name));
404 }
405
406 static void set_preferences(void)
407 {
408     nsIPrefBranch *pref;
409     nsresult nsres;
410
411     nsres = nsIServiceManager_GetServiceByContractID(pServMgr, NS_PREFERENCES_CONTRACTID,
412             &IID_nsIPrefBranch, (void**)&pref);
413     if(NS_FAILED(nsres)) {
414         ERR("Could not get preference service: %08x\n", nsres);
415         return;
416     }
417
418     set_lang(pref);
419     set_proxy(pref);
420     set_bool_pref(pref, "security.warn_entering_secure", FALSE);
421     set_bool_pref(pref, "security.warn_submit_insecure", FALSE);
422     set_int_pref(pref, "layout.spellcheckDefault", 0);
423
424     nsIPrefBranch_Release(pref);
425 }
426
427 static BOOL init_xpcom(const PRUnichar *gre_path)
428 {
429     nsresult nsres;
430     nsIObserver *pStartNotif;
431     nsIComponentRegistrar *registrar = NULL;
432     nsAString path;
433     nsIFile *gre_dir;
434
435     nsAString_Init(&path, gre_path);
436     nsres = NS_NewLocalFile(&path, FALSE, &gre_dir);
437     nsAString_Finish(&path);
438     if(NS_FAILED(nsres)) {
439         ERR("NS_NewLocalFile failed: %08x\n", nsres);
440         FreeLibrary(hXPCOM);
441         return FALSE;
442     }
443
444     nsres = NS_InitXPCOM2(&pServMgr, gre_dir, NULL);
445     if(NS_FAILED(nsres)) {
446         ERR("NS_InitXPCOM2 failed: %08x\n", nsres);
447         FreeLibrary(hXPCOM);
448         return FALSE;
449     }
450
451     nsres = nsIServiceManager_QueryInterface(pServMgr, &IID_nsIComponentManager, (void**)&pCompMgr);
452     if(NS_FAILED(nsres))
453         ERR("Could not get nsIComponentManager: %08x\n", nsres);
454
455     nsres = NS_GetComponentRegistrar(&registrar);
456     if(NS_SUCCEEDED(nsres)) {
457         nsres = nsIComponentRegistrar_AutoRegister(registrar, NULL);
458         if(NS_FAILED(nsres))
459             ERR("AutoRegister(NULL) failed: %08x\n", nsres);
460
461         init_nsio(pCompMgr, registrar);
462     }else {
463         ERR("NS_GetComponentRegistrar failed: %08x\n", nsres);
464     }
465
466     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_APPSTARTUPNOTIFIER_CONTRACTID,
467             NULL, &IID_nsIObserver, (void**)&pStartNotif);
468     if(NS_SUCCEEDED(nsres)) {
469         nsres = nsIObserver_Observe(pStartNotif, NULL, APPSTARTUP_TOPIC, NULL);
470         if(NS_FAILED(nsres))
471             ERR("Observe failed: %08x\n", nsres);
472
473         nsIObserver_Release(pStartNotif);
474     }else {
475         ERR("could not get appstartup-notifier: %08x\n", nsres);
476     }
477
478     set_preferences();
479
480     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_MEMORY_CONTRACTID,
481             NULL, &IID_nsIMemory, (void**)&nsmem);
482     if(NS_FAILED(nsres))
483         ERR("Could not get nsIMemory: %08x\n", nsres);
484
485     if(registrar) {
486         register_nsservice(registrar, pServMgr);
487         nsIComponentRegistrar_Release(registrar);
488     }
489
490     return TRUE;
491 }
492
493 static CRITICAL_SECTION cs_load_gecko;
494 static CRITICAL_SECTION_DEBUG cs_load_gecko_dbg =
495 {
496     0, 0, &cs_load_gecko,
497     { &cs_load_gecko_dbg.ProcessLocksList, &cs_load_gecko_dbg.ProcessLocksList },
498       0, 0, { (DWORD_PTR)(__FILE__ ": load_gecko") }
499 };
500 static CRITICAL_SECTION cs_load_gecko = { &cs_load_gecko_dbg, -1, 0, 0, 0, 0 };
501
502 BOOL load_gecko(BOOL silent)
503 {
504     PRUnichar gre_path[MAX_PATH];
505     BOOL ret = FALSE;
506
507     static DWORD loading_thread;
508
509     TRACE("()\n");
510
511     /* load_gecko may be called recursively */
512     if(loading_thread == GetCurrentThreadId())
513         return pCompMgr != NULL;
514
515     EnterCriticalSection(&cs_load_gecko);
516
517     if(!loading_thread) {
518         loading_thread = GetCurrentThreadId();
519
520         if(load_wine_gecko(gre_path)
521            || (install_wine_gecko(silent) && load_wine_gecko(gre_path)))
522             ret = init_xpcom(gre_path);
523         else
524            MESSAGE("Could not load wine-gecko. HTML rendering will be disabled.\n");
525     }else {
526         ret = pCompMgr != NULL;
527     }
528
529     LeaveCriticalSection(&cs_load_gecko);
530
531     return ret;
532 }
533
534 void *nsalloc(size_t size)
535 {
536     return nsIMemory_Alloc(nsmem, size);
537 }
538
539 void nsfree(void *mem)
540 {
541     nsIMemory_Free(nsmem, mem);
542 }
543
544 void nsACString_Init(nsACString *str, const char *data)
545 {
546     NS_CStringContainerInit(str);
547     if(data)
548         nsACString_SetData(str, data);
549 }
550
551 void nsACString_SetData(nsACString *str, const char *data)
552 {
553     NS_CStringSetData(str, data, PR_UINT32_MAX);
554 }
555
556 PRUint32 nsACString_GetData(const nsACString *str, const char **data)
557 {
558     return NS_CStringGetData(str, data, NULL);
559 }
560
561 void nsACString_Finish(nsACString *str)
562 {
563     NS_CStringContainerFinish(str);
564 }
565
566 void nsAString_Init(nsAString *str, const PRUnichar *data)
567 {
568     NS_StringContainerInit(str);
569     if(data)
570         nsAString_SetData(str, data);
571 }
572
573 void nsAString_SetData(nsAString *str, const PRUnichar *data)
574 {
575     NS_StringSetData(str, data, PR_UINT32_MAX);
576 }
577
578 PRUint32 nsAString_GetData(const nsAString *str, const PRUnichar **data)
579 {
580     return NS_StringGetData(str, data, NULL);
581 }
582
583 void nsAString_Finish(nsAString *str)
584 {
585     NS_StringContainerFinish(str);
586 }
587
588 nsIInputStream *create_nsstream(const char *data, PRInt32 data_len)
589 {
590     nsIStringInputStream *ret;
591     nsresult nsres;
592
593     if(!pCompMgr)
594         return NULL;
595
596     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
597             NS_STRINGSTREAM_CONTRACTID, NULL, &IID_nsIStringInputStream,
598             (void**)&ret);
599     if(NS_FAILED(nsres)) {
600         ERR("Could not get nsIStringInputStream\n");
601         return NULL;
602     }
603
604     nsres = nsIStringInputStream_SetData(ret, data, data_len);
605     if(NS_FAILED(nsres)) {
606         ERR("AdoptData failed: %08x\n", nsres);
607         nsIStringInputStream_Release(ret);
608         return NULL;
609     }
610
611     return (nsIInputStream*)ret;
612 }
613
614 nsICommandParams *create_nscommand_params(void)
615 {
616     nsICommandParams *ret = NULL;
617     nsresult nsres;
618
619     if(!pCompMgr)
620         return NULL;
621
622     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
623             NS_COMMANDPARAMS_CONTRACTID, NULL, &IID_nsICommandParams,
624             (void**)&ret);
625     if(NS_FAILED(nsres))
626         ERR("Could not get nsICommandParams\n");
627
628     return ret;
629 }
630
631 nsresult get_nsinterface(nsISupports *iface, REFIID riid, void **ppv)
632 {
633     nsIInterfaceRequestor *iface_req;
634     nsresult nsres;
635
636     nsres = nsISupports_QueryInterface(iface, &IID_nsIInterfaceRequestor, (void**)&iface_req);
637     if(NS_FAILED(nsres))
638         return nsres;
639
640     nsres = nsIInterfaceRequestor_GetInterface(iface_req, riid, ppv);
641     nsIInterfaceRequestor_Release(iface_req);
642
643     return nsres;
644 }
645
646 static HRESULT nsnode_to_nsstring_rec(nsIContentSerializer *serializer, nsIDOMNode *nsnode, nsAString *str)
647 {
648     nsIDOMNodeList *node_list = NULL;
649     PRBool has_children = FALSE;
650     PRUint16 type;
651     nsresult nsres;
652
653     nsIDOMNode_HasChildNodes(nsnode, &has_children);
654
655     nsres = nsIDOMNode_GetNodeType(nsnode, &type);
656     if(NS_FAILED(nsres)) {
657         ERR("GetType failed: %08x\n", nsres);
658         return E_FAIL;
659     }
660
661     switch(type) {
662     case ELEMENT_NODE: {
663         nsIDOMElement *nselem;
664         nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMElement, (void**)&nselem);
665         nsIContentSerializer_AppendElementStart(serializer, nselem, nselem, str);
666         nsIDOMElement_Release(nselem);
667         break;
668     }
669     case TEXT_NODE: {
670         nsIDOMText *nstext;
671         nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMText, (void**)&nstext);
672         nsIContentSerializer_AppendText(serializer, nstext, 0, -1, str);
673         nsIDOMText_Release(nstext);
674         break;
675     }
676     case COMMENT_NODE: {
677         nsIDOMComment *nscomment;
678         nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMComment, (void**)&nscomment);
679         nsres = nsIContentSerializer_AppendComment(serializer, nscomment, 0, -1, str);
680         break;
681     }
682     case DOCUMENT_NODE: {
683         nsIDOMDocument *nsdoc;
684         nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMDocument, (void**)&nsdoc);
685         nsIContentSerializer_AppendDocumentStart(serializer, nsdoc, str);
686         nsIDOMDocument_Release(nsdoc);
687         break;
688     }
689     case DOCUMENT_TYPE_NODE:
690         WARN("Ignoring DOCUMENT_TYPE_NODE\n");
691         break;
692     case DOCUMENT_FRAGMENT_NODE:
693         break;
694     default:
695         FIXME("Unhandled type %u\n", type);
696     }
697
698     if(has_children) {
699         PRUint32 child_cnt, i;
700         nsIDOMNode *child_node;
701
702         nsIDOMNode_GetChildNodes(nsnode, &node_list);
703         nsIDOMNodeList_GetLength(node_list, &child_cnt);
704
705         for(i=0; i<child_cnt; i++) {
706             nsres = nsIDOMNodeList_Item(node_list, i, &child_node);
707             if(NS_SUCCEEDED(nsres)) {
708                 nsnode_to_nsstring_rec(serializer, child_node, str);
709                 nsIDOMNode_Release(child_node);
710             }else {
711                 ERR("Item failed: %08x\n", nsres);
712             }
713         }
714
715         nsIDOMNodeList_Release(node_list);
716     }
717
718     if(type == ELEMENT_NODE) {
719         nsIDOMElement *nselem;
720         nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMElement, (void**)&nselem);
721         nsIContentSerializer_AppendElementEnd(serializer, nselem, str);
722         nsIDOMElement_Release(nselem);
723     }
724
725     return S_OK;
726 }
727
728 HRESULT nsnode_to_nsstring(nsIDOMNode *nsnode, nsAString *str)
729 {
730     nsIContentSerializer *serializer;
731     nsresult nsres;
732     HRESULT hres;
733
734     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
735             NS_HTMLSERIALIZER_CONTRACTID, NULL, &IID_nsIContentSerializer,
736             (void**)&serializer);
737     if(NS_FAILED(nsres)) {
738         ERR("Could not get nsIContentSerializer: %08x\n", nsres);
739         return E_FAIL;
740     }
741
742     nsres = nsIContentSerializer_Init(serializer, 0, 100, NULL, FALSE, FALSE /* FIXME */);
743     if(NS_FAILED(nsres))
744         ERR("Init failed: %08x\n", nsres);
745
746     hres = nsnode_to_nsstring_rec(serializer, nsnode, str);
747     if(SUCCEEDED(hres)) {
748         nsres = nsIContentSerializer_Flush(serializer, str);
749         if(NS_FAILED(nsres))
750             ERR("Flush failed: %08x\n", nsres);
751     }
752
753     nsIContentSerializer_Release(serializer);
754     return hres;
755 }
756
757 void get_editor_controller(NSContainer *This)
758 {
759     nsIEditingSession *editing_session = NULL;
760     nsIControllerContext *ctrlctx;
761     nsresult nsres;
762
763     if(This->editor) {
764         nsIEditor_Release(This->editor);
765         This->editor = NULL;
766     }
767
768     if(This->editor_controller) {
769         nsIController_Release(This->editor_controller);
770         This->editor_controller = NULL;
771     }
772
773     nsres = get_nsinterface((nsISupports*)This->webbrowser, &IID_nsIEditingSession,
774             (void**)&editing_session);
775     if(NS_FAILED(nsres)) {
776         ERR("Could not get nsIEditingSession: %08x\n", nsres);
777         return;
778     }
779
780     nsres = nsIEditingSession_GetEditorForWindow(editing_session,
781             This->doc->window->nswindow, &This->editor);
782     nsIEditingSession_Release(editing_session);
783     if(NS_FAILED(nsres)) {
784         ERR("Could not get editor: %08x\n", nsres);
785         return;
786     }
787
788     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
789             NS_EDITORCONTROLLER_CONTRACTID, NULL, &IID_nsIControllerContext, (void**)&ctrlctx);
790     if(NS_SUCCEEDED(nsres)) {
791         nsres = nsIControllerContext_SetCommandContext(ctrlctx, (nsISupports *)This->editor);
792         if(NS_FAILED(nsres))
793             ERR("SetCommandContext failed: %08x\n", nsres);
794         nsres = nsIControllerContext_QueryInterface(ctrlctx, &IID_nsIController,
795                 (void**)&This->editor_controller);
796         nsIControllerContext_Release(ctrlctx);
797         if(NS_FAILED(nsres))
798             ERR("Could not get nsIController interface: %08x\n", nsres);
799     }else {
800         ERR("Could not create edit controller: %08x\n", nsres);
801     }
802 }
803
804 void set_ns_editmode(NSContainer *This)
805 {
806     nsIEditingSession *editing_session = NULL;
807     nsIURIContentListener *listener = NULL;
808     nsIDOMWindow *dom_window = NULL;
809     nsresult nsres;
810
811     nsres = get_nsinterface((nsISupports*)This->webbrowser, &IID_nsIEditingSession,
812             (void**)&editing_session);
813     if(NS_FAILED(nsres)) {
814         ERR("Could not get nsIEditingSession: %08x\n", nsres);
815         return;
816     }
817
818     nsres = nsIWebBrowser_GetContentDOMWindow(This->webbrowser, &dom_window);
819     if(NS_FAILED(nsres)) {
820         ERR("Could not get content DOM window: %08x\n", nsres);
821         nsIEditingSession_Release(editing_session);
822         return;
823     }
824
825     nsres = nsIEditingSession_MakeWindowEditable(editing_session, dom_window,
826             NULL, FALSE, TRUE, TRUE);
827     nsIEditingSession_Release(editing_session);
828     nsIDOMWindow_Release(dom_window);
829     if(NS_FAILED(nsres)) {
830         ERR("MakeWindowEditable failed: %08x\n", nsres);
831         return;
832     }
833
834     /* MakeWindowEditable changes WebBrowser's parent URI content listener.
835      * It seams to be a bug in Gecko. To workaround it we set our content
836      * listener again and Gecko's one as its parent.
837      */
838     nsIWebBrowser_GetParentURIContentListener(This->webbrowser, &listener);
839     nsIURIContentListener_SetParentContentListener(NSURICL(This), listener);
840     nsIURIContentListener_Release(listener);
841     nsIWebBrowser_SetParentURIContentListener(This->webbrowser, NSURICL(This));
842 }
843
844 void update_nsdocument(HTMLDocument *doc)
845 {
846     nsIDOMHTMLDocument *nsdoc;
847     nsIDOMDocument *nsdomdoc;
848     nsresult nsres;
849
850     if(!doc->nscontainer || !doc->nscontainer->navigation)
851         return;
852
853     nsres = nsIWebNavigation_GetDocument(doc->nscontainer->navigation, &nsdomdoc);
854     if(NS_FAILED(nsres) || !nsdomdoc) {
855         ERR("GetDocument failed: %08x\n", nsres);
856         return;
857     }
858
859     nsres = nsIDOMDocument_QueryInterface(nsdomdoc, &IID_nsIDOMHTMLDocument, (void**)&nsdoc);
860     nsIDOMDocument_Release(nsdomdoc);
861     if(NS_FAILED(nsres)) {
862         ERR("Could not get nsIDOMHTMLDocument iface: %08x\n", nsres);
863         return;
864     }
865
866     if(nsdoc == doc->nsdoc) {
867         nsIDOMHTMLDocument_Release(nsdoc);
868         return;
869     }
870
871     if(doc->nsdoc) {
872         remove_mutation_observer(doc->nscontainer, doc->nsdoc);
873         nsIDOMHTMLDocument_Release(doc->nsdoc);
874     }
875
876     doc->nsdoc = nsdoc;
877
878     if(nsdoc)
879         set_mutation_observer(doc->nscontainer, nsdoc);
880 }
881
882 void close_gecko(void)
883 {
884     TRACE("()\n");
885
886     release_nsio();
887
888     if(pCompMgr)
889         nsIComponentManager_Release(pCompMgr);
890
891     if(pServMgr)
892         nsIServiceManager_Release(pServMgr);
893
894     if(nsmem)
895         nsIMemory_Release(nsmem);
896
897     /* Gecko doesn't really support being unloaded */
898     /* if (hXPCOM) FreeLibrary(hXPCOM); */
899 }
900
901 /**********************************************************
902  *      nsIWebBrowserChrome interface
903  */
904
905 #define NSWBCHROME_THIS(iface) DEFINE_THIS(NSContainer, WebBrowserChrome, iface)
906
907 static nsresult NSAPI nsWebBrowserChrome_QueryInterface(nsIWebBrowserChrome *iface,
908         nsIIDRef riid, nsQIResult result)
909 {
910     NSContainer *This = NSWBCHROME_THIS(iface);
911
912     *result = NULL;
913     if(IsEqualGUID(&IID_nsISupports, riid)) {
914         TRACE("(%p)->(IID_nsISupports, %p)\n", This, result);
915         *result = NSWBCHROME(This);
916     }else if(IsEqualGUID(&IID_nsIWebBrowserChrome, riid)) {
917         TRACE("(%p)->(IID_nsIWebBrowserChrome, %p)\n", This, result);
918         *result = NSWBCHROME(This);
919     }else if(IsEqualGUID(&IID_nsIContextMenuListener, riid)) {
920         TRACE("(%p)->(IID_nsIContextMenuListener, %p)\n", This, result);
921         *result = NSCML(This);
922     }else if(IsEqualGUID(&IID_nsIURIContentListener, riid)) {
923         TRACE("(%p)->(IID_nsIURIContentListener %p)\n", This, result);
924         *result = NSURICL(This);
925     }else if(IsEqualGUID(&IID_nsIEmbeddingSiteWindow, riid)) {
926         TRACE("(%p)->(IID_nsIEmbeddingSiteWindow %p)\n", This, result);
927         *result = NSEMBWNDS(This);
928     }else if(IsEqualGUID(&IID_nsITooltipListener, riid)) {
929         TRACE("(%p)->(IID_nsITooltipListener %p)\n", This, result);
930         *result = NSTOOLTIP(This);
931     }else if(IsEqualGUID(&IID_nsIInterfaceRequestor, riid)) {
932         TRACE("(%p)->(IID_nsIInterfaceRequestor %p)\n", This, result);
933         *result = NSIFACEREQ(This);
934     }else if(IsEqualGUID(&IID_nsIWeakReference, riid)) {
935         TRACE("(%p)->(IID_nsIWeakReference %p)\n", This, result);
936         *result = NSWEAKREF(This);
937     }else if(IsEqualGUID(&IID_nsISupportsWeakReference, riid)) {
938         TRACE("(%p)->(IID_nsISupportsWeakReference %p)\n", This, result);
939         *result = NSSUPWEAKREF(This);
940     }
941
942     if(*result) {
943         nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
944         return NS_OK;
945     }
946
947     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
948     return NS_NOINTERFACE;
949 }
950
951 static nsrefcnt NSAPI nsWebBrowserChrome_AddRef(nsIWebBrowserChrome *iface)
952 {
953     NSContainer *This = NSWBCHROME_THIS(iface);
954     LONG ref = InterlockedIncrement(&This->ref);
955
956     TRACE("(%p) ref=%d\n", This, ref);
957
958     return ref;
959 }
960
961 static nsrefcnt NSAPI nsWebBrowserChrome_Release(nsIWebBrowserChrome *iface)
962 {
963     NSContainer *This = NSWBCHROME_THIS(iface);
964     LONG ref = InterlockedDecrement(&This->ref);
965
966     TRACE("(%p) ref=%d\n", This, ref);
967
968     if(!ref) {
969         heap_free(This->event_vector);
970         if(This->parent)
971             nsIWebBrowserChrome_Release(NSWBCHROME(This->parent));
972         heap_free(This);
973     }
974
975     return ref;
976 }
977
978 static nsresult NSAPI nsWebBrowserChrome_SetStatus(nsIWebBrowserChrome *iface,
979         PRUint32 statusType, const PRUnichar *status)
980 {
981     NSContainer *This = NSWBCHROME_THIS(iface);
982
983     TRACE("(%p)->(%d %s)\n", This, statusType, debugstr_w(status));
984
985     /* FIXME: This hack should be removed when we'll load all pages by URLMoniker */
986     if(This->doc)
987         update_nsdocument(This->doc);
988
989     return NS_OK;
990 }
991
992 static nsresult NSAPI nsWebBrowserChrome_GetWebBrowser(nsIWebBrowserChrome *iface,
993         nsIWebBrowser **aWebBrowser)
994 {
995     NSContainer *This = NSWBCHROME_THIS(iface);
996
997     TRACE("(%p)->(%p)\n", This, aWebBrowser);
998
999     if(!aWebBrowser)
1000         return NS_ERROR_INVALID_ARG;
1001
1002     if(This->webbrowser)
1003         nsIWebBrowser_AddRef(This->webbrowser);
1004     *aWebBrowser = This->webbrowser;
1005     return S_OK;
1006 }
1007
1008 static nsresult NSAPI nsWebBrowserChrome_SetWebBrowser(nsIWebBrowserChrome *iface,
1009         nsIWebBrowser *aWebBrowser)
1010 {
1011     NSContainer *This = NSWBCHROME_THIS(iface);
1012
1013     TRACE("(%p)->(%p)\n", This, aWebBrowser);
1014
1015     if(aWebBrowser != This->webbrowser)
1016         ERR("Wrong nsWebBrowser!\n");
1017
1018     return NS_OK;
1019 }
1020
1021 static nsresult NSAPI nsWebBrowserChrome_GetChromeFlags(nsIWebBrowserChrome *iface,
1022         PRUint32 *aChromeFlags)
1023 {
1024     NSContainer *This = NSWBCHROME_THIS(iface);
1025     WARN("(%p)->(%p)\n", This, aChromeFlags);
1026     return NS_ERROR_NOT_IMPLEMENTED;
1027 }
1028
1029 static nsresult NSAPI nsWebBrowserChrome_SetChromeFlags(nsIWebBrowserChrome *iface,
1030         PRUint32 aChromeFlags)
1031 {
1032     NSContainer *This = NSWBCHROME_THIS(iface);
1033     WARN("(%p)->(%08x)\n", This, aChromeFlags);
1034     return NS_ERROR_NOT_IMPLEMENTED;
1035 }
1036
1037 static nsresult NSAPI nsWebBrowserChrome_DestroyBrowserWindow(nsIWebBrowserChrome *iface)
1038 {
1039     NSContainer *This = NSWBCHROME_THIS(iface);
1040     TRACE("(%p)\n", This);
1041     return NS_ERROR_NOT_IMPLEMENTED;
1042 }
1043
1044 static nsresult NSAPI nsWebBrowserChrome_SizeBrowserTo(nsIWebBrowserChrome *iface,
1045         PRInt32 aCX, PRInt32 aCY)
1046 {
1047     NSContainer *This = NSWBCHROME_THIS(iface);
1048     WARN("(%p)->(%d %d)\n", This, aCX, aCY);
1049     return NS_ERROR_NOT_IMPLEMENTED;
1050 }
1051
1052 static nsresult NSAPI nsWebBrowserChrome_ShowAsModal(nsIWebBrowserChrome *iface)
1053 {
1054     NSContainer *This = NSWBCHROME_THIS(iface);
1055     WARN("(%p)\n", This);
1056     return NS_ERROR_NOT_IMPLEMENTED;
1057 }
1058
1059 static nsresult NSAPI nsWebBrowserChrome_IsWindowModal(nsIWebBrowserChrome *iface, PRBool *_retval)
1060 {
1061     NSContainer *This = NSWBCHROME_THIS(iface);
1062     WARN("(%p)->(%p)\n", This, _retval);
1063     return NS_ERROR_NOT_IMPLEMENTED;
1064 }
1065
1066 static nsresult NSAPI nsWebBrowserChrome_ExitModalEventLoop(nsIWebBrowserChrome *iface,
1067         nsresult aStatus)
1068 {
1069     NSContainer *This = NSWBCHROME_THIS(iface);
1070     WARN("(%p)->(%08x)\n", This, aStatus);
1071     return NS_ERROR_NOT_IMPLEMENTED;
1072 }
1073
1074 #undef NSWBCHROME_THIS
1075
1076 static const nsIWebBrowserChromeVtbl nsWebBrowserChromeVtbl = {
1077     nsWebBrowserChrome_QueryInterface,
1078     nsWebBrowserChrome_AddRef,
1079     nsWebBrowserChrome_Release,
1080     nsWebBrowserChrome_SetStatus,
1081     nsWebBrowserChrome_GetWebBrowser,
1082     nsWebBrowserChrome_SetWebBrowser,
1083     nsWebBrowserChrome_GetChromeFlags,
1084     nsWebBrowserChrome_SetChromeFlags,
1085     nsWebBrowserChrome_DestroyBrowserWindow,
1086     nsWebBrowserChrome_SizeBrowserTo,
1087     nsWebBrowserChrome_ShowAsModal,
1088     nsWebBrowserChrome_IsWindowModal,
1089     nsWebBrowserChrome_ExitModalEventLoop
1090 };
1091
1092 /**********************************************************
1093  *      nsIContextMenuListener interface
1094  */
1095
1096 #define NSCML_THIS(iface) DEFINE_THIS(NSContainer, ContextMenuListener, iface)
1097
1098 static nsresult NSAPI nsContextMenuListener_QueryInterface(nsIContextMenuListener *iface,
1099         nsIIDRef riid, nsQIResult result)
1100 {
1101     NSContainer *This = NSCML_THIS(iface);
1102     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1103 }
1104
1105 static nsrefcnt NSAPI nsContextMenuListener_AddRef(nsIContextMenuListener *iface)
1106 {
1107     NSContainer *This = NSCML_THIS(iface);
1108     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1109 }
1110
1111 static nsrefcnt NSAPI nsContextMenuListener_Release(nsIContextMenuListener *iface)
1112 {
1113     NSContainer *This = NSCML_THIS(iface);
1114     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1115 }
1116
1117 static nsresult NSAPI nsContextMenuListener_OnShowContextMenu(nsIContextMenuListener *iface,
1118         PRUint32 aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode)
1119 {
1120     NSContainer *This = NSCML_THIS(iface);
1121     nsIDOMMouseEvent *event;
1122     POINT pt;
1123     DWORD dwID = CONTEXT_MENU_DEFAULT;
1124     nsresult nsres;
1125
1126     TRACE("(%p)->(%08x %p %p)\n", This, aContextFlags, aEvent, aNode);
1127
1128     nsres = nsIDOMEvent_QueryInterface(aEvent, &IID_nsIDOMMouseEvent, (void**)&event);
1129     if(NS_FAILED(nsres)) {
1130         ERR("Could not get nsIDOMMouseEvent interface: %08x\n", nsres);
1131         return nsres;
1132     }
1133
1134     nsIDOMMouseEvent_GetScreenX(event, &pt.x);
1135     nsIDOMMouseEvent_GetScreenY(event, &pt.y);
1136     nsIDOMMouseEvent_Release(event);
1137
1138     switch(aContextFlags) {
1139     case CONTEXT_NONE:
1140     case CONTEXT_DOCUMENT:
1141     case CONTEXT_TEXT:
1142         dwID = CONTEXT_MENU_DEFAULT;
1143         break;
1144     case CONTEXT_IMAGE:
1145     case CONTEXT_IMAGE|CONTEXT_LINK:
1146         dwID = CONTEXT_MENU_IMAGE;
1147         break;
1148     case CONTEXT_LINK:
1149         dwID = CONTEXT_MENU_ANCHOR;
1150         break;
1151     case CONTEXT_INPUT:
1152         dwID = CONTEXT_MENU_CONTROL;
1153         break;
1154     default:
1155         FIXME("aContextFlags=%08x\n", aContextFlags);
1156     };
1157
1158     show_context_menu(This->doc, dwID, &pt, (IDispatch*)HTMLDOMNODE(get_node(This->doc, aNode, TRUE)));
1159
1160     return NS_OK;
1161 }
1162
1163 #undef NSCML_THIS
1164
1165 static const nsIContextMenuListenerVtbl nsContextMenuListenerVtbl = {
1166     nsContextMenuListener_QueryInterface,
1167     nsContextMenuListener_AddRef,
1168     nsContextMenuListener_Release,
1169     nsContextMenuListener_OnShowContextMenu
1170 };
1171
1172 /**********************************************************
1173  *      nsIURIContentListener interface
1174  */
1175
1176 #define NSURICL_THIS(iface) DEFINE_THIS(NSContainer, URIContentListener, iface)
1177
1178 static nsresult NSAPI nsURIContentListener_QueryInterface(nsIURIContentListener *iface,
1179         nsIIDRef riid, nsQIResult result)
1180 {
1181     NSContainer *This = NSURICL_THIS(iface);
1182     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1183 }
1184
1185 static nsrefcnt NSAPI nsURIContentListener_AddRef(nsIURIContentListener *iface)
1186 {
1187     NSContainer *This = NSURICL_THIS(iface);
1188     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1189 }
1190
1191 static nsrefcnt NSAPI nsURIContentListener_Release(nsIURIContentListener *iface)
1192 {
1193     NSContainer *This = NSURICL_THIS(iface);
1194     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1195 }
1196
1197 static BOOL translate_url(HTMLDocument *doc, nsIWineURI *nsuri)
1198 {
1199     OLECHAR *new_url = NULL, *url;
1200     BOOL ret = FALSE;
1201     LPCWSTR wine_url;
1202     HRESULT hres;
1203
1204     if(!doc->hostui)
1205         return FALSE;
1206
1207     nsIWineURI_GetWineURL(nsuri, &wine_url);
1208
1209     url = heap_strdupW(wine_url);
1210     hres = IDocHostUIHandler_TranslateUrl(doc->hostui, 0, url, &new_url);
1211     heap_free(url);
1212     if(hres != S_OK || !new_url)
1213         return FALSE;
1214
1215     if(strcmpW(url, new_url)) {
1216         FIXME("TranslateUrl returned new URL %s -> %s\n", debugstr_w(url), debugstr_w(new_url));
1217         ret = TRUE;
1218     }
1219
1220     CoTaskMemFree(new_url);
1221     return ret;
1222 }
1223
1224 static nsresult NSAPI nsURIContentListener_OnStartURIOpen(nsIURIContentListener *iface,
1225                                                           nsIURI *aURI, PRBool *_retval)
1226 {
1227     NSContainer *This = NSURICL_THIS(iface);
1228     nsIWineURI *wine_uri;
1229     nsACString spec_str;
1230     const char *spec;
1231     nsresult nsres;
1232
1233     nsACString_Init(&spec_str, NULL);
1234     nsIURI_GetSpec(aURI, &spec_str);
1235     nsACString_GetData(&spec_str, &spec);
1236
1237     TRACE("(%p)->(%p(%s) %p)\n", This, aURI, debugstr_a(spec), _retval);
1238
1239     nsACString_Finish(&spec_str);
1240
1241     nsres = nsIURI_QueryInterface(aURI, &IID_nsIWineURI, (void**)&wine_uri);
1242     if(NS_FAILED(nsres)) {
1243         WARN("Could not get nsIWineURI interface: %08x\n", nsres);
1244         return NS_ERROR_NOT_IMPLEMENTED;
1245     }
1246
1247     nsIWineURI_SetNSContainer(wine_uri, This);
1248     nsIWineURI_SetIsDocumentURI(wine_uri, TRUE);
1249
1250     if(This->bscallback) {
1251         IMoniker *mon = get_channelbsc_mon(This->bscallback);
1252
1253         if(mon) {
1254             LPWSTR wine_url;
1255             HRESULT hres;
1256
1257             hres = IMoniker_GetDisplayName(mon, NULL, 0, &wine_url);
1258             if(SUCCEEDED(hres)) {
1259                 nsIWineURI_SetWineURL(wine_uri, wine_url);
1260                 CoTaskMemFree(wine_url);
1261             }else {
1262                 WARN("GetDisplayName failed: %08x\n", hres);
1263             }
1264
1265             IMoniker_Release(mon);
1266         }
1267
1268         *_retval = FALSE;
1269     }else if(This->doc) {
1270         *_retval = translate_url(This->doc, wine_uri);
1271     }
1272
1273     nsIWineURI_Release(wine_uri);
1274
1275     return !*_retval && This->content_listener
1276         ? nsIURIContentListener_OnStartURIOpen(This->content_listener, aURI, _retval)
1277         : NS_OK;
1278 }
1279
1280 static nsresult NSAPI nsURIContentListener_DoContent(nsIURIContentListener *iface,
1281         const char *aContentType, PRBool aIsContentPreferred, nsIRequest *aRequest,
1282         nsIStreamListener **aContentHandler, PRBool *_retval)
1283 {
1284     NSContainer *This = NSURICL_THIS(iface);
1285
1286     TRACE("(%p)->(%s %x %p %p %p)\n", This, debugstr_a(aContentType), aIsContentPreferred,
1287             aRequest, aContentHandler, _retval);
1288
1289     return This->content_listener
1290         ? nsIURIContentListener_DoContent(This->content_listener, aContentType,
1291                   aIsContentPreferred, aRequest, aContentHandler, _retval)
1292         : NS_ERROR_NOT_IMPLEMENTED;
1293 }
1294
1295 static nsresult NSAPI nsURIContentListener_IsPreferred(nsIURIContentListener *iface,
1296         const char *aContentType, char **aDesiredContentType, PRBool *_retval)
1297 {
1298     NSContainer *This = NSURICL_THIS(iface);
1299
1300     TRACE("(%p)->(%s %p %p)\n", This, debugstr_a(aContentType), aDesiredContentType, _retval);
1301
1302     /* FIXME: Should we do something here? */
1303     *_retval = TRUE; 
1304
1305     return This->content_listener
1306         ? nsIURIContentListener_IsPreferred(This->content_listener, aContentType,
1307                   aDesiredContentType, _retval)
1308         : NS_OK;
1309 }
1310
1311 static nsresult NSAPI nsURIContentListener_CanHandleContent(nsIURIContentListener *iface,
1312         const char *aContentType, PRBool aIsContentPreferred, char **aDesiredContentType,
1313         PRBool *_retval)
1314 {
1315     NSContainer *This = NSURICL_THIS(iface);
1316
1317     TRACE("(%p)->(%s %x %p %p)\n", This, debugstr_a(aContentType), aIsContentPreferred,
1318             aDesiredContentType, _retval);
1319
1320     return This->content_listener
1321         ? nsIURIContentListener_CanHandleContent(This->content_listener, aContentType,
1322                 aIsContentPreferred, aDesiredContentType, _retval)
1323         : NS_ERROR_NOT_IMPLEMENTED;
1324 }
1325
1326 static nsresult NSAPI nsURIContentListener_GetLoadCookie(nsIURIContentListener *iface,
1327         nsISupports **aLoadCookie)
1328 {
1329     NSContainer *This = NSURICL_THIS(iface);
1330
1331     WARN("(%p)->(%p)\n", This, aLoadCookie);
1332
1333     return This->content_listener
1334         ? nsIURIContentListener_GetLoadCookie(This->content_listener, aLoadCookie)
1335         : NS_ERROR_NOT_IMPLEMENTED;
1336 }
1337
1338 static nsresult NSAPI nsURIContentListener_SetLoadCookie(nsIURIContentListener *iface,
1339         nsISupports *aLoadCookie)
1340 {
1341     NSContainer *This = NSURICL_THIS(iface);
1342
1343     WARN("(%p)->(%p)\n", This, aLoadCookie);
1344
1345     return This->content_listener
1346         ? nsIURIContentListener_SetLoadCookie(This->content_listener, aLoadCookie)
1347         : NS_ERROR_NOT_IMPLEMENTED;
1348 }
1349
1350 static nsresult NSAPI nsURIContentListener_GetParentContentListener(nsIURIContentListener *iface,
1351         nsIURIContentListener **aParentContentListener)
1352 {
1353     NSContainer *This = NSURICL_THIS(iface);
1354
1355     TRACE("(%p)->(%p)\n", This, aParentContentListener);
1356
1357     if(This->content_listener)
1358         nsIURIContentListener_AddRef(This->content_listener);
1359
1360     *aParentContentListener = This->content_listener;
1361     return NS_OK;
1362 }
1363
1364 static nsresult NSAPI nsURIContentListener_SetParentContentListener(nsIURIContentListener *iface,
1365         nsIURIContentListener *aParentContentListener)
1366 {
1367     NSContainer *This = NSURICL_THIS(iface);
1368
1369     TRACE("(%p)->(%p)\n", This, aParentContentListener);
1370
1371     if(aParentContentListener == NSURICL(This))
1372         return NS_OK;
1373
1374     if(This->content_listener)
1375         nsIURIContentListener_Release(This->content_listener);
1376
1377     This->content_listener = aParentContentListener;
1378     if(This->content_listener)
1379         nsIURIContentListener_AddRef(This->content_listener);
1380
1381     return NS_OK;
1382 }
1383
1384 #undef NSURICL_THIS
1385
1386 static const nsIURIContentListenerVtbl nsURIContentListenerVtbl = {
1387     nsURIContentListener_QueryInterface,
1388     nsURIContentListener_AddRef,
1389     nsURIContentListener_Release,
1390     nsURIContentListener_OnStartURIOpen,
1391     nsURIContentListener_DoContent,
1392     nsURIContentListener_IsPreferred,
1393     nsURIContentListener_CanHandleContent,
1394     nsURIContentListener_GetLoadCookie,
1395     nsURIContentListener_SetLoadCookie,
1396     nsURIContentListener_GetParentContentListener,
1397     nsURIContentListener_SetParentContentListener
1398 };
1399
1400 /**********************************************************
1401  *      nsIEmbeddinSiteWindow interface
1402  */
1403
1404 #define NSEMBWNDS_THIS(iface) DEFINE_THIS(NSContainer, EmbeddingSiteWindow, iface)
1405
1406 static nsresult NSAPI nsEmbeddingSiteWindow_QueryInterface(nsIEmbeddingSiteWindow *iface,
1407         nsIIDRef riid, nsQIResult result)
1408 {
1409     NSContainer *This = NSEMBWNDS_THIS(iface);
1410     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1411 }
1412
1413 static nsrefcnt NSAPI nsEmbeddingSiteWindow_AddRef(nsIEmbeddingSiteWindow *iface)
1414 {
1415     NSContainer *This = NSEMBWNDS_THIS(iface);
1416     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1417 }
1418
1419 static nsrefcnt NSAPI nsEmbeddingSiteWindow_Release(nsIEmbeddingSiteWindow *iface)
1420 {
1421     NSContainer *This = NSEMBWNDS_THIS(iface);
1422     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1423 }
1424
1425 static nsresult NSAPI nsEmbeddingSiteWindow_SetDimensions(nsIEmbeddingSiteWindow *iface,
1426         PRUint32 flags, PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy)
1427 {
1428     NSContainer *This = NSEMBWNDS_THIS(iface);
1429     WARN("(%p)->(%08x %d %d %d %d)\n", This, flags, x, y, cx, cy);
1430     return NS_ERROR_NOT_IMPLEMENTED;
1431 }
1432
1433 static nsresult NSAPI nsEmbeddingSiteWindow_GetDimensions(nsIEmbeddingSiteWindow *iface,
1434         PRUint32 flags, PRInt32 *x, PRInt32 *y, PRInt32 *cx, PRInt32 *cy)
1435 {
1436     NSContainer *This = NSEMBWNDS_THIS(iface);
1437     WARN("(%p)->(%08x %p %p %p %p)\n", This, flags, x, y, cx, cy);
1438     return NS_ERROR_NOT_IMPLEMENTED;
1439 }
1440
1441 static nsresult NSAPI nsEmbeddingSiteWindow_SetFocus(nsIEmbeddingSiteWindow *iface)
1442 {
1443     NSContainer *This = NSEMBWNDS_THIS(iface);
1444
1445     TRACE("(%p)\n", This);
1446
1447     if(This->reset_focus)
1448         PostMessageW(This->hwnd, WM_RESETFOCUS_HACK, 0, 0);
1449
1450     return nsIBaseWindow_SetFocus(This->window);
1451 }
1452
1453 static nsresult NSAPI nsEmbeddingSiteWindow_GetVisibility(nsIEmbeddingSiteWindow *iface,
1454         PRBool *aVisibility)
1455 {
1456     NSContainer *This = NSEMBWNDS_THIS(iface);
1457
1458     TRACE("(%p)->(%p)\n", This, aVisibility);
1459
1460     *aVisibility = This->doc && This->doc->hwnd && IsWindowVisible(This->doc->hwnd);
1461     return NS_OK;
1462 }
1463
1464 static nsresult NSAPI nsEmbeddingSiteWindow_SetVisibility(nsIEmbeddingSiteWindow *iface,
1465         PRBool aVisibility)
1466 {
1467     NSContainer *This = NSEMBWNDS_THIS(iface);
1468
1469     TRACE("(%p)->(%x)\n", This, aVisibility);
1470
1471     return NS_OK;
1472 }
1473
1474 static nsresult NSAPI nsEmbeddingSiteWindow_GetTitle(nsIEmbeddingSiteWindow *iface,
1475         PRUnichar **aTitle)
1476 {
1477     NSContainer *This = NSEMBWNDS_THIS(iface);
1478     WARN("(%p)->(%p)\n", This, aTitle);
1479     return NS_ERROR_NOT_IMPLEMENTED;
1480 }
1481
1482 static nsresult NSAPI nsEmbeddingSiteWindow_SetTitle(nsIEmbeddingSiteWindow *iface,
1483         const PRUnichar *aTitle)
1484 {
1485     NSContainer *This = NSEMBWNDS_THIS(iface);
1486     WARN("(%p)->(%s)\n", This, debugstr_w(aTitle));
1487     return NS_ERROR_NOT_IMPLEMENTED;
1488 }
1489
1490 static nsresult NSAPI nsEmbeddingSiteWindow_GetSiteWindow(nsIEmbeddingSiteWindow *iface,
1491         void **aSiteWindow)
1492 {
1493     NSContainer *This = NSEMBWNDS_THIS(iface);
1494
1495     TRACE("(%p)->(%p)\n", This, aSiteWindow);
1496
1497     *aSiteWindow = This->hwnd;
1498     return NS_OK;
1499 }
1500
1501 static const nsIEmbeddingSiteWindowVtbl nsEmbeddingSiteWindowVtbl = {
1502     nsEmbeddingSiteWindow_QueryInterface,
1503     nsEmbeddingSiteWindow_AddRef,
1504     nsEmbeddingSiteWindow_Release,
1505     nsEmbeddingSiteWindow_SetDimensions,
1506     nsEmbeddingSiteWindow_GetDimensions,
1507     nsEmbeddingSiteWindow_SetFocus,
1508     nsEmbeddingSiteWindow_GetVisibility,
1509     nsEmbeddingSiteWindow_SetVisibility,
1510     nsEmbeddingSiteWindow_GetTitle,
1511     nsEmbeddingSiteWindow_SetTitle,
1512     nsEmbeddingSiteWindow_GetSiteWindow
1513 };
1514
1515 #define NSTOOLTIP_THIS(iface) DEFINE_THIS(NSContainer, TooltipListener, iface)
1516
1517 static nsresult NSAPI nsTooltipListener_QueryInterface(nsITooltipListener *iface, nsIIDRef riid,
1518                                                        nsQIResult result)
1519 {
1520     NSContainer *This = NSTOOLTIP_THIS(iface);
1521     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1522 }
1523
1524 static nsrefcnt NSAPI nsTooltipListener_AddRef(nsITooltipListener *iface)
1525 {
1526     NSContainer *This = NSTOOLTIP_THIS(iface);
1527     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1528 }
1529
1530 static nsrefcnt NSAPI nsTooltipListener_Release(nsITooltipListener *iface)
1531 {
1532     NSContainer *This = NSTOOLTIP_THIS(iface);
1533     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1534 }
1535
1536 static nsresult NSAPI nsTooltipListener_OnShowTooltip(nsITooltipListener *iface,
1537         PRInt32 aXCoord, PRInt32 aYCoord, const PRUnichar *aTipText)
1538 {
1539     NSContainer *This = NSTOOLTIP_THIS(iface);
1540
1541     if (This->doc)
1542         show_tooltip(This->doc, aXCoord, aYCoord, aTipText);
1543
1544     return NS_OK;
1545 }
1546
1547 static nsresult NSAPI nsTooltipListener_OnHideTooltip(nsITooltipListener *iface)
1548 {
1549     NSContainer *This = NSTOOLTIP_THIS(iface);
1550
1551     if (This->doc)
1552         hide_tooltip(This->doc);
1553
1554     return NS_OK;
1555 }
1556
1557 #undef NSTOOLTIM_THIS
1558
1559 static const nsITooltipListenerVtbl nsTooltipListenerVtbl = {
1560     nsTooltipListener_QueryInterface,
1561     nsTooltipListener_AddRef,
1562     nsTooltipListener_Release,
1563     nsTooltipListener_OnShowTooltip,
1564     nsTooltipListener_OnHideTooltip
1565 };
1566
1567 #define NSIFACEREQ_THIS(iface) DEFINE_THIS(NSContainer, InterfaceRequestor, iface)
1568
1569 static nsresult NSAPI nsInterfaceRequestor_QueryInterface(nsIInterfaceRequestor *iface,
1570                                                           nsIIDRef riid, nsQIResult result)
1571 {
1572     NSContainer *This = NSIFACEREQ_THIS(iface);
1573     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1574 }
1575
1576 static nsrefcnt NSAPI nsInterfaceRequestor_AddRef(nsIInterfaceRequestor *iface)
1577 {
1578     NSContainer *This = NSIFACEREQ_THIS(iface);
1579     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1580 }
1581
1582 static nsrefcnt NSAPI nsInterfaceRequestor_Release(nsIInterfaceRequestor *iface)
1583 {
1584     NSContainer *This = NSIFACEREQ_THIS(iface);
1585     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1586 }
1587
1588 static nsresult NSAPI nsInterfaceRequestor_GetInterface(nsIInterfaceRequestor *iface,
1589                                                         nsIIDRef riid, nsQIResult result)
1590 {
1591     NSContainer *This = NSIFACEREQ_THIS(iface);
1592
1593     if(IsEqualGUID(&IID_nsIDOMWindow, riid)) {
1594         TRACE("(%p)->(IID_nsIDOMWindow %p)\n", This, result);
1595         return nsIWebBrowser_GetContentDOMWindow(This->webbrowser, (nsIDOMWindow**)result);
1596     }
1597
1598     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1599 }
1600
1601 #undef NSIFACEREQ_THIS
1602
1603 static const nsIInterfaceRequestorVtbl nsInterfaceRequestorVtbl = {
1604     nsInterfaceRequestor_QueryInterface,
1605     nsInterfaceRequestor_AddRef,
1606     nsInterfaceRequestor_Release,
1607     nsInterfaceRequestor_GetInterface
1608 };
1609
1610 #define NSWEAKREF_THIS(iface) DEFINE_THIS(NSContainer, WeakReference, iface)
1611
1612 static nsresult NSAPI nsWeakReference_QueryInterface(nsIWeakReference *iface,
1613         nsIIDRef riid, nsQIResult result)
1614 {
1615     NSContainer *This = NSWEAKREF_THIS(iface);
1616     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1617 }
1618
1619 static nsrefcnt NSAPI nsWeakReference_AddRef(nsIWeakReference *iface)
1620 {
1621     NSContainer *This = NSWEAKREF_THIS(iface);
1622     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1623 }
1624
1625 static nsrefcnt NSAPI nsWeakReference_Release(nsIWeakReference *iface)
1626 {
1627     NSContainer *This = NSWEAKREF_THIS(iface);
1628     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1629 }
1630
1631 static nsresult NSAPI nsWeakReference_QueryReferent(nsIWeakReference *iface,
1632         const nsIID *riid, void **result)
1633 {
1634     NSContainer *This = NSWEAKREF_THIS(iface);
1635     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1636 }
1637
1638 #undef NSWEAKREF_THIS
1639
1640 static const nsIWeakReferenceVtbl nsWeakReferenceVtbl = {
1641     nsWeakReference_QueryInterface,
1642     nsWeakReference_AddRef,
1643     nsWeakReference_Release,
1644     nsWeakReference_QueryReferent
1645 };
1646
1647 #define NSSUPWEAKREF_THIS(iface) DEFINE_THIS(NSContainer, SupportsWeakReference, iface)
1648
1649 static nsresult NSAPI nsSupportsWeakReference_QueryInterface(nsISupportsWeakReference *iface,
1650         nsIIDRef riid, nsQIResult result)
1651 {
1652     NSContainer *This = NSSUPWEAKREF_THIS(iface);
1653     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1654 }
1655
1656 static nsrefcnt NSAPI nsSupportsWeakReference_AddRef(nsISupportsWeakReference *iface)
1657 {
1658     NSContainer *This = NSSUPWEAKREF_THIS(iface);
1659     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1660 }
1661
1662 static nsrefcnt NSAPI nsSupportsWeakReference_Release(nsISupportsWeakReference *iface)
1663 {
1664     NSContainer *This = NSSUPWEAKREF_THIS(iface);
1665     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1666 }
1667
1668 static nsresult NSAPI nsSupportsWeakReference_GetWeakReference(nsISupportsWeakReference *iface,
1669         nsIWeakReference **_retval)
1670 {
1671     NSContainer *This = NSSUPWEAKREF_THIS(iface);
1672
1673     TRACE("(%p)->(%p)\n", This, _retval);
1674
1675     nsIWeakReference_AddRef(NSWEAKREF(This));
1676     *_retval = NSWEAKREF(This);
1677     return NS_OK;
1678 }
1679
1680 #undef NSWEAKREF_THIS
1681
1682 static const nsISupportsWeakReferenceVtbl nsSupportsWeakReferenceVtbl = {
1683     nsSupportsWeakReference_QueryInterface,
1684     nsSupportsWeakReference_AddRef,
1685     nsSupportsWeakReference_Release,
1686     nsSupportsWeakReference_GetWeakReference
1687 };
1688
1689
1690 NSContainer *NSContainer_Create(HTMLDocument *doc, NSContainer *parent)
1691 {
1692     nsIWebBrowserSetup *wbsetup;
1693     nsIScrollable *scrollable;
1694     NSContainer *ret;
1695     nsresult nsres;
1696
1697     if(!load_gecko(FALSE))
1698         return NULL;
1699
1700     ret = heap_alloc_zero(sizeof(NSContainer));
1701
1702     ret->lpWebBrowserChromeVtbl      = &nsWebBrowserChromeVtbl;
1703     ret->lpContextMenuListenerVtbl   = &nsContextMenuListenerVtbl;
1704     ret->lpURIContentListenerVtbl    = &nsURIContentListenerVtbl;
1705     ret->lpEmbeddingSiteWindowVtbl   = &nsEmbeddingSiteWindowVtbl;
1706     ret->lpTooltipListenerVtbl       = &nsTooltipListenerVtbl;
1707     ret->lpInterfaceRequestorVtbl    = &nsInterfaceRequestorVtbl;
1708     ret->lpWeakReferenceVtbl         = &nsWeakReferenceVtbl;
1709     ret->lpSupportsWeakReferenceVtbl = &nsSupportsWeakReferenceVtbl;
1710
1711     ret->doc = doc;
1712     ret->ref = 1;
1713     init_mutation(ret);
1714
1715     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_WEBBROWSER_CONTRACTID,
1716             NULL, &IID_nsIWebBrowser, (void**)&ret->webbrowser);
1717     if(NS_FAILED(nsres)) {
1718         ERR("Creating WebBrowser failed: %08x\n", nsres);
1719         heap_free(ret);
1720         return NULL;
1721     }
1722
1723     if(parent)
1724         nsIWebBrowserChrome_AddRef(NSWBCHROME(parent));
1725     ret->parent = parent;
1726
1727     nsres = nsIWebBrowser_SetContainerWindow(ret->webbrowser, NSWBCHROME(ret));
1728     if(NS_FAILED(nsres))
1729         ERR("SetContainerWindow failed: %08x\n", nsres);
1730
1731     nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIBaseWindow,
1732             (void**)&ret->window);
1733     if(NS_FAILED(nsres))
1734         ERR("Could not get nsIBaseWindow interface: %08x\n", nsres);
1735
1736     nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIWebBrowserSetup,
1737                                          (void**)&wbsetup);
1738     if(NS_SUCCEEDED(nsres)) {
1739         nsres = nsIWebBrowserSetup_SetProperty(wbsetup, SETUP_IS_CHROME_WRAPPER, FALSE);
1740         nsIWebBrowserSetup_Release(wbsetup);
1741         if(NS_FAILED(nsres))
1742             ERR("SetProperty(SETUP_IS_CHROME_WRAPPER) failed: %08x\n", nsres);
1743     }else {
1744         ERR("Could not get nsIWebBrowserSetup interface\n");
1745     }
1746
1747     nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIWebNavigation,
1748             (void**)&ret->navigation);
1749     if(NS_FAILED(nsres))
1750         ERR("Could not get nsIWebNavigation interface: %08x\n", nsres);
1751
1752     nsres = nsIWebBrowserFocus_QueryInterface(ret->webbrowser, &IID_nsIWebBrowserFocus,
1753             (void**)&ret->focus);
1754     if(NS_FAILED(nsres))
1755         ERR("Could not get nsIWebBrowserFocus interface: %08x\n", nsres);
1756
1757     if(!nscontainer_class)
1758         register_nscontainer_class();
1759
1760     ret->hwnd = CreateWindowExW(0, wszNsContainer, NULL,
1761             WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, 100, 100,
1762             GetDesktopWindow(), NULL, hInst, ret);
1763
1764     nsres = nsIBaseWindow_InitWindow(ret->window, ret->hwnd, NULL, 0, 0, 100, 100);
1765     if(NS_SUCCEEDED(nsres)) {
1766         nsres = nsIBaseWindow_Create(ret->window);
1767         if(NS_FAILED(nsres))
1768             WARN("Creating window failed: %08x\n", nsres);
1769
1770         nsIBaseWindow_SetVisibility(ret->window, FALSE);
1771         nsIBaseWindow_SetEnabled(ret->window, FALSE);
1772     }else {
1773         ERR("InitWindow failed: %08x\n", nsres);
1774     }
1775
1776     nsres = nsIWebBrowser_SetParentURIContentListener(ret->webbrowser, NSURICL(ret));
1777     if(NS_FAILED(nsres))
1778         ERR("SetParentURIContentListener failed: %08x\n", nsres);
1779
1780     init_nsevents(ret);
1781
1782     nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIScrollable, (void**)&scrollable);
1783     if(NS_SUCCEEDED(nsres)) {
1784         nsres = nsIScrollable_SetDefaultScrollbarPreferences(scrollable,
1785                 ScrollOrientation_Y, Scrollbar_Always);
1786         if(NS_FAILED(nsres))
1787             ERR("Could not set default Y scrollbar prefs: %08x\n", nsres);
1788
1789         nsres = nsIScrollable_SetDefaultScrollbarPreferences(scrollable,
1790                 ScrollOrientation_X, Scrollbar_Auto);
1791         if(NS_FAILED(nsres))
1792             ERR("Could not set default X scrollbar prefs: %08x\n", nsres);
1793
1794         nsIScrollable_Release(scrollable);
1795     }else {
1796         ERR("Could not get nsIScrollable: %08x\n", nsres);
1797     }
1798
1799     return ret;
1800 }
1801
1802 void NSContainer_Release(NSContainer *This)
1803 {
1804     TRACE("(%p)\n", This);
1805
1806     This->doc = NULL;
1807
1808     ShowWindow(This->hwnd, SW_HIDE);
1809     SetParent(This->hwnd, NULL);
1810
1811     nsIBaseWindow_SetVisibility(This->window, FALSE);
1812     nsIBaseWindow_Destroy(This->window);
1813
1814     nsIWebBrowser_SetContainerWindow(This->webbrowser, NULL);
1815
1816     nsIWebBrowser_Release(This->webbrowser);
1817     This->webbrowser = NULL;
1818
1819     nsIWebNavigation_Release(This->navigation);
1820     This->navigation = NULL;
1821
1822     nsIBaseWindow_Release(This->window);
1823     This->window = NULL;
1824
1825     nsIWebBrowserFocus_Release(This->focus);
1826     This->focus = NULL;
1827
1828     if(This->editor_controller) {
1829         nsIController_Release(This->editor_controller);
1830         This->editor_controller = NULL;
1831     }
1832
1833     if(This->editor) {
1834         nsIEditor_Release(This->editor);
1835         This->editor = NULL;
1836     }
1837
1838     if(This->content_listener) {
1839         nsIURIContentListener_Release(This->content_listener);
1840         This->content_listener = NULL;
1841     }
1842
1843     if(This->hwnd) {
1844         DestroyWindow(This->hwnd);
1845         This->hwnd = NULL;
1846     }
1847
1848     nsIWebBrowserChrome_Release(NSWBCHROME(This));
1849 }