3 const { HttpServer
} = ChromeUtils
.importESModule(
4 "resource://testing-common/httpd.sys.mjs"
7 let httpServerIPv4
= new HttpServer();
8 let httpServerIPv6
= new HttpServer();
10 let testpath
= "/simple";
11 let httpbody
= "0123456789";
12 let CC_IPV4
= "example_cc_ipv4.com";
13 let CC_IPV6
= "example_cc_ipv6.com";
14 Services
.prefs
.clearUserPref("network.dns.native-is-localhost");
16 ChromeUtils
.defineLazyGetter(this, "URL_CC_IPV4", function () {
17 return `http://${CC_IPV4}:${httpServerIPv4.identity.primaryPort}${testpath}`;
19 ChromeUtils
.defineLazyGetter(this, "URL_CC_IPV6", function () {
20 return `http://${CC_IPV6}:${httpServerIPv6.identity.primaryPort}${testpath}`;
22 ChromeUtils
.defineLazyGetter(this, "URL6a", function () {
23 return `http://example6a.com:${httpServerIPv6.identity.primaryPort}${testpath}`;
25 ChromeUtils
.defineLazyGetter(this, "URL6b", function () {
26 return `http://example6b.com:${httpServerIPv6.identity.primaryPort}${testpath}`;
30 "@mozilla.org/network/network-connectivity-service;1"
31 ].getService(Ci
.nsINetworkConnectivityService
);
32 const { TestUtils
} = ChromeUtils
.importESModule(
33 "resource://testing-common/TestUtils.sys.mjs"
36 registerCleanupFunction(async () => {
37 Services
.prefs
.clearUserPref("network.http.speculative-parallel-limit");
38 Services
.prefs
.clearUserPref("network.captive-portal-service.testMode");
39 Services
.prefs
.clearUserPref("network.connectivity-service.IPv6.url");
40 Services
.prefs
.clearUserPref("network.connectivity-service.IPv4.url");
41 Services
.prefs
.clearUserPref("network.dns.localDomains");
44 await httpServerIPv4
.stop();
45 await httpServerIPv6
.stop();
46 await trrServer
.stop();
49 function makeChan(url
) {
50 let chan
= NetUtil
.newChannel({
52 loadUsingSystemPrincipal
: true,
53 }).QueryInterface(Ci
.nsIHttpChannel
);
54 chan
.loadFlags
|= Ci
.nsIRequest
.LOAD_BYPASS_CACHE
;
55 chan
.loadFlags
|= Ci
.nsIRequest
.INHIBIT_CACHING
;
56 chan
.setTRRMode(Ci
.nsIRequest
.TRR_DEFAULT_MODE
);
60 function serverHandler(metadata
, response
) {
61 response
.setHeader("Content-Type", "text/plain", false);
62 response
.bodyOutputStream
.write(httpbody
, httpbody
.length
);
65 add_task(async
function test_setup() {
66 httpServerIPv4
.registerPathHandler(testpath
, serverHandler
);
67 httpServerIPv4
.start(-1);
68 httpServerIPv6
.registerPathHandler(testpath
, serverHandler
);
69 httpServerIPv6
.start_ipv6(-1);
70 Services
.prefs
.setCharPref(
71 "network.dns.localDomains",
72 `foo.example.com, ${CC_IPV4}, ${CC_IPV6}`
75 trrServer
= new TRRServer();
76 await trrServer
.start();
78 if (mozinfo
.socketprocess_networking
) {
79 Services
.dns
; // Needed to trigger socket process.
80 await TestUtils
.waitForCondition(() => Services
.io
.socketProcessLaunched
);
83 Services
.prefs
.setIntPref("network.trr.mode", 3);
84 Services
.prefs
.setCharPref(
86 `https://foo.example.com:${trrServer.port()}/dns-query`
89 await
registerDoHAnswers(true, true);
92 async
function registerDoHAnswers(ipv4
, ipv6
) {
93 let hosts
= ["example6a.com", "example6b.com"];
94 for (const host
of hosts
) {
107 await trrServer
.registerDoHAnswers(host
, "A", {
108 answers
: ipv4answers
,
111 let ipv6answers
= [];
124 await trrServer
.registerDoHAnswers(host
, "AAAA", {
125 answers
: ipv6answers
,
129 Services
.dns
.clearCache(true);
132 let StatusCounter = function () {
133 this._statusCount
= {};
135 StatusCounter
.prototype = {
136 QueryInterface
: ChromeUtils
.generateQI([
137 "nsIInterfaceRequestor",
138 "nsIProgressEventSink",
142 return this.QueryInterface(iid
);
146 onStatus(request
, status
) {
147 this._statusCount
[status
] = 1 + (this._statusCount
[status
] || 0);
151 let HttpListener = function (finish
, succeeded
) {
152 this.finish
= finish
;
153 this.succeeded
= succeeded
;
156 HttpListener
.prototype = {
157 onStartRequest
: function testOnStartRequest() {},
159 onDataAvailable
: function testOnDataAvailable(request
, stream
, off
, cnt
) {
160 read_stream(stream
, cnt
);
163 onStopRequest
: function testOnStopRequest(request
, status
) {
164 equal(this.succeeded
, status
== Cr
.NS_OK
);
169 function promiseObserverNotification(aTopic
, matchFunc
) {
170 return new Promise(resolve
=> {
171 Services
.obs
.addObserver(function observe(subject
, topic
, data
) {
172 let matches
= typeof matchFunc
!= "function" || matchFunc(subject
, data
);
176 Services
.obs
.removeObserver(observe
, topic
);
177 resolve({ subject
, data
});
182 async
function make_request(uri
, check_events
, succeeded
) {
183 let chan
= makeChan(uri
);
184 let statusCounter
= new StatusCounter();
185 chan
.notificationCallbacks
= statusCounter
;
186 await
new Promise(resolve
=>
187 chan
.asyncOpen(new HttpListener(resolve
, succeeded
))
192 statusCounter
._statusCount
[0x4b000b] || 0,
194 "Expecting only one instance of NS_NET_STATUS_RESOLVED_HOST"
197 statusCounter
._statusCount
[0x4b0007] || 0,
199 "Expecting only one instance of NS_NET_STATUS_CONNECTING_TO"
204 async
function setup_connectivity(ipv6
, ipv4
) {
205 Services
.prefs
.setBoolPref("network.captive-portal-service.testMode", true);
208 Services
.prefs
.setCharPref(
209 "network.connectivity-service.IPv6.url",
210 URL_CC_IPV6
+ testpath
213 Services
.prefs
.setCharPref(
214 "network.connectivity-service.IPv6.url",
215 "http://donotexist.example.com"
220 Services
.prefs
.setCharPref(
221 "network.connectivity-service.IPv4.url",
222 URL_CC_IPV4
+ testpath
225 Services
.prefs
.setCharPref(
226 "network.connectivity-service.IPv4.url",
227 "http://donotexist.example.com"
231 let topic
= "network:connectivity-service:ip-checks-complete";
232 if (mozinfo
.socketprocess_networking
) {
233 topic
+= "-from-socket-process";
235 let observerNotification
= promiseObserverNotification(topic
);
236 ncs
.recheckIPConnectivity();
237 await observerNotification
;
242 Ci
.nsINetworkConnectivityService
.NOT_AVAILABLE
,
246 equal(ncs
.IPv6
, Ci
.nsINetworkConnectivityService
.OK
, "Check IPv6 support");
252 Ci
.nsINetworkConnectivityService
.NOT_AVAILABLE
,
256 equal(ncs
.IPv4
, Ci
.nsINetworkConnectivityService
.OK
, "Check IPv4 support");
260 // This test that we retry to connect using IPv4 when IPv6 connecivity is not
261 // present, but a ConnectionEntry have IPv6 prefered set.
262 // Speculative connections are disabled.
263 add_task(async
function test_prefer_address_version_fail_trr3_1() {
264 Services
.prefs
.setIntPref("network.http.speculative-parallel-limit", 0);
265 await
registerDoHAnswers(true, true);
267 // Make a request to setup the address version preference to a ConnectionEntry.
268 await
make_request(URL6a
, true, true);
270 // connect again using the address version preference from the ConnectionEntry.
271 await
make_request(URL6a
, true, true);
273 // Make IPv6 connectivity check fail
274 await
setup_connectivity(false, true);
276 Services
.dns
.clearCache(true);
278 // This will succeed as we query both DNS records
279 await
make_request(URL6a
, true, true);
281 // Now make the DNS server only return IPv4 records
282 await
registerDoHAnswers(true, false);
283 // This will fail, because the server is not lisenting to IPv4 address as well,
284 // We should still get NS_NET_STATUS_RESOLVED_HOST and
285 // NS_NET_STATUS_CONNECTING_TO notification.
286 await
make_request(URL6a
, true, false);
288 // Make IPv6 connectivity check succeed again
289 await
setup_connectivity(true, true);
292 // This test that we retry to connect using IPv4 when IPv6 connecivity is not
293 // present, but a ConnectionEntry have IPv6 prefered set.
294 // Speculative connections are enabled.
295 add_task(async
function test_prefer_address_version_fail_trr3_2() {
296 Services
.prefs
.setIntPref("network.http.speculative-parallel-limit", 6);
297 await
registerDoHAnswers(true, true);
299 // Make a request to setup the address version preference to a ConnectionEntry.
300 await
make_request(URL6b
, false, true);
302 // connect again using the address version preference from the ConnectionEntry.
303 await
make_request(URL6b
, false, true);
305 // Make IPv6 connectivity check fail
306 await
setup_connectivity(false, true);
308 Services
.dns
.clearCache(true);
310 // This will succeed as we query both DNS records
311 await
make_request(URL6b
, false, true);
313 // Now make the DNS server only return IPv4 records
314 await
registerDoHAnswers(true, false);
315 // This will fail, because the server is not lisenting to IPv4 address as well,
316 // We should still get NS_NET_STATUS_RESOLVED_HOST and
317 // NS_NET_STATUS_CONNECTING_TO notification.
318 await
make_request(URL6b
, true, false);