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