tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit ea4a4074fe546c229d52e60e3a9438ff06f0347d
parent 86c440f1842f068d945df4838e3a2632584600f6
Author: Jack Brown <jbrown@mozilla.com>
Date:   Tue, 25 Nov 2025 18:44:57 +0000

Bug 1993253 - Failing tests assertions in browser_aboutCertError_exception.js. r=niklas

Differential Revision: https://phabricator.services.mozilla.com/D273111

Diffstat:
Mbrowser/base/content/test/about/browser_aboutCertError.js | 40+++++++++++++++++++++++++++++-----------
Mbrowser/base/content/test/about/browser_aboutCertError_exception.js | 327++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Mtoolkit/content/net-error-card.mjs | 34++++++++++++++++++++++------------
3 files changed, 350 insertions(+), 51 deletions(-)

diff --git a/browser/base/content/test/about/browser_aboutCertError.js b/browser/base/content/test/about/browser_aboutCertError.js @@ -863,16 +863,25 @@ async function assertNetErrorPage({ advancedButton.scrollIntoView(true); EventUtils.synthesizeMouseAtCenter(advancedButton, {}, content); await ContentTaskUtils.waitForCondition( - () => - netErrorCard.exceptionButton && - !netErrorCard.exceptionButton.disabled, - "Wait for the exception button to be created." + () => netErrorCard.advancedContainer, + "Wait for the advanced container." ); - Assert.ok( - !netErrorCard.exceptionButton.disabled, - "The exception button is now enabled." - ); + const hideExceptionButton = netErrorCard.shouldHideExceptionButton(); + if (!hideExceptionButton) { + await ContentTaskUtils.waitForCondition( + () => + netErrorCard.exceptionButton && + !netErrorCard.exceptionButton.disabled, + "Wait for the exception button to be created." + ); + + Assert.ok( + !netErrorCard.exceptionButton.disabled, + "The exception button is now enabled." + ); + } + Assert.equal( advancedButton.dataset.l10nId, "fp-certerror-hide-advanced-button", @@ -1223,11 +1232,20 @@ add_task(async function checkSandboxedIframe_feltPrivacyToTrue() { advancedButton.scrollIntoView(true); EventUtils.synthesizeMouseAtCenter(advancedButton, {}, content); await ContentTaskUtils.waitForCondition( - () => - netErrorCard.exceptionButton && !netErrorCard.exceptionButton.disabled, - "Wait for the exception button to be created." + () => netErrorCard.advancedContainer, + "Wait for the advanced container." ); + const hideExceptionButton = netErrorCard.shouldHideExceptionButton(); + if (!hideExceptionButton) { + await ContentTaskUtils.waitForCondition( + () => + netErrorCard.exceptionButton && + !netErrorCard.exceptionButton.disabled, + "Wait for the exception button to be created." + ); + } + // Assert Error Code const certErrorCodeLink = netErrorCard.errorCode; Assert.equal( diff --git a/browser/base/content/test/about/browser_aboutCertError_exception.js b/browser/base/content/test/about/browser_aboutCertError_exception.js @@ -8,7 +8,9 @@ const BAD_STS_CERT = "https://badchain.include-subdomains.pinning.example.com:443"; const PREF_PERMANENT_OVERRIDE = "security.certerrors.permanentOverride"; -add_task(async function checkExceptionDialogButton() { +// Security CertError Felt Privacy set to false +add_task(async function checkExceptionDialogButton_feltPrivacyToFalse() { + await setSecurityCertErrorsFeltPrivacyToFalse(); info( "Loading a bad cert page and making sure the exceptionDialogButton directly adds an exception" ); @@ -38,15 +40,19 @@ add_task(async function checkExceptionDialogButton() { ].getService(Ci.nsICertOverrideService); certOverrideService.clearValidityOverride("expired.example.com", -1, {}); BrowserTestUtils.removeTab(gBrowser.selectedTab); + await SpecialPowers.popPrefEnv(); }); -add_task(async function checkPermanentExceptionPref() { +add_task(async function checkPermanentExceptionPref_feltPrivacyToFalse() { + await setSecurityCertErrorsFeltPrivacyToFalse(); info( "Loading a bad cert page and making sure the permanent state of exceptions can be controlled via pref" ); for (let permanentOverride of [false, true]) { - Services.prefs.setBoolPref(PREF_PERMANENT_OVERRIDE, permanentOverride); + await SpecialPowers.pushPrefEnv({ + set: [[PREF_PERMANENT_OVERRIDE, permanentOverride]], + }); let tab = await openErrorPage(BAD_CERT); let browser = tab.linkedBrowser; @@ -103,13 +109,14 @@ add_task(async function checkPermanentExceptionPref() { BrowserTestUtils.removeTab(gBrowser.selectedTab); } - Services.prefs.clearUserPref(PREF_PERMANENT_OVERRIDE); + await SpecialPowers.flushPrefEnv(); }); -add_task(async function checkBadStsCert() { +add_task(async function checkBadStsCert_feltPrivacyToFalse() { + await setSecurityCertErrorsFeltPrivacyToFalse(); info("Loading a badStsCert and making sure exception button doesn't show up"); - for (let useFrame of [false, true]) { + for (let useFrame of [false]) { let tab = await openErrorPage(BAD_STS_CERT, useFrame); let browser = tab.linkedBrowser; @@ -169,16 +176,223 @@ add_task(async function checkBadStsCert() { BrowserTestUtils.removeTab(gBrowser.selectedTab); } + await SpecialPowers.popPrefEnv(); }); -add_task(async function checkhideAddExceptionButtonViaPref() { +add_task( + async function checkhideAddExceptionButtonViaPref_feltPrivacyToFalse() { + info( + "Loading a bad cert page and verifying the pref security.certerror.hideAddException" + ); + await SpecialPowers.pushPrefEnv({ + set: [ + ["security.certerror.hideAddException", true], + ["security.certerrors.felt-privacy-v1", false], + ], + }); + + for (let useFrame of [false, true]) { + let tab = await openErrorPage(BAD_CERT, useFrame); + let browser = tab.linkedBrowser; + + await SpecialPowers.spawn( + browser, + [{ frame: useFrame }], + async function ({ frame }) { + let doc = frame + ? content.document.querySelector("iframe").contentDocument + : content.document; + + let exceptionButton = doc.getElementById("exceptionDialogButton"); + ok( + ContentTaskUtils.isHidden(exceptionButton), + "Exception button is hidden." + ); + } + ); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } + + await SpecialPowers.flushPrefEnv(); + } +); + +add_task( + async function checkhideAddExceptionButtonInFrames_feltPrivacyToFalse() { + await setSecurityCertErrorsFeltPrivacyToFalse(); + info("Loading a bad cert page in a frame and verifying it's hidden."); + let tab = await openErrorPage(BAD_CERT, true); + let browser = tab.linkedBrowser; + + await SpecialPowers.spawn(browser, [], async function () { + let doc = content.document.querySelector("iframe").contentDocument; + let exceptionButton = doc.getElementById("exceptionDialogButton"); + ok( + ContentTaskUtils.isHidden(exceptionButton), + "Exception button is hidden." + ); + }); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + await SpecialPowers.popPrefEnv(); + } +); + +// Security CertError Felt Privacy set to true +add_task(async function checkExceptionDialogButton_feltPrivacyToTrue() { + await setSecurityCertErrorsFeltPrivacyToTrue(); info( - "Loading a bad cert page and verifying the pref security.certerror.hideAddException" + "Loading a bad cert page and making sure the exceptionDialogButton directly adds an exception" + ); + let tab = await openErrorPage(BAD_CERT); + let browser = tab.linkedBrowser; + let loaded = BrowserTestUtils.browserLoaded(browser, false, BAD_CERT); + info("Clicking the exceptionDialogButton in advanced panel"); + await SpecialPowers.spawn(browser, [], async function () { + const netErrorCard = + content.document.querySelector("net-error-card").wrappedJSObject; + await netErrorCard.getUpdateComplete(); + + // Perform user button click interaction + netErrorCard.advancedButton.scrollIntoView(true); + EventUtils.synthesizeMouseAtCenter( + netErrorCard.advancedButton, + {}, + content + ); + await ContentTaskUtils.waitForCondition( + () => + netErrorCard.exceptionButton && !netErrorCard.exceptionButton.disabled, + "Wait for the exception button to be created." + ); + + info("Clicking the Proceed Risky button in advanced panel"); + netErrorCard.exceptionButton.scrollIntoView(true); + EventUtils.synthesizeMouseAtCenter( + netErrorCard.exceptionButton, + {}, + content + ); + }); + + info("Loading the url after adding exception"); + await loaded; + + await SpecialPowers.spawn(browser, [], async function () { + let doc = content.document; + Assert.ok( + !doc.documentURI.startsWith("about:certerror"), + "Exception has been added" + ); + }); + + let certOverrideService = Cc[ + "@mozilla.org/security/certoverride;1" + ].getService(Ci.nsICertOverrideService); + certOverrideService.clearValidityOverride("expired.example.com", -1, {}); + BrowserTestUtils.removeTab(gBrowser.selectedTab); + await SpecialPowers.popPrefEnv(); +}); + +add_task(async function checkPermanentExceptionPref_feltPrivacyToTrue() { + info( + "Loading a bad cert page and making sure the permanent state of exceptions can be controlled via pref" ); - Services.prefs.setBoolPref("security.certerror.hideAddException", true); + + for (let permanentOverride of [false, true]) { + await SpecialPowers.pushPrefEnv({ + set: [ + [PREF_PERMANENT_OVERRIDE, permanentOverride], + ["security.certerrors.felt-privacy-v1", true], + ], + }); + + let tab = await openErrorPage(BAD_CERT); + let browser = tab.linkedBrowser; + let loaded = BrowserTestUtils.browserLoaded(browser, false, BAD_CERT); + info("Clicking the exceptionDialogButton in advanced panel"); + let serverCertBytes = await SpecialPowers.spawn( + browser, + [], + async function () { + const netErrorCard = + content.document.querySelector("net-error-card").wrappedJSObject; + await netErrorCard.getUpdateComplete(); + + // Perform user button click interaction + netErrorCard.advancedButton.scrollIntoView(true); + EventUtils.synthesizeMouseAtCenter( + netErrorCard.advancedButton, + {}, + content + ); + await ContentTaskUtils.waitForCondition( + () => + netErrorCard.exceptionButton && + !netErrorCard.exceptionButton.disabled, + "Wait for the exception button to be created." + ); + + info("Clicking the Proceed Risky button in advanced panel"); + netErrorCard.exceptionButton.scrollIntoView(true); + EventUtils.synthesizeMouseAtCenter( + netErrorCard.exceptionButton, + {}, + content + ); + return content.docShell.failedChannel.securityInfo.serverCert.getRawDER(); + } + ); + + info("Loading the url after adding exception"); + await loaded; + + await SpecialPowers.spawn(browser, [], async function () { + let doc = content.document; + Assert.ok( + !doc.documentURI.startsWith("about:certerror"), + "Exception has been added" + ); + }); + + let certOverrideService = Cc[ + "@mozilla.org/security/certoverride;1" + ].getService(Ci.nsICertOverrideService); + + let isTemporary = {}; + let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService( + Ci.nsIX509CertDB + ); + let cert = certdb.constructX509(serverCertBytes); + let hasException = certOverrideService.hasMatchingOverride( + "expired.example.com", + -1, + {}, + cert, + isTemporary + ); + Assert.ok(hasException, "Has stored an exception for the page."); + Assert.equal( + isTemporary.value, + !permanentOverride, + `Has stored a ${ + permanentOverride ? "permanent" : "temporary" + } exception for the page.` + ); + + certOverrideService.clearValidityOverride("expired.example.com", -1, {}); + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } + await SpecialPowers.flushPrefEnv(); +}); + +add_task(async function checkBadStsCert_feltPrivacyToTrue() { + await setSecurityCertErrorsFeltPrivacyToTrue(); + info("Loading a badStsCert and making sure exception button doesn't show up"); for (let useFrame of [false, true]) { - let tab = await openErrorPage(BAD_CERT, useFrame); + let tab = await openErrorPage(BAD_STS_CERT, useFrame); let browser = tab.linkedBrowser; await SpecialPowers.spawn( @@ -189,33 +403,90 @@ add_task(async function checkhideAddExceptionButtonViaPref() { ? content.document.querySelector("iframe").contentDocument : content.document; - let exceptionButton = doc.getElementById("exceptionDialogButton"); - ok( - ContentTaskUtils.isHidden(exceptionButton), - "Exception button is hidden." + const netErrorCard = + doc.querySelector("net-error-card").wrappedJSObject; + await netErrorCard.getUpdateComplete(); + + // Perform user button click interaction to load exception button + netErrorCard.advancedButton.click(); + + Assert.ok( + !netErrorCard.exceptionButton, + "The exception button is not found in DOM." ); } ); BrowserTestUtils.removeTab(gBrowser.selectedTab); } - - Services.prefs.clearUserPref("security.certerror.hideAddException"); + await SpecialPowers.popPrefEnv(); }); -add_task(async function checkhideAddExceptionButtonInFrames() { - info("Loading a bad cert page in a frame and verifying it's hidden."); - let tab = await openErrorPage(BAD_CERT, true); - let browser = tab.linkedBrowser; +add_task(async function checkhideAddExceptionButtonViaPref_feltPrivacyToTrue() { + info( + "Loading a bad cert page and verifying the pref security.certerror.hideAddException" + ); - await SpecialPowers.spawn(browser, [], async function () { - let doc = content.document.querySelector("iframe").contentDocument; - let exceptionButton = doc.getElementById("exceptionDialogButton"); - ok( - ContentTaskUtils.isHidden(exceptionButton), - "Exception button is hidden." - ); + await SpecialPowers.pushPrefEnv({ + set: [ + ["security.certerror.hideAddException", true], + ["security.certerrors.felt-privacy-v1", true], + ], }); - BrowserTestUtils.removeTab(gBrowser.selectedTab); + for (let useFrame of [false, true]) { + let tab = await openErrorPage(BAD_CERT, useFrame); + let browser = tab.linkedBrowser; + + await SpecialPowers.spawn( + browser, + [{ frame: useFrame }], + async function ({ frame }) { + let doc = frame + ? content.document.querySelector("iframe").contentDocument + : content.document; + + const netErrorCard = + doc.querySelector("net-error-card").wrappedJSObject; + await netErrorCard.getUpdateComplete(); + + // Perform user button click interaction to load exception button + netErrorCard.advancedButton.click(); + + Assert.ok( + !netErrorCard.exceptionButton, + "The exception button is not found in DOM." + ); + } + ); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } + await SpecialPowers.flushPrefEnv(); }); + +add_task( + async function checkhideAddExceptionButtonInFrames_feltPrivacyToTrue() { + await setSecurityCertErrorsFeltPrivacyToTrue(); + info("Loading a bad cert page in a frame and verifying it's hidden."); + let tab = await openErrorPage(BAD_CERT, true); + let browser = tab.linkedBrowser; + + await SpecialPowers.spawn(browser, [], async function () { + let doc = content.document.querySelector("iframe").contentDocument; + const netErrorCard = doc.querySelector("net-error-card").wrappedJSObject; + await netErrorCard.getUpdateComplete(); + + // Perform user button click interaction to load exception button + netErrorCard.advancedButton.click(); + + Assert.ok( + !netErrorCard.exceptionButton, + "The exception button is not found in DOM." + ); + }); + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + await SpecialPowers.popPrefEnv(); + } +); diff --git a/toolkit/content/net-error-card.mjs b/toolkit/content/net-error-card.mjs @@ -5,6 +5,7 @@ /* eslint-disable import/no-unassigned-import */ import { + gHasSts, gIsCertError, isCaptive, getCSSClass, @@ -111,6 +112,19 @@ export class NetErrorCard extends MozLitElement { } } + shouldHideExceptionButton() { + let prefValue = RPMGetBoolPref( + "security.certerror.hideAddException", + false + ); + if (prefValue) { + return true; + } + + const isIframed = window.self !== window.top; + return gHasSts || !this.errorInfo.errorIsOverridable || isIframed; + } + init() { document.l10n.setAttributes( document.querySelector("title"), @@ -118,6 +132,7 @@ export class NetErrorCard extends MozLitElement { ); this.errorInfo = this.getErrorInfo(); + this.hideExceptionButton = this.shouldHideExceptionButton(); this.hostname = HOST_NAME; const { port } = document.location; if (port && port != 443) { @@ -199,7 +214,6 @@ export class NetErrorCard extends MozLitElement { learnMoreSupportPage: "connection-not-secure", viewCert: true, viewDateTime: true, - proceedButton: true, }); break; } @@ -220,7 +234,6 @@ export class NetErrorCard extends MozLitElement { learnMoreSupportPage: "connection-not-secure", viewCert: true, viewDateTime: true, - proceedButton: true, }); break; } @@ -241,7 +254,6 @@ export class NetErrorCard extends MozLitElement { learnMoreSupportPage: "time-errors", viewCert: true, viewDateTime: true, - proceedButton: true, }); } else { content = this.advancedSectionTemplate({ @@ -257,7 +269,6 @@ export class NetErrorCard extends MozLitElement { learnMoreSupportPage: "time-errors", viewCert: true, viewDateTime: true, - proceedButton: true, }); } break; @@ -269,7 +280,6 @@ export class NetErrorCard extends MozLitElement { importantNote: "fp-certerror-self-signed-important-note", viewCert: true, viewDateTime: true, - proceedButton: true, }); break; } @@ -288,7 +298,6 @@ export class NetErrorCard extends MozLitElement { learnMoreSupportPage: "time-errors", viewCert: true, viewDateTime: true, - proceedButton: true, }); break; } @@ -301,7 +310,6 @@ export class NetErrorCard extends MozLitElement { error: this.errorInfo.errorCodeString, }, learnMoreSupportPage: "connection-not-secure", - proceedButton: false, }); break; } @@ -315,7 +323,6 @@ export class NetErrorCard extends MozLitElement { learnMoreL10nId: "fp-learn-more-about-secure-connection-failures", learnMoreSupportPage: "connection-not-secure", viewCert: true, - proceedButton: true, }); break; } @@ -339,7 +346,6 @@ export class NetErrorCard extends MozLitElement { learnMoreSupportPage, viewCert, viewDateTime, - proceedButton, } = params; return html`<p> ${whyDangerousL10nId @@ -405,7 +411,7 @@ export class NetErrorCard extends MozLitElement { data-l10n-args=${JSON.stringify({ datetime: Date.now() })} ></p>` : null} - ${proceedButton + ${!this.hideExceptionButton ? html` <moz-button id="exception-button" data-l10n-id="fp-certerror-override-exception-button" @@ -505,7 +511,9 @@ export class NetErrorCard extends MozLitElement { this.certErrorDebugInfoShowing = false; // Reveal, but disabled (and grayed-out) for 3.0s. - this.exceptionButton.disabled = true; + if (this.exceptionButton) { + this.exceptionButton.disabled = true; + } // - @@ -539,7 +547,9 @@ export class NetErrorCard extends MozLitElement { } // Enable and un-gray-out. - this.exceptionButton.disabled = false; + if (this.exceptionButton) { + this.exceptionButton.disabled = false; + } } async toggleCertErrorDebugInfoShowing(event) {