Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* Any copyright is dedicated to the Public Domain.
"use strict";
const NET_ERROR_PAGE = "https://does-not-exist.test";
const BAD_CERT = "https://expired.example.com/";
async function getGleanEvents(metric) {
await Services.fog.testFlushAllChildren();
return metric.testGetValue();
}
// -- Felt Privacy path (default) --
// Test: load_aboutneterror fires for a DNS error (top-level)
add_task(async function test_feltprivacy_neterror_load() {
Services.fog.testResetFOG();
let pageLoaded;
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
() => {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, NET_ERROR_PAGE);
let browser = gBrowser.selectedBrowser;
pageLoaded = BrowserTestUtils.waitForErrorPage(browser);
},
false
);
await pageLoaded;
let events = await TestUtils.waitForCondition(
() => getGleanEvents(Glean.securityUiNeterror.loadAboutneterror),
"Waiting for load_aboutneterror Glean event"
);
Assert.equal(events.length, 1, "Exactly one load event recorded");
Assert.equal(events[0].extra.is_frame, "false", "Not in an iframe");
Assert.equal(
events[0].extra.value,
"dnsNotFound",
"Error code is dnsNotFound"
);
BrowserTestUtils.removeTab(tab);
});
// Test: load_aboutneterror fires with is_frame=true for iframe errors
add_task(async function test_feltprivacy_neterror_load_iframe() {
Services.fog.testResetFOG();
let tab = await openErrorPage(NET_ERROR_PAGE, true);
let events = await TestUtils.waitForCondition(
() => getGleanEvents(Glean.securityUiNeterror.loadAboutneterror),
"Waiting for load_aboutneterror Glean event in iframe"
);
Assert.equal(events.length, 1, "Exactly one load event recorded");
Assert.equal(events[0].extra.is_frame, "true", "Recorded as iframe");
BrowserTestUtils.removeTab(tab);
});
// Test: cert errors do NOT fire load_aboutneterror
add_task(async function test_feltprivacy_certerror_no_neterror() {
Services.fog.testResetFOG();
let tab = await openErrorPage(BAD_CERT, false);
// Wait for the cert error telemetry to confirm the page fully loaded
// and telemetry was processed, then verify no neterror event fired.
await TestUtils.waitForCondition(
() => getGleanEvents(Glean.securityUiCerterror.loadAboutcerterror),
"Waiting for cert error load event to confirm page loaded"
);
let events = Glean.securityUiNeterror.loadAboutneterror.testGetValue();
Assert.equal(events, null, "No neterror event for cert errors");
BrowserTestUtils.removeTab(tab);
});
// -- Legacy path (felt-privacy disabled) --
// Test: load_aboutneterror fires on the legacy path for a DNS error
add_task(async function test_legacy_neterror_load() {
await SpecialPowers.pushPrefEnv({
set: [["security.certerrors.felt-privacy-v1", false]],
});
Services.fog.testResetFOG();
let pageLoaded;
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
() => {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, NET_ERROR_PAGE);
let browser = gBrowser.selectedBrowser;
pageLoaded = BrowserTestUtils.waitForErrorPage(browser);
},
false
);
await pageLoaded;
let events = await TestUtils.waitForCondition(
() => getGleanEvents(Glean.securityUiNeterror.loadAboutneterror),
"Waiting for load_aboutneterror Glean event (legacy path)"
);
Assert.equal(events.length, 1, "Exactly one load event recorded");
Assert.equal(events[0].extra.is_frame, "false", "Not in an iframe");
Assert.equal(
events[0].extra.value,
"dnsNotFound",
"Error code is dnsNotFound"
);
BrowserTestUtils.removeTab(tab);
await SpecialPowers.popPrefEnv();
});
// Test: cert errors do NOT fire load_aboutneterror on the legacy path
add_task(async function test_legacy_certerror_no_neterror() {
await SpecialPowers.pushPrefEnv({
set: [["security.certerrors.felt-privacy-v1", false]],
});
Services.fog.testResetFOG();
let tab = await openErrorPage(BAD_CERT, false);
// Wait for the cert error telemetry to confirm the page fully loaded
// and telemetry was processed, then verify no neterror event fired.
await TestUtils.waitForCondition(
() => getGleanEvents(Glean.securityUiCerterror.loadAboutcerterror),
"Waiting for cert error load event to confirm page loaded (legacy)"
);
let events = Glean.securityUiNeterror.loadAboutneterror.testGetValue();
Assert.equal(events, null, "No neterror event for cert errors (legacy)");
BrowserTestUtils.removeTab(tab);
await SpecialPowers.popPrefEnv();
});
// -- TRR-only mode (DoH warning page telemetry) --
function assertDohEventExtras(event, label) {
Assert.equal(event.extra.value, "TRROnlyFailure", `${label}: value`);
Assert.equal(event.extra.mode, "3", `${label}: mode`);
Assert.equal(
event.extra.provider_key,
"mozilla.cloudflare-dns.com",
`${label}: provider_key`
);
Assert.equal(
event.extra.skip_reason,
"TRR_UNKNOWN_CHANNEL_FAILURE",
`${label}: skip_reason`
);
}
// Test: DoH warning page telemetry for load and button clicks in TRR-only mode
add_task(async function test_trr_only_telemetry() {
Services.fog.testResetFOG();
let browser = await loadTRRErrorPage();
let loadEvents = await TestUtils.waitForCondition(
() => getGleanEvents(Glean.securityDohNeterror.loadDohwarning),
"Waiting for DoH neterror load Glean event"
);
Assert.equal(loadEvents.length, 1, "Exactly one DoH load event");
assertDohEventExtras(loadEvents[0], "load event");
let tabOpenPromise = BrowserTestUtils.waitForNewTab(
gBrowser,
"about:preferences#privacy-doh"
);
await SpecialPowers.spawn(browser, [], async function () {
const doc = content.document;
const netErrorCard = await ContentTaskUtils.waitForCondition(
() => doc.querySelector("net-error-card")?.wrappedJSObject
);
if (netErrorCard) {
await netErrorCard.getUpdateComplete();
const trrSettingsButton = await ContentTaskUtils.waitForCondition(
() => netErrorCard.shadowRoot.getElementById("trrSettingsButton"),
"Waiting for trrSettingsButton"
);
trrSettingsButton.click();
const tryAgainButton = await ContentTaskUtils.waitForCondition(
() => netErrorCard.tryAgainButton,
"Waiting for tryAgainButton"
);
tryAgainButton.click();
} else {
let buttons = ["neterrorTryAgainButton", "trrSettingsButton"];
for (let buttonId of buttons) {
let button = await ContentTaskUtils.waitForCondition(
() => doc.getElementById(buttonId),
`Waiting for button ${buttonId}`
);
button.click();
}
}
}).catch(e => {
if (!e.message.includes("Actor 'SpecialPowers' destroyed")) {
throw e;
}
});
await tabOpenPromise;
await BrowserTestUtils.waitForErrorPage(browser);
Assert.equal(
gBrowser.tabs.length,
3,
"Should open about:preferences#privacy-doh in another tab"
);
let settingsEvents = await TestUtils.waitForCondition(
() => getGleanEvents(Glean.securityDohNeterror.clickSettingsButton),
"Waiting for DoH settings click Glean event"
);
Assert.equal(settingsEvents.length, 1, "Exactly one settings click event");
assertDohEventExtras(settingsEvents[0], "settings click event");
let tryAgainEvents = await TestUtils.waitForCondition(
() => getGleanEvents(Glean.securityDohNeterror.clickTryAgainButton),
"Waiting for DoH try-again click Glean event"
);
Assert.equal(tryAgainEvents.length, 1, "Exactly one try-again click event");
assertDohEventExtras(tryAgainEvents[0], "try-again click event");
BrowserTestUtils.removeTab(gBrowser.tabs[2]);
BrowserTestUtils.removeTab(gBrowser.tabs[1]);
resetTRRPrefs();
});