Bug 1642078 - Include heuristics state when determining if DoH is enabled in about:preferences. r=johannh,valentin

Depends on D77579

Differential Revision: https://phabricator.services.mozilla.com/D78583
This commit is contained in:
Nihanth Subramanya 2020-06-12 00:03:28 +00:00
parent ead758c5dc
commit bf0e4b2094
2 changed files with 111 additions and 11 deletions

View File

@ -39,6 +39,9 @@ Preferences.addAll([
{ id: "network.trr.uri", type: "string" },
{ id: "network.trr.resolvers", type: "string" },
{ id: "network.trr.custom_uri", type: "string" },
{ id: "doh-rollout.enabled", type: "bool" },
{ id: "doh-rollout.disable-heuristics", type: "bool" },
{ id: "doh-rollout.skipHeuristicsCheck", type: "bool" },
]);
window.addEventListener(
@ -67,8 +70,13 @@ window.addEventListener(
gConnectionsDialog.uiReady = new Promise(resolve => {
gConnectionsDialog._areTrrPrefsReady = false;
gConnectionsDialog._handleTrrPrefsReady = resolve;
}).then(() => {
gConnectionsDialog.initDnsOverHttpsUI();
}).then(async () => {
// awaiting this ensures that initDnsOverHttpsUI() is called after
// execution has been returned to the caller of _handleTrrPrefsReady,
// which is the checkbox value reading path. This ensures the checkbox
// gets checked, then initDnsOverHttpsUI() is called, then the uiReady
// promise resolves, preventing intermittent failures in tests.
await gConnectionsDialog.initDnsOverHttpsUI();
});
document
@ -440,10 +448,19 @@ var gConnectionsDialog = {
},
isDnsOverHttpsEnabled() {
// values outside 1:4 are considered falsey/disabled in this context
// We consider DoH enabled if:
// 1. network.trr.mode has a user-set value equal to 2 or 3.
// 2. network.trr.mode is 0, and DoH heuristics are enabled
let trrPref = Preferences.get("network.trr.mode");
let enabled = trrPref.value > 0 && trrPref.value < 5;
return enabled;
if (trrPref.value > 0) {
return trrPref.value == 2 || trrPref.value == 3;
}
let rolloutEnabled = Preferences.get("doh-rollout.enabled").value;
let heuristicsDisabled =
Preferences.get("doh-rollout.disable-heuristics").value ||
Preferences.get("doh-rollout.skipHeuristicsCheck").value;
return rolloutEnabled && !heuristicsDisabled;
},
readDnsOverHttpsMode() {
@ -466,7 +483,7 @@ var gConnectionsDialog = {
// called to update pref with user change
let trrModeCheckbox = document.getElementById("networkDnsOverHttps");
// we treat checked/enabled as mode 2
return trrModeCheckbox.checked ? 2 : 0;
return trrModeCheckbox.checked ? 2 : 5;
},
updateDnsOverHttpsUI() {

View File

@ -6,6 +6,9 @@ const TRR_MODE_PREF = "network.trr.mode";
const TRR_URI_PREF = "network.trr.uri";
const TRR_RESOLVERS_PREF = "network.trr.resolvers";
const TRR_CUSTOM_URI_PREF = "network.trr.custom_uri";
const ROLLOUT_ENABLED_PREF = "doh-rollout.enabled";
const ROLLOUT_SELF_ENABLED_PREF = "doh-rollout.self-enabled";
const HEURISTICS_DISABLED_PREF = "doh-rollout.disable-heuristics";
const DEFAULT_RESOLVER_VALUE = "https://mozilla.cloudflare-dns.com/dns-query";
const NEXTDNS_RESOLVER_VALUE = "https://trr.dns.nextdns.io/";
@ -27,6 +30,9 @@ function resetPrefs() {
Services.prefs.clearUserPref(TRR_URI_PREF);
Services.prefs.clearUserPref(TRR_RESOLVERS_PREF);
Services.prefs.clearUserPref(TRR_CUSTOM_URI_PREF);
Services.prefs.clearUserPref(ROLLOUT_ENABLED_PREF);
Services.prefs.clearUserPref(ROLLOUT_SELF_ENABLED_PREF);
Services.prefs.clearUserPref(HEURISTICS_DISABLED_PREF);
}
let preferencesOpen = new Promise(res => open_preferences(res));
@ -67,8 +73,20 @@ async function testWithProperties(props, startTime) {
": testWithProperties: testing with " +
JSON.stringify(props)
);
let rolloutReadyPref = ROLLOUT_SELF_ENABLED_PREF;
if (props.hasOwnProperty(TRR_MODE_PREF)) {
Services.prefs.setIntPref(TRR_MODE_PREF, props[TRR_MODE_PREF]);
if ([2, 3, 5].includes(props[TRR_MODE_PREF])) {
rolloutReadyPref = HEURISTICS_DISABLED_PREF;
}
}
if (props.hasOwnProperty(ROLLOUT_ENABLED_PREF)) {
let prefPromise = waitForPrefObserver(rolloutReadyPref);
Services.prefs.setBoolPref(
ROLLOUT_ENABLED_PREF,
props[ROLLOUT_ENABLED_PREF]
);
await prefPromise;
}
if (props.hasOwnProperty(TRR_CUSTOM_URI_PREF)) {
Services.prefs.setStringPref(
@ -101,8 +119,12 @@ async function testWithProperties(props, startTime) {
let resolverMenulist = doc.querySelector(resolverMenulistSelector);
let uriPrefChangedPromise;
let modePrefChangedPromise;
let disableHeuristicsPrefChangedPromise;
if (props.hasOwnProperty("expectedModeChecked")) {
await TestUtils.waitForCondition(
() => modeCheckbox.checked === props.expectedModeChecked
);
is(
modeCheckbox.checked,
props.expectedModeChecked,
@ -110,6 +132,9 @@ async function testWithProperties(props, startTime) {
);
}
if (props.hasOwnProperty("expectedUriValue")) {
await TestUtils.waitForCondition(
() => uriTextbox.value === props.expectedUriValue
);
is(
uriTextbox.value,
props.expectedUriValue,
@ -117,6 +142,9 @@ async function testWithProperties(props, startTime) {
);
}
if (props.hasOwnProperty("expectedResolverListValue")) {
await TestUtils.waitForCondition(
() => resolverMenulist.value === props.expectedResolverListValue
);
is(
resolverMenulist.value,
props.expectedResolverListValue,
@ -130,6 +158,11 @@ async function testWithProperties(props, startTime) {
": testWithProperties: clickMode, waiting for the pref observer"
);
modePrefChangedPromise = waitForPrefObserver(TRR_MODE_PREF);
if (props.hasOwnProperty("expectedDisabledHeuristics")) {
disableHeuristicsPrefChangedPromise = waitForPrefObserver(
HEURISTICS_DISABLED_PREF
);
}
info(
Date.now() - startTime + ": testWithProperties: clickMode, pref changed"
);
@ -197,7 +230,11 @@ async function testWithProperties(props, startTime) {
startTime +
": testWithProperties: waiting for any of uri and mode prefs to change"
);
await Promise.all([uriPrefChangedPromise, modePrefChangedPromise]);
await Promise.all([
uriPrefChangedPromise,
modePrefChangedPromise,
disableHeuristicsPrefChangedPromise,
]);
info(Date.now() - startTime + ": testWithProperties: prefs changed");
if (props.hasOwnProperty("expectedFinalUriPref")) {
@ -218,6 +255,17 @@ async function testWithProperties(props, startTime) {
);
}
if (props.hasOwnProperty("expectedDisabledHeuristics")) {
let disabledHeuristicsPref = Services.prefs.getBoolPref(
HEURISTICS_DISABLED_PREF
);
is(
disabledHeuristicsPref,
props.expectedDisabledHeuristics,
"disable-heuristics pref ended up with the expected value"
);
}
if (props.hasOwnProperty("expectedFinalCusomUriPref")) {
let customUriPref = Services.prefs.getStringPref(TRR_CUSTOM_URI_PREF);
is(
@ -260,7 +308,7 @@ let testVariations = [
{
name: "mode 1",
[TRR_MODE_PREF]: 1,
expectedModeChecked: true,
expectedModeChecked: false,
expectedFinalUriPref: DEFAULT_RESOLVER_VALUE,
},
{
@ -278,7 +326,7 @@ let testVariations = [
{
name: "mode 4",
[TRR_MODE_PREF]: 4,
expectedModeChecked: true,
expectedModeChecked: false,
expectedFinalUriPref: DEFAULT_RESOLVER_VALUE,
},
{ name: "mode 5", [TRR_MODE_PREF]: 5, expectedModeChecked: false },
@ -289,6 +337,32 @@ let testVariations = [
expectedModeChecked: false,
},
// verify automatic heuristics states
{
name: "heuristics on and mode unset",
[TRR_MODE_PREF]: 0,
[ROLLOUT_ENABLED_PREF]: true,
expectedModeChecked: true,
},
{
name: "heuristics on and mode set to 2",
[TRR_MODE_PREF]: 2,
[ROLLOUT_ENABLED_PREF]: true,
expectedModeChecked: true,
},
{
name: "heuristics on but disabled, mode unset",
[TRR_MODE_PREF]: 5,
[ROLLOUT_ENABLED_PREF]: true,
expectedModeChecked: false,
},
{
name: "heuristics on but disabled, mode set to 2",
[TRR_MODE_PREF]: 2,
[ROLLOUT_ENABLED_PREF]: true,
expectedModeChecked: true,
},
// verify toggling the checkbox gives the right outcomes
{
name: "toggle mode on",
@ -299,10 +373,19 @@ let testVariations = [
},
{
name: "toggle mode off",
[TRR_MODE_PREF]: 4,
[TRR_MODE_PREF]: 2,
expectedModeChecked: true,
clickMode: true,
expectedModePref: 0,
expectedModePref: 5,
},
{
name: "toggle mode off when on due to heuristics",
[TRR_MODE_PREF]: 0,
[ROLLOUT_ENABLED_PREF]: true,
expectedModeChecked: true,
clickMode: true,
expectedModePref: 5,
expectedDisabledHeuristics: true,
},
// Test selecting non-default, non-custom TRR provider, NextDNS.
{