From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../tests/browser_privacy_dnsoverhttps.js | 844 +++++++++++++++++++++ 1 file changed, 844 insertions(+) create mode 100644 browser/components/preferences/tests/browser_privacy_dnsoverhttps.js (limited to 'browser/components/preferences/tests/browser_privacy_dnsoverhttps.js') diff --git a/browser/components/preferences/tests/browser_privacy_dnsoverhttps.js b/browser/components/preferences/tests/browser_privacy_dnsoverhttps.js new file mode 100644 index 0000000000..48469cfce4 --- /dev/null +++ b/browser/components/preferences/tests/browser_privacy_dnsoverhttps.js @@ -0,0 +1,844 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(4); + +const { EnterprisePolicyTesting, PoliciesPrefTracker } = + ChromeUtils.importESModule( + "resource://testing-common/EnterprisePolicyTesting.sys.mjs" + ); + +ChromeUtils.defineESModuleGetters(this, { + DoHConfigController: "resource:///modules/DoHConfig.sys.mjs", + DoHController: "resource:///modules/DoHController.sys.mjs", + DoHTestUtils: "resource://testing-common/DoHTestUtils.sys.mjs", +}); + +const TRR_MODE_PREF = "network.trr.mode"; +const TRR_URI_PREF = "network.trr.uri"; +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 FIRST_RESOLVER_VALUE = DoHTestUtils.providers[0].uri; +const SECOND_RESOLVER_VALUE = DoHTestUtils.providers[1].uri; +const DEFAULT_RESOLVER_VALUE = FIRST_RESOLVER_VALUE; + +const defaultPrefValues = Object.freeze({ + [TRR_MODE_PREF]: 0, + [TRR_CUSTOM_URI_PREF]: "", +}); + +// See bug 1741554. This test should not actually try to create a connection to +// the real DoH endpoint. But a background request could do that while the test +// is in progress, before we've actually disabled TRR, and would cause a crash +// due to connecting to a non-local IP. +// To prevent that we override the IP to a local address. +Cc["@mozilla.org/network/native-dns-override;1"] + .getService(Ci.nsINativeDNSResolverOverride) + .addIPOverride("mozilla.cloudflare-dns.com", "127.0.0.1"); + +async function clearEvents() { + Services.telemetry.clearEvents(); + await TestUtils.waitForCondition(() => { + let events = Services.telemetry.snapshotEvents( + Ci.nsITelemetry.DATASET_ALL_CHANNELS, + true + ).parent; + return !events || !events.length; + }); +} + +async function getEvent(filter1, filter2) { + let event = await TestUtils.waitForCondition(() => { + let events = Services.telemetry.snapshotEvents( + Ci.nsITelemetry.DATASET_ALL_CHANNELS, + true + ).parent; + return events?.find(e => e[1] == filter1 && e[2] == filter2); + }, "recorded telemetry for the load"); + event.shift(); + return event; +} + +async function resetPrefs() { + await DoHTestUtils.resetRemoteSettingsConfig(); + await DoHController._uninit(); + Services.prefs.clearUserPref(TRR_MODE_PREF); + Services.prefs.clearUserPref(TRR_URI_PREF); + Services.prefs.clearUserPref(TRR_CUSTOM_URI_PREF); + Services.prefs.getChildList("doh-rollout.").forEach(pref => { + Services.prefs.clearUserPref(pref); + }); + // Clear out any telemetry events generated by DoHController so that we don't + // confuse tests running after this one that are looking at those. + Services.telemetry.clearEvents(); + await DoHController.init(); +} +Services.prefs.setStringPref("network.trr.confirmationNS", "skip"); + +registerCleanupFunction(async () => { + await resetPrefs(); + Services.prefs.clearUserPref("network.trr.confirmationNS"); +}); + +add_setup(async function setup() { + await SpecialPowers.pushPrefEnv({ + set: [["toolkit.telemetry.testing.overrideProductsCheck", true]], + }); + + await DoHTestUtils.resetRemoteSettingsConfig(); +}); + +function waitForPrefObserver(name) { + return new Promise(resolve => { + const observer = { + observe(aSubject, aTopic, aData) { + if (aData == name) { + Services.prefs.removeObserver(name, observer); + resolve(); + } + }, + }; + Services.prefs.addObserver(name, observer); + }); +} + +async function testWithProperties(props, startTime) { + info( + Date.now() - + startTime + + ": testWithProperties: testing with " + + JSON.stringify(props) + ); + + // There are two different signals that the DoHController is ready, depending + // on the config being tested. If we're setting the TRR mode pref, we should + // expect the disable-heuristics pref to be set as the signal. Else, we can + // expect the self-enabled pref as the signal. + let rolloutReadyPromise; + if (props.hasOwnProperty(TRR_MODE_PREF)) { + if ( + [2, 3, 5].includes(props[TRR_MODE_PREF]) && + props.hasOwnProperty(ROLLOUT_ENABLED_PREF) + ) { + // Only initialize the promise if we're going to enable the rollout - + // otherwise we will never await it, which could cause a leak if it doesn't + // end up resolving. + rolloutReadyPromise = waitForPrefObserver(HEURISTICS_DISABLED_PREF); + } + Services.prefs.setIntPref(TRR_MODE_PREF, props[TRR_MODE_PREF]); + } + if (props.hasOwnProperty(ROLLOUT_ENABLED_PREF)) { + if (!rolloutReadyPromise) { + rolloutReadyPromise = waitForPrefObserver(ROLLOUT_SELF_ENABLED_PREF); + } + Services.prefs.setBoolPref( + ROLLOUT_ENABLED_PREF, + props[ROLLOUT_ENABLED_PREF] + ); + await rolloutReadyPromise; + } + if (props.hasOwnProperty(TRR_CUSTOM_URI_PREF)) { + Services.prefs.setStringPref( + TRR_CUSTOM_URI_PREF, + props[TRR_CUSTOM_URI_PREF] + ); + } + if (props.hasOwnProperty(TRR_URI_PREF)) { + Services.prefs.setStringPref(TRR_URI_PREF, props[TRR_URI_PREF]); + } + + await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); + let doc = gBrowser.selectedBrowser.contentDocument; + + info(Date.now() - startTime + ": testWithProperties: tab now open"); + let modeRadioGroup = doc.getElementById("dohCategoryRadioGroup"); + let uriTextbox = doc.getElementById("dohEnabledInputField"); + let resolverMenulist = doc.getElementById("dohStrictResolverChoices"); + let modePrefChangedPromise; + let uriPrefChangedPromise; + let disableHeuristicsPrefChangedPromise; + + modeRadioGroup.scrollIntoView(); + + if (props.hasOwnProperty("expectedSelectedIndex")) { + await TestUtils.waitForCondition( + () => modeRadioGroup.selectedIndex === props.expectedSelectedIndex + ); + is( + modeRadioGroup.selectedIndex, + props.expectedSelectedIndex, + "dohCategoryRadioGroup has expected selected index" + ); + } + if (props.hasOwnProperty("expectedUriValue")) { + await TestUtils.waitForCondition( + () => uriTextbox.value === props.expectedUriValue + ); + is( + uriTextbox.value, + props.expectedUriValue, + "URI textbox has expected value" + ); + } + if (props.hasOwnProperty("expectedResolverListValue")) { + await TestUtils.waitForCondition( + () => resolverMenulist.value === props.expectedResolverListValue + ); + is( + resolverMenulist.value, + props.expectedResolverListValue, + "resolver menulist has expected value" + ); + } + + if (props.clickMode) { + await clearEvents(); + info( + Date.now() - + 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" + ); + let option = doc.getElementById(props.clickMode); + option.scrollIntoView(); + let win = doc.ownerGlobal; + EventUtils.synthesizeMouseAtCenter(option, {}, win); + info( + `${Date.now() - startTime} : testWithProperties: clickMode=${ + props.clickMode + }, mouse click synthesized` + ); + let clickEvent = await getEvent("security.doh.settings", "mode_changed"); + Assert.deepEqual(clickEvent, [ + "security.doh.settings", + "mode_changed", + "button", + props.clickMode, + ]); + } + if (props.hasOwnProperty("selectResolver")) { + await clearEvents(); + info( + Date.now() - + startTime + + ": testWithProperties: selectResolver, creating change event" + ); + resolverMenulist.focus(); + resolverMenulist.value = props.selectResolver; + resolverMenulist.dispatchEvent(new Event("input", { bubbles: true })); + resolverMenulist.dispatchEvent(new Event("command", { bubbles: true })); + info( + Date.now() - + startTime + + ": testWithProperties: selectResolver, item value set and events dispatched" + ); + let choiceEvent = await getEvent( + "security.doh.settings", + "provider_choice" + ); + Assert.deepEqual(choiceEvent, [ + "security.doh.settings", + "provider_choice", + "value", + props.selectResolver, + ]); + } + if (props.hasOwnProperty("inputUriKeys")) { + info( + Date.now() - + startTime + + ": testWithProperties: inputUriKeys, waiting for the pref observer" + ); + uriPrefChangedPromise = waitForPrefObserver(TRR_CUSTOM_URI_PREF); + info( + Date.now() - + startTime + + ": testWithProperties: inputUriKeys, pref changed, now enter the new value" + ); + let win = doc.ownerGlobal; + uriTextbox.focus(); + uriTextbox.value = props.inputUriKeys; + uriTextbox.dispatchEvent(new win.Event("input", { bubbles: true })); + uriTextbox.dispatchEvent(new win.Event("change", { bubbles: true })); + info( + Date.now() - + startTime + + ": testWithProperties: inputUriKeys, input and change events dispatched" + ); + } + + info( + Date.now() - + startTime + + ": testWithProperties: waiting for any of uri and mode prefs to change" + ); + await Promise.all([ + uriPrefChangedPromise, + modePrefChangedPromise, + disableHeuristicsPrefChangedPromise, + ]); + info(Date.now() - startTime + ": testWithProperties: prefs changed"); + + if (props.hasOwnProperty("expectedFinalUriPref")) { + if (props.expectedFinalUriPref) { + let uriPref = Services.prefs.getStringPref(TRR_URI_PREF); + is( + uriPref, + props.expectedFinalUriPref, + "uri pref ended up with the expected value" + ); + } else { + ok( + !Services.prefs.prefHasUserValue(TRR_URI_PREF), + `uri pref ended up with the expected value (unset) got ${Services.prefs.getStringPref( + TRR_URI_PREF + )}` + ); + } + } + + if (props.hasOwnProperty("expectedModePref")) { + let modePref = Services.prefs.getIntPref(TRR_MODE_PREF); + is( + modePref, + props.expectedModePref, + "mode pref ended up with the expected value" + ); + } + + 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("expectedFinalCustomUriPref")) { + let customUriPref = Services.prefs.getStringPref(TRR_CUSTOM_URI_PREF); + is( + customUriPref, + props.expectedFinalCustomUriPref, + "custom_uri pref ended up with the expected value" + ); + } + + if (props.hasOwnProperty("expectedModeValue")) { + let modeValue = Services.prefs.getIntPref(TRR_MODE_PREF); + is(modeValue, props.expectedModeValue, "mode pref has expected value"); + } + + gBrowser.removeCurrentTab(); + info(Date.now() - startTime + ": testWithProperties: fin"); +} + +add_task(async function default_values() { + let customUriPref = Services.prefs.getStringPref(TRR_CUSTOM_URI_PREF); + let uriPrefHasUserValue = Services.prefs.prefHasUserValue(TRR_URI_PREF); + let modePref = Services.prefs.getIntPref(TRR_MODE_PREF); + is( + modePref, + defaultPrefValues[TRR_MODE_PREF], + `Actual value of ${TRR_MODE_PREF} matches expected default value` + ); + ok( + !uriPrefHasUserValue, + `Actual value of ${TRR_URI_PREF} matches expected default value (unset)` + ); + is( + customUriPref, + defaultPrefValues[TRR_CUSTOM_URI_PREF], + `Actual value of ${TRR_CUSTOM_URI_PREF} matches expected default value` + ); +}); + +const DEFAULT_OPTION_INDEX = 0; +const ENABLED_OPTION_INDEX = 1; +const STRICT_OPTION_INDEX = 2; +const OFF_OPTION_INDEX = 3; + +let testVariations = [ + // verify state with defaults + { + name: "default", + expectedModePref: 0, + expectedSelectedIndex: DEFAULT_OPTION_INDEX, + expectedUriValue: "", + }, + + // verify each of the modes maps to the correct checked state + { + name: "mode 0", + [TRR_MODE_PREF]: 0, + expectedSelectedIndex: DEFAULT_OPTION_INDEX, + }, + { + name: "mode 1", + [TRR_MODE_PREF]: 1, + expectedSelectedIndex: OFF_OPTION_INDEX, + }, + { + name: "mode 2", + [TRR_MODE_PREF]: 2, + expectedSelectedIndex: ENABLED_OPTION_INDEX, + expectedFinalUriPref: "", + }, + { + name: "mode 3", + [TRR_MODE_PREF]: 3, + expectedSelectedIndex: STRICT_OPTION_INDEX, + expectedFinalUriPref: "", + }, + { + name: "mode 4", + [TRR_MODE_PREF]: 4, + expectedSelectedIndex: OFF_OPTION_INDEX, + }, + { + name: "mode 5", + [TRR_MODE_PREF]: 5, + expectedSelectedIndex: OFF_OPTION_INDEX, + }, + // verify an out of bounds mode value maps to the correct checked state + { + name: "mode out-of-bounds", + [TRR_MODE_PREF]: 77, + expectedSelectedIndex: OFF_OPTION_INDEX, + }, + + // verify automatic heuristics states + { + name: "heuristics on and mode unset", + [TRR_MODE_PREF]: 0, + [ROLLOUT_ENABLED_PREF]: true, + expectedSelectedIndex: DEFAULT_OPTION_INDEX, + }, + { + name: "heuristics on and mode set to 2", + [TRR_MODE_PREF]: 2, + [ROLLOUT_ENABLED_PREF]: true, + expectedSelectedIndex: ENABLED_OPTION_INDEX, + }, + { + name: "heuristics on but disabled, mode unset", + [TRR_MODE_PREF]: 5, + [ROLLOUT_ENABLED_PREF]: true, + expectedSelectedIndex: OFF_OPTION_INDEX, + }, + { + name: "heuristics on but disabled, mode set to 2", + [TRR_MODE_PREF]: 2, + [ROLLOUT_ENABLED_PREF]: true, + expectedSelectedIndex: ENABLED_OPTION_INDEX, + }, + + // verify picking each radio button option gives the right outcomes + { + name: "toggle mode on", + clickMode: "dohEnabledRadio", + expectedModeValue: 2, + expectedUriValue: "", + expectedFinalUriPref: "", + }, + { + name: "toggle mode off", + [TRR_MODE_PREF]: 2, + expectedSelectedIndex: ENABLED_OPTION_INDEX, + clickMode: "dohOffRadio", + expectedModePref: 5, + }, + { + name: "toggle mode off when on due to heuristics", + [TRR_MODE_PREF]: 0, + [ROLLOUT_ENABLED_PREF]: true, + expectedSelectedIndex: DEFAULT_OPTION_INDEX, + clickMode: "dohOffRadio", + expectedModePref: 5, + expectedDisabledHeuristics: true, + }, + // Test selecting non-default, non-custom TRR provider, NextDNS. + { + name: "Select NextDNS as TRR provider", + [TRR_MODE_PREF]: 2, + selectResolver: SECOND_RESOLVER_VALUE, + expectedFinalUriPref: SECOND_RESOLVER_VALUE, + }, + // Test selecting non-default, non-custom TRR provider, NextDNS, + // with DoH not enabled. The provider selection should stick. + { + name: "Select NextDNS as TRR provider in mode 0", + [TRR_MODE_PREF]: 0, + selectResolver: SECOND_RESOLVER_VALUE, + expectedFinalUriPref: SECOND_RESOLVER_VALUE, + }, + { + name: "return to default from NextDNS", + [TRR_MODE_PREF]: 2, + [TRR_URI_PREF]: SECOND_RESOLVER_VALUE, + expectedResolverListValue: SECOND_RESOLVER_VALUE, + selectResolver: DEFAULT_RESOLVER_VALUE, + expectedFinalUriPref: FIRST_RESOLVER_VALUE, + }, + // test that selecting Custom, when we have a TRR_CUSTOM_URI_PREF subsequently changes TRR_URI_PREF + { + name: "select custom with existing custom_uri pref value", + [TRR_MODE_PREF]: 2, + [TRR_CUSTOM_URI_PREF]: "https://example.com", + expectedModeValue: 2, + expectedSelectedIndex: ENABLED_OPTION_INDEX, + selectResolver: "custom", + expectedUriValue: "https://example.com", + expectedFinalUriPref: "https://example.com", + expectedFinalCustomUriPref: "https://example.com", + }, + { + name: "select custom and enter new custom_uri pref value", + [TRR_URI_PREF]: "", + [TRR_CUSTOM_URI_PREF]: "", + clickMode: "dohEnabledRadio", + selectResolver: "custom", + inputUriKeys: "https://custom.com", + expectedModePref: 2, + expectedFinalUriPref: "https://custom.com", + expectedFinalCustomUriPref: "https://custom.com", + }, + + { + name: "return to default from custom", + [TRR_MODE_PREF]: 2, + [TRR_URI_PREF]: "https://example.com", + [TRR_CUSTOM_URI_PREF]: "https://custom.com", + expectedUriValue: "https://example.com", + expectedResolverListValue: "custom", + selectResolver: DEFAULT_RESOLVER_VALUE, + expectedFinalUriPref: DEFAULT_RESOLVER_VALUE, + expectedFinalCustomUriPref: "https://example.com", + }, + { + name: "clear the custom uri", + [TRR_MODE_PREF]: 2, + [TRR_URI_PREF]: "https://example.com", + [TRR_CUSTOM_URI_PREF]: "https://example.com", + expectedUriValue: "https://example.com", + expectedResolverListValue: "custom", + inputUriKeys: "", + expectedFinalUriPref: " ", + expectedFinalCustomUriPref: "", + }, + { + name: "empty default resolver list", + [TRR_MODE_PREF]: 2, + [TRR_URI_PREF]: "https://example.com", + [TRR_CUSTOM_URI_PREF]: "", + expectedUriValue: "https://example.com", + expectedResolverListValue: "custom", + expectedFinalUriPref: "https://example.com", + expectedFinalCustomUriPref: "https://example.com", + }, +]; + +for (let props of testVariations) { + add_task(async function testVariation() { + let startTime = Date.now(); + info("starting test: " + props.name); + await testWithProperties(props, startTime); + await resetPrefs(); + }); +} + +add_task(async function testRemoteSettingsEnable() { + let startTime = Date.now(); + // Enable the rollout. + await DoHTestUtils.loadRemoteSettingsConfig({ + providers: "example-1, example-2", + rolloutEnabled: true, + steeringEnabled: false, + steeringProviders: "", + autoDefaultEnabled: false, + autoDefaultProviders: "", + id: "global", + }); + + await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); + let doc = gBrowser.selectedBrowser.contentDocument; + + info(Date.now() - startTime + ": testWithProperties: tab now open"); + let modeRadioGroup = doc.getElementById("dohCategoryRadioGroup"); + + is(modeRadioGroup.value, "0", "expecting default mode"); + + let status = doc.getElementById("dohStatus"); + await TestUtils.waitForCondition( + () => document.l10n.getAttributes(status).args.status == "Active" + ); + is( + document.l10n.getAttributes(status).args.status, + "Active", + "expecting status active" + ); + + let provider = doc.getElementById("dohResolver"); + is( + provider.hidden, + false, + "Provider should not be hidden when status is active" + ); + await TestUtils.waitForCondition( + () => + document.l10n.getAttributes(provider).args.name == + DoHConfigController.currentConfig.providerList[0].UIName + ); + is( + document.l10n.getAttributes(provider).args.name, + DoHConfigController.currentConfig.providerList[0].UIName, + "expecting the right provider name" + ); + + let option = doc.getElementById("dohEnabledRadio"); + option.scrollIntoView(); + let win = doc.ownerGlobal; + EventUtils.synthesizeMouseAtCenter(option, {}, win); + + await TestUtils.waitForCondition(() => + Services.prefs.prefHasUserValue("doh-rollout.disable-heuristics") + ); + is(provider.hidden, false); + await TestUtils.waitForCondition( + () => + document.l10n.getAttributes(provider).args.name == + DoHConfigController.currentConfig.providerList[0].UIName + ); + is( + document.l10n.getAttributes(provider).args.name, + DoHConfigController.currentConfig.providerList[0].UIName, + "expecting the right provider name" + ); + is( + Services.prefs.getIntPref("network.trr.mode"), + Ci.nsIDNSService.MODE_TRRFIRST + ); + + option = doc.getElementById("dohOffRadio"); + option.scrollIntoView(); + win = doc.ownerGlobal; + EventUtils.synthesizeMouseAtCenter(option, {}, win); + await TestUtils.waitForCondition(() => status.innerHTML == "Status: Off"); + is( + Services.prefs.getIntPref("network.trr.mode"), + Ci.nsIDNSService.MODE_TRROFF + ); + is(provider.hidden, true, "Expecting provider to be hidden when DoH is off"); + + gBrowser.removeCurrentTab(); +}); + +add_task(async function testEnterprisePolicy() { + async function withPolicy(policy, fn, preFn = () => {}) { + await resetPrefs(); + PoliciesPrefTracker.start(); + await EnterprisePolicyTesting.setupPolicyEngineWithJson(policy); + await preFn(); + + await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); + let doc = gBrowser.selectedBrowser.contentDocument; + + let modeRadioGroup = doc.getElementById("dohCategoryRadioGroup"); + let resolverMenulist = doc.getElementById("dohEnabledResolverChoices"); + let uriTextbox = doc.getElementById("dohEnabledInputField"); + + await fn({ + modeRadioGroup, + resolverMenulist, + doc, + uriTextbox, + }); + + gBrowser.removeCurrentTab(); + EnterprisePolicyTesting.resetRunOnceState(); + PoliciesPrefTracker.stop(); + } + + info("Check that a locked policy does not allow any changes in the UI"); + await withPolicy( + { + policies: { + DNSOverHTTPS: { + Enabled: true, + ProviderURL: "https://examplelocked.com/provider", + ExcludedDomains: ["examplelocked.com", "example.org"], + Locked: true, + }, + }, + }, + async res => { + is(res.modeRadioGroup.disabled, true, "The mode menu should be locked."); + is(res.modeRadioGroup.value, "2", "Should be enabled"); + is(res.resolverMenulist.value, "custom", "Resolver list shows custom"); + is( + res.uriTextbox.value, + "https://examplelocked.com/provider", + "Custom URI should be set" + ); + } + ); + + info("Check that an unlocked policy has editable fields in the dialog"); + await withPolicy( + { + policies: { + DNSOverHTTPS: { + Enabled: true, + ProviderURL: "https://example.com/provider", + ExcludedDomains: ["example.com", "example.org"], + }, + }, + }, + async res => { + is( + res.modeRadioGroup.disabled, + false, + "The mode menu should not be locked." + ); + is(res.modeRadioGroup.value, "2", "Should be enabled"); + is(res.resolverMenulist.value, "custom", "Resolver list shows custom"); + is( + res.uriTextbox.value, + "https://example.com/provider", + "Expected custom resolver" + ); + } + ); + + info("Check that a locked disabled policy disables the buttons"); + await withPolicy( + { + policies: { + DNSOverHTTPS: { + Enabled: false, + ProviderURL: "https://example.com/provider", + ExcludedDomains: ["example.com", "example.org"], + Locked: true, + }, + }, + }, + async res => { + is(res.modeRadioGroup.disabled, true, "The mode menu should be locked."); + is(res.modeRadioGroup.value, "5", "Should be disabled"); + } + ); + + info("Check that an unlocked disabled policy has editable fields"); + await withPolicy( + { + policies: { + DNSOverHTTPS: { + Enabled: false, + ProviderURL: "https://example.com/provider", + ExcludedDomains: ["example.com", "example.org"], + }, + }, + }, + async res => { + is( + res.modeRadioGroup.disabled, + false, + "The mode menu should not be locked." + ); + is(res.modeRadioGroup.value, "5", "Should be disabled"); + } + ); + + info("Check that the remote settings config doesn't override the policy"); + await withPolicy( + { + policies: { + DNSOverHTTPS: { + Enabled: true, + ProviderURL: "https://example.com/provider", + ExcludedDomains: ["example.com", "example.org"], + }, + }, + }, + async res => { + is( + res.modeRadioGroup.disabled, + false, + "The mode menu should not be locked." + ); + is(res.resolverMenulist.value, "custom", "Resolver list shows custom"); + is( + res.uriTextbox.value, + "https://example.com/provider", + "Expected custom resolver" + ); + }, + async function runAfterSettingPolicy() { + await DoHTestUtils.loadRemoteSettingsConfig({ + providers: "example-1, example-2", + rolloutEnabled: true, + steeringEnabled: false, + steeringProviders: "", + autoDefaultEnabled: false, + autoDefaultProviders: "", + id: "global", + }); + } + ); +}); + +add_task(async function clickWarnButton() { + Services.prefs.setBoolPref( + "network.trr_ui.show_fallback_warning_option", + true + ); + + await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); + let doc = gBrowser.selectedBrowser.contentDocument; + + await clearEvents(); + let checkbox = doc.getElementById("dohWarnCheckbox1"); + checkbox.click(); + + let event = await getEvent("security.doh.settings", "warn_checkbox"); + Assert.deepEqual(event, [ + "security.doh.settings", + "warn_checkbox", + "checkbox", + "true", + ]); + Assert.equal( + Services.prefs.getBoolPref("network.trr.display_fallback_warning"), + true, + "Clicking the checkbox should change the pref" + ); + + checkbox.click(); + event = await getEvent("security.doh.settings", "warn_checkbox"); + Assert.deepEqual(event, [ + "security.doh.settings", + "warn_checkbox", + "checkbox", + "false", + ]); + Assert.equal( + Services.prefs.getBoolPref("network.trr.display_fallback_warning"), + false, + "Clicking the checkbox should change the pref" + ); + gBrowser.removeCurrentTab(); +}); -- cgit v1.2.3