1/*
2 * Copyright (C) 2012 Company 100, Inc. All rights reserved.
3 * Copyright (C) 2015 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 GOOGLE 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 GOOGLE 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#pragma once
28
29#include "AtomicHTMLToken.h"
30#include "DocumentFragment.h"
31#include "Element.h"
32#include "HTMLNames.h"
33#include "MathMLNames.h"
34#include "SVGNames.h"
35
36namespace WebCore {
37
38class HTMLStackItem : public RefCounted<HTMLStackItem> {
39public:
40 // Normal HTMLElementStack and HTMLFormattingElementList items.
41 static Ref<HTMLStackItem> create(Ref<Element>&&, AtomicHTMLToken&&, const AtomicString& namespaceURI = HTMLNames::xhtmlNamespaceURI);
42 static Ref<HTMLStackItem> create(Ref<Element>&&, const AtomicString&, Vector<Attribute>&&);
43
44 // Document fragment or element for parsing context.
45 static Ref<HTMLStackItem> create(Element&);
46 static Ref<HTMLStackItem> create(DocumentFragment&);
47
48 bool isElement() const;
49 bool isDocumentFragment() const;
50
51 ContainerNode& node() const;
52 Element& element() const;
53
54 const AtomicString& namespaceURI() const;
55 const AtomicString& localName() const;
56
57 const Vector<Attribute>& attributes() const;
58 const Attribute* findAttribute(const QualifiedName& attributeName) const;
59
60 bool hasTagName(const QualifiedName&) const;
61 bool matchesHTMLTag(const AtomicString&) const;
62
63private:
64 HTMLStackItem(Ref<Element>&&, AtomicHTMLToken&&, const AtomicString& namespaceURI);
65 HTMLStackItem(Ref<Element>&&, const AtomicString& localName, const AtomicString& namespaceURI, Vector<Attribute>&&);
66 explicit HTMLStackItem(Element&);
67 explicit HTMLStackItem(DocumentFragment&);
68
69 const Ref<ContainerNode> m_node;
70 const AtomicString m_namespaceURI;
71 const AtomicString m_localName;
72 const Vector<Attribute> m_attributes;
73};
74
75bool isInHTMLNamespace(const HTMLStackItem&);
76bool isNumberedHeaderElement(const HTMLStackItem&);
77bool isSpecialNode(const HTMLStackItem&);
78
79inline HTMLStackItem::HTMLStackItem(Ref<Element>&& element, AtomicHTMLToken&& token, const AtomicString& namespaceURI = HTMLNames::xhtmlNamespaceURI)
80 : m_node(WTFMove(element))
81 , m_namespaceURI(namespaceURI)
82 , m_localName(token.name())
83 , m_attributes(WTFMove(token.attributes()))
84{
85}
86
87inline Ref<HTMLStackItem> HTMLStackItem::create(Ref<Element>&& element, AtomicHTMLToken&& token, const AtomicString& namespaceURI)
88{
89 return adoptRef(*new HTMLStackItem(WTFMove(element), WTFMove(token), namespaceURI));
90}
91
92inline HTMLStackItem::HTMLStackItem(Ref<Element>&& element, const AtomicString& localName, const AtomicString& namespaceURI, Vector<Attribute>&& attributes)
93 : m_node(WTFMove(element))
94 , m_namespaceURI(namespaceURI)
95 , m_localName(localName)
96 , m_attributes(WTFMove(attributes))
97{
98}
99
100inline Ref<HTMLStackItem> HTMLStackItem::create(Ref<Element>&& element, const AtomicString& localName, Vector<Attribute>&& attributes)
101{
102 auto& namespaceURI = element.get().namespaceURI();
103 return adoptRef(*new HTMLStackItem(WTFMove(element), localName, namespaceURI, WTFMove(attributes)));
104}
105
106inline HTMLStackItem::HTMLStackItem(Element& element)
107 : m_node(element)
108 , m_namespaceURI(element.namespaceURI())
109 , m_localName(element.localName())
110{
111}
112
113inline Ref<HTMLStackItem> HTMLStackItem::create(Element& element)
114{
115 return adoptRef(*new HTMLStackItem(element));
116}
117
118inline HTMLStackItem::HTMLStackItem(DocumentFragment& fragment)
119 : m_node(fragment)
120{
121}
122
123inline Ref<HTMLStackItem> HTMLStackItem::create(DocumentFragment& fragment)
124{
125 return adoptRef(*new HTMLStackItem(fragment));
126}
127
128inline ContainerNode& HTMLStackItem::node() const
129{
130 return m_node.get();
131}
132
133inline Element& HTMLStackItem::element() const
134{
135 return downcast<Element>(node());
136}
137
138inline bool HTMLStackItem::isDocumentFragment() const
139{
140 return m_localName.isNull();
141}
142
143inline bool HTMLStackItem::isElement() const
144{
145 return !isDocumentFragment();
146}
147
148inline const AtomicString& HTMLStackItem::namespaceURI() const
149{
150 return m_namespaceURI;
151}
152
153inline const AtomicString& HTMLStackItem::localName() const
154{
155 return m_localName;
156}
157
158inline const Vector<Attribute>& HTMLStackItem::attributes() const
159{
160 ASSERT(isElement());
161 return m_attributes;
162}
163
164inline const Attribute* HTMLStackItem::findAttribute(const QualifiedName& attributeName) const
165{
166 return WebCore::findAttribute(const_cast<Vector<Attribute>&>(attributes()), attributeName);
167}
168
169inline bool HTMLStackItem::hasTagName(const QualifiedName& name) const
170{
171 return m_localName == name.localName() && m_namespaceURI == name.namespaceURI();
172}
173
174inline bool HTMLStackItem::matchesHTMLTag(const AtomicString& name) const
175{
176 return m_localName == name && m_namespaceURI == HTMLNames::xhtmlNamespaceURI;
177}
178
179inline bool isInHTMLNamespace(const HTMLStackItem& item)
180{
181 // A DocumentFragment takes the place of the document element when parsing
182 // fragments and thus should be treated as if it was in the HTML namespace.
183 // FIXME: Is this also needed for a ShadowRoot that might be a non-HTML element?
184 return item.namespaceURI() == HTMLNames::xhtmlNamespaceURI || item.isDocumentFragment();
185}
186
187inline bool isNumberedHeaderElement(const HTMLStackItem& item)
188{
189 return item.namespaceURI() == HTMLNames::xhtmlNamespaceURI
190 && (item.localName() == HTMLNames::h1Tag
191 || item.localName() == HTMLNames::h2Tag
192 || item.localName() == HTMLNames::h3Tag
193 || item.localName() == HTMLNames::h4Tag
194 || item.localName() == HTMLNames::h5Tag
195 || item.localName() == HTMLNames::h6Tag);
196}
197
198// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#special
199inline bool isSpecialNode(const HTMLStackItem& item)
200{
201 if (item.isDocumentFragment())
202 return true;
203 const AtomicString& tagName = item.localName();
204 if (item.namespaceURI() == HTMLNames::xhtmlNamespaceURI) {
205 return tagName == HTMLNames::addressTag
206 || tagName == HTMLNames::appletTag
207 || tagName == HTMLNames::areaTag
208 || tagName == HTMLNames::articleTag
209 || tagName == HTMLNames::asideTag
210 || tagName == HTMLNames::baseTag
211 || tagName == HTMLNames::basefontTag
212 || tagName == HTMLNames::bgsoundTag
213 || tagName == HTMLNames::blockquoteTag
214 || tagName == HTMLNames::bodyTag
215 || tagName == HTMLNames::brTag
216 || tagName == HTMLNames::buttonTag
217 || tagName == HTMLNames::captionTag
218 || tagName == HTMLNames::centerTag
219 || tagName == HTMLNames::colTag
220 || tagName == HTMLNames::colgroupTag
221 || tagName == HTMLNames::commandTag
222 || tagName == HTMLNames::ddTag
223 || tagName == HTMLNames::detailsTag
224 || tagName == HTMLNames::dirTag
225 || tagName == HTMLNames::divTag
226 || tagName == HTMLNames::dlTag
227 || tagName == HTMLNames::dtTag
228 || tagName == HTMLNames::embedTag
229 || tagName == HTMLNames::fieldsetTag
230 || tagName == HTMLNames::figcaptionTag
231 || tagName == HTMLNames::figureTag
232 || tagName == HTMLNames::footerTag
233 || tagName == HTMLNames::formTag
234 || tagName == HTMLNames::frameTag
235 || tagName == HTMLNames::framesetTag
236 || tagName == HTMLNames::h1Tag
237 || tagName == HTMLNames::h2Tag
238 || tagName == HTMLNames::h3Tag
239 || tagName == HTMLNames::h4Tag
240 || tagName == HTMLNames::h5Tag
241 || tagName == HTMLNames::h6Tag
242 || tagName == HTMLNames::headTag
243 || tagName == HTMLNames::headerTag
244 || tagName == HTMLNames::hgroupTag
245 || tagName == HTMLNames::hrTag
246 || tagName == HTMLNames::htmlTag
247 || tagName == HTMLNames::iframeTag
248 || tagName == HTMLNames::imgTag
249 || tagName == HTMLNames::inputTag
250 || tagName == HTMLNames::liTag
251 || tagName == HTMLNames::linkTag
252 || tagName == HTMLNames::listingTag
253 || tagName == HTMLNames::mainTag
254 || tagName == HTMLNames::marqueeTag
255 || tagName == HTMLNames::menuTag
256 || tagName == HTMLNames::metaTag
257 || tagName == HTMLNames::navTag
258 || tagName == HTMLNames::noembedTag
259 || tagName == HTMLNames::noframesTag
260 || tagName == HTMLNames::noscriptTag
261 || tagName == HTMLNames::objectTag
262 || tagName == HTMLNames::olTag
263 || tagName == HTMLNames::pTag
264 || tagName == HTMLNames::paramTag
265 || tagName == HTMLNames::plaintextTag
266 || tagName == HTMLNames::preTag
267 || tagName == HTMLNames::scriptTag
268 || tagName == HTMLNames::sectionTag
269 || tagName == HTMLNames::selectTag
270 || tagName == HTMLNames::styleTag
271 || tagName == HTMLNames::summaryTag
272 || tagName == HTMLNames::tableTag
273 || tagName == HTMLNames::tbodyTag
274 || tagName == HTMLNames::tdTag
275 || tagName == HTMLNames::templateTag
276 || tagName == HTMLNames::textareaTag
277 || tagName == HTMLNames::tfootTag
278 || tagName == HTMLNames::thTag
279 || tagName == HTMLNames::theadTag
280 || tagName == HTMLNames::titleTag
281 || tagName == HTMLNames::trTag
282 || tagName == HTMLNames::ulTag
283 || tagName == HTMLNames::wbrTag
284 || tagName == HTMLNames::xmpTag;
285 }
286 if (item.namespaceURI() == MathMLNames::mathmlNamespaceURI) {
287 return tagName == MathMLNames::annotation_xmlTag
288 || tagName == MathMLNames::miTag
289 || tagName == MathMLNames::moTag
290 || tagName == MathMLNames::mnTag
291 || tagName == MathMLNames::msTag
292 || tagName == MathMLNames::mtextTag;
293 }
294 if (item.namespaceURI() == SVGNames::svgNamespaceURI) {
295 return tagName == SVGNames::descTag
296 || tagName == SVGNames::foreignObjectTag
297 || tagName == SVGNames::titleTag;
298 }
299 return false;
300}
301
302} // namespace WebCore
303