Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / HTMLCollection.h
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved.
5  * Copyright (C) 2014 Samsung Electronics. 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 HTMLCollection_h
25 #define HTMLCollection_h
26
27 #include "core/dom/LiveNodeListBase.h"
28 #include "core/html/CollectionItemsCache.h"
29 #include "core/html/CollectionType.h"
30 #include "wtf/Forward.h"
31
32 namespace blink {
33
34 class HTMLCollection : public RefCountedWillBeGarbageCollectedFinalized<HTMLCollection>, public ScriptWrappable, public LiveNodeListBase {
35     DEFINE_WRAPPERTYPEINFO();
36     WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(HTMLCollection);
37 public:
38     enum ItemAfterOverrideType {
39         OverridesItemAfter,
40         DoesNotOverrideItemAfter,
41     };
42
43     static PassRefPtrWillBeRawPtr<HTMLCollection> create(ContainerNode& base, CollectionType);
44     virtual ~HTMLCollection();
45     virtual void invalidateCache(Document* oldDocument = 0) const override;
46     void invalidateCacheForAttribute(const QualifiedName*) const;
47
48     // DOM API
49     unsigned length() const;
50     Element* item(unsigned offset) const;
51     virtual Element* namedItem(const AtomicString& name) const;
52     bool namedPropertyQuery(const AtomicString&, ExceptionState&);
53     void namedPropertyEnumerator(Vector<String>& names, ExceptionState&);
54
55     // Non-DOM API
56     void namedItems(const AtomicString& name, WillBeHeapVector<RefPtrWillBeMember<Element>>&) const;
57     bool isEmpty() const { return m_collectionItemsCache.isEmpty(*this); }
58     bool hasExactlyOneItem() const { return m_collectionItemsCache.hasExactlyOneNode(*this); }
59     bool elementMatches(const Element&) const;
60
61     // CollectionIndexCache API.
62     bool canTraverseBackward() const { return !overridesItemAfter(); }
63     Element* traverseToFirst() const;
64     Element* traverseToLast() const;
65     Element* traverseForwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset) const;
66     Element* traverseBackwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset) const;
67
68     virtual void trace(Visitor*);
69
70 protected:
71     HTMLCollection(ContainerNode& base, CollectionType, ItemAfterOverrideType);
72
73     class NamedItemCache final : public NoBaseWillBeGarbageCollected<NamedItemCache> {
74     public:
75         static PassOwnPtrWillBeRawPtr<NamedItemCache> create()
76         {
77             return adoptPtrWillBeNoop(new NamedItemCache);
78         }
79
80         WillBeHeapVector<RawPtrWillBeMember<Element>>* getElementsById(const AtomicString& id) const { return m_idCache.get(id.impl()); }
81         WillBeHeapVector<RawPtrWillBeMember<Element>>* getElementsByName(const AtomicString& name) const { return m_nameCache.get(name.impl()); }
82         void addElementWithId(const AtomicString& id, Element* element) { addElementToMap(m_idCache, id, element); }
83         void addElementWithName(const AtomicString& name, Element* element) { addElementToMap(m_nameCache, name, element); }
84
85         void trace(Visitor* visitor)
86         {
87 #if ENABLE(OILPAN)
88             visitor->trace(m_idCache);
89             visitor->trace(m_nameCache);
90 #endif
91         }
92
93     private:
94         NamedItemCache();
95         typedef WillBeHeapHashMap<StringImpl*, OwnPtrWillBeMember<WillBeHeapVector<RawPtrWillBeMember<Element>>>> StringToElementsMap;
96         static void addElementToMap(StringToElementsMap& map, const AtomicString& key, Element* element)
97         {
98             OwnPtrWillBeMember<WillBeHeapVector<RawPtrWillBeMember<Element>>>& vector = map.add(key.impl(), nullptr).storedValue->value;
99             if (!vector)
100                 vector = adoptPtrWillBeNoop(new WillBeHeapVector<RawPtrWillBeMember<Element>>);
101             vector->append(element);
102         }
103
104         StringToElementsMap m_idCache;
105         StringToElementsMap m_nameCache;
106     };
107
108     bool overridesItemAfter() const { return m_overridesItemAfter; }
109     virtual Element* virtualItemAfter(Element*) const;
110     bool shouldOnlyIncludeDirectChildren() const { return m_shouldOnlyIncludeDirectChildren; }
111     virtual void supportedPropertyNames(Vector<String>& names);
112
113     virtual void updateIdNameCache() const;
114     bool hasValidIdNameCache() const { return m_namedItemCache; }
115
116     void setNamedItemCache(PassOwnPtrWillBeRawPtr<NamedItemCache> cache) const
117     {
118         ASSERT(!m_namedItemCache);
119         document().registerNodeListWithIdNameCache(this);
120         m_namedItemCache = cache;
121     }
122
123     NamedItemCache& namedItemCache() const
124     {
125         ASSERT(m_namedItemCache);
126         return *m_namedItemCache;
127     }
128
129 private:
130     void invalidateIdNameCacheMaps(Document* oldDocument = 0) const
131     {
132         if (!hasValidIdNameCache())
133             return;
134
135         // Make sure we decrement the NodeListWithIdNameCache count from
136         // the old document instead of the new one in the case the collection
137         // is moved to a new document.
138         unregisterIdNameCacheFromDocument(oldDocument ? *oldDocument : document());
139
140         m_namedItemCache.clear();
141     }
142
143     void unregisterIdNameCacheFromDocument(Document& document) const
144     {
145         ASSERT(hasValidIdNameCache());
146         document.unregisterNodeListWithIdNameCache(this);
147     }
148
149     const unsigned m_overridesItemAfter : 1;
150     const unsigned m_shouldOnlyIncludeDirectChildren : 1;
151     mutable OwnPtrWillBeMember<NamedItemCache> m_namedItemCache;
152     mutable CollectionItemsCache<HTMLCollection, Element> m_collectionItemsCache;
153 };
154
155 DEFINE_TYPE_CASTS(HTMLCollection, LiveNodeListBase, collection, isHTMLCollectionType(collection->type()), isHTMLCollectionType(collection.type()));
156
157 inline void HTMLCollection::invalidateCacheForAttribute(const QualifiedName* attrName) const
158 {
159     if (!attrName || shouldInvalidateTypeOnAttributeChange(invalidationType(), *attrName))
160         invalidateCache();
161     else if (*attrName == HTMLNames::idAttr || *attrName == HTMLNames::nameAttr)
162         invalidateIdNameCacheMaps();
163 }
164
165 } // namespace blink
166
167 #endif // HTMLCollection_h