Extend the accent-color standin to Linux (and to the highlight/selecteditem family)
Categories
(Core :: Privacy: Anti-Tracking, enhancement)
Tracking
()
People
(Reporter: tjr, Unassigned)
References
(Blocks 1 open bug)
Details
The Windows-specific brand-color standin that Firefox applies to LookAndFeel::ColorID::Accentcolor / Accentcolortext is what collapses css_color_accentcolor on Windows from Shannon 3.602 bits / 105,897 distinct values down to 0.026 bits / 1,327 distinct values.
Linux carries an equivalent — and in some respects worse — fingerprint surface (~4.4 bits, ~15k distinct values) that Firefox does not currently standin. This writeup proposes extending the existing standin mechanism to (a) fire on Linux and (b) cover the broader accent family, not just Accentcolor[text]. Same architecture as the Windows case; same High-Contrast bypass; no change to Firefox's own chrome.
The choice
Apply the content-side standin (Firefox brand 0060DF via widget::sDefaultAccent) on Linux for the three colors that all derive from the user's desktop accent and form one correlated fingerprinting signal, plus their text companions:
Accentcolor/AccentcolortextHighlight/HighlighttextSelecteditem/Selecteditemtext
The mechanism is the existing ShouldUseStandinsForNativeColorForNonNativeTheme gate in widget/nsXPLookAndFeel.cpp:1255-1272. Two extension points:
- Either flip
widget.non-native-theme.use-theme-accentdefault to false on Linux (currently true), reusing the same accent special-case at:1264-1266that fires for Windows. - Or add the highlight/selecteditem
ColorIDs tosNonNativeThemeStandinColors(:1215-1252), which lets the standin fire for them on every platform automatically.
(2) is the broader and more defensible change because it closes the same axis on Windows and Darwin in the same patch — see "Why expand the family" below. (1) is the narrower Linux-only change if scope must be minimized.
Preserve the High-Contrast / forced-colors bypass at nsXPLookAndFeel.cpp:1270 (mUseDocumentColors=false) — High-Contrast users on any platform must be able to override the standin, the same reasoning that gates Windows today.
Rationale
1. Linux has a Windows-comparable accent-fingerprinting surface that is currently unmitigated
Per-OS Shannon entropy of color_accentcolor and the two correlated colors on Linux (e6_entropy.txt):
| OS | accentcolor H | highlight H | selecteditem H | distinct accents | CSS-side after current Firefox standin |
|---|---|---|---|---|---|
| Linux | 4.401 | 4.390 | 4.294 | 15,940 | NONE — content sees the real accent |
| WINNT | 3.602 | 0.755 | 0.755 | 105,897 (color_*) | 0.026 bits / 1,327 distinct (standin active) |
| Android | 6.824 | 6.824 | 6.824 | 17,514 | NONE — content sees the real accent |
| Darwin | 1.081 | 1.476 | 1.778 | 34 | NONE — content sees the real accent |
The privacy delta Mozilla already accepted on Windows (about 3.58 bits between the real accent and the brand standin) is more compelling on Linux: the underlying entropy is higher (4.40 vs 3.60), the absolute distinct-value count is in the same order of magnitude, and content currently has unobstructed read access via three different CSS keywords.
2. On Linux, Accentcolor, Highlight, and Selecteditem are one signal
GTK derives the selection background (gtk-selection-bg-color / libadwaita equivalent) and KDE Plasma derives its selection color from the same user-chosen accent setting. As a result, a user who picks a specific accent in their desktop settings gets the same RGB triple in all three fields. Standing-in only Accentcolor would close one of three leaky CSS keywords and leave the other two leaking the identical signal — a fingerprinter would shrug and read Highlight or SelectedItem instead. The combined fingerprint isn't ~13 bits (3 × 4.4) — it's ~4.4 bits — but it's also not addressable by patching one color in isolation. The standin set must cover the whole accent family on Linux to be meaningful.
3. Windows already established the policy precedent
The widget.non-native-theme.use-theme-accent=false default on Windows says, in policy terms: "the user's chosen OS accent is a fingerprintable signal we don't want to expose to content, even though that means content's AccentColor keyword shows Firefox blue instead of the OS accent." The same reasoning applies to Linux now. The standin is well-defined (widget::sDefaultAccent / widget::sDefaultAccentText), the code site is one file, the test surface is small.
4. Standin affects content, not Firefox chrome
The standin path runs only inside LookAndFeel::GetColor() calls reaching content — Firefox's own tabs/menus/address-bar continue to use the real GTK/KDE accent through the chrome's separate color lookup. Linux users keep their visually-integrated browser; only web content stops seeing the personal accent.
Privacy properties
| Approach | accentcolor H (Linux) | highlight/selecteditem H | Bits exposed via CSS family |
|---|---|---|---|
| Status quo (no standin on Linux) | 4.401 | 4.390 / 4.294 | ~4.4 (correlated trio) |
| Standin accentcolor only | ~0 | 4.390 / 4.294 | ~4.4 (still leaks via Highlight/SelectedItem) |
| Standin the accent family (proposed) | ~0 | ~0 | ~0 |
This proposal is content-side only: it changes what web content reads from LookAndFeel::GetColor() via the CSS system-color keywords. It does not change what Firefox's own chrome uses (still the real OS accent — see "Standin affects content, not Firefox chrome" above).
Implementation
Code changes
widget/nsXPLookAndFeel.cpp (the gate at :1255-1272). Two viable shapes:
(a) Add the highlight/selecteditem ColorIDs to sNonNativeThemeStandinColors at :1215-1252. This is the cleanest change because the standin then fires for these colors on every platform where the non-native-theme path runs, and the existing mUseDocumentColors accessibility bypass keeps working unchanged.
(b) If Linux-only is preferred for scope, change the accent special-case at :1264-1266 to also match Linux, and add a parallel block for highlight/selecteditem/their-texts gated on the same pref.
Either way, ensure the High-Contrast bypass at :1270 continues to apply.
widget/ThemeColors.h — sDefaultAccent (0xff0060df) and sDefaultAccentText (0xffffffff) are already defined and used by Windows. For the broader family, the standin values are the same on Windows today (the existing Accentcolor standin returns sDefaultAccent.ToABGR() at nsXPLookAndFeel.cpp:617); apply the same color for Highlight / Selecteditem to keep the trio visually consistent, and a contrasting opaque white (or the existing sDefaultAccentText) for the text variants.
metrics.yaml — extend the css_system_colors description note (already documents the Windows AccentColor standin from firefox-3-sandbox commit 4f81be8) to say the standin now also covers Highlight / SelectedItem / their text companions on Linux, with the same High-Contrast bypass. If shape (b) is chosen, mention Linux-only; if (a), note the cross-platform effect.
Test changes
toolkit/components/resistfingerprinting/tests/browser/browser_usercharacteristics_css.js — add assertions that on Linux (and on Windows if (a) is chosen), the Highlight and SelectedItem entries in css_system_colors JSON resolve to the brand 0060DF (or the appropriate standin value) when run with mUseDocumentColors=true, and pass through to the real OS value when mUseDocumentColors=false. Existing AccentColor test on Windows is the template.
WPT / mochitest for the Highlight CSS keyword in content: a new test that creates a <div style="color: Highlight"> and asserts the computed style equals the standin color (under default prefs). Counterpart test under forced-colors: active asserts the real color passes through.
What does NOT change
- Firefox's own chrome / tab bar / menus continue to use the real GTK/KDE accent. The
LookAndFeelinvocations from chrome code paths bypass the standin gate. - macOS behavior is unchanged in shape (b); in shape (a) macOS users would also see the
Highlight/SelectedItemstandin, which is a smaller absolute privacy win on macOS (highlight H ≈ 1.5 bits, 13.8k distinct) but is consistent.
Tradeoffs / considerations
- Visual jolt for Linux users who notice. Web content styled with
AccentColor/Highlight/SelectedItemCSS keywords currently picks up the user's GNOME/KDE accent — that visual coherence breaks. Counter: it already breaks on Windows; the Mozilla policy decision there generalizes; the Firefox UI itself stays coherent. - Sites that style content with system colors may look slightly off. This is the same compatibility concern Mozilla accepted on Windows. Real-world incidence is low (most sites use explicit colors, not system-color keywords).
- On Windows, this is not a fingerprint-protection feature. It's a default-on accent-standin patterned after the Windows precedent.
| Reporter | ||
Comment 1•4 months ago
|
||
This makes a significant improvement to the percentage of unique users on Linux:
| FPJS V2 — % unique | Linux |
|---|---|
| Baseline (P3) | 68.47% |
| + Linux accent standin | 58.40% |
And the cohort score improvement:
| FPJS V2 — HHI | Linux |
|---|---|
| % improvement | +39.02% |
| Reporter | ||
Updated•4 months ago
|
Description
•