From a9fb0d6f9178092714801374a6d190a24be38ddc Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Thu, 24 Nov 2011 17:28:12 +0200 Subject: [PATCH] Bug 705072 - Limit HTML support in XHR to responseType == "document" to avoid changing the behavior for legacy users. r=smaug. --- content/base/src/nsXMLHttpRequest.cpp | 32 +++++++++------------ content/base/src/nsXMLHttpRequest.h | 2 -- content/base/test/Makefile.in | 1 - content/base/test/file_html_in_xhr_slow.sjs | 24 ---------------- content/base/test/test_html_in_xhr.html | 23 +++++++-------- 5 files changed, 24 insertions(+), 58 deletions(-) delete mode 100644 content/base/test/file_html_in_xhr_slow.sjs diff --git a/content/base/src/nsXMLHttpRequest.cpp b/content/base/src/nsXMLHttpRequest.cpp index ae97ed540e0..d539f43637c 100644 --- a/content/base/src/nsXMLHttpRequest.cpp +++ b/content/base/src/nsXMLHttpRequest.cpp @@ -884,7 +884,7 @@ NS_IMETHODIMP nsXMLHttpRequest::GetResponseText(nsAString& aResponseText) // We only decode text lazily if we're also parsing to a doc. // Also, if we've decoded all current data already, then no need to decode // more. - if (IsWaitingForHTMLCharset() || !mResponseXML || + if (!mResponseXML || mResponseBodyDecodedPos == mResponseBody.Length()) { aResponseText = mResponseText; return NS_OK; @@ -1473,16 +1473,6 @@ nsXMLHttpRequest::IsSystemXHR() return !!nsContentUtils::IsSystemPrincipal(mPrincipal); } -bool -nsXMLHttpRequest::IsWaitingForHTMLCharset() -{ - if (!mIsHtml || !mResponseXML) { - return false; - } - nsCOMPtr doc = do_QueryInterface(mResponseXML); - return doc->GetDocumentCharacterSetSource() < kCharsetFromDocTypeDefault; -} - nsresult nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel) { @@ -1928,7 +1918,13 @@ nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt) nsCAutoString type; channel->GetContentType(type); - if (type.EqualsLiteral("text/html")) { + if ((mResponseType == XML_HTTP_RESPONSE_TYPE_DOCUMENT) && + type.EqualsLiteral("text/html")) { + // HTML parsing is only supported for responseType == "document" to + // avoid running the parser and, worse, populating responseXML for + // legacy users of XHR who use responseType == "" for retrieving the + // responseText of text/html resources. This legacy case is so common + // that it's not useful to emit a warning about it. if (!(mState & XML_HTTP_REQUEST_ASYNC)) { // We don't make cool new features available in the bad synchronous // mode. The synchronous mode is for legacy only. @@ -3138,13 +3134,11 @@ nsXMLHttpRequest::MaybeDispatchProgressEvents(bool aFinalProgress) mLoadTotal = mLoadTransferred; mLoadLengthComputable = true; } - if (aFinalProgress || !IsWaitingForHTMLCharset()) { - mInLoadProgressEvent = true; - DispatchProgressEvent(this, NS_LITERAL_STRING(PROGRESS_STR), - true, mLoadLengthComputable, mLoadTransferred, - mLoadTotal, mLoadTransferred, mLoadTotal); - mInLoadProgressEvent = false; - } + mInLoadProgressEvent = true; + DispatchProgressEvent(this, NS_LITERAL_STRING(PROGRESS_STR), + true, mLoadLengthComputable, mLoadTransferred, + mLoadTotal, mLoadTransferred, mLoadTotal); + mInLoadProgressEvent = false; if (mResponseType == XML_HTTP_RESPONSE_TYPE_CHUNKED_TEXT || mResponseType == XML_HTTP_RESPONSE_TYPE_CHUNKED_ARRAYBUFFER) { mResponseBody.Truncate(); diff --git a/content/base/src/nsXMLHttpRequest.h b/content/base/src/nsXMLHttpRequest.h index fa2230f223f..4b225713e23 100644 --- a/content/base/src/nsXMLHttpRequest.h +++ b/content/base/src/nsXMLHttpRequest.h @@ -236,8 +236,6 @@ protected: bool IsSystemXHR(); - bool IsWaitingForHTMLCharset(); - void ChangeStateToDone(); /** diff --git a/content/base/test/Makefile.in b/content/base/test/Makefile.in index 6828e6c53e1..c69a40b06f9 100644 --- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -510,7 +510,6 @@ _TEST_FILES2 = \ file_html_in_xhr2.html \ file_html_in_xhr3.html \ file_html_in_xhr.sjs \ - file_html_in_xhr_slow.sjs \ test_bug664916.html \ test_bug666604.html \ test_bug675121.html \ diff --git a/content/base/test/file_html_in_xhr_slow.sjs b/content/base/test/file_html_in_xhr_slow.sjs deleted file mode 100644 index 39f47bf72ee..00000000000 --- a/content/base/test/file_html_in_xhr_slow.sjs +++ /dev/null @@ -1,24 +0,0 @@ -var timer; - -function handleRequest(request, response) -{ - var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"] - .createInstance(Components.interfaces.nsIScriptableUnicodeConverter); - converter.charset = "windows-1251"; - var stream = converter.convertToInputStream("\u042E"); - var out = response.bodyOutputStream; - response.setHeader("Cache-Control", "no-cache", false); - response.setHeader("Content-Type", "text/html", false); - out.writeFrom(stream, 1); - var firstPart = ""); - response.finish(); - }, 500, Components.interfaces.nsITimer.TYPE_ONE_SHOT); -} - diff --git a/content/base/test/test_html_in_xhr.html b/content/base/test/test_html_in_xhr.html index c963e5aa881..658e6ecab14 100644 --- a/content/base/test/test_html_in_xhr.html +++ b/content/base/test/test_html_in_xhr.html @@ -29,7 +29,12 @@ function runTest() { ok(this.responseXML, "Should have gotten responseXML"); is(this.responseXML.characterSet, "windows-1251", "Wrong character encoding"); is(this.responseXML.documentElement.firstChild.data, " \u042E ", "Decoded using the wrong encoding."); - is(this.responseText.indexOf("\u042E"), 27, "Bad responseText"); + try { + this.responseText; + ok(false, "responseText access should have thrown."); + } catch (e) { + is(e.code, 11, "Should have thrown INVALID_STATE_ERR."); + } is(this.responseXML.getElementsByTagName("div").length, 1, "There should be one div."); ok(!this.responseXML.documentElement.hasAttribute("data-fail"), "Should not have a data-fail attribute."); var scripts = this.responseXML.getElementsByTagName("script"); @@ -44,27 +49,21 @@ function runTest() { } } xhr.open("GET", "file_html_in_xhr.html", true); + xhr.responseType = "document"; xhr.send(); } function continueAfterReport() { - ok(!document.documentElement.hasAttribute("data-fail"), "Should not have a data-fail attribute on mochitest doc."); xhr = new XMLHttpRequest(); - xhr.onprogress = function() { - ok(this.responseText, "Got falsy responseText"); - if (this.responseText) { - ok(this.responseText.length, "Got zero-length responseText"); - if (this.responseText.length) { - is(this.responseText.charCodeAt(0), 0x042E, "Wrong character encoding for slow text"); - } - } - } xhr.onreadystatechange = function() { if (this.readyState == 4) { + is(this.responseText.indexOf("\u042E"), -1, "Honored meta in default mode."); + is(this.responseText.indexOf("\uFFFD"), 29, "Honored meta in default mode 2."); + is(this.responseXML, null, "responseXML should be null for HTML in the default mode"); testNonParsingText(); } } - xhr.open("GET", "file_html_in_xhr_slow.sjs"); + xhr.open("GET", "file_html_in_xhr2.html"); xhr.send(); }