/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; /** * Tests for the fallback behavior during error resolution. * * These tests verify three scenarios: * 1. A registered SSL error resolves to its own config ID. * 2. An unregistered error does not trigger the nssFailure2 fallback when * gErrorCode is a registered error other than "nssFailure2". * 3. The deniedPortAccess error shows the correct intro text. */ const TLS10_PAGE = "https://tls1.example.com/"; async function openErrorTab(url) { let browser; let tab; let pageLoaded; await BrowserTestUtils.openNewForegroundTab( gBrowser, () => { gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, url); browser = gBrowser.selectedBrowser; tab = gBrowser.selectedTab; pageLoaded = BrowserTestUtils.waitForErrorPage(browser); }, false ); await pageLoaded; return { browser, tab }; } // Verify that a registered SSL error resolves directly to its own config, // not to the nssFailure2 fallback. add_task(async function test_registered_ssl_error() { info( "Testing that SSL_ERROR_RX_RECORD_TOO_LONG resolves to its own registry ID" ); Services.prefs.setIntPref("security.tls.version.min", 3); Services.prefs.setIntPref("security.tls.version.max", 4); registerCleanupFunction(() => { Services.prefs.clearUserPref("security.tls.version.min"); Services.prefs.clearUserPref("security.tls.version.max"); }); const { browser, tab } = await openErrorTab(TLS10_PAGE); registerCleanupFunction(() => BrowserTestUtils.removeTab(tab)); await SpecialPowers.spawn(browser, [], async () => { const doc = content.document; Assert.ok( doc.documentURI.startsWith("about:neterror"), "Should be on the error page" ); const netErrorCard = await ContentTaskUtils.waitForCondition( () => doc.querySelector("net-error-card")?.wrappedJSObject, "net-error-card should be present" ); await netErrorCard.getUpdateComplete(); // Call resolveErrorID directly with a mocked SSL_ERROR_RX_RECORD_TOO_LONG // input. initializeRegistry populates the full registry so that scenario 1 // (direct match) correctly resolves the registered error. const { resolveErrorID } = ChromeUtils.importESModule( "chrome://global/content/errors/error-lookup.mjs" ); const { initializeRegistry } = ChromeUtils.importESModule( "chrome://global/content/errors/error-registry.mjs" ); initializeRegistry(); Assert.equal( resolveErrorID({ errorCodeString: "SSL_ERROR_RX_RECORD_TOO_LONG", gErrorCode: "nssFailure2", noConnectivity: false, vpnActive: false, }), "SSL_ERROR_RX_RECORD_TOO_LONG", "Should resolve to the registered error, not fall back to nssFailure2" ); }); BrowserTestUtils.removeTab(tab); Services.prefs.clearUserPref("security.tls.version.min"); Services.prefs.clearUserPref("security.tls.version.max"); }); add_task(async function test_no_fallback_for_non_nssFailure2_gErrorCode() { info( "Testing that deniedPortAccess resolves directly to its own registry ID" ); await SpecialPowers.pushPrefEnv({ set: [ ["dom.security.https_first", false], ["network.security.ports.banned.override", ""], ], }); registerCleanupFunction(() => SpecialPowers.popPrefEnv()); // eslint-disable-next-line @microsoft/sdl/no-insecure-url const { browser, tab } = await openErrorTab("http://example.com:25"); registerCleanupFunction(() => BrowserTestUtils.removeTab(tab)); await SpecialPowers.spawn(browser, [], async () => { const doc = content.document; const netErrorCard = await ContentTaskUtils.waitForCondition( () => doc.querySelector("net-error-card")?.wrappedJSObject, "net-error-card should be present for deniedPortAccess" ); await netErrorCard.getUpdateComplete(); Assert.equal( netErrorCard.resolvedErrorId, "deniedPortAccess", "resolvedErrorId should be deniedPortAccess" ); }); BrowserTestUtils.removeTab(tab); await SpecialPowers.popPrefEnv(); }); add_task(async function test_denied_port_access_intro_text() { info("Testing deniedPortAccess shows correct intro text with felt privacy"); await SpecialPowers.pushPrefEnv({ set: [ ["dom.security.https_first", false], ["network.security.ports.banned.override", ""], ], }); registerCleanupFunction(() => SpecialPowers.popPrefEnv()); // Port 25 (SMTP) is on Firefox's blocked port list. // eslint-disable-next-line @microsoft/sdl/no-insecure-url const { browser, tab } = await openErrorTab("http://example.com:25"); registerCleanupFunction(() => BrowserTestUtils.removeTab(tab)); await SpecialPowers.spawn(browser, [], async () => { const doc = content.document; Assert.ok( doc.documentURI.startsWith("about:neterror"), "Should be on the error page" ); Assert.ok( doc.documentURI.includes("deniedPortAccess"), "Error code should be deniedPortAccess" ); const netErrorCard = await ContentTaskUtils.waitForCondition( () => doc.querySelector("net-error-card")?.wrappedJSObject, "net-error-card should be present for deniedPortAccess" ); await netErrorCard.getUpdateComplete(); const introEl = netErrorCard.errorIntro; Assert.ok(introEl, "Intro element should exist"); Assert.equal( introEl.dataset.l10nId, "fp-neterror-denied-port-access", "Should show the denied port access intro, not the offline intro" ); }); BrowserTestUtils.removeTab(tab); await SpecialPowers.popPrefEnv(); });