1 /*
2 * Copyright (C) 2011 Google Inc. All Rights Reserved.
3 * Copyright (C) 2012 Apple Inc. All Rights Reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #ifndef TreeScope_h
28 #define TreeScope_h
29
30 #include "core/dom/DocumentOrderedMap.h"
31 #include "platform/heap/Handle.h"
32 #include "wtf/text/AtomicString.h"
33
34 namespace blink {
35
36 class ContainerNode;
37 class DOMSelection;
38 class Document;
39 class Element;
40 class HTMLLabelElement;
41 class HTMLMapElement;
42 class HitTestResult;
43 class IdTargetObserverRegistry;
44 class ScopedStyleResolver;
45 class Node;
46
47 // A class which inherits both Node and TreeScope must call clearRareData() in its destructor
48 // so that the Node destructor no longer does problematic NodeList cache manipulation in
49 // the destructor.
50 class TreeScope : public WillBeGarbageCollectedMixin {
51 public:
parentTreeScope()52 TreeScope* parentTreeScope() const { return m_parentTreeScope; }
53
54 TreeScope* olderShadowRootOrParentTreeScope() const;
55 bool isInclusiveOlderSiblingShadowRootOrAncestorTreeScopeOf(const TreeScope&) const;
56
57 Element* adjustedFocusedElement() const;
58 Element* getElementById(const AtomicString&) const;
59 const WillBeHeapVector<RawPtrWillBeMember<Element> >& getAllElementsById(const AtomicString&) const;
60 bool hasElementWithId(const AtomicString& id) const;
61 bool containsMultipleElementsWithId(const AtomicString& id) const;
62 void addElementById(const AtomicString& elementId, Element*);
63 void removeElementById(const AtomicString& elementId, Element*);
64
document()65 Document& document() const
66 {
67 ASSERT(m_document);
68 return *m_document;
69 }
70
71 Node* ancestorInThisScope(Node*) const;
72
73 void addImageMap(HTMLMapElement*);
74 void removeImageMap(HTMLMapElement*);
75 HTMLMapElement* getImageMap(const String& url) const;
76
77 Element* elementFromPoint(int x, int y) const;
78
79 // For accessibility.
shouldCacheLabelsByForAttribute()80 bool shouldCacheLabelsByForAttribute() const { return m_labelsByForAttribute; }
81 void addLabel(const AtomicString& forAttributeValue, HTMLLabelElement*);
82 void removeLabel(const AtomicString& forAttributeValue, HTMLLabelElement*);
83 HTMLLabelElement* labelElementForId(const AtomicString& forAttributeValue);
84
85 DOMSelection* getSelection() const;
86
87 // Find first anchor with the given name.
88 // First searches for an element with the given ID, but if that fails, then looks
89 // for an anchor with the given name. ID matching is always case sensitive, but
90 // Anchor name matching is case sensitive in strict mode and not case sensitive in
91 // quirks mode for historical compatibility reasons.
92 Element* findAnchor(const String& name);
93
94 // Used by the basic DOM mutation methods (e.g., appendChild()).
95 void adoptIfNeeded(Node&);
96
rootNode()97 ContainerNode& rootNode() const { return *m_rootNode; }
98
idTargetObserverRegistry()99 IdTargetObserverRegistry& idTargetObserverRegistry() const { return *m_idTargetObserverRegistry.get(); }
100
101
102 #if !ENABLE(OILPAN)
103 // Nodes belonging to this scope hold guard references -
104 // these are enough to keep the scope from being destroyed, but
105 // not enough to keep it from removing its children. This allows a
106 // node that outlives its scope to still have a valid document
107 // pointer without introducing reference cycles.
guardRef()108 void guardRef()
109 {
110 ASSERT(!deletionHasBegun());
111 ++m_guardRefCount;
112 }
113
guardDeref()114 void guardDeref()
115 {
116 ASSERT(m_guardRefCount > 0);
117 ASSERT(!deletionHasBegun());
118 --m_guardRefCount;
119 if (!m_guardRefCount && !refCount() && !rootNodeHasTreeSharedParent()) {
120 beginDeletion();
121 delete this;
122 }
123 }
124 #endif
125
126 void removedLastRefToScope();
127
128 bool isInclusiveAncestorOf(const TreeScope&) const;
129 unsigned short comparePosition(const TreeScope&) const;
130
131 const TreeScope* commonAncestorTreeScope(const TreeScope& other) const;
132 TreeScope* commonAncestorTreeScope(TreeScope& other);
133
134 Element* getElementByAccessKey(const String& key) const;
135
136 virtual void trace(Visitor*);
137
scopedStyleResolver()138 ScopedStyleResolver* scopedStyleResolver() const { return m_scopedStyleResolver.get(); }
139 ScopedStyleResolver& ensureScopedStyleResolver();
140 void clearScopedStyleResolver();
141
142 protected:
143 TreeScope(ContainerNode&, Document&);
144 TreeScope(Document&);
145 virtual ~TreeScope();
146
147 #if !ENABLE(OILPAN)
148 void destroyTreeScopeData();
149 #endif
150
setDocument(Document & document)151 void setDocument(Document& document) { m_document = &document; }
152 void setParentTreeScope(TreeScope&);
153
154 #if !ENABLE(OILPAN)
hasGuardRefCount()155 bool hasGuardRefCount() const { return m_guardRefCount; }
156 #endif
157
158 void setNeedsStyleRecalcForViewportUnits();
159
160 private:
dispose()161 virtual void dispose() { }
162
163 #if !ENABLE(OILPAN)
164 int refCount() const;
165
166 #if ENABLE(SECURITY_ASSERT)
167 bool deletionHasBegun();
168 void beginDeletion();
169 #else
deletionHasBegun()170 bool deletionHasBegun() { return false; }
beginDeletion()171 void beginDeletion() { }
172 #endif
173 #endif
174
175 bool rootNodeHasTreeSharedParent() const;
176
177 RawPtrWillBeMember<ContainerNode> m_rootNode;
178 RawPtrWillBeMember<Document> m_document;
179 RawPtrWillBeMember<TreeScope> m_parentTreeScope;
180
181 #if !ENABLE(OILPAN)
182 int m_guardRefCount;
183 #endif
184
185 OwnPtrWillBeMember<DocumentOrderedMap> m_elementsById;
186 OwnPtrWillBeMember<DocumentOrderedMap> m_imageMapsByName;
187 OwnPtrWillBeMember<DocumentOrderedMap> m_labelsByForAttribute;
188
189 OwnPtrWillBeMember<IdTargetObserverRegistry> m_idTargetObserverRegistry;
190
191 OwnPtrWillBeMember<ScopedStyleResolver> m_scopedStyleResolver;
192
193 mutable RefPtrWillBeMember<DOMSelection> m_selection;
194 };
195
hasElementWithId(const AtomicString & id)196 inline bool TreeScope::hasElementWithId(const AtomicString& id) const
197 {
198 ASSERT(!id.isNull());
199 return m_elementsById && m_elementsById->contains(id);
200 }
201
containsMultipleElementsWithId(const AtomicString & id)202 inline bool TreeScope::containsMultipleElementsWithId(const AtomicString& id) const
203 {
204 return m_elementsById && m_elementsById->containsMultiple(id);
205 }
206
207 DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES(TreeScope)
208
209 HitTestResult hitTestInDocument(const Document*, int x, int y);
210 TreeScope* commonTreeScope(Node*, Node*);
211
212 } // namespace blink
213
214 #endif // TreeScope_h
215