зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1713036, bug 1714486) for XPCshell failures in netwerk/test/unit/test_trr.js. CLOSED TREE
Backed out changeset 06c40198b074 (bug 1713036) Backed out changeset 41800e77c675 (bug 1714486)
This commit is contained in:
Родитель
a019a450b2
Коммит
1779a0d311
|
@ -2039,6 +2039,17 @@ pref("extensions.screenshots.disabled", false);
|
|||
// Preference that determines whether Screenshots is opened as a dedicated browser component
|
||||
pref("screenshots.browser.component.enabled", false);
|
||||
|
||||
// DoH Rollout: whether to enable automatic performance-based TRR-selection.
|
||||
// This pref is controlled by a Normandy rollout so we don't overload providers.
|
||||
pref("doh-rollout.trr-selection.enabled", false);
|
||||
|
||||
// DoH Rollout: whether to enable automatic steering to provider endpoints.
|
||||
// This pref is also controlled by a Normandy rollout.
|
||||
pref("doh-rollout.provider-steering.enabled", true);
|
||||
|
||||
// DoH Rollout: provider details for automatic steering.
|
||||
pref("doh-rollout.provider-steering.provider-list", "[{ \"name\": \"comcast\", \"canonicalName\": \"doh-discovery.xfinity.com\", \"uri\": \"https://doh.xfinity.com/dns-query\" }]");
|
||||
|
||||
// DoH Rollout: whether to clear the mode value at shutdown.
|
||||
pref("doh-rollout.clearModeOnShutdown", false);
|
||||
|
||||
|
|
|
@ -26,39 +26,36 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
const kGlobalPrefBranch = "doh-rollout";
|
||||
var kRegionPrefBranch;
|
||||
|
||||
const kConfigPrefs = {
|
||||
kEnabledPref: "enabled",
|
||||
kProvidersPref: "provider-list",
|
||||
kTRRSelectionEnabledPref: "trr-selection.enabled",
|
||||
kTRRSelectionProvidersPref: "trr-selection.provider-list",
|
||||
kTRRSelectionCommitResultPref: "trr-selection.commit-result",
|
||||
kProviderSteeringEnabledPref: "provider-steering.enabled",
|
||||
kProviderSteeringListPref: "provider-steering.provider-list",
|
||||
};
|
||||
const kEnabledPref = "enabled";
|
||||
|
||||
const kProvidersPref = "provider-list";
|
||||
|
||||
const kTRRSelectionEnabledPref = "trr-selection.enabled";
|
||||
const kTRRSelectionProvidersPref = "trr-selection.provider-list";
|
||||
const kTRRSelectionCommitResultPref = "trr-selection.commit-result";
|
||||
|
||||
const kProviderSteeringEnabledPref = "provider-steering.enabled";
|
||||
const kProviderSteeringListPref = "provider-steering.provider-list";
|
||||
|
||||
const kPrefChangedTopic = "nsPref:changed";
|
||||
|
||||
const gProvidersCollection = RemoteSettings("doh-providers");
|
||||
const gConfigCollection = RemoteSettings("doh-config");
|
||||
|
||||
function getPrefValueRegionFirst(prefName) {
|
||||
let regionalPrefName = `${kRegionPrefBranch}.${prefName}`;
|
||||
if (Services.prefs.prefHasUserValue(regionalPrefName)) {
|
||||
return Preferences.get(regionalPrefName);
|
||||
}
|
||||
return Preferences.get(`${kGlobalPrefBranch}.${prefName}`);
|
||||
function getPrefValueRegionFirst(prefName, defaultValue) {
|
||||
return (
|
||||
Preferences.get(`${kRegionPrefBranch}.${prefName}`) ||
|
||||
Preferences.get(`${kGlobalPrefBranch}.${prefName}`, defaultValue)
|
||||
);
|
||||
}
|
||||
|
||||
function getProviderListFromPref(prefName) {
|
||||
let prefVal = getPrefValueRegionFirst(prefName);
|
||||
if (prefVal) {
|
||||
try {
|
||||
return JSON.parse(prefVal);
|
||||
return JSON.parse(getPrefValueRegionFirst(prefName, "[]"));
|
||||
} catch (e) {
|
||||
Cu.reportError(`DoH provider list not a valid JSON array: ${prefName}`);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
return [];
|
||||
}
|
||||
|
||||
// Generate a base config object with getters that return pref values. When
|
||||
|
@ -68,94 +65,43 @@ function getProviderListFromPref(prefName) {
|
|||
// from it, we lose the ability to override getters because they are defined
|
||||
// as non-configureable properties on class instances. So just use a function.
|
||||
function makeBaseConfigObject() {
|
||||
function makeConfigProperty({
|
||||
obj,
|
||||
propName,
|
||||
defaultVal,
|
||||
prefName,
|
||||
isProviderList,
|
||||
}) {
|
||||
let prefFn = isProviderList
|
||||
? getProviderListFromPref
|
||||
: getPrefValueRegionFirst;
|
||||
|
||||
let overridePropName = "_" + propName;
|
||||
|
||||
Object.defineProperty(obj, propName, {
|
||||
get() {
|
||||
// If a pref value exists, it gets top priority. Otherwise, if it has an
|
||||
// explicitly set value (from Remote Settings), we return that.
|
||||
let prefVal = prefFn(prefName);
|
||||
if (prefVal !== undefined) {
|
||||
return prefVal;
|
||||
}
|
||||
if (this[overridePropName] !== undefined) {
|
||||
return this[overridePropName];
|
||||
}
|
||||
return defaultVal;
|
||||
return {
|
||||
get enabled() {
|
||||
return getPrefValueRegionFirst(kEnabledPref, false);
|
||||
},
|
||||
set(val) {
|
||||
this[overridePropName] = val;
|
||||
|
||||
get providerList() {
|
||||
return getProviderListFromPref(kProvidersPref);
|
||||
},
|
||||
});
|
||||
}
|
||||
let newConfig = {
|
||||
|
||||
get fallbackProviderURI() {
|
||||
return this.providerList[0]?.uri;
|
||||
},
|
||||
trrSelection: {},
|
||||
providerSteering: {},
|
||||
|
||||
trrSelection: {
|
||||
get enabled() {
|
||||
return getPrefValueRegionFirst(kTRRSelectionEnabledPref, false);
|
||||
},
|
||||
|
||||
get commitResult() {
|
||||
return getPrefValueRegionFirst(kTRRSelectionCommitResultPref, false);
|
||||
},
|
||||
|
||||
get providerList() {
|
||||
return getProviderListFromPref(kTRRSelectionProvidersPref);
|
||||
},
|
||||
},
|
||||
|
||||
providerSteering: {
|
||||
get enabled() {
|
||||
return getPrefValueRegionFirst(kProviderSteeringEnabledPref, false);
|
||||
},
|
||||
|
||||
get providerList() {
|
||||
return getProviderListFromPref(kProviderSteeringListPref);
|
||||
},
|
||||
},
|
||||
};
|
||||
makeConfigProperty({
|
||||
obj: newConfig,
|
||||
propName: "enabled",
|
||||
defaultVal: false,
|
||||
prefName: kConfigPrefs.kEnabledPref,
|
||||
isProviderList: false,
|
||||
});
|
||||
makeConfigProperty({
|
||||
obj: newConfig,
|
||||
propName: "providerList",
|
||||
defaultVal: [],
|
||||
prefName: kConfigPrefs.kProvidersPref,
|
||||
isProviderList: true,
|
||||
});
|
||||
makeConfigProperty({
|
||||
obj: newConfig.trrSelection,
|
||||
propName: "enabled",
|
||||
defaultVal: false,
|
||||
prefName: kConfigPrefs.kTRRSelectionEnabledPref,
|
||||
isProviderList: false,
|
||||
});
|
||||
makeConfigProperty({
|
||||
obj: newConfig.trrSelection,
|
||||
propName: "commitResult",
|
||||
defaultVal: false,
|
||||
prefName: kConfigPrefs.kTRRSelectionCommitResultPref,
|
||||
isProviderList: false,
|
||||
});
|
||||
makeConfigProperty({
|
||||
obj: newConfig.trrSelection,
|
||||
propName: "providerList",
|
||||
defaultVal: [],
|
||||
prefName: kConfigPrefs.kTRRSelectionProvidersPref,
|
||||
isProviderList: true,
|
||||
});
|
||||
makeConfigProperty({
|
||||
obj: newConfig.providerSteering,
|
||||
propName: "enabled",
|
||||
defaultVal: false,
|
||||
prefName: kConfigPrefs.kProviderSteeringEnabledPref,
|
||||
isProviderList: false,
|
||||
});
|
||||
makeConfigProperty({
|
||||
obj: newConfig.providerSteering,
|
||||
propName: "providerList",
|
||||
defaultVal: [],
|
||||
prefName: kConfigPrefs.kProviderSteeringListPref,
|
||||
isProviderList: true,
|
||||
});
|
||||
return newConfig;
|
||||
}
|
||||
|
||||
const DoHConfigController = {
|
||||
|
@ -226,16 +172,10 @@ const DoHConfigController = {
|
|||
observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case kPrefChangedTopic:
|
||||
let allowedPrefs = Object.getOwnPropertyNames(kConfigPrefs).map(
|
||||
k => kConfigPrefs[k]
|
||||
);
|
||||
if (
|
||||
!allowedPrefs.some(pref =>
|
||||
[
|
||||
`${kRegionPrefBranch}.${pref}`,
|
||||
`${kGlobalPrefBranch}.${pref}`,
|
||||
].includes(data)
|
||||
)
|
||||
!data.startsWith(kRegionPrefBranch) &&
|
||||
data != `${kGlobalPrefBranch}.${kEnabledPref}` &&
|
||||
data != `${kGlobalPrefBranch}.${kProvidersPref}`
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
@ -280,6 +220,7 @@ const DoHConfigController = {
|
|||
}
|
||||
|
||||
if (localConfig.rolloutEnabled) {
|
||||
delete newConfig.enabled;
|
||||
newConfig.enabled = true;
|
||||
}
|
||||
|
||||
|
@ -301,6 +242,7 @@ const DoHConfigController = {
|
|||
|
||||
let regionalProviders = parseProviderList(localConfig.providers);
|
||||
if (regionalProviders?.length) {
|
||||
delete newConfig.providerList;
|
||||
newConfig.providerList = regionalProviders;
|
||||
}
|
||||
|
||||
|
@ -310,7 +252,10 @@ const DoHConfigController = {
|
|||
p => p.canonicalName?.length
|
||||
);
|
||||
if (steeringProviders?.length) {
|
||||
delete newConfig.providerSteering.providerList;
|
||||
newConfig.providerSteering.providerList = steeringProviders;
|
||||
|
||||
delete newConfig.providerSteering.enabled;
|
||||
newConfig.providerSteering.enabled = true;
|
||||
}
|
||||
}
|
||||
|
@ -320,7 +265,10 @@ const DoHConfigController = {
|
|||
localConfig.autoDefaultProviders
|
||||
);
|
||||
if (defaultProviders?.length) {
|
||||
delete newConfig.trrSelection.providerList;
|
||||
newConfig.trrSelection.providerList = defaultProviders;
|
||||
|
||||
delete newConfig.trrSelection.enabled;
|
||||
newConfig.trrSelection.enabled = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,13 +29,10 @@ add_task(async function testProviderSteering() {
|
|||
uri: "https://bar.provider2.com/query",
|
||||
},
|
||||
];
|
||||
let configFlushPromise = DoHTestUtils.waitForConfigFlush();
|
||||
Preferences.set(
|
||||
prefs.PROVIDER_STEERING_LIST_PREF,
|
||||
JSON.stringify(providerTestcases)
|
||||
);
|
||||
await configFlushPromise;
|
||||
await checkHeuristicsTelemetry("enable_doh", "startup");
|
||||
|
||||
let testNetChangeResult = async (
|
||||
expectedURI,
|
||||
|
|
|
@ -7,18 +7,6 @@
|
|||
add_task(setup);
|
||||
add_task(setupRegion);
|
||||
|
||||
async function setPrefAndWaitForConfigFlush(pref, value) {
|
||||
let configFlushedPromise = DoHTestUtils.waitForConfigFlush();
|
||||
Preferences.set(pref, value);
|
||||
await configFlushedPromise;
|
||||
}
|
||||
|
||||
async function clearPrefAndWaitForConfigFlush(pref, value) {
|
||||
let configFlushedPromise = DoHTestUtils.waitForConfigFlush();
|
||||
Preferences.reset(pref);
|
||||
await configFlushedPromise;
|
||||
}
|
||||
|
||||
add_task(async function testNewProfile() {
|
||||
is(
|
||||
DoHConfigController.currentConfig.enabled,
|
||||
|
@ -64,7 +52,6 @@ add_task(async function testNewProfile() {
|
|||
"Rollout should be enabled"
|
||||
);
|
||||
await ensureTRRMode(2);
|
||||
await checkHeuristicsTelemetry("enable_doh", "startup");
|
||||
Assert.deepEqual(
|
||||
DoHConfigController.currentConfig.providerList,
|
||||
[provider1, provider3],
|
||||
|
@ -96,46 +83,6 @@ add_task(async function testNewProfile() {
|
|||
"Fallback provider URI should be that of the first one"
|
||||
);
|
||||
|
||||
// Test that overriding with prefs works.
|
||||
await setPrefAndWaitForConfigFlush(prefs.PROVIDER_STEERING_PREF, false);
|
||||
is(
|
||||
DoHConfigController.currentConfig.providerSteering.enabled,
|
||||
false,
|
||||
"Provider steering should be disabled"
|
||||
);
|
||||
await ensureTRRMode(2);
|
||||
await checkHeuristicsTelemetry("enable_doh", "startup");
|
||||
|
||||
await setPrefAndWaitForConfigFlush(prefs.TRR_SELECT_ENABLED_PREF, false);
|
||||
is(
|
||||
DoHConfigController.currentConfig.trrSelection.enabled,
|
||||
false,
|
||||
"TRR selection should be disabled"
|
||||
);
|
||||
await ensureTRRMode(2);
|
||||
await checkHeuristicsTelemetry("enable_doh", "startup");
|
||||
|
||||
// Try a regional pref this time
|
||||
await setPrefAndWaitForConfigFlush(
|
||||
`${kRegionalPrefNamespace}.enabled`,
|
||||
false
|
||||
);
|
||||
is(
|
||||
DoHConfigController.currentConfig.enabled,
|
||||
false,
|
||||
"Rollout should be disabled"
|
||||
);
|
||||
await ensureTRRMode(undefined);
|
||||
await ensureNoHeuristicsTelemetry();
|
||||
|
||||
await clearPrefAndWaitForConfigFlush(`${kRegionalPrefNamespace}.enabled`);
|
||||
|
||||
is(
|
||||
DoHConfigController.currentConfig.enabled,
|
||||
true,
|
||||
"Rollout should be enabled"
|
||||
);
|
||||
|
||||
await DoHTestUtils.resetRemoteSettingsConfig();
|
||||
|
||||
is(
|
||||
|
|
|
@ -4,22 +4,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
async function waitForStartup() {
|
||||
await ensureTRRMode(2);
|
||||
await checkHeuristicsTelemetry("enable_doh", "startup");
|
||||
}
|
||||
|
||||
async function setPrefAndWaitForConfigFlush(pref, value) {
|
||||
let configFlushed = DoHTestUtils.waitForConfigFlush();
|
||||
if (value) {
|
||||
Preferences.set(pref, value);
|
||||
} else {
|
||||
Preferences.reset(pref);
|
||||
}
|
||||
await configFlushed;
|
||||
await waitForStartup();
|
||||
}
|
||||
|
||||
add_task(setup);
|
||||
|
||||
add_task(async function testTRRSelect() {
|
||||
|
@ -42,22 +26,25 @@ add_task(async function testTRRSelect() {
|
|||
// Reset and restart the controller for good measure.
|
||||
Preferences.reset(prefs.TRR_SELECT_DRY_RUN_RESULT_PREF);
|
||||
Preferences.reset(prefs.TRR_SELECT_URI_PREF);
|
||||
await restartDoHController();
|
||||
await waitForStartup();
|
||||
|
||||
prefPromise = TestUtils.waitForPrefChange(prefs.TRR_SELECT_URI_PREF);
|
||||
await restartDoHController();
|
||||
await prefPromise;
|
||||
is(
|
||||
Preferences.get(prefs.TRR_SELECT_URI_PREF),
|
||||
"https://example.com/dns-query",
|
||||
"TRR selection complete."
|
||||
);
|
||||
|
||||
// Disable committing. The committed URI should be reset to the
|
||||
// Wait for heuristics to complete.
|
||||
await ensureTRRMode(2);
|
||||
await checkHeuristicsTelemetry("enable_doh", "startup");
|
||||
|
||||
// Disable committing and reset. The committed URI should be reset to the
|
||||
// default provider and the dry-run-result should persist.
|
||||
prefPromise = TestUtils.waitForPrefChange(
|
||||
prefs.TRR_SELECT_URI_PREF,
|
||||
newVal => newVal == "https://example.com/1"
|
||||
);
|
||||
await setPrefAndWaitForConfigFlush(prefs.TRR_SELECT_COMMIT_PREF, false);
|
||||
Preferences.set(prefs.TRR_SELECT_COMMIT_PREF, false);
|
||||
prefPromise = TestUtils.waitForPrefChange(prefs.TRR_SELECT_URI_PREF);
|
||||
await restartDoHController();
|
||||
await prefPromise;
|
||||
is(
|
||||
Preferences.get(prefs.TRR_SELECT_URI_PREF),
|
||||
|
@ -78,13 +65,15 @@ add_task(async function testTRRSelect() {
|
|||
"dry-run result has the correct value."
|
||||
);
|
||||
|
||||
// Reset again, dry-run-result should be recorded but not
|
||||
// Wait for heuristics to complete.
|
||||
await ensureTRRMode(2);
|
||||
await checkHeuristicsTelemetry("enable_doh", "startup");
|
||||
|
||||
// Reset and restart again, dry-run-result should be recorded but not
|
||||
// be committed. Committing is still disabled from above.
|
||||
Preferences.reset(prefs.TRR_SELECT_DRY_RUN_RESULT_PREF);
|
||||
Preferences.reset(prefs.TRR_SELECT_URI_PREF);
|
||||
await restartDoHController();
|
||||
await waitForStartup();
|
||||
|
||||
try {
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
return (
|
||||
|
@ -106,6 +95,11 @@ add_task(async function testTRRSelect() {
|
|||
"https://example.com/dns-query",
|
||||
"TRR selection complete, dry-run result recorded."
|
||||
);
|
||||
Preferences.set(prefs.TRR_SELECT_COMMIT_PREF, true);
|
||||
|
||||
// Wait for heuristics to complete.
|
||||
await ensureTRRMode(2);
|
||||
await checkHeuristicsTelemetry("enable_doh", "startup");
|
||||
|
||||
// Reset doh-rollout.uri, and change the dry-run-result to another one on the
|
||||
// default list. After init, the existing dry-run-result should be committed.
|
||||
|
@ -118,7 +112,7 @@ add_task(async function testTRRSelect() {
|
|||
prefs.TRR_SELECT_URI_PREF,
|
||||
newVal => newVal == "https://example.com/2"
|
||||
);
|
||||
await setPrefAndWaitForConfigFlush(prefs.TRR_SELECT_COMMIT_PREF, true);
|
||||
await restartDoHController();
|
||||
await prefPromise;
|
||||
is(
|
||||
Preferences.get(prefs.TRR_SELECT_URI_PREF),
|
||||
|
@ -126,17 +120,18 @@ add_task(async function testTRRSelect() {
|
|||
"TRR selection complete, existing dry-run-result committed."
|
||||
);
|
||||
|
||||
// Wait for heuristics to complete.
|
||||
await ensureTRRMode(2);
|
||||
await checkHeuristicsTelemetry("enable_doh", "startup");
|
||||
|
||||
// Reset doh-rollout.uri, and change the dry-run-result to another one NOT on
|
||||
// default list. After init, a new TRR should be selected and committed.
|
||||
prefPromise = TestUtils.waitForPrefChange(
|
||||
prefs.TRR_SELECT_URI_PREF,
|
||||
newVal => newVal == "https://example.com/dns-query"
|
||||
);
|
||||
Preferences.reset(prefs.TRR_SELECT_URI_PREF);
|
||||
Preferences.set(
|
||||
prefs.TRR_SELECT_DRY_RUN_RESULT_PREF,
|
||||
"https://example.com/4"
|
||||
);
|
||||
prefPromise = TestUtils.waitForPrefChange(prefs.TRR_SELECT_URI_PREF);
|
||||
await restartDoHController();
|
||||
await prefPromise;
|
||||
is(
|
||||
|
@ -144,4 +139,8 @@ add_task(async function testTRRSelect() {
|
|||
"https://example.com/dns-query",
|
||||
"TRR selection complete, existing dry-run-result discarded and refreshed."
|
||||
);
|
||||
|
||||
// Wait for heuristics to complete.
|
||||
await ensureTRRMode(2);
|
||||
await checkHeuristicsTelemetry("enable_doh", "startup");
|
||||
});
|
||||
|
|
|
@ -7,12 +7,8 @@
|
|||
add_task(setup);
|
||||
|
||||
add_task(async function testTrrSelectionDisable() {
|
||||
// Turn off TRR Selection.
|
||||
let configFlushed = DoHTestUtils.waitForConfigFlush();
|
||||
Preferences.set(prefs.TRR_SELECT_ENABLED_PREF, false);
|
||||
await configFlushed;
|
||||
|
||||
// Set up a passing environment and enable DoH.
|
||||
Preferences.set(prefs.TRR_SELECT_ENABLED_PREF, false);
|
||||
setPassingHeuristics();
|
||||
let promise = waitForDoorhanger();
|
||||
Preferences.set(prefs.ENABLED_PREF, true);
|
||||
|
|
|
@ -86,10 +86,9 @@ async function setup() {
|
|||
// Avoid non-local connections to the TRR endpoint.
|
||||
Preferences.set(prefs.CONFIRMATION_NS_PREF, "skip");
|
||||
|
||||
// Enable trr selection and provider steeringfor tests. This is off
|
||||
// by default so it can be controlled via Normandy.
|
||||
// Enable trr selection for tests. This is off by default so it can be
|
||||
// controlled via Normandy.
|
||||
Preferences.set(prefs.TRR_SELECT_ENABLED_PREF, true);
|
||||
Preferences.set(prefs.PROVIDER_STEERING_PREF, true);
|
||||
|
||||
// Enable committing the TRR selection. This pref ships false by default so
|
||||
// it can be controlled e.g. via Normandy, but for testing let's set enable.
|
||||
|
@ -211,11 +210,11 @@ async function checkHeuristicsTelemetry(
|
|||
events = Services.telemetry.snapshotEvents(
|
||||
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS
|
||||
).parent;
|
||||
events = events?.filter(
|
||||
return events && events.length;
|
||||
});
|
||||
events = events.filter(
|
||||
e => e[1] == "doh" && e[2] == "evaluate_v2" && e[3] == "heuristics"
|
||||
);
|
||||
return events?.length;
|
||||
});
|
||||
is(events.length, 1, "Found the expected heuristics event.");
|
||||
is(events[0][4], decision, "The event records the expected decision");
|
||||
if (evaluateReason) {
|
||||
|
|
|
@ -7,12 +7,6 @@
|
|||
/* import-globals-from ../../../../toolkit/content/preferencesBindings.js */
|
||||
/* import-globals-from ../extensionControlled.js */
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"DoHConfigController",
|
||||
"resource:///modules/DoHConfig.jsm"
|
||||
);
|
||||
|
||||
document
|
||||
.getElementById("ConnectionsDialog")
|
||||
.addEventListener("dialoghelp", window.top.openPrefsHelp);
|
||||
|
@ -39,16 +33,13 @@ Preferences.addAll([
|
|||
{ id: "network.proxy.backup.ssl_port", type: "int" },
|
||||
{ id: "network.trr.mode", type: "int" },
|
||||
{ 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" },
|
||||
]);
|
||||
|
||||
const DoHConfigObserver = () => {
|
||||
gConnectionsDialog.initDnsOverHttpsUI();
|
||||
};
|
||||
|
||||
window.addEventListener(
|
||||
"DOMContentLoaded",
|
||||
() => {
|
||||
|
@ -65,20 +56,9 @@ window.addEventListener(
|
|||
gConnectionsDialog.updateDnsOverHttpsUI();
|
||||
});
|
||||
|
||||
Services.obs.addObserver(
|
||||
DoHConfigObserver,
|
||||
DoHConfigController.kConfigUpdateTopic
|
||||
);
|
||||
window.addEventListener(
|
||||
"unload",
|
||||
e => {
|
||||
Services.obs.removeObserver(
|
||||
DoHConfigObserver,
|
||||
DoHConfigController.kConfigUpdateTopic
|
||||
);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
Preferences.get("network.trr.resolvers").on("change", () => {
|
||||
gConnectionsDialog.initDnsOverHttpsUI();
|
||||
});
|
||||
|
||||
// XXX: We can't init the DNS-over-HTTPs UI until the onsyncfrompreference for network.trr.mode
|
||||
// has been called. The uiReady promise will be resolved after the first call to
|
||||
|
@ -127,12 +107,9 @@ var gConnectionsDialog = {
|
|||
if (customValue) {
|
||||
Services.prefs.setStringPref("network.trr.uri", customValue);
|
||||
} else {
|
||||
Services.prefs.setStringPref(
|
||||
"network.trr.uri",
|
||||
DoHConfigController.currentConfig.fallbackProviderURI
|
||||
);
|
||||
Services.prefs.clearUserPref("network.trr.uri");
|
||||
}
|
||||
} else if (this.isDnsOverHttpsEnabled()) {
|
||||
} else {
|
||||
Services.prefs.setStringPref(
|
||||
"network.trr.uri",
|
||||
dnsOverHttpsResolverChoice
|
||||
|
@ -422,14 +399,30 @@ var gConnectionsDialog = {
|
|||
},
|
||||
|
||||
get dnsOverHttpsResolvers() {
|
||||
let providers = DoHConfigController.currentConfig.providerList;
|
||||
let rawValue = Preferences.get("network.trr.resolvers", "").value;
|
||||
// if there's no default, we'll hold its position with an empty string
|
||||
let defaultURI = DoHConfigController.currentConfig.fallbackProviderURI;
|
||||
let defaultIndex = providers.findIndex(p => p.uri == defaultURI);
|
||||
let defaultURI = Preferences.get("network.trr.uri", "").defaultValue;
|
||||
let providers = [];
|
||||
if (rawValue) {
|
||||
try {
|
||||
providers = JSON.parse(rawValue);
|
||||
} catch (ex) {
|
||||
Cu.reportError(
|
||||
`Bad JSON data in pref network.trr.resolvers: ${rawValue}`
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!Array.isArray(providers)) {
|
||||
Cu.reportError(
|
||||
`Expected a JSON array in network.trr.resolvers: ${rawValue}`
|
||||
);
|
||||
providers = [];
|
||||
}
|
||||
let defaultIndex = providers.findIndex(p => p.url == defaultURI);
|
||||
if (defaultIndex == -1 && defaultURI) {
|
||||
// the default value for the pref isn't included in the resolvers list
|
||||
// so we'll make a stub for it. Without an id, we'll have to use the url as the label
|
||||
providers.unshift({ uri: defaultURI });
|
||||
providers.unshift({ url: defaultURI });
|
||||
}
|
||||
return providers;
|
||||
},
|
||||
|
@ -498,7 +491,7 @@ var gConnectionsDialog = {
|
|||
if (
|
||||
currentURI &&
|
||||
!customURI &&
|
||||
!resolvers.find(r => r.uri == currentURI)
|
||||
!resolvers.find(r => r.url == currentURI)
|
||||
) {
|
||||
Services.prefs.setStringPref("network.trr.custom_uri", currentURI);
|
||||
}
|
||||
|
@ -543,24 +536,24 @@ var gConnectionsDialog = {
|
|||
|
||||
initDnsOverHttpsUI() {
|
||||
let resolvers = this.dnsOverHttpsResolvers;
|
||||
let defaultURI = DoHConfigController.currentConfig.fallbackProviderURI;
|
||||
let defaultURI = Preferences.get("network.trr.uri").defaultValue;
|
||||
let currentURI = Preferences.get("network.trr.uri").value;
|
||||
let menu = document.getElementById("networkDnsOverHttpsResolverChoices");
|
||||
|
||||
// populate the DNS-Over-HTTPs resolver list
|
||||
menu.removeAllItems();
|
||||
for (let resolver of resolvers) {
|
||||
let item = menu.appendItem(undefined, resolver.uri);
|
||||
if (resolver.uri == defaultURI) {
|
||||
let item = menu.appendItem(undefined, resolver.url);
|
||||
if (resolver.url == defaultURI) {
|
||||
document.l10n.setAttributes(
|
||||
item,
|
||||
"connection-dns-over-https-url-item-default",
|
||||
{
|
||||
name: resolver.UIName || resolver.uri,
|
||||
name: resolver.name || resolver.url,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
item.label = resolver.UIName || resolver.uri;
|
||||
item.label = resolver.name || resolver.url;
|
||||
}
|
||||
}
|
||||
let lastItem = menu.appendItem(undefined, "custom");
|
||||
|
@ -571,7 +564,7 @@ var gConnectionsDialog = {
|
|||
|
||||
// set initial selection in the resolver provider picker
|
||||
let selectedIndex = currentURI
|
||||
? resolvers.findIndex(r => r.uri == currentURI)
|
||||
? resolvers.findIndex(r => r.url == currentURI)
|
||||
: 0;
|
||||
if (selectedIndex == -1) {
|
||||
// select the last "Custom" item
|
||||
|
|
|
@ -1,10 +1,3 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
requestLongerTimeout(2);
|
||||
|
||||
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
|
@ -12,34 +5,29 @@ ChromeUtils.defineModuleGetter(
|
|||
"DoHController",
|
||||
"resource:///modules/DoHController.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"DoHConfigController",
|
||||
"resource:///modules/DoHConfig.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"DoHTestUtils",
|
||||
"resource://testing-common/DoHTestUtils.jsm"
|
||||
);
|
||||
|
||||
const SUBDIALOG_URL =
|
||||
"chrome://browser/content/preferences/dialogs/connection.xhtml";
|
||||
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 FIRST_RESOLVER_VALUE = DoHTestUtils.providers[0].uri;
|
||||
const SECOND_RESOLVER_VALUE = DoHTestUtils.providers[1].uri;
|
||||
const DEFAULT_RESOLVER_VALUE = FIRST_RESOLVER_VALUE;
|
||||
const DEFAULT_RESOLVER_VALUE = "https://mozilla.cloudflare-dns.com/dns-query";
|
||||
const NEXTDNS_RESOLVER_VALUE = "https://firefox.dns.nextdns.io/";
|
||||
|
||||
const modeCheckboxSelector = "#networkDnsOverHttps";
|
||||
const uriTextboxSelector = "#networkCustomDnsOverHttpsInput";
|
||||
const resolverMenulistSelector = "#networkDnsOverHttpsResolverChoices";
|
||||
const defaultPrefValues = Object.freeze({
|
||||
[TRR_MODE_PREF]: 0,
|
||||
[TRR_URI_PREF]: "https://mozilla.cloudflare-dns.com/dns-query",
|
||||
[TRR_RESOLVERS_PREF]: JSON.stringify([
|
||||
{ name: "Cloudflare", url: DEFAULT_RESOLVER_VALUE },
|
||||
{ name: "example.org", url: "https://example.org/dns-query" },
|
||||
]),
|
||||
[TRR_CUSTOM_URI_PREF]: "",
|
||||
});
|
||||
|
||||
|
@ -47,6 +35,7 @@ async function resetPrefs() {
|
|||
await DoHController._uninit();
|
||||
Services.prefs.clearUserPref(TRR_MODE_PREF);
|
||||
Services.prefs.clearUserPref(TRR_URI_PREF);
|
||||
Services.prefs.clearUserPref(TRR_RESOLVERS_PREF);
|
||||
Services.prefs.clearUserPref(TRR_CUSTOM_URI_PREF);
|
||||
Services.prefs.getChildList("doh-rollout.").forEach(pref => {
|
||||
Services.prefs.clearUserPref(pref);
|
||||
|
@ -55,13 +44,12 @@ async function resetPrefs() {
|
|||
// confuse tests running after this one that are looking at those.
|
||||
Services.telemetry.clearEvents();
|
||||
await DoHController.init();
|
||||
await DoHTestUtils.resetRemoteSettingsConfig();
|
||||
}
|
||||
Services.prefs.setStringPref("network.trr.confirmationNS", "skip");
|
||||
let preferencesOpen = new Promise(res => open_preferences(res));
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
await resetPrefs();
|
||||
registerCleanupFunction(() => {
|
||||
resetPrefs();
|
||||
gBrowser.removeCurrentTab();
|
||||
Services.prefs.clearUserPref("network.trr.confirmationNS");
|
||||
});
|
||||
|
@ -134,6 +122,10 @@ async function testWithProperties(props, startTime) {
|
|||
if (props.hasOwnProperty(TRR_URI_PREF)) {
|
||||
Services.prefs.setStringPref(TRR_URI_PREF, props[TRR_URI_PREF]);
|
||||
}
|
||||
if (props.hasOwnProperty(TRR_RESOLVERS_PREF)) {
|
||||
info(`Setting ${TRR_RESOLVERS_PREF} to ${props[TRR_RESOLVERS_PREF]}`);
|
||||
Services.prefs.setStringPref(TRR_RESOLVERS_PREF, props[TRR_RESOLVERS_PREF]);
|
||||
}
|
||||
|
||||
let dialog = await openConnectionsSubDialog();
|
||||
await dialog.uiReady;
|
||||
|
@ -271,19 +263,12 @@ async function testWithProperties(props, startTime) {
|
|||
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)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (props.hasOwnProperty("expectedModePref")) {
|
||||
|
@ -320,16 +305,17 @@ async function testWithProperties(props, startTime) {
|
|||
|
||||
add_task(async function default_values() {
|
||||
let customUriPref = Services.prefs.getStringPref(TRR_CUSTOM_URI_PREF);
|
||||
let uriPrefHasUserValue = Services.prefs.prefHasUserValue(TRR_URI_PREF);
|
||||
let uriPref = Services.prefs.getStringPref(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(
|
||||
uriPref,
|
||||
defaultPrefValues[TRR_URI_PREF],
|
||||
`Actual value of ${TRR_URI_PREF} matches expected default value`
|
||||
);
|
||||
is(
|
||||
customUriPref,
|
||||
|
@ -348,6 +334,7 @@ let testVariations = [
|
|||
name: "mode 1",
|
||||
[TRR_MODE_PREF]: 1,
|
||||
expectedModeChecked: false,
|
||||
expectedFinalUriPref: DEFAULT_RESOLVER_VALUE,
|
||||
},
|
||||
{
|
||||
name: "mode 2",
|
||||
|
@ -365,6 +352,7 @@ let testVariations = [
|
|||
name: "mode 4",
|
||||
[TRR_MODE_PREF]: 4,
|
||||
expectedModeChecked: false,
|
||||
expectedFinalUriPref: DEFAULT_RESOLVER_VALUE,
|
||||
},
|
||||
{ name: "mode 5", [TRR_MODE_PREF]: 5, expectedModeChecked: false },
|
||||
// verify an out of bounds mode value maps to the correct checked state
|
||||
|
@ -428,14 +416,14 @@ let testVariations = [
|
|||
{
|
||||
name: "Select NextDNS as TRR provider",
|
||||
[TRR_MODE_PREF]: 2,
|
||||
selectResolver: SECOND_RESOLVER_VALUE,
|
||||
expectedFinalUriPref: SECOND_RESOLVER_VALUE,
|
||||
selectResolver: NEXTDNS_RESOLVER_VALUE,
|
||||
expectedFinalUriPref: NEXTDNS_RESOLVER_VALUE,
|
||||
},
|
||||
{
|
||||
name: "return to default from NextDNS",
|
||||
[TRR_MODE_PREF]: 2,
|
||||
[TRR_URI_PREF]: SECOND_RESOLVER_VALUE,
|
||||
expectedResolverListValue: SECOND_RESOLVER_VALUE,
|
||||
[TRR_URI_PREF]: NEXTDNS_RESOLVER_VALUE,
|
||||
expectedResolverListValue: NEXTDNS_RESOLVER_VALUE,
|
||||
selectResolver: DEFAULT_RESOLVER_VALUE,
|
||||
expectedFinalUriPref: DEFAULT_RESOLVER_VALUE,
|
||||
},
|
||||
|
@ -486,9 +474,11 @@ let testVariations = [
|
|||
},
|
||||
{
|
||||
name: "empty default resolver list",
|
||||
[TRR_RESOLVERS_PREF]: "",
|
||||
[TRR_MODE_PREF]: 2,
|
||||
[TRR_URI_PREF]: "https://example.com",
|
||||
[TRR_CUSTOM_URI_PREF]: "",
|
||||
[TRR_RESOLVERS_PREF]: "",
|
||||
expectedUriValue: "https://example.com",
|
||||
expectedResolverListValue: "custom",
|
||||
expectedFinalUriPref: "https://example.com",
|
||||
|
|
|
@ -9414,12 +9414,6 @@
|
|||
value: 1048576
|
||||
mirror: always
|
||||
|
||||
# Default global TRR provider
|
||||
- name: network.trr.default_provider_uri
|
||||
type: String
|
||||
value: "https://mozilla.cloudflare-dns.com/dns-query"
|
||||
mirror: never
|
||||
|
||||
# Single TRR request timeout, in milliseconds
|
||||
- name: network.trr.request_timeout_ms
|
||||
type: RelaxedAtomicUint32
|
||||
|
|
|
@ -3926,7 +3926,11 @@ pref("network.connectivity-service.IPv6.url", "http://detectportal.firefox.com/s
|
|||
// DNS Trusted Recursive Resolver
|
||||
// 0 - default off, 1 - reserved/off, 2 - TRR first, 3 - TRR only, 4 - reserved/off, 5 off by choice
|
||||
pref("network.trr.mode", 0);
|
||||
pref("network.trr.uri", "");
|
||||
// DNS-over-HTTP service to use, must be HTTPS://
|
||||
pref("network.trr.uri", "https://mozilla.cloudflare-dns.com/dns-query");
|
||||
// List of DNS-over-HTTP resolver service providers. This pref populates the
|
||||
// drop-down list in the Network Settings dialog box in about:preferences.
|
||||
pref("network.trr.resolvers", "[{ \"name\": \"Cloudflare\", \"url\": \"https://mozilla.cloudflare-dns.com/dns-query\" },{ \"name\": \"NextDNS\", \"url\": \"https://firefox.dns.nextdns.io/\" }]");
|
||||
// credentials to pass to DOH end-point
|
||||
pref("network.trr.credentials", "");
|
||||
pref("network.trr.custom_uri", "");
|
||||
|
|
|
@ -372,7 +372,6 @@ nsresult TRRService::ReadPrefs(const char* name) {
|
|||
}
|
||||
}
|
||||
if (!name || !strcmp(name, TRR_PREF("uri")) ||
|
||||
!strcmp(name, TRR_PREF("default_provider_uri")) ||
|
||||
!strcmp(name, kRolloutURIPref)) {
|
||||
OnTRRURIChange();
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "nsIDNSService.h"
|
||||
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
|
||||
#include "DNSLogging.h"
|
||||
#include "mozilla/StaticPrefs_network.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
@ -86,7 +85,7 @@ void TRRServiceBase::CheckURIPrefs() {
|
|||
}
|
||||
|
||||
// Otherwise just use the default value.
|
||||
MaybeSetPrivateURI(mDefaultURIPref);
|
||||
MaybeSetPrivateURI(mURIPref);
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -145,7 +144,6 @@ void TRRServiceBase::OnTRRURIChange() {
|
|||
mURIPrefHasUserValue = Preferences::HasUserValue("network.trr.uri");
|
||||
Preferences::GetCString("network.trr.uri", mURIPref);
|
||||
Preferences::GetCString(kRolloutURIPref, mRolloutURIPref);
|
||||
Preferences::GetCString("network.trr.default_provider_uri", mDefaultURIPref);
|
||||
|
||||
CheckURIPrefs();
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@ class TRRServiceBase {
|
|||
bool mURIPrefHasUserValue = false;
|
||||
nsCString mURIPref;
|
||||
nsCString mRolloutURIPref;
|
||||
nsCString mDefaultURIPref;
|
||||
|
||||
Atomic<nsIDNSService::ResolverMode, Relaxed> mMode;
|
||||
Atomic<bool, Relaxed> mURISetByDetection;
|
||||
|
|
|
@ -534,9 +534,9 @@ add_task(async function test_detected_uri() {
|
|||
dns.clearCache(true);
|
||||
Services.prefs.setIntPref("network.trr.mode", 3);
|
||||
Services.prefs.clearUserPref("network.trr.uri");
|
||||
let defaultURI = gDefaultPref.getCharPref("network.trr.default_provider_uri");
|
||||
let defaultURI = gDefaultPref.getCharPref("network.trr.uri");
|
||||
gDefaultPref.setCharPref(
|
||||
"network.trr.default_provider_uri",
|
||||
"network.trr.uri",
|
||||
`https://foo.example.com:${h2Port}/doh?responseIP=3.4.5.6`
|
||||
);
|
||||
await new TRRDNSListener("domainA.example.org.", "3.4.5.6");
|
||||
|
@ -544,7 +544,7 @@ add_task(async function test_detected_uri() {
|
|||
`https://foo.example.com:${h2Port}/doh?responseIP=1.2.3.4`
|
||||
);
|
||||
await new TRRDNSListener("domainB.example.org.", "1.2.3.4");
|
||||
gDefaultPref.setCharPref("network.trr.default_provider_uri", defaultURI);
|
||||
gDefaultPref.setCharPref("network.trr.uri", defaultURI);
|
||||
|
||||
// With a user-set doh uri this time.
|
||||
dns.clearCache(true);
|
||||
|
@ -562,7 +562,7 @@ add_task(async function test_detected_uri() {
|
|||
Services.prefs.setIntPref("network.trr.mode", 3);
|
||||
Services.prefs.clearUserPref("network.trr.uri");
|
||||
gDefaultPref.setCharPref(
|
||||
"network.trr.default_provider_uri",
|
||||
"network.trr.uri",
|
||||
`https://foo.example.com:${h2Port}/doh?responseIP=3.4.5.6`
|
||||
);
|
||||
await new TRRDNSListener("domainA.example.org.", "3.4.5.6");
|
||||
|
@ -584,15 +584,15 @@ add_task(async function test_detected_uri() {
|
|||
|
||||
await new TRRDNSListener("domainC.example.org.", "3.4.5.6");
|
||||
|
||||
gDefaultPref.setCharPref("network.trr.default_provider_uri", defaultURI);
|
||||
gDefaultPref.setCharPref("network.trr.uri", defaultURI);
|
||||
});
|
||||
|
||||
add_task(async function test_pref_changes() {
|
||||
info("Testing pref change handling");
|
||||
Services.prefs.clearUserPref("network.trr.uri");
|
||||
let defaultURI = gDefaultPref.getCharPref("network.trr.default_provider_uri");
|
||||
let defaultURI = gDefaultPref.getCharPref("network.trr.uri");
|
||||
|
||||
async function doThenCheckURI(closure, expectedURI, expectChange = true) {
|
||||
async function doThenCheckURI(closure, expectedURI, expectChange = false) {
|
||||
let uriChanged;
|
||||
if (expectChange) {
|
||||
uriChanged = topicObserved("network:trr-uri-changed");
|
||||
|
@ -607,7 +607,7 @@ add_task(async function test_pref_changes() {
|
|||
// setting the default value of the pref should be reflected in the URI
|
||||
await doThenCheckURI(() => {
|
||||
gDefaultPref.setCharPref(
|
||||
"network.trr.default_provider_uri",
|
||||
"network.trr.uri",
|
||||
`https://foo.example.com:${h2Port}/doh?default`
|
||||
);
|
||||
}, `https://foo.example.com:${h2Port}/doh?default`);
|
||||
|
@ -690,7 +690,7 @@ add_task(async function test_pref_changes() {
|
|||
);
|
||||
|
||||
// Restore the pref
|
||||
gDefaultPref.setCharPref("network.trr.default_provider_uri", defaultURI);
|
||||
gDefaultPref.setCharPref("network.trr.uri", defaultURI);
|
||||
});
|
||||
|
||||
add_task(async function test_dohrollout_mode() {
|
||||
|
|
|
@ -371,11 +371,9 @@ add_task(async function test_uri_pref_change() {
|
|||
|
||||
add_task(async function test_autodetected_uri() {
|
||||
const defaultPrefBranch = Services.prefs.getDefaultBranch("");
|
||||
let defaultURI = defaultPrefBranch.getCharPref(
|
||||
"network.trr.default_provider_uri"
|
||||
);
|
||||
let defaultURI = defaultPrefBranch.getCharPref("network.trr.uri");
|
||||
defaultPrefBranch.setCharPref(
|
||||
"network.trr.default_provider_uri",
|
||||
"network.trr.uri",
|
||||
`https://foo.example.com:${trrServer.port}/dns-query?changed`
|
||||
);
|
||||
// For setDetectedTrrURI to work we must pretend we are using the default.
|
||||
|
@ -396,5 +394,5 @@ add_task(async function test_autodetected_uri() {
|
|||
);
|
||||
|
||||
// reset the default URI
|
||||
defaultPrefBranch.setCharPref("network.trr.default_provider_uri", defaultURI);
|
||||
defaultPrefBranch.setCharPref("network.trr.uri", defaultURI);
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче