xref: /reactos/dll/win32/mshtml/nsembed.c (revision c2c66aff)
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 "mshtml_private.h"
20 
21 #include <wincon.h>
22 #include <shlobj.h>
23 
24 WINE_DECLARE_DEBUG_CHANNEL(gecko);
25 
26 #define NS_APPSTARTUPNOTIFIER_CONTRACTID "@mozilla.org/embedcomp/appstartup-notifier;1"
27 #define NS_WEBBROWSER_CONTRACTID "@mozilla.org/embedding/browser/nsWebBrowser;1"
28 #define NS_COMMANDPARAMS_CONTRACTID "@mozilla.org/embedcomp/command-params;1"
29 #define NS_HTMLSERIALIZER_CONTRACTID "@mozilla.org/layout/contentserializer;1?mimetype=text/html"
30 #define NS_EDITORCONTROLLER_CONTRACTID "@mozilla.org/editor/editorcontroller;1"
31 #define NS_PREFERENCES_CONTRACTID "@mozilla.org/preferences;1"
32 #define NS_VARIANT_CONTRACTID "@mozilla.org/variant;1"
33 #define NS_CATEGORYMANAGER_CONTRACTID "@mozilla.org/categorymanager;1"
34 #define NS_XMLHTTPREQUEST_CONTRACTID "@mozilla.org/xmlextras/xmlhttprequest;1"
35 #define NS_SCRIPTSECURITYMANAGER_CONTRACTID "@mozilla.org/scriptsecuritymanager;1"
36 
37 #define PR_UINT32_MAX 0xffffffff
38 
39 #define NS_STRING_CONTAINER_INIT_DEPEND  0x0002
40 #define NS_CSTRING_CONTAINER_INIT_DEPEND 0x0002
41 
42 typedef UINT32 PRUint32;
43 
44 static nsresult (CDECL *NS_InitXPCOM2)(nsIServiceManager**,void*,void*);
45 static nsresult (CDECL *NS_ShutdownXPCOM)(nsIServiceManager*);
46 static nsresult (CDECL *NS_GetComponentRegistrar)(nsIComponentRegistrar**);
47 static nsresult (CDECL *NS_StringContainerInit2)(nsStringContainer*,const PRUnichar*,PRUint32,PRUint32);
48 static nsresult (CDECL *NS_CStringContainerInit2)(nsCStringContainer*,const char*,PRUint32,PRUint32);
49 static nsresult (CDECL *NS_StringContainerFinish)(nsStringContainer*);
50 static nsresult (CDECL *NS_CStringContainerFinish)(nsCStringContainer*);
51 static nsresult (CDECL *NS_StringSetData)(nsAString*,const PRUnichar*,PRUint32);
52 static nsresult (CDECL *NS_CStringSetData)(nsACString*,const char*,PRUint32);
53 static nsresult (CDECL *NS_NewLocalFile)(const nsAString*,cpp_bool,nsIFile**);
54 static PRUint32 (CDECL *NS_StringGetData)(const nsAString*,const PRUnichar **,cpp_bool*);
55 static PRUint32 (CDECL *NS_CStringGetData)(const nsACString*,const char**,cpp_bool*);
56 static void* (CDECL *NS_Alloc)(SIZE_T);
57 static void (CDECL *NS_Free)(void*);
58 
59 static HINSTANCE xul_handle = NULL;
60 
61 static nsIServiceManager *pServMgr = NULL;
62 static nsIComponentManager *pCompMgr = NULL;
63 static nsICategoryManager *cat_mgr;
64 static nsIFile *profile_directory, *plugin_directory;
65 
66 static const WCHAR wszNsContainer[] = {'N','s','C','o','n','t','a','i','n','e','r',0};
67 
68 static ATOM nscontainer_class;
69 static WCHAR gecko_path[MAX_PATH];
70 static unsigned gecko_path_len;
71 
create_nsfile(const PRUnichar * path,nsIFile ** ret)72 nsresult create_nsfile(const PRUnichar *path, nsIFile **ret)
73 {
74     nsAString str;
75     nsresult nsres;
76 
77     nsAString_InitDepend(&str, path);
78     nsres = NS_NewLocalFile(&str, FALSE, ret);
79     nsAString_Finish(&str);
80 
81     if(NS_FAILED(nsres))
82         WARN("NS_NewLocalFile failed: %08x\n", nsres);
83     return nsres;
84 }
85 
86 typedef struct {
87     nsISimpleEnumerator nsISimpleEnumerator_iface;
88     LONG ref;
89     nsISupports *value;
90 } nsSingletonEnumerator;
91 
impl_from_nsISimpleEnumerator(nsISimpleEnumerator * iface)92 static inline nsSingletonEnumerator *impl_from_nsISimpleEnumerator(nsISimpleEnumerator *iface)
93 {
94     return CONTAINING_RECORD(iface, nsSingletonEnumerator, nsISimpleEnumerator_iface);
95 }
96 
nsSingletonEnumerator_QueryInterface(nsISimpleEnumerator * iface,nsIIDRef riid,void ** ppv)97 static nsresult NSAPI nsSingletonEnumerator_QueryInterface(nsISimpleEnumerator *iface, nsIIDRef riid, void **ppv)
98 {
99     nsSingletonEnumerator *This = impl_from_nsISimpleEnumerator(iface);
100 
101     if(IsEqualGUID(&IID_nsISupports, riid)) {
102         TRACE("(%p)->(IID_nsISupports %p)\n", This, ppv);
103         *ppv = &This->nsISimpleEnumerator_iface;
104     }else if(IsEqualGUID(&IID_nsISimpleEnumerator, riid)) {
105         TRACE("(%p)->(IID_nsISimpleEnumerator %p)\n", This, ppv);
106         *ppv = &This->nsISimpleEnumerator_iface;
107     }else {
108         TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
109         *ppv = NULL;
110         return NS_NOINTERFACE;
111     }
112 
113     nsISupports_AddRef((nsISupports*)*ppv);
114     return NS_OK;
115 }
116 
nsSingletonEnumerator_AddRef(nsISimpleEnumerator * iface)117 static nsrefcnt NSAPI nsSingletonEnumerator_AddRef(nsISimpleEnumerator *iface)
118 {
119     nsSingletonEnumerator *This = impl_from_nsISimpleEnumerator(iface);
120     nsrefcnt ref = InterlockedIncrement(&This->ref);
121 
122     TRACE("(%p) ref=%d\n", This, ref);
123 
124     return ref;
125 }
126 
nsSingletonEnumerator_Release(nsISimpleEnumerator * iface)127 static nsrefcnt NSAPI nsSingletonEnumerator_Release(nsISimpleEnumerator *iface)
128 {
129     nsSingletonEnumerator *This = impl_from_nsISimpleEnumerator(iface);
130     nsrefcnt ref = InterlockedDecrement(&This->ref);
131 
132     TRACE("(%p) ref=%d\n", This, ref);
133 
134     if(!ref) {
135         if(This->value)
136             nsISupports_Release(This->value);
137         heap_free(This);
138     }
139 
140     return ref;
141 }
142 
nsSingletonEnumerator_HasMoreElements(nsISimpleEnumerator * iface,cpp_bool * _retval)143 static nsresult NSAPI nsSingletonEnumerator_HasMoreElements(nsISimpleEnumerator *iface, cpp_bool *_retval)
144 {
145     nsSingletonEnumerator *This = impl_from_nsISimpleEnumerator(iface);
146 
147     TRACE("(%p)->()\n", This);
148 
149     *_retval = This->value != NULL;
150     return NS_OK;
151 }
152 
nsSingletonEnumerator_GetNext(nsISimpleEnumerator * iface,nsISupports ** _retval)153 static nsresult NSAPI nsSingletonEnumerator_GetNext(nsISimpleEnumerator *iface, nsISupports **_retval)
154 {
155     nsSingletonEnumerator *This = impl_from_nsISimpleEnumerator(iface);
156 
157     TRACE("(%p)->()\n", This);
158 
159     if(!This->value)
160         return NS_ERROR_UNEXPECTED;
161 
162     *_retval = This->value;
163     This->value = NULL;
164     return NS_OK;
165 }
166 
167 static const nsISimpleEnumeratorVtbl nsSingletonEnumeratorVtbl = {
168     nsSingletonEnumerator_QueryInterface,
169     nsSingletonEnumerator_AddRef,
170     nsSingletonEnumerator_Release,
171     nsSingletonEnumerator_HasMoreElements,
172     nsSingletonEnumerator_GetNext
173 };
174 
create_singleton_enumerator(nsISupports * value)175 static nsISimpleEnumerator *create_singleton_enumerator(nsISupports *value)
176 {
177     nsSingletonEnumerator *ret;
178 
179     ret = heap_alloc(sizeof(*ret));
180     if(!ret)
181         return NULL;
182 
183     ret->nsISimpleEnumerator_iface.lpVtbl = &nsSingletonEnumeratorVtbl;
184     ret->ref = 1;
185 
186     if(value)
187         nsISupports_AddRef(value);
188     ret->value = value;
189     return &ret->nsISimpleEnumerator_iface;
190 }
191 
nsDirectoryServiceProvider2_QueryInterface(nsIDirectoryServiceProvider2 * iface,nsIIDRef riid,void ** result)192 static nsresult NSAPI nsDirectoryServiceProvider2_QueryInterface(nsIDirectoryServiceProvider2 *iface,
193         nsIIDRef riid, void **result)
194 {
195     if(IsEqualGUID(&IID_nsISupports, riid)) {
196         TRACE("(IID_nsISupports %p)\n", result);
197         *result = iface;
198     }else if(IsEqualGUID(&IID_nsIDirectoryServiceProvider, riid)) {
199         TRACE("(IID_nsIDirectoryServiceProvider %p)\n", result);
200         *result = iface;
201     }else if(IsEqualGUID(&IID_nsIDirectoryServiceProvider2, riid)) {
202         TRACE("(IID_nsIDirectoryServiceProvider2 %p)\n", result);
203         *result = iface;
204     }else {
205         WARN("(%s %p)\n", debugstr_guid(riid), result);
206         *result = NULL;
207         return NS_NOINTERFACE;
208     }
209 
210     nsISupports_AddRef((nsISupports*)*result);
211     return NS_OK;
212 }
213 
nsDirectoryServiceProvider2_AddRef(nsIDirectoryServiceProvider2 * iface)214 static nsrefcnt NSAPI nsDirectoryServiceProvider2_AddRef(nsIDirectoryServiceProvider2 *iface)
215 {
216     return 2;
217 }
218 
nsDirectoryServiceProvider2_Release(nsIDirectoryServiceProvider2 * iface)219 static nsrefcnt NSAPI nsDirectoryServiceProvider2_Release(nsIDirectoryServiceProvider2 *iface)
220 {
221     return 1;
222 }
223 
create_profile_directory(void)224 static nsresult create_profile_directory(void)
225 {
226     static const WCHAR wine_geckoW[] = {'\\','w','i','n','e','_','g','e','c','k','o',0};
227 
228     WCHAR path[MAX_PATH + sizeof(wine_geckoW)/sizeof(WCHAR)];
229     cpp_bool exists;
230     nsresult nsres;
231     HRESULT hres;
232 
233     hres = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path);
234     if(FAILED(hres)) {
235         ERR("SHGetFolderPath failed: %08x\n", hres);
236         return NS_ERROR_FAILURE;
237     }
238 
239     strcatW(path, wine_geckoW);
240     nsres = create_nsfile(path, &profile_directory);
241     if(NS_FAILED(nsres))
242         return nsres;
243 
244     nsres = nsIFile_Exists(profile_directory, &exists);
245     if(NS_FAILED(nsres)) {
246         ERR("Exists failed: %08x\n", nsres);
247         return nsres;
248     }
249 
250     if(!exists) {
251         nsres = nsIFile_Create(profile_directory, 1, 0700);
252         if(NS_FAILED(nsres))
253             ERR("Create failed: %08x\n", nsres);
254     }
255 
256     return nsres;
257 }
258 
nsDirectoryServiceProvider2_GetFile(nsIDirectoryServiceProvider2 * iface,const char * prop,cpp_bool * persistent,nsIFile ** _retval)259 static nsresult NSAPI nsDirectoryServiceProvider2_GetFile(nsIDirectoryServiceProvider2 *iface,
260         const char *prop, cpp_bool *persistent, nsIFile **_retval)
261 {
262     TRACE("(%s %p %p)\n", debugstr_a(prop), persistent, _retval);
263 
264     if(!strcmp(prop, "ProfD")) {
265         if(!profile_directory) {
266             nsresult nsres;
267 
268             nsres = create_profile_directory();
269             if(NS_FAILED(nsres))
270                 return nsres;
271         }
272 
273         assert(profile_directory != NULL);
274         return nsIFile_Clone(profile_directory, _retval);
275     }
276 
277     *_retval = NULL;
278     return NS_ERROR_FAILURE;
279 }
280 
nsDirectoryServiceProvider2_GetFiles(nsIDirectoryServiceProvider2 * iface,const char * prop,nsISimpleEnumerator ** _retval)281 static nsresult NSAPI nsDirectoryServiceProvider2_GetFiles(nsIDirectoryServiceProvider2 *iface,
282         const char *prop, nsISimpleEnumerator **_retval)
283 {
284     TRACE("(%s %p)\n", debugstr_a(prop), _retval);
285 
286     if(!strcmp(prop, "APluginsDL")) {
287         WCHAR plugin_path[MAX_PATH];
288         nsIFile *file;
289         int len;
290         nsresult nsres;
291 
292         if(!plugin_directory) {
293             static const WCHAR gecko_pluginW[] = {'\\','g','e','c','k','o','\\','p','l','u','g','i','n',0};
294 
295             len = GetSystemDirectoryW(plugin_path, (sizeof(plugin_path)-sizeof(gecko_pluginW))/sizeof(WCHAR)+1);
296             if(!len)
297                 return NS_ERROR_UNEXPECTED;
298 
299             strcpyW(plugin_path+len, gecko_pluginW);
300             nsres = create_nsfile(plugin_path, &plugin_directory);
301             if(NS_FAILED(nsres)) {
302                 *_retval = NULL;
303                 return nsres;
304             }
305         }
306 
307         nsres = nsIFile_Clone(plugin_directory, &file);
308         if(NS_FAILED(nsres))
309             return nsres;
310 
311         *_retval = create_singleton_enumerator((nsISupports*)file);
312         nsIFile_Release(file);
313         if(!*_retval)
314             return NS_ERROR_OUT_OF_MEMORY;
315 
316         return NS_OK;
317     }
318 
319     *_retval = NULL;
320     return NS_ERROR_FAILURE;
321 }
322 
323 static const nsIDirectoryServiceProvider2Vtbl nsDirectoryServiceProvider2Vtbl = {
324     nsDirectoryServiceProvider2_QueryInterface,
325     nsDirectoryServiceProvider2_AddRef,
326     nsDirectoryServiceProvider2_Release,
327     nsDirectoryServiceProvider2_GetFile,
328     nsDirectoryServiceProvider2_GetFiles
329 };
330 
331 static nsIDirectoryServiceProvider2 nsDirectoryServiceProvider2 =
332     { &nsDirectoryServiceProvider2Vtbl };
333 
nsembed_proc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)334 static LRESULT WINAPI nsembed_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
335 {
336     NSContainer *This;
337     nsresult nsres;
338 
339     static const WCHAR wszTHIS[] = {'T','H','I','S',0};
340 
341     if(msg == WM_CREATE) {
342         This = *(NSContainer**)lParam;
343         SetPropW(hwnd, wszTHIS, This);
344     }else {
345         This = GetPropW(hwnd, wszTHIS);
346     }
347 
348     switch(msg) {
349     case WM_SIZE:
350         TRACE("(%p)->(WM_SIZE)\n", This);
351 
352         nsres = nsIBaseWindow_SetSize(This->window,
353                 LOWORD(lParam), HIWORD(lParam), TRUE);
354         if(NS_FAILED(nsres))
355             WARN("SetSize failed: %08x\n", nsres);
356         break;
357 
358     case WM_PARENTNOTIFY:
359         TRACE("WM_PARENTNOTIFY %x\n", (unsigned)wParam);
360 
361         switch(wParam) {
362         case WM_LBUTTONDOWN:
363         case WM_RBUTTONDOWN:
364             nsIWebBrowserFocus_Activate(This->focus);
365         }
366     }
367 
368     return DefWindowProcW(hwnd, msg, wParam, lParam);
369 }
370 
371 
register_nscontainer_class(void)372 static void register_nscontainer_class(void)
373 {
374     static WNDCLASSEXW wndclass = {
375         sizeof(WNDCLASSEXW),
376         CS_DBLCLKS,
377         nsembed_proc,
378         0, 0, NULL, NULL, NULL, NULL, NULL,
379         wszNsContainer,
380         NULL,
381     };
382     wndclass.hInstance = hInst;
383     nscontainer_class = RegisterClassExW(&wndclass);
384 }
385 
386 #ifndef __REACTOS__
install_wine_gecko(void)387 static BOOL install_wine_gecko(void)
388 {
389     PROCESS_INFORMATION pi;
390     STARTUPINFOW si;
391     WCHAR app[MAX_PATH];
392     WCHAR *args;
393     LONG len;
394     BOOL ret;
395 
396     static const WCHAR controlW[] = {'\\','c','o','n','t','r','o','l','.','e','x','e',0};
397     static const WCHAR argsW[] =
398         {' ','a','p','p','w','i','z','.','c','p','l',' ','i','n','s','t','a','l','l','_','g','e','c','k','o',0};
399 
400     len = GetSystemDirectoryW(app, MAX_PATH-sizeof(controlW)/sizeof(WCHAR));
401     memcpy(app+len, controlW, sizeof(controlW));
402 
403     args = heap_alloc(len*sizeof(WCHAR) + sizeof(controlW) + sizeof(argsW));
404     if(!args)
405         return FALSE;
406 
407     memcpy(args, app, len*sizeof(WCHAR) + sizeof(controlW));
408     memcpy(args + len + sizeof(controlW)/sizeof(WCHAR)-1, argsW, sizeof(argsW));
409 
410     TRACE("starting %s\n", debugstr_w(args));
411 
412     memset(&si, 0, sizeof(si));
413     si.cb = sizeof(si);
414     ret = CreateProcessW(app, args, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
415     heap_free(args);
416     if (ret) {
417         CloseHandle(pi.hThread);
418         WaitForSingleObject(pi.hProcess, INFINITE);
419         CloseHandle(pi.hProcess);
420     }
421 
422     return ret;
423 }
424 #endif
425 
set_environment(LPCWSTR gre_path)426 static void set_environment(LPCWSTR gre_path)
427 {
428     size_t len, gre_path_len;
429     int debug_level = 0;
430     WCHAR *path, buf[20];
431     const WCHAR *ptr;
432 
433     static const WCHAR pathW[] = {'P','A','T','H',0};
434     static const WCHAR warnW[] = {'w','a','r','n',0};
435     static const WCHAR xpcom_debug_breakW[] =
436         {'X','P','C','O','M','_','D','E','B','U','G','_','B','R','E','A','K',0};
437     static const WCHAR nspr_log_modulesW[] =
438         {'N','S','P','R','_','L','O','G','_','M','O','D','U','L','E','S',0};
439     static const WCHAR debug_formatW[] = {'a','l','l',':','%','d',0};
440 
441     SetEnvironmentVariableW(xpcom_debug_breakW, warnW);
442 
443     if(TRACE_ON(gecko))
444         debug_level = 5;
445     else if(WARN_ON(gecko))
446         debug_level = 3;
447     else if(ERR_ON(gecko))
448         debug_level = 2;
449 
450     sprintfW(buf, debug_formatW, debug_level);
451     SetEnvironmentVariableW(nspr_log_modulesW, buf);
452 
453     len = GetEnvironmentVariableW(pathW, NULL, 0);
454     gre_path_len = strlenW(gre_path);
455     path = heap_alloc((len+gre_path_len+1)*sizeof(WCHAR));
456     if(!path)
457         return;
458     GetEnvironmentVariableW(pathW, path, len);
459 
460     /* We have to modify PATH as xul.dll loads other DLLs from this directory. */
461     if(!(ptr = strstrW(path, gre_path))
462        || (ptr > path && *(ptr-1) != ';')
463        || (ptr[gre_path_len] && ptr[gre_path_len] != ';')) {
464         if(len)
465             path[len-1] = ';';
466         strcpyW(path+len, gre_path);
467         SetEnvironmentVariableW(pathW, path);
468     }
469     heap_free(path);
470 }
471 
load_xul(const PRUnichar * gre_path)472 static BOOL load_xul(const PRUnichar *gre_path)
473 {
474     static const WCHAR xul_dllW[] = {'\\','x','u','l','.','d','l','l',0};
475     WCHAR file_name[MAX_PATH];
476 
477     strcpyW(file_name, gre_path);
478     strcatW(file_name, xul_dllW);
479 
480     TRACE("(%s)\n", debugstr_w(file_name));
481 
482     set_environment(gre_path);
483 
484     xul_handle = LoadLibraryExW(file_name, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
485     if(!xul_handle) {
486         WARN("Could not load XUL: %d\n", GetLastError());
487         return FALSE;
488     }
489 
490 #define NS_DLSYM(func) \
491     func = (void *)GetProcAddress(xul_handle, #func); \
492     if(!func) \
493         ERR("Could not GetProcAddress(" #func ") failed\n")
494 
495     NS_DLSYM(NS_InitXPCOM2);
496     NS_DLSYM(NS_ShutdownXPCOM);
497     NS_DLSYM(NS_GetComponentRegistrar);
498     NS_DLSYM(NS_StringContainerInit2);
499     NS_DLSYM(NS_CStringContainerInit2);
500     NS_DLSYM(NS_StringContainerFinish);
501     NS_DLSYM(NS_CStringContainerFinish);
502     NS_DLSYM(NS_StringSetData);
503     NS_DLSYM(NS_CStringSetData);
504     NS_DLSYM(NS_NewLocalFile);
505     NS_DLSYM(NS_StringGetData);
506     NS_DLSYM(NS_CStringGetData);
507     NS_DLSYM(NS_Alloc);
508     NS_DLSYM(NS_Free);
509     NS_DLSYM(ccref_incr);
510     NS_DLSYM(ccref_decr);
511     NS_DLSYM(ccref_init);
512     NS_DLSYM(ccp_init);
513     NS_DLSYM(describe_cc_node);
514     NS_DLSYM(note_cc_edge);
515 
516 #undef NS_DLSYM
517 
518     return TRUE;
519 }
520 
check_version(LPCWSTR gre_path,const char * version_string)521 static BOOL check_version(LPCWSTR gre_path, const char *version_string)
522 {
523     WCHAR file_name[MAX_PATH];
524     char version[128];
525     DWORD read=0;
526     HANDLE hfile;
527 
528     static const WCHAR wszVersion[] = {'\\','V','E','R','S','I','O','N',0};
529 
530     strcpyW(file_name, gre_path);
531     strcatW(file_name, wszVersion);
532 
533     hfile = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL,
534                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
535     if(hfile == INVALID_HANDLE_VALUE) {
536         ERR("Could not open VERSION file\n");
537         return FALSE;
538     }
539 
540     ReadFile(hfile, version, sizeof(version), &read, NULL);
541     version[read] = 0;
542     CloseHandle(hfile);
543 
544     TRACE("%s\n", debugstr_a(version));
545 
546     if(strcmp(version, version_string)) {
547         ERR("Unexpected version %s, expected %s\n", debugstr_a(version),
548             debugstr_a(version_string));
549         return FALSE;
550     }
551 
552     return TRUE;
553 }
554 
load_wine_gecko_v(PRUnichar * gre_path,HKEY mshtml_key,const char * version,const char * version_string)555 static BOOL load_wine_gecko_v(PRUnichar *gre_path, HKEY mshtml_key,
556         const char *version, const char *version_string)
557 {
558     DWORD res, type, size = MAX_PATH;
559     HKEY hkey = mshtml_key;
560 
561     static const WCHAR wszGeckoPath[] =
562         {'G','e','c','k','o','P','a','t','h',0};
563 
564     if(version) {
565         /* @@ Wine registry key: HKLM\Software\Wine\MSHTML\<version> */
566         res = RegOpenKeyA(mshtml_key, version, &hkey);
567         if(res != ERROR_SUCCESS)
568             return FALSE;
569     }
570 
571     res = RegQueryValueExW(hkey, wszGeckoPath, NULL, &type, (LPBYTE)gre_path, &size);
572     if(hkey != mshtml_key)
573         RegCloseKey(hkey);
574     if(res != ERROR_SUCCESS || type != REG_SZ)
575         return FALSE;
576 
577     if(!check_version(gre_path, version_string))
578         return FALSE;
579 
580     return load_xul(gre_path);
581 }
582 
load_wine_gecko(PRUnichar * gre_path)583 static BOOL load_wine_gecko(PRUnichar *gre_path)
584 {
585     HKEY hkey;
586     DWORD res;
587     BOOL ret;
588 
589     static const WCHAR wszMshtmlKey[] = {
590         'S','o','f','t','w','a','r','e','\\','W','i','n','e',
591         '\\','M','S','H','T','M','L',0};
592 
593     /* @@ Wine registry key: HKLM\Software\Wine\MSHTML */
594     res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszMshtmlKey, &hkey);
595     if(res != ERROR_SUCCESS)
596         return FALSE;
597 
598     ret = load_wine_gecko_v(gre_path, hkey, GECKO_VERSION, GECKO_VERSION_STRING);
599 
600     RegCloseKey(hkey);
601     return ret;
602 }
603 
set_bool_pref(nsIPrefBranch * pref,const char * pref_name,BOOL val)604 static void set_bool_pref(nsIPrefBranch *pref, const char *pref_name, BOOL val)
605 {
606     nsresult nsres;
607 
608     nsres = nsIPrefBranch_SetBoolPref(pref, pref_name, val);
609     if(NS_FAILED(nsres))
610         ERR("Could not set pref %s\n", debugstr_a(pref_name));
611 }
612 
set_int_pref(nsIPrefBranch * pref,const char * pref_name,int val)613 static void set_int_pref(nsIPrefBranch *pref, const char *pref_name, int val)
614 {
615     nsresult nsres;
616 
617     nsres = nsIPrefBranch_SetIntPref(pref, pref_name, val);
618     if(NS_FAILED(nsres))
619         ERR("Could not set pref %s\n", debugstr_a(pref_name));
620 }
621 
set_string_pref(nsIPrefBranch * pref,const char * pref_name,const char * val)622 static void set_string_pref(nsIPrefBranch *pref, const char *pref_name, const char *val)
623 {
624     nsresult nsres;
625 
626     nsres = nsIPrefBranch_SetCharPref(pref, pref_name, val);
627     if(NS_FAILED(nsres))
628         ERR("Could not set pref %s\n", debugstr_a(pref_name));
629 }
630 
set_lang(nsIPrefBranch * pref)631 static void set_lang(nsIPrefBranch *pref)
632 {
633     char langs[100];
634     DWORD res, size, type;
635     HKEY hkey;
636 
637     static const WCHAR international_keyW[] =
638         {'S','o','f','t','w','a','r','e',
639          '\\','M','i','c','r','o','s','o','f','t',
640          '\\','I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r',
641          '\\','I','n','t','e','r','n','a','t','i','o','n','a','l',0};
642 
643     res = RegOpenKeyW(HKEY_CURRENT_USER, international_keyW, &hkey);
644     if(res != ERROR_SUCCESS)
645         return;
646 
647     size = sizeof(langs);
648     res = RegQueryValueExA(hkey, "AcceptLanguage", 0, &type, (LPBYTE)langs, &size);
649     RegCloseKey(hkey);
650     if(res != ERROR_SUCCESS || type != REG_SZ)
651         return;
652 
653     TRACE("Setting lang %s\n", debugstr_a(langs));
654 
655     set_string_pref(pref, "intl.accept_languages", langs);
656 }
657 
set_preferences(void)658 static void set_preferences(void)
659 {
660     nsIPrefBranch *pref;
661     nsresult nsres;
662 
663     nsres = nsIServiceManager_GetServiceByContractID(pServMgr, NS_PREFERENCES_CONTRACTID,
664             &IID_nsIPrefBranch, (void**)&pref);
665     if(NS_FAILED(nsres)) {
666         ERR("Could not get preference service: %08x\n", nsres);
667         return;
668     }
669 
670     set_lang(pref);
671     set_bool_pref(pref, "security.warn_entering_secure", FALSE);
672     set_bool_pref(pref, "security.warn_submit_insecure", FALSE);
673     set_int_pref(pref, "layout.spellcheckDefault", 0);
674 
675     nsIPrefBranch_Release(pref);
676 }
677 
init_xpcom(const PRUnichar * gre_path)678 static BOOL init_xpcom(const PRUnichar *gre_path)
679 {
680     nsIComponentRegistrar *registrar = NULL;
681     nsIFile *gre_dir;
682     WCHAR *ptr;
683     nsresult nsres;
684 
685     nsres = create_nsfile(gre_path, &gre_dir);
686     if(NS_FAILED(nsres)) {
687         FreeLibrary(xul_handle);
688         return FALSE;
689     }
690 
691     nsres = NS_InitXPCOM2(&pServMgr, gre_dir, (nsIDirectoryServiceProvider*)&nsDirectoryServiceProvider2);
692     if(NS_FAILED(nsres)) {
693         ERR("NS_InitXPCOM2 failed: %08x\n", nsres);
694         FreeLibrary(xul_handle);
695         return FALSE;
696     }
697 
698     strcpyW(gecko_path, gre_path);
699     for(ptr = gecko_path; *ptr; ptr++) {
700         if(*ptr == '\\')
701             *ptr = '/';
702     }
703     gecko_path_len = ptr-gecko_path;
704 
705     nsres = nsIServiceManager_QueryInterface(pServMgr, &IID_nsIComponentManager, (void**)&pCompMgr);
706     if(NS_FAILED(nsres))
707         ERR("Could not get nsIComponentManager: %08x\n", nsres);
708 
709     nsres = NS_GetComponentRegistrar(&registrar);
710     if(NS_SUCCEEDED(nsres))
711         init_nsio(pCompMgr, registrar);
712     else
713         ERR("NS_GetComponentRegistrar failed: %08x\n", nsres);
714 
715     init_mutation(pCompMgr);
716     set_preferences();
717 
718     nsres = nsIServiceManager_GetServiceByContractID(pServMgr, NS_CATEGORYMANAGER_CONTRACTID,
719             &IID_nsICategoryManager, (void**)&cat_mgr);
720     if(NS_FAILED(nsres))
721         ERR("Could not get category manager service: %08x\n", nsres);
722 
723     if(registrar) {
724         register_nsservice(registrar, pServMgr);
725         nsIComponentRegistrar_Release(registrar);
726     }
727 
728     init_node_cc();
729 
730     return TRUE;
731 }
732 
733 static CRITICAL_SECTION cs_load_gecko;
734 static CRITICAL_SECTION_DEBUG cs_load_gecko_dbg =
735 {
736     0, 0, &cs_load_gecko,
737     { &cs_load_gecko_dbg.ProcessLocksList, &cs_load_gecko_dbg.ProcessLocksList },
738       0, 0, { (DWORD_PTR)(__FILE__ ": load_gecko") }
739 };
740 static CRITICAL_SECTION cs_load_gecko = { &cs_load_gecko_dbg, -1, 0, 0, 0, 0 };
741 
load_gecko(void)742 BOOL load_gecko(void)
743 {
744     PRUnichar gre_path[MAX_PATH];
745     BOOL ret = FALSE;
746 
747     static DWORD loading_thread;
748 
749     TRACE("()\n");
750 
751     /* load_gecko may be called recursively */
752     if(loading_thread == GetCurrentThreadId())
753         return pCompMgr != NULL;
754 
755     EnterCriticalSection(&cs_load_gecko);
756 
757     if(!loading_thread) {
758         loading_thread = GetCurrentThreadId();
759 
760 #ifdef __REACTOS__
761         if(load_wine_gecko(gre_path))
762 #else
763         if(load_wine_gecko(gre_path)
764            || (install_wine_gecko() && load_wine_gecko(gre_path)))
765 #endif
766             ret = init_xpcom(gre_path);
767         else
768            MESSAGE("Could not load wine-gecko. HTML rendering will be disabled.\n");
769     }else {
770         ret = pCompMgr != NULL;
771     }
772 
773     LeaveCriticalSection(&cs_load_gecko);
774 
775     return ret;
776 }
777 
nsalloc(size_t size)778 void *nsalloc(size_t size)
779 {
780     return NS_Alloc(size);
781 }
782 
nsfree(void * mem)783 void nsfree(void *mem)
784 {
785     NS_Free(mem);
786 }
787 
nsACString_Init(nsACString * str,const char * data)788 BOOL nsACString_Init(nsACString *str, const char *data)
789 {
790     return NS_SUCCEEDED(NS_CStringContainerInit2(str, data, PR_UINT32_MAX, 0));
791 }
792 
793 /*
794  * Initializes nsACString with data owned by caller.
795  * Caller must ensure that data is valid during lifetime of string object.
796  */
nsACString_InitDepend(nsACString * str,const char * data)797 void nsACString_InitDepend(nsACString *str, const char *data)
798 {
799     NS_CStringContainerInit2(str, data, PR_UINT32_MAX, NS_CSTRING_CONTAINER_INIT_DEPEND);
800 }
801 
nsACString_SetData(nsACString * str,const char * data)802 void nsACString_SetData(nsACString *str, const char *data)
803 {
804     NS_CStringSetData(str, data, PR_UINT32_MAX);
805 }
806 
nsACString_GetData(const nsACString * str,const char ** data)807 UINT32 nsACString_GetData(const nsACString *str, const char **data)
808 {
809     return NS_CStringGetData(str, data, NULL);
810 }
811 
nsACString_Finish(nsACString * str)812 void nsACString_Finish(nsACString *str)
813 {
814     NS_CStringContainerFinish(str);
815 }
816 
nsAString_Init(nsAString * str,const PRUnichar * data)817 BOOL nsAString_Init(nsAString *str, const PRUnichar *data)
818 {
819     return NS_SUCCEEDED(NS_StringContainerInit2(str, data, PR_UINT32_MAX, 0));
820 }
821 
822 /*
823  * Initializes nsAString with data owned by caller.
824  * Caller must ensure that data is valid during lifetime of string object.
825  */
nsAString_InitDepend(nsAString * str,const PRUnichar * data)826 void nsAString_InitDepend(nsAString *str, const PRUnichar *data)
827 {
828     NS_StringContainerInit2(str, data, PR_UINT32_MAX, NS_STRING_CONTAINER_INIT_DEPEND);
829 }
830 
nsAString_GetData(const nsAString * str,const PRUnichar ** data)831 UINT32 nsAString_GetData(const nsAString *str, const PRUnichar **data)
832 {
833     return NS_StringGetData(str, data, NULL);
834 }
835 
nsAString_Finish(nsAString * str)836 void nsAString_Finish(nsAString *str)
837 {
838     NS_StringContainerFinish(str);
839 }
840 
return_nsstr(nsresult nsres,nsAString * nsstr,BSTR * p)841 HRESULT return_nsstr(nsresult nsres, nsAString *nsstr, BSTR *p)
842 {
843     const PRUnichar *str;
844 
845     if(NS_FAILED(nsres)) {
846         ERR("failed: %08x\n", nsres);
847         nsAString_Finish(nsstr);
848         return E_FAIL;
849     }
850 
851     nsAString_GetData(nsstr, &str);
852     TRACE("ret %s\n", debugstr_w(str));
853     if(*str) {
854         *p = SysAllocString(str);
855         if(!*p)
856             return E_OUTOFMEMORY;
857     }else {
858         *p = NULL;
859     }
860 
861     nsAString_Finish(nsstr);
862     return S_OK;
863 }
864 
create_nscommand_params(void)865 nsICommandParams *create_nscommand_params(void)
866 {
867     nsICommandParams *ret = NULL;
868     nsresult nsres;
869 
870     if(!pCompMgr)
871         return NULL;
872 
873     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
874             NS_COMMANDPARAMS_CONTRACTID, NULL, &IID_nsICommandParams,
875             (void**)&ret);
876     if(NS_FAILED(nsres))
877         ERR("Could not get nsICommandParams\n");
878 
879     return ret;
880 }
881 
create_nsvariant(void)882 nsIWritableVariant *create_nsvariant(void)
883 {
884     nsIWritableVariant *ret = NULL;
885     nsresult nsres;
886 
887     if(!pCompMgr)
888         return NULL;
889 
890     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
891             NS_VARIANT_CONTRACTID, NULL, &IID_nsIWritableVariant, (void**)&ret);
892     if(NS_FAILED(nsres))
893         ERR("Could not get nsIVariant\n");
894 
895     return ret;
896 }
897 
get_nscategory_entry(const char * category,const char * entry)898 char *get_nscategory_entry(const char *category, const char *entry)
899 {
900     char *ret = NULL;
901     nsresult nsres;
902 
903     nsres = nsICategoryManager_GetCategoryEntry(cat_mgr, category, entry, &ret);
904     return NS_SUCCEEDED(nsres) ? ret : NULL;
905 }
906 
get_nsinterface(nsISupports * iface,REFIID riid,void ** ppv)907 nsresult get_nsinterface(nsISupports *iface, REFIID riid, void **ppv)
908 {
909     nsIInterfaceRequestor *iface_req;
910     nsresult nsres;
911 
912     nsres = nsISupports_QueryInterface(iface, &IID_nsIInterfaceRequestor, (void**)&iface_req);
913     if(NS_FAILED(nsres))
914         return nsres;
915 
916     nsres = nsIInterfaceRequestor_GetInterface(iface_req, riid, ppv);
917     nsIInterfaceRequestor_Release(iface_req);
918 
919     return nsres;
920 }
921 
nsnode_to_nsstring_rec(nsIContentSerializer * serializer,nsIDOMNode * nsnode,nsAString * str)922 static HRESULT nsnode_to_nsstring_rec(nsIContentSerializer *serializer, nsIDOMNode *nsnode, nsAString *str)
923 {
924     nsIDOMNodeList *node_list = NULL;
925     cpp_bool has_children = FALSE;
926     nsIContent *nscontent;
927     UINT16 type;
928     nsresult nsres;
929 
930     nsIDOMNode_HasChildNodes(nsnode, &has_children);
931 
932     nsres = nsIDOMNode_GetNodeType(nsnode, &type);
933     if(NS_FAILED(nsres)) {
934         ERR("GetType failed: %08x\n", nsres);
935         return E_FAIL;
936     }
937 
938     if(type != DOCUMENT_NODE) {
939         nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIContent, (void**)&nscontent);
940         if(NS_FAILED(nsres)) {
941             ERR("Could not get nsIContent interface: %08x\n", nsres);
942             return E_FAIL;
943         }
944     }
945 
946     switch(type) {
947     case ELEMENT_NODE:
948         nsIContentSerializer_AppendElementStart(serializer, nscontent, nscontent, str);
949         break;
950     case TEXT_NODE:
951         nsIContentSerializer_AppendText(serializer, nscontent, 0, -1, str);
952         break;
953     case COMMENT_NODE:
954         nsres = nsIContentSerializer_AppendComment(serializer, nscontent, 0, -1, str);
955         break;
956     case DOCUMENT_NODE: {
957         nsIDocument *nsdoc;
958         nsIDOMNode_QueryInterface(nsnode, &IID_nsIDocument, (void**)&nsdoc);
959         nsIContentSerializer_AppendDocumentStart(serializer, nsdoc, str);
960         nsIDocument_Release(nsdoc);
961         break;
962     }
963     case DOCUMENT_TYPE_NODE:
964         nsIContentSerializer_AppendDoctype(serializer, nscontent, str);
965         break;
966     case DOCUMENT_FRAGMENT_NODE:
967         break;
968     default:
969         FIXME("Unhandled type %u\n", type);
970     }
971 
972     if(has_children) {
973         UINT32 child_cnt, i;
974         nsIDOMNode *child_node;
975 
976         nsIDOMNode_GetChildNodes(nsnode, &node_list);
977         nsIDOMNodeList_GetLength(node_list, &child_cnt);
978 
979         for(i=0; i<child_cnt; i++) {
980             nsres = nsIDOMNodeList_Item(node_list, i, &child_node);
981             if(NS_SUCCEEDED(nsres)) {
982                 nsnode_to_nsstring_rec(serializer, child_node, str);
983                 nsIDOMNode_Release(child_node);
984             }else {
985                 ERR("Item failed: %08x\n", nsres);
986             }
987         }
988 
989         nsIDOMNodeList_Release(node_list);
990     }
991 
992     if(type == ELEMENT_NODE)
993         nsIContentSerializer_AppendElementEnd(serializer, nscontent, str);
994 
995     if(type != DOCUMENT_NODE)
996         nsIContent_Release(nscontent);
997     return S_OK;
998 }
999 
nsnode_to_nsstring(nsIDOMNode * nsnode,nsAString * str)1000 HRESULT nsnode_to_nsstring(nsIDOMNode *nsnode, nsAString *str)
1001 {
1002     nsIContentSerializer *serializer;
1003     nsresult nsres;
1004     HRESULT hres;
1005 
1006     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
1007             NS_HTMLSERIALIZER_CONTRACTID, NULL, &IID_nsIContentSerializer,
1008             (void**)&serializer);
1009     if(NS_FAILED(nsres)) {
1010         ERR("Could not get nsIContentSerializer: %08x\n", nsres);
1011         return E_FAIL;
1012     }
1013 
1014     nsres = nsIContentSerializer_Init(serializer, 0, 100, NULL, FALSE, FALSE /* FIXME */);
1015     if(NS_FAILED(nsres))
1016         ERR("Init failed: %08x\n", nsres);
1017 
1018     hres = nsnode_to_nsstring_rec(serializer, nsnode, str);
1019     if(SUCCEEDED(hres)) {
1020         nsres = nsIContentSerializer_Flush(serializer, str);
1021         if(NS_FAILED(nsres))
1022             ERR("Flush failed: %08x\n", nsres);
1023     }
1024 
1025     nsIContentSerializer_Release(serializer);
1026     return hres;
1027 }
1028 
get_editor_controller(NSContainer * This)1029 void get_editor_controller(NSContainer *This)
1030 {
1031     nsIEditingSession *editing_session = NULL;
1032     nsIControllerContext *ctrlctx;
1033     nsresult nsres;
1034 
1035     if(This->editor) {
1036         nsIEditor_Release(This->editor);
1037         This->editor = NULL;
1038     }
1039 
1040     if(This->editor_controller) {
1041         nsIController_Release(This->editor_controller);
1042         This->editor_controller = NULL;
1043     }
1044 
1045     nsres = get_nsinterface((nsISupports*)This->webbrowser, &IID_nsIEditingSession,
1046             (void**)&editing_session);
1047     if(NS_FAILED(nsres)) {
1048         ERR("Could not get nsIEditingSession: %08x\n", nsres);
1049         return;
1050     }
1051 
1052     nsres = nsIEditingSession_GetEditorForWindow(editing_session,
1053             This->doc->basedoc.window->nswindow, &This->editor);
1054     nsIEditingSession_Release(editing_session);
1055     if(NS_FAILED(nsres)) {
1056         ERR("Could not get editor: %08x\n", nsres);
1057         return;
1058     }
1059 
1060     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
1061             NS_EDITORCONTROLLER_CONTRACTID, NULL, &IID_nsIControllerContext, (void**)&ctrlctx);
1062     if(NS_SUCCEEDED(nsres)) {
1063         nsres = nsIControllerContext_SetCommandContext(ctrlctx, (nsISupports *)This->editor);
1064         if(NS_FAILED(nsres))
1065             ERR("SetCommandContext failed: %08x\n", nsres);
1066         nsres = nsIControllerContext_QueryInterface(ctrlctx, &IID_nsIController,
1067                 (void**)&This->editor_controller);
1068         nsIControllerContext_Release(ctrlctx);
1069         if(NS_FAILED(nsres))
1070             ERR("Could not get nsIController interface: %08x\n", nsres);
1071     }else {
1072         ERR("Could not create edit controller: %08x\n", nsres);
1073     }
1074 }
1075 
close_gecko(void)1076 void close_gecko(void)
1077 {
1078     TRACE("()\n");
1079 
1080     release_nsio();
1081     init_mutation(NULL);
1082 
1083     if(profile_directory) {
1084         nsIFile_Release(profile_directory);
1085         profile_directory = NULL;
1086     }
1087 
1088     if(plugin_directory) {
1089         nsIFile_Release(plugin_directory);
1090         plugin_directory = NULL;
1091     }
1092 
1093     if(pCompMgr)
1094         nsIComponentManager_Release(pCompMgr);
1095 
1096     if(pServMgr)
1097         nsIServiceManager_Release(pServMgr);
1098 
1099     if(cat_mgr)
1100         nsICategoryManager_Release(cat_mgr);
1101 
1102     /* Gecko doesn't really support being unloaded */
1103     /* if (hXPCOM) FreeLibrary(hXPCOM); */
1104 
1105     DeleteCriticalSection(&cs_load_gecko);
1106 }
1107 
is_gecko_path(const char * path)1108 BOOL is_gecko_path(const char *path)
1109 {
1110     WCHAR *buf, *ptr;
1111     BOOL ret;
1112 
1113     buf = heap_strdupUtoW(path);
1114     if(!buf || strlenW(buf) < gecko_path_len)
1115         return FALSE;
1116 
1117     for(ptr = buf; *ptr; ptr++) {
1118         if(*ptr == '\\')
1119             *ptr = '/';
1120     }
1121 
1122     UrlUnescapeW(buf, NULL, NULL, URL_UNESCAPE_INPLACE);
1123     buf[gecko_path_len] = 0;
1124 
1125     ret = !strcmpiW(buf, gecko_path);
1126     heap_free(buf);
1127     return ret;
1128 }
1129 
set_viewer_zoom(NSContainer * nscontainer,float factor)1130 void set_viewer_zoom(NSContainer *nscontainer, float factor)
1131 {
1132     nsIContentViewer *content_viewer;
1133     nsIDocShell *doc_shell;
1134     nsresult nsres;
1135 
1136     TRACE("Setting to %f\n", factor);
1137 
1138     nsres = get_nsinterface((nsISupports*)nscontainer->navigation, &IID_nsIDocShell, (void**)&doc_shell);
1139     assert(nsres == NS_OK);
1140 
1141     nsres = nsIDocShell_GetContentViewer(doc_shell, &content_viewer);
1142     assert(nsres == NS_OK && content_viewer);
1143     nsIDocShell_Release(doc_shell);
1144 
1145     nsres = nsIContentViewer_SetFullZoom(content_viewer, factor);
1146     if(NS_FAILED(nsres))
1147         ERR("SetFullZoom failed: %08x\n", nsres);
1148 
1149     nsIContentViewer_Release(content_viewer);
1150 }
1151 
1152 struct nsWeakReference {
1153     nsIWeakReference nsIWeakReference_iface;
1154 
1155     LONG ref;
1156 
1157     NSContainer *nscontainer;
1158 };
1159 
impl_from_nsIWeakReference(nsIWeakReference * iface)1160 static inline nsWeakReference *impl_from_nsIWeakReference(nsIWeakReference *iface)
1161 {
1162     return CONTAINING_RECORD(iface, nsWeakReference, nsIWeakReference_iface);
1163 }
1164 
nsWeakReference_QueryInterface(nsIWeakReference * iface,nsIIDRef riid,void ** result)1165 static nsresult NSAPI nsWeakReference_QueryInterface(nsIWeakReference *iface,
1166         nsIIDRef riid, void **result)
1167 {
1168     nsWeakReference *This = impl_from_nsIWeakReference(iface);
1169 
1170     if(IsEqualGUID(&IID_nsISupports, riid)) {
1171         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
1172         *result = &This->nsIWeakReference_iface;
1173     }else if(IsEqualGUID(&IID_nsIWeakReference, riid)) {
1174         TRACE("(%p)->(IID_nsIWeakReference %p)\n", This, result);
1175         *result = &This->nsIWeakReference_iface;
1176     }else {
1177         WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
1178         *result = NULL;
1179         return NS_NOINTERFACE;
1180     }
1181 
1182     nsISupports_AddRef((nsISupports*)*result);
1183     return NS_OK;
1184 }
1185 
nsWeakReference_AddRef(nsIWeakReference * iface)1186 static nsrefcnt NSAPI nsWeakReference_AddRef(nsIWeakReference *iface)
1187 {
1188     nsWeakReference *This = impl_from_nsIWeakReference(iface);
1189     LONG ref = InterlockedIncrement(&This->ref);
1190 
1191     TRACE("(%p) ref=%d\n", This, ref);
1192 
1193     return ref;
1194 }
1195 
nsWeakReference_Release(nsIWeakReference * iface)1196 static nsrefcnt NSAPI nsWeakReference_Release(nsIWeakReference *iface)
1197 {
1198     nsWeakReference *This = impl_from_nsIWeakReference(iface);
1199     LONG ref = InterlockedIncrement(&This->ref);
1200 
1201     TRACE("(%p) ref=%d\n", This, ref);
1202 
1203     if(!ref) {
1204         assert(!This->nscontainer);
1205         heap_free(This);
1206     }
1207 
1208     return ref;
1209 }
1210 
nsWeakReference_QueryReferent(nsIWeakReference * iface,const nsIID * riid,void ** result)1211 static nsresult NSAPI nsWeakReference_QueryReferent(nsIWeakReference *iface,
1212         const nsIID *riid, void **result)
1213 {
1214     nsWeakReference *This = impl_from_nsIWeakReference(iface);
1215 
1216     if(!This->nscontainer)
1217         return NS_ERROR_NULL_POINTER;
1218 
1219     return nsIWebBrowserChrome_QueryInterface(&This->nscontainer->nsIWebBrowserChrome_iface, riid, result);
1220 }
1221 
1222 static const nsIWeakReferenceVtbl nsWeakReferenceVtbl = {
1223     nsWeakReference_QueryInterface,
1224     nsWeakReference_AddRef,
1225     nsWeakReference_Release,
1226     nsWeakReference_QueryReferent
1227 };
1228 
1229 /**********************************************************
1230  *      nsIWebBrowserChrome interface
1231  */
1232 
impl_from_nsIWebBrowserChrome(nsIWebBrowserChrome * iface)1233 static inline NSContainer *impl_from_nsIWebBrowserChrome(nsIWebBrowserChrome *iface)
1234 {
1235     return CONTAINING_RECORD(iface, NSContainer, nsIWebBrowserChrome_iface);
1236 }
1237 
nsWebBrowserChrome_QueryInterface(nsIWebBrowserChrome * iface,nsIIDRef riid,void ** result)1238 static nsresult NSAPI nsWebBrowserChrome_QueryInterface(nsIWebBrowserChrome *iface,
1239         nsIIDRef riid, void **result)
1240 {
1241     NSContainer *This = impl_from_nsIWebBrowserChrome(iface);
1242 
1243     *result = NULL;
1244     if(IsEqualGUID(&IID_nsISupports, riid)) {
1245         TRACE("(%p)->(IID_nsISupports, %p)\n", This, result);
1246         *result = &This->nsIWebBrowserChrome_iface;
1247     }else if(IsEqualGUID(&IID_nsIWebBrowserChrome, riid)) {
1248         TRACE("(%p)->(IID_nsIWebBrowserChrome, %p)\n", This, result);
1249         *result = &This->nsIWebBrowserChrome_iface;
1250     }else if(IsEqualGUID(&IID_nsIContextMenuListener, riid)) {
1251         TRACE("(%p)->(IID_nsIContextMenuListener, %p)\n", This, result);
1252         *result = &This->nsIContextMenuListener_iface;
1253     }else if(IsEqualGUID(&IID_nsIURIContentListener, riid)) {
1254         TRACE("(%p)->(IID_nsIURIContentListener %p)\n", This, result);
1255         *result = &This->nsIURIContentListener_iface;
1256     }else if(IsEqualGUID(&IID_nsIEmbeddingSiteWindow, riid)) {
1257         TRACE("(%p)->(IID_nsIEmbeddingSiteWindow %p)\n", This, result);
1258         *result = &This->nsIEmbeddingSiteWindow_iface;
1259     }else if(IsEqualGUID(&IID_nsITooltipListener, riid)) {
1260         TRACE("(%p)->(IID_nsITooltipListener %p)\n", This, result);
1261         *result = &This->nsITooltipListener_iface;
1262     }else if(IsEqualGUID(&IID_nsIInterfaceRequestor, riid)) {
1263         TRACE("(%p)->(IID_nsIInterfaceRequestor %p)\n", This, result);
1264         *result = &This->nsIInterfaceRequestor_iface;
1265     }else if(IsEqualGUID(&IID_nsISupportsWeakReference, riid)) {
1266         TRACE("(%p)->(IID_nsISupportsWeakReference %p)\n", This, result);
1267         *result = &This->nsISupportsWeakReference_iface;
1268     }
1269 
1270     if(*result) {
1271         nsIWebBrowserChrome_AddRef(&This->nsIWebBrowserChrome_iface);
1272         return NS_OK;
1273     }
1274 
1275     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
1276     return NS_NOINTERFACE;
1277 }
1278 
nsWebBrowserChrome_AddRef(nsIWebBrowserChrome * iface)1279 static nsrefcnt NSAPI nsWebBrowserChrome_AddRef(nsIWebBrowserChrome *iface)
1280 {
1281     NSContainer *This = impl_from_nsIWebBrowserChrome(iface);
1282     LONG ref = InterlockedIncrement(&This->ref);
1283 
1284     TRACE("(%p) ref=%d\n", This, ref);
1285 
1286     return ref;
1287 }
1288 
nsWebBrowserChrome_Release(nsIWebBrowserChrome * iface)1289 static nsrefcnt NSAPI nsWebBrowserChrome_Release(nsIWebBrowserChrome *iface)
1290 {
1291     NSContainer *This = impl_from_nsIWebBrowserChrome(iface);
1292     LONG ref = InterlockedDecrement(&This->ref);
1293 
1294     TRACE("(%p) ref=%d\n", This, ref);
1295 
1296     if(!ref) {
1297         if(This->parent)
1298             nsIWebBrowserChrome_Release(&This->parent->nsIWebBrowserChrome_iface);
1299         if(This->weak_reference) {
1300             This->weak_reference->nscontainer = NULL;
1301             nsIWeakReference_Release(&This->weak_reference->nsIWeakReference_iface);
1302         }
1303         heap_free(This);
1304     }
1305 
1306     return ref;
1307 }
1308 
nsWebBrowserChrome_SetStatus(nsIWebBrowserChrome * iface,UINT32 statusType,const PRUnichar * status)1309 static nsresult NSAPI nsWebBrowserChrome_SetStatus(nsIWebBrowserChrome *iface,
1310         UINT32 statusType, const PRUnichar *status)
1311 {
1312     NSContainer *This = impl_from_nsIWebBrowserChrome(iface);
1313     TRACE("(%p)->(%d %s)\n", This, statusType, debugstr_w(status));
1314     return NS_OK;
1315 }
1316 
nsWebBrowserChrome_GetWebBrowser(nsIWebBrowserChrome * iface,nsIWebBrowser ** aWebBrowser)1317 static nsresult NSAPI nsWebBrowserChrome_GetWebBrowser(nsIWebBrowserChrome *iface,
1318         nsIWebBrowser **aWebBrowser)
1319 {
1320     NSContainer *This = impl_from_nsIWebBrowserChrome(iface);
1321 
1322     TRACE("(%p)->(%p)\n", This, aWebBrowser);
1323 
1324     if(!aWebBrowser)
1325         return NS_ERROR_INVALID_ARG;
1326 
1327     if(This->webbrowser)
1328         nsIWebBrowser_AddRef(This->webbrowser);
1329     *aWebBrowser = This->webbrowser;
1330     return S_OK;
1331 }
1332 
nsWebBrowserChrome_SetWebBrowser(nsIWebBrowserChrome * iface,nsIWebBrowser * aWebBrowser)1333 static nsresult NSAPI nsWebBrowserChrome_SetWebBrowser(nsIWebBrowserChrome *iface,
1334         nsIWebBrowser *aWebBrowser)
1335 {
1336     NSContainer *This = impl_from_nsIWebBrowserChrome(iface);
1337 
1338     TRACE("(%p)->(%p)\n", This, aWebBrowser);
1339 
1340     if(aWebBrowser != This->webbrowser)
1341         ERR("Wrong nsWebBrowser!\n");
1342 
1343     return NS_OK;
1344 }
1345 
nsWebBrowserChrome_GetChromeFlags(nsIWebBrowserChrome * iface,UINT32 * aChromeFlags)1346 static nsresult NSAPI nsWebBrowserChrome_GetChromeFlags(nsIWebBrowserChrome *iface,
1347         UINT32 *aChromeFlags)
1348 {
1349     NSContainer *This = impl_from_nsIWebBrowserChrome(iface);
1350     WARN("(%p)->(%p)\n", This, aChromeFlags);
1351     return NS_ERROR_NOT_IMPLEMENTED;
1352 }
1353 
nsWebBrowserChrome_SetChromeFlags(nsIWebBrowserChrome * iface,UINT32 aChromeFlags)1354 static nsresult NSAPI nsWebBrowserChrome_SetChromeFlags(nsIWebBrowserChrome *iface,
1355         UINT32 aChromeFlags)
1356 {
1357     NSContainer *This = impl_from_nsIWebBrowserChrome(iface);
1358     WARN("(%p)->(%08x)\n", This, aChromeFlags);
1359     return NS_ERROR_NOT_IMPLEMENTED;
1360 }
1361 
nsWebBrowserChrome_DestroyBrowserWindow(nsIWebBrowserChrome * iface)1362 static nsresult NSAPI nsWebBrowserChrome_DestroyBrowserWindow(nsIWebBrowserChrome *iface)
1363 {
1364     NSContainer *This = impl_from_nsIWebBrowserChrome(iface);
1365     TRACE("(%p)\n", This);
1366     return NS_ERROR_NOT_IMPLEMENTED;
1367 }
1368 
nsWebBrowserChrome_SizeBrowserTo(nsIWebBrowserChrome * iface,LONG aCX,LONG aCY)1369 static nsresult NSAPI nsWebBrowserChrome_SizeBrowserTo(nsIWebBrowserChrome *iface,
1370         LONG aCX, LONG aCY)
1371 {
1372     NSContainer *This = impl_from_nsIWebBrowserChrome(iface);
1373     WARN("(%p)->(%d %d)\n", This, aCX, aCY);
1374     return NS_ERROR_NOT_IMPLEMENTED;
1375 }
1376 
nsWebBrowserChrome_ShowAsModal(nsIWebBrowserChrome * iface)1377 static nsresult NSAPI nsWebBrowserChrome_ShowAsModal(nsIWebBrowserChrome *iface)
1378 {
1379     NSContainer *This = impl_from_nsIWebBrowserChrome(iface);
1380     WARN("(%p)\n", This);
1381     return NS_ERROR_NOT_IMPLEMENTED;
1382 }
1383 
nsWebBrowserChrome_IsWindowModal(nsIWebBrowserChrome * iface,cpp_bool * _retval)1384 static nsresult NSAPI nsWebBrowserChrome_IsWindowModal(nsIWebBrowserChrome *iface, cpp_bool *_retval)
1385 {
1386     NSContainer *This = impl_from_nsIWebBrowserChrome(iface);
1387     WARN("(%p)->(%p)\n", This, _retval);
1388     return NS_ERROR_NOT_IMPLEMENTED;
1389 }
1390 
nsWebBrowserChrome_ExitModalEventLoop(nsIWebBrowserChrome * iface,nsresult aStatus)1391 static nsresult NSAPI nsWebBrowserChrome_ExitModalEventLoop(nsIWebBrowserChrome *iface,
1392         nsresult aStatus)
1393 {
1394     NSContainer *This = impl_from_nsIWebBrowserChrome(iface);
1395     WARN("(%p)->(%08x)\n", This, aStatus);
1396     return NS_ERROR_NOT_IMPLEMENTED;
1397 }
1398 
1399 static const nsIWebBrowserChromeVtbl nsWebBrowserChromeVtbl = {
1400     nsWebBrowserChrome_QueryInterface,
1401     nsWebBrowserChrome_AddRef,
1402     nsWebBrowserChrome_Release,
1403     nsWebBrowserChrome_SetStatus,
1404     nsWebBrowserChrome_GetWebBrowser,
1405     nsWebBrowserChrome_SetWebBrowser,
1406     nsWebBrowserChrome_GetChromeFlags,
1407     nsWebBrowserChrome_SetChromeFlags,
1408     nsWebBrowserChrome_DestroyBrowserWindow,
1409     nsWebBrowserChrome_SizeBrowserTo,
1410     nsWebBrowserChrome_ShowAsModal,
1411     nsWebBrowserChrome_IsWindowModal,
1412     nsWebBrowserChrome_ExitModalEventLoop
1413 };
1414 
1415 /**********************************************************
1416  *      nsIContextMenuListener interface
1417  */
1418 
impl_from_nsIContextMenuListener(nsIContextMenuListener * iface)1419 static inline NSContainer *impl_from_nsIContextMenuListener(nsIContextMenuListener *iface)
1420 {
1421     return CONTAINING_RECORD(iface, NSContainer, nsIContextMenuListener_iface);
1422 }
1423 
nsContextMenuListener_QueryInterface(nsIContextMenuListener * iface,nsIIDRef riid,void ** result)1424 static nsresult NSAPI nsContextMenuListener_QueryInterface(nsIContextMenuListener *iface,
1425         nsIIDRef riid, void **result)
1426 {
1427     NSContainer *This = impl_from_nsIContextMenuListener(iface);
1428     return nsIWebBrowserChrome_QueryInterface(&This->nsIWebBrowserChrome_iface, riid, result);
1429 }
1430 
nsContextMenuListener_AddRef(nsIContextMenuListener * iface)1431 static nsrefcnt NSAPI nsContextMenuListener_AddRef(nsIContextMenuListener *iface)
1432 {
1433     NSContainer *This = impl_from_nsIContextMenuListener(iface);
1434     return nsIWebBrowserChrome_AddRef(&This->nsIWebBrowserChrome_iface);
1435 }
1436 
nsContextMenuListener_Release(nsIContextMenuListener * iface)1437 static nsrefcnt NSAPI nsContextMenuListener_Release(nsIContextMenuListener *iface)
1438 {
1439     NSContainer *This = impl_from_nsIContextMenuListener(iface);
1440     return nsIWebBrowserChrome_Release(&This->nsIWebBrowserChrome_iface);
1441 }
1442 
nsContextMenuListener_OnShowContextMenu(nsIContextMenuListener * iface,UINT32 aContextFlags,nsIDOMEvent * aEvent,nsIDOMNode * aNode)1443 static nsresult NSAPI nsContextMenuListener_OnShowContextMenu(nsIContextMenuListener *iface,
1444         UINT32 aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode)
1445 {
1446     NSContainer *This = impl_from_nsIContextMenuListener(iface);
1447     nsIDOMMouseEvent *event;
1448     HTMLDOMNode *node;
1449     POINT pt;
1450     DWORD dwID = CONTEXT_MENU_DEFAULT;
1451     nsresult nsres;
1452     HRESULT hres;
1453 
1454     TRACE("(%p)->(%08x %p %p)\n", This, aContextFlags, aEvent, aNode);
1455 
1456     fire_event(This->doc->basedoc.doc_node /* FIXME */, EVENTID_CONTEXTMENU, TRUE, aNode, aEvent, NULL);
1457 
1458     nsres = nsIDOMEvent_QueryInterface(aEvent, &IID_nsIDOMMouseEvent, (void**)&event);
1459     if(NS_FAILED(nsres)) {
1460         ERR("Could not get nsIDOMMouseEvent interface: %08x\n", nsres);
1461         return nsres;
1462     }
1463 
1464     nsIDOMMouseEvent_GetScreenX(event, &pt.x);
1465     nsIDOMMouseEvent_GetScreenY(event, &pt.y);
1466     nsIDOMMouseEvent_Release(event);
1467 
1468     switch(aContextFlags) {
1469     case CONTEXT_NONE:
1470     case CONTEXT_DOCUMENT:
1471     case CONTEXT_TEXT: {
1472         nsISelection *selection;
1473 
1474         nsres = nsIDOMHTMLDocument_GetSelection(This->doc->basedoc.doc_node->nsdoc, &selection);
1475         if(NS_SUCCEEDED(nsres) && selection) {
1476             cpp_bool is_collapsed;
1477 
1478             /* FIXME: Check if the click was inside selection. */
1479             nsres = nsISelection_GetIsCollapsed(selection, &is_collapsed);
1480             nsISelection_Release(selection);
1481             if(NS_SUCCEEDED(nsres) && !is_collapsed)
1482                 dwID = CONTEXT_MENU_TEXTSELECT;
1483         }
1484         break;
1485     }
1486     case CONTEXT_IMAGE:
1487     case CONTEXT_IMAGE|CONTEXT_LINK:
1488         dwID = CONTEXT_MENU_IMAGE;
1489         break;
1490     case CONTEXT_LINK:
1491         dwID = CONTEXT_MENU_ANCHOR;
1492         break;
1493     case CONTEXT_INPUT:
1494         dwID = CONTEXT_MENU_CONTROL;
1495         break;
1496     default:
1497         FIXME("aContextFlags=%08x\n", aContextFlags);
1498     };
1499 
1500     hres = get_node(This->doc->basedoc.doc_node, aNode, TRUE, &node);
1501     if(FAILED(hres))
1502         return NS_ERROR_FAILURE;
1503 
1504     show_context_menu(This->doc, dwID, &pt, (IDispatch*)&node->IHTMLDOMNode_iface);
1505     node_release(node);
1506     return NS_OK;
1507 }
1508 
1509 static const nsIContextMenuListenerVtbl nsContextMenuListenerVtbl = {
1510     nsContextMenuListener_QueryInterface,
1511     nsContextMenuListener_AddRef,
1512     nsContextMenuListener_Release,
1513     nsContextMenuListener_OnShowContextMenu
1514 };
1515 
1516 /**********************************************************
1517  *      nsIURIContentListener interface
1518  */
1519 
impl_from_nsIURIContentListener(nsIURIContentListener * iface)1520 static inline NSContainer *impl_from_nsIURIContentListener(nsIURIContentListener *iface)
1521 {
1522     return CONTAINING_RECORD(iface, NSContainer, nsIURIContentListener_iface);
1523 }
1524 
nsURIContentListener_QueryInterface(nsIURIContentListener * iface,nsIIDRef riid,void ** result)1525 static nsresult NSAPI nsURIContentListener_QueryInterface(nsIURIContentListener *iface,
1526         nsIIDRef riid, void **result)
1527 {
1528     NSContainer *This = impl_from_nsIURIContentListener(iface);
1529     return nsIWebBrowserChrome_QueryInterface(&This->nsIWebBrowserChrome_iface, riid, result);
1530 }
1531 
nsURIContentListener_AddRef(nsIURIContentListener * iface)1532 static nsrefcnt NSAPI nsURIContentListener_AddRef(nsIURIContentListener *iface)
1533 {
1534     NSContainer *This = impl_from_nsIURIContentListener(iface);
1535     return nsIWebBrowserChrome_AddRef(&This->nsIWebBrowserChrome_iface);
1536 }
1537 
nsURIContentListener_Release(nsIURIContentListener * iface)1538 static nsrefcnt NSAPI nsURIContentListener_Release(nsIURIContentListener *iface)
1539 {
1540     NSContainer *This = impl_from_nsIURIContentListener(iface);
1541     return nsIWebBrowserChrome_Release(&This->nsIWebBrowserChrome_iface);
1542 }
1543 
nsURIContentListener_OnStartURIOpen(nsIURIContentListener * iface,nsIURI * aURI,cpp_bool * _retval)1544 static nsresult NSAPI nsURIContentListener_OnStartURIOpen(nsIURIContentListener *iface,
1545                                                           nsIURI *aURI, cpp_bool *_retval)
1546 {
1547     NSContainer *This = impl_from_nsIURIContentListener(iface);
1548     nsACString spec_str;
1549     const char *spec;
1550     nsresult nsres;
1551 
1552     nsACString_Init(&spec_str, NULL);
1553     nsIURI_GetSpec(aURI, &spec_str);
1554     nsACString_GetData(&spec_str, &spec);
1555 
1556     TRACE("(%p)->(%p(%s) %p)\n", This, aURI, debugstr_a(spec), _retval);
1557 
1558     nsACString_Finish(&spec_str);
1559 
1560     nsres = on_start_uri_open(This, aURI, _retval);
1561     if(NS_FAILED(nsres))
1562         return nsres;
1563 
1564     return !*_retval && This->content_listener
1565         ? nsIURIContentListener_OnStartURIOpen(This->content_listener, aURI, _retval)
1566         : NS_OK;
1567 }
1568 
nsURIContentListener_DoContent(nsIURIContentListener * iface,const nsACString * aContentType,cpp_bool aIsContentPreferred,nsIRequest * aRequest,nsIStreamListener ** aContentHandler,cpp_bool * _retval)1569 static nsresult NSAPI nsURIContentListener_DoContent(nsIURIContentListener *iface,
1570         const nsACString *aContentType, cpp_bool aIsContentPreferred, nsIRequest *aRequest,
1571         nsIStreamListener **aContentHandler, cpp_bool *_retval)
1572 {
1573     NSContainer *This = impl_from_nsIURIContentListener(iface);
1574 
1575     TRACE("(%p)->(%p %x %p %p %p)\n", This, aContentType, aIsContentPreferred,
1576             aRequest, aContentHandler, _retval);
1577 
1578     return This->content_listener
1579         ? nsIURIContentListener_DoContent(This->content_listener, aContentType,
1580                   aIsContentPreferred, aRequest, aContentHandler, _retval)
1581         : NS_ERROR_NOT_IMPLEMENTED;
1582 }
1583 
nsURIContentListener_IsPreferred(nsIURIContentListener * iface,const char * aContentType,char ** aDesiredContentType,cpp_bool * _retval)1584 static nsresult NSAPI nsURIContentListener_IsPreferred(nsIURIContentListener *iface,
1585         const char *aContentType, char **aDesiredContentType, cpp_bool *_retval)
1586 {
1587     NSContainer *This = impl_from_nsIURIContentListener(iface);
1588 
1589     TRACE("(%p)->(%s %p %p)\n", This, debugstr_a(aContentType), aDesiredContentType, _retval);
1590 
1591     /* FIXME: Should we do something here? */
1592     *_retval = TRUE;
1593 
1594     return This->content_listener
1595         ? nsIURIContentListener_IsPreferred(This->content_listener, aContentType,
1596                   aDesiredContentType, _retval)
1597         : NS_OK;
1598 }
1599 
nsURIContentListener_CanHandleContent(nsIURIContentListener * iface,const char * aContentType,cpp_bool aIsContentPreferred,char ** aDesiredContentType,cpp_bool * _retval)1600 static nsresult NSAPI nsURIContentListener_CanHandleContent(nsIURIContentListener *iface,
1601         const char *aContentType, cpp_bool aIsContentPreferred, char **aDesiredContentType,
1602         cpp_bool *_retval)
1603 {
1604     NSContainer *This = impl_from_nsIURIContentListener(iface);
1605 
1606     TRACE("(%p)->(%s %x %p %p)\n", This, debugstr_a(aContentType), aIsContentPreferred,
1607             aDesiredContentType, _retval);
1608 
1609     return This->content_listener
1610         ? nsIURIContentListener_CanHandleContent(This->content_listener, aContentType,
1611                 aIsContentPreferred, aDesiredContentType, _retval)
1612         : NS_ERROR_NOT_IMPLEMENTED;
1613 }
1614 
nsURIContentListener_GetLoadCookie(nsIURIContentListener * iface,nsISupports ** aLoadCookie)1615 static nsresult NSAPI nsURIContentListener_GetLoadCookie(nsIURIContentListener *iface,
1616         nsISupports **aLoadCookie)
1617 {
1618     NSContainer *This = impl_from_nsIURIContentListener(iface);
1619 
1620     WARN("(%p)->(%p)\n", This, aLoadCookie);
1621 
1622     return This->content_listener
1623         ? nsIURIContentListener_GetLoadCookie(This->content_listener, aLoadCookie)
1624         : NS_ERROR_NOT_IMPLEMENTED;
1625 }
1626 
nsURIContentListener_SetLoadCookie(nsIURIContentListener * iface,nsISupports * aLoadCookie)1627 static nsresult NSAPI nsURIContentListener_SetLoadCookie(nsIURIContentListener *iface,
1628         nsISupports *aLoadCookie)
1629 {
1630     NSContainer *This = impl_from_nsIURIContentListener(iface);
1631 
1632     WARN("(%p)->(%p)\n", This, aLoadCookie);
1633 
1634     return This->content_listener
1635         ? nsIURIContentListener_SetLoadCookie(This->content_listener, aLoadCookie)
1636         : NS_ERROR_NOT_IMPLEMENTED;
1637 }
1638 
nsURIContentListener_GetParentContentListener(nsIURIContentListener * iface,nsIURIContentListener ** aParentContentListener)1639 static nsresult NSAPI nsURIContentListener_GetParentContentListener(nsIURIContentListener *iface,
1640         nsIURIContentListener **aParentContentListener)
1641 {
1642     NSContainer *This = impl_from_nsIURIContentListener(iface);
1643 
1644     TRACE("(%p)->(%p)\n", This, aParentContentListener);
1645 
1646     if(This->content_listener)
1647         nsIURIContentListener_AddRef(This->content_listener);
1648 
1649     *aParentContentListener = This->content_listener;
1650     return NS_OK;
1651 }
1652 
nsURIContentListener_SetParentContentListener(nsIURIContentListener * iface,nsIURIContentListener * aParentContentListener)1653 static nsresult NSAPI nsURIContentListener_SetParentContentListener(nsIURIContentListener *iface,
1654         nsIURIContentListener *aParentContentListener)
1655 {
1656     NSContainer *This = impl_from_nsIURIContentListener(iface);
1657 
1658     TRACE("(%p)->(%p)\n", This, aParentContentListener);
1659 
1660     if(aParentContentListener == &This->nsIURIContentListener_iface)
1661         return NS_OK;
1662 
1663     if(This->content_listener)
1664         nsIURIContentListener_Release(This->content_listener);
1665 
1666     This->content_listener = aParentContentListener;
1667     if(This->content_listener)
1668         nsIURIContentListener_AddRef(This->content_listener);
1669 
1670     return NS_OK;
1671 }
1672 
1673 static const nsIURIContentListenerVtbl nsURIContentListenerVtbl = {
1674     nsURIContentListener_QueryInterface,
1675     nsURIContentListener_AddRef,
1676     nsURIContentListener_Release,
1677     nsURIContentListener_OnStartURIOpen,
1678     nsURIContentListener_DoContent,
1679     nsURIContentListener_IsPreferred,
1680     nsURIContentListener_CanHandleContent,
1681     nsURIContentListener_GetLoadCookie,
1682     nsURIContentListener_SetLoadCookie,
1683     nsURIContentListener_GetParentContentListener,
1684     nsURIContentListener_SetParentContentListener
1685 };
1686 
1687 /**********************************************************
1688  *      nsIEmbeddinSiteWindow interface
1689  */
1690 
impl_from_nsIEmbeddingSiteWindow(nsIEmbeddingSiteWindow * iface)1691 static inline NSContainer *impl_from_nsIEmbeddingSiteWindow(nsIEmbeddingSiteWindow *iface)
1692 {
1693     return CONTAINING_RECORD(iface, NSContainer, nsIEmbeddingSiteWindow_iface);
1694 }
1695 
nsEmbeddingSiteWindow_QueryInterface(nsIEmbeddingSiteWindow * iface,nsIIDRef riid,void ** result)1696 static nsresult NSAPI nsEmbeddingSiteWindow_QueryInterface(nsIEmbeddingSiteWindow *iface,
1697         nsIIDRef riid, void **result)
1698 {
1699     NSContainer *This = impl_from_nsIEmbeddingSiteWindow(iface);
1700     return nsIWebBrowserChrome_QueryInterface(&This->nsIWebBrowserChrome_iface, riid, result);
1701 }
1702 
nsEmbeddingSiteWindow_AddRef(nsIEmbeddingSiteWindow * iface)1703 static nsrefcnt NSAPI nsEmbeddingSiteWindow_AddRef(nsIEmbeddingSiteWindow *iface)
1704 {
1705     NSContainer *This = impl_from_nsIEmbeddingSiteWindow(iface);
1706     return nsIWebBrowserChrome_AddRef(&This->nsIWebBrowserChrome_iface);
1707 }
1708 
nsEmbeddingSiteWindow_Release(nsIEmbeddingSiteWindow * iface)1709 static nsrefcnt NSAPI nsEmbeddingSiteWindow_Release(nsIEmbeddingSiteWindow *iface)
1710 {
1711     NSContainer *This = impl_from_nsIEmbeddingSiteWindow(iface);
1712     return nsIWebBrowserChrome_Release(&This->nsIWebBrowserChrome_iface);
1713 }
1714 
nsEmbeddingSiteWindow_SetDimensions(nsIEmbeddingSiteWindow * iface,UINT32 flags,LONG x,LONG y,LONG cx,LONG cy)1715 static nsresult NSAPI nsEmbeddingSiteWindow_SetDimensions(nsIEmbeddingSiteWindow *iface,
1716         UINT32 flags, LONG x, LONG y, LONG cx, LONG cy)
1717 {
1718     NSContainer *This = impl_from_nsIEmbeddingSiteWindow(iface);
1719     WARN("(%p)->(%08x %d %d %d %d)\n", This, flags, x, y, cx, cy);
1720     return NS_ERROR_NOT_IMPLEMENTED;
1721 }
1722 
nsEmbeddingSiteWindow_GetDimensions(nsIEmbeddingSiteWindow * iface,UINT32 flags,LONG * x,LONG * y,LONG * cx,LONG * cy)1723 static nsresult NSAPI nsEmbeddingSiteWindow_GetDimensions(nsIEmbeddingSiteWindow *iface,
1724         UINT32 flags, LONG *x, LONG *y, LONG *cx, LONG *cy)
1725 {
1726     NSContainer *This = impl_from_nsIEmbeddingSiteWindow(iface);
1727     RECT r;
1728 
1729     TRACE("(%p)->(%x %p %p %p %p)\n", This, flags, x, y, cx, cy);
1730 
1731     if(!GetWindowRect(This->hwnd, &r)) {
1732         ERR("GetWindowRect failed\n");
1733         return NS_ERROR_FAILURE;
1734     }
1735 
1736     if(x)
1737         *x = r.left;
1738     if(y)
1739         *y = r.top;
1740     if(cx)
1741         *cx = r.right-r.left;
1742     if(cy)
1743         *cy = r.bottom-r.top;
1744     return NS_OK;
1745 }
1746 
nsEmbeddingSiteWindow_SetFocus(nsIEmbeddingSiteWindow * iface)1747 static nsresult NSAPI nsEmbeddingSiteWindow_SetFocus(nsIEmbeddingSiteWindow *iface)
1748 {
1749     NSContainer *This = impl_from_nsIEmbeddingSiteWindow(iface);
1750 
1751     TRACE("(%p)\n", This);
1752 
1753     return nsIBaseWindow_SetFocus(This->window);
1754 }
1755 
nsEmbeddingSiteWindow_GetVisibility(nsIEmbeddingSiteWindow * iface,cpp_bool * aVisibility)1756 static nsresult NSAPI nsEmbeddingSiteWindow_GetVisibility(nsIEmbeddingSiteWindow *iface,
1757         cpp_bool *aVisibility)
1758 {
1759     NSContainer *This = impl_from_nsIEmbeddingSiteWindow(iface);
1760 
1761     TRACE("(%p)->(%p)\n", This, aVisibility);
1762 
1763     *aVisibility = This->doc && This->doc->hwnd && IsWindowVisible(This->doc->hwnd);
1764     return NS_OK;
1765 }
1766 
nsEmbeddingSiteWindow_SetVisibility(nsIEmbeddingSiteWindow * iface,cpp_bool aVisibility)1767 static nsresult NSAPI nsEmbeddingSiteWindow_SetVisibility(nsIEmbeddingSiteWindow *iface,
1768         cpp_bool aVisibility)
1769 {
1770     NSContainer *This = impl_from_nsIEmbeddingSiteWindow(iface);
1771 
1772     TRACE("(%p)->(%x)\n", This, aVisibility);
1773 
1774     return NS_OK;
1775 }
1776 
nsEmbeddingSiteWindow_GetTitle(nsIEmbeddingSiteWindow * iface,PRUnichar ** aTitle)1777 static nsresult NSAPI nsEmbeddingSiteWindow_GetTitle(nsIEmbeddingSiteWindow *iface,
1778         PRUnichar **aTitle)
1779 {
1780     NSContainer *This = impl_from_nsIEmbeddingSiteWindow(iface);
1781     WARN("(%p)->(%p)\n", This, aTitle);
1782     return NS_ERROR_NOT_IMPLEMENTED;
1783 }
1784 
nsEmbeddingSiteWindow_SetTitle(nsIEmbeddingSiteWindow * iface,const PRUnichar * aTitle)1785 static nsresult NSAPI nsEmbeddingSiteWindow_SetTitle(nsIEmbeddingSiteWindow *iface,
1786         const PRUnichar *aTitle)
1787 {
1788     NSContainer *This = impl_from_nsIEmbeddingSiteWindow(iface);
1789     WARN("(%p)->(%s)\n", This, debugstr_w(aTitle));
1790     return NS_ERROR_NOT_IMPLEMENTED;
1791 }
1792 
nsEmbeddingSiteWindow_GetSiteWindow(nsIEmbeddingSiteWindow * iface,void ** aSiteWindow)1793 static nsresult NSAPI nsEmbeddingSiteWindow_GetSiteWindow(nsIEmbeddingSiteWindow *iface,
1794         void **aSiteWindow)
1795 {
1796     NSContainer *This = impl_from_nsIEmbeddingSiteWindow(iface);
1797 
1798     TRACE("(%p)->(%p)\n", This, aSiteWindow);
1799 
1800     *aSiteWindow = This->hwnd;
1801     return NS_OK;
1802 }
1803 
1804 static const nsIEmbeddingSiteWindowVtbl nsEmbeddingSiteWindowVtbl = {
1805     nsEmbeddingSiteWindow_QueryInterface,
1806     nsEmbeddingSiteWindow_AddRef,
1807     nsEmbeddingSiteWindow_Release,
1808     nsEmbeddingSiteWindow_SetDimensions,
1809     nsEmbeddingSiteWindow_GetDimensions,
1810     nsEmbeddingSiteWindow_SetFocus,
1811     nsEmbeddingSiteWindow_GetVisibility,
1812     nsEmbeddingSiteWindow_SetVisibility,
1813     nsEmbeddingSiteWindow_GetTitle,
1814     nsEmbeddingSiteWindow_SetTitle,
1815     nsEmbeddingSiteWindow_GetSiteWindow
1816 };
1817 
impl_from_nsITooltipListener(nsITooltipListener * iface)1818 static inline NSContainer *impl_from_nsITooltipListener(nsITooltipListener *iface)
1819 {
1820     return CONTAINING_RECORD(iface, NSContainer, nsITooltipListener_iface);
1821 }
1822 
nsTooltipListener_QueryInterface(nsITooltipListener * iface,nsIIDRef riid,void ** result)1823 static nsresult NSAPI nsTooltipListener_QueryInterface(nsITooltipListener *iface, nsIIDRef riid,
1824         void **result)
1825 {
1826     NSContainer *This = impl_from_nsITooltipListener(iface);
1827     return nsIWebBrowserChrome_QueryInterface(&This->nsIWebBrowserChrome_iface, riid, result);
1828 }
1829 
nsTooltipListener_AddRef(nsITooltipListener * iface)1830 static nsrefcnt NSAPI nsTooltipListener_AddRef(nsITooltipListener *iface)
1831 {
1832     NSContainer *This = impl_from_nsITooltipListener(iface);
1833     return nsIWebBrowserChrome_AddRef(&This->nsIWebBrowserChrome_iface);
1834 }
1835 
nsTooltipListener_Release(nsITooltipListener * iface)1836 static nsrefcnt NSAPI nsTooltipListener_Release(nsITooltipListener *iface)
1837 {
1838     NSContainer *This = impl_from_nsITooltipListener(iface);
1839     return nsIWebBrowserChrome_Release(&This->nsIWebBrowserChrome_iface);
1840 }
1841 
nsTooltipListener_OnShowTooltip(nsITooltipListener * iface,LONG aXCoord,LONG aYCoord,const PRUnichar * aTipText)1842 static nsresult NSAPI nsTooltipListener_OnShowTooltip(nsITooltipListener *iface,
1843         LONG aXCoord, LONG aYCoord, const PRUnichar *aTipText)
1844 {
1845     NSContainer *This = impl_from_nsITooltipListener(iface);
1846 
1847     if (This->doc)
1848         show_tooltip(This->doc, aXCoord, aYCoord, aTipText);
1849 
1850     return NS_OK;
1851 }
1852 
nsTooltipListener_OnHideTooltip(nsITooltipListener * iface)1853 static nsresult NSAPI nsTooltipListener_OnHideTooltip(nsITooltipListener *iface)
1854 {
1855     NSContainer *This = impl_from_nsITooltipListener(iface);
1856 
1857     if (This->doc)
1858         hide_tooltip(This->doc);
1859 
1860     return NS_OK;
1861 }
1862 
1863 static const nsITooltipListenerVtbl nsTooltipListenerVtbl = {
1864     nsTooltipListener_QueryInterface,
1865     nsTooltipListener_AddRef,
1866     nsTooltipListener_Release,
1867     nsTooltipListener_OnShowTooltip,
1868     nsTooltipListener_OnHideTooltip
1869 };
1870 
impl_from_nsIInterfaceRequestor(nsIInterfaceRequestor * iface)1871 static inline NSContainer *impl_from_nsIInterfaceRequestor(nsIInterfaceRequestor *iface)
1872 {
1873     return CONTAINING_RECORD(iface, NSContainer, nsIInterfaceRequestor_iface);
1874 }
1875 
nsInterfaceRequestor_QueryInterface(nsIInterfaceRequestor * iface,nsIIDRef riid,void ** result)1876 static nsresult NSAPI nsInterfaceRequestor_QueryInterface(nsIInterfaceRequestor *iface,
1877         nsIIDRef riid, void **result)
1878 {
1879     NSContainer *This = impl_from_nsIInterfaceRequestor(iface);
1880     return nsIWebBrowserChrome_QueryInterface(&This->nsIWebBrowserChrome_iface, riid, result);
1881 }
1882 
nsInterfaceRequestor_AddRef(nsIInterfaceRequestor * iface)1883 static nsrefcnt NSAPI nsInterfaceRequestor_AddRef(nsIInterfaceRequestor *iface)
1884 {
1885     NSContainer *This = impl_from_nsIInterfaceRequestor(iface);
1886     return nsIWebBrowserChrome_AddRef(&This->nsIWebBrowserChrome_iface);
1887 }
1888 
nsInterfaceRequestor_Release(nsIInterfaceRequestor * iface)1889 static nsrefcnt NSAPI nsInterfaceRequestor_Release(nsIInterfaceRequestor *iface)
1890 {
1891     NSContainer *This = impl_from_nsIInterfaceRequestor(iface);
1892     return nsIWebBrowserChrome_Release(&This->nsIWebBrowserChrome_iface);
1893 }
1894 
nsInterfaceRequestor_GetInterface(nsIInterfaceRequestor * iface,nsIIDRef riid,void ** result)1895 static nsresult NSAPI nsInterfaceRequestor_GetInterface(nsIInterfaceRequestor *iface,
1896         nsIIDRef riid, void **result)
1897 {
1898     NSContainer *This = impl_from_nsIInterfaceRequestor(iface);
1899 
1900     if(IsEqualGUID(&IID_nsIDOMWindow, riid)) {
1901         TRACE("(%p)->(IID_nsIDOMWindow %p)\n", This, result);
1902         return nsIWebBrowser_GetContentDOMWindow(This->webbrowser, (nsIDOMWindow**)result);
1903     }
1904 
1905     return nsIWebBrowserChrome_QueryInterface(&This->nsIWebBrowserChrome_iface, riid, result);
1906 }
1907 
1908 static const nsIInterfaceRequestorVtbl nsInterfaceRequestorVtbl = {
1909     nsInterfaceRequestor_QueryInterface,
1910     nsInterfaceRequestor_AddRef,
1911     nsInterfaceRequestor_Release,
1912     nsInterfaceRequestor_GetInterface
1913 };
1914 
impl_from_nsISupportsWeakReference(nsISupportsWeakReference * iface)1915 static inline NSContainer *impl_from_nsISupportsWeakReference(nsISupportsWeakReference *iface)
1916 {
1917     return CONTAINING_RECORD(iface, NSContainer, nsISupportsWeakReference_iface);
1918 }
1919 
nsSupportsWeakReference_QueryInterface(nsISupportsWeakReference * iface,nsIIDRef riid,void ** result)1920 static nsresult NSAPI nsSupportsWeakReference_QueryInterface(nsISupportsWeakReference *iface,
1921         nsIIDRef riid, void **result)
1922 {
1923     NSContainer *This = impl_from_nsISupportsWeakReference(iface);
1924     return nsIWebBrowserChrome_QueryInterface(&This->nsIWebBrowserChrome_iface, riid, result);
1925 }
1926 
nsSupportsWeakReference_AddRef(nsISupportsWeakReference * iface)1927 static nsrefcnt NSAPI nsSupportsWeakReference_AddRef(nsISupportsWeakReference *iface)
1928 {
1929     NSContainer *This = impl_from_nsISupportsWeakReference(iface);
1930     return nsIWebBrowserChrome_AddRef(&This->nsIWebBrowserChrome_iface);
1931 }
1932 
nsSupportsWeakReference_Release(nsISupportsWeakReference * iface)1933 static nsrefcnt NSAPI nsSupportsWeakReference_Release(nsISupportsWeakReference *iface)
1934 {
1935     NSContainer *This = impl_from_nsISupportsWeakReference(iface);
1936     return nsIWebBrowserChrome_Release(&This->nsIWebBrowserChrome_iface);
1937 }
1938 
nsSupportsWeakReference_GetWeakReference(nsISupportsWeakReference * iface,nsIWeakReference ** _retval)1939 static nsresult NSAPI nsSupportsWeakReference_GetWeakReference(nsISupportsWeakReference *iface,
1940         nsIWeakReference **_retval)
1941 {
1942     NSContainer *This = impl_from_nsISupportsWeakReference(iface);
1943 
1944     TRACE("(%p)->(%p)\n", This, _retval);
1945 
1946     if(!This->weak_reference) {
1947         This->weak_reference = heap_alloc(sizeof(nsWeakReference));
1948         if(!This->weak_reference)
1949             return NS_ERROR_OUT_OF_MEMORY;
1950 
1951         This->weak_reference->nsIWeakReference_iface.lpVtbl = &nsWeakReferenceVtbl;
1952         This->weak_reference->ref = 1;
1953         This->weak_reference->nscontainer = This;
1954     }
1955 
1956     *_retval = &This->weak_reference->nsIWeakReference_iface;
1957     nsIWeakReference_AddRef(*_retval);
1958     return NS_OK;
1959 }
1960 
1961 static const nsISupportsWeakReferenceVtbl nsSupportsWeakReferenceVtbl = {
1962     nsSupportsWeakReference_QueryInterface,
1963     nsSupportsWeakReference_AddRef,
1964     nsSupportsWeakReference_Release,
1965     nsSupportsWeakReference_GetWeakReference
1966 };
1967 
init_nscontainer(NSContainer * nscontainer)1968 static HRESULT init_nscontainer(NSContainer *nscontainer)
1969 {
1970     nsIWebBrowserSetup *wbsetup;
1971     nsIScrollable *scrollable;
1972     nsresult nsres;
1973 
1974     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_WEBBROWSER_CONTRACTID,
1975             NULL, &IID_nsIWebBrowser, (void**)&nscontainer->webbrowser);
1976     if(NS_FAILED(nsres)) {
1977         ERR("Creating WebBrowser failed: %08x\n", nsres);
1978         return E_FAIL;
1979     }
1980 
1981     nsres = nsIWebBrowser_SetContainerWindow(nscontainer->webbrowser, &nscontainer->nsIWebBrowserChrome_iface);
1982     if(NS_FAILED(nsres)) {
1983         ERR("SetContainerWindow failed: %08x\n", nsres);
1984         return E_FAIL;
1985     }
1986 
1987     nsres = nsIWebBrowser_QueryInterface(nscontainer->webbrowser, &IID_nsIBaseWindow,
1988             (void**)&nscontainer->window);
1989     if(NS_FAILED(nsres)) {
1990         ERR("Could not get nsIBaseWindow interface: %08x\n", nsres);
1991         return E_FAIL;
1992     }
1993 
1994     nsres = nsIWebBrowser_QueryInterface(nscontainer->webbrowser, &IID_nsIWebBrowserSetup,
1995                                          (void**)&wbsetup);
1996     if(NS_SUCCEEDED(nsres)) {
1997         nsres = nsIWebBrowserSetup_SetProperty(wbsetup, SETUP_IS_CHROME_WRAPPER, FALSE);
1998         nsIWebBrowserSetup_Release(wbsetup);
1999         if(NS_FAILED(nsres)) {
2000             ERR("SetProperty(SETUP_IS_CHROME_WRAPPER) failed: %08x\n", nsres);
2001             return E_FAIL;
2002         }
2003     }else {
2004         ERR("Could not get nsIWebBrowserSetup interface\n");
2005         return E_FAIL;
2006     }
2007 
2008     nsres = nsIWebBrowser_QueryInterface(nscontainer->webbrowser, &IID_nsIWebNavigation,
2009             (void**)&nscontainer->navigation);
2010     if(NS_FAILED(nsres)) {
2011         ERR("Could not get nsIWebNavigation interface: %08x\n", nsres);
2012         return E_FAIL;
2013     }
2014 
2015     nsres = nsIWebBrowser_QueryInterface(nscontainer->webbrowser, &IID_nsIWebBrowserFocus,
2016             (void**)&nscontainer->focus);
2017     if(NS_FAILED(nsres)) {
2018         ERR("Could not get nsIWebBrowserFocus interface: %08x\n", nsres);
2019         return E_FAIL;
2020     }
2021 
2022     if(!nscontainer_class) {
2023         register_nscontainer_class();
2024         if(!nscontainer_class)
2025             return E_FAIL;
2026     }
2027 
2028     nscontainer->hwnd = CreateWindowExW(0, wszNsContainer, NULL,
2029             WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, 100, 100,
2030             GetDesktopWindow(), NULL, hInst, nscontainer);
2031     if(!nscontainer->hwnd) {
2032         WARN("Could not create window\n");
2033         return E_FAIL;
2034     }
2035 
2036     nsres = nsIBaseWindow_InitWindow(nscontainer->window, nscontainer->hwnd, NULL, 0, 0, 100, 100);
2037     if(NS_SUCCEEDED(nsres)) {
2038         nsres = nsIBaseWindow_Create(nscontainer->window);
2039         if(NS_FAILED(nsres)) {
2040             WARN("Creating window failed: %08x\n", nsres);
2041             return E_FAIL;
2042         }
2043 
2044         nsIBaseWindow_SetVisibility(nscontainer->window, FALSE);
2045         nsIBaseWindow_SetEnabled(nscontainer->window, FALSE);
2046     }else {
2047         ERR("InitWindow failed: %08x\n", nsres);
2048         return E_FAIL;
2049     }
2050 
2051     nsres = nsIWebBrowser_SetParentURIContentListener(nscontainer->webbrowser,
2052             &nscontainer->nsIURIContentListener_iface);
2053     if(NS_FAILED(nsres))
2054         ERR("SetParentURIContentListener failed: %08x\n", nsres);
2055 
2056     nsres = nsIWebBrowser_QueryInterface(nscontainer->webbrowser, &IID_nsIScrollable, (void**)&scrollable);
2057     if(NS_SUCCEEDED(nsres)) {
2058         nsres = nsIScrollable_SetDefaultScrollbarPreferences(scrollable,
2059                 ScrollOrientation_Y, Scrollbar_Always);
2060         if(NS_FAILED(nsres))
2061             ERR("Could not set default Y scrollbar prefs: %08x\n", nsres);
2062 
2063         nsres = nsIScrollable_SetDefaultScrollbarPreferences(scrollable,
2064                 ScrollOrientation_X, Scrollbar_Auto);
2065         if(NS_FAILED(nsres))
2066             ERR("Could not set default X scrollbar prefs: %08x\n", nsres);
2067 
2068         nsIScrollable_Release(scrollable);
2069     }else {
2070         ERR("Could not get nsIScrollable: %08x\n", nsres);
2071     }
2072 
2073     return S_OK;
2074 }
2075 
create_nscontainer(HTMLDocumentObj * doc,NSContainer ** _ret)2076 HRESULT create_nscontainer(HTMLDocumentObj *doc, NSContainer **_ret)
2077 {
2078     NSContainer *ret;
2079     HRESULT hres;
2080 
2081     if(!load_gecko())
2082         return CLASS_E_CLASSNOTAVAILABLE;
2083 
2084     ret = heap_alloc_zero(sizeof(NSContainer));
2085     if(!ret)
2086         return E_OUTOFMEMORY;
2087 
2088     ret->nsIWebBrowserChrome_iface.lpVtbl = &nsWebBrowserChromeVtbl;
2089     ret->nsIContextMenuListener_iface.lpVtbl = &nsContextMenuListenerVtbl;
2090     ret->nsIURIContentListener_iface.lpVtbl = &nsURIContentListenerVtbl;
2091     ret->nsIEmbeddingSiteWindow_iface.lpVtbl = &nsEmbeddingSiteWindowVtbl;
2092     ret->nsITooltipListener_iface.lpVtbl = &nsTooltipListenerVtbl;
2093     ret->nsIInterfaceRequestor_iface.lpVtbl = &nsInterfaceRequestorVtbl;
2094     ret->nsISupportsWeakReference_iface.lpVtbl = &nsSupportsWeakReferenceVtbl;
2095 
2096     ret->doc = doc;
2097     ret->ref = 1;
2098 
2099     hres = init_nscontainer(ret);
2100     if(SUCCEEDED(hres))
2101         *_ret = ret;
2102     else
2103         nsIWebBrowserChrome_Release(&ret->nsIWebBrowserChrome_iface);
2104     return hres;
2105 }
2106 
NSContainer_Release(NSContainer * This)2107 void NSContainer_Release(NSContainer *This)
2108 {
2109     TRACE("(%p)\n", This);
2110 
2111     This->doc = NULL;
2112 
2113     ShowWindow(This->hwnd, SW_HIDE);
2114     SetParent(This->hwnd, NULL);
2115 
2116     nsIBaseWindow_SetVisibility(This->window, FALSE);
2117     nsIBaseWindow_Destroy(This->window);
2118 
2119     nsIWebBrowser_SetContainerWindow(This->webbrowser, NULL);
2120 
2121     nsIWebBrowser_Release(This->webbrowser);
2122     This->webbrowser = NULL;
2123 
2124     nsIWebNavigation_Release(This->navigation);
2125     This->navigation = NULL;
2126 
2127     nsIBaseWindow_Release(This->window);
2128     This->window = NULL;
2129 
2130     nsIWebBrowserFocus_Release(This->focus);
2131     This->focus = NULL;
2132 
2133     if(This->editor_controller) {
2134         nsIController_Release(This->editor_controller);
2135         This->editor_controller = NULL;
2136     }
2137 
2138     if(This->editor) {
2139         nsIEditor_Release(This->editor);
2140         This->editor = NULL;
2141     }
2142 
2143     if(This->content_listener) {
2144         nsIURIContentListener_Release(This->content_listener);
2145         This->content_listener = NULL;
2146     }
2147 
2148     if(This->hwnd) {
2149         DestroyWindow(This->hwnd);
2150         This->hwnd = NULL;
2151     }
2152 
2153     nsIWebBrowserChrome_Release(&This->nsIWebBrowserChrome_iface);
2154 }
2155 
create_nsxhr(nsIDOMWindow * nswindow)2156 nsIXMLHttpRequest *create_nsxhr(nsIDOMWindow *nswindow)
2157 {
2158     nsIScriptSecurityManager *secman;
2159     nsIPrincipal             *nspri;
2160     nsIGlobalObject          *nsglo;
2161     nsIXMLHttpRequest        *nsxhr;
2162     nsresult                  nsres;
2163 
2164     nsres = nsIServiceManager_GetServiceByContractID(pServMgr,
2165             NS_SCRIPTSECURITYMANAGER_CONTRACTID,
2166             &IID_nsIScriptSecurityManager, (void**)&secman);
2167     if(NS_FAILED(nsres)) {
2168         ERR("Could not get sec manager service: %08x\n", nsres);
2169         return NULL;
2170     }
2171 
2172     nsres = nsIScriptSecurityManager_GetSystemPrincipal(secman, &nspri);
2173     nsIScriptSecurityManager_Release(secman);
2174     if(NS_FAILED(nsres)) {
2175         ERR("GetSystemPrincipal failed: %08x\n", nsres);
2176         return NULL;
2177     }
2178 
2179     nsres = nsIDOMWindow_QueryInterface(nswindow, &IID_nsIGlobalObject, (void **)&nsglo);
2180     assert(nsres == NS_OK);
2181 
2182     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
2183             NS_XMLHTTPREQUEST_CONTRACTID, NULL, &IID_nsIXMLHttpRequest,
2184             (void**)&nsxhr);
2185     if(NS_FAILED(nsres)) {
2186         ERR("Could not get nsIXMLHttpRequest: %08x\n", nsres);
2187         nsISupports_Release(nspri);
2188         nsIGlobalObject_Release(nsglo);
2189         return NULL;
2190     }
2191 
2192     nsres = nsIXMLHttpRequest_Init(nsxhr, nspri, NULL, nsglo, NULL, NULL);
2193 
2194     nsISupports_Release(nspri);
2195     nsIGlobalObject_Release(nsglo);
2196     if(NS_FAILED(nsres)) {
2197         ERR("nsIXMLHttpRequest_Init failed: %08x\n", nsres);
2198         nsIXMLHttpRequest_Release(nsxhr);
2199         return NULL;
2200     }
2201     return nsxhr;
2202 }
2203