From 5b2ff5352f698db236da556673a4fc18b7cd143e Mon Sep 17 00:00:00 2001 From: Michael Heller <21163552+mdheller@users.noreply.github.com> Date: Thu, 23 Jul 2026 08:09:03 -0400 Subject: [PATCH] bearstart: port the native shell's branded start page into the Gecko build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The WKWebView shim had a real identity — bear wordmark, trust pills, sovereign search with inline federated results, shortcut tiles, green token system. The production Gecko build opened on an anonymous gutted about:newtab. This ports that page in as the new-tab + home page on all three platforms: - settings/start/bearbrowser-start.html: the page, with DM Sans self-hosted (variable woff2, zero network fetches) instead of the mac-only SF Pro stack - packaged into browser omni.ja at browser/bearstart/ via FINAL_TARGET_FILES (same mechanism as bearblocker) -> resource:///bearstart/... works identically on Linux/Windows/macOS, no package-manifest entries needed - new tab: AboutNewTab.newTabURL override via autoconfig JS (there is no pref for this) — appended to bearbrowser.cfg on Linux/Windows by the overlay script; injected as a minimal cfg post-package on macOS. Requires general.config.sandbox_enabled=false (our own baked-in file, same trust as the binary; LibreWolf ships its cfg the same way) - homepage: fixed the DEAD pref value — it pointed at the old native shell's absolute /Applications path (macOS-only, gone). Now the resource URL. Also dropped browser.newtab.url, removed from Firefox years ago - search: sovereign endpoints only (search-api JSON inline w/ receipt line, SearXNG HTML fallback), straight from the shim --- scripts/apply-sourceos-overlays.sh | 15 + scripts/bearbrowser-package-source-build.sh | 22 ++ scripts/bearbrowser-patches.py | 41 +++ settings/profiles/human-secure/user.js | 10 +- settings/start/bearbrowser-start.html | 355 ++++++++++++++++++++ settings/start/bearstart-autoconfig.js | 20 ++ settings/start/dm-sans-latin-ext.woff2 | Bin 0 -> 18192 bytes settings/start/dm-sans-latin.woff2 | Bin 0 -> 36980 bytes 8 files changed, 460 insertions(+), 3 deletions(-) create mode 100644 settings/start/bearbrowser-start.html create mode 100644 settings/start/bearstart-autoconfig.js create mode 100644 settings/start/dm-sans-latin-ext.woff2 create mode 100644 settings/start/dm-sans-latin.woff2 diff --git a/scripts/apply-sourceos-overlays.sh b/scripts/apply-sourceos-overlays.sh index 14bfbd3..9c16c99 100755 --- a/scripts/apply-sourceos-overlays.sh +++ b/scripts/apply-sourceos-overlays.sh @@ -363,12 +363,27 @@ if [ -f "$profile_dir/user.js" ]; then echo "settings: injected $profile user.js -> source/settings/bearbrowser.cfg (autoconfig)" fi +# BearStart new-tab wiring: append the privileged autoconfig JS that points +# AboutNewTab at resource:///bearstart/bearbrowser-start.html. There is no pref +# for the new-tab URL — this is the supported enterprise/autoconfig mechanism. +# Requires general.config.sandbox_enabled=false (set below). +if [ -f "$repo_root/settings/start/bearstart-autoconfig.js" ] && \ + [ -f "$workspace/source/settings/bearbrowser.cfg" ]; then + cat "$repo_root/settings/start/bearstart-autoconfig.js" \ + >> "$workspace/source/settings/bearbrowser.cfg" + echo "settings: appended bearstart-autoconfig.js -> bearbrowser.cfg (new-tab wiring)" +fi + # The autoconfig wiring: tell Firefox to load bearbrowser.cfg as the lockable # config file. obscure_value 0 means the .cfg is plain text (not byte-shifted). +# sandbox_enabled=false lets the cfg run privileged JS (the BearStart new-tab +# override) — the cfg is our own file baked into the package, same trust level +# as the binary itself (LibreWolf ships its cfg the same way). cat > "$inject_pref/local-settings.js" <<'EOF_LOCALSETTINGS' // BearBrowser autoconfig wiring — generated by apply-sourceos-overlays.sh pref("general.config.obscure_value", 0); pref("general.config.filename", "bearbrowser.cfg"); +pref("general.config.sandbox_enabled", false); EOF_LOCALSETTINGS echo "settings: wrote autoconfig wiring -> source/settings/defaults/pref/local-settings.js" diff --git a/scripts/bearbrowser-package-source-build.sh b/scripts/bearbrowser-package-source-build.sh index ee514bf..9f9996d 100755 --- a/scripts/bearbrowser-package-source-build.sh +++ b/scripts/bearbrowser-package-source-build.sh @@ -199,6 +199,28 @@ if [ -f "$profile_dir/policies.json" ]; then echo " policies.json → $policy_dest/policies.json (comments stripped)" fi +# BearStart new-tab wiring (macOS lane). Linux/Windows get this via the +# overlay-generated bearbrowser.cfg; on macOS the cfg is not emitted by the +# build (see the nightly-dmg manifest-relax step), so inject a minimal cfg here +# that only carries the AboutNewTab override, plus the autoconfig wiring prefs. +# Prefs themselves already ship via bearbrowser-user.js above — no duplication. +# NOTE: autoconfig .cfg files skip their FIRST line (must be a comment). +if [ -f "$repo_root/settings/start/bearstart-autoconfig.js" ]; then + cp "$repo_root/settings/start/bearstart-autoconfig.js" \ + "$out_app/Contents/Resources/bearbrowser.cfg" + # Autoconfig wiring must live in defaults/pref/ at the resources root — the + # one loose default-pref dir packaged Firefox reads (enterprise-documented). + wiring_dest="$out_app/Contents/Resources/defaults/pref" + mkdir -p "$wiring_dest" + cat > "$wiring_dest/local-settings.js" <<'EOF_BEARSTART_WIRING' +// BearBrowser autoconfig wiring — injected by bearbrowser-package-source-build.sh +pref("general.config.obscure_value", 0); +pref("general.config.filename", "bearbrowser.cfg"); +pref("general.config.sandbox_enabled", false); +EOF_BEARSTART_WIRING + echo " bearstart-autoconfig.js → Contents/Resources/bearbrowser.cfg (new-tab wiring)" +fi + # ── Step 5: Ad-hoc sign ─────────────────────────────────────────────────────── echo "[5/6] Code signing..." if [ "$skip_sign" = "true" ]; then diff --git a/scripts/bearbrowser-patches.py b/scripts/bearbrowser-patches.py index d00974d..df0fe24 100755 --- a/scripts/bearbrowser-patches.py +++ b/scripts/bearbrowser-patches.py @@ -347,6 +347,47 @@ def _strip_l10n_base(_path): # l10n locale patching skipped for dev build (--with-l10n-base removed from mozconfig) print("-> Skipping l10n download (dev build — en-US only)") + # ── BearStart: branded start page (new tab + home) ── + # Ported from the native macOS shell's landing page. Packaged into the + # browser omni.ja via FINAL_TARGET_FILES (same mechanism as bearblocker) + # so it ships identically on Linux/Windows/macOS with no package-manifest + # entries. Served at resource:///bearstart/bearbrowser-start.html; wired + # as the new-tab page by settings/start/bearstart-autoconfig.js (appended + # to bearbrowser.cfg) and as the homepage by the human-secure user.js. + _bs_dir = Path("browser/bearstart") + _bs_dir.mkdir(exist_ok=True) + _bs_src = Path("../settings/start") + _bs_files = ["bearbrowser-start.html", "dm-sans-latin.woff2", "dm-sans-latin-ext.woff2"] + _bs_installed = [] + for _bs_file in _bs_files: + _src = _bs_src / _bs_file + if _src.exists(): + _shutil.copy(str(_src), str(_bs_dir / _bs_file)) + _bs_installed.append(_bs_file) + print(f"-> Installed {_bs_file} to browser/bearstart/") + else: + print(f"warning: {_src} not found — BearStart asset missing") + _bs_mozbuild = _bs_dir / "moz.build" + if _bs_installed and not _bs_mozbuild.exists(): + _bs_mozbuild.write_text( + "# BearStart start page — packaged to dist/bin/browser/bearstart/\n" + "# Accessible at resource:///bearstart/ inside the browser.\n" + "FINAL_TARGET_FILES.bearstart += [\n" + + "".join(f' "{f}",\n' for f in _bs_installed) + + "]\n" + ) + print("-> Created browser/bearstart/moz.build") + _browser_mozbuild_bs = Path("browser/moz.build") + if _bs_installed and _browser_mozbuild_bs.exists(): + _bm_bs = _browser_mozbuild_bs.read_text() + if '"bearstart"' not in _bm_bs: + _bm_bs = _bm_bs.replace( + ' "actors",\n "base",', + ' "actors",\n "base",\n "bearstart",', + ) + _browser_mozbuild_bs.write_text(_bm_bs) + print("-> Added bearstart to browser/moz.build DIRS") + # ── BearBlocker: native adblock-rust content classifier + cosmetic filtering ── # Step 1: Install filter lists into browser/bearblocker/ _bb_dir = Path("browser/bearblocker") diff --git a/settings/profiles/human-secure/user.js b/settings/profiles/human-secure/user.js index 6e70c27..e8c7ed1 100644 --- a/settings/profiles/human-secure/user.js +++ b/settings/profiles/human-secure/user.js @@ -159,10 +159,14 @@ user_pref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features", user_pref("extensions.pocket.enabled", false); user_pref("extensions.pocket.api", ""); user_pref("extensions.pocket.site", ""); -// Homepage — BearBrowser custom start page -user_pref("browser.startup.homepage", "file:///Applications/BearBrowser.app/Contents/Resources/BearBrowser-start.html"); +// Homepage — BearBrowser start page, packaged into the browser omni.ja at +// browser/bearstart/ (see scripts/bearbrowser-patches.py) so the same URL works +// on Linux/Windows/macOS regardless of install location. (The old value was the +// native-shell's absolute /Applications file path — macOS-only and dead.) +// New-tab uses the same page via settings/start/bearstart-autoconfig.js — +// browser.newtab.url was removed from Firefox years ago and did nothing. +user_pref("browser.startup.homepage", "resource:///bearstart/bearbrowser-start.html"); user_pref("browser.startup.page", 1); -user_pref("browser.newtab.url", "file:///Applications/BearBrowser.app/Contents/Resources/BearBrowser-start.html"); // ── Search engine ───────────────────────────────────────────────────────────── // Remove Google as a preset and default to a privacy-respecting engine. diff --git a/settings/start/bearbrowser-start.html b/settings/start/bearbrowser-start.html new file mode 100644 index 0000000..e395521 --- /dev/null +++ b/settings/start/bearbrowser-start.html @@ -0,0 +1,355 @@ + + +
+ + + + +BIzWQCyd+mywf;gDH;8MyA=GkZ8nK~-QdHe34!g<{hSB4f3PuV=
zi?m6h_$nQ5MV@v;s<7Il5$}}F }Z}$dJQx;lcT!3LjRb5AsKZ^??A{rH5}%C{Li{=(A~w
zH4`v*+ Eeu}d)z%T^F%BtLt2}`oV_%=D?4ACZ99sP^L+*CzK
z+rzphHi3vT4WY#3o6YM9g+8aDjplSy4-?af;H%fYXBuS?#HjY$F`fI77-VEcY1Kar
zLRYgHb;^mvO=zS~B&t7+BOCa7dpkJaq)4$ Bs-c~B4%FL^ y1B^409Ct?~dPBYx3;>a17IuVd26beOUW;{D?>4sjdy3Vgn?m2-l2LSz=R
zl=LtXAthI!QzR)XbI!4?H!(YyRI2F7!bQd{^V-Y>#
z7CEFZeRUTaOE2=%7-nJGi=^`*i7z_OQE>r
zCa2{hOXaCnjL9y!x^gCQB5Cwh`0iksEb4Xz8o~r7W-V+|rWE0@1_~x;nDU$D8+LB-Lk!_
&~
zpPQ(U2`hh0Soo!3XTpr7
@dd5v~Ki-rbcPPMN|P|3gW$yLnh&?l~&qUh|LxP;lU|7`6
zxFANHfY3i;phcsKnvP%uK_uh))6PN02Y19P?0`XMY|yDg|4kJWo5ZMKHwcqsL?VgO
zcmj1?Vr1s&hOhj@4Fbl0zTyIFX}tvwoyH3uJDlBaPkIrW+=WZ7oNkXuBocu}E&Kny
zOBTgtsLIoDQ-ruTY9UxF*s9kC*XwvqGsfy+K9+x;2p46);j}M49RaPD$Q{JqqgcXz
ze=ucttv6#u4ahY|0D(sz
#uf_7-5}6u0)Bd
z3*IfD8iyjQ4dvrA!OQAyvJ&T+zgaIg>ZO8$#hZ$!1SB)%ZgnV2VIai)FrRwYtVES1
zn7}&I9?eZR4l8R|(H%>BZ={dJwv`sa_XqG+8Q^yW%-6Q3z~%-n&t1jp0@yh%vU0(t
zu+8wvs?HDP1dszV(+af>Z4a9TUmoVv)J=cpXyf@rJjHJ3c*#mtOO!v@eP;hM6f;er
zY2@!>>n*KTa1RE+&LuT7D;G^gHI&5D