cloneChildNodes looks for deleteButtonController in each level of recursion
[WebKit-https.git] / Source / WebCore / dom / ContainerNode.cpp
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, 2010, 2011, 2012, 2013 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 "AXObjectCache.h"
27 #include "ChildListMutationScope.h"
28 #include "Chrome.h"
29 #include "ChromeClient.h"
30 #include "ContainerNodeAlgorithms.h"
31 #include "Editor.h"
32 #include "EventNames.h"
33 #include "ExceptionCode.h"
34 #include "FloatRect.h"
35 #include "Frame.h"
36 #include "FrameView.h"
37 #include "HTMLNames.h"
38 #include "InlineTextBox.h"
39 #include "InsertionPoint.h"
40 #include "InspectorInstrumentation.h"
41 #include "JSNode.h"
42 #include "LoaderStrategy.h"
43 #include "MemoryCache.h"
44 #include "MutationEvent.h"
45 #include "NodeRenderStyle.h"
46 #include "NodeTraversal.h"
47 #include "Page.h"
48 #include "PlatformStrategies.h"
49 #include "RenderBox.h"
50 #include "RenderTheme.h"
51 #include "RenderWidget.h"
52 #include "ResourceLoadScheduler.h"
53 #include "RootInlineBox.h"
54 #include "TemplateContentDocumentFragment.h"
55 #include <wtf/CurrentTime.h>
56 #include <wtf/Vector.h>
57
58 #if ENABLE(DELETION_UI)
59 #include "DeleteButtonController.h"
60 #endif
61
62 using namespace std;
63
64 namespace WebCore {
65
66 static void dispatchChildInsertionEvents(Node*);
67 static void dispatchChildRemovalEvents(Node*);
68 static void updateTreeAfterInsertion(ContainerNode*, Node*, AttachBehavior);
69
70 typedef pair<RefPtr<Node>, unsigned> CallbackParameters;
71 typedef pair<NodeCallback, CallbackParameters> CallbackInfo;
72 typedef Vector<CallbackInfo> NodeCallbackQueue;
73
74 static NodeCallbackQueue* s_postAttachCallbackQueue;
75
76 static size_t s_attachDepth;
77 static bool s_shouldReEnableMemoryCacheCallsAfterAttach;
78
79 ChildNodesLazySnapshot* ChildNodesLazySnapshot::latestSnapshot = 0;
80
81 #ifndef NDEBUG
82 unsigned NoEventDispatchAssertion::s_count = 0;
83 #endif
84
85 static void collectChildrenAndRemoveFromOldParent(Node* node, NodeVector& nodes, ExceptionCode& ec)
86 {
87     if (node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE) {
88         nodes.append(node);
89         if (ContainerNode* oldParent = node->parentNode())
90             oldParent->removeChild(node, ec);
91         return;
92     }
93     getChildNodes(node, nodes);
94     toContainerNode(node)->removeChildren();
95 }
96
97 void ContainerNode::removeDetachedChildren()
98 {
99     if (connectedSubframeCount()) {
100         for (Node* child = firstChild(); child; child = child->nextSibling())
101             child->updateAncestorConnectedSubframeCountForRemoval();
102     }
103     // FIXME: We should be able to ASSERT(!attached()) here: https://bugs.webkit.org/show_bug.cgi?id=107801
104     removeDetachedChildrenInContainer<Node, ContainerNode>(this);
105 }
106
107 void ContainerNode::takeAllChildrenFrom(ContainerNode* oldParent)
108 {
109     NodeVector children;
110     getChildNodes(oldParent, children);
111
112     if (oldParent->document()->hasMutationObserversOfType(MutationObserver::ChildList)) {
113         ChildListMutationScope mutation(oldParent);
114         for (unsigned i = 0; i < children.size(); ++i)
115             mutation.willRemoveChild(children[i].get());
116     }
117
118     // FIXME: We need to do notifyMutationObserversNodeWillDetach() for each child,
119     // probably inside removeDetachedChildrenInContainer.
120
121     oldParent->removeDetachedChildren();
122
123     for (unsigned i = 0; i < children.size(); ++i) {
124         if (children[i]->attached())
125             children[i]->detach();
126         // FIXME: We need a no mutation event version of adoptNode.
127         RefPtr<Node> child = document()->adoptNode(children[i].release(), ASSERT_NO_EXCEPTION);
128         parserAppendChild(child.get());
129         // FIXME: Together with adoptNode above, the tree scope might get updated recursively twice
130         // (if the document changed or oldParent was in a shadow tree, AND *this is in a shadow tree).
131         // Can we do better?
132         treeScope()->adoptIfNeeded(child.get());
133         if (attached() && !child->attached())
134             child->attach();
135     }
136 }
137
138 ContainerNode::~ContainerNode()
139 {
140     if (Document* document = documentInternal())
141         willBeDeletedFrom(document);
142     removeDetachedChildren();
143 }
144
145 static inline bool isChildTypeAllowed(ContainerNode* newParent, Node* child)
146 {
147     if (!child->isDocumentFragment())
148         return newParent->childTypeAllowed(child->nodeType());
149
150     for (Node* node = child->firstChild(); node; node = node->nextSibling()) {
151         if (!newParent->childTypeAllowed(node->nodeType()))
152             return false;
153     }
154     return true;
155 }
156
157 static inline bool isInTemplateContent(const Node* node)
158 {
159 #if ENABLE(TEMPLATE_ELEMENT)
160     Document* document = node->document();
161     return document && document == document->templateDocument();
162 #else
163     UNUSED_PARAM(node);
164     return false;
165 #endif
166 }
167
168 static inline bool containsConsideringHostElements(const Node* newChild, const Node* newParent)
169 {
170     return (newParent->isInShadowTree() || isInTemplateContent(newParent))
171         ? newChild->containsIncludingHostElements(newParent)
172         : newChild->contains(newParent);
173 }
174
175 static inline ExceptionCode checkAcceptChild(ContainerNode* newParent, Node* newChild, Node* oldChild)
176 {
177     // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
178     if (!newChild)
179         return NOT_FOUND_ERR;
180
181     // Use common case fast path if possible.
182     if ((newChild->isElementNode() || newChild->isTextNode()) && newParent->isElementNode()) {
183         ASSERT(!newParent->isReadOnlyNode());
184         ASSERT(!newParent->isDocumentTypeNode());
185         ASSERT(isChildTypeAllowed(newParent, newChild));
186         if (containsConsideringHostElements(newChild, newParent))
187             return HIERARCHY_REQUEST_ERR;
188         return 0;
189     }
190
191     // This should never happen, but also protect release builds from tree corruption.
192     ASSERT(!newChild->isPseudoElement());
193     if (newChild->isPseudoElement())
194         return HIERARCHY_REQUEST_ERR;
195
196     if (newParent->isReadOnlyNode())
197         return NO_MODIFICATION_ALLOWED_ERR;
198     if (newChild->inDocument() && newChild->isDocumentTypeNode())
199         return HIERARCHY_REQUEST_ERR;
200     if (containsConsideringHostElements(newChild, newParent))
201         return HIERARCHY_REQUEST_ERR;
202
203     if (oldChild && newParent->isDocumentNode()) {
204         if (!toDocument(newParent)->canReplaceChild(newChild, oldChild))
205             return HIERARCHY_REQUEST_ERR;
206     } else if (!isChildTypeAllowed(newParent, newChild))
207         return HIERARCHY_REQUEST_ERR;
208
209     return 0;
210 }
211
212 static inline bool checkAcceptChildGuaranteedNodeTypes(ContainerNode* newParent, Node* newChild, ExceptionCode& ec)
213 {
214     ASSERT(!newParent->isReadOnlyNode());
215     ASSERT(!newParent->isDocumentTypeNode());
216     ASSERT(isChildTypeAllowed(newParent, newChild));
217     if (newChild->contains(newParent)) {
218         ec = HIERARCHY_REQUEST_ERR;
219         return false;
220     }
221
222     return true;
223 }
224
225 static inline bool checkAddChild(ContainerNode* newParent, Node* newChild, ExceptionCode& ec)
226 {
227     ec = checkAcceptChild(newParent, newChild, 0);
228     if (ec)
229         return false;
230
231     return true;
232 }
233
234 static inline bool checkReplaceChild(ContainerNode* newParent, Node* newChild, Node* oldChild, ExceptionCode& ec)
235 {
236     ec = checkAcceptChild(newParent, newChild, oldChild);
237     if (ec)
238         return false;
239
240     return true;
241 }
242
243 bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, AttachBehavior attachBehavior)
244 {
245     // Check that this node is not "floating".
246     // If it is, it can be deleted as a side effect of sending mutation events.
247     ASSERT(refCount() || parentOrShadowHostNode());
248
249     RefPtr<Node> protect(this);
250
251     ec = 0;
252
253     // insertBefore(node, 0) is equivalent to appendChild(node)
254     if (!refChild)
255         return appendChild(newChild, ec, attachBehavior);
256
257     // Make sure adding the new child is OK.
258     if (!checkAddChild(this, newChild.get(), ec))
259         return false;
260
261     // NOT_FOUND_ERR: Raised if refChild is not a child of this node
262     if (refChild->parentNode() != this) {
263         ec = NOT_FOUND_ERR;
264         return false;
265     }
266
267     if (refChild->previousSibling() == newChild || refChild == newChild) // nothing to do
268         return true;
269
270     RefPtr<Node> next = refChild;
271
272     NodeVector targets;
273     collectChildrenAndRemoveFromOldParent(newChild.get(), targets, ec);
274     if (ec)
275         return false;
276     if (targets.isEmpty())
277         return true;
278
279     // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events.
280     if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), ec))
281         return false;
282
283     InspectorInstrumentation::willInsertDOMNode(document(), this);
284
285     ChildListMutationScope mutation(this);
286     for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
287         Node* child = it->get();
288
289         // Due to arbitrary code running in response to a DOM mutation event it's
290         // possible that "next" is no longer a child of "this".
291         // It's also possible that "child" has been inserted elsewhere.
292         // In either of those cases, we'll just stop.
293         if (next->parentNode() != this)
294             break;
295         if (child->parentNode())
296             break;
297
298         treeScope()->adoptIfNeeded(child);
299
300         insertBeforeCommon(next.get(), child);
301
302         updateTreeAfterInsertion(this, child, attachBehavior);
303     }
304
305     dispatchSubtreeModifiedEvent();
306     return true;
307 }
308
309 void ContainerNode::insertBeforeCommon(Node* nextChild, Node* newChild)
310 {
311     NoEventDispatchAssertion assertNoEventDispatch;
312
313     ASSERT(newChild);
314     ASSERT(!newChild->parentNode()); // Use insertBefore if you need to handle reparenting (and want DOM mutation events).
315     ASSERT(!newChild->nextSibling());
316     ASSERT(!newChild->previousSibling());
317     ASSERT(!newChild->isShadowRoot());
318
319     Node* prev = nextChild->previousSibling();
320     ASSERT(m_lastChild != prev);
321     nextChild->setPreviousSibling(newChild);
322     if (prev) {
323         ASSERT(m_firstChild != nextChild);
324         ASSERT(prev->nextSibling() == nextChild);
325         prev->setNextSibling(newChild);
326     } else {
327         ASSERT(m_firstChild == nextChild);
328         m_firstChild = newChild;
329     }
330     newChild->setParentOrShadowHostNode(this);
331     newChild->setPreviousSibling(prev);
332     newChild->setNextSibling(nextChild);
333 }
334
335 void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node* nextChild)
336 {
337     ASSERT(newChild);
338     ASSERT(nextChild);
339     ASSERT(nextChild->parentNode() == this);
340     ASSERT(!newChild->isDocumentFragment());
341 #if ENABLE(TEMPLATE_ELEMENT)
342     ASSERT(!hasTagName(HTMLNames::templateTag));
343 #endif
344
345     if (nextChild->previousSibling() == newChild || nextChild == newChild) // nothing to do
346         return;
347
348     if (document() != newChild->document())
349         document()->adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
350
351     insertBeforeCommon(nextChild, newChild.get());
352
353     newChild->updateAncestorConnectedSubframeCountForInsertion();
354
355     ChildListMutationScope(this).childAdded(newChild.get());
356
357     childrenChanged(true, newChild->previousSibling(), nextChild, 1);
358     ChildNodeInsertionNotifier(this).notify(newChild.get());
359 }
360
361 bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, AttachBehavior attachBehavior)
362 {
363     // Check that this node is not "floating".
364     // If it is, it can be deleted as a side effect of sending mutation events.
365     ASSERT(refCount() || parentOrShadowHostNode());
366
367     RefPtr<Node> protect(this);
368
369     ec = 0;
370
371     if (oldChild == newChild) // nothing to do
372         return true;
373
374     if (!oldChild) {
375         ec = NOT_FOUND_ERR;
376         return false;
377     }
378
379     // Make sure replacing the old child with the new is ok
380     if (!checkReplaceChild(this, newChild.get(), oldChild, ec))
381         return false;
382
383     // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
384     if (oldChild->parentNode() != this) {
385         ec = NOT_FOUND_ERR;
386         return false;
387     }
388
389     ChildListMutationScope mutation(this);
390
391     RefPtr<Node> next = oldChild->nextSibling();
392
393     // Remove the node we're replacing
394     RefPtr<Node> removedChild = oldChild;
395     removeChild(oldChild, ec);
396     if (ec)
397         return false;
398
399     if (next && (next->previousSibling() == newChild || next == newChild)) // nothing to do
400         return true;
401
402     // Does this one more time because removeChild() fires a MutationEvent.
403     if (!checkReplaceChild(this, newChild.get(), oldChild, ec))
404         return false;
405
406     NodeVector targets;
407     collectChildrenAndRemoveFromOldParent(newChild.get(), targets, ec);
408     if (ec)
409         return false;
410
411     // Does this yet another check because collectChildrenAndRemoveFromOldParent() fires a MutationEvent.
412     if (!checkReplaceChild(this, newChild.get(), oldChild, ec))
413         return false;
414
415     InspectorInstrumentation::willInsertDOMNode(document(), this);
416
417     // Add the new child(ren)
418     for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
419         Node* child = it->get();
420
421         // Due to arbitrary code running in response to a DOM mutation event it's
422         // possible that "next" is no longer a child of "this".
423         // It's also possible that "child" has been inserted elsewhere.
424         // In either of those cases, we'll just stop.
425         if (next && next->parentNode() != this)
426             break;
427         if (child->parentNode())
428             break;
429
430         treeScope()->adoptIfNeeded(child);
431
432         // Add child before "next".
433         {
434             NoEventDispatchAssertion assertNoEventDispatch;
435             if (next)
436                 insertBeforeCommon(next.get(), child);
437             else
438                 appendChildToContainer(child, this);
439         }
440
441         updateTreeAfterInsertion(this, child, attachBehavior);
442     }
443
444     dispatchSubtreeModifiedEvent();
445     return true;
446 }
447
448 static void willRemoveChild(Node* child)
449 {
450     ASSERT(child->parentNode());
451     ChildListMutationScope(child->parentNode()).willRemoveChild(child);
452     child->notifyMutationObserversNodeWillDetach();
453     dispatchChildRemovalEvents(child);
454     child->document()->nodeWillBeRemoved(child); // e.g. mutation event listener can create a new range.
455     ChildFrameDisconnector(child).disconnect();
456 }
457
458 static void willRemoveChildren(ContainerNode* container)
459 {
460     NodeVector children;
461     getChildNodes(container, children);
462
463     container->document()->nodeChildrenWillBeRemoved(container);
464
465     ChildListMutationScope mutation(container);
466     for (NodeVector::const_iterator it = children.begin(); it != children.end(); ++it) {
467         Node* child = it->get();
468         mutation.willRemoveChild(child);
469         child->notifyMutationObserversNodeWillDetach();
470
471         // fire removed from document mutation events.
472         dispatchChildRemovalEvents(child);
473     }
474
475     ChildFrameDisconnector(container).disconnect(ChildFrameDisconnector::DescendantsOnly);
476 }
477
478 void ContainerNode::disconnectDescendantFrames()
479 {
480     ChildFrameDisconnector(this).disconnect();
481 }
482
483 bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec)
484 {
485     // Check that this node is not "floating".
486     // If it is, it can be deleted as a side effect of sending mutation events.
487     ASSERT(refCount() || parentOrShadowHostNode());
488
489     RefPtr<Node> protect(this);
490
491     ec = 0;
492
493     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
494     if (isReadOnlyNode()) {
495         ec = NO_MODIFICATION_ALLOWED_ERR;
496         return false;
497     }
498
499     // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
500     if (!oldChild || oldChild->parentNode() != this) {
501         ec = NOT_FOUND_ERR;
502         return false;
503     }
504
505     RefPtr<Node> child = oldChild;
506
507     document()->removeFocusedNodeOfSubtree(child.get());
508
509 #if ENABLE(FULLSCREEN_API)
510     document()->removeFullScreenElementOfSubtree(child.get());
511 #endif
512
513     // Events fired when blurring currently focused node might have moved this
514     // child into a different parent.
515     if (child->parentNode() != this) {
516         ec = NOT_FOUND_ERR;
517         return false;
518     }
519
520     willRemoveChild(child.get());
521
522     // Mutation events might have moved this child into a different parent.
523     if (child->parentNode() != this) {
524         ec = NOT_FOUND_ERR;
525         return false;
526     }
527
528     {
529         WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
530
531         Node* prev = child->previousSibling();
532         Node* next = child->nextSibling();
533         removeBetween(prev, next, child.get());
534         childrenChanged(false, prev, next, -1);
535         ChildNodeRemovalNotifier(this).notify(child.get());
536     }
537     dispatchSubtreeModifiedEvent();
538
539     return child;
540 }
541
542 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node* oldChild)
543 {
544     NoEventDispatchAssertion assertNoEventDispatch;
545
546     ASSERT(oldChild);
547     ASSERT(oldChild->parentNode() == this);
548
549     // Remove from rendering tree
550     if (oldChild->attached())
551         oldChild->detach();
552
553     if (nextChild)
554         nextChild->setPreviousSibling(previousChild);
555     if (previousChild)
556         previousChild->setNextSibling(nextChild);
557     if (m_firstChild == oldChild)
558         m_firstChild = nextChild;
559     if (m_lastChild == oldChild)
560         m_lastChild = previousChild;
561
562     oldChild->setPreviousSibling(0);
563     oldChild->setNextSibling(0);
564     oldChild->setParentOrShadowHostNode(0);
565
566     document()->adoptIfNeeded(oldChild);
567 }
568
569 void ContainerNode::parserRemoveChild(Node* oldChild)
570 {
571     ASSERT(oldChild);
572     ASSERT(oldChild->parentNode() == this);
573     ASSERT(!oldChild->isDocumentFragment());
574
575     Node* prev = oldChild->previousSibling();
576     Node* next = oldChild->nextSibling();
577
578     oldChild->updateAncestorConnectedSubframeCountForRemoval();
579
580     ChildListMutationScope(this).willRemoveChild(oldChild);
581     oldChild->notifyMutationObserversNodeWillDetach();
582
583     removeBetween(prev, next, oldChild);
584
585     childrenChanged(true, prev, next, -1);
586     ChildNodeRemovalNotifier(this).notify(oldChild);
587 }
588
589 // this differs from other remove functions because it forcibly removes all the children,
590 // regardless of read-only status or event exceptions, e.g.
591 void ContainerNode::removeChildren()
592 {
593     if (!m_firstChild)
594         return;
595
596     // The container node can be removed from event handlers.
597     RefPtr<ContainerNode> protect(this);
598
599     // exclude this node when looking for removed focusedNode since only children will be removed
600     document()->removeFocusedNodeOfSubtree(this, true);
601
602 #if ENABLE(FULLSCREEN_API)
603     document()->removeFullScreenElementOfSubtree(this, true);
604 #endif
605
606     // Do any prep work needed before actually starting to detach
607     // and remove... e.g. stop loading frames, fire unload events.
608     willRemoveChildren(protect.get());
609
610     Vector<RefPtr<Node>, 10> removedChildren;
611     {
612         WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
613         {
614             NoEventDispatchAssertion assertNoEventDispatch;
615             removedChildren.reserveInitialCapacity(childNodeCount());
616             while (RefPtr<Node> n = m_firstChild) {
617                 Node* next = n->nextSibling();
618
619                 if (n->attached())
620                     n->detach();
621
622                 n->setPreviousSibling(0);
623                 n->setNextSibling(0);
624                 n->setParentOrShadowHostNode(0);
625                 document()->adoptIfNeeded(n.get());
626
627                 m_firstChild = next;
628                 if (n == m_lastChild)
629                     m_lastChild = 0;
630                 else
631                     m_firstChild->setPreviousSibling(0);
632
633                 removedChildren.append(n.release());
634             }
635         }
636
637         childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size()));
638         
639         for (size_t i = 0; i < removedChildren.size(); ++i)
640             ChildNodeRemovalNotifier(this).notify(removedChildren[i].get());
641     }
642
643     dispatchSubtreeModifiedEvent();
644 }
645
646 bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, AttachBehavior attachBehavior)
647 {
648     RefPtr<ContainerNode> protect(this);
649
650     // Check that this node is not "floating".
651     // If it is, it can be deleted as a side effect of sending mutation events.
652     ASSERT(refCount() || parentOrShadowHostNode());
653
654     ec = 0;
655
656     // Make sure adding the new child is ok
657     if (!checkAddChild(this, newChild.get(), ec))
658         return false;
659
660     if (newChild == m_lastChild) // nothing to do
661         return newChild;
662
663     NodeVector targets;
664     collectChildrenAndRemoveFromOldParent(newChild.get(), targets, ec);
665     if (ec)
666         return false;
667
668     if (targets.isEmpty())
669         return true;
670
671     // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events.
672     if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), ec))
673         return false;
674
675     InspectorInstrumentation::willInsertDOMNode(document(), this);
676
677     // Now actually add the child(ren)
678     ChildListMutationScope mutation(this);
679     for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
680         Node* child = it->get();
681
682         // If the child has a parent again, just stop what we're doing, because
683         // that means someone is doing something with DOM mutation -- can't re-parent
684         // a child that already has a parent.
685         if (child->parentNode())
686             break;
687
688         treeScope()->adoptIfNeeded(child);
689
690         // Append child to the end of the list
691         {
692             NoEventDispatchAssertion assertNoEventDispatch;
693             appendChildToContainer(child, this);
694         }
695
696         updateTreeAfterInsertion(this, child, attachBehavior);
697     }
698
699     dispatchSubtreeModifiedEvent();
700     return true;
701 }
702
703 void ContainerNode::parserAppendChild(PassRefPtr<Node> newChild)
704 {
705     ASSERT(newChild);
706     ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle reparenting (and want DOM mutation events).
707     ASSERT(!newChild->isDocumentFragment());
708 #if ENABLE(TEMPLATE_ELEMENT)
709     ASSERT(!hasTagName(HTMLNames::templateTag));
710 #endif
711
712     if (document() != newChild->document())
713         document()->adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
714
715     Node* last = m_lastChild;
716     {
717         NoEventDispatchAssertion assertNoEventDispatch;
718         // FIXME: This method should take a PassRefPtr.
719         appendChildToContainer(newChild.get(), this);
720         treeScope()->adoptIfNeeded(newChild.get());
721     }
722
723     newChild->updateAncestorConnectedSubframeCountForInsertion();
724
725     ChildListMutationScope(this).childAdded(newChild.get());
726
727     childrenChanged(true, last, 0, 1);
728     ChildNodeInsertionNotifier(this).notify(newChild.get());
729 }
730
731 void ContainerNode::suspendPostAttachCallbacks()
732 {
733     if (!s_attachDepth) {
734         ASSERT(!s_shouldReEnableMemoryCacheCallsAfterAttach);
735         if (Page* page = document()->page()) {
736             // FIXME: How can this call be specific to one Page, while the
737             // s_attachDepth is a global? Doesn't make sense.
738             if (page->areMemoryCacheClientCallsEnabled()) {
739                 page->setMemoryCacheClientCallsEnabled(false);
740                 s_shouldReEnableMemoryCacheCallsAfterAttach = true;
741             }
742         }
743 #if USE(PLATFORM_STRATEGIES)
744         platformStrategies()->loaderStrategy()->resourceLoadScheduler()->suspendPendingRequests();
745 #else
746         resourceLoadScheduler()->suspendPendingRequests();
747 #endif
748     }
749     ++s_attachDepth;
750 }
751
752 void ContainerNode::resumePostAttachCallbacks()
753 {
754     if (s_attachDepth == 1) {
755         RefPtr<ContainerNode> protect(this);
756
757         if (s_postAttachCallbackQueue)
758             dispatchPostAttachCallbacks();
759         if (s_shouldReEnableMemoryCacheCallsAfterAttach) {
760             s_shouldReEnableMemoryCacheCallsAfterAttach = false;
761             if (Page* page = document()->page())
762                 page->setMemoryCacheClientCallsEnabled(true);
763         }
764 #if USE(PLATFORM_STRATEGIES)
765         platformStrategies()->loaderStrategy()->resourceLoadScheduler()->resumePendingRequests();
766 #else
767         resourceLoadScheduler()->resumePendingRequests();
768 #endif
769     }
770     --s_attachDepth;
771 }
772
773 void ContainerNode::queuePostAttachCallback(NodeCallback callback, Node* node, unsigned callbackData)
774 {
775     if (!s_postAttachCallbackQueue)
776         s_postAttachCallbackQueue = new NodeCallbackQueue;
777     
778     s_postAttachCallbackQueue->append(CallbackInfo(callback, CallbackParameters(node, callbackData)));
779 }
780
781 bool ContainerNode::postAttachCallbacksAreSuspended()
782 {
783     return s_attachDepth;
784 }
785
786 void ContainerNode::dispatchPostAttachCallbacks()
787 {
788     // We recalculate size() each time through the loop because a callback
789     // can add more callbacks to the end of the queue.
790     for (size_t i = 0; i < s_postAttachCallbackQueue->size(); ++i) {
791         const CallbackInfo& info = (*s_postAttachCallbackQueue)[i];
792         NodeCallback callback = info.first;
793         CallbackParameters params = info.second;
794
795         callback(params.first.get(), params.second);
796     }
797     s_postAttachCallbackQueue->clear();
798 }
799
800 static void needsStyleRecalcCallback(Node* node, unsigned data)
801 {
802     node->setNeedsStyleRecalc(static_cast<StyleChangeType>(data));
803 }
804
805 void ContainerNode::scheduleSetNeedsStyleRecalc(StyleChangeType changeType)
806 {
807     if (postAttachCallbacksAreSuspended())
808         queuePostAttachCallback(needsStyleRecalcCallback, this, static_cast<unsigned>(changeType));
809     else
810         setNeedsStyleRecalc(changeType);
811 }
812
813 void ContainerNode::attach()
814 {
815     attachChildren();
816     Node::attach();
817 }
818
819 void ContainerNode::detach()
820 {
821     detachChildren();
822     clearChildNeedsStyleRecalc();
823     Node::detach();
824 }
825
826 void ContainerNode::childrenChanged(bool changedByParser, Node*, Node*, int childCountDelta)
827 {
828     document()->incDOMTreeVersion();
829     if (!changedByParser && childCountDelta)
830         document()->updateRangesAfterChildrenChanged(this);
831     invalidateNodeListCachesInAncestors();
832 }
833
834 inline static void cloneChildNodesAvoidingDeleteButton(ContainerNode* parent, ContainerNode* clonedParent, HTMLElement* deleteButtonContainerElement)
835 {
836     ExceptionCode ec = 0;
837     for (Node* child = parent->firstChild(); child && !ec; child = child->nextSibling()) {
838
839 #if ENABLE(DELETION_UI)
840         if (child == deleteButtonContainerElement)
841             continue;
842 #else
843         UNUSED_PARAM(deleteButtonContainerElement);
844 #endif
845
846         RefPtr<Node> clonedChild = child->cloneNode(false);
847         clonedParent->appendChild(clonedChild, ec);
848
849         if (!ec && child->isContainerNode())
850             cloneChildNodesAvoidingDeleteButton(toContainerNode(child), toContainerNode(clonedChild.get()), deleteButtonContainerElement);
851     }
852 }
853
854 void ContainerNode::cloneChildNodes(ContainerNode *clone)
855 {
856 #if ENABLE(DELETION_UI)
857     HTMLElement* deleteButtonContainerElement = 0;
858     if (Frame* frame = document()->frame())
859         deleteButtonContainerElement = frame->editor()->deleteButtonController()->containerElement();
860     cloneChildNodesAvoidingDeleteButton(this, clone, deleteButtonContainerElement);
861 #else
862     cloneChildNodesAvoidingDeleteButton(this, clone, 0);
863 #endif
864 }
865
866 bool ContainerNode::getUpperLeftCorner(FloatPoint& point) const
867 {
868     if (!renderer())
869         return false;
870     // What is this code really trying to do?
871     RenderObject* o = renderer();
872     RenderObject* p = o;
873
874     if (!o->isInline() || o->isReplaced()) {
875         point = o->localToAbsolute(FloatPoint(), UseTransforms);
876         return true;
877     }
878
879     // find the next text/image child, to get a position
880     while (o) {
881         p = o;
882         if (o->firstChild())
883             o = o->firstChild();
884         else if (o->nextSibling())
885             o = o->nextSibling();
886         else {
887             RenderObject* next = 0;
888             while (!next && o->parent()) {
889                 o = o->parent();
890                 next = o->nextSibling();
891             }
892             o = next;
893
894             if (!o)
895                 break;
896         }
897         ASSERT(o);
898
899         if (!o->isInline() || o->isReplaced()) {
900             point = o->localToAbsolute(FloatPoint(), UseTransforms);
901             return true;
902         }
903
904         if (p->node() && p->node() == this && o->isText() && !o->isBR() && !toRenderText(o)->firstTextBox()) {
905             // do nothing - skip unrendered whitespace that is a child or next sibling of the anchor
906         } else if ((o->isText() && !o->isBR()) || o->isReplaced()) {
907             point = FloatPoint();
908             if (o->isText() && toRenderText(o)->firstTextBox()) {
909                 point.move(toRenderText(o)->linesBoundingBox().x(), toRenderText(o)->firstTextBox()->root()->lineTop());
910             } else if (o->isBox()) {
911                 RenderBox* box = toRenderBox(o);
912                 point.moveBy(box->location());
913             }
914             point = o->container()->localToAbsolute(point, UseTransforms);
915             return true;
916         }
917     }
918     
919     // If the target doesn't have any children or siblings that could be used to calculate the scroll position, we must be
920     // at the end of the document. Scroll to the bottom. FIXME: who said anything about scrolling?
921     if (!o && document()->view()) {
922         point = FloatPoint(0, document()->view()->contentsHeight());
923         return true;
924     }
925     return false;
926 }
927
928 bool ContainerNode::getLowerRightCorner(FloatPoint& point) const
929 {
930     if (!renderer())
931         return false;
932
933     RenderObject* o = renderer();
934     if (!o->isInline() || o->isReplaced()) {
935         RenderBox* box = toRenderBox(o);
936         point = o->localToAbsolute(LayoutPoint(box->size()), UseTransforms);
937         return true;
938     }
939
940     // find the last text/image child, to get a position
941     while (o) {
942         if (o->lastChild())
943             o = o->lastChild();
944         else if (o->previousSibling())
945             o = o->previousSibling();
946         else {
947             RenderObject* prev = 0;
948             while (!prev) {
949                 o = o->parent();
950                 if (!o)
951                     return false;
952                 prev = o->previousSibling();
953             }
954             o = prev;
955         }
956         ASSERT(o);
957         if (o->isText() || o->isReplaced()) {
958             point = FloatPoint();
959             if (o->isText()) {
960                 RenderText* text = toRenderText(o);
961                 IntRect linesBox = text->linesBoundingBox();
962                 if (!linesBox.maxX() && !linesBox.maxY())
963                     continue;
964                 point.moveBy(linesBox.maxXMaxYCorner());
965             } else {
966                 RenderBox* box = toRenderBox(o);
967                 point.moveBy(box->frameRect().maxXMaxYCorner());
968             }
969             point = o->container()->localToAbsolute(point, UseTransforms);
970             return true;
971         }
972     }
973     return true;
974 }
975
976 LayoutRect ContainerNode::boundingBox() const
977 {
978     FloatPoint upperLeft, lowerRight;
979     bool foundUpperLeft = getUpperLeftCorner(upperLeft);
980     bool foundLowerRight = getLowerRightCorner(lowerRight);
981     
982     // If we've found one corner, but not the other,
983     // then we should just return a point at the corner that we did find.
984     if (foundUpperLeft != foundLowerRight) {
985         if (foundUpperLeft)
986             lowerRight = upperLeft;
987         else
988             upperLeft = lowerRight;
989     } 
990
991     return enclosingLayoutRect(FloatRect(upperLeft, lowerRight.expandedTo(upperLeft) - upperLeft));
992 }
993
994 void ContainerNode::setFocus(bool received)
995 {
996     if (focused() == received)
997         return;
998
999     Node::setFocus(received);
1000
1001     // note that we need to recalc the style
1002     setNeedsStyleRecalc();
1003 }
1004
1005 void ContainerNode::setActive(bool down, bool pause)
1006 {
1007     if (down == active()) return;
1008
1009     Node::setActive(down);
1010
1011     // note that we need to recalc the style
1012     // FIXME: Move to Element
1013     if (renderer()) {
1014         bool reactsToPress = renderStyle()->affectedByActive() || (isElementNode() && toElement(this)->childrenAffectedByActive());
1015         if (reactsToPress)
1016             setNeedsStyleRecalc();
1017         if (renderStyle()->hasAppearance()) {
1018             if (renderer()->theme()->stateChanged(renderer(), PressedState))
1019                 reactsToPress = true;
1020         }
1021
1022         // The rest of this function implements a feature that only works if the
1023         // platform supports immediate invalidations on the ChromeClient, so bail if
1024         // that isn't supported.
1025         if (!document()->page()->chrome()->client()->supportsImmediateInvalidation())
1026             return;
1027
1028         if (reactsToPress && pause) {
1029             // The delay here is subtle.  It relies on an assumption, namely that the amount of time it takes
1030             // to repaint the "down" state of the control is about the same time as it would take to repaint the
1031             // "up" state.  Once you assume this, you can just delay for 100ms - that time (assuming that after you
1032             // leave this method, it will be about that long before the flush of the up state happens again).
1033 #ifdef HAVE_FUNC_USLEEP
1034             double startTime = currentTime();
1035 #endif
1036
1037             // Ensure there are no pending changes
1038             Document::updateStyleForAllDocuments();
1039             // Do an immediate repaint.
1040             if (renderer())
1041                 renderer()->repaint(true);
1042
1043             // FIXME: Find a substitute for usleep for Win32.
1044             // Better yet, come up with a way of doing this that doesn't use this sort of thing at all.
1045 #ifdef HAVE_FUNC_USLEEP
1046             // Now pause for a small amount of time (1/10th of a second from before we repainted in the pressed state)
1047             double remainingTime = 0.1 - (currentTime() - startTime);
1048             if (remainingTime > 0)
1049                 usleep(static_cast<useconds_t>(remainingTime * 1000000.0));
1050 #endif
1051         }
1052     }
1053 }
1054
1055 void ContainerNode::setHovered(bool over)
1056 {
1057     if (over == hovered()) return;
1058
1059     Node::setHovered(over);
1060
1061     // note that we need to recalc the style
1062     // FIXME: Move to Element
1063     if (renderer()) {
1064         if (renderStyle()->affectedByHover() || (isElementNode() && toElement(this)->childrenAffectedByHover()))
1065             setNeedsStyleRecalc();
1066         if (renderer() && renderer()->style()->hasAppearance())
1067             renderer()->theme()->stateChanged(renderer(), HoverState);
1068     }
1069 }
1070
1071 unsigned ContainerNode::childNodeCount() const
1072 {
1073     unsigned count = 0;
1074     Node *n;
1075     for (n = firstChild(); n; n = n->nextSibling())
1076         count++;
1077     return count;
1078 }
1079
1080 Node *ContainerNode::childNode(unsigned index) const
1081 {
1082     unsigned i;
1083     Node *n = firstChild();
1084     for (i = 0; n != 0 && i < index; i++)
1085         n = n->nextSibling();
1086     return n;
1087 }
1088
1089 static void dispatchChildInsertionEvents(Node* child)
1090 {
1091     if (child->isInShadowTree())
1092         return;
1093
1094     ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
1095
1096     RefPtr<Node> c = child;
1097     RefPtr<Document> document = child->document();
1098
1099     if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER))
1100         c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode()));
1101
1102     // dispatch the DOMNodeInsertedIntoDocument event to all descendants
1103     if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) {
1104         for (; c; c = NodeTraversal::next(c.get(), child))
1105             c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false));
1106     }
1107 }
1108
1109 static void dispatchChildRemovalEvents(Node* child)
1110 {
1111     if (child->isInShadowTree()) {
1112         InspectorInstrumentation::willRemoveDOMNode(child->document(), child);
1113         return;
1114     }
1115
1116     ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
1117
1118     willCreatePossiblyOrphanedTreeByRemoval(child);
1119     InspectorInstrumentation::willRemoveDOMNode(child->document(), child);
1120
1121     RefPtr<Node> c = child;
1122     RefPtr<Document> document = child->document();
1123
1124     // dispatch pre-removal mutation events
1125     if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER))
1126         c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode()));
1127
1128     // dispatch the DOMNodeRemovedFromDocument event to all descendants
1129     if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) {
1130         for (; c; c = NodeTraversal::next(c.get(), child))
1131             c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false));
1132     }
1133 }
1134
1135 static void updateTreeAfterInsertion(ContainerNode* parent, Node* child, AttachBehavior attachBehavior)
1136 {
1137     ASSERT(parent->refCount());
1138     ASSERT(child->refCount());
1139
1140     ChildListMutationScope(parent).childAdded(child);
1141
1142     parent->childrenChanged(false, child->previousSibling(), child->nextSibling(), 1);
1143
1144     ChildNodeInsertionNotifier(parent).notify(child);
1145
1146     // FIXME: Attachment should be the first operation in this function, but some code
1147     // (for example, HTMLFormControlElement's autofocus support) requires this ordering.
1148     if (parent->attached() && !child->attached() && child->parentNode() == parent) {
1149         if (attachBehavior == AttachLazily)
1150             child->lazyAttach();
1151         else
1152             child->attach();
1153     }
1154
1155     dispatchChildInsertionEvents(child);
1156 }
1157
1158 #ifndef NDEBUG
1159 bool childAttachedAllowedWhenAttachingChildren(ContainerNode* node)
1160 {
1161     if (node->isShadowRoot())
1162         return true;
1163
1164     if (node->isInsertionPoint())
1165         return true;
1166
1167     if (node->isElementNode() && toElement(node)->shadow())
1168         return true;
1169
1170     return false;
1171 }
1172 #endif
1173
1174 } // namespace WebCore