1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
// In an SJS file we need to get NetUtil ourselves, despite
// what eslint might think applies for browser tests.
// eslint-disable-next-line mozilla/no-redeclare-with-import-autofix
let { NetUtil } = ChromeUtils.importESModule(
"resource://gre/modules/NetUtil.sys.mjs"
);
const RELATIVE_PATH = "browser/toolkit/mozapps/extensions/test/xpinstall";
const NOTIFICATION_TOPIC = "slowinstall-complete";
/**
* Helper function to create a JS object representing the url parameters from
* the request's queryString.
*
* @param aQueryString
* The request's query string.
* @return A JS object representing the url parameters from the request's
* queryString.
*/
function parseQueryString(aQueryString) {
var paramArray = aQueryString.split("&");
var regex = /^([^=]+)=(.*)$/;
var params = {};
for (var i = 0, sz = paramArray.length; i < sz; i++) {
var match = regex.exec(paramArray[i]);
if (!match) {
throw new Error("Bad parameter in queryString! '" + paramArray[i] + "'");
}
params[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
}
return params;
}
function handleRequest(aRequest, aResponse) {
let id = +getState("ID");
setState("ID", "" + (id + 1));
function LOG(str) {
dump("slowinstall.sjs[" + id + "]: " + str + "\n");
}
aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
var params = {};
if (aRequest.queryString) {
params = parseQueryString(aRequest.queryString);
}
if (params.file) {
let xpiFile = "";
function complete_download() {
LOG("Completing download");
try {
// Doesn't seem to be a sane way to read using IOUtils and write to an
// nsIOutputStream so here we are.
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
file.initWithPath(xpiFile);
let stream = Cc[
"@mozilla.org/network/file-input-stream;1"
].createInstance(Ci.nsIFileInputStream);
stream.init(file, -1, -1, stream.DEFER_OPEN + stream.CLOSE_ON_EOF);
NetUtil.asyncCopy(stream, aResponse.bodyOutputStream, () => {
LOG("Download complete");
aResponse.finish();
});
} catch (e) {
LOG("Exception " + e);
}
}
let waitForComplete = new Promise(resolve => {
function complete() {
Services.obs.removeObserver(complete, NOTIFICATION_TOPIC);
resolve();
}
Services.obs.addObserver(complete, NOTIFICATION_TOPIC);
});
aResponse.processAsync();
const dir = Services.dirsvc.get("CurWorkD", Ci.nsIFile).path;
xpiFile = PathUtils.join(dir, ...RELATIVE_PATH.split("/"), params.file);
LOG("Starting slow download of " + xpiFile);
IOUtils.stat(xpiFile).then(info => {
aResponse.setHeader("Content-Type", "binary/octet-stream");
aResponse.setHeader("Content-Length", info.size.toString());
LOG("Download paused");
waitForComplete.then(complete_download);
});
} else if (params.continue) {
dump(
"slowinstall.sjs: Received signal to complete all current downloads.\n"
);
Services.obs.notifyObservers(null, NOTIFICATION_TOPIC);
}
}
|