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 "core/HTMLNames.h" 30 #include "core/MathMLNames.h" 31 #include "core/SVGNames.h" 32 #include "core/dom/Element.h" 33 #include "core/html/parser/AtomicHTMLToken.h" 34 #include "platform/RuntimeEnabledFeatures.h" 35 #include "wtf/RefCounted.h" 36 #include "wtf/RefPtr.h" 37 #include "wtf/text/AtomicString.h" 38 39 namespace blink { 40 41 class ContainerNode; 42 43 class HTMLStackItem : public RefCountedWillBeGarbageCollectedFinalized<HTMLStackItem> { 44 public: 45 enum ItemType { 46 ItemForContextElement, 47 ItemForDocumentFragmentNode 48 }; 49 50 // Used by document fragment node and context element. 51 static PassRefPtrWillBeRawPtr<HTMLStackItem> create(PassRefPtrWillBeRawPtr<ContainerNode> node, ItemType type) 52 { 53 return adoptRefWillBeNoop(new HTMLStackItem(node, type)); 54 } 55 56 // Used by HTMLElementStack and HTMLFormattingElementList. 57 static PassRefPtrWillBeRawPtr<HTMLStackItem> create(PassRefPtrWillBeRawPtr<ContainerNode> node, AtomicHTMLToken* token, const AtomicString& namespaceURI = HTMLNames::xhtmlNamespaceURI) 58 { 59 return adoptRefWillBeNoop(new HTMLStackItem(node, token, namespaceURI)); 60 } 61 62 Element* element() const { return toElement(m_node.get()); } 63 ContainerNode* node() const { return m_node.get(); } 64 65 bool isDocumentFragmentNode() const { return m_isDocumentFragmentNode; } 66 bool isElementNode() const { return !m_isDocumentFragmentNode; } 67 68 const AtomicString& namespaceURI() const { return m_namespaceURI; } 69 const AtomicString& localName() const { return m_tokenLocalName; } 70 71 const Vector<Attribute>& attributes() const { ASSERT(m_tokenLocalName); return m_tokenAttributes; } 72 Attribute* getAttributeItem(const QualifiedName& attributeName) 73 { 74 ASSERT(m_tokenLocalName); 75 return findAttributeInVector(m_tokenAttributes, attributeName); 76 } 77 78 bool hasLocalName(const AtomicString& name) const { return m_tokenLocalName == name; } 79 bool hasTagName(const QualifiedName& name) const { return m_tokenLocalName == name.localName() && m_namespaceURI == name.namespaceURI(); } 80 81 bool matchesHTMLTag(const AtomicString& name) const { return m_tokenLocalName == name && m_namespaceURI == HTMLNames::xhtmlNamespaceURI; } 82 bool matchesHTMLTag(const QualifiedName& name) const { return m_tokenLocalName == name && m_namespaceURI == HTMLNames::xhtmlNamespaceURI; } 83 84 bool causesFosterParenting() 85 { 86 return hasTagName(HTMLNames::tableTag) 87 || hasTagName(HTMLNames::tbodyTag) 88 || hasTagName(HTMLNames::tfootTag) 89 || hasTagName(HTMLNames::theadTag) 90 || hasTagName(HTMLNames::trTag); 91 } 92 93 bool isInHTMLNamespace() const 94 { 95 // A DocumentFragment takes the place of the document element when parsing 96 // fragments and should be considered in the HTML namespace. 97 return namespaceURI() == HTMLNames::xhtmlNamespaceURI 98 || isDocumentFragmentNode(); // FIXME: Does this also apply to ShadowRoot? 99 } 100 101 bool isNumberedHeaderElement() const 102 { 103 return hasTagName(HTMLNames::h1Tag) 104 || hasTagName(HTMLNames::h2Tag) 105 || hasTagName(HTMLNames::h3Tag) 106 || hasTagName(HTMLNames::h4Tag) 107 || hasTagName(HTMLNames::h5Tag) 108 || hasTagName(HTMLNames::h6Tag); 109 } 110 111 bool isTableBodyContextElement() const 112 { 113 return hasTagName(HTMLNames::tbodyTag) 114 || hasTagName(HTMLNames::tfootTag) 115 || hasTagName(HTMLNames::theadTag); 116 } 117 118 // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#special 119 bool isSpecialNode() const 120 { 121 if (hasTagName(MathMLNames::miTag) 122 || hasTagName(MathMLNames::moTag) 123 || hasTagName(MathMLNames::mnTag) 124 || hasTagName(MathMLNames::msTag) 125 || hasTagName(MathMLNames::mtextTag) 126 || hasTagName(MathMLNames::annotation_xmlTag) 127 || hasTagName(SVGNames::foreignObjectTag) 128 || hasTagName(SVGNames::descTag) 129 || hasTagName(SVGNames::titleTag)) 130 return true; 131 if (isDocumentFragmentNode()) 132 return true; 133 if (!isInHTMLNamespace()) 134 return false; 135 const AtomicString& tagName = localName(); 136 return tagName == HTMLNames::addressTag 137 || tagName == HTMLNames::appletTag 138 || tagName == HTMLNames::areaTag 139 || tagName == HTMLNames::articleTag 140 || tagName == HTMLNames::asideTag 141 || tagName == HTMLNames::baseTag 142 || tagName == HTMLNames::basefontTag 143 || tagName == HTMLNames::bgsoundTag 144 || tagName == HTMLNames::blockquoteTag 145 || tagName == HTMLNames::bodyTag 146 || tagName == HTMLNames::brTag 147 || tagName == HTMLNames::buttonTag 148 || tagName == HTMLNames::captionTag 149 || tagName == HTMLNames::centerTag 150 || tagName == HTMLNames::colTag 151 || tagName == HTMLNames::colgroupTag 152 || tagName == HTMLNames::commandTag 153 || tagName == HTMLNames::ddTag 154 || tagName == HTMLNames::detailsTag 155 || tagName == HTMLNames::dirTag 156 || tagName == HTMLNames::divTag 157 || tagName == HTMLNames::dlTag 158 || tagName == HTMLNames::dtTag 159 || tagName == HTMLNames::embedTag 160 || tagName == HTMLNames::fieldsetTag 161 || tagName == HTMLNames::figcaptionTag 162 || tagName == HTMLNames::figureTag 163 || tagName == HTMLNames::footerTag 164 || tagName == HTMLNames::formTag 165 || tagName == HTMLNames::frameTag 166 || tagName == HTMLNames::framesetTag 167 || isNumberedHeaderElement() 168 || tagName == HTMLNames::headTag 169 || tagName == HTMLNames::headerTag 170 || tagName == HTMLNames::hgroupTag 171 || tagName == HTMLNames::hrTag 172 || tagName == HTMLNames::htmlTag 173 || tagName == HTMLNames::iframeTag 174 || tagName == HTMLNames::imgTag 175 || tagName == HTMLNames::inputTag 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 || (RuntimeEnabledFeatures::contextMenuEnabled() && tagName == HTMLNames::menuitemTag) 183 || tagName == HTMLNames::metaTag 184 || tagName == HTMLNames::navTag 185 || tagName == HTMLNames::noembedTag 186 || tagName == HTMLNames::noframesTag 187 || tagName == HTMLNames::noscriptTag 188 || tagName == HTMLNames::objectTag 189 || tagName == HTMLNames::olTag 190 || tagName == HTMLNames::pTag 191 || tagName == HTMLNames::paramTag 192 || tagName == HTMLNames::plaintextTag 193 || tagName == HTMLNames::preTag 194 || tagName == HTMLNames::scriptTag 195 || tagName == HTMLNames::sectionTag 196 || tagName == HTMLNames::selectTag 197 || tagName == HTMLNames::styleTag 198 || tagName == HTMLNames::summaryTag 199 || tagName == HTMLNames::tableTag 200 || isTableBodyContextElement() 201 || tagName == HTMLNames::tdTag 202 || tagName == HTMLNames::templateTag 203 || tagName == HTMLNames::textareaTag 204 || tagName == HTMLNames::thTag 205 || tagName == HTMLNames::titleTag 206 || tagName == HTMLNames::trTag 207 || tagName == HTMLNames::ulTag 208 || tagName == HTMLNames::wbrTag 209 || tagName == HTMLNames::xmpTag; 210 } 211 212 void trace(Visitor* visitor) { visitor->trace(m_node); } 213 214 private: 215 HTMLStackItem(PassRefPtrWillBeRawPtr<ContainerNode> node, ItemType type) 216 : m_node(node) 217 { 218 switch (type) { 219 case ItemForDocumentFragmentNode: 220 m_isDocumentFragmentNode = true; 221 break; 222 case ItemForContextElement: 223 m_tokenLocalName = m_node->localName(); 224 m_namespaceURI = m_node->namespaceURI(); 225 m_isDocumentFragmentNode = false; 226 break; 227 } 228 } 229 230 HTMLStackItem(PassRefPtrWillBeRawPtr<ContainerNode> node, AtomicHTMLToken* token, const AtomicString& namespaceURI = HTMLNames::xhtmlNamespaceURI) 231 : m_node(node) 232 , m_tokenLocalName(token->name()) 233 , m_tokenAttributes(token->attributes()) 234 , m_namespaceURI(namespaceURI) 235 , m_isDocumentFragmentNode(false) 236 { 237 } 238 239 RefPtrWillBeMember<ContainerNode> m_node; 240 241 AtomicString m_tokenLocalName; 242 Vector<Attribute> m_tokenAttributes; 243 AtomicString m_namespaceURI; 244 bool m_isDocumentFragmentNode; 245 }; 246 247 } // namespace blink 248 249 #endif // HTMLStackItem_h 250