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