"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 ` `; } 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(); }