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 var { setTimeout
} = ChromeUtils
.importESModule(
8 "resource://gre/modules/Timer.sys.mjs"
10 const mockNetwork
= Cc
[
11 "@mozilla.org/network/mock-network-controller;1"
12 ].getService(Ci
.nsIMockNetworkLayerController
);
16 const certOverrideService
= Cc
[
17 "@mozilla.org/security/certoverride;1"
18 ].getService(Ci
.nsICertOverrideService
);
21 h3Port
= Services
.env
.get("MOZHTTP3_PORT");
22 Assert
.notEqual(h3Port
, null);
23 Assert
.notEqual(h3Port
, "");
24 Services
.prefs
.setBoolPref("network.socket.attach_mock_network_layer", true);
28 registerCleanupFunction(async () => {
29 Services
.prefs
.clearUserPref("network.dns.upgrade_with_https_rr");
30 Services
.prefs
.clearUserPref("network.dns.use_https_rr_as_altsvc");
31 Services
.prefs
.clearUserPref("network.dns.echconfig.enabled");
32 Services
.prefs
.clearUserPref(
33 "network.dns.echconfig.fallback_to_origin_when_all_failed"
35 Services
.prefs
.clearUserPref("network.dns.httpssvc.reset_exclustion_list");
36 Services
.prefs
.clearUserPref("network.http.http3.enable");
37 Services
.prefs
.clearUserPref(
38 "network.dns.httpssvc.http3_fast_fallback_timeout"
40 Services
.prefs
.clearUserPref(
41 "network.http.http3.alt-svc-mapping-for-testing"
43 Services
.prefs
.clearUserPref("network.dns.localDomains");
44 Services
.prefs
.clearUserPref("network.http.http3.use_nspr_for_io");
45 Services
.prefs
.clearUserPref("network.dns.preferIPv6");
46 Services
.prefs
.clearUserPref(
47 "network.http.move_to_pending_list_after_network_change"
51 function makeChan(url
) {
52 let chan
= NetUtil
.newChannel({
54 loadUsingSystemPrincipal
: true,
55 contentPolicyType
: Ci
.nsIContentPolicy
.TYPE_DOCUMENT
,
56 }).QueryInterface(Ci
.nsIHttpChannel
);
57 chan
.loadFlags
= Ci
.nsIChannel
.LOAD_INITIAL_DOCUMENT_URI
;
61 function channelOpenPromise(chan
, flags
) {
62 return new Promise(resolve
=> {
63 function finish(req
, buffer
) {
64 resolve([req
, buffer
]);
65 certOverrideService
.setDisableAllSecurityChecksAndLetAttackersInterceptMyData(
69 certOverrideService
.setDisableAllSecurityChecksAndLetAttackersInterceptMyData(
72 chan
.asyncOpen(new ChannelListener(finish
, null, flags
));
76 // Test the failure of an HTTP/3 connection when a network change occurs,
77 // specifically ensuring that blocking UDP I/O leads to the expected
78 // connection failure.
79 add_task(async
function test_h3_with_network_change_fail() {
80 Services
.prefs
.setBoolPref("network.http.http3.use_nspr_for_io", true);
81 Services
.prefs
.setBoolPref(
82 "network.http.move_to_pending_list_after_network_change",
85 await
http3_setup_tests("h3");
87 let chan
= makeChan(`https://foo.example.com:${h3Port}`);
88 let [req
] = await
channelOpenPromise(chan
, CL_ALLOW_UNKNOWN_CL
);
89 req
.QueryInterface(Ci
.nsIHttpChannel
);
90 Assert
.equal(req
.protocolVersion
, "h3");
92 // Blocking the UDP I/O to simulate a network change.
93 let addr
= mockNetwork
.createScriptableNetAddr("127.0.0.1", h3Port
);
94 mockNetwork
.blockUDPAddrIO(addr
);
95 registerCleanupFunction(async () => {
96 mockNetwork
.clearBlockedUDPAddr();
99 Services
.obs
.notifyObservers(null, "network:link-status-changed", "changed");
100 // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
101 await
new Promise(resolve
=> setTimeout(resolve
, 1000));
103 // This request will fail because the HTTP/3 connection is reused.
104 chan
= makeChan(`https://foo.example.com:${h3Port}`);
105 [req
] = await
channelOpenPromise(chan
, CL_EXPECT_FAILURE
);
108 add_task(async
function test_h3_with_network_change_success() {
109 Services
.prefs
.setBoolPref("network.http.http3.use_nspr_for_io", true);
110 Services
.prefs
.setBoolPref(
111 "network.http.move_to_pending_list_after_network_change",
115 h3Port
= await
create_h3_server();
116 Services
.prefs
.setCharPref(
117 "network.http.http3.alt-svc-mapping-for-testing",
118 `foo.example.com;h3=:${h3Port}`
121 let chan
= makeChan(`https://foo.example.com:${h3Port}`);
122 let [req
] = await
channelOpenPromise(chan
, CL_ALLOW_UNKNOWN_CL
);
123 req
.QueryInterface(Ci
.nsIHttpChannel
);
124 Assert
.equal(req
.protocolVersion
, "h3");
126 let addr
= mockNetwork
.createScriptableNetAddr("127.0.0.1", h3Port
);
127 mockNetwork
.blockUDPAddrIO(addr
);
128 registerCleanupFunction(async () => {
129 mockNetwork
.clearBlockedUDPAddr();
132 Services
.obs
.notifyObservers(null, "network:link-status-changed", "changed");
133 // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
134 await
new Promise(resolve
=> setTimeout(resolve
, 1000));
136 // Make sure the host name can be resolved to an IPv6 address, since
137 // 127.0.0.1 is blocked.
138 Services
.prefs
.setBoolPref("network.dns.preferIPv6", true);
139 Services
.prefs
.setBoolPref("network.dns.disableIPv6", false);
140 Services
.dns
.clearCache(true);
142 chan
= makeChan(`https://foo.example.com:${h3Port}`);
143 [req
] = await
channelOpenPromise(chan
, CL_ALLOW_UNKNOWN_CL
);
144 Assert
.equal(req
.protocolVersion
, "h3");