Home | History | Annotate | Download | only in parser
      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