402 lines
12 KiB
JavaScript
402 lines
12 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
"use strict";
|
|
|
|
const { TestUtils } = ChromeUtils.importESModule(
|
|
"resource://testing-common/TestUtils.sys.mjs"
|
|
);
|
|
|
|
async function waitForConfirmationState(state, msToWait = 0) {
|
|
await TestUtils.waitForCondition(
|
|
() => Services.dns.currentTrrConfirmationState == state,
|
|
`Timed out waiting for ${state}. Currently ${Services.dns.currentTrrConfirmationState}`,
|
|
1,
|
|
msToWait
|
|
);
|
|
equal(
|
|
Services.dns.currentTrrConfirmationState,
|
|
state,
|
|
"expected confirmation state"
|
|
);
|
|
}
|
|
|
|
const CONFIRM_OFF = 0;
|
|
const CONFIRM_TRYING_OK = 1;
|
|
const CONFIRM_OK = 2;
|
|
const CONFIRM_FAILED = 3;
|
|
const CONFIRM_TRYING_FAILED = 4;
|
|
const CONFIRM_DISABLED = 5;
|
|
|
|
function setup() {
|
|
trr_test_setup();
|
|
Services.prefs.setBoolPref("network.trr.skip-check-for-blocked-host", true);
|
|
}
|
|
|
|
setup();
|
|
registerCleanupFunction(async () => {
|
|
trr_clear_prefs();
|
|
Services.prefs.clearUserPref("network.trr.skip-check-for-blocked-host");
|
|
});
|
|
|
|
let trrServer = null;
|
|
add_task(async function start_trr_server() {
|
|
trrServer = new TRRServer();
|
|
registerCleanupFunction(async () => {
|
|
await trrServer.stop();
|
|
});
|
|
await trrServer.start();
|
|
dump(`port = ${trrServer.port()}\n`);
|
|
|
|
await trrServer.registerDoHAnswers(`faily.com`, "NS", {
|
|
answers: [
|
|
{
|
|
name: "faily.com",
|
|
ttl: 55,
|
|
type: "NS",
|
|
flush: false,
|
|
data: "ns.faily.com",
|
|
},
|
|
],
|
|
});
|
|
|
|
for (let i = 0; i < 15; i++) {
|
|
await trrServer.registerDoHAnswers(`failing-domain${i}.faily.com`, "A", {
|
|
error: 600,
|
|
});
|
|
await trrServer.registerDoHAnswers(`failing-domain${i}.faily.com`, "AAAA", {
|
|
error: 600,
|
|
});
|
|
}
|
|
});
|
|
|
|
function trigger15Failures() {
|
|
// We need to clear the cache in case a previous call to this method
|
|
// put the results in the DNS cache.
|
|
Services.dns.clearCache(true);
|
|
|
|
let dnsRequests = [];
|
|
// There are actually two TRR requests sent for A and AAAA records, so doing
|
|
// DNS query 10 times should be enough to trigger confirmation process.
|
|
for (let i = 0; i < 10; i++) {
|
|
dnsRequests.push(
|
|
new TRRDNSListener(`failing-domain${i}.faily.com`, {
|
|
expectedAnswer: "127.0.0.1",
|
|
})
|
|
);
|
|
}
|
|
|
|
return Promise.all(dnsRequests);
|
|
}
|
|
|
|
async function registerNS(delay) {
|
|
return trrServer.registerDoHAnswers("confirm.example.com", "NS", {
|
|
answers: [
|
|
{
|
|
name: "confirm.example.com",
|
|
ttl: 55,
|
|
type: "NS",
|
|
flush: false,
|
|
data: "test.com",
|
|
},
|
|
],
|
|
delay,
|
|
});
|
|
}
|
|
|
|
add_task(async function confirm_off() {
|
|
Services.prefs.setCharPref(
|
|
"network.trr.confirmationNS",
|
|
"confirm.example.com"
|
|
);
|
|
Services.prefs.setIntPref(
|
|
"network.trr.mode",
|
|
Ci.nsIDNSService.MODE_NATIVEONLY
|
|
);
|
|
equal(Services.dns.currentTrrConfirmationState, CONFIRM_OFF);
|
|
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRROFF);
|
|
equal(Services.dns.currentTrrConfirmationState, CONFIRM_OFF);
|
|
});
|
|
|
|
add_task(async function confirm_disabled() {
|
|
Services.prefs.setCharPref(
|
|
"network.trr.confirmationNS",
|
|
"confirm.example.com"
|
|
);
|
|
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRONLY);
|
|
equal(Services.dns.currentTrrConfirmationState, CONFIRM_DISABLED);
|
|
Services.prefs.setCharPref("network.trr.confirmationNS", "skip");
|
|
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
|
|
equal(Services.dns.currentTrrConfirmationState, CONFIRM_DISABLED);
|
|
});
|
|
|
|
add_task(async function confirm_ok() {
|
|
Services.dns.clearCache(true);
|
|
Services.prefs.setCharPref(
|
|
"network.trr.confirmationNS",
|
|
"confirm.example.com"
|
|
);
|
|
await registerNS(0);
|
|
await trrServer.registerDoHAnswers("example.com", "A", {
|
|
answers: [
|
|
{
|
|
name: "example.com",
|
|
ttl: 55,
|
|
type: "A",
|
|
flush: false,
|
|
data: "1.2.3.4",
|
|
},
|
|
],
|
|
});
|
|
Services.prefs.setCharPref(
|
|
"network.trr.uri",
|
|
`https://foo.example.com:${trrServer.port()}/dns-query`
|
|
);
|
|
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
|
|
equal(
|
|
Services.dns.currentTrrConfirmationState,
|
|
CONFIRM_TRYING_OK,
|
|
"Should be CONFIRM_TRYING_OK"
|
|
);
|
|
await new TRRDNSListener("example.com", { expectedAnswer: "1.2.3.4" });
|
|
equal(await trrServer.requestCount("example.com", "A"), 1);
|
|
await waitForConfirmationState(CONFIRM_OK, 1000);
|
|
|
|
await registerNS(500);
|
|
Services.prefs.setIntPref(
|
|
"network.trr.mode",
|
|
Ci.nsIDNSService.MODE_NATIVEONLY
|
|
);
|
|
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
|
|
equal(
|
|
Services.dns.currentTrrConfirmationState,
|
|
CONFIRM_TRYING_OK,
|
|
"Should be CONFIRM_TRYING_OK"
|
|
);
|
|
await new Promise(resolve => do_timeout(100, resolve));
|
|
equal(
|
|
Services.dns.currentTrrConfirmationState,
|
|
CONFIRM_TRYING_OK,
|
|
"Confirmation should still be pending"
|
|
);
|
|
await waitForConfirmationState(CONFIRM_OK, 1000);
|
|
});
|
|
|
|
add_task(async function confirm_timeout() {
|
|
Services.prefs.setIntPref(
|
|
"network.trr.mode",
|
|
Ci.nsIDNSService.MODE_NATIVEONLY
|
|
);
|
|
equal(Services.dns.currentTrrConfirmationState, CONFIRM_OFF);
|
|
await registerNS(7000);
|
|
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
|
|
equal(
|
|
Services.dns.currentTrrConfirmationState,
|
|
CONFIRM_TRYING_OK,
|
|
"Should be CONFIRM_TRYING_OK"
|
|
);
|
|
await waitForConfirmationState(CONFIRM_FAILED, 7500);
|
|
// After the confirmation fails, a timer will periodically trigger a retry
|
|
// causing the state to go into CONFIRM_TRYING_FAILED.
|
|
await waitForConfirmationState(CONFIRM_TRYING_FAILED, 500);
|
|
});
|
|
|
|
add_task(async function confirm_fail_fast() {
|
|
Services.prefs.setIntPref(
|
|
"network.trr.mode",
|
|
Ci.nsIDNSService.MODE_NATIVEONLY
|
|
);
|
|
equal(Services.dns.currentTrrConfirmationState, CONFIRM_OFF);
|
|
await trrServer.registerDoHAnswers("confirm.example.com", "NS", {
|
|
error: 404,
|
|
});
|
|
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
|
|
equal(
|
|
Services.dns.currentTrrConfirmationState,
|
|
CONFIRM_TRYING_OK,
|
|
"Should be CONFIRM_TRYING_OK"
|
|
);
|
|
await waitForConfirmationState(CONFIRM_FAILED, 100);
|
|
});
|
|
|
|
add_task(async function multiple_failures() {
|
|
Services.prefs.setIntPref(
|
|
"network.trr.mode",
|
|
Ci.nsIDNSService.MODE_NATIVEONLY
|
|
);
|
|
Services.prefs.setIntPref("network.trr.max-retry-timeout-ms", 8000);
|
|
equal(Services.dns.currentTrrConfirmationState, CONFIRM_OFF);
|
|
|
|
await registerNS(100);
|
|
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
|
|
equal(
|
|
Services.dns.currentTrrConfirmationState,
|
|
CONFIRM_TRYING_OK,
|
|
"Should be CONFIRM_TRYING_OK"
|
|
);
|
|
await waitForConfirmationState(CONFIRM_OK, 1000);
|
|
await registerNS(4000);
|
|
let failures = trigger15Failures();
|
|
await waitForConfirmationState(CONFIRM_TRYING_OK, 3000);
|
|
await failures;
|
|
// Check that failures during confirmation are ignored.
|
|
await trigger15Failures();
|
|
equal(
|
|
Services.dns.currentTrrConfirmationState,
|
|
CONFIRM_TRYING_OK,
|
|
"Should be CONFIRM_TRYING_OK"
|
|
);
|
|
await waitForConfirmationState(CONFIRM_OK, 8500);
|
|
});
|
|
|
|
add_task(async function test_connectivity_change() {
|
|
await registerNS(100);
|
|
Services.prefs.setIntPref(
|
|
"network.trr.mode",
|
|
Ci.nsIDNSService.MODE_NATIVEONLY
|
|
);
|
|
let confirmationCount = await trrServer.requestCount(
|
|
"confirm.example.com",
|
|
"NS"
|
|
);
|
|
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
|
|
equal(
|
|
Services.dns.currentTrrConfirmationState,
|
|
CONFIRM_TRYING_OK,
|
|
"Should be CONFIRM_TRYING_OK"
|
|
);
|
|
await waitForConfirmationState(CONFIRM_OK, 1000);
|
|
equal(
|
|
await trrServer.requestCount("confirm.example.com", "NS"),
|
|
confirmationCount + 1
|
|
);
|
|
Services.obs.notifyObservers(
|
|
null,
|
|
"network:captive-portal-connectivity",
|
|
"clear"
|
|
);
|
|
// This means a CP check completed successfully. But no CP was previously
|
|
// detected, so this is mostly a no-op.
|
|
equal(Services.dns.currentTrrConfirmationState, CONFIRM_OK);
|
|
|
|
Services.obs.notifyObservers(
|
|
null,
|
|
"network:captive-portal-connectivity",
|
|
"captive"
|
|
);
|
|
// This basically a successful CP login event. Wasn't captive before.
|
|
// Still treating as a no-op.
|
|
equal(Services.dns.currentTrrConfirmationState, CONFIRM_OK);
|
|
|
|
// This makes the TRR service set mCaptiveIsPassed=false
|
|
Services.obs.notifyObservers(
|
|
null,
|
|
"captive-portal-login",
|
|
"{type: 'captive-portal-login', id: 0, url: 'http://localhost/'}"
|
|
);
|
|
|
|
await registerNS(500);
|
|
let failures = trigger15Failures();
|
|
// The failure should cause us to go into CONFIRM_TRYING_OK and do an NS req
|
|
await waitForConfirmationState(CONFIRM_TRYING_OK, 3000);
|
|
await failures;
|
|
|
|
// The notification sets mCaptiveIsPassed=true then triggers an entirely new
|
|
// confirmation.
|
|
Services.obs.notifyObservers(
|
|
null,
|
|
"network:captive-portal-connectivity",
|
|
"clear"
|
|
);
|
|
// The notification should cause us to send a new confirmation request
|
|
equal(
|
|
Services.dns.currentTrrConfirmationState,
|
|
CONFIRM_TRYING_OK,
|
|
"Should be CONFIRM_TRYING_OK"
|
|
);
|
|
await waitForConfirmationState(CONFIRM_OK, 1000);
|
|
// two extra confirmation events should have been received by the server
|
|
equal(
|
|
await trrServer.requestCount("confirm.example.com", "NS"),
|
|
confirmationCount + 3
|
|
);
|
|
});
|
|
|
|
add_task(async function test_network_change() {
|
|
let confirmationCount = await trrServer.requestCount(
|
|
"confirm.example.com",
|
|
"NS"
|
|
);
|
|
equal(Services.dns.currentTrrConfirmationState, CONFIRM_OK);
|
|
|
|
Services.obs.notifyObservers(null, "network:link-status-changed", "up");
|
|
equal(Services.dns.currentTrrConfirmationState, CONFIRM_OK);
|
|
equal(
|
|
await trrServer.requestCount("confirm.example.com", "NS"),
|
|
confirmationCount
|
|
);
|
|
|
|
let failures = trigger15Failures();
|
|
// The failure should cause us to go into CONFIRM_TRYING_OK and do an NS req
|
|
await waitForConfirmationState(CONFIRM_TRYING_OK, 3000);
|
|
await failures;
|
|
// The network up event should reset the confirmation to TRYING_OK and do
|
|
// another NS req
|
|
Services.obs.notifyObservers(null, "network:link-status-changed", "up");
|
|
equal(Services.dns.currentTrrConfirmationState, CONFIRM_TRYING_OK);
|
|
await waitForConfirmationState(CONFIRM_OK, 1000);
|
|
// two extra confirmation events should have been received by the server
|
|
equal(
|
|
await trrServer.requestCount("confirm.example.com", "NS"),
|
|
confirmationCount + 2
|
|
);
|
|
});
|
|
|
|
add_task(async function test_uri_pref_change() {
|
|
let confirmationCount = await trrServer.requestCount(
|
|
"confirm.example.com",
|
|
"NS"
|
|
);
|
|
equal(Services.dns.currentTrrConfirmationState, CONFIRM_OK);
|
|
Services.prefs.setCharPref(
|
|
"network.trr.uri",
|
|
`https://foo.example.com:${trrServer.port()}/dns-query?changed`
|
|
);
|
|
equal(Services.dns.currentTrrConfirmationState, CONFIRM_TRYING_OK);
|
|
await waitForConfirmationState(CONFIRM_OK, 1000);
|
|
equal(
|
|
await trrServer.requestCount("confirm.example.com", "NS"),
|
|
confirmationCount + 1
|
|
);
|
|
});
|
|
|
|
add_task(async function test_autodetected_uri() {
|
|
const defaultPrefBranch = Services.prefs.getDefaultBranch("");
|
|
let defaultURI = defaultPrefBranch.getCharPref(
|
|
"network.trr.default_provider_uri"
|
|
);
|
|
defaultPrefBranch.setCharPref(
|
|
"network.trr.default_provider_uri",
|
|
`https://foo.example.com:${trrServer.port()}/dns-query?changed`
|
|
);
|
|
// For setDetectedTrrURI to work we must pretend we are using the default.
|
|
Services.prefs.clearUserPref("network.trr.uri");
|
|
await waitForConfirmationState(CONFIRM_OK, 1000);
|
|
let confirmationCount = await trrServer.requestCount(
|
|
"confirm.example.com",
|
|
"NS"
|
|
);
|
|
Services.dns.setDetectedTrrURI(
|
|
`https://foo.example.com:${trrServer.port()}/dns-query?changed2`
|
|
);
|
|
equal(Services.dns.currentTrrConfirmationState, CONFIRM_TRYING_OK);
|
|
await waitForConfirmationState(CONFIRM_OK, 1000);
|
|
equal(
|
|
await trrServer.requestCount("confirm.example.com", "NS"),
|
|
confirmationCount + 1
|
|
);
|
|
|
|
// reset the default URI
|
|
defaultPrefBranch.setCharPref("network.trr.default_provider_uri", defaultURI);
|
|
});
|