From 509e2178fb39cd8b9ae390c9ded4e4ad09f4b961 Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Tue, 1 Nov 2011 17:27:36 +0200 Subject: [PATCH] Bug 479959 - Reimplement text/plain loading using the HTML5 parser. r=Olli.Pettay. --- content/base/test/chrome/test_bug430050.xul | 2 +- content/html/document/src/nsHTMLDocument.cpp | 36 ++++++++++++++----- layout/build/nsContentDLF.cpp | 3 +- parser/html/nsHtml5Parser.cpp | 2 ++ parser/html/nsHtml5StreamParser.cpp | 8 ++++- parser/html/nsHtml5TokenizerCppSupplement.h | 6 ++++ parser/html/nsHtml5TokenizerHSupplement.h | 6 ++++ parser/html/nsHtml5TreeBuilderCppSupplement.h | 9 +++++ parser/html/nsHtml5TreeBuilderHSupplement.h | 2 ++ 9 files changed, 63 insertions(+), 11 deletions(-) diff --git a/content/base/test/chrome/test_bug430050.xul b/content/base/test/chrome/test_bug430050.xul index e090d19c9a4..b5948fad0c2 100644 --- a/content/base/test/chrome/test_bug430050.xul +++ b/content/base/test/chrome/test_bug430050.xul @@ -36,7 +36,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=430050 document.getElementById('b').loadURI('data:text/plain,succeeded', null, 'UTF-8'); - setTimeout(endTest, 0); + document.getElementById('b').addEventListener("load", endTest); } }, true); document.documentElement.setAttribute("foo", "bar"); diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index f3d1dd8f3a9..ffbc057a868 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -141,6 +141,7 @@ #include "prprf.h" #include "mozilla/dom/Element.h" #include "mozilla/Preferences.h" +#include "nsMimeTypes.h" using namespace mozilla; using namespace mozilla::dom; @@ -162,6 +163,7 @@ const PRInt32 kBackward = 1; //#define DEBUG_charset #define NS_USE_NEW_VIEW_SOURCE 1 +#define NS_USE_NEW_PLAIN_TEXT 1 static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID); @@ -652,17 +654,30 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand, bool aReset, nsIContentSink* aSink) { + nsCAutoString contentType; + aChannel->GetContentType(contentType); + bool viewSource = aCommand && !nsCRT::strcmp(aCommand, "view-source") && NS_USE_NEW_VIEW_SOURCE; - bool loadAsHtml5 = nsHtml5Module::sEnabled || viewSource; + bool plainText = (contentType.EqualsLiteral(TEXT_PLAIN) || + contentType.EqualsLiteral(TEXT_CSS) || + contentType.EqualsLiteral(APPLICATION_JAVASCRIPT) || + contentType.EqualsLiteral(APPLICATION_XJAVASCRIPT) || + contentType.EqualsLiteral(TEXT_ECMASCRIPT) || + contentType.EqualsLiteral(APPLICATION_ECMASCRIPT) || + contentType.EqualsLiteral(TEXT_JAVASCRIPT)); + bool loadAsHtml5 = nsHtml5Module::sEnabled || viewSource || plainText; + if (!NS_USE_NEW_PLAIN_TEXT && !viewSource) { + plainText = false; + } + + NS_ASSERTION(!(plainText && aSink), + "Someone tries to load plain text into a custom sink."); if (aSink) { loadAsHtml5 = false; } - nsCAutoString contentType; - aChannel->GetContentType(contentType); - if (contentType.Equals("application/xhtml+xml") && !viewSource) { // We're parsing XHTML as XML, remember that. @@ -677,7 +692,8 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand, } #endif - if (loadAsHtml5 && !viewSource && !(contentType.EqualsLiteral("text/html") && + if (loadAsHtml5 && !viewSource && + (!(contentType.EqualsLiteral("text/html") || plainText) && aCommand && !nsCRT::strcmp(aCommand, "view"))) { loadAsHtml5 = false; } @@ -731,9 +747,13 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand, if (needsParser) { if (loadAsHtml5) { mParser = nsHtml5Module::NewHtml5Parser(); - mParser->MarkAsNotScriptCreated((viewSource && - !contentType.EqualsLiteral("text/html")) ? - "view-source-xml": aCommand); + if (plainText) { + mParser->MarkAsNotScriptCreated("plain-text"); + } else if (viewSource && !contentType.EqualsLiteral("text/html")) { + mParser->MarkAsNotScriptCreated("view-source-xml"); + } else { + mParser->MarkAsNotScriptCreated(aCommand); + } } else { mParser = do_CreateInstance(kCParserCID, &rv); NS_ENSURE_SUCCESS(rv, rv); diff --git a/layout/build/nsContentDLF.cpp b/layout/build/nsContentDLF.cpp index 7eded0760c6..1e25531a130 100644 --- a/layout/build/nsContentDLF.cpp +++ b/layout/build/nsContentDLF.cpp @@ -87,7 +87,8 @@ nsresult NS_NewContentViewer(nsIContentViewer** aResult); // XXXbz if you change the MIME types here, be sure to update -// nsIParser.h and DetermineParseMode in nsParser.cpp accordingly. +// nsIParser.h and DetermineParseMode in nsParser.cpp and +// nsHTMLDocument::StartDocumentLoad accordingly. static const char* const gHTMLTypes[] = { TEXT_HTML, TEXT_PLAIN, diff --git a/parser/html/nsHtml5Parser.cpp b/parser/html/nsHtml5Parser.cpp index fef35797714..4cbc7cd9463 100644 --- a/parser/html/nsHtml5Parser.cpp +++ b/parser/html/nsHtml5Parser.cpp @@ -707,6 +707,8 @@ nsHtml5Parser::MarkAsNotScriptCreated(const char* aCommand) mode = VIEW_SOURCE_HTML; } else if (!nsCRT::strcmp(aCommand, "view-source-xml")) { mode = VIEW_SOURCE_XML; + } else if (!nsCRT::strcmp(aCommand, "plain-text")) { + mode = PLAIN_TEXT; } #ifdef DEBUG else { diff --git a/parser/html/nsHtml5StreamParser.cpp b/parser/html/nsHtml5StreamParser.cpp index 6b569f5b27a..391a03551ca 100644 --- a/parser/html/nsHtml5StreamParser.cpp +++ b/parser/html/nsHtml5StreamParser.cpp @@ -866,6 +866,12 @@ nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext) mTokenizer->start(); mExecutor->Start(); mExecutor->StartReadingFromStage(); + + if (mMode == PLAIN_TEXT) { + mTreeBuilder->StartPlainText(); + mTokenizer->StartPlainText(); + } + /* * If you move the following line, be very careful not to cause * WillBuildModel to be called before the document has had its @@ -891,7 +897,7 @@ nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext) // The line below means that the encoding can end up being wrong if // a view-source URL is loaded without having the encoding hint from a // previous normal load in the history. - mReparseForbidden = !(mMode == NORMAL); + mReparseForbidden = !(mMode == NORMAL || mMode == PLAIN_TEXT); nsCOMPtr httpChannel(do_QueryInterface(mRequest, &rv)); if (NS_SUCCEEDED(rv)) { diff --git a/parser/html/nsHtml5TokenizerCppSupplement.h b/parser/html/nsHtml5TokenizerCppSupplement.h index 9b71c6db2bf..45542c59abe 100644 --- a/parser/html/nsHtml5TokenizerCppSupplement.h +++ b/parser/html/nsHtml5TokenizerCppSupplement.h @@ -35,6 +35,12 @@ * * ***** END LICENSE BLOCK ***** */ +void +nsHtml5Tokenizer::StartPlainText() +{ + stateSave = NS_HTML5TOKENIZER_PLAINTEXT; +} + void nsHtml5Tokenizer::EnableViewSource(nsHtml5Highlighter* aHighlighter) { diff --git a/parser/html/nsHtml5TokenizerHSupplement.h b/parser/html/nsHtml5TokenizerHSupplement.h index 3650114fcaa..6c7fd5b8846 100644 --- a/parser/html/nsHtml5TokenizerHSupplement.h +++ b/parser/html/nsHtml5TokenizerHSupplement.h @@ -37,6 +37,12 @@ nsAutoPtr mViewSource; +/** + * Starts handling text/plain. This is a one-way initialization. There is + * no corresponding EndPlainText() call. + */ +void StartPlainText(); + void EnableViewSource(nsHtml5Highlighter* aHighlighter); bool FlushViewSource(); diff --git a/parser/html/nsHtml5TreeBuilderCppSupplement.h b/parser/html/nsHtml5TreeBuilderCppSupplement.h index 3fb16234322..c108106292f 100644 --- a/parser/html/nsHtml5TreeBuilderCppSupplement.h +++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h @@ -700,6 +700,15 @@ nsHtml5TreeBuilder::MarkAsBroken() mOpQueue.AppendElement()->Init(eTreeOpMarkAsBroken); } +void +nsHtml5TreeBuilder::StartPlainText() +{ + startTag(nsHtml5ElementName::ELT_PRE, + nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES, + false); + needToDropLF = false; +} + // DocumentModeHandler void nsHtml5TreeBuilder::documentMode(nsHtml5DocumentMode m) diff --git a/parser/html/nsHtml5TreeBuilderHSupplement.h b/parser/html/nsHtml5TreeBuilderHSupplement.h index 0614e7c61b4..03c9990bfc5 100644 --- a/parser/html/nsHtml5TreeBuilderHSupplement.h +++ b/parser/html/nsHtml5TreeBuilderHSupplement.h @@ -95,6 +95,8 @@ ~nsHtml5TreeBuilder(); + void StartPlainText(); + bool HasScript(); void SetOpSink(nsAHtml5TreeOpSink* aOpSink) {