• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         if (attached() && !child->attached())
94             child->attach();
95     }
96 }
97 
~ContainerNode()98 ContainerNode::~ContainerNode()
99 {
100     removeAllChildren();
101 }
102 
insertBefore(PassRefPtr<Node> newChild,Node * refChild,ExceptionCode & ec,bool shouldLazyAttach)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 
insertBeforeCommon(Node * nextChild,Node * newChild)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 
parserInsertBefore(PassRefPtr<Node> newChild,Node * nextChild)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 
replaceChild(PassRefPtr<Node> newChild,Node * oldChild,ExceptionCode & ec,bool shouldLazyAttach)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 
willRemove()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 
willRemoveChild(Node * child)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 
willRemoveChildren(ContainerNode * container)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 
removeChild(Node * oldChild,ExceptionCode & ec)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 
removeBetween(Node * previousChild,Node * nextChild,Node * oldChild)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 
parserRemoveChild(Node * oldChild)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.
removeChildren()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 
appendChild(PassRefPtr<Node> newChild,ExceptionCode & ec,bool shouldLazyAttach)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 
parserAddChild(PassRefPtr<Node> newChild)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 
deprecatedParserAddChild(PassRefPtr<Node> node)670 void ContainerNode::deprecatedParserAddChild(PassRefPtr<Node> node)
671 {
672     parserAddChild(node);
673 }
674 
suspendPostAttachCallbacks()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 
resumePostAttachCallbacks()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 
queuePostAttachCallback(NodeCallback callback,Node * node)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 
postAttachCallbacksAreSuspended()713 bool ContainerNode::postAttachCallbacksAreSuspended()
714 {
715     return s_attachDepth;
716 }
717 
dispatchPostAttachCallbacks()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 
attach()732 void ContainerNode::attach()
733 {
734     for (Node* child = m_firstChild; child; child = child->nextSibling())
735         child->attach();
736     Node::attach();
737 }
738 
detach()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 
insertedIntoDocument()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 
removedFromDocument()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 
insertedIntoTree(bool deep)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 
removedFromTree(bool deep)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 
childrenChanged(bool changedByParser,Node * beforeChange,Node * afterChange,int childCountDelta)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 
cloneChildNodes(ContainerNode * clone)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 
getUpperLeftCorner(FloatPoint & point) const819 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.
getLowerRightCorner(FloatPoint & point) const883 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 
getRect() const932 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 
setFocus(bool received)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 
setActive(bool down,bool pause)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 
setHovered(bool over)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 
childNodeCount() const1023 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 
childNode(unsigned index) const1032 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 
notifyChildInserted(Node * child)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 
dispatchChildInsertionEvents(Node * child)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 
dispatchChildRemovalEvents(Node * child)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 
dispatchBeforeLoadEvent(const String & sourceURL)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