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