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 24 static const IID NS_ICONTENTUTILS_CID = 25 {0x762C4AE7,0xB923,0x422F,{0xB9,0x7E,0xB9,0xBF,0xC1,0xEF,0x7B,0xF0}}; 26 27 static nsIContentUtils *content_utils; 28 29 static 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 153 static 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 190 static 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 */ 218 static 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 238 static 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 257 static 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 277 static 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 343 typedef struct nsRunnable nsRunnable; 344 345 typedef nsresult (*runnable_proc_t)(HTMLDocumentNode*,nsISupports*,nsISupports*); 346 347 struct 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 359 static inline nsRunnable *impl_from_nsIRunnable(nsIRunnable *iface) 360 { 361 return CONTAINING_RECORD(iface, nsRunnable, nsIRunnable_iface); 362 } 363 364 static 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 385 static 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 395 static 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 414 static 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 421 static const nsIRunnableVtbl nsRunnableVtbl = { 422 nsRunnable_QueryInterface, 423 nsRunnable_AddRef, 424 nsRunnable_Release, 425 nsRunnable_Run 426 }; 427 428 static 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 456 static inline HTMLDocumentNode *impl_from_nsIDocumentObserver(nsIDocumentObserver *iface) 457 { 458 return CONTAINING_RECORD(iface, HTMLDocumentNode, nsIDocumentObserver_iface); 459 } 460 461 static 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 485 static nsrefcnt NSAPI nsDocumentObserver_AddRef(nsIDocumentObserver *iface) 486 { 487 HTMLDocumentNode *This = impl_from_nsIDocumentObserver(iface); 488 return htmldoc_addref(&This->basedoc); 489 } 490 491 static nsrefcnt NSAPI nsDocumentObserver_Release(nsIDocumentObserver *iface) 492 { 493 HTMLDocumentNode *This = impl_from_nsIDocumentObserver(iface); 494 return htmldoc_release(&This->basedoc); 495 } 496 497 static void NSAPI nsDocumentObserver_CharacterDataWillChange(nsIDocumentObserver *iface, 498 nsIDocument *aDocument, nsIContent *aContent, void /*CharacterDataChangeInfo*/ *aInfo) 499 { 500 } 501 502 static void NSAPI nsDocumentObserver_CharacterDataChanged(nsIDocumentObserver *iface, 503 nsIDocument *aDocument, nsIContent *aContent, void /*CharacterDataChangeInfo*/ *aInfo) 504 { 505 } 506 507 static void NSAPI nsDocumentObserver_AttributeWillChange(nsIDocumentObserver *iface, nsIDocument *aDocument, 508 nsIContent *aContent, LONG aNameSpaceID, nsIAtom *aAttribute, LONG aModType) 509 { 510 } 511 512 static void NSAPI nsDocumentObserver_AttributeChanged(nsIDocumentObserver *iface, nsIDocument *aDocument, 513 nsIContent *aContent, LONG aNameSpaceID, nsIAtom *aAttribute, LONG aModType) 514 { 515 } 516 517 static void NSAPI nsDocumentObserver_AttributeSetToCurrentValue(nsIDocumentObserver *iface, nsIDocument *aDocument, 518 void *aElement, LONG aNameSpaceID, nsIAtom *aAttribute) 519 { 520 } 521 522 static void NSAPI nsDocumentObserver_ContentAppended(nsIDocumentObserver *iface, nsIDocument *aDocument, 523 nsIContent *aContainer, nsIContent *aFirstNewContent, LONG aNewIndexInContainer) 524 { 525 } 526 527 static void NSAPI nsDocumentObserver_ContentInserted(nsIDocumentObserver *iface, nsIDocument *aDocument, 528 nsIContent *aContainer, nsIContent *aChild, LONG aIndexInContainer) 529 { 530 } 531 532 static void NSAPI nsDocumentObserver_ContentRemoved(nsIDocumentObserver *iface, nsIDocument *aDocument, 533 nsIContent *aContainer, nsIContent *aChild, LONG aIndexInContainer, 534 nsIContent *aProviousSibling) 535 { 536 } 537 538 static void NSAPI nsDocumentObserver_NodeWillBeDestroyed(nsIDocumentObserver *iface, const nsINode *aNode) 539 { 540 } 541 542 static void NSAPI nsDocumentObserver_ParentChainChanged(nsIDocumentObserver *iface, nsIContent *aContent) 543 { 544 } 545 546 static void NSAPI nsDocumentObserver_BeginUpdate(nsIDocumentObserver *iface, nsIDocument *aDocument, 547 nsUpdateType aUpdateType) 548 { 549 } 550 551 static void NSAPI nsDocumentObserver_EndUpdate(nsIDocumentObserver *iface, nsIDocument *aDocument, 552 nsUpdateType aUpdateType) 553 { 554 } 555 556 static void NSAPI nsDocumentObserver_BeginLoad(nsIDocumentObserver *iface, nsIDocument *aDocument) 557 { 558 } 559 560 static 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 573 static void NSAPI nsDocumentObserver_ContentStatesChanged(nsIDocumentObserver *iface, nsIDocument *aDocument, 574 nsIContent *aContent, EventStates aStateMask) 575 { 576 } 577 578 static void NSAPI nsDocumentObserver_DocumentStatesChanged(nsIDocumentObserver *iface, nsIDocument *aDocument, 579 EventStates aStateMask) 580 { 581 } 582 583 static void NSAPI nsDocumentObserver_StyleSheetAdded(nsIDocumentObserver *iface, nsIDocument *aDocument, 584 nsIStyleSheet *aStyleSheet, cpp_bool aDocumentSheet) 585 { 586 } 587 588 static void NSAPI nsDocumentObserver_StyleSheetRemoved(nsIDocumentObserver *iface, nsIDocument *aDocument, 589 nsIStyleSheet *aStyleSheet, cpp_bool aDocumentSheet) 590 { 591 } 592 593 static void NSAPI nsDocumentObserver_StyleSheetApplicableStateChanged(nsIDocumentObserver *iface, 594 nsIDocument *aDocument, nsIStyleSheet *aStyleSheet, cpp_bool aApplicable) 595 { 596 } 597 598 static void NSAPI nsDocumentObserver_StyleRuleChanged(nsIDocumentObserver *iface, nsIDocument *aDocument, 599 nsIStyleSheet *aStyleSheet, nsIStyleRule *aOldStyleRule, nsIStyleSheet *aNewStyleRule) 600 { 601 } 602 603 static void NSAPI nsDocumentObserver_StyleRuleAdded(nsIDocumentObserver *iface, nsIDocument *aDocument, 604 nsIStyleSheet *aStyleSheet, nsIStyleRule *aStyleRule) 605 { 606 } 607 608 static void NSAPI nsDocumentObserver_StyleRuleRemoved(nsIDocumentObserver *iface, nsIDocument *aDocument, 609 nsIStyleSheet *aStyleSheet, nsIStyleRule *aStyleRule) 610 { 611 } 612 613 static 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 678 static 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 696 static 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 726 void 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 743 void 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 758 JSContext *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 774 void 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 } 799