summaryrefslogtreecommitdiffstats
path: root/docshell/test/mochitest/file_bug1747033.sjs
diff options
context:
space:
mode:
Diffstat (limited to 'docshell/test/mochitest/file_bug1747033.sjs')
-rw-r--r--docshell/test/mochitest/file_bug1747033.sjs110
1 files changed, 110 insertions, 0 deletions
diff --git a/docshell/test/mochitest/file_bug1747033.sjs b/docshell/test/mochitest/file_bug1747033.sjs
new file mode 100644
index 0000000000..14401101b2
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1747033.sjs
@@ -0,0 +1,110 @@
+"use strict";
+
+const BOUNDARY = "BOUNDARY";
+
+// waitForPageShow should be false if this is for multipart/x-mixed-replace
+// and it's not the last part, Gecko doesn't fire pageshow for those parts.
+function documentString(waitForPageShow = true) {
+ return `<html>
+ <head>
+ <script>
+ let bc = new BroadcastChannel("bug1747033");
+ bc.addEventListener("message", ({ data: { cmd, arg = undefined } }) => {
+ switch (cmd) {
+ case "load":
+ location.href = arg;
+ break;
+ case "replaceState":
+ history.replaceState({}, "Replaced state", arg);
+ bc.postMessage({ "historyLength": history.length, "location": location.href });
+ break;
+ case "back":
+ history.back();
+ break;
+ case "close":
+ close();
+ break;
+ }
+ });
+
+ function reply() {
+ bc.postMessage({ "historyLength": history.length, "location": location.href });
+ }
+
+ ${waitForPageShow ? `addEventListener("pageshow", reply);` : "reply();"}
+ </script>
+ </head>
+ <body></body>
+</html>
+`;
+}
+
+function boundary(last = false) {
+ let b = `--${BOUNDARY}`;
+ if (last) {
+ b += "--";
+ }
+ return b + "\n";
+}
+
+function sendMultipart(response, last = false) {
+ setState("sendMore", "");
+
+ response.write(`Content-Type: text/html
+
+${documentString(last)}
+`);
+ response.write(boundary(last));
+}
+
+function shouldSendMore() {
+ return new Promise(resolve => {
+ let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ timer.initWithCallback(
+ () => {
+ let sendMore = getState("sendMore");
+ if (sendMore !== "") {
+ timer.cancel();
+ resolve(sendMore);
+ }
+ },
+ 100,
+ Ci.nsITimer.TYPE_REPEATING_SLACK
+ );
+ });
+}
+
+async function handleRequest(request, response) {
+ if (request.queryString == "") {
+ // This is for non-multipart/x-mixed-replace loads.
+ response.write(documentString());
+ return;
+ }
+
+ if (request.queryString == "sendNextPart") {
+ setState("sendMore", "next");
+ return;
+ }
+
+ if (request.queryString == "sendLastPart") {
+ setState("sendMore", "last");
+ return;
+ }
+
+ response.processAsync();
+
+ response.setHeader(
+ "Content-Type",
+ `multipart/x-mixed-replace; boundary=${BOUNDARY}`,
+ false
+ );
+ response.setStatusLine(request.httpVersion, 200, "OK");
+
+ response.write(boundary());
+ sendMultipart(response);
+ while ((await shouldSendMore("sendMore")) !== "last") {
+ sendMultipart(response);
+ }
+ sendMultipart(response, true);
+ response.finish();
+}