mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-27 21:00:50 +00:00
Bug 918719 - Only fire one loading readystatechange per XHR, but keep the old behavior available behind the preference dom.send_multiple_xhr_loading_readystatechanges. r=smaug
--HG-- extra : rebase_source : 296943a67ae8bd3065749cc424a4379320169585
This commit is contained in:
parent
4dd22032fa
commit
3cf91c9343
47
dom/tests/mochitest/bugs/bug918719.sjs
Normal file
47
dom/tests/mochitest/bugs/bug918719.sjs
Normal file
@ -0,0 +1,47 @@
|
||||
// Keep track of one in-flight XHR by allowing secondary ones to
|
||||
// tell us when the client has received a Progress event and wants
|
||||
// more data or to stop the in-flight XHR.
|
||||
|
||||
const STATE_NAME = "bug918719_loading_event_test";
|
||||
const CHUNK_DATA = "chunk";
|
||||
|
||||
function setReq(req) {
|
||||
setObjectState(STATE_NAME, req);
|
||||
}
|
||||
|
||||
function getReq() {
|
||||
let req;
|
||||
getObjectState(STATE_NAME, function(v) {
|
||||
req = v;
|
||||
});
|
||||
return req;
|
||||
}
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
var pairs = request.queryString.split("&");
|
||||
var command = pairs.shift();
|
||||
|
||||
response.setHeader("Content-Type", "text/plain");
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
|
||||
switch(command) {
|
||||
case "more":
|
||||
getReq().write(CHUNK_DATA);
|
||||
break;
|
||||
|
||||
case "done":
|
||||
getReq().finish();
|
||||
setReq(null);
|
||||
break;
|
||||
|
||||
default:
|
||||
response.processAsync();
|
||||
response.write(CHUNK_DATA);
|
||||
setReq(response);
|
||||
return;
|
||||
}
|
||||
|
||||
response.setHeader("Content-Length", "2", false);
|
||||
response.write("ok");
|
||||
}
|
@ -7,6 +7,7 @@ support-files =
|
||||
bug346659-parent-echoer.html
|
||||
bug346659-parent.html
|
||||
bug458091_child.html
|
||||
bug918719.sjs
|
||||
child_bug260264.html
|
||||
devicemotion_inner.html
|
||||
devicemotion_outer.html
|
||||
@ -155,6 +156,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
|
||||
[test_bug857555.html]
|
||||
[test_bug862540.html]
|
||||
[test_bug876098.html]
|
||||
[test_bug918719.html]
|
||||
[test_bug927901.html]
|
||||
[test_devicemotion_multiple_listeners.html]
|
||||
skip-if = toolkit == 'android' #bug 775227
|
||||
|
89
dom/tests/mochitest/bugs/test_bug918719.html
Normal file
89
dom/tests/mochitest/bugs/test_bug918719.html
Normal file
@ -0,0 +1,89 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=918719
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 918719</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=918719">Mozilla Bug 918719</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const SERVER_URL = "bug918719.sjs";
|
||||
|
||||
function sendCommand(cmd) {
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("get", SERVER_URL + "?" + cmd);
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
// Manipulate one in-flight XHR using secondary command XHRs, to guarantee
|
||||
// that multiple OnDataAvailable events are triggered (which are where
|
||||
// LOADING readystatechanges are triggered). We return a promise that will
|
||||
// resolve with a count of the number of LOADING events that were detected.
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let xhr = new XMLHttpRequest();
|
||||
let numProgressEvents = 0;
|
||||
let numLoadingEvents = 0;
|
||||
|
||||
xhr.onreadystatechange = e => {
|
||||
if (xhr.readyState === xhr.LOADING) {
|
||||
++numLoadingEvents;
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onprogress = e => {
|
||||
if (++numProgressEvents < 2) {
|
||||
sendCommand("more");
|
||||
} else {
|
||||
sendCommand("done");
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = e => {
|
||||
reject(e);
|
||||
};
|
||||
|
||||
xhr.onloadend = e => {
|
||||
resolve(numLoadingEvents);
|
||||
};
|
||||
|
||||
xhr.open("GET", SERVER_URL);
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
|
||||
function prefChangePromise(args) {
|
||||
return new Promise(function(resolve) {
|
||||
SpecialPowers.pushPrefEnv(args, resolve);
|
||||
});
|
||||
}
|
||||
|
||||
runTest().then(function(count) {
|
||||
ok(count === 1, "Only one loading readystatechange event should have been fired with the pref off.");
|
||||
}).then(function() {
|
||||
return prefChangePromise({"set": [["dom.fire_extra_xhr_loading_readystatechanges", true]]});
|
||||
}).then(function() {
|
||||
return runTest();
|
||||
}).then(function(count) {
|
||||
ok(count > 1, "Multiple loading readystatechange events should have been fired with the pref on.");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -169,6 +169,7 @@ XMLHttpRequestMainThread::XMLHttpRequestMainThread()
|
||||
mFlagSyncLooping(false), mFlagBackgroundRequest(false),
|
||||
mFlagHadUploadListenersOnSend(false), mFlagACwithCredentials(false),
|
||||
mFlagTimedOut(false), mFlagDeleted(false), mFlagSend(false),
|
||||
mSendExtraLoadingEvents(Preferences::GetBool("dom.fire_extra_xhr_loading_readystatechanges", true)),
|
||||
mUploadTransferred(0), mUploadTotal(0), mUploadComplete(true),
|
||||
mProgressSinceLastProgressEvent(false),
|
||||
mRequestSentTime(0), mTimeoutMilliseconds(0),
|
||||
@ -1731,7 +1732,9 @@ XMLHttpRequestMainThread::OnDataAvailable(nsIRequest *request,
|
||||
|
||||
mDataAvailable += totalRead;
|
||||
|
||||
ChangeState(State::loading);
|
||||
if (mState == State::headers_received || mSendExtraLoadingEvents) {
|
||||
ChangeState(State::loading);
|
||||
}
|
||||
|
||||
if (!mFlagSynchronous && !mProgressTimerIsActive) {
|
||||
StartProgressEventTimer();
|
||||
|
@ -703,6 +703,14 @@ protected:
|
||||
// late, and ensure the XHR only handles one in-flight request at once.
|
||||
bool mFlagSend;
|
||||
|
||||
// Before ProgressEvents were a thing, multiple readystatechange events were
|
||||
// fired during the loading state to give sites a way to monitor XHR progress.
|
||||
// The XHR spec now has proper progress events and dictates that only one
|
||||
// "loading" readystatechange should be fired per send. However, it's possible
|
||||
// that some content still relies on this old behavior, so we're keeping it
|
||||
// (behind a preference) for now. See bug 918719.
|
||||
bool mSendExtraLoadingEvents;
|
||||
|
||||
RefPtr<XMLHttpRequestUpload> mUpload;
|
||||
int64_t mUploadTransferred;
|
||||
int64_t mUploadTotal;
|
||||
|
@ -5076,6 +5076,10 @@ pref("dom.voicemail.defaultServiceId", 0);
|
||||
// Enable mapped array buffer by default.
|
||||
pref("dom.mapped_arraybuffer.enabled", true);
|
||||
|
||||
// Whether to send more than one "loading" readystatechange during XHRs to
|
||||
// simulate progress events for sites still not using modern progress events.
|
||||
pref("dom.fire_extra_xhr_loading_readystatechanges", false);
|
||||
|
||||
// The tables used for Safebrowsing phishing and malware checks.
|
||||
pref("urlclassifier.malwareTable", "goog-malware-shavar,goog-unwanted-shavar,test-malware-simple,test-unwanted-simple");
|
||||
|
||||
|
@ -1,5 +0,0 @@
|
||||
[event-readystatechange-loaded.htm]
|
||||
type: testharness
|
||||
[XMLHttpRequest: the LOADING state change should only happen once]
|
||||
expected: FAIL
|
||||
|
Loading…
x
Reference in New Issue
Block a user