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