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 "wtf/Forward.h" 32 #include "wtf/text/AtomicString.h" 33 34 namespace WebCore { 35 36 class ContainerNode; 37 class DOMSelection; 38 class Document; 39 class Element; 40 class HTMLLabelElement; 41 class HTMLMapElement; 42 class LayoutPoint; 43 class IdTargetObserverRegistry; 44 class Node; 45 46 // A class which inherits both Node and TreeScope must call clearRareData() in its destructor 47 // so that the Node destructor no longer does problematic NodeList cache manipulation in 48 // the destructor. 49 class TreeScope { 50 friend class Document; 51 friend class TreeScopeAdopter; 52 53 public: 54 TreeScope* parentTreeScope() const { return m_parentTreeScope; } 55 void setParentTreeScope(TreeScope*); 56 57 Element* adjustedFocusedElement(); 58 Element* getElementById(const AtomicString&) const; 59 bool hasElementWithId(StringImpl* id) const; 60 bool containsMultipleElementsWithId(const AtomicString& id) const; 61 void addElementById(const AtomicString& elementId, Element*); 62 void removeElementById(const AtomicString& elementId, Element*); 63 64 Document* documentScope() const { return m_documentScope; } 65 66 Node* ancestorInThisScope(Node*) const; 67 68 void addImageMap(HTMLMapElement*); 69 void removeImageMap(HTMLMapElement*); 70 HTMLMapElement* getImageMap(const String& url) const; 71 72 Element* elementFromPoint(int x, int y) const; 73 74 // For accessibility. 75 bool shouldCacheLabelsByForAttribute() const { return m_labelsByForAttribute; } 76 void addLabel(const AtomicString& forAttributeValue, HTMLLabelElement*); 77 void removeLabel(const AtomicString& forAttributeValue, HTMLLabelElement*); 78 HTMLLabelElement* labelElementForId(const AtomicString& forAttributeValue); 79 80 DOMSelection* getSelection() const; 81 82 // Find first anchor with the given name. 83 // First searches for an element with the given ID, but if that fails, then looks 84 // for an anchor with the given name. ID matching is always case sensitive, but 85 // Anchor name matching is case sensitive in strict mode and not case sensitive in 86 // quirks mode for historical compatibility reasons. 87 Element* findAnchor(const String& name); 88 89 bool applyAuthorStyles() const; 90 91 // Used by the basic DOM mutation methods (e.g., appendChild()). 92 void adoptIfNeeded(Node*); 93 94 Node* rootNode() const { return m_rootNode; } 95 96 IdTargetObserverRegistry& idTargetObserverRegistry() const { return *m_idTargetObserverRegistry.get(); } 97 98 static TreeScope* noDocumentInstance() 99 { 100 DEFINE_STATIC_LOCAL(TreeScope, instance, ()); 101 return &instance; 102 } 103 104 // Nodes belonging to this scope hold guard references - 105 // these are enough to keep the scope from being destroyed, but 106 // not enough to keep it from removing its children. This allows a 107 // node that outlives its scope to still have a valid document 108 // pointer without introducing reference cycles. 109 void guardRef() 110 { 111 ASSERT(!deletionHasBegun()); 112 ++m_guardRefCount; 113 } 114 115 void guardDeref() 116 { 117 ASSERT(!deletionHasBegun()); 118 --m_guardRefCount; 119 if (!m_guardRefCount && !refCount() && this != noDocumentInstance() && !rootNodeHasTreeSharedParent()) { 120 beginDeletion(); 121 delete this; 122 } 123 } 124 125 void removedLastRefToScope(); 126 127 bool isInclusiveAncestorOf(const TreeScope*) const; 128 unsigned short comparePosition(const TreeScope*) const; 129 130 Element* getElementByAccessKey(const String& key) const; 131 132 protected: 133 TreeScope(ContainerNode*, Document*); 134 TreeScope(Document*); 135 virtual ~TreeScope(); 136 137 void destroyTreeScopeData(); 138 void clearDocumentScope(); 139 void setDocumentScope(Document* document) 140 { 141 ASSERT(document); 142 ASSERT(this != noDocumentInstance()); 143 m_documentScope = document; 144 } 145 146 bool hasGuardRefCount() const { return m_guardRefCount; } 147 148 private: 149 TreeScope(); 150 151 virtual void dispose() { } 152 153 int refCount() const; 154 #ifndef NDEBUG 155 bool deletionHasBegun(); 156 void beginDeletion(); 157 #else 158 bool deletionHasBegun() { return false; } 159 void beginDeletion() { } 160 #endif 161 162 bool rootNodeHasTreeSharedParent() const; 163 164 Node* m_rootNode; 165 Document* m_documentScope; 166 TreeScope* m_parentTreeScope; 167 int m_guardRefCount; 168 169 OwnPtr<DocumentOrderedMap> m_elementsById; 170 OwnPtr<DocumentOrderedMap> m_imageMapsByName; 171 OwnPtr<DocumentOrderedMap> m_labelsByForAttribute; 172 173 OwnPtr<IdTargetObserverRegistry> m_idTargetObserverRegistry; 174 175 mutable RefPtr<DOMSelection> m_selection; 176 }; 177 178 inline bool TreeScope::hasElementWithId(StringImpl* id) const 179 { 180 ASSERT(id); 181 return m_elementsById && m_elementsById->contains(id); 182 } 183 184 inline bool TreeScope::containsMultipleElementsWithId(const AtomicString& id) const 185 { 186 return m_elementsById && m_elementsById->containsMultiple(id.impl()); 187 } 188 189 Node* nodeFromPoint(Document*, int x, int y, LayoutPoint* localPoint = 0); 190 TreeScope* commonTreeScope(Node*, Node*); 191 192 } // namespace WebCore 193 194 #endif // TreeScope_h 195