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