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 "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 RefCountedWillBeGarbageCollectedFinalized<HTMLStackItem> { 43 public: 44 enum ItemType { 45 ItemForContextElement, 46 ItemForDocumentFragmentNode 47 }; 48 49 // Used by document fragment node and context element. 50 static PassRefPtrWillBeRawPtr<HTMLStackItem> create(PassRefPtrWillBeRawPtr<ContainerNode> node, ItemType type) 51 { 52 return adoptRefWillBeNoop(new HTMLStackItem(node, type)); 53 } 54 55 // Used by HTMLElementStack and HTMLFormattingElementList. 56 static PassRefPtrWillBeRawPtr<HTMLStackItem> create(PassRefPtrWillBeRawPtr<ContainerNode> node, AtomicHTMLToken* token, const AtomicString& namespaceURI = HTMLNames::xhtmlNamespaceURI) 57 { 58 return adoptRefWillBeNoop(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::liTag 176 || tagName == HTMLNames::linkTag 177 || tagName == HTMLNames::listingTag 178 || tagName == HTMLNames::mainTag 179 || tagName == HTMLNames::marqueeTag 180 || tagName == HTMLNames::menuTag 181 || tagName == HTMLNames::metaTag 182 || tagName == HTMLNames::navTag 183 || tagName == HTMLNames::noembedTag 184 || tagName == HTMLNames::noframesTag 185 || tagName == HTMLNames::noscriptTag 186 || tagName == HTMLNames::objectTag 187 || tagName == HTMLNames::olTag 188 || tagName == HTMLNames::pTag 189 || tagName == HTMLNames::paramTag 190 || tagName == HTMLNames::plaintextTag 191 || tagName == HTMLNames::preTag 192 || tagName == HTMLNames::scriptTag 193 || tagName == HTMLNames::sectionTag 194 || tagName == HTMLNames::selectTag 195 || tagName == HTMLNames::styleTag 196 || tagName == HTMLNames::summaryTag 197 || tagName == HTMLNames::tableTag 198 || isTableBodyContextElement() 199 || tagName == HTMLNames::tdTag 200 || tagName == HTMLNames::templateTag 201 || tagName == HTMLNames::textareaTag 202 || tagName == HTMLNames::thTag 203 || tagName == HTMLNames::titleTag 204 || tagName == HTMLNames::trTag 205 || tagName == HTMLNames::ulTag 206 || tagName == HTMLNames::wbrTag 207 || tagName == HTMLNames::xmpTag; 208 } 209 210 void trace(Visitor* visitor) { visitor->trace(m_node); } 211 212 private: 213 HTMLStackItem(PassRefPtrWillBeRawPtr<ContainerNode> node, ItemType type) 214 : m_node(node) 215 { 216 switch (type) { 217 case ItemForDocumentFragmentNode: 218 m_isDocumentFragmentNode = true; 219 break; 220 case ItemForContextElement: 221 m_tokenLocalName = m_node->localName(); 222 m_namespaceURI = m_node->namespaceURI(); 223 m_isDocumentFragmentNode = false; 224 break; 225 } 226 } 227 228 HTMLStackItem(PassRefPtrWillBeRawPtr<ContainerNode> node, AtomicHTMLToken* token, const AtomicString& namespaceURI = HTMLNames::xhtmlNamespaceURI) 229 : m_node(node) 230 , m_tokenLocalName(token->name()) 231 , m_tokenAttributes(token->attributes()) 232 , m_namespaceURI(namespaceURI) 233 , m_isDocumentFragmentNode(false) 234 { 235 } 236 237 RefPtrWillBeMember<ContainerNode> m_node; 238 239 AtomicString m_tokenLocalName; 240 Vector<Attribute> m_tokenAttributes; 241 AtomicString m_namespaceURI; 242 bool m_isDocumentFragmentNode; 243 }; 244 245 } // namespace WebCore 246 247 #endif // HTMLStackItem_h 248