1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* import-globals-from head_cache.js */
8 /* import-globals-from head_cookies.js */
9 /* import-globals-from head_channels.js */
10 /* import-globals-from head_servers.js */
12 const gDashboard
= Cc
["@mozilla.org/network/dashboard;1"].getService(
16 const { TestUtils
} = ChromeUtils
.importESModule(
17 "resource://testing-common/TestUtils.sys.mjs"
20 function makeChan(uri
) {
21 let chan
= NetUtil
.newChannel({
23 loadUsingSystemPrincipal
: true,
24 }).QueryInterface(Ci
.nsIHttpChannel
);
25 chan
.loadFlags
= Ci
.nsIChannel
.LOAD_INITIAL_DOCUMENT_URI
;
29 function channelOpenPromise(chan
, flags
) {
30 return new Promise(resolve
=> {
31 function finish(req
, buffer
) {
32 resolve([req
, buffer
]);
34 chan
.asyncOpen(new ChannelListener(finish
, null, flags
));
38 async
function registerSimplePathHandler(server
, path
) {
39 return server
.registerPathHandler(path
, (req
, resp
) => {
45 add_task(async
function test_verify_traffic_for_http2() {
46 Services
.prefs
.setBoolPref(
47 "network.http.http2.move_to_pending_list_after_network_change",
51 // Bug 1878505: It seems when HTTPS RR is enabled, a speculative
52 // connection that waits to receive a HTTPS response will receive it
53 // after the actual connection is established, leading to an extra
54 // connection being established.
55 Services
.prefs
.setIntPref("network.http.speculative-parallel-limit", 0);
57 let certdb
= Cc
["@mozilla.org/security/x509certdb;1"].getService(
60 addCertFromFile(certdb
, "http2-ca.pem", "CTu,u,u");
62 let server
= new NodeHTTP2Server();
64 registerCleanupFunction(async () => {
65 Services
.prefs
.clearUserPref(
66 "network.http.http2.move_to_pending_list_after_network_change"
72 await server
.registerPathHandler("/longDelay", (req
, resp
) => {
73 // eslint-disable-next-line mozilla/no-arbitrary-setTimeout, no-undef
74 setTimeout(function () {
81 await
registerSimplePathHandler(server
, "/test");
83 // Send some requests and check if we have only one h2 session.
84 for (let i
= 0; i
< 2; i
++) {
85 let chan
= makeChan(`https://localhost:${server.port()}/test`);
86 await
channelOpenPromise(chan
, CL_ALLOW_UNKNOWN_CL
);
88 let sessionCount
= await server
.sessionCount();
89 Assert
.equal(sessionCount
, 1);
91 let res
= await
new Promise(resolve
=> {
92 // Create a request that takes 8s to finish.
93 let chan
= makeChan(`https://localhost:${server.port()}/longDelay`);
94 chan
.asyncOpen(new ChannelListener(resolve
, null, CL_ALLOW_UNKNOWN_CL
));
96 // Send a network change event to trigger VerifyTraffic(). After this,
97 // the connnection will be put in the pending list.
98 // We'll crate a new connection for the new request.
99 Services
.obs
.notifyObservers(
101 "network:link-status-changed",
105 // This request will use the new connection.
106 let chan1
= makeChan(`https://localhost:${server.port()}/test`);
107 chan1
.asyncOpen(new ChannelListener(() => {}, null, CL_ALLOW_UNKNOWN_CL
));
110 // The connection in the pending list should be still working.
111 Assert
.equal(res
.status
, Cr
.NS_OK
);
112 Assert
.equal(res
.QueryInterface(Ci
.nsIHttpChannel
).responseStatus
, 200);
114 sessionCount
= await server
.sessionCount();
115 Assert
.equal(sessionCount
, 2);
117 // Create another request and trigger the network change event again.
118 // The second network change event is to put the second connection into the
120 res
= await
new Promise(resolve
=> {
121 // Create a request that takes 8s to finish.
122 let chan
= makeChan(`https://localhost:${server.port()}/longDelay`);
123 chan
.asyncOpen(new ChannelListener(resolve
, null, CL_ALLOW_UNKNOWN_CL
));
125 Services
.obs
.notifyObservers(
127 "network:link-status-changed",
132 Assert
.equal(res
.status
, Cr
.NS_OK
);
133 Assert
.equal(res
.QueryInterface(Ci
.nsIHttpChannel
).responseStatus
, 200);
135 async
function getSocketCount() {
136 return new Promise(resolve
=> {
137 gDashboard
.requestSockets(function (data
) {
138 resolve(data
.sockets
.length
);
143 await TestUtils
.waitForCondition(async () => {
144 const socketCount
= await
getSocketCount();
145 return socketCount
=== 0;
146 }, "Socket count should be 0");