mirror of
https://github.com/lhns/steam-frame-nix.git
synced 2026-10-06 04:00:12 +02:00
firefox: desktop profile user.js only while its Firefox runs
The desktop profile's user.js link (undoing the fullscreen fix there) was kept in place on every switch and before every launch. Now the launcher (nested desktop only) makes it right before Firefox starts, waits for Firefox instead of exec'ing it, and once it has exited and the profile is no longer in use removes the link and the value Firefox stored from it in prefs.js. A second launch that hands its URL to the running Firefox returns at once and leaves both alone; a user.js of the user's own is never touched. The desktop profile itself is a normal Firefox profile (browser data) and is never removed. No activation step touches profiles anymore: leftovers of a crash and what older versions wrote (user.js copies and links, their prefs.js values) are steam-frame-nix-cleanup's (orphans on switch), which leaves the desktop link alone while the profile is in use; the firefox-desktop-userjs --keep is gone. The launcher lives in firefox/launcher.nix; checks.firefox runs it against a fake flatpak (link only while running, forwarded second launch, prefs.js cleaned only once unlocked, own user.js untouched, Steam session).
This commit is contained in:
1 parent
a0111813b3
commit
1672210ead
6 files changed
+198
-140
No files matched your search
@@ -56,10 +56,11 @@
|
|||||||
}) self.packages;
|
}) self.packages;
|
||||||
|
|
||||||
# Tests of the VR keyboard (text model, corrector, swipe decoder on the
|
# Tests of the VR keyboard (text model, corrector, swipe decoder on the
|
||||||
# default German + English dictionary), the Jellyfin mpv shim and
|
# default German + English dictionary), the Jellyfin mpv shim, the
|
||||||
# install.sh cleanup: nix flake check
|
# Firefox launcher and install.sh cleanup: nix flake check
|
||||||
checks = forSystems (pkgs: {
|
checks = forSystems (pkgs: {
|
||||||
cleanup = import ./modules/cleanup/check.nix { inherit pkgs; };
|
cleanup = import ./modules/cleanup/check.nix { inherit pkgs; };
|
||||||
|
firefox = import ./modules/firefox/check.nix { inherit pkgs; };
|
||||||
jellyfin = import ./modules/jellyfin/check.nix { inherit pkgs; };
|
jellyfin = import ./modules/jellyfin/check.nix { inherit pkgs; };
|
||||||
vr-keyboard = (import ./modules/vr-keyboard/build.nix {
|
vr-keyboard = (import ./modules/vr-keyboard/build.nix {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
|||||||
+17
-13
@@ -74,8 +74,7 @@ Commands:
|
|||||||
or before removing it.
|
or before removing it.
|
||||||
--orphans what the configuration no longer uses (run by the Home
|
--orphans what the configuration no longer uses (run by the Home
|
||||||
Manager module on every switch); keeps saved choices.
|
Manager module on every switch); keeps saved choices.
|
||||||
--keep still in use (with --orphans): debugger,
|
--keep still in use (with --orphans): debugger
|
||||||
firefox-desktop-userjs=<profile>
|
|
||||||
--dry-run only print what would be done
|
--dry-run only print what would be done
|
||||||
--quiet print only actions, deferrals and warnings
|
--quiet print only actions, deferrals and warnings
|
||||||
SteamVR's VRWebHelper.DebuggerEnabled can't be changed while SteamVR
|
SteamVR's VRWebHelper.DebuggerEnabled can't be changed while SteamVR
|
||||||
@@ -396,10 +395,12 @@ EOF
|
|||||||
# icons links hicolor/scalable/apps/<name>.svg -> Breeze in the store
|
# icons links hicolor/scalable/apps/<name>.svg -> Breeze in the store
|
||||||
# (the icon-fallbacks script of 2026-09; manifest
|
# (the icon-fallbacks script of 2026-09; manifest
|
||||||
# $SFN_STATE/icon-fallbacks).
|
# $SFN_STATE/icon-fallbacks).
|
||||||
# firefox user.js in Firefox profiles: links to the desktop profile's
|
# firefox user.js in Firefox profiles: links to
|
||||||
# /app/etc/firefox/steam-frame-nix-desktop-user.js, older links
|
# /app/etc/firefox/steam-frame-nix-desktop-user.js (the
|
||||||
# to *-firefox-*user.js and copies starting with FF_MARKER, and
|
# launcher's, while the desktop profile runs; left alone while
|
||||||
# the values they left in prefs.js (only with Firefox closed).
|
# the profile is in use), older links to *-firefox-*user.js and
|
||||||
|
# copies starting with FF_MARKER, and the values they left in
|
||||||
|
# prefs.js (only with Firefox closed).
|
||||||
# jellyfin the hwdec shim entries in the Jellyfin Flatpak's user override
|
# jellyfin the hwdec shim entries in the Jellyfin Flatpak's user override
|
||||||
# (nix-flatpak), an empty override file, and the shim copy of
|
# (nix-flatpak), an empty override file, and the shim copy of
|
||||||
# earlier versions (marker $SFN_STATE/jellyfin-hwdec-shim).
|
# earlier versions (marker $SFN_STATE/jellyfin-hwdec-shim).
|
||||||
@@ -714,8 +715,8 @@ clean_icons() {
|
|||||||
ff_keys() { sed -n 's/^[[:space:]]*user_pref(\("[^"]*"\),.*/\1/p' "$1" 2>/dev/null || true; }
|
ff_keys() { sed -n 's/^[[:space:]]*user_pref(\("[^"]*"\),.*/\1/p' "$1" 2>/dev/null || true; }
|
||||||
ff_in_use() { find /proc/[0-9]*/fd -lname "$1/.parentlock" -print -quit 2>/dev/null | grep -q .; }
|
ff_in_use() { find /proc/[0-9]*/fd -lname "$1/.parentlock" -print -quit 2>/dev/null | grep -q .; }
|
||||||
|
|
||||||
clean_firefox() { # keep_profile ('' = none)
|
clean_firefox() { # all
|
||||||
local keep=$1 prof name u t kind keys pats left
|
local all=$1 prof name u t kind keys pats left
|
||||||
[[ -d $FF_DIR ]] || return 0
|
[[ -d $FF_DIR ]] || return 0
|
||||||
for prof in "$FF_DIR"/*/; do
|
for prof in "$FF_DIR"/*/; do
|
||||||
prof=${prof%/}; name=${prof##*/}; u=$prof/user.js
|
prof=${prof%/}; name=${prof##*/}; u=$prof/user.js
|
||||||
@@ -725,7 +726,11 @@ clean_firefox() { # keep_profile ('' = none)
|
|||||||
t="$(readlink "$u")"
|
t="$(readlink "$u")"
|
||||||
case $t in
|
case $t in
|
||||||
"$FF_DESKTOP_JS")
|
"$FF_DESKTOP_JS")
|
||||||
[[ $name == "$keep" ]] && continue
|
# The launcher's, while Firefox runs in the desktop profile.
|
||||||
|
if ff_in_use "$prof"; then
|
||||||
|
(( all )) && c_defer "$u: Firefox is using profile $name; close it and run this again"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
kind="desktop profile user.js link"; keys='"full-screen-api.ignore-widgets"' ;;
|
kind="desktop profile user.js link"; keys='"full-screen-api.ignore-widgets"' ;;
|
||||||
/nix/store/*-firefox-user.js|/nix/store/*-firefox-desktop-user.js)
|
/nix/store/*-firefox-user.js|/nix/store/*-firefox-desktop-user.js)
|
||||||
kind="user.js link of an older version"; keys="$(ff_keys "$u")"
|
kind="user.js link of an older version"; keys="$(ff_keys "$u")"
|
||||||
@@ -846,7 +851,7 @@ clean_ui_state() { # all
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmd_cleanup() {
|
cmd_cleanup() {
|
||||||
local mode='' keep_debugger=0 keep_ff='' keeps=0 k
|
local mode='' keep_debugger=0 keeps=0 k
|
||||||
while (( $# )); do
|
while (( $# )); do
|
||||||
case $1 in
|
case $1 in
|
||||||
--all) mode=all; shift ;;
|
--all) mode=all; shift ;;
|
||||||
@@ -858,8 +863,7 @@ cmd_cleanup() {
|
|||||||
k=$2; shift 2; keeps=$((keeps + 1))
|
k=$2; shift 2; keeps=$((keeps + 1))
|
||||||
case $k in
|
case $k in
|
||||||
debugger) keep_debugger=1 ;;
|
debugger) keep_debugger=1 ;;
|
||||||
firefox-desktop-userjs=?*) keep_ff=${k#*=} ;;
|
*) die "cleanup: unknown artifact '$k' for --keep (debugger)" ;;
|
||||||
*) die "cleanup: unknown artifact '$k' for --keep (debugger, firefox-desktop-userjs=<profile>)" ;;
|
|
||||||
esac ;;
|
esac ;;
|
||||||
-h|--help) usage; exit 0 ;;
|
-h|--help) usage; exit 0 ;;
|
||||||
*) die "cleanup: unknown option '$1' (see --help)" ;;
|
*) die "cleanup: unknown option '$1' (see --help)" ;;
|
||||||
@@ -875,7 +879,7 @@ cmd_cleanup() {
|
|||||||
if (( ! CLEAN_QUIET )); then step "$CLEAN_HEADER"; CLEAN_HEADER=''; fi
|
if (( ! CLEAN_QUIET )); then step "$CLEAN_HEADER"; CLEAN_HEADER=''; fi
|
||||||
clean_debugger "$keep_debugger"
|
clean_debugger "$keep_debugger"
|
||||||
clean_icons
|
clean_icons
|
||||||
clean_firefox "$keep_ff"
|
clean_firefox "$([[ $mode == all ]] && echo 1 || echo 0)"
|
||||||
clean_jellyfin
|
clean_jellyfin
|
||||||
clean_ui_state "$([[ $mode == all ]] && echo 1 || echo 0)"
|
clean_ui_state "$([[ $mode == all ]] && echo 1 || echo 0)"
|
||||||
c_rmdir "$SFN_STATE"
|
c_rmdir "$SFN_STATE"
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ pkgs.runCommand "cleanup-check" { nativeBuildInputs = [ cleanup pkgs.jq ]; } ''
|
|||||||
echo absent > $S/steamvr-debugger.armed
|
echo absent > $S/steamvr-debugger.armed
|
||||||
mkdir -p $F/desktop $F/x.default
|
mkdir -p $F/desktop $F/x.default
|
||||||
ln -s /app/etc/firefox/steam-frame-nix-desktop-user.js $F/desktop/user.js
|
ln -s /app/etc/firefox/steam-frame-nix-desktop-user.js $F/desktop/user.js
|
||||||
|
touch $F/desktop/.parentlock; exec 8< $F/desktop/.parentlock # the launcher's, Firefox running
|
||||||
ln -s /app/etc/firefox/steam-frame-nix-desktop-user.js $F/x.default/user.js
|
ln -s /app/etc/firefox/steam-frame-nix-desktop-user.js $F/x.default/user.js
|
||||||
printf '[Context]\ndevices=all;\nfilesystems=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim:ro;\n\n[Environment]\nLD_PRELOAD=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim/lib/mpv-hwdec-shim.so\nSFN_MPV_HWDEC=x\n' > $O/org.jellyfin.JellyfinDesktop
|
printf '[Context]\ndevices=all;\nfilesystems=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim:ro;\n\n[Environment]\nLD_PRELOAD=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim/lib/mpv-hwdec-shim.so\nSFN_MPV_HWDEC=x\n' > $O/org.jellyfin.JellyfinDesktop
|
||||||
mkdir -p $HOME/.var/app/org.jellyfin.JellyfinDesktop
|
mkdir -p $HOME/.var/app/org.jellyfin.JellyfinDesktop
|
||||||
@@ -164,25 +165,28 @@ pkgs.runCommand "cleanup-check" { nativeBuildInputs = [ cleanup pkgs.jq ]; } ''
|
|||||||
echo '{' > $S/ui-patches/x.json.tmp; touch -d '-1 hour' $S/ui-patches/x.json.tmp
|
echo '{' > $S/ui-patches/x.json.tmp; touch -d '-1 hour' $S/ui-patches/x.json.tmp
|
||||||
echo '{' > $S/ui-patches/y.json.tmp # being written: kept
|
echo '{' > $S/ui-patches/y.json.tmp # being written: kept
|
||||||
echo active > $STUB/state
|
echo active > $STUB/state
|
||||||
res=$(steam-frame-nix-cleanup --orphans --keep debugger --keep firefox-desktop-userjs=desktop); echo "$res"
|
res=$(steam-frame-nix-cleanup --orphans --keep debugger); echo "$res"
|
||||||
hasnt "$res" "deferred" # kept: the next start re-arms it
|
hasnt "$res" "deferred" # kept: the next start re-arms it
|
||||||
there $root/run/systemd/user/steamvr.service.d/50-steam-frame-nix-debugger.conf $S/steamvr-debugger.armed
|
there $root/run/systemd/user/steamvr.service.d/50-steam-frame-nix-debugger.conf $S/steamvr-debugger.armed
|
||||||
there $F/desktop/user.js $S/ui-patches/frame-controls.json $S/ui-patches/vr-cat.json $S/ui-patches/y.json.tmp
|
there $F/desktop/user.js $S/ui-patches/frame-controls.json $S/ui-patches/vr-cat.json $S/ui-patches/y.json.tmp
|
||||||
gone $F/x.default/user.js $O/org.jellyfin.JellyfinDesktop $S/ui-patches/x.json.tmp
|
gone $F/x.default/user.js $O/org.jellyfin.JellyfinDesktop $S/ui-patches/x.json.tmp
|
||||||
there $HOME/.var/app/org.jellyfin.JellyfinDesktop/mpv-hwdec-shim.so
|
there $HOME/.var/app/org.jellyfin.JellyfinDesktop/mpv-hwdec-shim.so
|
||||||
has "$res" "left alone: $HOME/.var/app/org.jellyfin.JellyfinDesktop/mpv-hwdec-shim.so"
|
has "$res" "left alone: $HOME/.var/app/org.jellyfin.JellyfinDesktop/mpv-hwdec-shim.so"
|
||||||
noop --orphans --keep debugger --keep firefox-desktop-userjs=desktop
|
noop --orphans --keep debugger
|
||||||
# SteamVR stopped (e.g. after a power loss): the key is restored, hook kept
|
# SteamVR stopped (e.g. after a power loss): the key is restored, hook kept
|
||||||
echo inactive > $STUB/state
|
echo inactive > $STUB/state
|
||||||
res=$(steam-frame-nix-cleanup --orphans --keep debugger --keep firefox-desktop-userjs=desktop)
|
res=$(steam-frame-nix-cleanup --orphans --keep debugger)
|
||||||
[ "$(jq -c . $V)" = '{}' ] || fail "orphans restore: $(cat $V)"
|
[ "$(jq -c . $V)" = '{}' ] || fail "orphans restore: $(cat $V)"
|
||||||
gone $S/steamvr-debugger.armed
|
gone $S/steamvr-debugger.armed
|
||||||
there $root/run/systemd/user/steamvr.service.d/50-steam-frame-nix-debugger.conf
|
there $root/run/systemd/user/steamvr.service.d/50-steam-frame-nix-debugger.conf
|
||||||
# debugger no longer kept: runtime pieces go
|
# debugger no longer kept: runtime pieces go
|
||||||
res=$(steam-frame-nix-cleanup --orphans --keep firefox-desktop-userjs=desktop)
|
res=$(steam-frame-nix-cleanup --orphans)
|
||||||
gone $root/run/steam-frame-nix $root/run/systemd
|
gone $root/run/steam-frame-nix $root/run/systemd
|
||||||
noop --orphans --keep firefox-desktop-userjs=desktop
|
noop --orphans
|
||||||
there $S/ui-patches/frame-controls.json $HOME/.local/share/icons/hicolor/scalable/apps # not ours
|
there $S/ui-patches/frame-controls.json $HOME/.local/share/icons/hicolor/scalable/apps # not ours
|
||||||
|
exec 8<&- # Firefox closed
|
||||||
|
res=$(steam-frame-nix-cleanup --orphans)
|
||||||
|
gone $F/desktop/user.js
|
||||||
! steam-frame-nix-cleanup --all --keep debugger 2>/dev/null || fail "--all --keep accepted"
|
! steam-frame-nix-cleanup --all --keep debugger 2>/dev/null || fail "--all --keep accepted"
|
||||||
! steam-frame-nix-cleanup --orphans --keep bogus 2>/dev/null || fail "unknown --keep accepted"
|
! steam-frame-nix-cleanup --orphans --keep bogus 2>/dev/null || fail "unknown --keep accepted"
|
||||||
echo "C ok"
|
echo "C ok"
|
||||||
|
|||||||
+47
-120
@@ -12,14 +12,14 @@
|
|||||||
# fullscreen inside the window.
|
# fullscreen inside the window.
|
||||||
# - desktopProfile: the sessions have separate buses/displays, so a second
|
# - desktopProfile: the sessions have separate buses/displays, so a second
|
||||||
# Firefox can't reach the running one and hits the profile lock; the nested
|
# Firefox can't reach the running one and hits the profile lock; the nested
|
||||||
# desktop gets its own profile. Fullscreen works there, so the fix is undone
|
# desktop gets its own profile (a normal Firefox profile: browser data).
|
||||||
# by a user.js in that profile: a link to the extension's
|
# Fullscreen works there, so the launcher undoes the fix in that profile
|
||||||
# steam-frame-nix-desktop-user.js (a sandbox path; dangling on the host).
|
# only while its Firefox runs: a user.js link to the extension's
|
||||||
# - profileSync (on switch and before each launch) keeps those links and
|
# steam-frame-nix-desktop-user.js (a sandbox path; dangling on the host),
|
||||||
# removes what older versions wrote: user.js copies starting with `marker`
|
# made right before Firefox starts and removed, with the value Firefox
|
||||||
# and links to *-firefox-*user.js store files, whose user_pref values
|
# stored from it in prefs.js, once it has exited (firefox/launcher.nix).
|
||||||
# Firefox had stored in prefs.js. They are taken out of prefs.js too, which
|
# Leftovers (a crash) and what older versions wrote into profiles (user.js
|
||||||
# needs the profile closed; profiles in use are left for the next run.
|
# copies and links) are removed by steam-frame-nix-cleanup (on switch).
|
||||||
# The entry shadows the Flatpak's (same ID), keeping MIME associations, and is
|
# The entry shadows the Flatpak's (same ID), keeping MIME associations, and is
|
||||||
# seen by the "+" menu (which reads only ~/.local/share/applications).
|
# seen by the "+" menu (which reads only ~/.local/share/applications).
|
||||||
{ config, pkgs, lib, ... }:
|
{ config, pkgs, lib, ... }:
|
||||||
@@ -32,7 +32,7 @@ let
|
|||||||
// lib.optionalAttrs cfg.vrFullscreenFix { "full-screen-api.ignore-widgets" = true; }
|
// lib.optionalAttrs cfg.vrFullscreenFix { "full-screen-api.ignore-widgets" = true; }
|
||||||
// cfg.prefs;
|
// cfg.prefs;
|
||||||
desktopFix = cfg.enable && cfg.vrFullscreenFix && cfg.desktopProfile != null;
|
desktopFix = cfg.enable && cfg.vrFullscreenFix && cfg.desktopProfile != null;
|
||||||
# Only ever this one pref (profileSync relies on it).
|
# Only ever this one pref (steam-frame-nix-cleanup relies on it).
|
||||||
desktopKeys = [ "full-screen-api.ignore-widgets" ];
|
desktopKeys = [ "full-screen-api.ignore-widgets" ];
|
||||||
desktopUserJsName = "steam-frame-nix-desktop-user.js";
|
desktopUserJsName = "steam-frame-nix-desktop-user.js";
|
||||||
|
|
||||||
@@ -46,78 +46,11 @@ let
|
|||||||
(k: "user_pref(${builtins.toJSON k}, false);\n") desktopKeys)} $out/${desktopUserJsName}
|
(k: "user_pref(${builtins.toJSON k}, false);\n") desktopKeys)} $out/${desktopUserJsName}
|
||||||
'');
|
'');
|
||||||
|
|
||||||
# Written by versions that copied user.js into every profile.
|
firefox = pkgs.callPackage ./firefox/launcher.nix {
|
||||||
marker = "// Managed by steam-frame-nix (steamFrame.firefox); rewritten on switch.";
|
profileDir = if cfg.desktopProfile == null then null else profileDir;
|
||||||
|
inherit desktopFix desktopKeys;
|
||||||
profileSync = pkgs.writeShellScript "firefox-profile-sync" ''
|
desktopJs = "/app/etc/firefox/${desktopUserJsName}";
|
||||||
PATH=${lib.makeBinPath (with pkgs; [ coreutils diffutils findutils gnugrep gnused ])}
|
};
|
||||||
ffDir="${ffDir}"
|
|
||||||
desktopJs=/app/etc/firefox/${desktopUserJsName}
|
|
||||||
[ -d "$ffDir" ] || exit 0
|
|
||||||
|
|
||||||
# Firefox holds .parentlock open while it uses a profile (the sandbox
|
|
||||||
# sees the profile at the same path).
|
|
||||||
inUse() { find /proc/[0-9]*/fd -lname "$1/.parentlock" -print -quit 2>/dev/null | grep -q .; }
|
|
||||||
keysOf() { sed -n 's/^[[:space:]]*user_pref(\("[^"]*"\),.*/\1/p' "$1" 2>/dev/null; }
|
|
||||||
|
|
||||||
for prof in "$ffDir"/*/; do
|
|
||||||
prof=''${prof%/}; name=''${prof##*/}
|
|
||||||
[ -f "$prof/prefs.js" ] || [ "$name" = ${lib.escapeShellArg (toString cfg.desktopProfile)} ] || continue
|
|
||||||
want= wantKeys=
|
|
||||||
${lib.optionalString desktopFix ''
|
|
||||||
[ "$name" = ${lib.escapeShellArg cfg.desktopProfile} ] &&
|
|
||||||
want=$desktopJs wantKeys=${lib.escapeShellArg (lib.concatMapStrings (k: builtins.toJSON k + "\n") desktopKeys)}
|
|
||||||
''}
|
|
||||||
userJs=$prof/user.js
|
|
||||||
if [ -L "$userJs" ]; then
|
|
||||||
case $(readlink "$userJs") in
|
|
||||||
"$want") continue ;;
|
|
||||||
"$desktopJs") oldKeys=${lib.escapeShellArg (lib.concatMapStrings (k: builtins.toJSON k + "\n") desktopKeys)} ;;
|
|
||||||
/nix/store/*-firefox-user.js|/nix/store/*-firefox-desktop-user.js) oldKeys=$(keysOf "$userJs") ;;
|
|
||||||
*) oldKeys=foreign ;;
|
|
||||||
esac
|
|
||||||
elif [ -f "$userJs" ]; then
|
|
||||||
if [ "$(head -n1 "$userJs")" = ${lib.escapeShellArg marker} ]; then oldKeys=$(keysOf "$userJs"); else oldKeys=foreign; fi
|
|
||||||
elif [ -e "$userJs" ]; then oldKeys=foreign
|
|
||||||
else oldKeys=
|
|
||||||
fi
|
|
||||||
if [ "$oldKeys" = foreign ]; then
|
|
||||||
[ -z "$want" ] || echo "firefox: skipping $userJs (not managed by steam-frame-nix, move it away to adopt)"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -e "$userJs" ] || [ -L "$userJs" ]; then
|
|
||||||
# Values our user.js set, no longer set by one: out of prefs.js.
|
|
||||||
keys=$(printf '%s\n' "$oldKeys" | grep -vxF -f <(printf '%s\n' "$wantKeys") | grep .)
|
|
||||||
if [ -n "$keys" ]; then
|
|
||||||
if inUse "$prof"; then
|
|
||||||
echo "firefox: $name is in use; its old user.js stays until the next switch or launch with Firefox closed"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
grep -vF "$(sed 's/.*/user_pref(&,/' <<< "$keys")" "$prof/prefs.js" > "$prof/prefs.js.sfn" || true
|
|
||||||
if cmp -s "$prof/prefs.js" "$prof/prefs.js.sfn"; then rm "$prof/prefs.js.sfn"
|
|
||||||
else cat "$prof/prefs.js.sfn" > "$prof/prefs.js"; rm "$prof/prefs.js.sfn"; echo "firefox: $name: removed from prefs.js:" $keys
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -f "$userJs"
|
|
||||||
fi
|
|
||||||
if [ -n "$want" ]; then ln -s "$want" "$userJs"; fi
|
|
||||||
done
|
|
||||||
'';
|
|
||||||
|
|
||||||
firefox = pkgs.writeShellScript "firefox-launcher" (''
|
|
||||||
profile=()
|
|
||||||
'' + lib.optionalString (cfg.desktopProfile != null) ''
|
|
||||||
if [ "$XDG_CURRENT_DESKTOP" = KDE ]; then
|
|
||||||
# Firefox exits (status 1) if the --profile dir doesn't exist yet.
|
|
||||||
mkdir -p "${profileDir}"
|
|
||||||
profile=(--profile "${profileDir}")
|
|
||||||
fi
|
|
||||||
'' + ''
|
|
||||||
${profileSync} >&2 || true
|
|
||||||
exec /usr/bin/flatpak run --branch=stable --arch=aarch64 --command=firefox \
|
|
||||||
--file-forwarding org.mozilla.firefox "''${profile[@]}" "$@"
|
|
||||||
'');
|
|
||||||
in {
|
in {
|
||||||
imports = [ ./cleanup.nix ];
|
imports = [ ./cleanup.nix ];
|
||||||
|
|
||||||
@@ -158,49 +91,43 @@ in {
|
|||||||
type = lib.types.nullOr lib.types.str;
|
type = lib.types.nullOr lib.types.str;
|
||||||
default = "desktop";
|
default = "desktop";
|
||||||
description = ''
|
description = ''
|
||||||
Profile used in the nested desktop, so both sessions can run Firefox at
|
Profile (directory name under the Flatpak's
|
||||||
once; null = default profile in both.
|
~/.var/app/org.mozilla.firefox/config/mozilla/firefox) used in the
|
||||||
|
nested desktop, so both sessions can run Firefox at once; created on
|
||||||
|
first use, a normal profile with its own browser data. null = the
|
||||||
|
default profile in both sessions.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkMerge [
|
config = lib.mkIf cfg.enable {
|
||||||
{
|
# stable: the branch the launcher runs (the extension point has no
|
||||||
# Always, so disabling removes our user.js links (and old copies).
|
# version, so it takes the app's branch).
|
||||||
home.activation.firefoxProfiles =
|
xdg.dataFile = lib.optionalAttrs (defaultPrefs != { } || desktopFix) {
|
||||||
lib.hm.dag.entryAfter [ "writeBoundary" ] "run ${profileSync}\n";
|
"flatpak/extension/org.mozilla.firefox.systemconfig/aarch64/stable".source = sysconfig;
|
||||||
# The desktop profile's user.js link (steam-frame-nix-cleanup).
|
} // {
|
||||||
steamFrame.cleanup.keep = lib.optional desktopFix "firefox-desktop-userjs=${cfg.desktopProfile}";
|
"applications/org.mozilla.firefox.desktop".text = ''
|
||||||
}
|
[Desktop Entry]
|
||||||
(lib.mkIf cfg.enable {
|
Type=Application
|
||||||
# stable: the branch the launcher runs (the extension point has no
|
Name=Firefox
|
||||||
# version, so it takes the app's branch).
|
GenericName=Web Browser
|
||||||
xdg.dataFile = lib.optionalAttrs (defaultPrefs != { } || desktopFix) {
|
Icon=org.mozilla.firefox
|
||||||
"flatpak/extension/org.mozilla.firefox.systemconfig/aarch64/stable".source = sysconfig;
|
Exec=${firefox} @@u %u @@
|
||||||
} // {
|
StartupWMClass=firefox
|
||||||
"applications/org.mozilla.firefox.desktop".text = ''
|
StartupNotify=true
|
||||||
[Desktop Entry]
|
Terminal=false
|
||||||
Type=Application
|
Categories=Network;WebBrowser;
|
||||||
Name=Firefox
|
MimeType=application/json;application/pdf;application/rdf+xml;application/rss+xml;application/x-xpinstall;application/xhtml+xml;application/xml;audio/flac;audio/ogg;audio/webm;image/avif;image/gif;image/jpeg;image/png;image/svg+xml;image/webp;text/html;text/xml;video/ogg;video/webm;x-scheme-handler/chrome;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/mailto;
|
||||||
GenericName=Web Browser
|
Actions=new-window;new-private-window;
|
||||||
Icon=org.mozilla.firefox
|
|
||||||
Exec=${firefox} @@u %u @@
|
|
||||||
StartupWMClass=firefox
|
|
||||||
StartupNotify=true
|
|
||||||
Terminal=false
|
|
||||||
Categories=Network;WebBrowser;
|
|
||||||
MimeType=application/json;application/pdf;application/rdf+xml;application/rss+xml;application/x-xpinstall;application/xhtml+xml;application/xml;audio/flac;audio/ogg;audio/webm;image/avif;image/gif;image/jpeg;image/png;image/svg+xml;image/webp;text/html;text/xml;video/ogg;video/webm;x-scheme-handler/chrome;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/mailto;
|
|
||||||
Actions=new-window;new-private-window;
|
|
||||||
|
|
||||||
[Desktop Action new-window]
|
[Desktop Action new-window]
|
||||||
Name=New Window
|
Name=New Window
|
||||||
Exec=${firefox} --new-window @@u %u @@
|
Exec=${firefox} --new-window @@u %u @@
|
||||||
|
|
||||||
[Desktop Action new-private-window]
|
[Desktop Action new-private-window]
|
||||||
Name=New Private Window
|
Name=New Private Window
|
||||||
Exec=${firefox} --private-window @@u %u @@
|
Exec=${firefox} --private-window @@u %u @@
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
})
|
};
|
||||||
];
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# Checks of the Firefox launcher's desktop profile user.js (launcher.nix)
|
||||||
|
# against a fake flatpak: the link exists only while Firefox runs, a second
|
||||||
|
# launch that hands over to the running Firefox doesn't remove it, the value
|
||||||
|
# Firefox stored from it leaves prefs.js once the profile is unlocked, and a
|
||||||
|
# user.js of the user's own is never touched.
|
||||||
|
{ pkgs }:
|
||||||
|
let
|
||||||
|
# Fake `flatpak run … org.mozilla.firefox --profile DIR …`: with the
|
||||||
|
# profile locked by another process it "forwards" and returns; otherwise it
|
||||||
|
# holds .parentlock, records user.js and stores the pref like Firefox does,
|
||||||
|
# and runs until $FAKE/release exists.
|
||||||
|
fakeFlatpak = pkgs.writeShellScript "flatpak" ''
|
||||||
|
while [ $# -gt 0 ] && [ "$1" != --profile ]; do shift; done
|
||||||
|
[ $# -gt 0 ] || { echo "default profile" >> $FAKE/log; exit 0; }
|
||||||
|
prof=$2
|
||||||
|
if find /proc/[0-9]*/fd -lname "$prof/.parentlock" -print -quit 2>/dev/null | grep -q .; then
|
||||||
|
echo forwarded >> $FAKE/log; exit 0
|
||||||
|
fi
|
||||||
|
touch "$prof/.parentlock"; exec 9< "$prof/.parentlock"
|
||||||
|
echo "started $(readlink "$prof/user.js" || echo none)" >> $FAKE/log
|
||||||
|
[ -L "$prof/user.js" ] && echo 'user_pref("full-screen-api.ignore-widgets", false);' >> "$prof/prefs.js"
|
||||||
|
while [ ! -e $FAKE/release ]; do sleep 0.1; done
|
||||||
|
exit 3
|
||||||
|
'';
|
||||||
|
launcher = pkgs.callPackage ./launcher.nix {
|
||||||
|
flatpakBin = fakeFlatpak;
|
||||||
|
profileDir = "$HOME/ff/desktop";
|
||||||
|
desktopFix = true;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
pkgs.runCommand "firefox-check" { nativeBuildInputs = [ pkgs.findutils pkgs.gnugrep ]; } ''
|
||||||
|
set -euo pipefail
|
||||||
|
fail() { echo "FAIL: $*" >&2; cat $FAKE/log >&2 || true; exit 1; }
|
||||||
|
export HOME=$PWD/home FAKE=$PWD/fake XDG_CURRENT_DESKTOP=KDE
|
||||||
|
mkdir -p $HOME $FAKE; : > $FAKE/log
|
||||||
|
p=$HOME/ff/desktop
|
||||||
|
|
||||||
|
# first launch: link made, Firefox runs
|
||||||
|
${launcher} https://example.org & first=$!
|
||||||
|
for i in $(seq 100); do grep -q started $FAKE/log && break; sleep 0.1; done
|
||||||
|
grep -qx 'started /app/etc/firefox/steam-frame-nix-desktop-user.js' $FAKE/log || fail "not linked at start"
|
||||||
|
echo 'user_pref("other", 1);' >> $p/prefs.js
|
||||||
|
# second launch: hands over, returns, cleans nothing
|
||||||
|
${launcher} https://example.com
|
||||||
|
grep -qx forwarded $FAKE/log || fail "no forward"
|
||||||
|
[ -L $p/user.js ] || fail "second launch removed the link"
|
||||||
|
# Firefox exits: link and value gone, exit status passed on
|
||||||
|
touch $FAKE/release
|
||||||
|
status=0; wait $first || status=$?
|
||||||
|
[ $status = 3 ] || fail "status $status"
|
||||||
|
[ ! -e $p/user.js ] && [ ! -L $p/user.js ] || fail "link left"
|
||||||
|
[ "$(cat $p/prefs.js)" = 'user_pref("other", 1);' ] || fail "prefs.js: $(cat $p/prefs.js)"
|
||||||
|
|
||||||
|
# a user.js of the user's own: untouched
|
||||||
|
echo 'user_pref("mine", 1);' > $p/user.js
|
||||||
|
echo 'user_pref("full-screen-api.ignore-widgets", false);' >> $p/prefs.js
|
||||||
|
${launcher} || true
|
||||||
|
[ "$(cat $p/user.js)" = 'user_pref("mine", 1);' ] || fail "own user.js changed"
|
||||||
|
grep -q ignore-widgets $p/prefs.js || fail "prefs.js changed with an own user.js"
|
||||||
|
rm $p/user.js
|
||||||
|
|
||||||
|
# Steam session: default profile, no link
|
||||||
|
: > $FAKE/log
|
||||||
|
XDG_CURRENT_DESKTOP=gamescope ${launcher} || true
|
||||||
|
grep -qx 'default profile' $FAKE/log || fail "used --profile in the Steam session"
|
||||||
|
[ ! -e $p/user.js ] || fail "linked in the Steam session"
|
||||||
|
echo ok
|
||||||
|
touch $out
|
||||||
|
''
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# The Firefox Flatpak launcher (firefox.nix). In the nested desktop (KDE) it
|
||||||
|
# uses the desktop profile; with the fullscreen fix it links that profile's
|
||||||
|
# user.js to the sandbox path desktopJs (undoing the fix there) right before
|
||||||
|
# Firefox starts, and once Firefox has exited and the profile is no longer in
|
||||||
|
# use (a second launch that only hands its URL to the running Firefox returns
|
||||||
|
# at once) removes the link and the value Firefox stored from it in
|
||||||
|
# prefs.js. A user.js of the user's own is never touched. After a crash the
|
||||||
|
# next launch or steam-frame-nix-cleanup finishes the removal.
|
||||||
|
{ lib, writeShellScript, coreutils, findutils, gnugrep
|
||||||
|
, flatpakBin ? "/usr/bin/flatpak" # (not `flatpak`: callPackage would pass pkgs.flatpak)
|
||||||
|
, profileDir ? null # shell word, e.g. "$HOME/.var/app/…/desktop"; null: no desktop profile
|
||||||
|
, desktopFix ? false
|
||||||
|
, desktopJs ? "/app/etc/firefox/steam-frame-nix-desktop-user.js"
|
||||||
|
, desktopKeys ? [ "full-screen-api.ignore-widgets" ]
|
||||||
|
}:
|
||||||
|
writeShellScript "firefox-launcher" (''
|
||||||
|
PATH=${lib.makeBinPath [ coreutils findutils gnugrep ]}:$PATH
|
||||||
|
run=(${flatpakBin} run --branch=stable --arch=aarch64 --command=firefox --file-forwarding org.mozilla.firefox)
|
||||||
|
'' + (if profileDir == null then ''
|
||||||
|
exec "''${run[@]}" "$@"
|
||||||
|
'' else ''
|
||||||
|
if [ "$XDG_CURRENT_DESKTOP" != KDE ]; then exec "''${run[@]}" "$@"; fi
|
||||||
|
prof="${profileDir}"
|
||||||
|
# Firefox exits (status 1) if the --profile dir doesn't exist yet.
|
||||||
|
mkdir -p "$prof"
|
||||||
|
'' + lib.optionalString desktopFix ''
|
||||||
|
js=${lib.escapeShellArg desktopJs}
|
||||||
|
u=$prof/user.js
|
||||||
|
# Firefox holds .parentlock open while it uses a profile (the sandbox sees
|
||||||
|
# the profile at the same path).
|
||||||
|
inUse() { find /proc/[0-9]*/fd -lname "$prof/.parentlock" -print -quit 2>/dev/null | grep -q .; }
|
||||||
|
ours() { [ -L "$u" ] && [ "$(readlink "$u")" = "$js" ]; }
|
||||||
|
sfn_unlink() {
|
||||||
|
ours && ! inUse || return 0
|
||||||
|
if [ -f "$prof/prefs.js" ] && grep -qF -f <(printf '%s\n' ${lib.escapeShellArgs (map (k: "user_pref(${builtins.toJSON k},") desktopKeys)}) "$prof/prefs.js"; then
|
||||||
|
grep -vF -f <(printf '%s\n' ${lib.escapeShellArgs (map (k: "user_pref(${builtins.toJSON k},") desktopKeys)}) "$prof/prefs.js" > "$prof/prefs.js.sfn" || true
|
||||||
|
cat "$prof/prefs.js.sfn" > "$prof/prefs.js"
|
||||||
|
rm -f "$prof/prefs.js.sfn"
|
||||||
|
fi
|
||||||
|
rm -f "$u"
|
||||||
|
}
|
||||||
|
if [ -e "$u" ] || [ -L "$u" ]; then
|
||||||
|
ours || echo "firefox: $u is not steam-frame-nix's; fullscreen stays inside the window in this profile" >&2
|
||||||
|
else
|
||||||
|
ln -s "$js" "$u"
|
||||||
|
fi
|
||||||
|
"''${run[@]}" --profile "$prof" "$@"
|
||||||
|
status=$?
|
||||||
|
sfn_unlink
|
||||||
|
exit $status
|
||||||
|
'' + lib.optionalString (!desktopFix) ''
|
||||||
|
exec "''${run[@]}" --profile "$prof" "$@"
|
||||||
|
''))
|
||||||
Reference in new issue
Block a user