1 /* 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. 3 * Copyright (C) 2011 Apple Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #ifndef HTMLConstructionSite_h 28 #define HTMLConstructionSite_h 29 30 #include "FragmentScriptingPermission.h" 31 #include "HTMLElementStack.h" 32 #include "HTMLFormattingElementList.h" 33 #include "NotImplemented.h" 34 #include <wtf/Noncopyable.h> 35 #include <wtf/PassRefPtr.h> 36 #include <wtf/RefPtr.h> 37 38 namespace WebCore { 39 40 class AtomicHTMLToken; 41 class Document; 42 class Element; 43 44 class HTMLConstructionSite { 45 WTF_MAKE_NONCOPYABLE(HTMLConstructionSite); 46 public: 47 HTMLConstructionSite(Document*); 48 HTMLConstructionSite(DocumentFragment*, FragmentScriptingPermission); 49 ~HTMLConstructionSite(); 50 51 void detach(); 52 53 void insertDoctype(AtomicHTMLToken&); 54 void insertComment(AtomicHTMLToken&); 55 void insertCommentOnDocument(AtomicHTMLToken&); 56 void insertCommentOnHTMLHtmlElement(AtomicHTMLToken&); 57 void insertHTMLElement(AtomicHTMLToken&); 58 void insertSelfClosingHTMLElement(AtomicHTMLToken&); 59 void insertFormattingElement(AtomicHTMLToken&); 60 void insertHTMLHeadElement(AtomicHTMLToken&); 61 void insertHTMLBodyElement(AtomicHTMLToken&); 62 void insertHTMLFormElement(AtomicHTMLToken&, bool isDemoted = false); 63 void insertScriptElement(AtomicHTMLToken&); 64 void insertTextNode(const String&); 65 void insertForeignElement(AtomicHTMLToken&, const AtomicString& namespaceURI); 66 67 void insertHTMLHtmlStartTagBeforeHTML(AtomicHTMLToken&); 68 void insertHTMLHtmlStartTagInBody(AtomicHTMLToken&); 69 void insertHTMLBodyStartTagInBody(AtomicHTMLToken&); 70 71 PassRefPtr<Element> createHTMLElement(AtomicHTMLToken&); 72 PassRefPtr<Element> createHTMLElementFromElementRecord(HTMLElementStack::ElementRecord*); 73 74 bool shouldFosterParent() const; 75 void fosterParent(Node*); 76 77 bool indexOfFirstUnopenFormattingElement(unsigned& firstUnopenElementIndex) const; 78 void reconstructTheActiveFormattingElements(); 79 80 void generateImpliedEndTags(); 81 void generateImpliedEndTagsWithExclusion(const AtomicString& tagName); 82 currentElement()83 Element* currentElement() const { return m_openElements.top(); } currentNode()84 ContainerNode* currentNode() const { return m_openElements.topNode(); } oneBelowTop()85 Element* oneBelowTop() const { return m_openElements.oneBelowTop(); } 86 openElements()87 HTMLElementStack* openElements() const { return &m_openElements; } activeFormattingElements()88 HTMLFormattingElementList* activeFormattingElements() const { return &m_activeFormattingElements; } 89 head()90 Element* head() const { return m_head.get(); } 91 92 void setForm(HTMLFormElement*); form()93 HTMLFormElement* form() const { return m_form.get(); } 94 PassRefPtr<HTMLFormElement> takeForm(); 95 96 class RedirectToFosterParentGuard { 97 WTF_MAKE_NONCOPYABLE(RedirectToFosterParentGuard); 98 public: RedirectToFosterParentGuard(HTMLConstructionSite & tree)99 RedirectToFosterParentGuard(HTMLConstructionSite& tree) 100 : m_tree(tree) 101 , m_wasRedirectingBefore(tree.m_redirectAttachToFosterParent) 102 { 103 m_tree.m_redirectAttachToFosterParent = true; 104 } 105 ~RedirectToFosterParentGuard()106 ~RedirectToFosterParentGuard() 107 { 108 m_tree.m_redirectAttachToFosterParent = m_wasRedirectingBefore; 109 } 110 111 private: 112 HTMLConstructionSite& m_tree; 113 bool m_wasRedirectingBefore; 114 }; 115 116 private: 117 struct AttachmentSite { 118 ContainerNode* parent; 119 Node* nextChild; 120 }; 121 122 template<typename ChildType> 123 PassRefPtr<ChildType> attach(ContainerNode* parent, PassRefPtr<ChildType> child); 124 PassRefPtr<Element> attachToCurrent(PassRefPtr<Element>); 125 126 void attachAtSite(const AttachmentSite&, PassRefPtr<Node> child); 127 void findFosterSite(AttachmentSite&); 128 129 PassRefPtr<Element> createHTMLElementFromSavedElement(Element*); 130 PassRefPtr<Element> createElement(AtomicHTMLToken&, const AtomicString& namespaceURI); 131 132 void mergeAttributesFromTokenIntoElement(AtomicHTMLToken&, Element*); 133 void dispatchDocumentElementAvailableIfNeeded(); 134 135 Document* m_document; 136 137 // This is the root ContainerNode to which the parser attaches all newly 138 // constructed nodes. It points to a DocumentFragment when parsing fragments 139 // and a Document in all other cases. 140 ContainerNode* m_attachmentRoot; 141 142 RefPtr<Element> m_head; 143 RefPtr<HTMLFormElement> m_form; 144 mutable HTMLElementStack m_openElements; 145 mutable HTMLFormattingElementList m_activeFormattingElements; 146 147 FragmentScriptingPermission m_fragmentScriptingPermission; 148 bool m_isParsingFragment; 149 150 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#parsing-main-intable 151 // In the "in table" insertion mode, we sometimes get into a state where 152 // "whenever a node would be inserted into the current node, it must instead 153 // be foster parented." This flag tracks whether we're in that state. 154 bool m_redirectAttachToFosterParent; 155 }; 156 157 } 158 159 #endif 160