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 "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