1 /* 2 * Copyright (C) 2012 Company 100, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #ifndef HTMLStackItem_h 27 #define HTMLStackItem_h 28 29 #include "HTMLNames.h" 30 #include "MathMLNames.h" 31 #include "SVGNames.h" 32 #include "core/dom/Element.h" 33 #include "core/html/parser/AtomicHTMLToken.h" 34 #include "wtf/RefCounted.h" 35 #include "wtf/RefPtr.h" 36 #include "wtf/text/AtomicString.h" 37 38 namespace WebCore { 39 40 class ContainerNode; 41 42 class HTMLStackItem : public RefCounted<HTMLStackItem> { 43 public: 44 enum ItemType { 45 ItemForContextElement, 46 ItemForDocumentFragmentNode 47 }; 48 49 // Used by document fragment node and context element. 50 static PassRefPtr<HTMLStackItem> create(PassRefPtr<ContainerNode> node, ItemType type) 51 { 52 return adoptRef(new HTMLStackItem(node, type)); 53 } 54 55 // Used by HTMLElementStack and HTMLFormattingElementList. 56 static PassRefPtr<HTMLStackItem> create(PassRefPtr<ContainerNode> node, AtomicHTMLToken* token, const AtomicString& namespaceURI = HTMLNames::xhtmlNamespaceURI) 57 { 58 return adoptRef(new HTMLStackItem(node, token, namespaceURI)); 59 } 60 61 Element* element() const { return toElement(m_node.get()); } 62 ContainerNode* node() const { return m_node.get(); } 63 64 bool isDocumentFragmentNode() const { return m_isDocumentFragmentNode; } 65 bool isElementNode() const { return !m_isDocumentFragmentNode; } 66 67 const AtomicString& namespaceURI() const { return m_namespaceURI; } 68 const AtomicString& localName() const { return m_tokenLocalName; } 69 70 const Vector<Attribute>& attributes() const { ASSERT(m_tokenLocalName); return m_tokenAttributes; } 71 Attribute* getAttributeItem(const QualifiedName& attributeName) 72 { 73 ASSERT(m_tokenLocalName); 74 return findAttributeInVector(m_tokenAttributes, attributeName); 75 } 76 77 bool hasLocalName(const AtomicString& name) const { return m_tokenLocalName == name; } 78 bool hasTagName(const QualifiedName& name) const { return m_tokenLocalName == name.localName() && m_namespaceURI == name.namespaceURI(); } 79 80 bool matchesHTMLTag(const AtomicString& name) const { return m_tokenLocalName == name && m_namespaceURI == HTMLNames::xhtmlNamespaceURI; } 81 bool matchesHTMLTag(const QualifiedName& name) const { return m_tokenLocalName == name && m_namespaceURI == HTMLNames::xhtmlNamespaceURI; } 82 83 bool causesFosterParenting() 84 { 85 return hasTagName(HTMLNames::tableTag) 86 || hasTagName(HTMLNames::tbodyTag) 87 || hasTagName(HTMLNames::tfootTag) 88 || hasTagName(HTMLNames::theadTag) 89 || hasTagName(HTMLNames::trTag); 90 } 91 92 bool isInHTMLNamespace() const 93 { 94 // A DocumentFragment takes the place of the document element when parsing 95 // fragments and should be considered in the HTML namespace. 96 return namespaceURI() == HTMLNames::xhtmlNamespaceURI 97 || isDocumentFragmentNode(); // FIXME: Does this also apply to ShadowRoot? 98 } 99 100 bool isNumberedHeaderElement() const 101 { 102 return hasTagName(HTMLNames::h1Tag) 103 || hasTagName(HTMLNames::h2Tag) 104 || hasTagName(HTMLNames::h3Tag) 105 || hasTagName(HTMLNames::h4Tag) 106 || hasTagName(HTMLNames::h5Tag) 107 || hasTagName(HTMLNames::h6Tag); 108 } 109 110 bool isTableBodyContextElement() const 111 { 112 return hasTagName(HTMLNames::tbodyTag) 113 || hasTagName(HTMLNames::tfootTag) 114 || hasTagName(HTMLNames::theadTag); 115 } 116 117 // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#special 118 bool isSpecialNode() const 119 { 120 if (hasTagName(MathMLNames::miTag) 121 || hasTagName(MathMLNames::moTag) 122 || hasTagName(MathMLNames::mnTag) 123 || hasTagName(MathMLNames::msTag) 124 || hasTagName(MathMLNames::mtextTag) 125 || hasTagName(MathMLNames::annotation_xmlTag) 126 || hasTagName(SVGNames::foreignObjectTag) 127 || hasTagName(SVGNames::descTag) 128 || hasTagName(SVGNames::titleTag)) 129 return true; 130 if (isDocumentFragmentNode()) 131 return true; 132 if (!isInHTMLNamespace()) 133 return false; 134 const AtomicString& tagName = localName(); 135 return tagName == HTMLNames::addressTag 136 || tagName == HTMLNames::appletTag 137 || tagName == HTMLNames::areaTag 138 || tagName == HTMLNames::articleTag 139 || tagName == HTMLNames::asideTag 140 || tagName == HTMLNames::baseTag 141 || tagName == HTMLNames::basefontTag 142 || tagName == HTMLNames::bgsoundTag 143 || tagName == HTMLNames::blockquoteTag 144 || tagName == HTMLNames::bodyTag 145 || tagName == HTMLNames::brTag 146 || tagName == HTMLNames::buttonTag 147 || tagName == HTMLNames::captionTag 148 || tagName == HTMLNames::centerTag 149 || tagName == HTMLNames::colTag 150 || tagName == HTMLNames::colgroupTag 151 || tagName == HTMLNames::commandTag 152 || tagName == HTMLNames::ddTag 153 || tagName == HTMLNames::detailsTag 154 || tagName == HTMLNames::dirTag 155 || tagName == HTMLNames::divTag 156 || tagName == HTMLNames::dlTag 157 || tagName == HTMLNames::dtTag 158 || tagName == HTMLNames::embedTag 159 || tagName == HTMLNames::fieldsetTag 160 || tagName == HTMLNames::figcaptionTag 161 || tagName == HTMLNames::figureTag 162 || tagName == HTMLNames::footerTag 163 || tagName == HTMLNames::formTag 164 || tagName == HTMLNames::frameTag 165 || tagName == HTMLNames::framesetTag 166 || isNumberedHeaderElement() 167 || tagName == HTMLNames::headTag 168 || tagName == HTMLNames::headerTag 169 || tagName == HTMLNames::hgroupTag 170 || tagName == HTMLNames::hrTag 171 || tagName == HTMLNames::htmlTag 172 || tagName == HTMLNames::iframeTag 173 || tagName == HTMLNames::imgTag 174 || tagName == HTMLNames::inputTag 175 || tagName == HTMLNames::isindexTag 176 || tagName == HTMLNames::liTag 177 || tagName == HTMLNames::linkTag 178 || tagName == HTMLNames::listingTag 179 || tagName == HTMLNames::mainTag 180 || tagName == HTMLNames::marqueeTag 181 || tagName == HTMLNames::menuTag 182 || tagName == HTMLNames::metaTag 183 || tagName == HTMLNames::navTag 184 || tagName == HTMLNames::noembedTag 185 || tagName == HTMLNames::noframesTag 186 || tagName == HTMLNames::noscriptTag 187 || tagName == HTMLNames::objectTag 188 || tagName == HTMLNames::olTag 189 || tagName == HTMLNames::pTag 190 || tagName == HTMLNames::paramTag 191 || tagName == HTMLNames::plaintextTag 192 || tagName == HTMLNames::preTag 193 || tagName == HTMLNames::scriptTag 194 || tagName == HTMLNames::sectionTag 195 || tagName == HTMLNames::selectTag 196 || tagName == HTMLNames::styleTag 197 || tagName == HTMLNames::summaryTag 198 || tagName == HTMLNames::tableTag 199 || isTableBodyContextElement() 200 || tagName == HTMLNames::tdTag 201 || tagName == HTMLNames::templateTag 202 || tagName == HTMLNames::textareaTag 203 || tagName == HTMLNames::thTag 204 || tagName == HTMLNames::titleTag 205 || tagName == HTMLNames::trTag 206 || tagName == HTMLNames::ulTag 207 || tagName == HTMLNames::wbrTag 208 || tagName == HTMLNames::xmpTag; 209 } 210 211 private: 212 HTMLStackItem(PassRefPtr<ContainerNode> node, ItemType type) 213 : m_node(node) 214 { 215 switch (type) { 216 case ItemForDocumentFragmentNode: 217 m_isDocumentFragmentNode = true; 218 break; 219 case ItemForContextElement: 220 m_tokenLocalName = m_node->localName(); 221 m_namespaceURI = m_node->namespaceURI(); 222 m_isDocumentFragmentNode = false; 223 break; 224 } 225 } 226 227 HTMLStackItem(PassRefPtr<ContainerNode> node, AtomicHTMLToken* token, const AtomicString& namespaceURI = HTMLNames::xhtmlNamespaceURI) 228 : m_node(node) 229 , m_tokenLocalName(token->name()) 230 , m_tokenAttributes(token->attributes()) 231 , m_namespaceURI(namespaceURI) 232 , m_isDocumentFragmentNode(false) 233 { 234 } 235 236 RefPtr<ContainerNode> m_node; 237 238 AtomicString m_tokenLocalName; 239 Vector<Attribute> m_tokenAttributes; 240 AtomicString m_namespaceURI; 241 bool m_isDocumentFragmentNode; 242 }; 243 244 } // namespace WebCore 245 246 #endif // HTMLStackItem_h 247