A reboot kills Chromium rather than closing it, so it writes "exit_type":"Crashed" into its profile. On the next boot it came up with a restore prompt and a tab stuck for ever on a blank "Loading..." page - navigation never committed, navigator.serviceWorker was still undefined, nothing on screen. On a device with a monitor and no keyboard that is permanent, and the backend was healthy throughout: / answered in 5 ms and /api/library returned 812 kB the whole time. --disable-session-crashed-bubble hides the prompt but not the state behind it, and here the prompt showed anyway. .xinitrc now rewrites exit_type and exited_cleanly before launching, which is the usual remedy for a kiosk that gets powered off rather than shut down, and adds --hide-crash-restore-bubble (the current name for the flag). Verified by rebooting and leaving it alone: the page comes up on its own with its title and its content. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
79 lines
3.7 KiB
Django/Jinja
79 lines
3.7 KiB
Django/Jinja
#!/bin/sh
|
|
# Managed by ansible (pi_kiosk role).
|
|
#
|
|
# Openbox is here for one concrete reason: a browser asks to be full-screen over EWMH,
|
|
# and only a window manager answers that request. With no WM running, --kiosk was
|
|
# silently ignored and the browser fell back to its default window size in the
|
|
# top-left corner of a 1920x1080 screen - black bands down the right edge and along
|
|
# the bottom, looking exactly like an overscan problem and not being one.
|
|
|
|
xset s off
|
|
xset -dpms
|
|
xset s noblank
|
|
|
|
{% if pi_kiosk_browser == 'chromium' %}
|
|
BROWSER=chromium
|
|
|
|
# The first four flags are the difference between compositing on the GPU and
|
|
# rasterizing every frame on the CPU:
|
|
# --use-gl=egl reach V3D through EGL rather than desktop GLX
|
|
# --enable-gpu-rasterization rasterize layer content on the GPU
|
|
# --ignore-gpu-blocklist Chromium's blocklist does not know this driver, and
|
|
# without this it quietly falls back to software
|
|
# --enable-zero-copy hand tiles to the compositor without a CPU copy
|
|
# The rest are about a machine nobody sits in front of: no update checks, no crash
|
|
# bubbles, no keyring prompt, no first-run wizard, no "restore pages?" after a power
|
|
# cut. Anything policy-shaped rather than flag-shaped is in
|
|
# /etc/chromium/policies/managed/.
|
|
BROWSER_ARGS="--use-gl=egl --enable-gpu-rasterization --ignore-gpu-blocklist --enable-zero-copy"
|
|
BROWSER_ARGS="$BROWSER_ARGS --noerrdialogs --disable-infobars --no-first-run"
|
|
BROWSER_ARGS="$BROWSER_ARGS --no-default-browser-check --disable-session-crashed-bubble"
|
|
BROWSER_ARGS="$BROWSER_ARGS --password-store=basic --check-for-update-interval=31536000"
|
|
BROWSER_ARGS="$BROWSER_ARGS --hide-crash-restore-bubble"
|
|
|
|
# Chromium records in its profile how it last exited. A reboot kills it rather than
|
|
# closing it, so that record says "Crashed", and the next start comes up with a restore
|
|
# prompt and a tab stuck on a blank "Loading..." page - which, on a device with no
|
|
# keyboard in front of it, it never leaves. The flags above hide the prompt but do not
|
|
# clear the state behind it; rewriting the two keys before launch does, and is the
|
|
# standard remedy for a kiosk that is powered off rather than shut down.
|
|
PREFS="$HOME/.config/chromium/Default/Preferences"
|
|
if [ -f "$PREFS" ]; then
|
|
sed -i 's/"exit_type":"[^"]*"/"exit_type":"Normal"/; s/"exited_cleanly":false/"exited_cleanly":true/' "$PREFS"
|
|
fi
|
|
{% if pi_kiosk_mode == 'debug' %}
|
|
# Debug mode only. Binds to 127.0.0.1, so it is reachable over an ssh tunnel and from
|
|
# nowhere else. Lets the page be driven and measured from a shell - `curl
|
|
# localhost:9222/json` lists the tabs - instead of by poking XTEST key events at a
|
|
# window and hoping they land.
|
|
BROWSER_ARGS="$BROWSER_ARGS --remote-debugging-port=9222"
|
|
{% endif %}
|
|
{% else %}
|
|
BROWSER=firefox
|
|
BROWSER_ARGS=""
|
|
{% endif %}
|
|
|
|
{% if pi_kiosk_mode == 'debug' %}
|
|
# Debug session. The browser is an ordinary window with its chrome (so devtools and the
|
|
# URL bar are reachable) and is *not* relaunched when it exits - quitting it should
|
|
# leave a usable desktop, not fight you for the screen. Openbox is the session leader
|
|
# instead: when it exits (root menu -> Exit) the X session ends and .bash_profile
|
|
# starts a fresh one. Right-click the desktop for a terminal.
|
|
# shellcheck disable=SC2086 # BROWSER_ARGS is a word list on purpose
|
|
$BROWSER $BROWSER_ARGS "{{ pi_kiosk_url }}" &
|
|
|
|
exec openbox
|
|
{% else %}
|
|
openbox &
|
|
|
|
unclutter -idle 0.5 -root &
|
|
|
|
# The loop is what takes the place of a WM's "keep something on screen" job: Openbox
|
|
# manages the window, but nothing else would bring the browser back if it died.
|
|
while true; do
|
|
# shellcheck disable=SC2086
|
|
$BROWSER --kiosk $BROWSER_ARGS "{{ pi_kiosk_url }}"
|
|
sleep 2
|
|
done
|
|
{% endif %}
|