tor-browser

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

commit 7ae138a2c58f184aed3c3a7d252e82db8633220e
parent 6cbecf227bcb4b3e9088636030a3b431a5ed1a89
Author: Benjamin VanderSloot <bvandersloot@mozilla.com>
Date:   Tue,  6 Jan 2026 13:44:12 +0000

Bug 2007918 - Add telemetry to count configuration issues and a pref to be able to disable the security-privacy-status card - r=hjones,emz

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

Diffstat:
Mbrowser/components/preferences/metrics.yaml | 44++++++++++++++++++++++++++++++++++++++++++++
Mbrowser/components/preferences/privacy.js | 20++++++++++++++++++--
Mbrowser/components/preferences/tests/browser_privacy_status_card.js | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 140 insertions(+), 2 deletions(-)

diff --git a/browser/components/preferences/metrics.yaml b/browser/components/preferences/metrics.yaml @@ -414,3 +414,47 @@ aboutpreferences: telemetry_mirror: Aboutpreferences_Show_Hash no_lint: - COMMON_PREFIX + +security.preferences.warnings: + warnings_shown: + type: event + description: > + Recorded when the security warnings card is possibly added to the page + in about:preferences#privacy. This tracks the count of visible + security warning items to understand how many issues users are seeing. + This only fires once per time the settings page is loaded. + bugs: + - https://bugzilla.mozilla.org/2007918 + data_reviews: + - https://bugzilla.mozilla.org/2007918 + notification_emails: + - bvandersloot@mozilla.com + expires: never + extra_keys: + count: + description: The number of visible security warning items in the card + type: quantity + warning_fixed: + type: event + description: > + Recorded when the user interacts with the "fix" button in the issue box + item. + bugs: + - https://bugzilla.mozilla.org/2007918 + data_reviews: + - https://bugzilla.mozilla.org/2007918 + notification_emails: + - bvandersloot@mozilla.com + expires: never + warning_dismissed: + type: event + description: > + Recorded when the user interacts with the dismiss button in the issue box + item. + bugs: + - https://bugzilla.mozilla.org/2007918 + data_reviews: + - https://bugzilla.mozilla.org/2007918 + notification_emails: + - bvandersloot@mozilla.com + expires: never diff --git a/browser/components/preferences/privacy.js b/browser/components/preferences/privacy.js @@ -299,6 +299,7 @@ Preferences.addAll([ if (SECURITY_PRIVACY_STATUS_CARD_ENABLED) { Preferences.addAll([ // Security and Privacy Warnings + { id: "browser.preferences.config_warning.dismissAll", type: "bool" }, { id: "privacy.ui.status_card.testing.show_issue", type: "bool" }, { id: "browser.preferences.config_warning.warningTest.dismissed", @@ -812,6 +813,8 @@ class WarningSettingConfig { if (isDismissable) { this.dismissedPrefId = `browser.preferences.config_warning.${this.id}.dismissed`; this.prefMapping.dismissed = this.dismissedPrefId; + this.dismissAllPrefId = `browser.preferences.config_warning.dismissAll`; + this.prefMapping.dismissAll = this.dismissAllPrefId; } this.problematic = problematic; } @@ -823,7 +826,11 @@ class WarningSettingConfig { * @returns {boolean} Whether or not to show this configuration as a warning to the user */ visible() { - return !this.dismissed?.value && this.problematic(this); + return ( + !this.dismissAll?.value && + !this.dismissed?.value && + this.problematic(this) + ); } /** @@ -878,10 +885,12 @@ class WarningSettingConfig { switch (event.target.id) { case "reset": { this.reset(); + Glean.securityPreferencesWarnings.warningFixed.record(); break; } case "dismiss": { this.dismiss(); + Glean.securityPreferencesWarnings.warningDismissed.record(); break; } } @@ -1416,7 +1425,14 @@ if (SECURITY_PRIVACY_STATUS_CARD_ENABLED) { id: "warningCard", deps: SECURITY_WARNINGS.map(warning => warning.id), visible: deps => { - return Object.values(deps).some(depSetting => depSetting.visible); + const count = Object.values(deps).filter( + depSetting => depSetting.visible + ).length; + if (!this._telemetrySent) { + Glean.securityPreferencesWarnings.warningsShown.record({ count }); + this._telemetrySent = true; + } + return count > 0; }, }); } diff --git a/browser/components/preferences/tests/browser_privacy_status_card.js b/browser/components/preferences/tests/browser_privacy_status_card.js @@ -208,6 +208,7 @@ add_task(async function test_issue_fix() { ["privacy.ui.status_card.testing.show_issue", true], ].concat(RESET_PROBLEMATIC_TEST_DEFAULTS), }); + Services.fog.testResetFOG(); await BrowserTestUtils.withNewTab( { gBrowser, url: "about:preferences#privacy" }, @@ -239,6 +240,28 @@ add_task(async function test_issue_fix() { ), "Pref has no user value after clicking the fix button" ); + let events = + Glean.securityPreferencesWarnings.warningFixed.testGetValue(); + Assert.equal(events.length, 1, "One telemetry event was recorded"); + Assert.equal( + events[0].category, + "security.preferences.warnings", + "Category is correct" + ); + Assert.equal(events[0].name, "warning_fixed", "Event name is correct"); + + let warningsShownEvents = + Glean.securityPreferencesWarnings.warningsShown.testGetValue(); + Assert.equal( + warningsShownEvents.length, + 1, + "warningsShown telemetry was recorded exactly once" + ); + Assert.equal( + warningsShownEvents[0].extra.count, + "1", + "Count of warnings shown is correct" + ); } ); @@ -252,6 +275,7 @@ add_task(async function test_issue_dismiss() { ["privacy.ui.status_card.testing.show_issue", true], ].concat(RESET_PROBLEMATIC_TEST_DEFAULTS), }); + Services.fog.testResetFOG(); await BrowserTestUtils.withNewTab( { gBrowser, url: "about:preferences#privacy" }, @@ -283,6 +307,31 @@ add_task(async function test_issue_dismiss() { ), "Pref has no user value after clicking the fix button" ); + let events = + Glean.securityPreferencesWarnings.warningDismissed.testGetValue(); + Assert.equal(events.length, 1, "One telemetry event was recorded"); + Assert.equal( + events[0].category, + "security.preferences.warnings", + "Category is correct" + ); + Assert.equal( + events[0].name, + "warning_dismissed", + "Event name is correct" + ); + let warningsShownEvents = + Glean.securityPreferencesWarnings.warningsShown.testGetValue(); + Assert.equal( + warningsShownEvents.length, + 1, + "warningsShown telemetry was recorded exactly once" + ); + Assert.equal( + warningsShownEvents[0].extra.count, + "1", + "Count of warnings shown is correct" + ); Services.prefs.clearUserPref( "browser.preferences.config_warning.warningTest.dismissed" ); @@ -292,6 +341,35 @@ add_task(async function test_issue_dismiss() { await SpecialPowers.popPrefEnv(); }); +add_task(async function test_dismiss_all_hides_issues() { + await SpecialPowers.pushPrefEnv({ + set: [ + [FEATURE_PREF, true], + ["privacy.ui.status_card.testing.show_issue", true], + ["browser.preferences.config_warning.dismissAll", true], + ].concat(RESET_PROBLEMATIC_TEST_DEFAULTS), + }); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:preferences#privacy" }, + async function (browser) { + let card = getCardAndCheckHeader( + browser.contentDocument, + "security-privacy-status-ok-header" + ); + assertHappyBullets(card); + + let configCard = browser.contentDocument.getElementById(ISSUE_CONTROL_ID); + Assert.ok( + BrowserTestUtils.isHidden(configCard), + "Issue card is not present when dismissAll is true" + ); + } + ); + + await SpecialPowers.popPrefEnv(); +}); + add_task(async function test_update_status_indicator() { await SpecialPowers.pushPrefEnv({ set: [[FEATURE_PREF, true]].concat(RESET_PROBLEMATIC_TEST_DEFAULTS),