test_trr_confirmation.js (12304B)
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/. */ 4 5 "use strict"; 6 7 const { TestUtils } = ChromeUtils.importESModule( 8 "resource://testing-common/TestUtils.sys.mjs" 9 ); 10 11 async function waitForConfirmationState(state, msToWait = 0) { 12 await TestUtils.waitForCondition( 13 () => Services.dns.currentTrrConfirmationState == state, 14 `Timed out waiting for ${state}. Currently ${Services.dns.currentTrrConfirmationState}`, 15 1, 16 msToWait 17 ); 18 equal( 19 Services.dns.currentTrrConfirmationState, 20 state, 21 "expected confirmation state" 22 ); 23 } 24 25 const CONFIRM_OFF = 0; 26 const CONFIRM_TRYING_OK = 1; 27 const CONFIRM_OK = 2; 28 const CONFIRM_FAILED = 3; 29 const CONFIRM_TRYING_FAILED = 4; 30 const CONFIRM_DISABLED = 5; 31 32 function setup() { 33 trr_test_setup(); 34 Services.prefs.setBoolPref("network.trr.skip-check-for-blocked-host", true); 35 } 36 37 setup(); 38 registerCleanupFunction(async () => { 39 trr_clear_prefs(); 40 Services.prefs.clearUserPref("network.trr.skip-check-for-blocked-host"); 41 }); 42 43 let trrServer = null; 44 add_task(async function start_trr_server() { 45 trrServer = new TRRServer(); 46 registerCleanupFunction(async () => { 47 await trrServer.stop(); 48 }); 49 await trrServer.start(); 50 dump(`port = ${trrServer.port()}\n`); 51 52 await trrServer.registerDoHAnswers(`faily.com`, "NS", { 53 answers: [ 54 { 55 name: "faily.com", 56 ttl: 55, 57 type: "NS", 58 flush: false, 59 data: "ns.faily.com", 60 }, 61 ], 62 }); 63 64 for (let i = 0; i < 15; i++) { 65 await trrServer.registerDoHAnswers(`failing-domain${i}.faily.com`, "A", { 66 error: 600, 67 }); 68 await trrServer.registerDoHAnswers(`failing-domain${i}.faily.com`, "AAAA", { 69 error: 600, 70 }); 71 } 72 }); 73 74 function trigger15Failures() { 75 // We need to clear the cache in case a previous call to this method 76 // put the results in the DNS cache. 77 Services.dns.clearCache(true); 78 79 let dnsRequests = []; 80 // There are actually two TRR requests sent for A and AAAA records, so doing 81 // DNS query 10 times should be enough to trigger confirmation process. 82 for (let i = 0; i < 10; i++) { 83 dnsRequests.push( 84 new TRRDNSListener(`failing-domain${i}.faily.com`, { 85 expectedAnswer: "127.0.0.1", 86 }) 87 ); 88 } 89 90 return Promise.all(dnsRequests); 91 } 92 93 async function registerNS(delay) { 94 return trrServer.registerDoHAnswers("confirm.example.com", "NS", { 95 answers: [ 96 { 97 name: "confirm.example.com", 98 ttl: 55, 99 type: "NS", 100 flush: false, 101 data: "test.com", 102 }, 103 ], 104 delay, 105 }); 106 } 107 108 add_task(async function confirm_off() { 109 Services.prefs.setCharPref( 110 "network.trr.confirmationNS", 111 "confirm.example.com" 112 ); 113 Services.prefs.setIntPref( 114 "network.trr.mode", 115 Ci.nsIDNSService.MODE_NATIVEONLY 116 ); 117 equal(Services.dns.currentTrrConfirmationState, CONFIRM_OFF); 118 Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRROFF); 119 equal(Services.dns.currentTrrConfirmationState, CONFIRM_OFF); 120 }); 121 122 add_task(async function confirm_disabled() { 123 Services.prefs.setCharPref( 124 "network.trr.confirmationNS", 125 "confirm.example.com" 126 ); 127 Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRONLY); 128 equal(Services.dns.currentTrrConfirmationState, CONFIRM_DISABLED); 129 Services.prefs.setCharPref("network.trr.confirmationNS", "skip"); 130 Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST); 131 equal(Services.dns.currentTrrConfirmationState, CONFIRM_DISABLED); 132 }); 133 134 add_task(async function confirm_ok() { 135 Services.dns.clearCache(true); 136 Services.prefs.setCharPref( 137 "network.trr.confirmationNS", 138 "confirm.example.com" 139 ); 140 await registerNS(0); 141 await trrServer.registerDoHAnswers("example.com", "A", { 142 answers: [ 143 { 144 name: "example.com", 145 ttl: 55, 146 type: "A", 147 flush: false, 148 data: "1.2.3.4", 149 }, 150 ], 151 }); 152 Services.prefs.setCharPref( 153 "network.trr.uri", 154 `https://foo.example.com:${trrServer.port()}/dns-query` 155 ); 156 Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST); 157 equal( 158 Services.dns.currentTrrConfirmationState, 159 CONFIRM_TRYING_OK, 160 "Should be CONFIRM_TRYING_OK" 161 ); 162 await new TRRDNSListener("example.com", { expectedAnswer: "1.2.3.4" }); 163 equal(await trrServer.requestCount("example.com", "A"), 1); 164 await waitForConfirmationState(CONFIRM_OK, 1000); 165 166 await registerNS(500); 167 Services.prefs.setIntPref( 168 "network.trr.mode", 169 Ci.nsIDNSService.MODE_NATIVEONLY 170 ); 171 Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST); 172 equal( 173 Services.dns.currentTrrConfirmationState, 174 CONFIRM_TRYING_OK, 175 "Should be CONFIRM_TRYING_OK" 176 ); 177 await new Promise(resolve => do_timeout(100, resolve)); 178 equal( 179 Services.dns.currentTrrConfirmationState, 180 CONFIRM_TRYING_OK, 181 "Confirmation should still be pending" 182 ); 183 await waitForConfirmationState(CONFIRM_OK, 1000); 184 }); 185 186 add_task(async function confirm_timeout() { 187 Services.prefs.setIntPref( 188 "network.trr.mode", 189 Ci.nsIDNSService.MODE_NATIVEONLY 190 ); 191 equal(Services.dns.currentTrrConfirmationState, CONFIRM_OFF); 192 await registerNS(7000); 193 Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST); 194 equal( 195 Services.dns.currentTrrConfirmationState, 196 CONFIRM_TRYING_OK, 197 "Should be CONFIRM_TRYING_OK" 198 ); 199 await waitForConfirmationState(CONFIRM_FAILED, 7500); 200 // After the confirmation fails, a timer will periodically trigger a retry 201 // causing the state to go into CONFIRM_TRYING_FAILED. 202 await waitForConfirmationState(CONFIRM_TRYING_FAILED, 500); 203 }); 204 205 add_task(async function confirm_fail_fast() { 206 Services.prefs.setIntPref( 207 "network.trr.mode", 208 Ci.nsIDNSService.MODE_NATIVEONLY 209 ); 210 equal(Services.dns.currentTrrConfirmationState, CONFIRM_OFF); 211 await trrServer.registerDoHAnswers("confirm.example.com", "NS", { 212 error: 404, 213 }); 214 Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST); 215 equal( 216 Services.dns.currentTrrConfirmationState, 217 CONFIRM_TRYING_OK, 218 "Should be CONFIRM_TRYING_OK" 219 ); 220 await waitForConfirmationState(CONFIRM_FAILED, 100); 221 }); 222 223 add_task(async function multiple_failures() { 224 Services.prefs.setIntPref( 225 "network.trr.mode", 226 Ci.nsIDNSService.MODE_NATIVEONLY 227 ); 228 Services.prefs.setIntPref("network.trr.max-retry-timeout-ms", 8000); 229 equal(Services.dns.currentTrrConfirmationState, CONFIRM_OFF); 230 231 await registerNS(100); 232 Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST); 233 equal( 234 Services.dns.currentTrrConfirmationState, 235 CONFIRM_TRYING_OK, 236 "Should be CONFIRM_TRYING_OK" 237 ); 238 await waitForConfirmationState(CONFIRM_OK, 1000); 239 await registerNS(4000); 240 let failures = trigger15Failures(); 241 await waitForConfirmationState(CONFIRM_TRYING_OK, 3000); 242 await failures; 243 // Check that failures during confirmation are ignored. 244 await trigger15Failures(); 245 equal( 246 Services.dns.currentTrrConfirmationState, 247 CONFIRM_TRYING_OK, 248 "Should be CONFIRM_TRYING_OK" 249 ); 250 await waitForConfirmationState(CONFIRM_OK, 8500); 251 }); 252 253 add_task(async function test_connectivity_change() { 254 await registerNS(100); 255 Services.prefs.setIntPref( 256 "network.trr.mode", 257 Ci.nsIDNSService.MODE_NATIVEONLY 258 ); 259 let confirmationCount = await trrServer.requestCount( 260 "confirm.example.com", 261 "NS" 262 ); 263 Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST); 264 equal( 265 Services.dns.currentTrrConfirmationState, 266 CONFIRM_TRYING_OK, 267 "Should be CONFIRM_TRYING_OK" 268 ); 269 await waitForConfirmationState(CONFIRM_OK, 1000); 270 equal( 271 await trrServer.requestCount("confirm.example.com", "NS"), 272 confirmationCount + 1 273 ); 274 Services.obs.notifyObservers( 275 null, 276 "network:captive-portal-connectivity", 277 "clear" 278 ); 279 // This means a CP check completed successfully. But no CP was previously 280 // detected, so this is mostly a no-op. 281 equal(Services.dns.currentTrrConfirmationState, CONFIRM_OK); 282 283 Services.obs.notifyObservers( 284 null, 285 "network:captive-portal-connectivity", 286 "captive" 287 ); 288 // This basically a successful CP login event. Wasn't captive before. 289 // Still treating as a no-op. 290 equal(Services.dns.currentTrrConfirmationState, CONFIRM_OK); 291 292 // This makes the TRR service set mCaptiveIsPassed=false 293 Services.obs.notifyObservers( 294 null, 295 "captive-portal-login", 296 "{type: 'captive-portal-login', id: 0, url: 'http://localhost/'}" 297 ); 298 299 await registerNS(500); 300 let failures = trigger15Failures(); 301 // The failure should cause us to go into CONFIRM_TRYING_OK and do an NS req 302 await waitForConfirmationState(CONFIRM_TRYING_OK, 3000); 303 await failures; 304 305 // The notification sets mCaptiveIsPassed=true then triggers an entirely new 306 // confirmation. 307 Services.obs.notifyObservers( 308 null, 309 "network:captive-portal-connectivity", 310 "clear" 311 ); 312 // The notification should cause us to send a new confirmation request 313 equal( 314 Services.dns.currentTrrConfirmationState, 315 CONFIRM_TRYING_OK, 316 "Should be CONFIRM_TRYING_OK" 317 ); 318 await waitForConfirmationState(CONFIRM_OK, 1000); 319 // two extra confirmation events should have been received by the server 320 equal( 321 await trrServer.requestCount("confirm.example.com", "NS"), 322 confirmationCount + 3 323 ); 324 }); 325 326 add_task(async function test_network_change() { 327 let confirmationCount = await trrServer.requestCount( 328 "confirm.example.com", 329 "NS" 330 ); 331 equal(Services.dns.currentTrrConfirmationState, CONFIRM_OK); 332 333 Services.obs.notifyObservers(null, "network:link-status-changed", "up"); 334 equal(Services.dns.currentTrrConfirmationState, CONFIRM_OK); 335 equal( 336 await trrServer.requestCount("confirm.example.com", "NS"), 337 confirmationCount 338 ); 339 340 let failures = trigger15Failures(); 341 // The failure should cause us to go into CONFIRM_TRYING_OK and do an NS req 342 await waitForConfirmationState(CONFIRM_TRYING_OK, 3000); 343 await failures; 344 // The network up event should reset the confirmation to TRYING_OK and do 345 // another NS req 346 Services.obs.notifyObservers(null, "network:link-status-changed", "up"); 347 equal(Services.dns.currentTrrConfirmationState, CONFIRM_TRYING_OK); 348 await waitForConfirmationState(CONFIRM_OK, 1000); 349 // two extra confirmation events should have been received by the server 350 equal( 351 await trrServer.requestCount("confirm.example.com", "NS"), 352 confirmationCount + 2 353 ); 354 }); 355 356 add_task(async function test_uri_pref_change() { 357 let confirmationCount = await trrServer.requestCount( 358 "confirm.example.com", 359 "NS" 360 ); 361 equal(Services.dns.currentTrrConfirmationState, CONFIRM_OK); 362 Services.prefs.setCharPref( 363 "network.trr.uri", 364 `https://foo.example.com:${trrServer.port()}/dns-query?changed` 365 ); 366 equal(Services.dns.currentTrrConfirmationState, CONFIRM_TRYING_OK); 367 await waitForConfirmationState(CONFIRM_OK, 1000); 368 equal( 369 await trrServer.requestCount("confirm.example.com", "NS"), 370 confirmationCount + 1 371 ); 372 }); 373 374 add_task(async function test_autodetected_uri() { 375 const defaultPrefBranch = Services.prefs.getDefaultBranch(""); 376 let defaultURI = defaultPrefBranch.getCharPref( 377 "network.trr.default_provider_uri" 378 ); 379 defaultPrefBranch.setCharPref( 380 "network.trr.default_provider_uri", 381 `https://foo.example.com:${trrServer.port()}/dns-query?changed` 382 ); 383 // For setDetectedTrrURI to work we must pretend we are using the default. 384 Services.prefs.clearUserPref("network.trr.uri"); 385 await waitForConfirmationState(CONFIRM_OK, 1000); 386 let confirmationCount = await trrServer.requestCount( 387 "confirm.example.com", 388 "NS" 389 ); 390 Services.dns.setDetectedTrrURI( 391 `https://foo.example.com:${trrServer.port()}/dns-query?changed2` 392 ); 393 equal(Services.dns.currentTrrConfirmationState, CONFIRM_TRYING_OK); 394 await waitForConfirmationState(CONFIRM_OK, 1000); 395 equal( 396 await trrServer.requestCount("confirm.example.com", "NS"), 397 confirmationCount + 1 398 ); 399 400 // reset the default URI 401 defaultPrefBranch.setCharPref("network.trr.default_provider_uri", defaultURI); 402 });