From 3378d3709d7e6ab8321bd677465b85c4f6e2b95e Mon Sep 17 00:00:00 2001 From: TheBananaPancake Date: Mon, 26 Oct 2026 21:37:41 +0000 Subject: [PATCH] Add LibreWolf as supported browser Signed-off-by: TheBananaPancake <256630335+TheBananaPancake@users.noreply.github.com> --- bin/omarchy-default-browser | 6 ++- bin/omarchy-install-browser | 12 ++++- bin/omarchy-remove-browser | 9 +++- default/fonts/omarchy/README.md | 1 + default/fonts/omarchy/omarchy.ttf | Bin 16212 -> 16868 bytes default/librewolf/policies.json | 27 +++++++++++ default/omarchy/omarchy-menu.jsonc | 3 ++ install/helpers/browser-policy.sh | 44 +++++++++++++++++ manual/23-browsers.md | 10 ++-- test/shell.d/browser-policy-dir-test.sh | 60 ++++++++++++++++++++++++ test/shell.d/default-apps-test.sh | 54 +++++++++++++++++++++ 11 files changed, 216 insertions(+), 10 deletions(-) create mode 100644 default/librewolf/policies.json diff --git a/bin/omarchy-default-browser b/bin/omarchy-default-browser index 5328d86fac8..9a78b33654d 100755 --- a/bin/omarchy-default-browser +++ b/bin/omarchy-default-browser @@ -1,7 +1,7 @@ #!/bin/bash # omarchy:summary=Set the default browser for Omarchy and XDG handlers -# omarchy:args=[chromium|chrome|brave|brave-origin|edge|firefox|zen] +# omarchy:args=[chromium|chrome|brave|brave-origin|edge|firefox|librewolf|zen] # omarchy:examples=omarchy default browser firefox | omarchy default browser brave installing=false @@ -19,6 +19,7 @@ if (($# == 0)); then brave-origin.desktop) echo "brave-origin" ;; microsoft-edge.desktop) echo "edge" ;; firefox.desktop) echo "firefox" ;; + librewolf.desktop) echo "librewolf" ;; zen.desktop) echo "zen" ;; *) echo "$current_browser" ;; esac @@ -32,9 +33,10 @@ brave) browser="brave"; command="brave"; desktop_id="brave-browser.desktop"; nam brave-origin) browser="brave-origin"; command="brave-origin"; desktop_id="brave-origin.desktop"; name="Brave Origin"; glyph=󰖟 ;; edge) browser="edge"; command="microsoft-edge-stable"; desktop_id="microsoft-edge.desktop"; name="Edge"; glyph=󰇩 ;; firefox) browser="firefox"; command="firefox"; desktop_id="firefox.desktop"; name="Firefox"; glyph=󰈹 ;; +librewolf) browser="librewolf"; command="librewolf"; desktop_id="librewolf.desktop"; name="LibreWolf"; glyph=󰖟 ;; zen) browser="zen"; command="zen-browser"; desktop_id="zen.desktop"; name="Zen"; glyph=󰖟 ;; *) - echo "Usage: omarchy-default-browser " + echo "Usage: omarchy-default-browser " exit 1 ;; esac diff --git a/bin/omarchy-install-browser b/bin/omarchy-install-browser index 196e89ccc98..f83ac77f457 100755 --- a/bin/omarchy-install-browser +++ b/bin/omarchy-install-browser @@ -1,7 +1,7 @@ #!/bin/bash # omarchy:summary=Install a supported browser -# omarchy:args= +# omarchy:args= # omarchy:examples=omarchy install browser chromium | omarchy install browser firefox set -e @@ -105,6 +105,14 @@ firefox) omarchy-lifecycle-dispatch post-install firefox announce_browser_installed "Firefox" ;; +librewolf) + echo "Installing LibreWolf..." + omarchy-pkg-add librewolf || exit 1 + + browser_policy_setup_librewolf_policies /etc/librewolf/policies + setup_firefox_wayland + announce_browser_installed "LibreWolf" + ;; zen) echo "Installing Zen..." omarchy-pkg-aur-add zen-browser-bin || exit 1 @@ -115,7 +123,7 @@ zen) announce_browser_installed "Zen" ;; *) - echo "Usage: omarchy-install-browser " + echo "Usage: omarchy-install-browser " exit 1 ;; esac diff --git a/bin/omarchy-remove-browser b/bin/omarchy-remove-browser index 4c7f7bae284..901ec2fed48 100755 --- a/bin/omarchy-remove-browser +++ b/bin/omarchy-remove-browser @@ -1,7 +1,7 @@ #!/bin/bash # omarchy:summary=Remove a supported browser and clean up Omarchy browser defaults -# omarchy:args= +# omarchy:args= # omarchy:examples=omarchy remove browser firefox | omarchy remove browser brave # omarchy:requires-sudo=true @@ -58,13 +58,18 @@ firefox) set_fallback_default_browser firefox.desktop omarchy-pkg-drop firefox ;; +librewolf) + echo "Removing LibreWolf..." + set_fallback_default_browser librewolf.desktop + omarchy-pkg-drop librewolf + ;; zen) echo "Removing Zen..." set_fallback_default_browser zen.desktop omarchy-pkg-drop zen-browser-bin ;; *) - echo "Usage: omarchy-remove-browser " + echo "Usage: omarchy-remove-browser " exit 1 ;; esac diff --git a/default/fonts/omarchy/README.md b/default/fonts/omarchy/README.md index df8a0d802ff..1aa098ee0bf 100644 --- a/default/fonts/omarchy/README.md +++ b/default/fonts/omarchy/README.md @@ -34,6 +34,7 @@ The private-use glyphs in `omarchy.ttf` are: - `U+E91D` — Kimi, from - `U+E91E` — Crush, the heartbit from , its eyes and mouth cut out - `U+E91F` — Muse Code, from : Meta publishes no separate Muse mark and dev.meta.ai uses this one +- `U+E920` — LibreWolf, from The agent marks are monochrome so the menu can render them using the active theme's foreground and selection colors. diff --git a/default/fonts/omarchy/omarchy.ttf b/default/fonts/omarchy/omarchy.ttf index 10277b494ed6027fad14f7788edade79bc8d229b..66ee41a001408362618d9d49e5fd7cd97189bc70 100644 GIT binary patch delta 899 zcmZ9KTWb?R6vyYbyR-LO)-|oUblYs2T4UR^Nl}{yL@SEeh)7k6jkOmcy`V)aXd~DM zL6Abef{!AU>Wc_g!8Z#Af)7%BvG^u_1fATfIDcl~cjkZ2oC8x`+j|T*`b%r(1OV^} z0O;&o@&0V$OV@7za20@~>+>^(o5`2Qo&k_z9*~}A0SZYE;|<1L^9w7h>p=R(_!Z;l z#ii-O`=OoJ01Vdrmlg`E%kUKHWBh_~bg{57lX|-Qkntw~_*0Cs1c$}=tqLM=tBScJB?59Fhqv)Ih=6lo2UM8HJx~`fG~~w{N@p5s z#d#;tbTWTxpn1zYLxar>Ki;TRKbzI++56rSGw(y|fpnY|5InX60w4D?>3X^5vn;yb zfWWf`+<&>|ujy~qlq+O1XfmJAj&ynudYvQLe15XUrBH!sD{D|YA|k4HW@ delta 241 zcmaFT%y^}4f?<8FU^oKZ9sxrr48j4n(D z3=BpZK)ym=Vs5H&_nlfG--CgHdt*UOg9y+"$tmp"; then + rm -f "$tmp" + return 1 + fi + + if as_root install -m 644 -o root -g root -T "$tmp" "$policy_dir/policies.json"; then + rm -f "$tmp" + return 0 + fi + + rm -f "$tmp" + return 1 +} + +browser_policy_setup_librewolf_policies() { + local policy_dir=$1 + local packaged=${2:-/usr/lib/librewolf/distribution/policies.json} + local overlay=${3:-$OMARCHY_PATH/default/librewolf/policies.json} + + browser_policy_setup_parent "$policy_dir" + browser_policy_purge_dir "$policy_dir" + browser_policy_install_librewolf_policies "$policy_dir" "$packaged" "$overlay" +} diff --git a/manual/23-browsers.md b/manual/23-browsers.md index 03548c7a2c3..86c46a2b3e2 100644 --- a/manual/23-browsers.md +++ b/manual/23-browsers.md @@ -2,7 +2,7 @@ Omarchy ships with [Chromium](https://www.chromium.org/) as the default browser. It's the plain open-source build, themed to match the rest of your system, and it's what `Super + Shift + Return` opens and what every [web app](25-web-apps.md) runs inside. -If Chromium isn't your taste, you're not stuck with it. Under _Install > Browser_ in the Omarchy menu you'll find Chrome, Edge, Brave, Brave Origin, Firefox, and [Zen](https://zen-browser.app/). Pick one and Omarchy installs it, sets up its policy directory, and applies your current theme to it. +If Chromium isn't your taste, you're not stuck with it. Under _Install > Browser_ in the Omarchy menu you'll find Chrome, Edge, Brave, Brave Origin, Firefox, LibreWolf, and [Zen](https://zen-browser.app/). Pick one and Omarchy installs it, sets up its policy directory, and applies your current theme to it. ## Making one the default @@ -26,11 +26,13 @@ The Chromium-family browsers (Chromium itself, Chrome, Edge, and Brave) come wit Both extensions talk to Omarchy through a small native messaging host, which gets installed for you along with the browser. That's the piece that lets a web page's video end up in your home directory and a URL end up in your clipboard manager, which a normal extension can't do on its own. -These are Chromium-family only. Firefox and Zen don't get them. +These are Chromium-family only. Firefox, LibreWolf, and Zen don't get them. -## Firefox and Zen +## Firefox, LibreWolf, and Zen -Firefox and Zen are a different family, so they get different treatment: Omarchy installs a policies file for sensible defaults and switches them into native Wayland mode, which you want for fractional scaling and smooth trackpad scrolling. +Firefox, LibreWolf, and Zen are a different family, so they get different treatment: Omarchy installs a policies file for sensible defaults and switches them into native Wayland mode, which you want for fractional scaling and smooth trackpad scrolling. + +LibreWolf is a special case: it ships its own policies (uBlock Origin installed, HTTPS-Only on), and it uses either its own file or Omarchy's, never both. So when Omarchy installs it, it merges its own defaults over the policies LibreWolf ships, and you keep everything LibreWolf brings even as LibreWolf updates those policies. They don't get the Chromium extensions above, and they're not themed by Omarchy, so those parts of the experience are yours to set up. diff --git a/test/shell.d/browser-policy-dir-test.sh b/test/shell.d/browser-policy-dir-test.sh index 8cb5159e392..0efd5cc30b9 100755 --- a/test/shell.d/browser-policy-dir-test.sh +++ b/test/shell.d/browser-policy-dir-test.sh @@ -277,6 +277,66 @@ fi [[ -d $dir_dist/policies.json ]] || fail "Firefox policy install leaves a planted policies.json directory in place" pass "Firefox policy install does not write into a planted policies.json directory" +lw_packaged=$test_tmp/librewolf-packaged-policies.json +cat >"$lw_packaged" <<'JSON' +{ + "__COMMENT__ More Information": "https://github.com/mozilla/policy-templates/blob/master/README.md", + "policies": { + "DisableTelemetry": true, + "HttpsOnlyMode": "enabled", + "ExtensionSettings": { + "uBlock0@raymondhill.net": { + "install_url": "https://addons.mozilla.org/firefox/downloads/latest/uBlock0@raymondhill.net/latest.xpi", + "installation_mode": "normal_installed", + "private_browsing": true + } + }, + "Preferences": { + "apz.overscroll.enabled": { + "Value": false, + "Status": "locked" + } + } + } +} +JSON + +lw_merged=$(browser_policy_librewolf_merged_policies "$lw_packaged") +jq -e '.policies.DisableTelemetry == true and .policies.HttpsOnlyMode == "enabled"' <<<"$lw_merged" >/dev/null || + fail "the LibreWolf merge keeps LibreWolf's own policies" +jq -e '.policies.ExtensionSettings."uBlock0@raymondhill.net".installation_mode == "normal_installed"' <<<"$lw_merged" >/dev/null || + fail "the LibreWolf merge keeps LibreWolf's uBlock Origin defaults" +jq -e '.policies.Preferences."widget.wayland.fractional-scale.enabled" == {"Value": true, "Status": "default"}' <<<"$lw_merged" >/dev/null || + fail "the LibreWolf merge carries Omarchy's Preferences" +jq -e '.policies.Preferences."apz.overscroll.enabled" == {"Value": true, "Status": "default"}' <<<"$lw_merged" >/dev/null || + fail "the LibreWolf merge lets Omarchy's overlay win over the packaged policies" +jq -e '."__COMMENT__ More Information" != null' <<<"$lw_merged" >/dev/null || + fail "the LibreWolf merge keeps the packaged comment keys" +pass "LibreWolf policies merge the packaged file with Omarchy's overlay" + +lw_dir=$test_tmp/librewolf-policies +mkdir -p "$lw_dir" +printf 'original\n' >"$test_tmp/librewolf-pwn" +ln -s "$test_tmp/librewolf-pwn" "$lw_dir/policies.json" +as_root() { unprivileged_as_root "$@"; } +browser_policy_install_librewolf_policies "$lw_dir" "$lw_packaged" || + fail "LibreWolf policy install replaces a planted policies.json symlink" +[[ -f $lw_dir/policies.json && ! -L $lw_dir/policies.json ]] || + fail "LibreWolf policy install unlinks a planted policies.json symlink instead of writing through it" +grep -Fxq 'original' "$test_tmp/librewolf-pwn" || fail "LibreWolf policy install leaves the symlink target unchanged" +mode=$(stat -c '%a' "$lw_dir/policies.json") +[[ $mode == "644" ]] || fail "LibreWolf policy install writes a root-mode policies.json" "mode=$mode" +jq -e '.policies.ExtensionSettings."uBlock0@raymondhill.net" != null and .policies.Preferences != null' "$lw_dir/policies.json" >/dev/null || + fail "LibreWolf policy install writes the merged policies" +pass "LibreWolf policy install does not follow a planted policies.json symlink" + +if browser_policy_install_librewolf_policies "$lw_dir" "$test_tmp/no-such-packaged-policies.json" 2>/dev/null; then + fail "LibreWolf policy install refuses a missing packaged policies file" +fi +jq -e '.policies.Preferences != null' "$lw_dir/policies.json" >/dev/null || + fail "a refused LibreWolf install leaves the existing merged policies intact" +pass "LibreWolf policy install refuses to merge without the packaged policies" + grep -F 'exit "$failed"' "$ROOT/bin/omarchy-theme-set-browser" >/dev/null || fail "omarchy-theme-set-browser exits non-zero when a policy write fails" pass "omarchy-theme-set-browser exits non-zero when a policy write fails" diff --git a/test/shell.d/default-apps-test.sh b/test/shell.d/default-apps-test.sh index fe7787c9682..2a090fc0fbc 100755 --- a/test/shell.d/default-apps-test.sh +++ b/test/shell.d/default-apps-test.sh @@ -14,9 +14,30 @@ install_log="$test_tmp/install-log" terminal_log="$test_tmp/terminal-log" notification_log="$test_tmp/notification-log" setup_log="$test_tmp/setup-log" +jq_log="$test_tmp/jq-log" browser_file="$test_tmp/browser" mkdir -p "$mock_bin" "$test_home/.config" "$installed_dir" +# The LibreWolf installer merges the packaged policies with Omarchy's overlay +# through jq. The packaged file only exists on machines that have LibreWolf +# installed, so the merge runs against this stand-in and only its invocation +# is asserted here; browser-policy-dir-test.sh exercises the real merge. +librewolf_packaged="$test_tmp/librewolf-packaged-policies.json" +cat >"$librewolf_packaged" <<'JSON' +{ + "policies": { + "DisableTelemetry": true, + "HttpsOnlyMode": "enabled", + "ExtensionSettings": { + "uBlock0@raymondhill.net": { + "installation_mode": "normal_installed", + "private_browsing": true + } + } + } +} +JSON + cat >"$mock_bin/omarchy-cmd-missing" <<'SH' #!/bin/bash [[ ! -e $OMARCHY_TEST_INSTALLED_DIR/$1 ]] @@ -58,6 +79,16 @@ set) esac SH +cat >"$mock_bin/jq" <<'SH' +#!/bin/bash +printf 'jq:%s\n' "$*" >>"$OMARCHY_TEST_JQ_LOG" +if [[ $1 == "-s" && $2 == '.[0] * .[1]' ]]; then + cat "$OMARCHY_TEST_LIBREWOLF_PACKAGED_POLICIES" +elif [[ -x /usr/bin/jq ]]; then + exec /usr/bin/jq "$@" +fi +SH + cat >"$mock_bin/omarchy-test-installer" <<'SH' #!/bin/bash installer=${0##*/} @@ -73,6 +104,7 @@ omarchy-pkg-add|omarchy-pkg-aur-add) case $package in chromium) command=chromium ;; firefox) command=firefox ;; + librewolf) command=librewolf ;; zen-browser-bin) command=zen-browser ;; cursor-bin) command=cursor ;; sublime-text-4) command=subl ;; @@ -90,6 +122,7 @@ omarchy-install-browser) brave-origin) command=brave-origin ;; edge) command=microsoft-edge-stable ;; firefox) command=firefox ;; + librewolf) command=librewolf ;; zen) command=zen-browser ;; esac ;; @@ -144,7 +177,9 @@ export OMARCHY_TEST_INSTALL_LOG="$install_log" export OMARCHY_TEST_TERMINAL_LOG="$terminal_log" export OMARCHY_TEST_NOTIFICATION_LOG="$notification_log" export OMARCHY_TEST_SETUP_LOG="$setup_log" +export OMARCHY_TEST_JQ_LOG="$jq_log" export OMARCHY_TEST_BROWSER_FILE="$browser_file" +export OMARCHY_TEST_LIBREWOLF_PACKAGED_POLICIES="$librewolf_packaged" assert_missing_opens_installer() { local type=$1 @@ -164,6 +199,7 @@ browser_cases=( 'brave-origin brave-origin browser:brave-origin' 'edge microsoft-edge-stable browser:edge' 'firefox firefox browser:firefox' + 'librewolf librewolf browser:librewolf' 'zen zen-browser browser:zen' ) @@ -251,6 +287,24 @@ grep -Fxq "sudo:install -m 644 -o root -g root -T $ROOT/default/firefox/policies [[ -e $installed_dir/firefox ]] || fail "Firefox browser installer marks firefox installed" pass "Firefox browser installer restores the complete Omarchy setup" +: >"$install_log" +: >"$setup_log" +: >"$jq_log" +rm -f "$installed_dir/librewolf" +OMARCHY_TEST_REAL_BROWSER_INSTALL=true omarchy-default-browser --install librewolf >/dev/null +[[ $(<"$install_log") == "pkg:librewolf" ]] || fail "LibreWolf browser installer installs the package" +[[ $(omarchy-default-browser) == "librewolf" ]] || fail "LibreWolf becomes the default after its full installer succeeds" +grep -Fxq 'sudo:install -d -m 0755 -o root -g root /etc/librewolf/policies' "$setup_log" || + fail "LibreWolf browser installer creates its policy directory" +grep -Fxq 'sudo:find /etc/librewolf/policies -mindepth 1 -maxdepth 1 ! -user root -exec rm -rf -- {} +' "$setup_log" || + fail "LibreWolf browser installer drops non-root files from its policy directory" +grep -Eq 'sudo:install -m 644 -o root -g root -T [^ ]+ /etc/librewolf/policies/policies\.json' "$setup_log" || + fail "LibreWolf browser installer installs its merged policies.json without following a destination symlink" +grep -Fxq "jq:-s .[0] * .[1] /usr/lib/librewolf/distribution/policies.json $ROOT/default/librewolf/policies.json" "$jq_log" || + fail "LibreWolf browser installer merges LibreWolf's packaged policies with Omarchy's overlay" +[[ -e $installed_dir/librewolf ]] || fail "LibreWolf browser installer marks librewolf installed" +pass "LibreWolf browser installer restores the complete Omarchy setup" + : >"$install_log" : >"$setup_log" rm -f "$installed_dir/zen-browser"