Home | History | Annotate | Download | only in dom
      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