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:
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) {