Use the original token to create an element in "reconstruct the active formatting...
[WebKit-https.git] / Source / WebCore / html / parser / HTMLTreeBuilder.cpp
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 #include "config.h"
28 #include "HTMLTreeBuilder.h"
29
30 #include "Comment.h"
31 #include "DOMWindow.h"
32 #include "DocumentFragment.h"
33 #include "DocumentType.h"
34 #include "Frame.h"
35 #include "HTMLDocument.h"
36 #include "HTMLDocumentParser.h"
37 #include "HTMLElementFactory.h"
38 #include "HTMLFormElement.h"
39 #include "HTMLHtmlElement.h"
40 #include "HTMLNames.h"
41 #include "HTMLParserIdioms.h"
42 #include "HTMLScriptElement.h"
43 #include "HTMLStackItem.h"
44 #include "HTMLToken.h"
45 #include "HTMLTokenizer.h"
46 #include "LocalizedStrings.h"
47 #include "MathMLNames.h"
48 #include "NotImplemented.h"
49 #include "SVGNames.h"
50 #include "Text.h"
51 #include "XLinkNames.h"
52 #include "XMLNSNames.h"
53 #include "XMLNames.h"
54 #include <wtf/unicode/CharacterNames.h>
55
56 namespace WebCore {
57
58 using namespace HTMLNames;
59
60 static TextPosition uninitializedPositionValue1()
61 {
62     return TextPosition(OrdinalNumber::fromOneBasedInt(-1), OrdinalNumber::first());
63 }
64
65 namespace {
66
67 inline bool isHTMLSpaceOrReplacementCharacter(UChar character)
68 {
69     return isHTMLSpace(character) || character == replacementCharacter;
70 }
71
72 inline bool isAllWhitespace(const String& string)
73 {
74     return string.isAllSpecialCharacters<isHTMLSpace>();
75 }
76
77 inline bool isAllWhitespaceOrReplacementCharacters(const String& string)
78 {
79     return string.isAllSpecialCharacters<isHTMLSpaceOrReplacementCharacter>();
80 }
81
82 bool isNumberedHeaderTag(const AtomicString& tagName)
83 {
84     return tagName == h1Tag
85         || tagName == h2Tag
86         || tagName == h3Tag
87         || tagName == h4Tag
88         || tagName == h5Tag
89         || tagName == h6Tag;
90 }
91
92 bool isCaptionColOrColgroupTag(const AtomicString& tagName)
93 {
94     return tagName == captionTag
95         || tagName == colTag
96         || tagName == colgroupTag;
97 }
98
99 bool isTableCellContextTag(const AtomicString& tagName)
100 {
101     return tagName == thTag || tagName == tdTag;
102 }
103
104 bool isTableBodyContextTag(const AtomicString& tagName)
105 {
106     return tagName == tbodyTag
107         || tagName == tfootTag
108         || tagName == theadTag;
109 }
110
111 // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#special
112 bool isSpecialNode(Node* node)
113 {
114     if (node->hasTagName(MathMLNames::miTag)
115         || node->hasTagName(MathMLNames::moTag)
116         || node->hasTagName(MathMLNames::mnTag)
117         || node->hasTagName(MathMLNames::msTag)
118         || node->hasTagName(MathMLNames::mtextTag)
119         || node->hasTagName(MathMLNames::annotation_xmlTag)
120         || node->hasTagName(SVGNames::foreignObjectTag)
121         || node->hasTagName(SVGNames::descTag)
122         || node->hasTagName(SVGNames::titleTag))
123         return true;
124     if (node->nodeType() == Node::DOCUMENT_FRAGMENT_NODE)
125         return true;
126     if (!isInHTMLNamespace(node))
127         return false;
128     const AtomicString& tagName = node->localName();
129     return tagName == addressTag
130         || tagName == appletTag
131         || tagName == areaTag
132         || tagName == articleTag
133         || tagName == asideTag
134         || tagName == baseTag
135         || tagName == basefontTag
136         || tagName == bgsoundTag
137         || tagName == blockquoteTag
138         || tagName == bodyTag
139         || tagName == brTag
140         || tagName == buttonTag
141         || tagName == captionTag
142         || tagName == centerTag
143         || tagName == colTag
144         || tagName == colgroupTag
145         || tagName == commandTag
146         || tagName == ddTag
147         || tagName == detailsTag
148         || tagName == dirTag
149         || tagName == divTag
150         || tagName == dlTag
151         || tagName == dtTag
152         || tagName == embedTag
153         || tagName == fieldsetTag
154         || tagName == figcaptionTag
155         || tagName == figureTag
156         || tagName == footerTag
157         || tagName == formTag
158         || tagName == frameTag
159         || tagName == framesetTag
160         || isNumberedHeaderTag(tagName)
161         || tagName == headTag
162         || tagName == headerTag
163         || tagName == hgroupTag
164         || tagName == hrTag
165         || tagName == htmlTag
166         || tagName == iframeTag
167         || tagName == imgTag
168         || tagName == inputTag
169         || tagName == isindexTag
170         || tagName == liTag
171         || tagName == linkTag
172         || tagName == listingTag
173         || tagName == marqueeTag
174         || tagName == menuTag
175         || tagName == metaTag
176         || tagName == navTag
177         || tagName == noembedTag
178         || tagName == noframesTag
179         || tagName == noscriptTag
180         || tagName == objectTag
181         || tagName == olTag
182         || tagName == pTag
183         || tagName == paramTag
184         || tagName == plaintextTag
185         || tagName == preTag
186         || tagName == scriptTag
187         || tagName == sectionTag
188         || tagName == selectTag
189         || tagName == styleTag
190         || tagName == summaryTag
191         || tagName == tableTag
192         || isTableBodyContextTag(tagName)
193         || tagName == tdTag
194         || tagName == textareaTag
195         || tagName == thTag
196         || tagName == titleTag
197         || tagName == trTag
198         || tagName == ulTag
199         || tagName == wbrTag
200         || tagName == xmpTag;
201 }
202
203 bool isNonAnchorNonNobrFormattingTag(const AtomicString& tagName)
204 {
205     return tagName == bTag
206         || tagName == bigTag
207         || tagName == codeTag
208         || tagName == emTag
209         || tagName == fontTag
210         || tagName == iTag
211         || tagName == sTag
212         || tagName == smallTag
213         || tagName == strikeTag
214         || tagName == strongTag
215         || tagName == ttTag
216         || tagName == uTag;
217 }
218
219 bool isNonAnchorFormattingTag(const AtomicString& tagName)
220 {
221     return tagName == nobrTag
222         || isNonAnchorNonNobrFormattingTag(tagName);
223 }
224
225 // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#formatting
226 bool isFormattingTag(const AtomicString& tagName)
227 {
228     return tagName == aTag || isNonAnchorFormattingTag(tagName);
229 }
230
231 HTMLFormElement* closestFormAncestor(Element* element)
232 {
233     while (element) {
234         if (element->hasTagName(formTag))
235             return static_cast<HTMLFormElement*>(element);
236         ContainerNode* parent = element->parentNode();
237         if (!parent || !parent->isElementNode())
238             return 0;
239         element = static_cast<Element*>(parent);
240     }
241     return 0;
242 }
243
244 } // namespace
245
246 class HTMLTreeBuilder::ExternalCharacterTokenBuffer {
247     WTF_MAKE_NONCOPYABLE(ExternalCharacterTokenBuffer);
248 public:
249     explicit ExternalCharacterTokenBuffer(AtomicHTMLToken* token)
250         : m_current(token->characters().data())
251         , m_end(m_current + token->characters().size())
252     {
253         ASSERT(!isEmpty());
254     }
255
256     explicit ExternalCharacterTokenBuffer(const String& string)
257         : m_current(string.characters())
258         , m_end(m_current + string.length())
259     {
260         ASSERT(!isEmpty());
261     }
262
263     ~ExternalCharacterTokenBuffer()
264     {
265         ASSERT(isEmpty());
266     }
267
268     bool isEmpty() const { return m_current == m_end; }
269
270     void skipAtMostOneLeadingNewline()
271     {
272         ASSERT(!isEmpty());
273         if (*m_current == '\n')
274             ++m_current;
275     }
276
277     void skipLeadingWhitespace()
278     {
279         skipLeading<isHTMLSpace>();
280     }
281
282     String takeLeadingWhitespace()
283     {
284         return takeLeading<isHTMLSpace>();
285     }
286
287     void skipLeadingNonWhitespace()
288     {
289         skipLeading<isNotHTMLSpace>();
290     }
291
292     String takeRemaining()
293     {
294         ASSERT(!isEmpty());
295         const UChar* start = m_current;
296         m_current = m_end;
297         return String(start, m_current - start);
298     }
299
300     void giveRemainingTo(StringBuilder& recipient)
301     {
302         recipient.append(m_current, m_end - m_current);
303         m_current = m_end;
304     }
305
306     String takeRemainingWhitespace()
307     {
308         ASSERT(!isEmpty());
309         Vector<UChar> whitespace;
310         do {
311             UChar cc = *m_current++;
312             if (isHTMLSpace(cc))
313                 whitespace.append(cc);
314         } while (m_current < m_end);
315         // Returning the null string when there aren't any whitespace
316         // characters is slightly cleaner semantically because we don't want
317         // to insert a text node (as opposed to inserting an empty text node).
318         if (whitespace.isEmpty())
319             return String();
320         return String::adopt(whitespace);
321     }
322
323 private:
324     template<bool characterPredicate(UChar)>
325     void skipLeading()
326     {
327         ASSERT(!isEmpty());
328         while (characterPredicate(*m_current)) {
329             if (++m_current == m_end)
330                 return;
331         }
332     }
333
334     template<bool characterPredicate(UChar)>
335     String takeLeading()
336     {
337         ASSERT(!isEmpty());
338         const UChar* start = m_current;
339         skipLeading<characterPredicate>();
340         if (start == m_current)
341             return String();
342         return String(start, m_current - start);
343     }
344
345     const UChar* m_current;
346     const UChar* m_end;
347 };
348
349
350 HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser, HTMLDocument* document, bool, bool usePreHTML5ParserQuirks, unsigned maximumDOMTreeDepth)
351     : m_framesetOk(true)
352     , m_document(document)
353     , m_tree(document, maximumDOMTreeDepth)
354     , m_insertionMode(InitialMode)
355     , m_originalInsertionMode(InitialMode)
356     , m_shouldSkipLeadingNewline(false)
357     , m_parser(parser)
358     , m_scriptToProcessStartPosition(uninitializedPositionValue1())
359     , m_usePreHTML5ParserQuirks(usePreHTML5ParserQuirks)
360 {
361 }
362
363 // FIXME: Member variables should be grouped into self-initializing structs to
364 // minimize code duplication between these constructors.
365 HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser, DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission, bool usePreHTML5ParserQuirks, unsigned maximumDOMTreeDepth)
366     : m_framesetOk(true)
367     , m_fragmentContext(fragment, contextElement, scriptingPermission)
368     , m_document(fragment->document())
369     , m_tree(fragment, scriptingPermission, maximumDOMTreeDepth)
370     , m_insertionMode(InitialMode)
371     , m_originalInsertionMode(InitialMode)
372     , m_shouldSkipLeadingNewline(false)
373     , m_parser(parser)
374     , m_scriptToProcessStartPosition(uninitializedPositionValue1())
375     , m_usePreHTML5ParserQuirks(usePreHTML5ParserQuirks)
376 {
377     // FIXME: This assertion will become invalid if <http://webkit.org/b/60316> is fixed.
378     ASSERT(contextElement);
379     if (contextElement) {
380         // Steps 4.2-4.6 of the HTML5 Fragment Case parsing algorithm:
381         // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#fragment-case
382         // For efficiency, we skip step 4.2 ("Let root be a new html element with no attributes")
383         // and instead use the DocumentFragment as a root node.
384         m_tree.openElements()->pushRootNode(HTMLStackItem::create(fragment));
385         resetInsertionModeAppropriately();
386         m_tree.setForm(closestFormAncestor(contextElement));
387     }
388 }
389
390 HTMLTreeBuilder::~HTMLTreeBuilder()
391 {
392 }
393
394 void HTMLTreeBuilder::detach()
395 {
396     // This call makes little sense in fragment mode, but for consistency
397     // DocumentParser expects detach() to always be called before it's destroyed.
398     m_document = 0;
399     // HTMLConstructionSite might be on the callstack when detach() is called
400     // otherwise we'd just call m_tree.clear() here instead.
401     m_tree.detach();
402 }
403
404 HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext()
405     : m_fragment(0)
406     , m_contextElement(0)
407     , m_scriptingPermission(AllowScriptingContent)
408 {
409 }
410
411 HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext(DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission)
412     : m_fragment(fragment)
413     , m_contextElement(contextElement)
414     , m_scriptingPermission(scriptingPermission)
415 {
416     ASSERT(!fragment->hasChildNodes());
417 }
418
419 HTMLTreeBuilder::FragmentParsingContext::~FragmentParsingContext()
420 {
421 }
422
423 PassRefPtr<Element> HTMLTreeBuilder::takeScriptToProcess(TextPosition& scriptStartPosition)
424 {
425     ASSERT(m_scriptToProcess);
426     // Unpause ourselves, callers may pause us again when processing the script.
427     // The HTML5 spec is written as though scripts are executed inside the tree
428     // builder.  We pause the parser to exit the tree builder, and then resume
429     // before running scripts.
430     scriptStartPosition = m_scriptToProcessStartPosition;
431     m_scriptToProcessStartPosition = uninitializedPositionValue1();
432     return m_scriptToProcess.release();
433 }
434
435 void HTMLTreeBuilder::constructTreeFromToken(HTMLToken& rawToken)
436 {
437     RefPtr<AtomicHTMLToken> token = AtomicHTMLToken::create(rawToken);
438
439     // We clear the rawToken in case constructTreeFromAtomicToken
440     // synchronously re-enters the parser. We don't clear the token immedately
441     // for Character tokens because the AtomicHTMLToken avoids copying the
442     // characters by keeping a pointer to the underlying buffer in the
443     // HTMLToken. Fortuantely, Character tokens can't cause use to re-enter
444     // the parser.
445     //
446     // FIXME: Stop clearing the rawToken once we start running the parser off
447     // the main thread or once we stop allowing synchronous JavaScript
448     // execution from parseAttribute.
449     if (rawToken.type() != HTMLTokenTypes::Character)
450         rawToken.clear();
451
452     constructTreeFromAtomicToken(token.get());
453
454     if (!rawToken.isUninitialized()) {
455         ASSERT(rawToken.type() == HTMLTokenTypes::Character);
456         rawToken.clear();
457     }
458 }
459
460 void HTMLTreeBuilder::constructTreeFromAtomicToken(AtomicHTMLToken* token)
461 {
462     if (shouldProcessTokenInForeignContent(token))
463         processTokenInForeignContent(token);
464     else
465         processToken(token);
466
467     bool inForeignContent = !m_tree.isEmpty()
468         && !isInHTMLNamespace(m_tree.currentNode())
469         && !HTMLElementStack::isHTMLIntegrationPoint(m_tree.currentNode())
470         && !HTMLElementStack::isMathMLTextIntegrationPoint(m_tree.currentNode());
471
472     m_parser->tokenizer()->setForceNullCharacterReplacement(m_insertionMode == TextMode || inForeignContent);
473     m_parser->tokenizer()->setShouldAllowCDATA(inForeignContent);
474
475     m_tree.executeQueuedTasks();
476     // We might be detached now.
477 }
478
479 void HTMLTreeBuilder::processToken(AtomicHTMLToken* token)
480 {
481     switch (token->type()) {
482     case HTMLTokenTypes::Uninitialized:
483         ASSERT_NOT_REACHED();
484         break;
485     case HTMLTokenTypes::DOCTYPE:
486         m_shouldSkipLeadingNewline = false;
487         processDoctypeToken(token);
488         break;
489     case HTMLTokenTypes::StartTag:
490         m_shouldSkipLeadingNewline = false;
491         processStartTag(token);
492         break;
493     case HTMLTokenTypes::EndTag:
494         m_shouldSkipLeadingNewline = false;
495         processEndTag(token);
496         break;
497     case HTMLTokenTypes::Comment:
498         m_shouldSkipLeadingNewline = false;
499         processComment(token);
500         return;
501     case HTMLTokenTypes::Character:
502         processCharacter(token);
503         break;
504     case HTMLTokenTypes::EndOfFile:
505         m_shouldSkipLeadingNewline = false;
506         processEndOfFile(token);
507         break;
508     }
509 }
510
511 void HTMLTreeBuilder::processDoctypeToken(AtomicHTMLToken* token)
512 {
513     ASSERT(token->type() == HTMLTokenTypes::DOCTYPE);
514     if (m_insertionMode == InitialMode) {
515         m_tree.insertDoctype(token);
516         setInsertionMode(BeforeHTMLMode);
517         return;
518     }
519     if (m_insertionMode == InTableTextMode) {
520         defaultForInTableText();
521         processDoctypeToken(token);
522         return;
523     }
524     parseError(token);
525 }
526
527 void HTMLTreeBuilder::processFakeStartTag(const QualifiedName& tagName, const Vector<Attribute>& attributes)
528 {
529     // FIXME: We'll need a fancier conversion than just "localName" for SVG/MathML tags.
530     RefPtr<AtomicHTMLToken> fakeToken = AtomicHTMLToken::create(HTMLTokenTypes::StartTag, tagName.localName(), attributes);
531     processStartTag(fakeToken.get());
532 }
533
534 void HTMLTreeBuilder::processFakeEndTag(const QualifiedName& tagName)
535 {
536     // FIXME: We'll need a fancier conversion than just "localName" for SVG/MathML tags.
537     RefPtr<AtomicHTMLToken> fakeToken = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, tagName.localName());
538     processEndTag(fakeToken.get());
539 }
540
541 void HTMLTreeBuilder::processFakeCharacters(const String& characters)
542 {
543     ASSERT(!characters.isEmpty());
544     ExternalCharacterTokenBuffer buffer(characters);
545     processCharacterBuffer(buffer);
546 }
547
548 void HTMLTreeBuilder::processFakePEndTagIfPInButtonScope()
549 {
550     if (!m_tree.openElements()->inButtonScope(pTag.localName()))
551         return;
552     RefPtr<AtomicHTMLToken> endP = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, pTag.localName());
553     processEndTag(endP.get());
554 }
555
556 Vector<Attribute> HTMLTreeBuilder::attributesForIsindexInput(AtomicHTMLToken* token)
557 {
558     Vector<Attribute> attributes = token->attributes();
559     for (int i = attributes.size() - 1; i >= 0; --i) {
560         const QualifiedName& name = attributes.at(i).name();
561         if (name.matches(nameAttr) || name.matches(actionAttr) || name.matches(promptAttr))
562             attributes.remove(i);
563     }
564
565     attributes.append(Attribute(nameAttr, isindexTag.localName()));
566     return attributes;
567 }
568
569 void HTMLTreeBuilder::processIsindexStartTagForInBody(AtomicHTMLToken* token)
570 {
571     ASSERT(token->type() == HTMLTokenTypes::StartTag);
572     ASSERT(token->name() == isindexTag);
573     parseError(token);
574     if (m_tree.form())
575         return;
576     notImplemented(); // Acknowledge self-closing flag
577     processFakeStartTag(formTag);
578     Attribute* actionAttribute = token->getAttributeItem(actionAttr);
579     if (actionAttribute)
580         m_tree.form()->setAttribute(actionAttr, actionAttribute->value());
581     processFakeStartTag(hrTag);
582     processFakeStartTag(labelTag);
583     Attribute* promptAttribute = token->getAttributeItem(promptAttr);
584     if (promptAttribute)
585         processFakeCharacters(promptAttribute->value());
586     else
587         processFakeCharacters(searchableIndexIntroduction());
588     processFakeStartTag(inputTag, attributesForIsindexInput(token));
589     notImplemented(); // This second set of characters may be needed by non-english locales.
590     processFakeEndTag(labelTag);
591     processFakeStartTag(hrTag);
592     processFakeEndTag(formTag);
593 }
594
595 namespace {
596
597 bool isLi(const ContainerNode* element)
598 {
599     return element->hasTagName(liTag);
600 }
601
602 bool isDdOrDt(const ContainerNode* element)
603 {
604     return element->hasTagName(ddTag)
605         || element->hasTagName(dtTag);
606 }
607
608 }
609
610 template <bool shouldClose(const ContainerNode*)>
611 void HTMLTreeBuilder::processCloseWhenNestedTag(AtomicHTMLToken* token)
612 {
613     m_framesetOk = false;
614     HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord();
615     while (1) {
616         RefPtr<ContainerNode> node = nodeRecord->node();
617         if (shouldClose(node.get())) {
618             ASSERT(node->isElementNode());
619             processFakeEndTag(toElement(node.get())->tagQName());
620             break;
621         }
622         if (isSpecialNode(node.get()) && !node->hasTagName(addressTag) && !node->hasTagName(divTag) && !node->hasTagName(pTag))
623             break;
624         nodeRecord = nodeRecord->next();
625     }
626     processFakePEndTagIfPInButtonScope();
627     m_tree.insertHTMLElement(token);
628 }
629
630 namespace {
631
632 typedef HashMap<AtomicString, QualifiedName> PrefixedNameToQualifiedNameMap;
633
634 void mapLoweredLocalNameToName(PrefixedNameToQualifiedNameMap* map, QualifiedName** names, size_t length)
635 {
636     for (size_t i = 0; i < length; ++i) {
637         const QualifiedName& name = *names[i];
638         const AtomicString& localName = name.localName();
639         AtomicString loweredLocalName = localName.lower();
640         if (loweredLocalName != localName)
641             map->add(loweredLocalName, name);
642     }
643 }
644
645 void adjustSVGTagNameCase(AtomicHTMLToken* token)
646 {
647     static PrefixedNameToQualifiedNameMap* caseMap = 0;
648     if (!caseMap) {
649         caseMap = new PrefixedNameToQualifiedNameMap;
650         size_t length = 0;
651         QualifiedName** svgTags = SVGNames::getSVGTags(&length);
652         mapLoweredLocalNameToName(caseMap, svgTags, length);
653     }
654
655     const QualifiedName& casedName = caseMap->get(token->name());
656     if (casedName.localName().isNull())
657         return;
658     token->setName(casedName.localName());
659 }
660
661 template<QualifiedName** getAttrs(size_t* length)>
662 void adjustAttributes(AtomicHTMLToken* token)
663 {
664     static PrefixedNameToQualifiedNameMap* caseMap = 0;
665     if (!caseMap) {
666         caseMap = new PrefixedNameToQualifiedNameMap;
667         size_t length = 0;
668         QualifiedName** attrs = getAttrs(&length);
669         mapLoweredLocalNameToName(caseMap, attrs, length);
670     }
671
672     for (unsigned i = 0; i < token->attributes().size(); ++i) {
673         Attribute& tokenAttribute = token->attributes().at(i);
674         const QualifiedName& casedName = caseMap->get(tokenAttribute.localName());
675         if (!casedName.localName().isNull())
676             tokenAttribute.parserSetName(casedName);
677     }
678 }
679
680 void adjustSVGAttributes(AtomicHTMLToken* token)
681 {
682     adjustAttributes<SVGNames::getSVGAttrs>(token);
683 }
684
685 void adjustMathMLAttributes(AtomicHTMLToken* token)
686 {
687     adjustAttributes<MathMLNames::getMathMLAttrs>(token);
688 }
689
690 void addNamesWithPrefix(PrefixedNameToQualifiedNameMap* map, const AtomicString& prefix, QualifiedName** names, size_t length)
691 {
692     for (size_t i = 0; i < length; ++i) {
693         QualifiedName* name = names[i];
694         const AtomicString& localName = name->localName();
695         AtomicString prefixColonLocalName = prefix + ':' + localName;
696         QualifiedName nameWithPrefix(prefix, localName, name->namespaceURI());
697         map->add(prefixColonLocalName, nameWithPrefix);
698     }
699 }
700
701 void adjustForeignAttributes(AtomicHTMLToken* token)
702 {
703     static PrefixedNameToQualifiedNameMap* map = 0;
704     if (!map) {
705         map = new PrefixedNameToQualifiedNameMap;
706         size_t length = 0;
707         QualifiedName** attrs = XLinkNames::getXLinkAttrs(&length);
708         addNamesWithPrefix(map, "xlink", attrs, length);
709
710         attrs = XMLNames::getXMLAttrs(&length);
711         addNamesWithPrefix(map, "xml", attrs, length);
712
713         map->add("xmlns", XMLNSNames::xmlnsAttr);
714         map->add("xmlns:xlink", QualifiedName("xmlns", "xlink", XMLNSNames::xmlnsNamespaceURI));
715     }
716
717     for (unsigned i = 0; i < token->attributes().size(); ++i) {
718         Attribute& tokenAttribute = token->attributes().at(i);
719         const QualifiedName& name = map->get(tokenAttribute.localName());
720         if (!name.localName().isNull())
721             tokenAttribute.parserSetName(name);
722     }
723 }
724
725 }
726
727 void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token)
728 {
729     ASSERT(token->type() == HTMLTokenTypes::StartTag);
730     if (token->name() == htmlTag) {
731         processHtmlStartTagForInBody(token);
732         return;
733     }
734     if (token->name() == baseTag
735         || token->name() == basefontTag
736         || token->name() == bgsoundTag
737         || token->name() == commandTag
738         || token->name() == linkTag
739         || token->name() == metaTag
740         || token->name() == noframesTag
741         || token->name() == scriptTag
742         || token->name() == styleTag
743         || token->name() == titleTag) {
744         bool didProcess = processStartTagForInHead(token);
745         ASSERT_UNUSED(didProcess, didProcess);
746         return;
747     }
748     if (token->name() == bodyTag) {
749         parseError(token);
750         if (!m_tree.openElements()->secondElementIsHTMLBodyElement() || m_tree.openElements()->hasOnlyOneElement()) {
751             ASSERT(isParsingFragment());
752             return;
753         }
754         m_framesetOk = false;
755         m_tree.insertHTMLBodyStartTagInBody(token);
756         return;
757     }
758     if (token->name() == framesetTag) {
759         parseError(token);
760         if (!m_tree.openElements()->secondElementIsHTMLBodyElement() || m_tree.openElements()->hasOnlyOneElement()) {
761             ASSERT(isParsingFragment());
762             return;
763         }
764         if (!m_framesetOk)
765             return;
766         ExceptionCode ec = 0;
767         m_tree.openElements()->bodyElement()->remove(ec);
768         ASSERT(!ec);
769         m_tree.openElements()->popUntil(m_tree.openElements()->bodyElement());
770         m_tree.openElements()->popHTMLBodyElement();
771         ASSERT(m_tree.openElements()->top() == m_tree.openElements()->htmlElement());
772         m_tree.insertHTMLElement(token);
773         setInsertionMode(InFramesetMode);
774         return;
775     }
776     if (token->name() == addressTag
777         || token->name() == articleTag
778         || token->name() == asideTag
779         || token->name() == blockquoteTag
780         || token->name() == centerTag
781         || token->name() == detailsTag
782         || token->name() == dirTag
783         || token->name() == divTag
784         || token->name() == dlTag
785         || token->name() == fieldsetTag
786         || token->name() == figcaptionTag
787         || token->name() == figureTag
788         || token->name() == footerTag
789         || token->name() == headerTag
790         || token->name() == hgroupTag
791         || token->name() == menuTag
792         || token->name() == navTag
793         || token->name() == olTag
794         || token->name() == pTag
795         || token->name() == sectionTag
796         || token->name() == summaryTag
797         || token->name() == ulTag) {
798         processFakePEndTagIfPInButtonScope();
799         m_tree.insertHTMLElement(token);
800         return;
801     }
802     if (isNumberedHeaderTag(token->name())) {
803         processFakePEndTagIfPInButtonScope();
804         if (isNumberedHeaderTag(m_tree.currentNode()->localName())) {
805             parseError(token);
806             m_tree.openElements()->pop();
807         }
808         m_tree.insertHTMLElement(token);
809         return;
810     }
811     if (token->name() == preTag || token->name() == listingTag) {
812         processFakePEndTagIfPInButtonScope();
813         m_tree.insertHTMLElement(token);
814         m_shouldSkipLeadingNewline = true;
815         m_framesetOk = false;
816         return;
817     }
818     if (token->name() == formTag) {
819         if (m_tree.form()) {
820             parseError(token);
821             return;
822         }
823         processFakePEndTagIfPInButtonScope();
824         m_tree.insertHTMLFormElement(token);
825         return;
826     }
827     if (token->name() == liTag) {
828         processCloseWhenNestedTag<isLi>(token);
829         return;
830     }
831     if (token->name() == ddTag || token->name() == dtTag) {
832         processCloseWhenNestedTag<isDdOrDt>(token);
833         return;
834     }
835     if (token->name() == plaintextTag) {
836         processFakePEndTagIfPInButtonScope();
837         m_tree.insertHTMLElement(token);
838         m_parser->tokenizer()->setState(HTMLTokenizerState::PLAINTEXTState);
839         return;
840     }
841     if (token->name() == buttonTag) {
842         if (m_tree.openElements()->inScope(buttonTag)) {
843             parseError(token);
844             processFakeEndTag(buttonTag);
845             processStartTag(token); // FIXME: Could we just fall through here?
846             return;
847         }
848         m_tree.reconstructTheActiveFormattingElements();
849         m_tree.insertHTMLElement(token);
850         m_framesetOk = false;
851         return;
852     }
853     if (token->name() == aTag) {
854         Element* activeATag = m_tree.activeFormattingElements()->closestElementInScopeWithName(aTag.localName());
855         if (activeATag) {
856             parseError(token);
857             processFakeEndTag(aTag);
858             m_tree.activeFormattingElements()->remove(activeATag);
859             if (m_tree.openElements()->contains(activeATag))
860                 m_tree.openElements()->remove(activeATag);
861         }
862         m_tree.reconstructTheActiveFormattingElements();
863         m_tree.insertFormattingElement(token);
864         return;
865     }
866     if (isNonAnchorNonNobrFormattingTag(token->name())) {
867         m_tree.reconstructTheActiveFormattingElements();
868         m_tree.insertFormattingElement(token);
869         return;
870     }
871     if (token->name() == nobrTag) {
872         m_tree.reconstructTheActiveFormattingElements();
873         if (m_tree.openElements()->inScope(nobrTag)) {
874             parseError(token);
875             processFakeEndTag(nobrTag);
876             m_tree.reconstructTheActiveFormattingElements();
877         }
878         m_tree.insertFormattingElement(token);
879         return;
880     }
881     if (token->name() == appletTag
882         || token->name() == marqueeTag
883         || token->name() == objectTag) {
884         m_tree.reconstructTheActiveFormattingElements();
885         m_tree.insertHTMLElement(token);
886         m_tree.activeFormattingElements()->appendMarker();
887         m_framesetOk = false;
888         return;
889     }
890     if (token->name() == tableTag) {
891         if (!m_document->inQuirksMode() && m_tree.openElements()->inButtonScope(pTag))
892             processFakeEndTag(pTag);
893         m_tree.insertHTMLElement(token);
894         m_framesetOk = false;
895         setInsertionMode(InTableMode);
896         return;
897     }
898     if (token->name() == imageTag) {
899         parseError(token);
900         // Apparently we're not supposed to ask.
901         token->setName(imgTag.localName());
902         // Note the fall through to the imgTag handling below!
903     }
904     if (token->name() == areaTag
905         || token->name() == brTag
906         || token->name() == embedTag
907         || token->name() == imgTag
908         || token->name() == keygenTag
909         || token->name() == wbrTag) {
910         m_tree.reconstructTheActiveFormattingElements();
911         m_tree.insertSelfClosingHTMLElement(token);
912         m_framesetOk = false;
913         return;
914     }
915     if (token->name() == inputTag) {
916         Attribute* typeAttribute = token->getAttributeItem(typeAttr);
917         m_tree.reconstructTheActiveFormattingElements();
918         m_tree.insertSelfClosingHTMLElement(token);
919         if (!typeAttribute || !equalIgnoringCase(typeAttribute->value(), "hidden"))
920             m_framesetOk = false;
921         return;
922     }
923     if (token->name() == paramTag
924         || token->name() == sourceTag
925         || token->name() == trackTag) {
926         m_tree.insertSelfClosingHTMLElement(token);
927         return;
928     }
929     if (token->name() == hrTag) {
930         processFakePEndTagIfPInButtonScope();
931         m_tree.insertSelfClosingHTMLElement(token);
932         m_framesetOk = false;
933         return;
934     }
935     if (token->name() == isindexTag) {
936         processIsindexStartTagForInBody(token);
937         return;
938     }
939     if (token->name() == textareaTag) {
940         m_tree.insertHTMLElement(token);
941         m_shouldSkipLeadingNewline = true;
942         m_parser->tokenizer()->setState(HTMLTokenizerState::RCDATAState);
943         m_originalInsertionMode = m_insertionMode;
944         m_framesetOk = false;
945         setInsertionMode(TextMode);
946         return;
947     }
948     if (token->name() == xmpTag) {
949         processFakePEndTagIfPInButtonScope();
950         m_tree.reconstructTheActiveFormattingElements();
951         m_framesetOk = false;
952         processGenericRawTextStartTag(token);
953         return;
954     }
955     if (token->name() == iframeTag) {
956         m_framesetOk = false;
957         processGenericRawTextStartTag(token);
958         return;
959     }
960     if (token->name() == noembedTag && pluginsEnabled(m_document->frame())) {
961         processGenericRawTextStartTag(token);
962         return;
963     }
964     if (token->name() == noscriptTag && scriptEnabled(m_document->frame())) {
965         processGenericRawTextStartTag(token);
966         return;
967     }
968     if (token->name() == selectTag) {
969         m_tree.reconstructTheActiveFormattingElements();
970         m_tree.insertHTMLElement(token);
971         m_framesetOk = false;
972         if (m_insertionMode == InTableMode
973              || m_insertionMode == InCaptionMode
974              || m_insertionMode == InColumnGroupMode
975              || m_insertionMode == InTableBodyMode
976              || m_insertionMode == InRowMode
977              || m_insertionMode == InCellMode)
978             setInsertionMode(InSelectInTableMode);
979         else
980             setInsertionMode(InSelectMode);
981         return;
982     }
983     if (token->name() == optgroupTag || token->name() == optionTag) {
984         if (m_tree.currentNode()->hasTagName(optionTag)) {
985             RefPtr<AtomicHTMLToken> endOption = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, optionTag.localName());
986             processEndTag(endOption.get());
987         }
988         m_tree.reconstructTheActiveFormattingElements();
989         m_tree.insertHTMLElement(token);
990         return;
991     }
992     if (token->name() == rpTag || token->name() == rtTag) {
993         if (m_tree.openElements()->inScope(rubyTag.localName())) {
994             m_tree.generateImpliedEndTags();
995             if (!m_tree.currentNode()->hasTagName(rubyTag))
996                 parseError(token);
997         }
998         m_tree.insertHTMLElement(token);
999         return;
1000     }
1001     if (token->name() == MathMLNames::mathTag.localName()) {
1002         m_tree.reconstructTheActiveFormattingElements();
1003         adjustMathMLAttributes(token);
1004         adjustForeignAttributes(token);
1005         m_tree.insertForeignElement(token, MathMLNames::mathmlNamespaceURI);
1006         return;
1007     }
1008     if (token->name() == SVGNames::svgTag.localName()) {
1009         m_tree.reconstructTheActiveFormattingElements();
1010         adjustSVGAttributes(token);
1011         adjustForeignAttributes(token);
1012         m_tree.insertForeignElement(token, SVGNames::svgNamespaceURI);
1013         return;
1014     }
1015     if (isCaptionColOrColgroupTag(token->name())
1016         || token->name() == frameTag
1017         || token->name() == headTag
1018         || isTableBodyContextTag(token->name())
1019         || isTableCellContextTag(token->name())
1020         || token->name() == trTag) {
1021         parseError(token);
1022         return;
1023     }
1024     m_tree.reconstructTheActiveFormattingElements();
1025     m_tree.insertHTMLElement(token);
1026 }
1027
1028 bool HTMLTreeBuilder::processColgroupEndTagForInColumnGroup()
1029 {
1030     if (m_tree.currentNode() == m_tree.openElements()->rootNode()) {
1031         ASSERT(isParsingFragment());
1032         // FIXME: parse error
1033         return false;
1034     }
1035     m_tree.openElements()->pop();
1036     setInsertionMode(InTableMode);
1037     return true;
1038 }
1039
1040 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#close-the-cell
1041 void HTMLTreeBuilder::closeTheCell()
1042 {
1043     ASSERT(insertionMode() == InCellMode);
1044     if (m_tree.openElements()->inTableScope(tdTag)) {
1045         ASSERT(!m_tree.openElements()->inTableScope(thTag));
1046         processFakeEndTag(tdTag);
1047         return;
1048     }
1049     ASSERT(m_tree.openElements()->inTableScope(thTag));
1050     processFakeEndTag(thTag);
1051     ASSERT(insertionMode() == InRowMode);
1052 }
1053
1054 void HTMLTreeBuilder::processStartTagForInTable(AtomicHTMLToken* token)
1055 {
1056     ASSERT(token->type() == HTMLTokenTypes::StartTag);
1057     if (token->name() == captionTag) {
1058         m_tree.openElements()->popUntilTableScopeMarker();
1059         m_tree.activeFormattingElements()->appendMarker();
1060         m_tree.insertHTMLElement(token);
1061         setInsertionMode(InCaptionMode);
1062         return;
1063     }
1064     if (token->name() == colgroupTag) {
1065         m_tree.openElements()->popUntilTableScopeMarker();
1066         m_tree.insertHTMLElement(token);
1067         setInsertionMode(InColumnGroupMode);
1068         return;
1069     }
1070     if (token->name() == colTag) {
1071         processFakeStartTag(colgroupTag);
1072         ASSERT(InColumnGroupMode);
1073         processStartTag(token);
1074         return;
1075     }
1076     if (isTableBodyContextTag(token->name())) {
1077         m_tree.openElements()->popUntilTableScopeMarker();
1078         m_tree.insertHTMLElement(token);
1079         setInsertionMode(InTableBodyMode);
1080         return;
1081     }
1082     if (isTableCellContextTag(token->name())
1083         || token->name() == trTag) {
1084         processFakeStartTag(tbodyTag);
1085         ASSERT(insertionMode() == InTableBodyMode);
1086         processStartTag(token);
1087         return;
1088     }
1089     if (token->name() == tableTag) {
1090         parseError(token);
1091         if (!processTableEndTagForInTable()) {
1092             ASSERT(isParsingFragment());
1093             return;
1094         }
1095         processStartTag(token);
1096         return;
1097     }
1098     if (token->name() == styleTag || token->name() == scriptTag) {
1099         processStartTagForInHead(token);
1100         return;
1101     }
1102     if (token->name() == inputTag) {
1103         Attribute* typeAttribute = token->getAttributeItem(typeAttr);
1104         if (typeAttribute && equalIgnoringCase(typeAttribute->value(), "hidden")) {
1105             parseError(token);
1106             m_tree.insertSelfClosingHTMLElement(token);
1107             return;
1108         }
1109         // Fall through to "anything else" case.
1110     }
1111     if (token->name() == formTag) {
1112         parseError(token);
1113         if (m_tree.form())
1114             return;
1115         m_tree.insertHTMLFormElement(token, true);
1116         m_tree.openElements()->pop();
1117         return;
1118     }
1119     parseError(token);
1120     HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
1121     processStartTagForInBody(token);
1122 }
1123
1124 void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
1125 {
1126     ASSERT(token->type() == HTMLTokenTypes::StartTag);
1127     switch (insertionMode()) {
1128     case InitialMode:
1129         ASSERT(insertionMode() == InitialMode);
1130         defaultForInitial();
1131         // Fall through.
1132     case BeforeHTMLMode:
1133         ASSERT(insertionMode() == BeforeHTMLMode);
1134         if (token->name() == htmlTag) {
1135             m_tree.insertHTMLHtmlStartTagBeforeHTML(token);
1136             setInsertionMode(BeforeHeadMode);
1137             return;
1138         }
1139         defaultForBeforeHTML();
1140         // Fall through.
1141     case BeforeHeadMode:
1142         ASSERT(insertionMode() == BeforeHeadMode);
1143         if (token->name() == htmlTag) {
1144             processHtmlStartTagForInBody(token);
1145             return;
1146         }
1147         if (token->name() == headTag) {
1148             m_tree.insertHTMLHeadElement(token);
1149             setInsertionMode(InHeadMode);
1150             return;
1151         }
1152         defaultForBeforeHead();
1153         // Fall through.
1154     case InHeadMode:
1155         ASSERT(insertionMode() == InHeadMode);
1156         if (processStartTagForInHead(token))
1157             return;
1158         defaultForInHead();
1159         // Fall through.
1160     case AfterHeadMode:
1161         ASSERT(insertionMode() == AfterHeadMode);
1162         if (token->name() == htmlTag) {
1163             processHtmlStartTagForInBody(token);
1164             return;
1165         }
1166         if (token->name() == bodyTag) {
1167             m_framesetOk = false;
1168             m_tree.insertHTMLBodyElement(token);
1169             setInsertionMode(InBodyMode);
1170             return;
1171         }
1172         if (token->name() == framesetTag) {
1173             m_tree.insertHTMLElement(token);
1174             setInsertionMode(InFramesetMode);
1175             return;
1176         }
1177         if (token->name() == baseTag
1178             || token->name() == basefontTag
1179             || token->name() == bgsoundTag
1180             || token->name() == linkTag
1181             || token->name() == metaTag
1182             || token->name() == noframesTag
1183             || token->name() == scriptTag
1184             || token->name() == styleTag
1185             || token->name() == titleTag) {
1186             parseError(token);
1187             ASSERT(m_tree.head());
1188             m_tree.openElements()->pushHTMLHeadElement(HTMLStackItem::create(m_tree.head(), token));
1189             processStartTagForInHead(token);
1190             m_tree.openElements()->removeHTMLHeadElement(m_tree.head());
1191             return;
1192         }
1193         if (token->name() == headTag) {
1194             parseError(token);
1195             return;
1196         }
1197         defaultForAfterHead();
1198         // Fall through
1199     case InBodyMode:
1200         ASSERT(insertionMode() == InBodyMode);
1201         processStartTagForInBody(token);
1202         break;
1203     case InTableMode:
1204         ASSERT(insertionMode() == InTableMode);
1205         processStartTagForInTable(token);
1206         break;
1207     case InCaptionMode:
1208         ASSERT(insertionMode() == InCaptionMode);
1209         if (isCaptionColOrColgroupTag(token->name())
1210             || isTableBodyContextTag(token->name())
1211             || isTableCellContextTag(token->name())
1212             || token->name() == trTag) {
1213             parseError(token);
1214             if (!processCaptionEndTagForInCaption()) {
1215                 ASSERT(isParsingFragment());
1216                 return;
1217             }
1218             processStartTag(token);
1219             return;
1220         }
1221         processStartTagForInBody(token);
1222         break;
1223     case InColumnGroupMode:
1224         ASSERT(insertionMode() == InColumnGroupMode);
1225         if (token->name() == htmlTag) {
1226             processHtmlStartTagForInBody(token);
1227             return;
1228         }
1229         if (token->name() == colTag) {
1230             m_tree.insertSelfClosingHTMLElement(token);
1231             return;
1232         }
1233         if (!processColgroupEndTagForInColumnGroup()) {
1234             ASSERT(isParsingFragment());
1235             return;
1236         }
1237         processStartTag(token);
1238         break;
1239     case InTableBodyMode:
1240         ASSERT(insertionMode() == InTableBodyMode);
1241         if (token->name() == trTag) {
1242             m_tree.openElements()->popUntilTableBodyScopeMarker(); // How is there ever anything to pop?
1243             m_tree.insertHTMLElement(token);
1244             setInsertionMode(InRowMode);
1245             return;
1246         }
1247         if (isTableCellContextTag(token->name())) {
1248             parseError(token);
1249             processFakeStartTag(trTag);
1250             ASSERT(insertionMode() == InRowMode);
1251             processStartTag(token);
1252             return;
1253         }
1254         if (isCaptionColOrColgroupTag(token->name()) || isTableBodyContextTag(token->name())) {
1255             // FIXME: This is slow.
1256             if (!m_tree.openElements()->inTableScope(tbodyTag.localName()) && !m_tree.openElements()->inTableScope(theadTag.localName()) && !m_tree.openElements()->inTableScope(tfootTag.localName())) {
1257                 ASSERT(isParsingFragment());
1258                 parseError(token);
1259                 return;
1260             }
1261             m_tree.openElements()->popUntilTableBodyScopeMarker();
1262             ASSERT(isTableBodyContextTag(m_tree.currentElement()->localName()));
1263             processFakeEndTag(m_tree.currentElement()->tagQName());
1264             processStartTag(token);
1265             return;
1266         }
1267         processStartTagForInTable(token);
1268         break;
1269     case InRowMode:
1270         ASSERT(insertionMode() == InRowMode);
1271         if (isTableCellContextTag(token->name())) {
1272             m_tree.openElements()->popUntilTableRowScopeMarker();
1273             m_tree.insertHTMLElement(token);
1274             setInsertionMode(InCellMode);
1275             m_tree.activeFormattingElements()->appendMarker();
1276             return;
1277         }
1278         if (token->name() == trTag
1279             || isCaptionColOrColgroupTag(token->name())
1280             || isTableBodyContextTag(token->name())) {
1281             if (!processTrEndTagForInRow()) {
1282                 ASSERT(isParsingFragment());
1283                 return;
1284             }
1285             ASSERT(insertionMode() == InTableBodyMode);
1286             processStartTag(token);
1287             return;
1288         }
1289         processStartTagForInTable(token);
1290         break;
1291     case InCellMode:
1292         ASSERT(insertionMode() == InCellMode);
1293         if (isCaptionColOrColgroupTag(token->name())
1294             || isTableCellContextTag(token->name())
1295             || token->name() == trTag
1296             || isTableBodyContextTag(token->name())) {
1297             // FIXME: This could be more efficient.
1298             if (!m_tree.openElements()->inTableScope(tdTag) && !m_tree.openElements()->inTableScope(thTag)) {
1299                 ASSERT(isParsingFragment());
1300                 parseError(token);
1301                 return;
1302             }
1303             closeTheCell();
1304             processStartTag(token);
1305             return;
1306         }
1307         processStartTagForInBody(token);
1308         break;
1309     case AfterBodyMode:
1310     case AfterAfterBodyMode:
1311         ASSERT(insertionMode() == AfterBodyMode || insertionMode() == AfterAfterBodyMode);
1312         if (token->name() == htmlTag) {
1313             processHtmlStartTagForInBody(token);
1314             return;
1315         }
1316         setInsertionMode(InBodyMode);
1317         processStartTag(token);
1318         break;
1319     case InHeadNoscriptMode:
1320         ASSERT(insertionMode() == InHeadNoscriptMode);
1321         if (token->name() == htmlTag) {
1322             processHtmlStartTagForInBody(token);
1323             return;
1324         }
1325         if (token->name() == basefontTag
1326             || token->name() == bgsoundTag
1327             || token->name() == linkTag
1328             || token->name() == metaTag
1329             || token->name() == noframesTag
1330             || token->name() == styleTag) {
1331             bool didProcess = processStartTagForInHead(token);
1332             ASSERT_UNUSED(didProcess, didProcess);
1333             return;
1334         }
1335         if (token->name() == htmlTag || token->name() == noscriptTag) {
1336             parseError(token);
1337             return;
1338         }
1339         defaultForInHeadNoscript();
1340         processToken(token);
1341         break;
1342     case InFramesetMode:
1343         ASSERT(insertionMode() == InFramesetMode);
1344         if (token->name() == htmlTag) {
1345             processHtmlStartTagForInBody(token);
1346             return;
1347         }
1348         if (token->name() == framesetTag) {
1349             m_tree.insertHTMLElement(token);
1350             return;
1351         }
1352         if (token->name() == frameTag) {
1353             m_tree.insertSelfClosingHTMLElement(token);
1354             return;
1355         }
1356         if (token->name() == noframesTag) {
1357             processStartTagForInHead(token);
1358             return;
1359         }
1360         parseError(token);
1361         break;
1362     case AfterFramesetMode:
1363     case AfterAfterFramesetMode:
1364         ASSERT(insertionMode() == AfterFramesetMode || insertionMode() == AfterAfterFramesetMode);
1365         if (token->name() == htmlTag) {
1366             processHtmlStartTagForInBody(token);
1367             return;
1368         }
1369         if (token->name() == noframesTag) {
1370             processStartTagForInHead(token);
1371             return;
1372         }
1373         parseError(token);
1374         break;
1375     case InSelectInTableMode:
1376         ASSERT(insertionMode() == InSelectInTableMode);
1377         if (token->name() == captionTag
1378             || token->name() == tableTag
1379             || isTableBodyContextTag(token->name())
1380             || token->name() == trTag
1381             || isTableCellContextTag(token->name())) {
1382             parseError(token);
1383             RefPtr<AtomicHTMLToken> endSelect = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, selectTag.localName());
1384             processEndTag(endSelect.get());
1385             processStartTag(token);
1386             return;
1387         }
1388         // Fall through
1389     case InSelectMode:
1390         ASSERT(insertionMode() == InSelectMode || insertionMode() == InSelectInTableMode);
1391         if (token->name() == htmlTag) {
1392             processHtmlStartTagForInBody(token);
1393             return;
1394         }
1395         if (token->name() == optionTag) {
1396             if (m_tree.currentNode()->hasTagName(optionTag)) {
1397                 RefPtr<AtomicHTMLToken> endOption = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, optionTag.localName());
1398                 processEndTag(endOption.get());
1399             }
1400             m_tree.insertHTMLElement(token);
1401             return;
1402         }
1403         if (token->name() == optgroupTag) {
1404             if (m_tree.currentNode()->hasTagName(optionTag)) {
1405                 RefPtr<AtomicHTMLToken> endOption = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, optionTag.localName());
1406                 processEndTag(endOption.get());
1407             }
1408             if (m_tree.currentNode()->hasTagName(optgroupTag)) {
1409                 RefPtr<AtomicHTMLToken> endOptgroup = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, optgroupTag.localName());
1410                 processEndTag(endOptgroup.get());
1411             }
1412             m_tree.insertHTMLElement(token);
1413             return;
1414         }
1415         if (token->name() == selectTag) {
1416             parseError(token);
1417             RefPtr<AtomicHTMLToken> endSelect = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, selectTag.localName());
1418             processEndTag(endSelect.get());
1419             return;
1420         }
1421         if (token->name() == inputTag
1422             || token->name() == keygenTag
1423             || token->name() == textareaTag) {
1424             parseError(token);
1425             if (!m_tree.openElements()->inSelectScope(selectTag)) {
1426                 ASSERT(isParsingFragment());
1427                 return;
1428             }
1429             RefPtr<AtomicHTMLToken> endSelect = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, selectTag.localName());
1430             processEndTag(endSelect.get());
1431             processStartTag(token);
1432             return;
1433         }
1434         if (token->name() == scriptTag) {
1435             bool didProcess = processStartTagForInHead(token);
1436             ASSERT_UNUSED(didProcess, didProcess);
1437             return;
1438         }
1439         break;
1440     case InTableTextMode:
1441         defaultForInTableText();
1442         processStartTag(token);
1443         break;
1444     case TextMode:
1445         ASSERT_NOT_REACHED();
1446         break;
1447     }
1448 }
1449
1450 void HTMLTreeBuilder::processHtmlStartTagForInBody(AtomicHTMLToken* token)
1451 {
1452     parseError(token);
1453     m_tree.insertHTMLHtmlStartTagInBody(token);
1454 }
1455
1456 bool HTMLTreeBuilder::processBodyEndTagForInBody(AtomicHTMLToken* token)
1457 {
1458     ASSERT(token->type() == HTMLTokenTypes::EndTag);
1459     ASSERT(token->name() == bodyTag);
1460     if (!m_tree.openElements()->inScope(bodyTag.localName())) {
1461         parseError(token);
1462         return false;
1463     }
1464     notImplemented(); // Emit a more specific parse error based on stack contents.
1465     setInsertionMode(AfterBodyMode);
1466     return true;
1467 }
1468
1469 void HTMLTreeBuilder::processAnyOtherEndTagForInBody(AtomicHTMLToken* token)
1470 {
1471     ASSERT(token->type() == HTMLTokenTypes::EndTag);
1472     HTMLElementStack::ElementRecord* record = m_tree.openElements()->topRecord();
1473     while (1) {
1474         RefPtr<ContainerNode> node = record->node();
1475         if (node->hasLocalName(token->name())) {
1476             m_tree.generateImpliedEndTagsWithExclusion(token->name());
1477             if (!m_tree.currentNode()->hasLocalName(token->name()))
1478                 parseError(token);
1479             m_tree.openElements()->popUntilPopped(toElement(node.get()));
1480             return;
1481         }
1482         if (isSpecialNode(node.get())) {
1483             parseError(token);
1484             return;
1485         }
1486         record = record->next();
1487     }
1488 }
1489
1490 // FIXME: This probably belongs on HTMLElementStack.
1491 HTMLElementStack::ElementRecord* HTMLTreeBuilder::furthestBlockForFormattingElement(Element* formattingElement)
1492 {
1493     HTMLElementStack::ElementRecord* furthestBlock = 0;
1494     HTMLElementStack::ElementRecord* record = m_tree.openElements()->topRecord();
1495     for (; record; record = record->next()) {
1496         if (record->element() == formattingElement)
1497             return furthestBlock;
1498         if (isSpecialNode(record->element()))
1499             furthestBlock = record;
1500     }
1501     ASSERT_NOT_REACHED();
1502     return 0;
1503 }
1504
1505 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#parsing-main-inbody
1506 void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken* token)
1507 {
1508     // The adoption agency algorithm is N^2. We limit the number of iterations
1509     // to stop from hanging the whole browser. This limit is specified in the
1510     // adoption agency algorithm: 
1511     // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#parsing-main-inbody
1512     static const int outerIterationLimit = 8;
1513     static const int innerIterationLimit = 3;
1514
1515     for (int i = 0; i < outerIterationLimit; ++i) {
1516         // 1.
1517         Element* formattingElement = m_tree.activeFormattingElements()->closestElementInScopeWithName(token->name());
1518         if (!formattingElement || ((m_tree.openElements()->contains(formattingElement)) && !m_tree.openElements()->inScope(formattingElement))) {
1519             parseError(token);
1520             notImplemented(); // Check the stack of open elements for a more specific parse error.
1521             return;
1522         }
1523         HTMLElementStack::ElementRecord* formattingElementRecord = m_tree.openElements()->find(formattingElement);
1524         if (!formattingElementRecord) {
1525             parseError(token);
1526             m_tree.activeFormattingElements()->remove(formattingElement);
1527             return;
1528         }
1529         if (formattingElement != m_tree.currentElement())
1530             parseError(token);
1531         // 2.
1532         HTMLElementStack::ElementRecord* furthestBlock = furthestBlockForFormattingElement(formattingElement);
1533         // 3.
1534         if (!furthestBlock) {
1535             m_tree.openElements()->popUntilPopped(formattingElement);
1536             m_tree.activeFormattingElements()->remove(formattingElement);
1537             return;
1538         }
1539         // 4.
1540         ASSERT(furthestBlock->isAbove(formattingElementRecord));
1541         RefPtr<ContainerNode> commonAncestor = formattingElementRecord->next()->node();
1542         // 5.
1543         HTMLFormattingElementList::Bookmark bookmark = m_tree.activeFormattingElements()->bookmarkFor(formattingElement);
1544         // 6.
1545         HTMLElementStack::ElementRecord* node = furthestBlock;
1546         HTMLElementStack::ElementRecord* nextNode = node->next();
1547         HTMLElementStack::ElementRecord* lastNode = furthestBlock;
1548         for (int i = 0; i < innerIterationLimit; ++i) {
1549             // 6.1
1550             node = nextNode;
1551             ASSERT(node);
1552             nextNode = node->next(); // Save node->next() for the next iteration in case node is deleted in 6.2.
1553             // 6.2
1554             if (!m_tree.activeFormattingElements()->contains(node->element())) {
1555                 m_tree.openElements()->remove(node->element());
1556                 node = 0;
1557                 continue;
1558             }
1559             // 6.3
1560             if (node == formattingElementRecord)
1561                 break;
1562             // 6.5
1563             RefPtr<HTMLStackItem> newItem = m_tree.createElementFromSavedToken(node->stackItem().get());
1564
1565             HTMLFormattingElementList::Entry* nodeEntry = m_tree.activeFormattingElements()->find(node->element());
1566             nodeEntry->replaceElement(newItem);
1567             node->replaceElement(newItem.release());
1568             // 6.4 -- Intentionally out of order to handle the case where node
1569             // was replaced in 6.5.
1570             // http://www.w3.org/Bugs/Public/show_bug.cgi?id=10096
1571             if (lastNode == furthestBlock)
1572                 bookmark.moveToAfter(nodeEntry);
1573             // 6.6
1574             if (ContainerNode* parent = lastNode->element()->parentNode())
1575                 parent->parserRemoveChild(lastNode->element());
1576             node->element()->parserAddChild(lastNode->element());
1577             if (lastNode->element()->parentElement()->attached() && !lastNode->element()->attached())
1578                 lastNode->element()->lazyAttach();
1579             // 6.7
1580             lastNode = node;
1581         }
1582         // 7
1583         const AtomicString& commonAncestorTag = commonAncestor->localName();
1584         if (ContainerNode* parent = lastNode->element()->parentNode())
1585             parent->parserRemoveChild(lastNode->element());
1586         // FIXME: If this moves to HTMLConstructionSite, this check should use
1587         // causesFosterParenting(tagName) instead.
1588         if (commonAncestorTag == tableTag
1589             || commonAncestorTag == trTag
1590             || isTableBodyContextTag(commonAncestorTag))
1591             m_tree.fosterParent(lastNode->element());
1592         else {
1593             commonAncestor->parserAddChild(lastNode->element());
1594             ASSERT(lastNode->node()->isElementNode());
1595             ASSERT(lastNode->element()->parentNode());
1596             if (lastNode->element()->parentNode()->attached() && !lastNode->element()->attached())
1597                 lastNode->element()->lazyAttach();
1598         }
1599         // 8
1600         RefPtr<HTMLStackItem> newItem = m_tree.createElementFromSavedToken(formattingElementRecord->stackItem().get());
1601         // 9
1602         newItem->element()->takeAllChildrenFrom(furthestBlock->element());
1603         // 10
1604         Element* furthestBlockElement = furthestBlock->element();
1605         // FIXME: All this creation / parserAddChild / attach business should
1606         //        be in HTMLConstructionSite.  My guess is that steps 8--12
1607         //        should all be in some HTMLConstructionSite function.
1608         furthestBlockElement->parserAddChild(newItem->element());
1609         if (furthestBlockElement->attached() && !newItem->element()->attached()) {
1610             // Notice that newItem->element() might already be attached if, for example, one of the reparented
1611             // children is a style element, which attaches itself automatically.
1612             newItem->element()->attach();
1613         }
1614         // 11
1615         m_tree.activeFormattingElements()->swapTo(formattingElement, newItem, bookmark);
1616         // 12
1617         m_tree.openElements()->remove(formattingElement);
1618         m_tree.openElements()->insertAbove(newItem, furthestBlock);
1619     }
1620 }
1621
1622 void HTMLTreeBuilder::resetInsertionModeAppropriately()
1623 {
1624     // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#reset-the-insertion-mode-appropriately
1625     bool last = false;
1626     HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord();
1627     while (1) {
1628         ContainerNode* node = nodeRecord->node();
1629         if (node == m_tree.openElements()->rootNode()) {
1630             ASSERT(isParsingFragment());
1631             last = true;
1632             node = m_fragmentContext.contextElement();
1633         }
1634         if (node->hasTagName(selectTag)) {
1635             ASSERT(isParsingFragment());
1636             return setInsertionMode(InSelectMode);
1637         }
1638         if (node->hasTagName(tdTag) || node->hasTagName(thTag))
1639             return setInsertionMode(InCellMode);
1640         if (node->hasTagName(trTag))
1641             return setInsertionMode(InRowMode);
1642         if (node->hasTagName(tbodyTag) || node->hasTagName(theadTag) || node->hasTagName(tfootTag))
1643             return setInsertionMode(InTableBodyMode);
1644         if (node->hasTagName(captionTag))
1645             return setInsertionMode(InCaptionMode);
1646         if (node->hasTagName(colgroupTag)) {
1647             ASSERT(isParsingFragment());
1648             return setInsertionMode(InColumnGroupMode);
1649         }
1650         if (node->hasTagName(tableTag))
1651             return setInsertionMode(InTableMode);
1652         if (node->hasTagName(headTag)) {
1653             ASSERT(isParsingFragment());
1654             return setInsertionMode(InBodyMode);
1655         }
1656         if (node->hasTagName(bodyTag))
1657             return setInsertionMode(InBodyMode);
1658         if (node->hasTagName(framesetTag)) {
1659             ASSERT(isParsingFragment());
1660             return setInsertionMode(InFramesetMode);
1661         }
1662         if (node->hasTagName(htmlTag)) {
1663             ASSERT(isParsingFragment());
1664             return setInsertionMode(BeforeHeadMode);
1665         }
1666         if (last) {
1667             ASSERT(isParsingFragment());
1668             return setInsertionMode(InBodyMode);
1669         }
1670         nodeRecord = nodeRecord->next();
1671     }
1672 }
1673
1674 void HTMLTreeBuilder::processEndTagForInTableBody(AtomicHTMLToken* token)
1675 {
1676     ASSERT(token->type() == HTMLTokenTypes::EndTag);
1677     if (isTableBodyContextTag(token->name())) {
1678         if (!m_tree.openElements()->inTableScope(token->name())) {
1679             parseError(token);
1680             return;
1681         }
1682         m_tree.openElements()->popUntilTableBodyScopeMarker();
1683         m_tree.openElements()->pop();
1684         setInsertionMode(InTableMode);
1685         return;
1686     }
1687     if (token->name() == tableTag) {
1688         // FIXME: This is slow.
1689         if (!m_tree.openElements()->inTableScope(tbodyTag.localName()) && !m_tree.openElements()->inTableScope(theadTag.localName()) && !m_tree.openElements()->inTableScope(tfootTag.localName())) {
1690             ASSERT(isParsingFragment());
1691             parseError(token);
1692             return;
1693         }
1694         m_tree.openElements()->popUntilTableBodyScopeMarker();
1695         ASSERT(isTableBodyContextTag(m_tree.currentElement()->localName()));
1696         processFakeEndTag(m_tree.currentElement()->tagQName());
1697         processEndTag(token);
1698         return;
1699     }
1700     if (token->name() == bodyTag
1701         || isCaptionColOrColgroupTag(token->name())
1702         || token->name() == htmlTag
1703         || isTableCellContextTag(token->name())
1704         || token->name() == trTag) {
1705         parseError(token);
1706         return;
1707     }
1708     processEndTagForInTable(token);
1709 }
1710
1711 void HTMLTreeBuilder::processEndTagForInRow(AtomicHTMLToken* token)
1712 {
1713     ASSERT(token->type() == HTMLTokenTypes::EndTag);
1714     if (token->name() == trTag) {
1715         processTrEndTagForInRow();
1716         return;
1717     }
1718     if (token->name() == tableTag) {
1719         if (!processTrEndTagForInRow()) {
1720             ASSERT(isParsingFragment());
1721             return;
1722         }
1723         ASSERT(insertionMode() == InTableBodyMode);
1724         processEndTag(token);
1725         return;
1726     }
1727     if (isTableBodyContextTag(token->name())) {
1728         if (!m_tree.openElements()->inTableScope(token->name())) {
1729             parseError(token);
1730             return;
1731         }
1732         processFakeEndTag(trTag);
1733         ASSERT(insertionMode() == InTableBodyMode);
1734         processEndTag(token);
1735         return;
1736     }
1737     if (token->name() == bodyTag
1738         || isCaptionColOrColgroupTag(token->name())
1739         || token->name() == htmlTag
1740         || isTableCellContextTag(token->name())) {
1741         parseError(token);
1742         return;
1743     }
1744     processEndTagForInTable(token);
1745 }
1746
1747 void HTMLTreeBuilder::processEndTagForInCell(AtomicHTMLToken* token)
1748 {
1749     ASSERT(token->type() == HTMLTokenTypes::EndTag);
1750     if (isTableCellContextTag(token->name())) {
1751         if (!m_tree.openElements()->inTableScope(token->name())) {
1752             parseError(token);
1753             return;
1754         }
1755         m_tree.generateImpliedEndTags();
1756         if (!m_tree.currentNode()->hasLocalName(token->name()))
1757             parseError(token);
1758         m_tree.openElements()->popUntilPopped(token->name());
1759         m_tree.activeFormattingElements()->clearToLastMarker();
1760         setInsertionMode(InRowMode);
1761         return;
1762     }
1763     if (token->name() == bodyTag
1764         || isCaptionColOrColgroupTag(token->name())
1765         || token->name() == htmlTag) {
1766         parseError(token);
1767         return;
1768     }
1769     if (token->name() == tableTag
1770         || token->name() == trTag
1771         || isTableBodyContextTag(token->name())) {
1772         if (!m_tree.openElements()->inTableScope(token->name())) {
1773             ASSERT(isTableBodyContextTag(token->name()) || isParsingFragment());
1774             parseError(token);
1775             return;
1776         }
1777         closeTheCell();
1778         processEndTag(token);
1779         return;
1780     }
1781     processEndTagForInBody(token);
1782 }
1783
1784 void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
1785 {
1786     ASSERT(token->type() == HTMLTokenTypes::EndTag);
1787     if (token->name() == bodyTag) {
1788         processBodyEndTagForInBody(token);
1789         return;
1790     }
1791     if (token->name() == htmlTag) {
1792         RefPtr<AtomicHTMLToken> endBody = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, bodyTag.localName());
1793         if (processBodyEndTagForInBody(endBody.get()))
1794             processEndTag(token);
1795         return;
1796     }
1797     if (token->name() == addressTag
1798         || token->name() == articleTag
1799         || token->name() == asideTag
1800         || token->name() == blockquoteTag
1801         || token->name() == buttonTag
1802         || token->name() == centerTag
1803         || token->name() == detailsTag
1804         || token->name() == dirTag
1805         || token->name() == divTag
1806         || token->name() == dlTag
1807         || token->name() == fieldsetTag
1808         || token->name() == figcaptionTag
1809         || token->name() == figureTag
1810         || token->name() == footerTag
1811         || token->name() == headerTag
1812         || token->name() == hgroupTag
1813         || token->name() == listingTag
1814         || token->name() == menuTag
1815         || token->name() == navTag
1816         || token->name() == olTag
1817         || token->name() == preTag
1818         || token->name() == sectionTag
1819         || token->name() == summaryTag
1820         || token->name() == ulTag) {
1821         if (!m_tree.openElements()->inScope(token->name())) {
1822             parseError(token);
1823             return;
1824         }
1825         m_tree.generateImpliedEndTags();
1826         if (!m_tree.currentNode()->hasLocalName(token->name()))
1827             parseError(token);
1828         m_tree.openElements()->popUntilPopped(token->name());
1829         return;
1830     }
1831     if (token->name() == formTag) {
1832         RefPtr<Element> node = m_tree.takeForm();
1833         if (!node || !m_tree.openElements()->inScope(node.get())) {
1834             parseError(token);
1835             return;
1836         }
1837         m_tree.generateImpliedEndTags();
1838         if (m_tree.currentElement() != node.get())
1839             parseError(token);
1840         m_tree.openElements()->remove(node.get());
1841     }
1842     if (token->name() == pTag) {
1843         if (!m_tree.openElements()->inButtonScope(token->name())) {
1844             parseError(token);
1845             processFakeStartTag(pTag);
1846             ASSERT(m_tree.openElements()->inScope(token->name()));
1847             processEndTag(token);
1848             return;
1849         }
1850         m_tree.generateImpliedEndTagsWithExclusion(token->name());
1851         if (!m_tree.currentNode()->hasLocalName(token->name()))
1852             parseError(token);
1853         m_tree.openElements()->popUntilPopped(token->name());
1854         return;
1855     }
1856     if (token->name() == liTag) {
1857         if (!m_tree.openElements()->inListItemScope(token->name())) {
1858             parseError(token);
1859             return;
1860         }
1861         m_tree.generateImpliedEndTagsWithExclusion(token->name());
1862         if (!m_tree.currentNode()->hasLocalName(token->name()))
1863             parseError(token);
1864         m_tree.openElements()->popUntilPopped(token->name());
1865         return;
1866     }
1867     if (token->name() == ddTag
1868         || token->name() == dtTag) {
1869         if (!m_tree.openElements()->inScope(token->name())) {
1870             parseError(token);
1871             return;
1872         }
1873         m_tree.generateImpliedEndTagsWithExclusion(token->name());
1874         if (!m_tree.currentNode()->hasLocalName(token->name()))
1875             parseError(token);
1876         m_tree.openElements()->popUntilPopped(token->name());
1877         return;
1878     }
1879     if (isNumberedHeaderTag(token->name())) {
1880         if (!m_tree.openElements()->hasNumberedHeaderElementInScope()) {
1881             parseError(token);
1882             return;
1883         }
1884         m_tree.generateImpliedEndTags();
1885         if (!m_tree.currentNode()->hasLocalName(token->name()))
1886             parseError(token);
1887         m_tree.openElements()->popUntilNumberedHeaderElementPopped();
1888         return;
1889     }
1890     if (isFormattingTag(token->name())) {
1891         callTheAdoptionAgency(token);
1892         return;
1893     }
1894     if (token->name() == appletTag
1895         || token->name() == marqueeTag
1896         || token->name() == objectTag) {
1897         if (!m_tree.openElements()->inScope(token->name())) {
1898             parseError(token);
1899             return;
1900         }
1901         m_tree.generateImpliedEndTags();
1902         if (!m_tree.currentNode()->hasLocalName(token->name()))
1903             parseError(token);
1904         m_tree.openElements()->popUntilPopped(token->name());
1905         m_tree.activeFormattingElements()->clearToLastMarker();
1906         return;
1907     }
1908     if (token->name() == brTag) {
1909         parseError(token);
1910         processFakeStartTag(brTag);
1911         return;
1912     }
1913     processAnyOtherEndTagForInBody(token);
1914 }
1915
1916 bool HTMLTreeBuilder::processCaptionEndTagForInCaption()
1917 {
1918     if (!m_tree.openElements()->inTableScope(captionTag.localName())) {
1919         ASSERT(isParsingFragment());
1920         // FIXME: parse error
1921         return false;
1922     }
1923     m_tree.generateImpliedEndTags();
1924     // FIXME: parse error if (!m_tree.currentElement()->hasTagName(captionTag))
1925     m_tree.openElements()->popUntilPopped(captionTag.localName());
1926     m_tree.activeFormattingElements()->clearToLastMarker();
1927     setInsertionMode(InTableMode);
1928     return true;
1929 }
1930
1931 bool HTMLTreeBuilder::processTrEndTagForInRow()
1932 {
1933     if (!m_tree.openElements()->inTableScope(trTag.localName())) {
1934         ASSERT(isParsingFragment());
1935         // FIXME: parse error
1936         return false;
1937     }
1938     m_tree.openElements()->popUntilTableRowScopeMarker();
1939     ASSERT(m_tree.currentElement()->hasTagName(trTag));
1940     m_tree.openElements()->pop();
1941     setInsertionMode(InTableBodyMode);
1942     return true;
1943 }
1944
1945 bool HTMLTreeBuilder::processTableEndTagForInTable()
1946 {
1947     if (!m_tree.openElements()->inTableScope(tableTag)) {
1948         ASSERT(isParsingFragment());
1949         // FIXME: parse error.
1950         return false;
1951     }
1952     m_tree.openElements()->popUntilPopped(tableTag.localName());
1953     resetInsertionModeAppropriately();
1954     return true;
1955 }
1956
1957 void HTMLTreeBuilder::processEndTagForInTable(AtomicHTMLToken* token)
1958 {
1959     ASSERT(token->type() == HTMLTokenTypes::EndTag);
1960     if (token->name() == tableTag) {
1961         processTableEndTagForInTable();
1962         return;
1963     }
1964     if (token->name() == bodyTag
1965         || isCaptionColOrColgroupTag(token->name())
1966         || token->name() == htmlTag
1967         || isTableBodyContextTag(token->name())
1968         || isTableCellContextTag(token->name())
1969         || token->name() == trTag) {
1970         parseError(token);
1971         return;
1972     }
1973     parseError(token);
1974     // Is this redirection necessary here?
1975     HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
1976     processEndTagForInBody(token);
1977 }
1978
1979 void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
1980 {
1981     ASSERT(token->type() == HTMLTokenTypes::EndTag);
1982     switch (insertionMode()) {
1983     case InitialMode:
1984         ASSERT(insertionMode() == InitialMode);
1985         defaultForInitial();
1986         // Fall through.
1987     case BeforeHTMLMode:
1988         ASSERT(insertionMode() == BeforeHTMLMode);
1989         if (token->name() != headTag && token->name() != bodyTag && token->name() != htmlTag && token->name() != brTag) {
1990             parseError(token);
1991             return;
1992         }
1993         defaultForBeforeHTML();
1994         // Fall through.
1995     case BeforeHeadMode:
1996         ASSERT(insertionMode() == BeforeHeadMode);
1997         if (token->name() != headTag && token->name() != bodyTag && token->name() != htmlTag && token->name() != brTag) {
1998             parseError(token);
1999             return;
2000         }
2001         defaultForBeforeHead();
2002         // Fall through.
2003     case InHeadMode:
2004         ASSERT(insertionMode() == InHeadMode);
2005         if (token->name() == headTag) {
2006             m_tree.openElements()->popHTMLHeadElement();
2007             setInsertionMode(AfterHeadMode);
2008             return;
2009         }
2010         if (token->name() != bodyTag && token->name() != htmlTag && token->name() != brTag) {
2011             parseError(token);
2012             return;
2013         }
2014         defaultForInHead();
2015         // Fall through.
2016     case AfterHeadMode:
2017         ASSERT(insertionMode() == AfterHeadMode);
2018         if (token->name() != bodyTag && token->name() != htmlTag && token->name() != brTag) {
2019             parseError(token);
2020             return;
2021         }
2022         defaultForAfterHead();
2023         // Fall through
2024     case InBodyMode:
2025         ASSERT(insertionMode() == InBodyMode);
2026         processEndTagForInBody(token);
2027         break;
2028     case InTableMode:
2029         ASSERT(insertionMode() == InTableMode);
2030         processEndTagForInTable(token);
2031         break;
2032     case InCaptionMode:
2033         ASSERT(insertionMode() == InCaptionMode);
2034         if (token->name() == captionTag) {
2035             processCaptionEndTagForInCaption();
2036             return;
2037         }
2038         if (token->name() == tableTag) {
2039             parseError(token);
2040             if (!processCaptionEndTagForInCaption()) {
2041                 ASSERT(isParsingFragment());
2042                 return;
2043             }
2044             processEndTag(token);
2045             return;
2046         }
2047         if (token->name() == bodyTag
2048             || token->name() == colTag
2049             || token->name() == colgroupTag
2050             || token->name() == htmlTag
2051             || isTableBodyContextTag(token->name())
2052             || isTableCellContextTag(token->name())
2053             || token->name() == trTag) {
2054             parseError(token);
2055             return;
2056         }
2057         processEndTagForInBody(token);
2058         break;
2059     case InColumnGroupMode:
2060         ASSERT(insertionMode() == InColumnGroupMode);
2061         if (token->name() == colgroupTag) {
2062             processColgroupEndTagForInColumnGroup();
2063             return;
2064         }
2065         if (token->name() == colTag) {
2066             parseError(token);
2067             return;
2068         }
2069         if (!processColgroupEndTagForInColumnGroup()) {
2070             ASSERT(isParsingFragment());
2071             return;
2072         }
2073         processEndTag(token);
2074         break;
2075     case InRowMode:
2076         ASSERT(insertionMode() == InRowMode);
2077         processEndTagForInRow(token);
2078         break;
2079     case InCellMode:
2080         ASSERT(insertionMode() == InCellMode);
2081         processEndTagForInCell(token);
2082         break;
2083     case InTableBodyMode:
2084         ASSERT(insertionMode() == InTableBodyMode);
2085         processEndTagForInTableBody(token);
2086         break;
2087     case AfterBodyMode:
2088         ASSERT(insertionMode() == AfterBodyMode);
2089         if (token->name() == htmlTag) {
2090             if (isParsingFragment()) {
2091                 parseError(token);
2092                 return;
2093             }
2094             setInsertionMode(AfterAfterBodyMode);
2095             return;
2096         }
2097         // Fall through.
2098     case AfterAfterBodyMode:
2099         ASSERT(insertionMode() == AfterBodyMode || insertionMode() == AfterAfterBodyMode);
2100         parseError(token);
2101         setInsertionMode(InBodyMode);
2102         processEndTag(token);
2103         break;
2104     case InHeadNoscriptMode:
2105         ASSERT(insertionMode() == InHeadNoscriptMode);
2106         if (token->name() == noscriptTag) {
2107             ASSERT(m_tree.currentElement()->hasTagName(noscriptTag));
2108             m_tree.openElements()->pop();
2109             ASSERT(m_tree.currentElement()->hasTagName(headTag));
2110             setInsertionMode(InHeadMode);
2111             return;
2112         }
2113         if (token->name() != brTag) {
2114             parseError(token);
2115             return;
2116         }
2117         defaultForInHeadNoscript();
2118         processToken(token);
2119         break;
2120     case TextMode:
2121         if (token->name() == scriptTag) {
2122             // Pause ourselves so that parsing stops until the script can be processed by the caller.
2123             ASSERT(m_tree.currentElement()->hasTagName(scriptTag));
2124             m_scriptToProcess = m_tree.currentElement();
2125             m_tree.openElements()->pop();
2126             if (isParsingFragment() && m_fragmentContext.scriptingPermission() == DisallowScriptingContent)
2127                 m_scriptToProcess->removeAllChildren();
2128             setInsertionMode(m_originalInsertionMode);
2129
2130             // This token will not have been created by the tokenizer if a
2131             // self-closing script tag was encountered and pre-HTML5 parser
2132             // quirks are enabled. We must set the tokenizer's state to
2133             // DataState explicitly if the tokenizer didn't have a chance to.
2134             ASSERT(m_parser->tokenizer()->state() == HTMLTokenizerState::DataState || m_usePreHTML5ParserQuirks);
2135             m_parser->tokenizer()->setState(HTMLTokenizerState::DataState);
2136             return;
2137         }
2138         m_tree.openElements()->pop();
2139         setInsertionMode(m_originalInsertionMode);
2140         break;
2141     case InFramesetMode:
2142         ASSERT(insertionMode() == InFramesetMode);
2143         if (token->name() == framesetTag) {
2144             if (m_tree.currentNode() == m_tree.openElements()->rootNode()) {
2145                 parseError(token);
2146                 return;
2147             }
2148             m_tree.openElements()->pop();
2149             if (!isParsingFragment() && !m_tree.currentElement()->hasTagName(framesetTag))
2150                 setInsertionMode(AfterFramesetMode);
2151             return;
2152         }
2153         break;
2154     case AfterFramesetMode:
2155         ASSERT(insertionMode() == AfterFramesetMode);
2156         if (token->name() == htmlTag) {
2157             setInsertionMode(AfterAfterFramesetMode);
2158             return;
2159         }
2160         // Fall through.
2161     case AfterAfterFramesetMode:
2162         ASSERT(insertionMode() == AfterFramesetMode || insertionMode() == AfterAfterFramesetMode);
2163         parseError(token);
2164         break;
2165     case InSelectInTableMode:
2166         ASSERT(insertionMode() == InSelectInTableMode);
2167         if (token->name() == captionTag
2168             || token->name() == tableTag
2169             || isTableBodyContextTag(token->name())
2170             || token->name() == trTag
2171             || isTableCellContextTag(token->name())) {
2172             parseError(token);
2173             if (m_tree.openElements()->inTableScope(token->name())) {
2174                 RefPtr<AtomicHTMLToken> endSelect = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, selectTag.localName());
2175                 processEndTag(endSelect.get());
2176                 processEndTag(token);
2177             }
2178             return;
2179         }
2180         // Fall through.
2181     case InSelectMode:
2182         ASSERT(insertionMode() == InSelectMode || insertionMode() == InSelectInTableMode);
2183         if (token->name() == optgroupTag) {
2184             if (m_tree.currentNode()->hasTagName(optionTag) && m_tree.oneBelowTop() && m_tree.oneBelowTop()->hasTagName(optgroupTag))
2185                 processFakeEndTag(optionTag);
2186             if (m_tree.currentNode()->hasTagName(optgroupTag)) {
2187                 m_tree.openElements()->pop();
2188                 return;
2189             }
2190             parseError(token);
2191             return;
2192         }
2193         if (token->name() == optionTag) {
2194             if (m_tree.currentNode()->hasTagName(optionTag)) {
2195                 m_tree.openElements()->pop();
2196                 return;
2197             }
2198             parseError(token);
2199             return;
2200         }
2201         if (token->name() == selectTag) {
2202             if (!m_tree.openElements()->inSelectScope(token->name())) {
2203                 ASSERT(isParsingFragment());
2204                 parseError(token);
2205                 return;
2206             }
2207             m_tree.openElements()->popUntilPopped(selectTag.localName());
2208             resetInsertionModeAppropriately();
2209             return;
2210         }
2211         break;
2212     case InTableTextMode:
2213         defaultForInTableText();
2214         processEndTag(token);
2215         break;
2216     }
2217 }
2218
2219 void HTMLTreeBuilder::processComment(AtomicHTMLToken* token)
2220 {
2221     ASSERT(token->type() == HTMLTokenTypes::Comment);
2222     if (m_insertionMode == InitialMode
2223         || m_insertionMode == BeforeHTMLMode
2224         || m_insertionMode == AfterAfterBodyMode
2225         || m_insertionMode == AfterAfterFramesetMode) {
2226         m_tree.insertCommentOnDocument(token);
2227         return;
2228     }
2229     if (m_insertionMode == AfterBodyMode) {
2230         m_tree.insertCommentOnHTMLHtmlElement(token);
2231         return;
2232     }
2233     if (m_insertionMode == InTableTextMode) {
2234         defaultForInTableText();
2235         processComment(token);
2236         return;
2237     }
2238     m_tree.insertComment(token);
2239 }
2240
2241 void HTMLTreeBuilder::processCharacter(AtomicHTMLToken* token)
2242 {
2243     ASSERT(token->type() == HTMLTokenTypes::Character);
2244     ExternalCharacterTokenBuffer buffer(token);
2245     processCharacterBuffer(buffer);
2246 }
2247
2248 void HTMLTreeBuilder::processCharacterBuffer(ExternalCharacterTokenBuffer& buffer)
2249 {
2250 ReprocessBuffer:
2251     // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#parsing-main-inbody
2252     // Note that this logic is different than the generic \r\n collapsing
2253     // handled in the input stream preprocessor. This logic is here as an
2254     // "authoring convenience" so folks can write:
2255     //
2256     // <pre>
2257     // lorem ipsum
2258     // lorem ipsum
2259     // </pre>
2260     //
2261     // without getting an extra newline at the start of their <pre> element.
2262     if (m_shouldSkipLeadingNewline) {
2263         m_shouldSkipLeadingNewline = false;
2264         buffer.skipAtMostOneLeadingNewline();
2265         if (buffer.isEmpty())
2266             return;
2267     }
2268
2269     switch (insertionMode()) {
2270     case InitialMode: {
2271         ASSERT(insertionMode() == InitialMode);
2272         buffer.skipLeadingWhitespace();
2273         if (buffer.isEmpty())
2274             return;
2275         defaultForInitial();
2276         // Fall through.
2277     }
2278     case BeforeHTMLMode: {
2279         ASSERT(insertionMode() == BeforeHTMLMode);
2280         buffer.skipLeadingWhitespace();
2281         if (buffer.isEmpty())
2282             return;
2283         defaultForBeforeHTML();
2284         // Fall through.
2285     }
2286     case BeforeHeadMode: {
2287         ASSERT(insertionMode() == BeforeHeadMode);
2288         buffer.skipLeadingWhitespace();
2289         if (buffer.isEmpty())
2290             return;
2291         defaultForBeforeHead();
2292         // Fall through.
2293     }
2294     case InHeadMode: {
2295         ASSERT(insertionMode() == InHeadMode);
2296         String leadingWhitespace = buffer.takeLeadingWhitespace();
2297         if (!leadingWhitespace.isEmpty())
2298             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
2299         if (buffer.isEmpty())
2300             return;
2301         defaultForInHead();
2302         // Fall through.
2303     }
2304     case AfterHeadMode: {
2305         ASSERT(insertionMode() == AfterHeadMode);
2306         String leadingWhitespace = buffer.takeLeadingWhitespace();
2307         if (!leadingWhitespace.isEmpty())
2308             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
2309         if (buffer.isEmpty())
2310             return;
2311         defaultForAfterHead();
2312         // Fall through.
2313     }
2314     case InBodyMode:
2315     case InCaptionMode:
2316     case InCellMode: {
2317         ASSERT(insertionMode() == InBodyMode || insertionMode() == InCaptionMode || insertionMode() == InCellMode);
2318         processCharacterBufferForInBody(buffer);
2319         break;
2320     }
2321     case InTableMode:
2322     case InTableBodyMode:
2323     case InRowMode: {
2324         ASSERT(insertionMode() == InTableMode || insertionMode() == InTableBodyMode || insertionMode() == InRowMode);
2325         ASSERT(m_pendingTableCharacters.isEmpty());
2326         if (m_tree.currentNode()->isElementNode()
2327             && (m_tree.currentElement()->hasTagName(HTMLNames::tableTag)
2328                 || m_tree.currentElement()->hasTagName(HTMLNames::tbodyTag)
2329                 || m_tree.currentElement()->hasTagName(HTMLNames::tfootTag)
2330                 || m_tree.currentElement()->hasTagName(HTMLNames::theadTag)
2331                 || m_tree.currentElement()->hasTagName(HTMLNames::trTag))) {
2332             m_originalInsertionMode = m_insertionMode;
2333             setInsertionMode(InTableTextMode);
2334             // Note that we fall through to the InTableTextMode case below.
2335         } else {
2336             HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
2337             processCharacterBufferForInBody(buffer);
2338             break;
2339         }
2340         // Fall through.
2341     }
2342     case InTableTextMode: {
2343         buffer.giveRemainingTo(m_pendingTableCharacters);
2344         break;
2345     }
2346     case InColumnGroupMode: {
2347         ASSERT(insertionMode() == InColumnGroupMode);
2348         String leadingWhitespace = buffer.takeLeadingWhitespace();
2349         if (!leadingWhitespace.isEmpty())
2350             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
2351         if (buffer.isEmpty())
2352             return;
2353         if (!processColgroupEndTagForInColumnGroup()) {
2354             ASSERT(isParsingFragment());
2355             // The spec tells us to drop these characters on the floor.
2356             buffer.skipLeadingNonWhitespace();
2357             if (buffer.isEmpty())
2358                 return;
2359         }
2360         goto ReprocessBuffer;
2361     }
2362     case AfterBodyMode:
2363     case AfterAfterBodyMode: {
2364         ASSERT(insertionMode() == AfterBodyMode || insertionMode() == AfterAfterBodyMode);
2365         // FIXME: parse error
2366         setInsertionMode(InBodyMode);
2367         goto ReprocessBuffer;
2368         break;
2369     }
2370     case TextMode: {
2371         ASSERT(insertionMode() == TextMode);
2372         m_tree.insertTextNode(buffer.takeRemaining());
2373         break;
2374     }
2375     case InHeadNoscriptMode: {
2376         ASSERT(insertionMode() == InHeadNoscriptMode);
2377         String leadingWhitespace = buffer.takeLeadingWhitespace();
2378         if (!leadingWhitespace.isEmpty())
2379             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
2380         if (buffer.isEmpty())
2381             return;
2382         defaultForInHeadNoscript();
2383         goto ReprocessBuffer;
2384         break;
2385     }
2386     case InFramesetMode:
2387     case AfterFramesetMode: {
2388         ASSERT(insertionMode() == InFramesetMode || insertionMode() == AfterFramesetMode || insertionMode() == AfterAfterFramesetMode);
2389         String leadingWhitespace = buffer.takeRemainingWhitespace();
2390         if (!leadingWhitespace.isEmpty())
2391             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
2392         // FIXME: We should generate a parse error if we skipped over any
2393         // non-whitespace characters.
2394         break;
2395     }
2396     case InSelectInTableMode:
2397     case InSelectMode: {
2398         ASSERT(insertionMode() == InSelectMode || insertionMode() == InSelectInTableMode);
2399         m_tree.insertTextNode(buffer.takeRemaining());
2400         break;
2401     }
2402     case AfterAfterFramesetMode: {
2403         String leadingWhitespace = buffer.takeRemainingWhitespace();
2404         if (!leadingWhitespace.isEmpty()) {
2405             m_tree.reconstructTheActiveFormattingElements();
2406             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
2407         }
2408         // FIXME: We should generate a parse error if we skipped over any
2409         // non-whitespace characters.
2410         break;
2411     }
2412     }
2413 }
2414
2415 void HTMLTreeBuilder::processCharacterBufferForInBody(ExternalCharacterTokenBuffer& buffer)
2416 {
2417     m_tree.reconstructTheActiveFormattingElements();
2418     String characters = buffer.takeRemaining();
2419     m_tree.insertTextNode(characters);
2420     if (m_framesetOk && !isAllWhitespaceOrReplacementCharacters(characters))
2421         m_framesetOk = false;
2422 }
2423
2424 void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken* token)
2425 {
2426     ASSERT(token->type() == HTMLTokenTypes::EndOfFile);
2427     switch (insertionMode()) {
2428     case InitialMode:
2429         ASSERT(insertionMode() == InitialMode);
2430         defaultForInitial();
2431         // Fall through.
2432     case BeforeHTMLMode:
2433         ASSERT(insertionMode() == BeforeHTMLMode);
2434         defaultForBeforeHTML();
2435         // Fall through.
2436     case BeforeHeadMode:
2437         ASSERT(insertionMode() == BeforeHeadMode);
2438         defaultForBeforeHead();
2439         // Fall through.
2440     case InHeadMode:
2441         ASSERT(insertionMode() == InHeadMode);
2442         defaultForInHead();
2443         // Fall through.
2444     case AfterHeadMode:
2445         ASSERT(insertionMode() == AfterHeadMode);
2446         defaultForAfterHead();
2447         // Fall through
2448     case InBodyMode:
2449     case InCellMode:
2450     case InCaptionMode:
2451     case InRowMode:
2452         ASSERT(insertionMode() == InBodyMode || insertionMode() == InCellMode || insertionMode() == InCaptionMode || insertionMode() == InRowMode);
2453         notImplemented(); // Emit parse error based on what elements are still open.
2454         break;
2455     case AfterBodyMode:
2456     case AfterAfterBodyMode:
2457         ASSERT(insertionMode() == AfterBodyMode || insertionMode() == AfterAfterBodyMode);
2458         break;
2459     case InHeadNoscriptMode:
2460         ASSERT(insertionMode() == InHeadNoscriptMode);
2461         defaultForInHeadNoscript();
2462         processEndOfFile(token);
2463         return;
2464     case AfterFramesetMode:
2465     case AfterAfterFramesetMode:
2466         ASSERT(insertionMode() == AfterFramesetMode || insertionMode() == AfterAfterFramesetMode);
2467         break;
2468     case InFramesetMode:
2469     case InTableMode:
2470     case InTableBodyMode:
2471     case InSelectInTableMode:
2472     case InSelectMode:
2473         ASSERT(insertionMode() == InSelectMode || insertionMode() == InSelectInTableMode || insertionMode() == InTableMode || insertionMode() == InFramesetMode || insertionMode() == InTableBodyMode);
2474         if (m_tree.currentNode() != m_tree.openElements()->rootNode())
2475             parseError(token);
2476         break;
2477     case InColumnGroupMode:
2478         if (m_tree.currentNode() == m_tree.openElements()->rootNode()) {
2479             ASSERT(isParsingFragment());
2480             return; // FIXME: Should we break here instead of returning?
2481         }
2482         if (!processColgroupEndTagForInColumnGroup()) {
2483             ASSERT(isParsingFragment());
2484             return; // FIXME: Should we break here instead of returning?
2485         }
2486         processEndOfFile(token);
2487         return;
2488     case InTableTextMode:
2489         defaultForInTableText();
2490         processEndOfFile(token);
2491         return;
2492     case TextMode:
2493         parseError(token);
2494         if (m_tree.currentNode()->hasTagName(scriptTag))
2495             notImplemented(); // mark the script element as "already started".
2496         m_tree.openElements()->pop();
2497         ASSERT(m_originalInsertionMode != TextMode);
2498         setInsertionMode(m_originalInsertionMode);
2499         processEndOfFile(token);
2500         return;
2501     }
2502     ASSERT(m_tree.currentNode());
2503     m_tree.openElements()->popAll();
2504 }
2505
2506 void HTMLTreeBuilder::defaultForInitial()
2507 {
2508     notImplemented();
2509     if (!m_fragmentContext.fragment() && !m_document->isSrcdocDocument())
2510         m_document->setCompatibilityMode(Document::QuirksMode);
2511     // FIXME: parse error
2512     setInsertionMode(BeforeHTMLMode);
2513 }
2514
2515 void HTMLTreeBuilder::defaultForBeforeHTML()
2516 {
2517     RefPtr<AtomicHTMLToken> startHTML = AtomicHTMLToken::create(HTMLTokenTypes::StartTag, htmlTag.localName());
2518     m_tree.insertHTMLHtmlStartTagBeforeHTML(startHTML.get());
2519     setInsertionMode(BeforeHeadMode);
2520 }
2521
2522 void HTMLTreeBuilder::defaultForBeforeHead()
2523 {
2524     RefPtr<AtomicHTMLToken> startHead = AtomicHTMLToken::create(HTMLTokenTypes::StartTag, headTag.localName());
2525     processStartTag(startHead.get());
2526 }
2527
2528 void HTMLTreeBuilder::defaultForInHead()
2529 {
2530     RefPtr<AtomicHTMLToken> endHead = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, headTag.localName());
2531     processEndTag(endHead.get());
2532 }
2533
2534 void HTMLTreeBuilder::defaultForInHeadNoscript()
2535 {
2536     RefPtr<AtomicHTMLToken> endNoscript = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, noscriptTag.localName());
2537     processEndTag(endNoscript.get());
2538 }
2539
2540 void HTMLTreeBuilder::defaultForAfterHead()
2541 {
2542     RefPtr<AtomicHTMLToken> startBody = AtomicHTMLToken::create(HTMLTokenTypes::StartTag, bodyTag.localName());
2543     processStartTag(startBody.get());
2544     m_framesetOk = true;
2545 }
2546
2547 void HTMLTreeBuilder::defaultForInTableText()
2548 {
2549     String characters = m_pendingTableCharacters.toString();
2550     m_pendingTableCharacters.clear();
2551     if (!isAllWhitespace(characters)) {
2552         // FIXME: parse error
2553         HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
2554         m_tree.reconstructTheActiveFormattingElements();
2555         m_tree.insertTextNode(characters, NotAllWhitespace);
2556         m_framesetOk = false;
2557         setInsertionMode(m_originalInsertionMode);
2558         return;
2559     }
2560     m_tree.insertTextNode(characters);
2561     setInsertionMode(m_originalInsertionMode);
2562 }
2563
2564 bool HTMLTreeBuilder::processStartTagForInHead(AtomicHTMLToken* token)
2565 {
2566     ASSERT(token->type() == HTMLTokenTypes::StartTag);
2567     if (token->name() == htmlTag) {
2568         processHtmlStartTagForInBody(token);
2569         return true;
2570     }
2571     if (token->name() == baseTag
2572         || token->name() == basefontTag
2573         || token->name() == bgsoundTag
2574         || token->name() == commandTag
2575         || token->name() == linkTag
2576         || token->name() == metaTag) {
2577         m_tree.insertSelfClosingHTMLElement(token);
2578         // Note: The custom processing for the <meta> tag is done in HTMLMetaElement::process().
2579         return true;
2580     }
2581     if (token->name() == titleTag) {
2582         processGenericRCDATAStartTag(token);
2583         return true;
2584     }
2585     if (token->name() == noscriptTag) {
2586         if (scriptEnabled(m_document->frame())) {
2587             processGenericRawTextStartTag(token);
2588             return true;
2589         }
2590         m_tree.insertHTMLElement(token);
2591         setInsertionMode(InHeadNoscriptMode);
2592         return true;
2593     }
2594     if (token->name() == noframesTag || token->name() == styleTag) {
2595         processGenericRawTextStartTag(token);
2596         return true;
2597     }
2598     if (token->name() == scriptTag) {
2599         processScriptStartTag(token);
2600         if (m_usePreHTML5ParserQuirks && token->selfClosing())
2601             processFakeEndTag(scriptTag);
2602         return true;
2603     }
2604     if (token->name() == headTag) {
2605         parseError(token);
2606         return true;
2607     }
2608     return false;
2609 }
2610
2611 void HTMLTreeBuilder::processGenericRCDATAStartTag(AtomicHTMLToken* token)
2612 {
2613     ASSERT(token->type() == HTMLTokenTypes::StartTag);
2614     m_tree.insertHTMLElement(token);
2615     m_parser->tokenizer()->setState(HTMLTokenizerState::RCDATAState);
2616     m_originalInsertionMode = m_insertionMode;
2617     setInsertionMode(TextMode);
2618 }
2619
2620 void HTMLTreeBuilder::processGenericRawTextStartTag(AtomicHTMLToken* token)
2621 {
2622     ASSERT(token->type() == HTMLTokenTypes::StartTag);
2623     m_tree.insertHTMLElement(token);
2624     m_parser->tokenizer()->setState(HTMLTokenizerState::RAWTEXTState);
2625     m_originalInsertionMode = m_insertionMode;
2626     setInsertionMode(TextMode);
2627 }
2628
2629 void HTMLTreeBuilder::processScriptStartTag(AtomicHTMLToken* token)
2630 {
2631     ASSERT(token->type() == HTMLTokenTypes::StartTag);
2632     m_tree.insertScriptElement(token);
2633     m_parser->tokenizer()->setState(HTMLTokenizerState::ScriptDataState);
2634     m_originalInsertionMode = m_insertionMode;
2635
2636     TextPosition position = m_parser->textPosition();
2637
2638     m_scriptToProcessStartPosition = position;
2639
2640     setInsertionMode(TextMode);
2641 }
2642
2643 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#tree-construction
2644 bool HTMLTreeBuilder::shouldProcessTokenInForeignContent(AtomicHTMLToken* token)
2645 {
2646     if (m_tree.isEmpty())
2647         return false;
2648     ContainerNode* node = m_tree.currentNode();
2649     if (isInHTMLNamespace(node))
2650         return false;
2651     if (HTMLElementStack::isMathMLTextIntegrationPoint(node)) {
2652         if (token->type() == HTMLTokenTypes::StartTag
2653             && token->name() != MathMLNames::mglyphTag
2654             && token->name() != MathMLNames::malignmarkTag)
2655             return false;
2656         if (token->type() == HTMLTokenTypes::Character)
2657             return false;
2658     }
2659     if (node->hasTagName(MathMLNames::annotation_xmlTag)
2660         && token->type() == HTMLTokenTypes::StartTag
2661         && token->name() == SVGNames::svgTag)
2662         return false;
2663     if (HTMLElementStack::isHTMLIntegrationPoint(node)) {
2664         if (token->type() == HTMLTokenTypes::StartTag)
2665             return false;
2666         if (token->type() == HTMLTokenTypes::Character)
2667             return false;
2668     }
2669     if (token->type() == HTMLTokenTypes::EndOfFile)
2670         return false;
2671     return true;
2672 }
2673
2674 void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken* token)
2675 {
2676     switch (token->type()) {
2677     case HTMLTokenTypes::Uninitialized:
2678         ASSERT_NOT_REACHED();
2679         break;
2680     case HTMLTokenTypes::DOCTYPE:
2681         parseError(token);
2682         break;
2683     case HTMLTokenTypes::StartTag: {
2684         if (token->name() == bTag
2685             || token->name() == bigTag
2686             || token->name() == blockquoteTag
2687             || token->name() == bodyTag
2688             || token->name() == brTag
2689             || token->name() == centerTag
2690             || token->name() == codeTag
2691             || token->name() == ddTag
2692             || token->name() == divTag
2693             || token->name() == dlTag
2694             || token->name() == dtTag
2695             || token->name() == emTag
2696             || token->name() == embedTag
2697             || isNumberedHeaderTag(token->name())
2698             || token->name() == headTag
2699             || token->name() == hrTag
2700             || token->name() == iTag
2701             || token->name() == imgTag
2702             || token->name() == liTag
2703             || token->name() == listingTag
2704             || token->name() == menuTag
2705             || token->name() == metaTag
2706             || token->name() == nobrTag
2707             || token->name() == olTag
2708             || token->name() == pTag
2709             || token->name() == preTag
2710             || token->name() == rubyTag
2711             || token->name() == sTag
2712             || token->name() == smallTag
2713             || token->name() == spanTag
2714             || token->name() == strongTag
2715             || token->name() == strikeTag
2716             || token->name() == subTag
2717             || token->name() == supTag
2718             || token->name() == tableTag
2719             || token->name() == ttTag
2720             || token->name() == uTag
2721             || token->name() == ulTag
2722             || token->name() == varTag
2723             || (token->name() == fontTag && (token->getAttributeItem(colorAttr) || token->getAttributeItem(faceAttr) || token->getAttributeItem(sizeAttr)))) {
2724             parseError(token);
2725             m_tree.openElements()->popUntilForeignContentScopeMarker();
2726             processStartTag(token);
2727             return;
2728         }
2729         const AtomicString& currentNamespace = m_tree.currentElement()->namespaceURI();
2730         if (currentNamespace == MathMLNames::mathmlNamespaceURI)
2731             adjustMathMLAttributes(token);
2732         if (currentNamespace == SVGNames::svgNamespaceURI) {
2733             adjustSVGTagNameCase(token);
2734             adjustSVGAttributes(token);
2735         }
2736         adjustForeignAttributes(token);
2737         m_tree.insertForeignElement(token, currentNamespace);
2738         break;
2739     }
2740     case HTMLTokenTypes::EndTag: {
2741         if (m_tree.currentNode()->namespaceURI() == SVGNames::svgNamespaceURI)
2742             adjustSVGTagNameCase(token);
2743
2744         if (token->name() == SVGNames::scriptTag && m_tree.currentNode()->hasTagName(SVGNames::scriptTag)) {
2745             m_scriptToProcess = m_tree.currentElement();
2746             m_tree.openElements()->pop();
2747             return;
2748         }
2749         if (!isInHTMLNamespace(m_tree.currentNode())) {
2750             // FIXME: This code just wants an Element* iterator, instead of an ElementRecord*
2751             HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord();
2752             if (!nodeRecord->node()->hasLocalName(token->name()))
2753                 parseError(token);
2754             while (1) {
2755                 if (nodeRecord->node()->hasLocalName(token->name())) {
2756                     m_tree.openElements()->popUntilPopped(nodeRecord->element());
2757                     return;
2758                 }
2759                 nodeRecord = nodeRecord->next();
2760
2761                 if (isInHTMLNamespace(nodeRecord->node()))
2762                     break;
2763             }
2764         }
2765         // Otherwise, process the token according to the rules given in the section corresponding to the current insertion mode in HTML content.
2766         processEndTag(token);
2767         break;
2768     }
2769     case HTMLTokenTypes::Comment:
2770         m_tree.insertComment(token);
2771         return;
2772     case HTMLTokenTypes::Character: {
2773         String characters = String(token->characters().data(), token->characters().size());
2774         m_tree.insertTextNode(characters);
2775         if (m_framesetOk && !isAllWhitespaceOrReplacementCharacters(characters))
2776             m_framesetOk = false;
2777         break;
2778     }
2779     case HTMLTokenTypes::EndOfFile:
2780         ASSERT_NOT_REACHED();
2781         break;
2782     }
2783 }
2784
2785 void HTMLTreeBuilder::finished()
2786 {
2787     if (isParsingFragment())
2788         return;
2789     
2790     ASSERT(m_document);
2791     // Warning, this may detach the parser. Do not do anything else after this.
2792     m_document->finishedParsing();
2793 }
2794
2795 void HTMLTreeBuilder::parseError(AtomicHTMLToken*)
2796 {
2797 }
2798
2799 bool HTMLTreeBuilder::scriptEnabled(Frame* frame)
2800 {
2801     if (!frame)
2802         return false;
2803     return frame->script()->canExecuteScripts(NotAboutToExecuteScript);
2804 }
2805
2806 bool HTMLTreeBuilder::pluginsEnabled(Frame* frame)
2807 {
2808     if (!frame)
2809         return false;
2810     return frame->loader()->subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin);
2811 }
2812
2813 }