Bug 705072 - Limit HTML support in XHR to responseType == "document" to avoid changing the behavior for legacy users. r=smaug.

This commit is contained in:
Henri Sivonen 2011-11-24 17:28:12 +02:00
Родитель 1f97f4a559
Коммит a9fb0d6f91
5 изменённых файлов: 24 добавлений и 58 удалений

Просмотреть файл

@ -884,7 +884,7 @@ NS_IMETHODIMP nsXMLHttpRequest::GetResponseText(nsAString& aResponseText)
// We only decode text lazily if we're also parsing to a doc. // 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 // Also, if we've decoded all current data already, then no need to decode
// more. // more.
if (IsWaitingForHTMLCharset() || !mResponseXML || if (!mResponseXML ||
mResponseBodyDecodedPos == mResponseBody.Length()) { mResponseBodyDecodedPos == mResponseBody.Length()) {
aResponseText = mResponseText; aResponseText = mResponseText;
return NS_OK; return NS_OK;
@ -1473,16 +1473,6 @@ nsXMLHttpRequest::IsSystemXHR()
return !!nsContentUtils::IsSystemPrincipal(mPrincipal); return !!nsContentUtils::IsSystemPrincipal(mPrincipal);
} }
bool
nsXMLHttpRequest::IsWaitingForHTMLCharset()
{
if (!mIsHtml || !mResponseXML) {
return false;
}
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mResponseXML);
return doc->GetDocumentCharacterSetSource() < kCharsetFromDocTypeDefault;
}
nsresult nsresult
nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel) nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel)
{ {
@ -1928,7 +1918,13 @@ nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
nsCAutoString type; nsCAutoString type;
channel->GetContentType(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)) { if (!(mState & XML_HTTP_REQUEST_ASYNC)) {
// We don't make cool new features available in the bad synchronous // We don't make cool new features available in the bad synchronous
// mode. The synchronous mode is for legacy only. // mode. The synchronous mode is for legacy only.
@ -3138,13 +3134,11 @@ nsXMLHttpRequest::MaybeDispatchProgressEvents(bool aFinalProgress)
mLoadTotal = mLoadTransferred; mLoadTotal = mLoadTransferred;
mLoadLengthComputable = true; mLoadLengthComputable = true;
} }
if (aFinalProgress || !IsWaitingForHTMLCharset()) { mInLoadProgressEvent = true;
mInLoadProgressEvent = true; DispatchProgressEvent(this, NS_LITERAL_STRING(PROGRESS_STR),
DispatchProgressEvent(this, NS_LITERAL_STRING(PROGRESS_STR), true, mLoadLengthComputable, mLoadTransferred,
true, mLoadLengthComputable, mLoadTransferred, mLoadTotal, mLoadTransferred, mLoadTotal);
mLoadTotal, mLoadTransferred, mLoadTotal); mInLoadProgressEvent = false;
mInLoadProgressEvent = false;
}
if (mResponseType == XML_HTTP_RESPONSE_TYPE_CHUNKED_TEXT || if (mResponseType == XML_HTTP_RESPONSE_TYPE_CHUNKED_TEXT ||
mResponseType == XML_HTTP_RESPONSE_TYPE_CHUNKED_ARRAYBUFFER) { mResponseType == XML_HTTP_RESPONSE_TYPE_CHUNKED_ARRAYBUFFER) {
mResponseBody.Truncate(); mResponseBody.Truncate();

Просмотреть файл

@ -236,8 +236,6 @@ protected:
bool IsSystemXHR(); bool IsSystemXHR();
bool IsWaitingForHTMLCharset();
void ChangeStateToDone(); void ChangeStateToDone();
/** /**

Просмотреть файл

@ -510,7 +510,6 @@ _TEST_FILES2 = \
file_html_in_xhr2.html \ file_html_in_xhr2.html \
file_html_in_xhr3.html \ file_html_in_xhr3.html \
file_html_in_xhr.sjs \ file_html_in_xhr.sjs \
file_html_in_xhr_slow.sjs \
test_bug664916.html \ test_bug664916.html \
test_bug666604.html \ test_bug666604.html \
test_bug675121.html \ test_bug675121.html \

Просмотреть файл

@ -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 = "<meta charset='windows";
out.write(firstPart, firstPart.length);
out.flush();
response.processAsync();
timer = Components.classes["@mozilla.org/timer;1"]
.createInstance(Components.interfaces.nsITimer);
timer.initWithCallback(function() {
response.write("-1251'>");
response.finish();
}, 500, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
}

Просмотреть файл

@ -29,7 +29,12 @@ function runTest() {
ok(this.responseXML, "Should have gotten responseXML"); ok(this.responseXML, "Should have gotten responseXML");
is(this.responseXML.characterSet, "windows-1251", "Wrong character encoding"); is(this.responseXML.characterSet, "windows-1251", "Wrong character encoding");
is(this.responseXML.documentElement.firstChild.data, " \u042E ", "Decoded using the wrong 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."); 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."); ok(!this.responseXML.documentElement.hasAttribute("data-fail"), "Should not have a data-fail attribute.");
var scripts = this.responseXML.getElementsByTagName("script"); var scripts = this.responseXML.getElementsByTagName("script");
@ -44,27 +49,21 @@ function runTest() {
} }
} }
xhr.open("GET", "file_html_in_xhr.html", true); xhr.open("GET", "file_html_in_xhr.html", true);
xhr.responseType = "document";
xhr.send(); xhr.send();
} }
function continueAfterReport() { function continueAfterReport() {
ok(!document.documentElement.hasAttribute("data-fail"), "Should not have a data-fail attribute on mochitest doc.");
xhr = new XMLHttpRequest(); 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() { xhr.onreadystatechange = function() {
if (this.readyState == 4) { 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(); testNonParsingText();
} }
} }
xhr.open("GET", "file_html_in_xhr_slow.sjs"); xhr.open("GET", "file_html_in_xhr2.html");
xhr.send(); xhr.send();
} }