Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / dom / ContainerNode.h
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, 2009, 2010, 2011 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
24 #ifndef ContainerNode_h
25 #define ContainerNode_h
26
27 #include "bindings/v8/ExceptionStatePlaceholder.h"
28 #include "core/dom/Node.h"
29 #include "wtf/OwnPtr.h"
30 #include "wtf/Vector.h"
31
32 namespace WebCore {
33
34 class ExceptionState;
35 class FloatPoint;
36 class HTMLCollection;
37
38 namespace Private {
39     template<class GenericNode, class GenericNodeContainer>
40     void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer&);
41 }
42
43 class NoEventDispatchAssertion {
44 public:
45     NoEventDispatchAssertion()
46     {
47 #ifndef NDEBUG
48         if (!isMainThread())
49             return;
50         s_count++;
51 #endif
52     }
53
54     ~NoEventDispatchAssertion()
55     {
56 #ifndef NDEBUG
57         if (!isMainThread())
58             return;
59         ASSERT(s_count);
60         s_count--;
61 #endif
62     }
63
64 #ifndef NDEBUG
65     static bool isEventDispatchForbidden()
66     {
67         if (!isMainThread())
68             return false;
69         return s_count;
70     }
71 #endif
72
73 private:
74 #ifndef NDEBUG
75     static unsigned s_count;
76 #endif
77 };
78
79 class ContainerNode : public Node {
80 public:
81     virtual ~ContainerNode();
82
83     Node* firstChild() const { return m_firstChild; }
84     Node* lastChild() const { return m_lastChild; }
85     bool hasChildNodes() const { return m_firstChild; }
86
87     bool hasOneChild() const { return m_firstChild && !m_firstChild->nextSibling(); }
88     bool hasOneTextChild() const { return hasOneChild() && m_firstChild->isTextNode(); }
89
90     // ParentNode interface API
91     PassRefPtr<HTMLCollection> children();
92     Element* firstElementChild() const;
93     Element* lastElementChild() const;
94     unsigned childElementCount() const;
95
96     unsigned childNodeCount() const;
97     Node* childNode(unsigned index) const;
98
99     PassRefPtr<Element> querySelector(const AtomicString& selectors, ExceptionState&);
100     PassRefPtr<NodeList> querySelectorAll(const AtomicString& selectors, ExceptionState&);
101
102     void insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionState& = ASSERT_NO_EXCEPTION);
103     void replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionState& = ASSERT_NO_EXCEPTION);
104     void removeChild(Node* child, ExceptionState& = ASSERT_NO_EXCEPTION);
105     void appendChild(PassRefPtr<Node> newChild, ExceptionState& = ASSERT_NO_EXCEPTION);
106
107     PassRefPtr<NodeList> getElementsByTagName(const AtomicString&);
108     PassRefPtr<NodeList> getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName);
109     PassRefPtr<NodeList> getElementsByName(const AtomicString& elementName);
110     PassRefPtr<NodeList> getElementsByClassName(const AtomicString& classNames);
111     PassRefPtr<RadioNodeList> radioNodeList(const AtomicString&, bool onlyMatchImgElements = false);
112
113     // These methods are only used during parsing.
114     // They don't send DOM mutation events or handle reparenting.
115     // However, arbitrary code may be run by beforeload handlers.
116     void parserAppendChild(PassRefPtr<Node>);
117     void parserRemoveChild(Node&);
118     void parserInsertBefore(PassRefPtr<Node> newChild, Node& refChild);
119     void parserTakeAllChildrenFrom(ContainerNode&);
120
121     void removeChildren();
122
123     void cloneChildNodes(ContainerNode* clone);
124
125     virtual void attach(const AttachContext& = AttachContext()) OVERRIDE;
126     virtual void detach(const AttachContext& = AttachContext()) OVERRIDE;
127     virtual LayoutRect boundingBox() const OVERRIDE FINAL;
128     virtual void setFocus(bool) OVERRIDE;
129     void focusStateChanged();
130     virtual void setActive(bool = true) OVERRIDE;
131     virtual void setHovered(bool = true) OVERRIDE;
132
133     // -----------------------------------------------------------------------------
134     // Notification of document structure changes (see core/dom/Node.h for more notification methods)
135
136     // Notifies the node that it's list of children have changed (either by adding or removing child nodes), or a child
137     // node that is of the type CDATA_SECTION_NODE, TEXT_NODE or COMMENT_NODE has changed its value.
138     virtual void childrenChanged(bool createdByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
139
140     void disconnectDescendantFrames();
141
142 protected:
143     ContainerNode(TreeScope*, ConstructionType = CreateContainer);
144
145     template<class GenericNode, class GenericNodeContainer>
146     friend void appendChildToContainer(GenericNode& child, GenericNodeContainer&);
147
148     template<class GenericNode, class GenericNodeContainer>
149     friend void Private::addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer&);
150
151     void removeDetachedChildren();
152     void setFirstChild(Node* child) { m_firstChild = child; }
153     void setLastChild(Node* child) { m_lastChild = child; }
154
155 private:
156     void removeBetween(Node* previousChild, Node* nextChild, Node& oldChild);
157     void insertBeforeCommon(Node& nextChild, Node& oldChild);
158     void updateTreeAfterInsertion(Node& child);
159     void willRemoveChildren();
160     void willRemoveChild(Node& child);
161
162     inline bool checkAcceptChildGuaranteedNodeTypes(const Node& newChild, ExceptionState&) const;
163     inline bool checkAcceptChild(const Node* newChild, const Node* oldChild, ExceptionState&) const;
164     inline bool containsConsideringHostElements(const Node&) const;
165     inline bool isChildTypeAllowed(const Node& child) const;
166
167     void attachChildren(const AttachContext& = AttachContext());
168     void detachChildren(const AttachContext& = AttachContext());
169
170     bool getUpperLeftCorner(FloatPoint&) const;
171     bool getLowerRightCorner(FloatPoint&) const;
172
173     Node* m_firstChild;
174     Node* m_lastChild;
175 };
176
177 #ifndef NDEBUG
178 bool childAttachedAllowedWhenAttachingChildren(ContainerNode*);
179 #endif
180
181 DEFINE_NODE_TYPE_CASTS(ContainerNode, isContainerNode());
182
183 inline ContainerNode::ContainerNode(TreeScope* treeScope, ConstructionType type)
184     : Node(treeScope, type)
185     , m_firstChild(0)
186     , m_lastChild(0)
187 {
188 }
189
190 inline void ContainerNode::attachChildren(const AttachContext& context)
191 {
192     AttachContext childrenContext(context);
193     childrenContext.resolvedStyle = 0;
194
195     for (Node* child = firstChild(); child; child = child->nextSibling()) {
196         ASSERT(child->needsAttach() || childAttachedAllowedWhenAttachingChildren(this));
197         if (child->needsAttach())
198             child->attach(childrenContext);
199     }
200 }
201
202 inline void ContainerNode::detachChildren(const AttachContext& context)
203 {
204     AttachContext childrenContext(context);
205     childrenContext.resolvedStyle = 0;
206
207     for (Node* child = firstChild(); child; child = child->nextSibling())
208         child->detach(childrenContext);
209 }
210
211 inline unsigned Node::childNodeCount() const
212 {
213     if (!isContainerNode())
214         return 0;
215     return toContainerNode(this)->childNodeCount();
216 }
217
218 inline Node* Node::childNode(unsigned index) const
219 {
220     if (!isContainerNode())
221         return 0;
222     return toContainerNode(this)->childNode(index);
223 }
224
225 inline Node* Node::firstChild() const
226 {
227     if (!isContainerNode())
228         return 0;
229     return toContainerNode(this)->firstChild();
230 }
231
232 inline Node* Node::lastChild() const
233 {
234     if (!isContainerNode())
235         return 0;
236     return toContainerNode(this)->lastChild();
237 }
238
239 inline Node* Node::highestAncestor() const
240 {
241     Node* node = const_cast<Node*>(this);
242     Node* highest = node;
243     for (; node; node = node->parentNode())
244         highest = node;
245     return highest;
246 }
247
248 // This constant controls how much buffer is initially allocated
249 // for a Node Vector that is used to store child Nodes of a given Node.
250 // FIXME: Optimize the value.
251 const int initialNodeVectorSize = 11;
252 typedef Vector<RefPtr<Node>, initialNodeVectorSize> NodeVector;
253
254 inline void getChildNodes(Node& node, NodeVector& nodes)
255 {
256     ASSERT(!nodes.size());
257     for (Node* child = node.firstChild(); child; child = child->nextSibling())
258         nodes.append(child);
259 }
260
261 class ChildNodesLazySnapshot {
262     WTF_MAKE_NONCOPYABLE(ChildNodesLazySnapshot);
263     WTF_MAKE_FAST_ALLOCATED;
264 public:
265     explicit ChildNodesLazySnapshot(Node& parentNode)
266         : m_currentNode(parentNode.firstChild())
267         , m_currentIndex(0)
268     {
269         m_nextSnapshot = latestSnapshot;
270         latestSnapshot = this;
271     }
272
273     ~ChildNodesLazySnapshot()
274     {
275         latestSnapshot = m_nextSnapshot;
276     }
277
278     // Returns 0 if there is no next Node.
279     PassRefPtr<Node> nextNode()
280     {
281         if (LIKELY(!hasSnapshot())) {
282             RefPtr<Node> node = m_currentNode;
283             if (node)
284                 m_currentNode = node->nextSibling();
285             return node.release();
286         }
287         Vector<RefPtr<Node> >& nodeVector = *m_childNodes;
288         if (m_currentIndex >= nodeVector.size())
289             return 0;
290         return nodeVector[m_currentIndex++];
291     }
292
293     void takeSnapshot()
294     {
295         if (hasSnapshot())
296             return;
297         m_childNodes = adoptPtr(new Vector<RefPtr<Node> >());
298         Node* node = m_currentNode.get();
299         while (node) {
300             m_childNodes->append(node);
301             node = node->nextSibling();
302         }
303     }
304
305     ChildNodesLazySnapshot* nextSnapshot() { return m_nextSnapshot; }
306     bool hasSnapshot() { return !!m_childNodes.get(); }
307
308     static void takeChildNodesLazySnapshot()
309     {
310         ChildNodesLazySnapshot* snapshot = latestSnapshot;
311         while (snapshot && !snapshot->hasSnapshot()) {
312             snapshot->takeSnapshot();
313             snapshot = snapshot->nextSnapshot();
314         }
315     }
316
317 private:
318     static ChildNodesLazySnapshot* latestSnapshot;
319
320     RefPtr<Node> m_currentNode;
321     unsigned m_currentIndex;
322     OwnPtr<Vector<RefPtr<Node> > > m_childNodes; // Lazily instantiated.
323     ChildNodesLazySnapshot* m_nextSnapshot;
324 };
325
326 } // namespace WebCore
327
328 #endif // ContainerNode_h