149 lines
4.6 KiB
JavaScript
149 lines
4.6 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
"use strict";
|
|
|
|
/* import-globals-from head_cache.js */
|
|
/* import-globals-from head_cookies.js */
|
|
/* import-globals-from head_channels.js */
|
|
/* import-globals-from head_servers.js */
|
|
|
|
const gDashboard = Cc["@mozilla.org/network/dashboard;1"].getService(
|
|
Ci.nsIDashboard
|
|
);
|
|
|
|
const { TestUtils } = ChromeUtils.importESModule(
|
|
"resource://testing-common/TestUtils.sys.mjs"
|
|
);
|
|
|
|
function makeChan(uri) {
|
|
let chan = NetUtil.newChannel({
|
|
uri,
|
|
loadUsingSystemPrincipal: true,
|
|
}).QueryInterface(Ci.nsIHttpChannel);
|
|
chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
|
|
return chan;
|
|
}
|
|
|
|
function channelOpenPromise(chan, flags) {
|
|
return new Promise(resolve => {
|
|
function finish(req, buffer) {
|
|
resolve([req, buffer]);
|
|
}
|
|
chan.asyncOpen(new ChannelListener(finish, null, flags));
|
|
});
|
|
}
|
|
|
|
async function registerSimplePathHandler(server, path) {
|
|
return server.registerPathHandler(path, (req, resp) => {
|
|
resp.writeHead(200);
|
|
resp.end("done");
|
|
});
|
|
}
|
|
|
|
add_task(async function test_verify_traffic_for_http2() {
|
|
Services.prefs.setBoolPref(
|
|
"network.http.http2.move_to_pending_list_after_network_change",
|
|
true
|
|
);
|
|
|
|
// Bug 1878505: It seems when HTTPS RR is enabled, a speculative
|
|
// connection that waits to receive a HTTPS response will receive it
|
|
// after the actual connection is established, leading to an extra
|
|
// connection being established.
|
|
Services.prefs.setIntPref("network.http.speculative-parallel-limit", 0);
|
|
|
|
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
|
|
Ci.nsIX509CertDB
|
|
);
|
|
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
|
|
|
|
let server = new NodeHTTP2Server();
|
|
await server.start();
|
|
registerCleanupFunction(async () => {
|
|
Services.prefs.clearUserPref(
|
|
"network.http.http2.move_to_pending_list_after_network_change"
|
|
);
|
|
await server.stop();
|
|
});
|
|
|
|
try {
|
|
await server.registerPathHandler("/longDelay", (req, resp) => {
|
|
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout, no-undef
|
|
setTimeout(function () {
|
|
resp.writeHead(200);
|
|
resp.end("done");
|
|
}, 8000);
|
|
});
|
|
} catch (e) {}
|
|
|
|
await registerSimplePathHandler(server, "/test");
|
|
|
|
// Send some requests and check if we have only one h2 session.
|
|
for (let i = 0; i < 2; i++) {
|
|
let chan = makeChan(`https://localhost:${server.port()}/test`);
|
|
await channelOpenPromise(chan, CL_ALLOW_UNKNOWN_CL);
|
|
}
|
|
let sessionCount = await server.sessionCount();
|
|
Assert.equal(sessionCount, 1);
|
|
|
|
let res = await new Promise(resolve => {
|
|
// Create a request that takes 8s to finish.
|
|
let chan = makeChan(`https://localhost:${server.port()}/longDelay`);
|
|
chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
|
|
|
|
// Send a network change event to trigger VerifyTraffic(). After this,
|
|
// the connnection will be put in the pending list.
|
|
// We'll crate a new connection for the new request.
|
|
Services.obs.notifyObservers(
|
|
null,
|
|
"network:link-status-changed",
|
|
"changed"
|
|
);
|
|
|
|
// This request will use the new connection.
|
|
let chan1 = makeChan(`https://localhost:${server.port()}/test`);
|
|
chan1.asyncOpen(new ChannelListener(() => {}, null, CL_ALLOW_UNKNOWN_CL));
|
|
});
|
|
|
|
// The connection in the pending list should be still working.
|
|
Assert.equal(res.status, Cr.NS_OK);
|
|
Assert.equal(res.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
|
|
|
|
sessionCount = await server.sessionCount();
|
|
Assert.equal(sessionCount, 2);
|
|
|
|
// Create another request and trigger the network change event again.
|
|
// The second network change event is to put the second connection into the
|
|
// pending list.
|
|
res = await new Promise(resolve => {
|
|
// Create a request that takes 8s to finish.
|
|
let chan = makeChan(`https://localhost:${server.port()}/longDelay`);
|
|
chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
|
|
|
|
Services.obs.notifyObservers(
|
|
null,
|
|
"network:link-status-changed",
|
|
"changed"
|
|
);
|
|
});
|
|
|
|
Assert.equal(res.status, Cr.NS_OK);
|
|
Assert.equal(res.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
|
|
|
|
async function getSocketCount() {
|
|
return new Promise(resolve => {
|
|
gDashboard.requestSockets(function (data) {
|
|
resolve(data.sockets.length);
|
|
});
|
|
});
|
|
}
|
|
|
|
await TestUtils.waitForCondition(async () => {
|
|
const socketCount = await getSocketCount();
|
|
return socketCount === 0;
|
|
}, "Socket count should be 0");
|
|
|
|
await server.stop();
|
|
});
|