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