fix(build): enable bundled fonts on macOS - #708
Conversation
camoufox ships 287 font files under Contents/Resources/fonts on macOS
(Makefile passes `--fonts windows linux` to package.py) and already sets
`defaultPref("gfx.bundled-fonts.activate", 1)` in settings/camoufox.cfg,
but none of them are ever loaded: the macOS build does not define
MOZ_BUNDLED_FONTS, so CoreTextFontList::ActivateBundledFonts() is
compiled out. That function is the only caller of ActivateFontsFromDir(),
which is what registers <GRE>/fonts with CoreText via
CTFontManagerRegisterFontURLs().
Upstream defaults the option to `target.os == "WINNT" or target.kernel ==
"Linux"` (toolkit/moz.configure), so Linux and Windows enable it
implicitly and macOS silently does not. The configure option itself is
gated only on `project == "browser"`, which camoufox is; there is no
platform restriction.
Effect on a macOS host: a spoofed font list currently resolves against
the host's own fonts, so the measurable set is `host fonts INTERSECT
claimed list` -- 13 of 60 claimed families measurable in local testing,
and those 13 are exactly the macOS-native ones. Font metrics are a
cross-checked fingerprinting surface (a UA claiming Windows alongside
macOS font metrics is a contradiction detectors look for), so this
undercuts the spoofing rather than merely reducing it.
Refs daijro#706
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Independent confirmation on a different build path, plus a data point for your open question. I cross-compiled this from Linux ( A warning for anyone verifying this: With a proper control build — identical tree, only Gecko level (no
With the spoofed Windows list active (all 107 from
build-tester shows no regression: 1038–1039/1048 with the flag vs 1037/1048 on the control, Grade A both, On your open question — why Mozilla defaults this off on macOS. There is a measurable startup cost. Launch-to-first-page, headless, 7 runs each, same machine, alternating builds:
+214 ms, roughly 21%. That is 287 files going through Verified on 152.0.4-beta.28, cross-compiled from Linux, macOS 15.3.1 arm64 (M4). |
|
Correction: the "remaining gaps" section of this PR description is wrong about localized family names. Details and the measurements are in #706 (comment) Short version: bundled fonts load lazily (the first measurement is what triggers loading), and the whitelist is keyed on canonical en-US family names while The before/after comparison in the PR is unaffected — both sides used one frozen config, so seed and whitelist were identical. |
Fixes the macOS side of #706.
What's wrong
Camoufox ships 287 font files under
Contents/Resources/fontson macOS(
Makefilepasses--fonts windows linuxtopackage.py) and already setsdefaultPref("gfx.bundled-fonts.activate", 1)insettings/camoufox.cfg— butnone of them are ever loaded.
Firefox does have the macOS code for this:
CoreTextFontList::ActivateBundledFonts()reads<GRE>/fontsand hands it toActivateFontsFromDir(), which registers the files withCTFontManagerRegisterFontURLs(urls, kCTFontManagerScopeProcess, ...). Thatfunction is guarded by
#ifdef MOZ_BUNDLED_FONTS, and upstream defaults theoption to:
macOS is not in that set, so the whole path is compiled out. Linux and Windows
get it implicitly and never needed the flag written down; macOS does. The option
itself is gated only on
project == "browser"— there is no platformrestriction.
Note that
ActivateFontsFromDir()is not inside the#ifdef, which is whyCTFontManagerRegisterFontURLsstill shows up in XUL's symbol table on macOSeven though nothing calls it for the bundled set. That misleads binary
inspection.
Why it matters
On a macOS host the spoofed font list currently resolves against the host's own
fonts, so the measurable set is
host fonts ∩ claimed list. Font metrics are across-checked surface — a UA claiming Windows next to macOS font metrics is a
contradiction detectors specifically look for — so this weakens the spoof rather
than merely narrowing it.
Verification
Built this branch on CI (macos/arm64) and measured both builds with the same
frozen config, so the claimed font list is identical on both sides and the only
variable is the flag. Measurement is the usual metrics probe (render a string in
"<family>", monospace|serif|sans-serifand compare against each generic'sbaseline), not an enumeration API.
Calibri, Consolas, Segoe UI, Cambria Math and Nirmala UI all go from
unmeasurable to measurable.
The 16 that remain
Not failures of this change:
4 are weight variants whose base family does resolve (
Segoe UI Semilight→
Segoe UI✓,Yu Gothic UI Light→Yu Gothic UI✓). CSS collapses theseonto one family, so a metrics probe cannot distinguish them. Measurement-method
floor, not a spoofing gap.
Most of the rest are localized family names. Eight pairs, tested with every
name added to the whitelist so filtering is not a factor:
English 8/8 resolve, localized 8/8 do not. The fonts are loaded — the English
names prove that — but CoreText registration only exposes the en-US family name
(nameID 1), not the localized aliases. DirectWrite on real Windows honours
both, so this is a separate and much narrower gap, worth its own issue.
I also briefly suspected
.ttccollections were the problem, since most of thestragglers are
.ttc.Cambria Mathcomes fromcambria.ttcand resolvesfine, so that theory is wrong.
-apple-systemstill resolves on both builds. That is thefont-system-fonts-css2.patchpath, unrelated to this change.Open question
Do you know why Mozilla defaults this off on macOS? I could not find a rationale.
If it is just that nobody needed it, this is the whole fix. If there is a known
problem with process-scoped CoreText registration (startup cost, sandboxing),
that would be worth knowing before this ships.
Untested here: whether the metrics of the now-loaded fonts match real Windows,
and whether the Windows build's implicit
MOZ_BUNDLED_FONTSactually works inpractice — I only have a macOS host.