Reactos
at master 798 lines 24 kB view raw
1/* 2 * Copyright 2008 Jacek Caban for CodeWeavers 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19#include "mshtml_private.h" 20 21#define IE_MAJOR_VERSION 7 22#define IE_MINOR_VERSION 0 23 24static const IID NS_ICONTENTUTILS_CID = 25 {0x762C4AE7,0xB923,0x422F,{0xB9,0x7E,0xB9,0xBF,0xC1,0xEF,0x7B,0xF0}}; 26 27static nsIContentUtils *content_utils; 28 29static PRUnichar *handle_insert_comment(HTMLDocumentNode *doc, const PRUnichar *comment) 30{ 31 int majorv = 0, minorv = 0; 32 const PRUnichar *ptr, *end; 33 PRUnichar *buf; 34 DWORD len; 35 36 enum { 37 CMP_EQ, 38 CMP_LT, 39 CMP_LTE, 40 CMP_GT, 41 CMP_GTE 42 } cmpt = CMP_EQ; 43 44 static const PRUnichar endifW[] = {'<','!','[','e','n','d','i','f',']'}; 45 46 if(comment[0] != '[' || comment[1] != 'i' || comment[2] != 'f') 47 return NULL; 48 49 ptr = comment+3; 50 while(isspaceW(*ptr)) 51 ptr++; 52 53 if(ptr[0] == 'l' && ptr[1] == 't') { 54 ptr += 2; 55 if(*ptr == 'e') { 56 cmpt = CMP_LTE; 57 ptr++; 58 }else { 59 cmpt = CMP_LT; 60 } 61 }else if(ptr[0] == 'g' && ptr[1] == 't') { 62 ptr += 2; 63 if(*ptr == 'e') { 64 cmpt = CMP_GTE; 65 ptr++; 66 }else { 67 cmpt = CMP_GT; 68 } 69 } 70 71 if(!isspaceW(*ptr++)) 72 return NULL; 73 while(isspaceW(*ptr)) 74 ptr++; 75 76 if(ptr[0] != 'I' || ptr[1] != 'E') 77 return NULL; 78 79 ptr +=2; 80 if(!isspaceW(*ptr++)) 81 return NULL; 82 while(isspaceW(*ptr)) 83 ptr++; 84 85 if(!isdigitW(*ptr)) 86 return NULL; 87 while(isdigitW(*ptr)) 88 majorv = majorv*10 + (*ptr++ - '0'); 89 90 if(*ptr == '.') { 91 ptr++; 92 if(!isdigitW(*ptr)) 93 return NULL; 94 while(isdigitW(*ptr)) 95 minorv = minorv*10 + (*ptr++ - '0'); 96 } 97 98 while(isspaceW(*ptr)) 99 ptr++; 100 if(ptr[0] != ']' || ptr[1] != '>') 101 return NULL; 102 ptr += 2; 103 104 len = strlenW(ptr); 105 if(len < sizeof(endifW)/sizeof(WCHAR)) 106 return NULL; 107 108 end = ptr + len-sizeof(endifW)/sizeof(WCHAR); 109 if(memcmp(end, endifW, sizeof(endifW))) 110 return NULL; 111 112 switch(cmpt) { 113 case CMP_EQ: 114 if(majorv == IE_MAJOR_VERSION && minorv == IE_MINOR_VERSION) 115 break; 116 return NULL; 117 case CMP_LT: 118 if(majorv > IE_MAJOR_VERSION) 119 break; 120 if(majorv == IE_MAJOR_VERSION && minorv > IE_MINOR_VERSION) 121 break; 122 return NULL; 123 case CMP_LTE: 124 if(majorv > IE_MAJOR_VERSION) 125 break; 126 if(majorv == IE_MAJOR_VERSION && minorv >= IE_MINOR_VERSION) 127 break; 128 return NULL; 129 case CMP_GT: 130 if(majorv < IE_MAJOR_VERSION) 131 break; 132 if(majorv == IE_MAJOR_VERSION && minorv < IE_MINOR_VERSION) 133 break; 134 return NULL; 135 case CMP_GTE: 136 if(majorv < IE_MAJOR_VERSION) 137 break; 138 if(majorv == IE_MAJOR_VERSION && minorv <= IE_MINOR_VERSION) 139 break; 140 return NULL; 141 } 142 143 buf = heap_alloc((end-ptr+1)*sizeof(WCHAR)); 144 if(!buf) 145 return NULL; 146 147 memcpy(buf, ptr, (end-ptr)*sizeof(WCHAR)); 148 buf[end-ptr] = 0; 149 150 return buf; 151} 152 153static nsresult run_insert_comment(HTMLDocumentNode *doc, nsISupports *comment_iface, nsISupports *arg2) 154{ 155 const PRUnichar *comment; 156 nsIDOMComment *nscomment; 157 PRUnichar *replace_html; 158 nsAString comment_str; 159 nsresult nsres; 160 161 nsres = nsISupports_QueryInterface(comment_iface, &IID_nsIDOMComment, (void**)&nscomment); 162 if(NS_FAILED(nsres)) { 163 ERR("Could not get nsIDOMComment iface:%08x\n", nsres); 164 return nsres; 165 } 166 167 nsAString_Init(&comment_str, NULL); 168 nsres = nsIDOMComment_GetData(nscomment, &comment_str); 169 if(NS_FAILED(nsres)) 170 return nsres; 171 172 nsAString_GetData(&comment_str, &comment); 173 replace_html = handle_insert_comment(doc, comment); 174 nsAString_Finish(&comment_str); 175 176 if(replace_html) { 177 HRESULT hres; 178 179 hres = replace_node_by_html(doc->nsdoc, (nsIDOMNode*)nscomment, replace_html); 180 heap_free(replace_html); 181 if(FAILED(hres)) 182 nsres = NS_ERROR_FAILURE; 183 } 184 185 186 nsIDOMComment_Release(nscomment); 187 return nsres; 188} 189 190static nsresult run_bind_to_tree(HTMLDocumentNode *doc, nsISupports *nsiface, nsISupports *arg2) 191{ 192 nsIDOMNode *nsnode; 193 HTMLDOMNode *node; 194 nsresult nsres; 195 HRESULT hres; 196 197 TRACE("(%p)->(%p)\n", doc, nsiface); 198 199 nsres = nsISupports_QueryInterface(nsiface, &IID_nsIDOMNode, (void**)&nsnode); 200 if(NS_FAILED(nsres)) 201 return nsres; 202 203 hres = get_node(doc, nsnode, TRUE, &node); 204 nsIDOMNode_Release(nsnode); 205 if(FAILED(hres)) { 206 ERR("Could not get node\n"); 207 return nsres; 208 } 209 210 if(node->vtbl->bind_to_tree) 211 node->vtbl->bind_to_tree(node); 212 213 node_release(node); 214 return nsres; 215} 216 217/* Calls undocumented 69 cmd of CGID_Explorer */ 218static void call_explorer_69(HTMLDocumentObj *doc) 219{ 220 IOleCommandTarget *olecmd; 221 VARIANT var; 222 HRESULT hres; 223 224 if(!doc->client) 225 return; 226 227 hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd); 228 if(FAILED(hres)) 229 return; 230 231 VariantInit(&var); 232 hres = IOleCommandTarget_Exec(olecmd, &CGID_Explorer, 69, 0, NULL, &var); 233 IOleCommandTarget_Release(olecmd); 234 if(SUCCEEDED(hres) && V_VT(&var) != VT_NULL) 235 FIXME("handle result\n"); 236} 237 238static void parse_complete(HTMLDocumentObj *doc) 239{ 240 TRACE("(%p)\n", doc); 241 242 if(doc->usermode == EDITMODE) 243 init_editor(&doc->basedoc); 244 245 call_explorer_69(doc); 246 if(doc->view_sink) 247 IAdviseSink_OnViewChange(doc->view_sink, DVASPECT_CONTENT, -1); 248 call_property_onchanged(&doc->basedoc.cp_container, 1005); 249 call_explorer_69(doc); 250 251 if(doc->webbrowser && doc->usermode != EDITMODE && !(doc->basedoc.window->load_flags & BINDING_REFRESH)) 252 IDocObjectService_FireNavigateComplete2(doc->doc_object_service, &doc->basedoc.window->base.IHTMLWindow2_iface, 0); 253 254 /* FIXME: IE7 calls EnableModelless(TRUE), EnableModelless(FALSE) and sets interactive state here */ 255} 256 257static nsresult run_end_load(HTMLDocumentNode *This, nsISupports *arg1, nsISupports *arg2) 258{ 259 TRACE("(%p)\n", This); 260 261 if(!This->basedoc.doc_obj) 262 return NS_OK; 263 264 if(This == This->basedoc.doc_obj->basedoc.doc_node) { 265 /* 266 * This should be done in the worker thread that parses HTML, 267 * but we don't have such thread (Gecko parses HTML for us). 268 */ 269 parse_complete(This->basedoc.doc_obj); 270 } 271 272 bind_event_scripts(This); 273 set_ready_state(This->basedoc.window, READYSTATE_INTERACTIVE); 274 return NS_OK; 275} 276 277static nsresult run_insert_script(HTMLDocumentNode *doc, nsISupports *script_iface, nsISupports *parser_iface) 278{ 279 nsIDOMHTMLScriptElement *nsscript; 280 HTMLScriptElement *script_elem; 281 nsIParser *nsparser = NULL; 282 script_queue_entry_t *iter; 283 HTMLInnerWindow *window; 284 nsresult nsres; 285 HRESULT hres; 286 287 TRACE("(%p)->(%p)\n", doc, script_iface); 288 289 window = doc->window; 290 if(!window) 291 return NS_OK; 292 293 nsres = nsISupports_QueryInterface(script_iface, &IID_nsIDOMHTMLScriptElement, (void**)&nsscript); 294 if(NS_FAILED(nsres)) { 295 ERR("Could not get nsIDOMHTMLScriptElement: %08x\n", nsres); 296 return nsres; 297 } 298 299 if(parser_iface) { 300 nsres = nsISupports_QueryInterface(parser_iface, &IID_nsIParser, (void**)&nsparser); 301 if(NS_FAILED(nsres)) { 302 ERR("Could not get nsIParser iface: %08x\n", nsres); 303 nsparser = NULL; 304 } 305 } 306 307 hres = script_elem_from_nsscript(doc, nsscript, &script_elem); 308 nsIDOMHTMLScriptElement_Release(nsscript); 309 if(FAILED(hres)) 310 return NS_ERROR_FAILURE; 311 312 if(nsparser) { 313 nsIParser_BeginEvaluatingParserInsertedScript(nsparser); 314 window->parser_callback_cnt++; 315 } 316 317 IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); 318 319 doc_insert_script(window, script_elem); 320 321 while(!list_empty(&window->script_queue)) { 322 iter = LIST_ENTRY(list_head(&window->script_queue), script_queue_entry_t, entry); 323 list_remove(&iter->entry); 324 if(!iter->script->parsed) 325 doc_insert_script(window, iter->script); 326 IHTMLScriptElement_Release(&iter->script->IHTMLScriptElement_iface); 327 heap_free(iter); 328 } 329 330 IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); 331 332 if(nsparser) { 333 window->parser_callback_cnt--; 334 nsIParser_EndEvaluatingParserInsertedScript(nsparser); 335 nsIParser_Release(nsparser); 336 } 337 338 IHTMLScriptElement_Release(&script_elem->IHTMLScriptElement_iface); 339 340 return NS_OK; 341} 342 343typedef struct nsRunnable nsRunnable; 344 345typedef nsresult (*runnable_proc_t)(HTMLDocumentNode*,nsISupports*,nsISupports*); 346 347struct nsRunnable { 348 nsIRunnable nsIRunnable_iface; 349 350 LONG ref; 351 352 runnable_proc_t proc; 353 354 HTMLDocumentNode *doc; 355 nsISupports *arg1; 356 nsISupports *arg2; 357}; 358 359static inline nsRunnable *impl_from_nsIRunnable(nsIRunnable *iface) 360{ 361 return CONTAINING_RECORD(iface, nsRunnable, nsIRunnable_iface); 362} 363 364static nsresult NSAPI nsRunnable_QueryInterface(nsIRunnable *iface, 365 nsIIDRef riid, void **result) 366{ 367 nsRunnable *This = impl_from_nsIRunnable(iface); 368 369 if(IsEqualGUID(riid, &IID_nsISupports)) { 370 TRACE("(%p)->(IID_nsISupports %p)\n", This, result); 371 *result = &This->nsIRunnable_iface; 372 }else if(IsEqualGUID(riid, &IID_nsIRunnable)) { 373 TRACE("(%p)->(IID_nsIRunnable %p)\n", This, result); 374 *result = &This->nsIRunnable_iface; 375 }else { 376 *result = NULL; 377 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), result); 378 return NS_NOINTERFACE; 379 } 380 381 nsISupports_AddRef((nsISupports*)*result); 382 return NS_OK; 383} 384 385static nsrefcnt NSAPI nsRunnable_AddRef(nsIRunnable *iface) 386{ 387 nsRunnable *This = impl_from_nsIRunnable(iface); 388 LONG ref = InterlockedIncrement(&This->ref); 389 390 TRACE("(%p) ref=%d\n", This, ref); 391 392 return ref; 393} 394 395static nsrefcnt NSAPI nsRunnable_Release(nsIRunnable *iface) 396{ 397 nsRunnable *This = impl_from_nsIRunnable(iface); 398 LONG ref = InterlockedDecrement(&This->ref); 399 400 TRACE("(%p) ref=%d\n", This, ref); 401 402 if(!ref) { 403 htmldoc_release(&This->doc->basedoc); 404 if(This->arg1) 405 nsISupports_Release(This->arg1); 406 if(This->arg2) 407 nsISupports_Release(This->arg2); 408 heap_free(This); 409 } 410 411 return ref; 412} 413 414static nsresult NSAPI nsRunnable_Run(nsIRunnable *iface) 415{ 416 nsRunnable *This = impl_from_nsIRunnable(iface); 417 418 return This->proc(This->doc, This->arg1, This->arg2); 419} 420 421static const nsIRunnableVtbl nsRunnableVtbl = { 422 nsRunnable_QueryInterface, 423 nsRunnable_AddRef, 424 nsRunnable_Release, 425 nsRunnable_Run 426}; 427 428static void add_script_runner(HTMLDocumentNode *This, runnable_proc_t proc, nsISupports *arg1, nsISupports *arg2) 429{ 430 nsRunnable *runnable; 431 432 runnable = heap_alloc_zero(sizeof(*runnable)); 433 if(!runnable) 434 return; 435 436 runnable->nsIRunnable_iface.lpVtbl = &nsRunnableVtbl; 437 runnable->ref = 1; 438 439 htmldoc_addref(&This->basedoc); 440 runnable->doc = This; 441 runnable->proc = proc; 442 443 if(arg1) 444 nsISupports_AddRef(arg1); 445 runnable->arg1 = arg1; 446 447 if(arg2) 448 nsISupports_AddRef(arg2); 449 runnable->arg2 = arg2; 450 451 nsIContentUtils_AddScriptRunner(content_utils, &runnable->nsIRunnable_iface); 452 453 nsIRunnable_Release(&runnable->nsIRunnable_iface); 454} 455 456static inline HTMLDocumentNode *impl_from_nsIDocumentObserver(nsIDocumentObserver *iface) 457{ 458 return CONTAINING_RECORD(iface, HTMLDocumentNode, nsIDocumentObserver_iface); 459} 460 461static nsresult NSAPI nsDocumentObserver_QueryInterface(nsIDocumentObserver *iface, 462 nsIIDRef riid, void **result) 463{ 464 HTMLDocumentNode *This = impl_from_nsIDocumentObserver(iface); 465 466 if(IsEqualGUID(&IID_nsISupports, riid)) { 467 TRACE("(%p)->(IID_nsISupports, %p)\n", This, result); 468 *result = &This->nsIDocumentObserver_iface; 469 }else if(IsEqualGUID(&IID_nsIMutationObserver, riid)) { 470 TRACE("(%p)->(IID_nsIMutationObserver %p)\n", This, result); 471 *result = &This->nsIDocumentObserver_iface; 472 }else if(IsEqualGUID(&IID_nsIDocumentObserver, riid)) { 473 TRACE("(%p)->(IID_nsIDocumentObserver %p)\n", This, result); 474 *result = &This->nsIDocumentObserver_iface; 475 }else { 476 *result = NULL; 477 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result); 478 return NS_NOINTERFACE; 479 } 480 481 htmldoc_addref(&This->basedoc); 482 return NS_OK; 483} 484 485static nsrefcnt NSAPI nsDocumentObserver_AddRef(nsIDocumentObserver *iface) 486{ 487 HTMLDocumentNode *This = impl_from_nsIDocumentObserver(iface); 488 return htmldoc_addref(&This->basedoc); 489} 490 491static nsrefcnt NSAPI nsDocumentObserver_Release(nsIDocumentObserver *iface) 492{ 493 HTMLDocumentNode *This = impl_from_nsIDocumentObserver(iface); 494 return htmldoc_release(&This->basedoc); 495} 496 497static void NSAPI nsDocumentObserver_CharacterDataWillChange(nsIDocumentObserver *iface, 498 nsIDocument *aDocument, nsIContent *aContent, void /*CharacterDataChangeInfo*/ *aInfo) 499{ 500} 501 502static void NSAPI nsDocumentObserver_CharacterDataChanged(nsIDocumentObserver *iface, 503 nsIDocument *aDocument, nsIContent *aContent, void /*CharacterDataChangeInfo*/ *aInfo) 504{ 505} 506 507static void NSAPI nsDocumentObserver_AttributeWillChange(nsIDocumentObserver *iface, nsIDocument *aDocument, 508 nsIContent *aContent, LONG aNameSpaceID, nsIAtom *aAttribute, LONG aModType) 509{ 510} 511 512static void NSAPI nsDocumentObserver_AttributeChanged(nsIDocumentObserver *iface, nsIDocument *aDocument, 513 nsIContent *aContent, LONG aNameSpaceID, nsIAtom *aAttribute, LONG aModType) 514{ 515} 516 517static void NSAPI nsDocumentObserver_AttributeSetToCurrentValue(nsIDocumentObserver *iface, nsIDocument *aDocument, 518 void *aElement, LONG aNameSpaceID, nsIAtom *aAttribute) 519{ 520} 521 522static void NSAPI nsDocumentObserver_ContentAppended(nsIDocumentObserver *iface, nsIDocument *aDocument, 523 nsIContent *aContainer, nsIContent *aFirstNewContent, LONG aNewIndexInContainer) 524{ 525} 526 527static void NSAPI nsDocumentObserver_ContentInserted(nsIDocumentObserver *iface, nsIDocument *aDocument, 528 nsIContent *aContainer, nsIContent *aChild, LONG aIndexInContainer) 529{ 530} 531 532static void NSAPI nsDocumentObserver_ContentRemoved(nsIDocumentObserver *iface, nsIDocument *aDocument, 533 nsIContent *aContainer, nsIContent *aChild, LONG aIndexInContainer, 534 nsIContent *aProviousSibling) 535{ 536} 537 538static void NSAPI nsDocumentObserver_NodeWillBeDestroyed(nsIDocumentObserver *iface, const nsINode *aNode) 539{ 540} 541 542static void NSAPI nsDocumentObserver_ParentChainChanged(nsIDocumentObserver *iface, nsIContent *aContent) 543{ 544} 545 546static void NSAPI nsDocumentObserver_BeginUpdate(nsIDocumentObserver *iface, nsIDocument *aDocument, 547 nsUpdateType aUpdateType) 548{ 549} 550 551static void NSAPI nsDocumentObserver_EndUpdate(nsIDocumentObserver *iface, nsIDocument *aDocument, 552 nsUpdateType aUpdateType) 553{ 554} 555 556static void NSAPI nsDocumentObserver_BeginLoad(nsIDocumentObserver *iface, nsIDocument *aDocument) 557{ 558} 559 560static void NSAPI nsDocumentObserver_EndLoad(nsIDocumentObserver *iface, nsIDocument *aDocument) 561{ 562 HTMLDocumentNode *This = impl_from_nsIDocumentObserver(iface); 563 564 TRACE("(%p)\n", This); 565 566 if(This->skip_mutation_notif) 567 return; 568 569 This->content_ready = TRUE; 570 add_script_runner(This, run_end_load, NULL, NULL); 571} 572 573static void NSAPI nsDocumentObserver_ContentStatesChanged(nsIDocumentObserver *iface, nsIDocument *aDocument, 574 nsIContent *aContent, EventStates aStateMask) 575{ 576} 577 578static void NSAPI nsDocumentObserver_DocumentStatesChanged(nsIDocumentObserver *iface, nsIDocument *aDocument, 579 EventStates aStateMask) 580{ 581} 582 583static void NSAPI nsDocumentObserver_StyleSheetAdded(nsIDocumentObserver *iface, nsIDocument *aDocument, 584 nsIStyleSheet *aStyleSheet, cpp_bool aDocumentSheet) 585{ 586} 587 588static void NSAPI nsDocumentObserver_StyleSheetRemoved(nsIDocumentObserver *iface, nsIDocument *aDocument, 589 nsIStyleSheet *aStyleSheet, cpp_bool aDocumentSheet) 590{ 591} 592 593static void NSAPI nsDocumentObserver_StyleSheetApplicableStateChanged(nsIDocumentObserver *iface, 594 nsIDocument *aDocument, nsIStyleSheet *aStyleSheet, cpp_bool aApplicable) 595{ 596} 597 598static void NSAPI nsDocumentObserver_StyleRuleChanged(nsIDocumentObserver *iface, nsIDocument *aDocument, 599 nsIStyleSheet *aStyleSheet, nsIStyleRule *aOldStyleRule, nsIStyleSheet *aNewStyleRule) 600{ 601} 602 603static void NSAPI nsDocumentObserver_StyleRuleAdded(nsIDocumentObserver *iface, nsIDocument *aDocument, 604 nsIStyleSheet *aStyleSheet, nsIStyleRule *aStyleRule) 605{ 606} 607 608static void NSAPI nsDocumentObserver_StyleRuleRemoved(nsIDocumentObserver *iface, nsIDocument *aDocument, 609 nsIStyleSheet *aStyleSheet, nsIStyleRule *aStyleRule) 610{ 611} 612 613static void NSAPI nsDocumentObserver_BindToDocument(nsIDocumentObserver *iface, nsIDocument *aDocument, 614 nsIContent *aContent) 615{ 616 HTMLDocumentNode *This = impl_from_nsIDocumentObserver(iface); 617 nsIDOMHTMLIFrameElement *nsiframe; 618 nsIDOMHTMLFrameElement *nsframe; 619 nsIDOMHTMLScriptElement *nsscript; 620 nsIDOMHTMLElement *nselem; 621 nsIDOMComment *nscomment; 622 nsresult nsres; 623 624 TRACE("(%p)->(%p %p)\n", This, aDocument, aContent); 625 626 nsres = nsIContent_QueryInterface(aContent, &IID_nsIDOMHTMLElement, (void**)&nselem); 627 if(NS_SUCCEEDED(nsres)) { 628 check_event_attr(This, nselem); 629 nsIDOMHTMLElement_Release(nselem); 630 } 631 632 nsres = nsIContent_QueryInterface(aContent, &IID_nsIDOMComment, (void**)&nscomment); 633 if(NS_SUCCEEDED(nsres)) { 634 TRACE("comment node\n"); 635 636 add_script_runner(This, run_insert_comment, (nsISupports*)nscomment, NULL); 637 nsIDOMComment_Release(nscomment); 638 return; 639 } 640 641 nsres = nsIContent_QueryInterface(aContent, &IID_nsIDOMHTMLIFrameElement, (void**)&nsiframe); 642 if(NS_SUCCEEDED(nsres)) { 643 TRACE("iframe node\n"); 644 645 add_script_runner(This, run_bind_to_tree, (nsISupports*)nsiframe, NULL); 646 nsIDOMHTMLIFrameElement_Release(nsiframe); 647 return; 648 } 649 650 nsres = nsIContent_QueryInterface(aContent, &IID_nsIDOMHTMLFrameElement, (void**)&nsframe); 651 if(NS_SUCCEEDED(nsres)) { 652 TRACE("frame node\n"); 653 654 add_script_runner(This, run_bind_to_tree, (nsISupports*)nsframe, NULL); 655 nsIDOMHTMLFrameElement_Release(nsframe); 656 return; 657 } 658 659 nsres = nsIContent_QueryInterface(aContent, &IID_nsIDOMHTMLScriptElement, (void**)&nsscript); 660 if(NS_SUCCEEDED(nsres)) { 661 HTMLScriptElement *script_elem; 662 HRESULT hres; 663 664 TRACE("script element\n"); 665 666 hres = script_elem_from_nsscript(This, nsscript, &script_elem); 667 nsIDOMHTMLScriptElement_Release(nsscript); 668 if(FAILED(hres)) 669 return; 670 671 if(script_elem->parse_on_bind) 672 add_script_runner(This, run_insert_script, (nsISupports*)nsscript, NULL); 673 674 IHTMLScriptElement_Release(&script_elem->IHTMLScriptElement_iface); 675 } 676} 677 678static void NSAPI nsDocumentObserver_AttemptToExecuteScript(nsIDocumentObserver *iface, nsIContent *aContent, 679 nsIParser *aParser, cpp_bool *aBlock) 680{ 681 HTMLDocumentNode *This = impl_from_nsIDocumentObserver(iface); 682 nsIDOMHTMLScriptElement *nsscript; 683 nsresult nsres; 684 685 TRACE("(%p)->(%p %p %p)\n", This, aContent, aParser, aBlock); 686 687 nsres = nsIContent_QueryInterface(aContent, &IID_nsIDOMHTMLScriptElement, (void**)&nsscript); 688 if(NS_SUCCEEDED(nsres)) { 689 TRACE("script node\n"); 690 691 add_script_runner(This, run_insert_script, (nsISupports*)nsscript, (nsISupports*)aParser); 692 nsIDOMHTMLScriptElement_Release(nsscript); 693 } 694} 695 696static const nsIDocumentObserverVtbl nsDocumentObserverVtbl = { 697 nsDocumentObserver_QueryInterface, 698 nsDocumentObserver_AddRef, 699 nsDocumentObserver_Release, 700 nsDocumentObserver_CharacterDataWillChange, 701 nsDocumentObserver_CharacterDataChanged, 702 nsDocumentObserver_AttributeWillChange, 703 nsDocumentObserver_AttributeChanged, 704 nsDocumentObserver_AttributeSetToCurrentValue, 705 nsDocumentObserver_ContentAppended, 706 nsDocumentObserver_ContentInserted, 707 nsDocumentObserver_ContentRemoved, 708 nsDocumentObserver_NodeWillBeDestroyed, 709 nsDocumentObserver_ParentChainChanged, 710 nsDocumentObserver_BeginUpdate, 711 nsDocumentObserver_EndUpdate, 712 nsDocumentObserver_BeginLoad, 713 nsDocumentObserver_EndLoad, 714 nsDocumentObserver_ContentStatesChanged, 715 nsDocumentObserver_DocumentStatesChanged, 716 nsDocumentObserver_StyleSheetAdded, 717 nsDocumentObserver_StyleSheetRemoved, 718 nsDocumentObserver_StyleSheetApplicableStateChanged, 719 nsDocumentObserver_StyleRuleChanged, 720 nsDocumentObserver_StyleRuleAdded, 721 nsDocumentObserver_StyleRuleRemoved, 722 nsDocumentObserver_BindToDocument, 723 nsDocumentObserver_AttemptToExecuteScript 724}; 725 726void init_document_mutation(HTMLDocumentNode *doc) 727{ 728 nsIDocument *nsdoc; 729 nsresult nsres; 730 731 doc->nsIDocumentObserver_iface.lpVtbl = &nsDocumentObserverVtbl; 732 733 nsres = nsIDOMHTMLDocument_QueryInterface(doc->nsdoc, &IID_nsIDocument, (void**)&nsdoc); 734 if(NS_FAILED(nsres)) { 735 ERR("Could not get nsIDocument: %08x\n", nsres); 736 return; 737 } 738 739 nsIContentUtils_AddDocumentObserver(content_utils, nsdoc, &doc->nsIDocumentObserver_iface); 740 nsIDocument_Release(nsdoc); 741} 742 743void release_document_mutation(HTMLDocumentNode *doc) 744{ 745 nsIDocument *nsdoc; 746 nsresult nsres; 747 748 nsres = nsIDOMHTMLDocument_QueryInterface(doc->nsdoc, &IID_nsIDocument, (void**)&nsdoc); 749 if(NS_FAILED(nsres)) { 750 ERR("Could not get nsIDocument: %08x\n", nsres); 751 return; 752 } 753 754 nsIContentUtils_RemoveDocumentObserver(content_utils, nsdoc, &doc->nsIDocumentObserver_iface); 755 nsIDocument_Release(nsdoc); 756} 757 758JSContext *get_context_from_document(nsIDOMHTMLDocument *nsdoc) 759{ 760 nsIDocument *doc; 761 JSContext *ctx; 762 nsresult nsres; 763 764 nsres = nsIDOMHTMLDocument_QueryInterface(nsdoc, &IID_nsIDocument, (void**)&doc); 765 assert(nsres == NS_OK); 766 767 ctx = nsIContentUtils_GetContextFromDocument(content_utils, doc); 768 nsIDocument_Release(doc); 769 770 TRACE("ret %p\n", ctx); 771 return ctx; 772} 773 774void init_mutation(nsIComponentManager *component_manager) 775{ 776 nsIFactory *factory; 777 nsresult nsres; 778 779 if(!component_manager) { 780 if(content_utils) { 781 nsIContentUtils_Release(content_utils); 782 content_utils = NULL; 783 } 784 return; 785 } 786 787 nsres = nsIComponentManager_GetClassObject(component_manager, &NS_ICONTENTUTILS_CID, 788 &IID_nsIFactory, (void**)&factory); 789 if(NS_FAILED(nsres)) { 790 ERR("Could not create nsIContentUtils service: %08x\n", nsres); 791 return; 792 } 793 794 nsres = nsIFactory_CreateInstance(factory, NULL, &IID_nsIContentUtils, (void**)&content_utils); 795 nsIFactory_Release(factory); 796 if(NS_FAILED(nsres)) 797 ERR("Could not create nsIContentUtils instance: %08x\n", nsres); 798}