Bug 1931425 - Limit how often moz-label's #setStyles runs r=reusable-components-revie...
[gecko.git] / netwerk / test / unit / test_dooh.js
blobd422bac5e9bab8ddfa6ac76e6c05f632670e0fff
1 /* Any copyright is dedicated to the Public Domain.
2 * https://creativecommons.org/publicdomain/zero/1.0/ */
4 "use strict";
6 /* import-globals-from trr_common.js */
8 const { setTimeout } = ChromeUtils.importESModule(
9 "resource://gre/modules/Timer.sys.mjs"
12 let httpServer;
13 let ohttpServer;
14 let ohttpEncodedConfig = "not a valid config";
16 // Decapsulate the request, send it to the actual TRR, receive the response,
17 // encapsulate it, and send it back through `response`.
18 async function forwardToTRR(request, response) {
19 let inputStream = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
20 Ci.nsIScriptableInputStream
22 inputStream.init(request.bodyInputStream);
23 let requestBody = inputStream.readBytes(inputStream.available());
24 let ohttpResponse = ohttpServer.decapsulate(stringToBytes(requestBody));
25 let bhttp = Cc["@mozilla.org/network/binary-http;1"].getService(
26 Ci.nsIBinaryHttp
28 let decodedRequest = bhttp.decodeRequest(ohttpResponse.request);
29 let headers = {};
30 for (
31 let i = 0;
32 i < decodedRequest.headerNames.length && decodedRequest.headerValues.length;
33 i++
34 ) {
35 headers[decodedRequest.headerNames[i]] = decodedRequest.headerValues[i];
37 let uri = `${decodedRequest.scheme}://${decodedRequest.authority}${decodedRequest.path}`;
38 let body = new Uint8Array(decodedRequest.content.length);
39 for (let i = 0; i < decodedRequest.content.length; i++) {
40 body[i] = decodedRequest.content[i];
42 try {
43 // Timeout after 10 seconds.
44 let fetchInProgress = true;
45 let controller = new AbortController();
46 // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
47 setTimeout(() => {
48 if (fetchInProgress) {
49 controller.abort();
51 }, 10000);
52 let trrResponse = await fetch(uri, {
53 method: decodedRequest.method,
54 headers,
55 body: decodedRequest.method == "POST" ? body : undefined,
56 credentials: "omit",
57 signal: controller.signal,
58 });
59 fetchInProgress = false;
60 let data = new Uint8Array(await trrResponse.arrayBuffer());
61 let trrResponseContent = [];
62 for (let i = 0; i < data.length; i++) {
63 trrResponseContent.push(data[i]);
65 let trrResponseHeaderNames = [];
66 let trrResponseHeaderValues = [];
67 for (let header of trrResponse.headers) {
68 trrResponseHeaderNames.push(header[0]);
69 trrResponseHeaderValues.push(header[1]);
71 let binaryResponse = new BinaryHttpResponse(
72 trrResponse.status,
73 trrResponseHeaderNames,
74 trrResponseHeaderValues,
75 trrResponseContent
77 let responseBytes = bhttp.encodeResponse(binaryResponse);
78 let encResponse = ohttpResponse.encapsulate(responseBytes);
79 response.setStatusLine(request.httpVersion, 200, "OK");
80 response.setHeader("Content-Type", "message/ohttp-res", false);
81 response.write(bytesToString(encResponse));
82 } catch (e) {
83 // Some tests involve the responder either timing out or closing the
84 // connection unexpectedly.
88 add_setup(async function setup() {
89 h2Port = trr_test_setup();
90 runningOHTTPTests = true;
92 if (mozinfo.socketprocess_networking) {
93 Services.dns; // Needed to trigger socket process.
94 await TestUtils.waitForCondition(() => Services.io.socketProcessLaunched);
97 Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRONLY);
99 let ohttp = Cc["@mozilla.org/network/oblivious-http;1"].getService(
100 Ci.nsIObliviousHttp
102 ohttpServer = ohttp.server();
104 httpServer = new HttpServer();
105 httpServer.registerPathHandler("/relay", function (request, response) {
106 response.processAsync();
107 forwardToTRR(request, response).then(() => {
108 response.finish();
111 httpServer.registerPathHandler("/config", function (request, response) {
112 response.setStatusLine(request.httpVersion, 200, "OK");
113 response.setHeader("Content-Type", "application/ohttp-keys", false);
114 response.write(ohttpEncodedConfig);
116 httpServer.start(-1);
118 Services.prefs.setBoolPref("network.trr.use_ohttp", true);
119 // On windows the TTL fetch will race with clearing the cache
120 // to refresh the cache entry.
121 Services.prefs.setBoolPref("network.dns.get-ttl", false);
123 registerCleanupFunction(async () => {
124 trr_clear_prefs();
125 Services.prefs.clearUserPref("network.trr.use_ohttp");
126 Services.prefs.clearUserPref("network.trr.ohttp.config_uri");
127 Services.prefs.clearUserPref("network.trr.ohttp.relay_uri");
128 Services.prefs.clearUserPref("network.trr.ohttp.uri");
129 Services.prefs.clearUserPref("network.dns.get-ttl");
130 await new Promise(resolve => {
131 httpServer.stop(resolve);
136 // Test that if DNS-over-OHTTP isn't configured, the implementation falls back
137 // to platform resolution.
138 add_task(async function test_ohttp_not_configured() {
139 Services.dns.clearCache(true);
140 setModeAndURI(2, "doh?responseIP=2.2.2.2");
141 await new TRRDNSListener("example.com", "127.0.0.1");
144 add_task(async function set_ohttp_invalid_prefs() {
145 let configPromise = TestUtils.topicObserved("ohttp-service-config-loaded");
146 Services.prefs.setCharPref(
147 "network.trr.ohttp.relay_uri",
148 "http://nonexistent.test"
150 Services.prefs.setCharPref(
151 "network.trr.ohttp.config_uri",
152 "http://nonexistent.test"
155 Cc["@mozilla.org/network/oblivious-http-service;1"].getService(
156 Ci.nsIObliviousHttpService
158 await configPromise;
161 // Test that if DNS-over-OHTTP has an invalid configuration, the implementation
162 // falls back to platform resolution.
163 add_task(async function test_ohttp_invalid_prefs_fallback() {
164 Services.dns.clearCache(true);
165 setModeAndURI(2, "doh?responseIP=2.2.2.2");
166 await new TRRDNSListener("example.com", "127.0.0.1");
169 add_task(async function set_ohttp_prefs_500_error() {
170 let configPromise = TestUtils.topicObserved("ohttp-service-config-loaded");
171 Services.prefs.setCharPref(
172 "network.trr.ohttp.relay_uri",
173 `http://localhost:${httpServer.identity.primaryPort}/relay`
175 Services.prefs.setCharPref(
176 "network.trr.ohttp.config_uri",
177 `http://localhost:${httpServer.identity.primaryPort}/500error`
179 await configPromise;
182 // Test that if DNS-over-OHTTP has an invalid configuration, the implementation
183 // falls back to platform resolution.
184 add_task(async function test_ohttp_500_error_fallback() {
185 Services.dns.clearCache(true);
186 setModeAndURI(2, "doh?responseIP=2.2.2.2");
187 await new TRRDNSListener("example.com", "127.0.0.1");
190 add_task(async function retryConfigOnConnectivityChange() {
191 Services.prefs.setCharPref("network.trr.confirmationNS", "skip");
192 // First we make sure the config is properly loaded
193 setModeAndURI(2, "doh?responseIP=2.2.2.2");
194 let ohttpService = Cc[
195 "@mozilla.org/network/oblivious-http-service;1"
196 ].getService(Ci.nsIObliviousHttpService);
197 ohttpService.clearTRRConfig();
198 ohttpEncodedConfig = bytesToString(ohttpServer.encodedConfig);
199 let configPromise = TestUtils.topicObserved("ohttp-service-config-loaded");
200 Services.prefs.setCharPref(
201 "network.trr.ohttp.relay_uri",
202 `http://localhost:${httpServer.identity.primaryPort}/relay`
204 Services.prefs.setCharPref(
205 "network.trr.ohttp.config_uri",
206 `http://localhost:${httpServer.identity.primaryPort}/config`
208 let [, status] = await configPromise;
209 equal(status, "success");
210 info("retryConfigOnConnectivityChange setup complete");
212 ohttpService.clearTRRConfig();
214 let port = httpServer.identity.primaryPort;
215 // Stop the server so getting the config fails.
216 await httpServer.stop();
218 configPromise = TestUtils.topicObserved("ohttp-service-config-loaded");
219 Services.obs.notifyObservers(
220 null,
221 "network:captive-portal-connectivity-changed"
223 [, status] = await configPromise;
224 equal(status, "failed");
226 // Should fallback to native DNS since the config is empty
227 Services.dns.clearCache(true);
228 await new TRRDNSListener("example.com", "127.0.0.1");
230 // Start the server back again.
231 httpServer.start(port);
232 Assert.equal(
233 port,
234 httpServer.identity.primaryPort,
235 "server should get the same port"
238 // Still the config hasn't been reloaded.
239 await new TRRDNSListener("example2.com", "127.0.0.1");
241 // Signal a connectivity change so we reload the config
242 configPromise = TestUtils.topicObserved("ohttp-service-config-loaded");
243 Services.obs.notifyObservers(
244 null,
245 "network:captive-portal-connectivity-changed"
247 [, status] = await configPromise;
248 equal(status, "success");
250 await new TRRDNSListener("example3.com", "2.2.2.2");
252 // Now check that we also reload a missing config if a TRR confirmation fails.
253 ohttpService.clearTRRConfig();
254 configPromise = TestUtils.topicObserved("ohttp-service-config-loaded");
255 Services.obs.notifyObservers(
256 null,
257 "network:trr-confirmation",
258 "CONFIRM_FAILED"
260 [, status] = await configPromise;
261 equal(status, "success");
262 await new TRRDNSListener("example4.com", "2.2.2.2");
264 // set the config to an invalid value and check that as long as the URL
265 // doesn't change, we dont reload it again on connectivity notifications.
266 ohttpEncodedConfig = "not a valid config";
267 configPromise = TestUtils.topicObserved("ohttp-service-config-loaded");
268 Services.obs.notifyObservers(
269 null,
270 "network:captive-portal-connectivity-changed"
273 await new TRRDNSListener("example5.com", "2.2.2.2");
275 // The change should not cause any config reload because we already have a config.
276 [, status] = await configPromise;
277 equal(status, "no-changes");
279 await new TRRDNSListener("example6.com", "2.2.2.2");
280 // Clear the config_uri pref so it gets set to the proper value in the next test.
281 configPromise = TestUtils.topicObserved("ohttp-service-config-loaded");
282 Services.prefs.setCharPref("network.trr.ohttp.config_uri", ``);
283 await configPromise;
286 add_task(async function set_ohttp_prefs_valid() {
287 let ohttpService = Cc[
288 "@mozilla.org/network/oblivious-http-service;1"
289 ].getService(Ci.nsIObliviousHttpService);
290 ohttpService.clearTRRConfig();
291 let configPromise = TestUtils.topicObserved("ohttp-service-config-loaded");
292 ohttpEncodedConfig = bytesToString(ohttpServer.encodedConfig);
293 Services.prefs.setCharPref(
294 "network.trr.ohttp.config_uri",
295 `http://localhost:${httpServer.identity.primaryPort}/config`
297 await configPromise;
300 add_task(test_A_record);
302 add_task(test_AAAA_records);
304 add_task(test_RFC1918);
306 add_task(test_GET_ECS);
308 add_task(test_timeout_mode3);
310 add_task(test_strict_native_fallback);
312 add_task(test_no_answers_fallback);
314 add_task(test_404_fallback);
316 add_task(test_mode_1_and_4);
318 add_task(test_CNAME);
320 add_task(test_name_mismatch);
322 add_task(test_mode_2);
324 add_task(test_excluded_domains);
326 add_task(test_captiveportal_canonicalURL);
328 add_task(test_parentalcontrols);
330 // TRR-first check that DNS result is used if domain is part of the builtin-excluded-domains pref
331 add_task(test_builtin_excluded_domains);
333 add_task(test_excluded_domains_mode3);
335 add_task(test25e);
337 add_task(test_parentalcontrols_mode3);
339 add_task(test_builtin_excluded_domains_mode3);
341 add_task(count_cookies);
343 // This test doesn't work with having a JS httpd server as a relay.
344 // add_task(test_connection_closed);
346 add_task(test_fetch_time);
348 add_task(test_fqdn);
350 add_task(test_ipv6_trr_fallback);
352 add_task(test_ipv4_trr_fallback);
354 add_task(test_no_retry_without_doh);