OSDN Git Service

Scroll position now passed to all layers
[android-x86/external-webkit.git] / Source / WebCore / dom / XMLDocumentParserQt.cpp
1 /*
2  * Copyright (C) 2000 Peter Kelly (pmk@post.com)
3  * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved.
4  * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
5  * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
6  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
7  * Copyright (C) 2008 Holger Hans Peter Freyther
8  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 #include "config.h"
27 #include "XMLDocumentParser.h"
28
29 #include "CDATASection.h"
30 #include "CachedScript.h"
31 #include "Comment.h"
32 #include "CachedResourceLoader.h"
33 #include "Document.h"
34 #include "DocumentFragment.h"
35 #include "DocumentType.h"
36 #include "Frame.h"
37 #include "FrameLoader.h"
38 #include "FrameView.h"
39 #include "HTMLEntityParser.h"
40 #include "HTMLHtmlElement.h"
41 #include "HTMLLinkElement.h"
42 #include "HTMLNames.h"
43 #include "HTMLStyleElement.h"
44 #include "ProcessingInstruction.h"
45 #include "ResourceError.h"
46 #include "ResourceHandle.h"
47 #include "ResourceRequest.h"
48 #include "ResourceResponse.h"
49 #include "ScriptableDocumentParser.h"
50 #include "ScriptController.h"
51 #include "ScriptElement.h"
52 #include "ScriptSourceCode.h"
53 #include "ScriptValue.h"
54 #include "TextResourceDecoder.h"
55 #include "TransformSource.h"
56 #include <QDebug>
57 #include <wtf/StringExtras.h>
58 #include <wtf/Threading.h>
59 #include <wtf/Vector.h>
60 #include <wtf/text/CString.h>
61
62 #if ENABLE(XHTMLMP)
63 #include "HTMLNames.h"
64 #include "HTMLScriptElement.h"
65 #endif
66
67 using namespace std;
68
69 namespace WebCore {
70
71 class EntityResolver : public QXmlStreamEntityResolver {
72     virtual QString resolveUndeclaredEntity(const QString &name);
73 };
74
75 QString EntityResolver::resolveUndeclaredEntity(const QString &name)
76 {
77     UChar c = decodeNamedEntity(name.toUtf8().constData());
78     return QString(c);
79 }
80
81 // --------------------------------
82
83 bool XMLDocumentParser::supportsXMLVersion(const String& version)
84 {
85     return version == "1.0";
86 }
87
88 XMLDocumentParser::XMLDocumentParser(Document* document, FrameView* frameView)
89     : ScriptableDocumentParser(document)
90     , m_view(frameView)
91     , m_wroteText(false)
92     , m_currentNode(document)
93     , m_sawError(false)
94     , m_sawCSS(false)
95     , m_sawXSLTransform(false)
96     , m_sawFirstElement(false)
97     , m_isXHTMLDocument(false)
98 #if ENABLE(XHTMLMP)
99     , m_isXHTMLMPDocument(false)
100     , m_hasDocTypeDeclaration(false)
101 #endif
102     , m_parserPaused(false)
103     , m_requestingScript(false)
104     , m_finishCalled(false)
105     , m_errorCount(0)
106     , m_lastErrorPosition(TextPosition1::belowRangePosition())
107     , m_pendingScript(0)
108     , m_scriptStartPosition(TextPosition1::belowRangePosition())
109     , m_parsingFragment(false)
110     , m_scriptingPermission(FragmentScriptingAllowed)
111 {
112     m_stream.setEntityResolver(new EntityResolver);
113 }
114
115 XMLDocumentParser::XMLDocumentParser(DocumentFragment* fragment, Element* parentElement, FragmentScriptingPermission permission)
116     : ScriptableDocumentParser(fragment->document())
117     , m_view(0)
118     , m_wroteText(false)
119     , m_currentNode(fragment)
120     , m_sawError(false)
121     , m_sawCSS(false)
122     , m_sawXSLTransform(false)
123     , m_sawFirstElement(false)
124     , m_isXHTMLDocument(false)
125 #if ENABLE(XHTMLMP)
126     , m_isXHTMLMPDocument(false)
127     , m_hasDocTypeDeclaration(false)
128 #endif
129     , m_parserPaused(false)
130     , m_requestingScript(false)
131     , m_finishCalled(false)
132     , m_errorCount(0)
133     , m_lastErrorPosition(TextPosition1::belowRangePosition())
134     , m_pendingScript(0)
135     , m_scriptStartPosition(TextPosition1::belowRangePosition())
136     , m_parsingFragment(true)
137     , m_scriptingPermission(permission)
138 {
139     fragment->ref();
140
141     // Add namespaces based on the parent node
142     Vector<Element*> elemStack;
143     while (parentElement) {
144         elemStack.append(parentElement);
145
146         Node* n = parentElement->parentNode();
147         if (!n || !n->isElementNode())
148             break;
149         parentElement = static_cast<Element*>(n);
150     }
151
152     if (elemStack.isEmpty())
153         return;
154
155     QXmlStreamNamespaceDeclarations namespaces;
156     for (Element* element = elemStack.last(); !elemStack.isEmpty(); elemStack.removeLast()) {
157         if (NamedNodeMap* attrs = element->attributes()) {
158             for (unsigned i = 0; i < attrs->length(); i++) {
159                 Attribute* attr = attrs->attributeItem(i);
160                 if (attr->localName() == "xmlns")
161                     m_defaultNamespaceURI = attr->value();
162                 else if (attr->prefix() == "xmlns")
163                     namespaces.append(QXmlStreamNamespaceDeclaration(attr->localName(), attr->value()));
164             }
165         }
166     }
167     m_stream.addExtraNamespaceDeclarations(namespaces);
168     m_stream.setEntityResolver(new EntityResolver);
169
170     // If the parent element is not in document tree, there may be no xmlns attribute; just default to the parent's namespace.
171     if (m_defaultNamespaceURI.isNull() && !parentElement->inDocument())
172         m_defaultNamespaceURI = parentElement->namespaceURI();
173 }
174
175 XMLDocumentParser::~XMLDocumentParser()
176 {
177     clearCurrentNodeStack();
178     if (m_pendingScript)
179         m_pendingScript->removeClient(this);
180     delete m_stream.entityResolver();
181 }
182
183 void XMLDocumentParser::doWrite(const String& parseString)
184 {
185     m_wroteText = true;
186
187     if (document()->decoder() && document()->decoder()->sawError()) {
188         // If the decoder saw an error, report it as fatal (stops parsing)
189         handleError(fatal, "Encoding error", lineNumber(), columnNumber());
190         return;
191     }
192
193     QString data(parseString);
194     if (!data.isEmpty()) {
195         // JavaScript may cause the parser to detach,
196         // keep this alive until this function is done.
197         RefPtr<XMLDocumentParser> protect(this);
198
199         m_stream.addData(data);
200         parse();
201     }
202
203     return;
204 }
205
206 void XMLDocumentParser::initializeParserContext(const char*)
207 {
208     DocumentParser::startParsing();
209     m_sawError = false;
210     m_sawCSS = false;
211     m_sawXSLTransform = false;
212     m_sawFirstElement = false;
213 }
214
215 void XMLDocumentParser::doEnd()
216 {
217 #if ENABLE(XSLT)
218     if (m_sawXSLTransform) {
219         document()->setTransformSource(new TransformSource(m_originalSourceForTransform));
220         document()->setParsing(false); // Make the doc think it's done, so it will apply xsl sheets.
221         document()->styleSelectorChanged(RecalcStyleImmediately);
222         document()->setParsing(true);
223         DocumentParser::stopParsing();
224     }
225 #endif
226
227     if (m_stream.error() == QXmlStreamReader::PrematureEndOfDocumentError
228         || (m_wroteText && !m_sawFirstElement && !m_sawXSLTransform && !m_sawError))
229         handleError(fatal, qPrintable(m_stream.errorString()), lineNumber(), columnNumber());
230 }
231
232 int XMLDocumentParser::lineNumber() const
233 {
234     return m_stream.lineNumber();
235 }
236
237 int XMLDocumentParser::columnNumber() const
238 {
239     return m_stream.columnNumber();
240 }
241
242 TextPosition0 XMLDocumentParser::textPosition() const
243 {
244     return TextPosition0(WTF::ZeroBasedNumber::fromZeroBasedInt(lineNumber()), WTF::ZeroBasedNumber::fromZeroBasedInt(columnNumber()));
245 }
246
247 // This method incorrectly reinterprets zero-base lineNumber method as one-based number.
248 // FIXME: This error is kept for compatibility. We should fix it eventually. 
249 TextPosition1 XMLDocumentParser::textPositionOneBased() const
250 {
251     return TextPosition1(WTF::OneBasedNumber::fromOneBasedInt(lineNumber()), WTF::OneBasedNumber::fromOneBasedInt(columnNumber()));
252 }
253
254 void XMLDocumentParser::stopParsing()
255 {
256     ScriptableDocumentParser::stopParsing();
257 }
258
259 void XMLDocumentParser::resumeParsing()
260 {
261     ASSERT(m_parserPaused);
262
263     m_parserPaused = false;
264
265     // First, execute any pending callbacks
266     parse();
267     if (m_parserPaused)
268         return;
269
270     // Then, write any pending data
271     SegmentedString rest = m_pendingSrc;
272     m_pendingSrc.clear();
273     append(rest);
274
275     // Finally, if finish() has been called and append() didn't result
276     // in any further callbacks being queued, call end()
277     if (m_finishCalled && !m_parserPaused && !m_pendingScript)
278         end();
279 }
280
281 bool XMLDocumentParser::appendFragmentSource(const String& source)
282 {
283     ASSERT(!m_sawFirstElement);
284     append(String("<qxmlstreamdummyelement>"));
285     append(source);
286     append(String("</qxmlstreamdummyelement>"));
287     return !hasError();
288 }
289
290 // --------------------------------
291
292 struct AttributeParseState {
293     HashMap<String, String> attributes;
294     bool gotAttributes;
295 };
296
297 static void attributesStartElementNsHandler(AttributeParseState* state, const QXmlStreamAttributes& attrs)
298 {
299     if (attrs.count() <= 0)
300         return;
301
302     state->gotAttributes = true;
303
304     for (int i = 0; i < attrs.count(); i++) {
305         const QXmlStreamAttribute& attr = attrs[i];
306         String attrLocalName = attr.name();
307         String attrValue     = attr.value();
308         String attrURI       = attr.namespaceUri();
309         String attrQName     = attr.qualifiedName();
310         state->attributes.set(attrQName, attrValue);
311     }
312 }
313
314 HashMap<String, String> parseAttributes(const String& string, bool& attrsOK)
315 {
316     AttributeParseState state;
317     state.gotAttributes = false;
318
319     QXmlStreamReader stream;
320     QString dummy = QString(QLatin1String("<?xml version=\"1.0\"?><attrs %1 />")).arg(string);
321     stream.addData(dummy);
322     while (!stream.atEnd()) {
323         stream.readNext();
324         if (stream.isStartElement()) {
325             attributesStartElementNsHandler(&state, stream.attributes());
326         }
327     }
328     attrsOK = state.gotAttributes;
329     return state.attributes;
330 }
331
332 static inline String prefixFromQName(const QString& qName)
333 {
334     const int offset = qName.indexOf(QLatin1Char(':'));
335     if (offset <= 0)
336         return String();
337     else
338         return qName.left(offset);
339 }
340
341 static inline void handleElementNamespaces(Element* newElement, const QXmlStreamNamespaceDeclarations &ns,
342                                            ExceptionCode& ec, FragmentScriptingPermission scriptingPermission)
343 {
344     for (int i = 0; i < ns.count(); ++i) {
345         const QXmlStreamNamespaceDeclaration &decl = ns[i];
346         String namespaceURI = decl.namespaceUri();
347         String namespaceQName = decl.prefix().isEmpty() ? String("xmlns") : String("xmlns:");
348         namespaceQName.append(decl.prefix());
349         newElement->setAttributeNS("http://www.w3.org/2000/xmlns/", namespaceQName, namespaceURI, ec, scriptingPermission);
350         if (ec) // exception setting attributes
351             return;
352     }
353 }
354
355 static inline void handleElementAttributes(Element* newElement, const QXmlStreamAttributes &attrs, ExceptionCode& ec,
356                                            FragmentScriptingPermission scriptingPermission)
357 {
358     for (int i = 0; i < attrs.count(); ++i) {
359         const QXmlStreamAttribute &attr = attrs[i];
360         String attrLocalName = attr.name();
361         String attrValue     = attr.value();
362         String attrURI       = attr.namespaceUri().isEmpty() ? String() : String(attr.namespaceUri());
363         String attrQName     = attr.qualifiedName();
364         newElement->setAttributeNS(attrURI, attrQName, attrValue, ec, scriptingPermission);
365         if (ec) // exception setting attributes
366             return;
367     }
368 }
369
370 void XMLDocumentParser::parse()
371 {
372     while (!isStopped() && !m_parserPaused && !m_stream.atEnd()) {
373         m_stream.readNext();
374         switch (m_stream.tokenType()) {
375         case QXmlStreamReader::StartDocument: {
376             startDocument();
377         }
378             break;
379         case QXmlStreamReader::EndDocument: {
380             endDocument();
381         }
382             break;
383         case QXmlStreamReader::StartElement: {
384 #if ENABLE(XHTMLMP)
385             if (document()->isXHTMLMPDocument() && !m_hasDocTypeDeclaration) {
386                 handleError(fatal, "DOCTYPE declaration lost.", lineNumber(), columnNumber());
387                 break;
388             }
389 #endif
390             parseStartElement();
391         }
392             break;
393         case QXmlStreamReader::EndElement: {
394             parseEndElement();
395         }
396             break;
397         case QXmlStreamReader::Characters: {
398             if (m_stream.isCDATA()) {
399                 //cdata
400                 parseCdata();
401             } else {
402                 //characters
403                 parseCharacters();
404             }
405         }
406             break;
407         case QXmlStreamReader::Comment: {
408             parseComment();
409         }
410             break;
411         case QXmlStreamReader::DTD: {
412             //qDebug()<<"------------- DTD";
413             parseDtd();
414 #if ENABLE(XHTMLMP)
415             m_hasDocTypeDeclaration = true;
416 #endif
417         }
418             break;
419         case QXmlStreamReader::EntityReference: {
420             //qDebug()<<"---------- ENTITY = "<<m_stream.name().toString()
421             //        <<", t = "<<m_stream.text().toString();
422             if (isXHTMLDocument()
423 #if ENABLE(XHTMLMP)
424                 || isXHTMLMPDocument()
425 #endif
426 #if ENABLE(WML)
427                 || isWMLDocument()
428 #endif
429                ) {
430                 QString entity = m_stream.name().toString();
431                 UChar c = decodeNamedEntity(entity.toUtf8().constData());
432                 if (!m_currentNode->isTextNode())
433                     enterText();
434                 ExceptionCode ec = 0;
435                 String str(&c, 1);
436                 // qDebug()<<" ------- adding entity "<<str;
437                 static_cast<Text*>(m_currentNode)->appendData(str, ec);
438             }
439         }
440             break;
441         case QXmlStreamReader::ProcessingInstruction: {
442             parseProcessingInstruction();
443         }
444             break;
445         default: {
446             if (m_stream.error() != QXmlStreamReader::PrematureEndOfDocumentError) {
447                 ErrorType type = (m_stream.error() == QXmlStreamReader::NotWellFormedError) ?
448                                  fatal : warning;
449                 handleError(type, qPrintable(m_stream.errorString()), lineNumber(),
450                             columnNumber());
451             }
452         }
453             break;
454         }
455     }
456 }
457
458 void XMLDocumentParser::startDocument()
459 {
460     initializeParserContext();
461     ExceptionCode ec = 0;
462
463     if (!m_parsingFragment) {
464         document()->setXMLStandalone(m_stream.isStandaloneDocument(), ec);
465
466         QStringRef version = m_stream.documentVersion();
467         if (!version.isEmpty())
468             document()->setXMLVersion(version, ec);
469         QStringRef encoding = m_stream.documentEncoding();
470         if (!encoding.isEmpty())
471             document()->setXMLEncoding(encoding);
472     }
473 }
474
475 void XMLDocumentParser::parseStartElement()
476 {
477     if (!m_sawFirstElement && m_parsingFragment) {
478         // skip dummy element for fragments
479         m_sawFirstElement = true;
480         return;
481     }
482
483     exitText();
484
485     String localName = m_stream.name();
486     String uri       = m_stream.namespaceUri();
487     String prefix    = prefixFromQName(m_stream.qualifiedName().toString());
488
489     if (m_parsingFragment && uri.isNull()) {
490         Q_ASSERT(prefix.isNull());
491         uri = m_defaultNamespaceURI;
492     }
493
494     QualifiedName qName(prefix, localName, uri);
495     RefPtr<Element> newElement = document()->createElement(qName, true);
496     if (!newElement) {
497         stopParsing();
498         return;
499     }
500
501 #if ENABLE(XHTMLMP)
502     if (!m_sawFirstElement && isXHTMLMPDocument()) {
503         // As per 7.1 section of OMA-WAP-XHTMLMP-V1_1-20061020-A.pdf,
504         // we should make sure that the root element MUST be 'html' and
505         // ensure the name of the default namespace on the root elment 'html'
506         // MUST be 'http://www.w3.org/1999/xhtml'
507         if (localName != HTMLNames::htmlTag.localName()) {
508             handleError(fatal, "XHTMLMP document expects 'html' as root element.", lineNumber(), columnNumber());
509             return;
510         }
511
512         if (uri.isNull()) {
513             m_defaultNamespaceURI = HTMLNames::xhtmlNamespaceURI;
514             uri = m_defaultNamespaceURI;
515             m_stream.addExtraNamespaceDeclaration(QXmlStreamNamespaceDeclaration(prefix, HTMLNames::xhtmlNamespaceURI));
516         }
517     }
518 #endif
519
520     bool isFirstElement = !m_sawFirstElement;
521     m_sawFirstElement = true;
522
523     ExceptionCode ec = 0;
524     handleElementNamespaces(newElement.get(), m_stream.namespaceDeclarations(), ec, m_scriptingPermission);
525     if (ec) {
526         stopParsing();
527         return;
528     }
529
530     handleElementAttributes(newElement.get(), m_stream.attributes(), ec, m_scriptingPermission);
531     if (ec) {
532         stopParsing();
533         return;
534     }
535
536     ScriptElement* scriptElement = toScriptElement(newElement.get());
537     if (scriptElement)
538         m_scriptStartPosition = textPositionOneBased();
539
540     m_currentNode->deprecatedParserAddChild(newElement.get());
541
542     pushCurrentNode(newElement.get());
543     if (m_view && !newElement->attached())
544         newElement->attach();
545
546 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
547     if (newElement->hasTagName(HTMLNames::htmlTag))
548         static_cast<HTMLHtmlElement*>(newElement.get())->insertedByParser();
549 #endif
550
551     if (isFirstElement && document()->frame())
552         document()->frame()->loader()->dispatchDocumentElementAvailable();
553 }
554
555 void XMLDocumentParser::parseEndElement()
556 {
557     exitText();
558
559     RefPtr<Node> n = m_currentNode;
560     n->finishParsingChildren();
561
562     if (m_scriptingPermission == FragmentScriptingNotAllowed && n->isElementNode() && toScriptElement(static_cast<Element*>(n.get()))) {
563         popCurrentNode();
564         ExceptionCode ec;
565         n->remove(ec);
566         return;
567     }
568
569     if (!n->isElementNode() || !m_view) {
570         if (!m_currentNodeStack.isEmpty())
571             popCurrentNode();
572         return;
573     }
574
575     Element* element = static_cast<Element*>(n.get());
576
577     // The element's parent may have already been removed from document.
578     // Parsing continues in this case, but scripts aren't executed.
579     if (!element->inDocument()) {
580         popCurrentNode();
581         return;
582     }
583
584     ScriptElement* scriptElement = toScriptElement(element);
585     if (!scriptElement) {
586         popCurrentNode();
587         return;
588     }
589
590     // don't load external scripts for standalone documents (for now)
591     ASSERT(!m_pendingScript);
592     m_requestingScript = true;
593
594     bool successfullyPrepared = scriptElement->prepareScript(m_scriptStartPosition, ScriptElement::AllowLegacyTypeInTypeAttribute);
595     if (!successfullyPrepared) {
596 #if ENABLE(XHTMLMP)
597         if (!scriptElement->isScriptTypeSupported(ScriptElement::AllowLegacyTypeInTypeAttribute))
598             document()->setShouldProcessNoscriptElement(true);
599 #endif
600     } else {
601         if (scriptElement->readyToBeParserExecuted())
602             scriptElement->executeScript(ScriptSourceCode(scriptElement->scriptContent(), document()->url(), m_scriptStartPosition));
603         else if (scriptElement->willBeParserExecuted()) {
604             m_pendingScript = scriptElement->cachedScript();
605             m_scriptElement = element;
606             m_pendingScript->addClient(this);
607
608             // m_pendingScript will be 0 if script was already loaded and addClient() executed it.
609             if (m_pendingScript)
610                 pauseParsing();
611         } else
612             m_scriptElement = 0;
613     }
614     m_requestingScript = false;
615     popCurrentNode();
616 }
617
618 void XMLDocumentParser::parseCharacters()
619 {
620     if (!m_currentNode->isTextNode())
621         enterText();
622     ExceptionCode ec = 0;
623     static_cast<Text*>(m_currentNode)->appendData(m_stream.text(), ec);
624 }
625
626 void XMLDocumentParser::parseProcessingInstruction()
627 {
628     exitText();
629
630     // ### handle exceptions
631     int exception = 0;
632     RefPtr<ProcessingInstruction> pi = document()->createProcessingInstruction(
633         m_stream.processingInstructionTarget(),
634         m_stream.processingInstructionData(), exception);
635     if (exception)
636         return;
637
638     pi->setCreatedByParser(true);
639
640     m_currentNode->deprecatedParserAddChild(pi.get());
641     if (m_view && !pi->attached())
642         pi->attach();
643
644     pi->finishParsingChildren();
645
646     if (pi->isCSS())
647         m_sawCSS = true;
648 #if ENABLE(XSLT)
649     m_sawXSLTransform = !m_sawFirstElement && pi->isXSL();
650     if (m_sawXSLTransform && !document()->transformSourceDocument())
651         stopParsing();
652 #endif
653 }
654
655 void XMLDocumentParser::parseCdata()
656 {
657     exitText();
658
659     RefPtr<Node> newNode = CDATASection::create(document(), m_stream.text());
660
661     m_currentNode->deprecatedParserAddChild(newNode.get());
662     if (m_view && !newNode->attached())
663         newNode->attach();
664 }
665
666 void XMLDocumentParser::parseComment()
667 {
668     exitText();
669
670     RefPtr<Node> newNode = Comment::create(document(), m_stream.text());
671
672     m_currentNode->deprecatedParserAddChild(newNode.get());
673     if (m_view && !newNode->attached())
674         newNode->attach();
675 }
676
677 void XMLDocumentParser::endDocument()
678 {
679 #if ENABLE(XHTMLMP)
680     m_hasDocTypeDeclaration = false;
681 #endif
682 }
683
684 bool XMLDocumentParser::hasError() const
685 {
686     return m_stream.hasError();
687 }
688
689 void XMLDocumentParser::parseDtd()
690 {
691     QStringRef name = m_stream.dtdName();
692     QStringRef publicId = m_stream.dtdPublicId();
693     QStringRef systemId = m_stream.dtdSystemId();
694
695     //qDebug() << dtd << name << publicId << systemId;
696     if ((publicId == QLatin1String("-//W3C//DTD XHTML 1.0 Transitional//EN"))
697         || (publicId == QLatin1String("-//W3C//DTD XHTML 1.1//EN"))
698         || (publicId == QLatin1String("-//W3C//DTD XHTML 1.0 Strict//EN"))
699         || (publicId == QLatin1String("-//W3C//DTD XHTML 1.0 Frameset//EN"))
700         || (publicId == QLatin1String("-//W3C//DTD XHTML Basic 1.0//EN"))
701         || (publicId == QLatin1String("-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN"))
702         || (publicId == QLatin1String("-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN"))
703 #if !ENABLE(XHTMLMP)
704         || (publicId == QLatin1String("-//WAPFORUM//DTD XHTML Mobile 1.0//EN"))
705 #endif
706        )
707         setIsXHTMLDocument(true); // controls if we replace entities or not.
708 #if ENABLE(XHTMLMP)
709     else if ((publicId == QLatin1String("-//WAPFORUM//DTD XHTML Mobile 1.1//EN"))
710              || (publicId == QLatin1String("-//WAPFORUM//DTD XHTML Mobile 1.0//EN"))) {
711         if (AtomicString(name) != HTMLNames::htmlTag.localName()) {
712             handleError(fatal, "Invalid DOCTYPE declaration, expected 'html' as root element.", lineNumber(), columnNumber());
713             return;
714         }
715
716         if (document()->isXHTMLMPDocument()) // check if the MIME type is correct with this method
717             setIsXHTMLMPDocument(true);
718         else
719             setIsXHTMLDocument(true);
720     }
721 #endif
722 #if ENABLE(WML)
723     else if (document()->isWMLDocument()
724              && publicId != QLatin1String("-//WAPFORUM//DTD WML 1.3//EN")
725              && publicId != QLatin1String("-//WAPFORUM//DTD WML 1.2//EN")
726              && publicId != QLatin1String("-//WAPFORUM//DTD WML 1.1//EN")
727              && publicId != QLatin1String("-//WAPFORUM//DTD WML 1.0//EN"))
728         handleError(fatal, "Invalid DTD Public ID", lineNumber(), columnNumber());
729 #endif
730     if (!m_parsingFragment)
731         document()->parserAddChild(DocumentType::create(document(), name, publicId, systemId));
732
733 }
734 }