1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2001 Dirk Mueller (mueller (at) kde.org) 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Library General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Library General Public License for more details. 16 * 17 * You should have received a copy of the GNU Library General Public License 18 * along with this library; see the file COPYING.LIB. If not, write to 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA. 21 */ 22 23 #include "config.h" 24 #include "ContainerNode.h" 25 26 #include "BeforeLoadEvent.h" 27 #include "MemoryCache.h" 28 #include "ContainerNodeAlgorithms.h" 29 #include "DeleteButtonController.h" 30 #include "EventNames.h" 31 #include "ExceptionCode.h" 32 #include "FloatRect.h" 33 #include "Frame.h" 34 #include "FrameView.h" 35 #include "InlineTextBox.h" 36 #include "InspectorInstrumentation.h" 37 #include "MutationEvent.h" 38 #include "ResourceLoadScheduler.h" 39 #include "Page.h" 40 #include "RenderBox.h" 41 #include "RenderTheme.h" 42 #include "RootInlineBox.h" 43 #include <wtf/CurrentTime.h> 44 #include <wtf/Vector.h> 45 46 namespace WebCore { 47 48 static void notifyChildInserted(Node*); 49 static void dispatchChildInsertionEvents(Node*); 50 static void dispatchChildRemovalEvents(Node*); 51 52 typedef Vector<std::pair<NodeCallback, RefPtr<Node> > > NodeCallbackQueue; 53 typedef Vector<RefPtr<Node>, 1> NodeVector; 54 static NodeCallbackQueue* s_postAttachCallbackQueue; 55 56 static size_t s_attachDepth; 57 static bool s_shouldReEnableMemoryCacheCallsAfterAttach; 58 59 static inline void collectNodes(Node* node, NodeVector& nodes) 60 { 61 for (Node* child = node->firstChild(); child; child = child->nextSibling()) 62 nodes.append(child); 63 } 64 65 static void collectTargetNodes(Node* node, NodeVector& nodes) 66 { 67 if (node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE) { 68 nodes.append(node); 69 return; 70 } 71 collectNodes(node, nodes); 72 } 73 74 void ContainerNode::removeAllChildren() 75 { 76 removeAllChildrenInContainer<Node, ContainerNode>(this); 77 } 78 79 void ContainerNode::takeAllChildrenFrom(ContainerNode* oldParent) 80 { 81 NodeVector children; 82 collectNodes(oldParent, children); 83 oldParent->removeAllChildren(); 84 85 for (unsigned i = 0; i < children.size(); ++i) { 86 ExceptionCode ec = 0; 87 if (children[i]->attached()) 88 children[i]->detach(); 89 // FIXME: We need a no mutation event version of adoptNode. 90 RefPtr<Node> child = document()->adoptNode(children[i].release(), ec); 91 ASSERT(!ec); 92 parserAddChild(child.get()); 93 if (attached() && !child->attached()) 94 child->attach(); 95 } 96 } 97 98 ContainerNode::~ContainerNode() 99 { 100 removeAllChildren(); 101 } 102 103 bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach) 104 { 105 // Check that this node is not "floating". 106 // If it is, it can be deleted as a side effect of sending mutation events. 107 ASSERT(refCount() || parentOrHostNode()); 108 109 ec = 0; 110 111 // insertBefore(node, 0) is equivalent to appendChild(node) 112 if (!refChild) 113 return appendChild(newChild, ec, shouldLazyAttach); 114 115 // Make sure adding the new child is OK. 116 checkAddChild(newChild.get(), ec); 117 if (ec) 118 return false; 119 120 // NOT_FOUND_ERR: Raised if refChild is not a child of this node 121 if (refChild->parentNode() != this) { 122 ec = NOT_FOUND_ERR; 123 return false; 124 } 125 126 NodeVector targets; 127 collectTargetNodes(newChild.get(), targets); 128 if (targets.isEmpty()) 129 return true; 130 131 // Now actually add the child(ren) 132 if (refChild->previousSibling() == newChild || refChild == newChild) // nothing to do 133 return true; 134 135 RefPtr<Node> next = refChild; 136 RefPtr<Node> refChildPreviousSibling = refChild->previousSibling(); 137 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) { 138 Node* child = it->get(); 139 140 // If child is already present in the tree, first remove it from the old location. 141 if (ContainerNode* oldParent = child->parentNode()) 142 oldParent->removeChild(child, ec); 143 if (ec) 144 return false; 145 146 // FIXME: After sending the mutation events, "this" could be destroyed. 147 // We can prevent that by doing a "ref", but first we have to make sure 148 // that no callers call with ref count == 0 and parent = 0 (as of this 149 // writing, there are definitely callers who call that way). 150 151 // Due to arbitrary code running in response to a DOM mutation event it's 152 // possible that "next" is no longer a child of "this". 153 // It's also possible that "child" has been inserted elsewhere. 154 // In either of those cases, we'll just stop. 155 if (next->parentNode() != this) 156 break; 157 if (child->parentNode()) 158 break; 159 160 #if ENABLE(INSPECTOR) 161 InspectorInstrumentation::willInsertDOMNode(document(), child, this); 162 #endif 163 164 child->setTreeScopeRecursively(treeScope()); 165 166 insertBeforeCommon(next.get(), child); 167 168 // Send notification about the children change. 169 childrenChanged(false, refChildPreviousSibling.get(), next.get(), 1); 170 notifyChildInserted(child); 171 172 // Add child to the rendering tree. 173 if (attached() && !child->attached() && child->parentNode() == this) { 174 if (shouldLazyAttach) 175 child->lazyAttach(); 176 else 177 child->attach(); 178 } 179 180 // Now that the child is attached to the render tree, dispatch 181 // the relevant mutation events. 182 dispatchChildInsertionEvents(child); 183 } 184 185 dispatchSubtreeModifiedEvent(); 186 return true; 187 } 188 189 void ContainerNode::insertBeforeCommon(Node* nextChild, Node* newChild) 190 { 191 ASSERT(newChild); 192 ASSERT(!newChild->parentNode()); // Use insertBefore if you need to handle reparenting (and want DOM mutation events). 193 ASSERT(!newChild->nextSibling()); 194 ASSERT(!newChild->previousSibling()); 195 196 forbidEventDispatch(); 197 Node* prev = nextChild->previousSibling(); 198 ASSERT(m_lastChild != prev); 199 nextChild->setPreviousSibling(newChild); 200 if (prev) { 201 ASSERT(m_firstChild != nextChild); 202 ASSERT(prev->nextSibling() == nextChild); 203 prev->setNextSibling(newChild); 204 } else { 205 ASSERT(m_firstChild == nextChild); 206 m_firstChild = newChild; 207 } 208 newChild->setParent(this); 209 newChild->setPreviousSibling(prev); 210 newChild->setNextSibling(nextChild); 211 allowEventDispatch(); 212 } 213 214 void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node* nextChild) 215 { 216 ASSERT(newChild); 217 ASSERT(nextChild); 218 ASSERT(nextChild->parentNode() == this); 219 220 NodeVector targets; 221 collectTargetNodes(newChild.get(), targets); 222 if (targets.isEmpty()) 223 return; 224 225 if (nextChild->previousSibling() == newChild || nextChild == newChild) // nothing to do 226 return; 227 228 RefPtr<Node> next = nextChild; 229 RefPtr<Node> nextChildPreviousSibling = nextChild->previousSibling(); 230 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) { 231 Node* child = it->get(); 232 233 #if ENABLE(INSPECTOR) 234 InspectorInstrumentation::willInsertDOMNode(document(), child, this); 235 #endif 236 237 insertBeforeCommon(next.get(), child); 238 239 childrenChanged(true, nextChildPreviousSibling.get(), nextChild, 1); 240 notifyChildInserted(child); 241 } 242 } 243 244 bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, bool shouldLazyAttach) 245 { 246 // Check that this node is not "floating". 247 // If it is, it can be deleted as a side effect of sending mutation events. 248 ASSERT(refCount() || parentOrHostNode()); 249 250 ec = 0; 251 252 if (oldChild == newChild) // nothing to do 253 return true; 254 255 // Make sure replacing the old child with the new is ok 256 checkReplaceChild(newChild.get(), oldChild, ec); 257 if (ec) 258 return false; 259 260 // NOT_FOUND_ERR: Raised if oldChild is not a child of this node. 261 if (!oldChild || oldChild->parentNode() != this) { 262 ec = NOT_FOUND_ERR; 263 return false; 264 } 265 266 RefPtr<Node> prev = oldChild->previousSibling(); 267 RefPtr<Node> next = oldChild->nextSibling(); 268 269 // Remove the node we're replacing 270 RefPtr<Node> removedChild = oldChild; 271 removeChild(oldChild, ec); 272 if (ec) 273 return false; 274 275 // FIXME: After sending the mutation events, "this" could be destroyed. 276 // We can prevent that by doing a "ref", but first we have to make sure 277 // that no callers call with ref count == 0 and parent = 0 (as of this 278 // writing, there are definitely callers who call that way). 279 280 bool isFragment = newChild->nodeType() == DOCUMENT_FRAGMENT_NODE; 281 282 // Add the new child(ren) 283 RefPtr<Node> child = isFragment ? newChild->firstChild() : newChild; 284 while (child) { 285 // If the new child is already in the right place, we're done. 286 if (prev && (prev == child || prev == child->previousSibling())) 287 break; 288 289 // For a fragment we have more children to do. 290 RefPtr<Node> nextChild = isFragment ? child->nextSibling() : 0; 291 292 // Remove child from its old position. 293 if (ContainerNode* oldParent = child->parentNode()) 294 oldParent->removeChild(child.get(), ec); 295 if (ec) 296 return false; 297 298 // Due to arbitrary code running in response to a DOM mutation event it's 299 // possible that "prev" is no longer a child of "this". 300 // It's also possible that "child" has been inserted elsewhere. 301 // In either of those cases, we'll just stop. 302 if (prev && prev->parentNode() != this) 303 break; 304 if (child->parentNode()) 305 break; 306 307 ASSERT(!child->nextSibling()); 308 ASSERT(!child->previousSibling()); 309 310 #if ENABLE(INSPECTOR) 311 InspectorInstrumentation::willInsertDOMNode(document(), child.get(), this); 312 #endif 313 314 child->setTreeScopeRecursively(treeScope()); 315 316 // Add child after "prev". 317 forbidEventDispatch(); 318 Node* next; 319 if (prev) { 320 next = prev->nextSibling(); 321 ASSERT(m_firstChild != next); 322 prev->setNextSibling(child.get()); 323 } else { 324 next = m_firstChild; 325 m_firstChild = child.get(); 326 } 327 if (next) { 328 ASSERT(m_lastChild != prev); 329 ASSERT(next->previousSibling() == prev); 330 next->setPreviousSibling(child.get()); 331 } else { 332 ASSERT(m_lastChild == prev); 333 m_lastChild = child.get(); 334 } 335 child->setParent(this); 336 child->setPreviousSibling(prev.get()); 337 child->setNextSibling(next); 338 allowEventDispatch(); 339 340 childrenChanged(false, prev.get(), next, 1); 341 notifyChildInserted(child.get()); 342 343 // Add child to the rendering tree 344 if (attached() && !child->attached() && child->parentNode() == this) { 345 if (shouldLazyAttach) 346 child->lazyAttach(); 347 else 348 child->attach(); 349 } 350 351 // Now that the child is attached to the render tree, dispatch 352 // the relevant mutation events. 353 dispatchChildInsertionEvents(child.get()); 354 355 prev = child; 356 child = nextChild.release(); 357 } 358 359 dispatchSubtreeModifiedEvent(); 360 return true; 361 } 362 363 void ContainerNode::willRemove() 364 { 365 Vector<RefPtr<Node>, 10> nodes; 366 nodes.reserveInitialCapacity(childNodeCount()); 367 for (Node* n = m_lastChild; n; n = n->previousSibling()) 368 nodes.append(n); 369 for (; nodes.size(); nodes.removeLast()) 370 nodes.last().get()->willRemove(); 371 Node::willRemove(); 372 } 373 374 static void willRemoveChild(Node* child) 375 { 376 // update auxiliary doc info (e.g. iterators) to note that node is being removed 377 child->document()->nodeWillBeRemoved(child); 378 child->document()->incDOMTreeVersion(); 379 380 // fire removed from document mutation events. 381 dispatchChildRemovalEvents(child); 382 child->willRemove(); 383 } 384 385 static void willRemoveChildren(ContainerNode* container) 386 { 387 container->document()->nodeChildrenWillBeRemoved(container); 388 container->document()->incDOMTreeVersion(); 389 390 NodeVector children; 391 collectNodes(container, children); 392 393 for (NodeVector::const_iterator it = children.begin(); it != children.end(); it++) { 394 Node* child = it->get(); 395 // fire removed from document mutation events. 396 dispatchChildRemovalEvents(child); 397 child->willRemove(); 398 } 399 } 400 401 bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec) 402 { 403 // Check that this node is not "floating". 404 // If it is, it can be deleted as a side effect of sending mutation events. 405 ASSERT(refCount() || parentOrHostNode()); 406 407 ec = 0; 408 409 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. 410 if (isReadOnlyNode()) { 411 ec = NO_MODIFICATION_ALLOWED_ERR; 412 return false; 413 } 414 415 // NOT_FOUND_ERR: Raised if oldChild is not a child of this node. 416 if (!oldChild || oldChild->parentNode() != this) { 417 ec = NOT_FOUND_ERR; 418 return false; 419 } 420 421 RefPtr<Node> child = oldChild; 422 willRemoveChild(child.get()); 423 424 // Mutation events might have moved this child into a different parent. 425 if (child->parentNode() != this) { 426 ec = NOT_FOUND_ERR; 427 return false; 428 } 429 430 document()->removeFocusedNodeOfSubtree(child.get()); 431 432 // Events fired when blurring currently focused node might have moved this 433 // child into a different parent. 434 if (child->parentNode() != this) { 435 ec = NOT_FOUND_ERR; 436 return false; 437 } 438 439 // FIXME: After sending the mutation events, "this" could be destroyed. 440 // We can prevent that by doing a "ref", but first we have to make sure 441 // that no callers call with ref count == 0 and parent = 0 (as of this 442 // writing, there are definitely callers who call that way). 443 444 Node* prev = child->previousSibling(); 445 Node* next = child->nextSibling(); 446 removeBetween(prev, next, child.get()); 447 448 // Dispatch post-removal mutation events 449 childrenChanged(false, prev, next, -1); 450 dispatchSubtreeModifiedEvent(); 451 452 if (child->inDocument()) 453 child->removedFromDocument(); 454 else 455 child->removedFromTree(true); 456 457 return child; 458 } 459 460 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node* oldChild) 461 { 462 ASSERT(oldChild); 463 ASSERT(oldChild->parentNode() == this); 464 465 forbidEventDispatch(); 466 467 // Remove from rendering tree 468 if (oldChild->attached()) 469 oldChild->detach(); 470 471 if (nextChild) 472 nextChild->setPreviousSibling(previousChild); 473 if (previousChild) 474 previousChild->setNextSibling(nextChild); 475 if (m_firstChild == oldChild) 476 m_firstChild = nextChild; 477 if (m_lastChild == oldChild) 478 m_lastChild = previousChild; 479 480 oldChild->setPreviousSibling(0); 481 oldChild->setNextSibling(0); 482 oldChild->setParent(0); 483 484 allowEventDispatch(); 485 } 486 487 void ContainerNode::parserRemoveChild(Node* oldChild) 488 { 489 ASSERT(oldChild); 490 ASSERT(oldChild->parentNode() == this); 491 492 Node* prev = oldChild->previousSibling(); 493 Node* next = oldChild->nextSibling(); 494 495 removeBetween(prev, next, oldChild); 496 497 childrenChanged(true, prev, next, -1); 498 if (oldChild->inDocument()) 499 oldChild->removedFromDocument(); 500 else 501 oldChild->removedFromTree(true); 502 } 503 504 // this differs from other remove functions because it forcibly removes all the children, 505 // regardless of read-only status or event exceptions, e.g. 506 void ContainerNode::removeChildren() 507 { 508 if (!m_firstChild) 509 return; 510 511 // The container node can be removed from event handlers. 512 RefPtr<ContainerNode> protect(this); 513 514 // Do any prep work needed before actually starting to detach 515 // and remove... e.g. stop loading frames, fire unload events. 516 willRemoveChildren(protect.get()); 517 518 // exclude this node when looking for removed focusedNode since only children will be removed 519 document()->removeFocusedNodeOfSubtree(this, true); 520 521 forbidEventDispatch(); 522 Vector<RefPtr<Node>, 10> removedChildren; 523 removedChildren.reserveInitialCapacity(childNodeCount()); 524 while (RefPtr<Node> n = m_firstChild) { 525 Node* next = n->nextSibling(); 526 527 // Remove the node from the tree before calling detach or removedFromDocument (4427024, 4129744). 528 // removeChild() does this after calling detach(). There is no explanation for 529 // this discrepancy between removeChild() and its optimized version removeChildren(). 530 n->setPreviousSibling(0); 531 n->setNextSibling(0); 532 n->setParent(0); 533 534 m_firstChild = next; 535 if (n == m_lastChild) 536 m_lastChild = 0; 537 removedChildren.append(n.release()); 538 } 539 540 size_t removedChildrenCount = removedChildren.size(); 541 size_t i; 542 543 // Detach the nodes only after properly removed from the tree because 544 // a. detaching requires a proper DOM tree (for counters and quotes for 545 // example) and during the previous loop the next sibling still points to 546 // the node being removed while the node being removed does not point back 547 // and does not point to the same parent as its next sibling. 548 // b. destroying Renderers of standalone nodes is sometimes faster. 549 for (i = 0; i < removedChildrenCount; ++i) { 550 Node* removedChild = removedChildren[i].get(); 551 if (removedChild->attached()) 552 removedChild->detach(); 553 } 554 555 allowEventDispatch(); 556 557 // Dispatch a single post-removal mutation event denoting a modified subtree. 558 childrenChanged(false, 0, 0, -static_cast<int>(removedChildrenCount)); 559 dispatchSubtreeModifiedEvent(); 560 561 for (i = 0; i < removedChildrenCount; ++i) { 562 Node* removedChild = removedChildren[i].get(); 563 if (removedChild->inDocument()) 564 removedChild->removedFromDocument(); 565 // removeChild() calls removedFromTree(true) if the child was not in the 566 // document. There is no explanation for this discrepancy between removeChild() 567 // and its optimized version removeChildren(). 568 } 569 } 570 571 bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach) 572 { 573 // Check that this node is not "floating". 574 // If it is, it can be deleted as a side effect of sending mutation events. 575 ASSERT(refCount() || parentOrHostNode()); 576 577 ec = 0; 578 579 // Make sure adding the new child is ok 580 checkAddChild(newChild.get(), ec); 581 if (ec) 582 return false; 583 584 if (newChild == m_lastChild) // nothing to do 585 return newChild; 586 587 NodeVector targets; 588 collectTargetNodes(newChild.get(), targets); 589 if (targets.isEmpty()) 590 return true; 591 592 // Now actually add the child(ren) 593 RefPtr<Node> prev = lastChild(); 594 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) { 595 Node* child = it->get(); 596 // If child is already present in the tree, first remove it 597 if (ContainerNode* oldParent = child->parentNode()) { 598 oldParent->removeChild(child, ec); 599 if (ec) 600 return false; 601 602 // If the child has a parent again, just stop what we're doing, because 603 // that means someone is doing something with DOM mutation -- can't re-parent 604 // a child that already has a parent. 605 if (child->parentNode()) 606 break; 607 } 608 609 #if ENABLE(INSPECTOR) 610 InspectorInstrumentation::willInsertDOMNode(document(), child, this); 611 #endif 612 613 child->setTreeScopeRecursively(treeScope()); 614 615 // Append child to the end of the list 616 forbidEventDispatch(); 617 child->setParent(this); 618 if (m_lastChild) { 619 child->setPreviousSibling(m_lastChild); 620 m_lastChild->setNextSibling(child); 621 } else 622 m_firstChild = child; 623 m_lastChild = child; 624 allowEventDispatch(); 625 626 // Send notification about the children change. 627 childrenChanged(false, prev.get(), 0, 1); 628 notifyChildInserted(child); 629 630 // Add child to the rendering tree 631 if (attached() && !child->attached() && child->parentNode() == this) { 632 if (shouldLazyAttach) 633 child->lazyAttach(); 634 else 635 child->attach(); 636 } 637 638 // Now that the child is attached to the render tree, dispatch 639 // the relevant mutation events. 640 dispatchChildInsertionEvents(child); 641 prev = child; 642 } 643 644 dispatchSubtreeModifiedEvent(); 645 return true; 646 } 647 648 void ContainerNode::parserAddChild(PassRefPtr<Node> newChild) 649 { 650 ASSERT(newChild); 651 ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle reparenting (and want DOM mutation events). 652 653 #if ENABLE(INSPECTOR) 654 InspectorInstrumentation::willInsertDOMNode(document(), newChild.get(), this); 655 #endif 656 657 forbidEventDispatch(); 658 Node* last = m_lastChild; 659 // FIXME: This method should take a PassRefPtr. 660 appendChildToContainer<Node, ContainerNode>(newChild.get(), this); 661 allowEventDispatch(); 662 663 // FIXME: Why doesn't this use notifyChildInserted(newChild) instead? 664 document()->incDOMTreeVersion(); 665 if (inDocument()) 666 newChild->insertedIntoDocument(); 667 childrenChanged(true, last, 0, 1); 668 } 669 670 void ContainerNode::deprecatedParserAddChild(PassRefPtr<Node> node) 671 { 672 parserAddChild(node); 673 } 674 675 void ContainerNode::suspendPostAttachCallbacks() 676 { 677 if (!s_attachDepth) { 678 ASSERT(!s_shouldReEnableMemoryCacheCallsAfterAttach); 679 if (Page* page = document()->page()) { 680 if (page->areMemoryCacheClientCallsEnabled()) { 681 page->setMemoryCacheClientCallsEnabled(false); 682 s_shouldReEnableMemoryCacheCallsAfterAttach = true; 683 } 684 } 685 resourceLoadScheduler()->suspendPendingRequests(); 686 } 687 ++s_attachDepth; 688 } 689 690 void ContainerNode::resumePostAttachCallbacks() 691 { 692 if (s_attachDepth == 1) { 693 if (s_postAttachCallbackQueue) 694 dispatchPostAttachCallbacks(); 695 if (s_shouldReEnableMemoryCacheCallsAfterAttach) { 696 s_shouldReEnableMemoryCacheCallsAfterAttach = false; 697 if (Page* page = document()->page()) 698 page->setMemoryCacheClientCallsEnabled(true); 699 } 700 resourceLoadScheduler()->resumePendingRequests(); 701 } 702 --s_attachDepth; 703 } 704 705 void ContainerNode::queuePostAttachCallback(NodeCallback callback, Node* node) 706 { 707 if (!s_postAttachCallbackQueue) 708 s_postAttachCallbackQueue = new NodeCallbackQueue; 709 710 s_postAttachCallbackQueue->append(std::pair<NodeCallback, RefPtr<Node> >(callback, node)); 711 } 712 713 bool ContainerNode::postAttachCallbacksAreSuspended() 714 { 715 return s_attachDepth; 716 } 717 718 void ContainerNode::dispatchPostAttachCallbacks() 719 { 720 // We recalculate size() each time through the loop because a callback 721 // can add more callbacks to the end of the queue. 722 for (size_t i = 0; i < s_postAttachCallbackQueue->size(); ++i) { 723 std::pair<NodeCallback, RefPtr<Node> >& pair = (*s_postAttachCallbackQueue)[i]; 724 NodeCallback callback = pair.first; 725 Node* node = pair.second.get(); 726 727 callback(node); 728 } 729 s_postAttachCallbackQueue->clear(); 730 } 731 732 void ContainerNode::attach() 733 { 734 for (Node* child = m_firstChild; child; child = child->nextSibling()) 735 child->attach(); 736 Node::attach(); 737 } 738 739 void ContainerNode::detach() 740 { 741 for (Node* child = m_firstChild; child; child = child->nextSibling()) 742 child->detach(); 743 clearChildNeedsStyleRecalc(); 744 Node::detach(); 745 } 746 747 void ContainerNode::insertedIntoDocument() 748 { 749 Node::insertedIntoDocument(); 750 insertedIntoTree(false); 751 752 // Determine set of children before operating on any of them. 753 NodeVector children; 754 collectNodes(this, children); 755 756 NodeVector::iterator it; 757 for (it = children.begin(); it != children.end() && inDocument(); ++it) { 758 Node* child = it->get(); 759 child->insertedIntoDocument(); 760 } 761 } 762 763 void ContainerNode::removedFromDocument() 764 { 765 Node::removedFromDocument(); 766 if (document()->cssTarget() == this) 767 document()->setCSSTarget(0); 768 clearInDocument(); 769 removedFromTree(false); 770 for (Node* child = m_firstChild; child; child = child->nextSibling()) 771 child->removedFromDocument(); 772 } 773 774 void ContainerNode::insertedIntoTree(bool deep) 775 { 776 if (!deep) 777 return; 778 for (Node* child = m_firstChild; child; child = child->nextSibling()) 779 child->insertedIntoTree(true); 780 } 781 782 void ContainerNode::removedFromTree(bool deep) 783 { 784 if (!deep) 785 return; 786 for (Node* child = m_firstChild; child; child = child->nextSibling()) 787 child->removedFromTree(true); 788 } 789 790 void ContainerNode::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) 791 { 792 Node::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 793 if (!changedByParser && childCountDelta) 794 document()->nodeChildrenChanged(this); 795 if (document()->hasNodeListCaches()) 796 notifyNodeListsChildrenChanged(); 797 } 798 799 void ContainerNode::cloneChildNodes(ContainerNode *clone) 800 { 801 // disable the delete button so it's elements are not serialized into the markup 802 bool isEditorEnabled = false; 803 if (document()->frame() && document()->frame()->editor()->canEdit()) { 804 SelectionController* selection = document()->frame()->selection(); 805 Element* root = selection ? selection->rootEditableElement() : 0; 806 isEditorEnabled = root && isDescendantOf(root); 807 808 if (isEditorEnabled) 809 document()->frame()->editor()->deleteButtonController()->disable(); 810 } 811 812 ExceptionCode ec = 0; 813 for (Node* n = firstChild(); n && !ec; n = n->nextSibling()) 814 clone->appendChild(n->cloneNode(true), ec); 815 if (isEditorEnabled && document()->frame()) 816 document()->frame()->editor()->deleteButtonController()->enable(); 817 } 818 819 bool ContainerNode::getUpperLeftCorner(FloatPoint& point) const 820 { 821 if (!renderer()) 822 return false; 823 // What is this code really trying to do? 824 RenderObject *o = renderer(); 825 RenderObject *p = o; 826 827 if (!o->isInline() || o->isReplaced()) { 828 point = o->localToAbsolute(FloatPoint(), false, true); 829 return true; 830 } 831 832 // find the next text/image child, to get a position 833 while (o) { 834 p = o; 835 if (o->firstChild()) 836 o = o->firstChild(); 837 else if (o->nextSibling()) 838 o = o->nextSibling(); 839 else { 840 RenderObject *next = 0; 841 while (!next && o->parent()) { 842 o = o->parent(); 843 next = o->nextSibling(); 844 } 845 o = next; 846 847 if (!o) 848 break; 849 } 850 ASSERT(o); 851 852 if (!o->isInline() || o->isReplaced()) { 853 point = o->localToAbsolute(FloatPoint(), false, true); 854 return true; 855 } 856 857 if (p->node() && p->node() == this && o->isText() && !o->isBR() && !toRenderText(o)->firstTextBox()) { 858 // do nothing - skip unrendered whitespace that is a child or next sibling of the anchor 859 } else if ((o->isText() && !o->isBR()) || o->isReplaced()) { 860 point = FloatPoint(); 861 if (o->isText() && toRenderText(o)->firstTextBox()) { 862 point.move(toRenderText(o)->linesBoundingBox().x(), 863 toRenderText(o)->firstTextBox()->root()->lineTop()); 864 } else if (o->isBox()) { 865 RenderBox* box = toRenderBox(o); 866 point.move(box->x(), box->y()); 867 } 868 point = o->container()->localToAbsolute(point, false, true); 869 return true; 870 } 871 } 872 873 // If the target doesn't have any children or siblings that could be used to calculate the scroll position, we must be 874 // at the end of the document. Scroll to the bottom. FIXME: who said anything about scrolling? 875 if (!o && document()->view()) { 876 point = FloatPoint(0, document()->view()->contentsHeight()); 877 return true; 878 } 879 return false; 880 } 881 882 // FIXME: This doesn't work correctly with transforms. 883 bool ContainerNode::getLowerRightCorner(FloatPoint& point) const 884 { 885 if (!renderer()) 886 return false; 887 888 RenderObject* o = renderer(); 889 if (!o->isInline() || o->isReplaced()) { 890 RenderBox* box = toRenderBox(o); 891 point = o->localToAbsolute(FloatPoint(), false, true); 892 point.move(box->width(), box->height()); 893 return true; 894 } 895 896 // find the last text/image child, to get a position 897 while (o) { 898 if (o->lastChild()) 899 o = o->lastChild(); 900 else if (o->previousSibling()) 901 o = o->previousSibling(); 902 else { 903 RenderObject* prev = 0; 904 while (!prev) { 905 o = o->parent(); 906 if (!o) 907 return false; 908 prev = o->previousSibling(); 909 } 910 o = prev; 911 } 912 ASSERT(o); 913 if (o->isText() || o->isReplaced()) { 914 point = FloatPoint(); 915 if (o->isText()) { 916 RenderText* text = toRenderText(o); 917 IntRect linesBox = text->linesBoundingBox(); 918 if (!linesBox.x() && !linesBox.width() && !linesBox.y() && !linesBox.height()) 919 continue; 920 point.move(linesBox.x() + linesBox.width(), linesBox.y() + linesBox.height()); 921 } else { 922 RenderBox* box = toRenderBox(o); 923 point.move(box->x() + box->width(), box->y() + box->height()); 924 } 925 point = o->container()->localToAbsolute(point, false, true); 926 return true; 927 } 928 } 929 return true; 930 } 931 932 IntRect ContainerNode::getRect() const 933 { 934 FloatPoint upperLeft, lowerRight; 935 bool foundUpperLeft = getUpperLeftCorner(upperLeft); 936 bool foundLowerRight = getLowerRightCorner(lowerRight); 937 938 // If we've found one corner, but not the other, 939 // then we should just return a point at the corner that we did find. 940 if (foundUpperLeft != foundLowerRight) { 941 if (foundUpperLeft) 942 lowerRight = upperLeft; 943 else 944 upperLeft = lowerRight; 945 } 946 947 lowerRight.setX(max(upperLeft.x(), lowerRight.x())); 948 lowerRight.setY(max(upperLeft.y(), lowerRight.y())); 949 950 return enclosingIntRect(FloatRect(upperLeft, lowerRight - upperLeft)); 951 } 952 953 void ContainerNode::setFocus(bool received) 954 { 955 if (focused() == received) 956 return; 957 958 Node::setFocus(received); 959 960 // note that we need to recalc the style 961 setNeedsStyleRecalc(); 962 } 963 964 void ContainerNode::setActive(bool down, bool pause) 965 { 966 if (down == active()) return; 967 968 Node::setActive(down); 969 970 // note that we need to recalc the style 971 // FIXME: Move to Element 972 if (renderer()) { 973 bool reactsToPress = renderer()->style()->affectedByActiveRules(); 974 if (reactsToPress) 975 setNeedsStyleRecalc(); 976 if (renderer() && renderer()->style()->hasAppearance()) { 977 if (renderer()->theme()->stateChanged(renderer(), PressedState)) 978 reactsToPress = true; 979 } 980 if (reactsToPress && pause) { 981 // The delay here is subtle. It relies on an assumption, namely that the amount of time it takes 982 // to repaint the "down" state of the control is about the same time as it would take to repaint the 983 // "up" state. Once you assume this, you can just delay for 100ms - that time (assuming that after you 984 // leave this method, it will be about that long before the flush of the up state happens again). 985 #ifdef HAVE_FUNC_USLEEP 986 double startTime = currentTime(); 987 #endif 988 989 // Ensure there are no pending changes 990 Document::updateStyleForAllDocuments(); 991 // Do an immediate repaint. 992 if (renderer()) 993 renderer()->repaint(true); 994 995 // FIXME: Find a substitute for usleep for Win32. 996 // Better yet, come up with a way of doing this that doesn't use this sort of thing at all. 997 #ifdef HAVE_FUNC_USLEEP 998 // Now pause for a small amount of time (1/10th of a second from before we repainted in the pressed state) 999 double remainingTime = 0.1 - (currentTime() - startTime); 1000 if (remainingTime > 0) 1001 usleep(static_cast<useconds_t>(remainingTime * 1000000.0)); 1002 #endif 1003 } 1004 } 1005 } 1006 1007 void ContainerNode::setHovered(bool over) 1008 { 1009 if (over == hovered()) return; 1010 1011 Node::setHovered(over); 1012 1013 // note that we need to recalc the style 1014 // FIXME: Move to Element 1015 if (renderer()) { 1016 if (renderer()->style()->affectedByHoverRules()) 1017 setNeedsStyleRecalc(); 1018 if (renderer() && renderer()->style()->hasAppearance()) 1019 renderer()->theme()->stateChanged(renderer(), HoverState); 1020 } 1021 } 1022 1023 unsigned ContainerNode::childNodeCount() const 1024 { 1025 unsigned count = 0; 1026 Node *n; 1027 for (n = firstChild(); n; n = n->nextSibling()) 1028 count++; 1029 return count; 1030 } 1031 1032 Node *ContainerNode::childNode(unsigned index) const 1033 { 1034 unsigned i; 1035 Node *n = firstChild(); 1036 for (i = 0; n != 0 && i < index; i++) 1037 n = n->nextSibling(); 1038 return n; 1039 } 1040 1041 static void notifyChildInserted(Node* child) 1042 { 1043 ASSERT(!eventDispatchForbidden()); 1044 1045 #if ENABLE(INSPECTOR) 1046 InspectorInstrumentation::didInsertDOMNode(child->document(), child); 1047 #endif 1048 1049 RefPtr<Node> c = child; 1050 RefPtr<Document> document = child->document(); 1051 1052 Node* parentOrHostNode = c->parentOrHostNode(); 1053 if (parentOrHostNode && parentOrHostNode->inDocument()) 1054 c->insertedIntoDocument(); 1055 else 1056 c->insertedIntoTree(true); 1057 1058 document->incDOMTreeVersion(); 1059 } 1060 1061 static void dispatchChildInsertionEvents(Node* child) 1062 { 1063 ASSERT(!eventDispatchForbidden()); 1064 1065 RefPtr<Node> c = child; 1066 RefPtr<Document> document = child->document(); 1067 1068 if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER)) 1069 c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode())); 1070 1071 // dispatch the DOMNodeInsertedIntoDocument event to all descendants 1072 if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) { 1073 for (; c; c = c->traverseNextNode(child)) 1074 c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false)); 1075 } 1076 } 1077 1078 static void dispatchChildRemovalEvents(Node* child) 1079 { 1080 ASSERT(!eventDispatchForbidden()); 1081 1082 #if ENABLE(INSPECTOR) 1083 InspectorInstrumentation::willRemoveDOMNode(child->document(), child); 1084 #endif 1085 1086 RefPtr<Node> c = child; 1087 RefPtr<Document> document = child->document(); 1088 1089 // dispatch pre-removal mutation events 1090 if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER)) 1091 c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode())); 1092 1093 // dispatch the DOMNodeRemovedFromDocument event to all descendants 1094 if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) { 1095 for (; c; c = c->traverseNextNode(child)) 1096 c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false)); 1097 } 1098 } 1099 1100 bool ContainerNode::dispatchBeforeLoadEvent(const String& sourceURL) 1101 { 1102 if (!document()->hasListenerType(Document::BEFORELOAD_LISTENER)) 1103 return true; 1104 1105 RefPtr<ContainerNode> protector(this); 1106 RefPtr<BeforeLoadEvent> beforeLoadEvent = BeforeLoadEvent::create(sourceURL); 1107 dispatchEvent(beforeLoadEvent.get()); 1108 return !beforeLoadEvent->defaultPrevented(); 1109 } 1110 1111 } // namespace WebCore 1112