180 lines
4.8 KiB
Bash
180 lines
4.8 KiB
Bash
#!/bin/sh
|
|
set -eu
|
|
|
|
family="${1:-chromium}"
|
|
start_url="${NEKO_START_URL:-about:blank}"
|
|
arch="$(uname -m 2>/dev/null || echo unknown)"
|
|
|
|
prune_path() {
|
|
target="${1:-}"
|
|
[ -n "$target" ] || return 0
|
|
[ -e "$target" ] || return 0
|
|
rm -rf "$target"
|
|
}
|
|
|
|
ensure_profile_preferences() {
|
|
if ! command -v python3 >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
mkdir -p "$profile_dir/Default"
|
|
PROFILE_DIR="$profile_dir" python3 - <<'PY'
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
|
|
profile_dir = Path(os.environ["PROFILE_DIR"])
|
|
|
|
def load_json(path: Path) -> dict:
|
|
if path.exists():
|
|
try:
|
|
return json.loads(path.read_text(encoding="utf-8"))
|
|
except Exception:
|
|
return {}
|
|
return {}
|
|
|
|
def save_json(path: Path, data: dict) -> None:
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(
|
|
json.dumps(data, ensure_ascii=False, separators=(",", ":")),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
for relative_path in ("Default/Preferences", "Local State"):
|
|
path = profile_dir / relative_path
|
|
data = load_json(path)
|
|
extensions = data.setdefault("extensions", {})
|
|
ui = extensions.setdefault("ui", {})
|
|
ui["developer_mode"] = True
|
|
profile = data.setdefault("profile", {})
|
|
profile["exit_type"] = "Normal"
|
|
save_json(path, data)
|
|
PY
|
|
}
|
|
|
|
find_bin() {
|
|
if [ "$family" = "google-chrome" ]; then
|
|
command -v google-chrome 2>/dev/null || command -v google-chrome-stable 2>/dev/null || true
|
|
else
|
|
command -v chromium 2>/dev/null || command -v chromium-browser 2>/dev/null || true
|
|
fi
|
|
}
|
|
|
|
browser_bin="$(find_bin)"
|
|
if [ -z "$browser_bin" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
profile_dir="/home/neko/.config/chromium"
|
|
if [ "$family" = "google-chrome" ]; then
|
|
profile_dir="/home/neko/.config/google-chrome"
|
|
fi
|
|
|
|
render_mode="${NEKO_BROWSER_RENDER_MODE:-auto}"
|
|
render_flags="--disable-gpu --use-gl=swiftshader --enable-unsafe-swiftshader"
|
|
case "$render_mode" in
|
|
auto)
|
|
case "$arch:$family" in
|
|
x86_64:google-chrome|amd64:google-chrome)
|
|
render_flags="--disable-gpu --disable-software-rasterizer --disable-features=UseSkiaRenderer"
|
|
;;
|
|
esac
|
|
;;
|
|
gpu)
|
|
render_flags=""
|
|
;;
|
|
legacy|x11|disable-gpu)
|
|
render_flags="--disable-gpu --disable-software-rasterizer --disable-features=UseSkiaRenderer"
|
|
;;
|
|
software|swiftshader)
|
|
render_flags="--disable-gpu --use-gl=swiftshader --enable-unsafe-swiftshader --disable-features=UseSkiaRenderer"
|
|
;;
|
|
esac
|
|
|
|
mkdir -p "$profile_dir"
|
|
prune_path "$profile_dir/SingletonCookie"
|
|
prune_path "$profile_dir/SingletonLock"
|
|
prune_path "$profile_dir/SingletonSocket"
|
|
prune_path "$profile_dir/SingletonStartupLock"
|
|
prune_path "$profile_dir/BrowserMetrics"
|
|
prune_path "$profile_dir/Crash Reports"
|
|
prune_path "$profile_dir/Crashpad"
|
|
prune_path "$profile_dir/ShaderCache"
|
|
prune_path "$profile_dir/GrShaderCache"
|
|
prune_path "$profile_dir/GraphiteDawnCache"
|
|
prune_path "$profile_dir/Default/Cache"
|
|
prune_path "$profile_dir/Default/Code Cache"
|
|
prune_path "$profile_dir/Default/GPUCache"
|
|
prune_path "$profile_dir/Default/DawnGraphiteCache"
|
|
prune_path "$profile_dir/Default/DawnWebGPUCache"
|
|
ensure_profile_preferences
|
|
|
|
browser_class="google-chrome"
|
|
if [ "$family" != "google-chrome" ]; then
|
|
browser_class="chromium"
|
|
fi
|
|
|
|
launch_browser() {
|
|
"$browser_bin" \
|
|
${render_flags} \
|
|
--window-position=0,0 \
|
|
--display="${DISPLAY:?DISPLAY is required}" \
|
|
--remote-debugging-address=127.0.0.1 \
|
|
--remote-debugging-port=9222 \
|
|
--user-data-dir="$profile_dir" \
|
|
--password-store=basic \
|
|
--no-first-run \
|
|
--new-window \
|
|
--start-maximized \
|
|
--force-dark-mode \
|
|
--disable-background-mode \
|
|
--disable-dev-shm-usage \
|
|
--disable-background-networking \
|
|
--disable-breakpad \
|
|
--disable-default-apps \
|
|
--disable-sync \
|
|
--disable-translate \
|
|
--metrics-recording-only \
|
|
--no-default-browser-check \
|
|
--no-first-run \
|
|
"$start_url" &
|
|
browser_pid=$!
|
|
}
|
|
|
|
visible_window_count() {
|
|
if ! command -v xdotool >/dev/null 2>&1; then
|
|
return 1
|
|
fi
|
|
DISPLAY="${DISPLAY:?DISPLAY is required}" xdotool search --onlyvisible --class "$browser_class" 2>/dev/null | wc -l | tr -d ' '
|
|
}
|
|
|
|
launch_browser
|
|
|
|
seen_window=0
|
|
startup_misses=0
|
|
closed_misses=0
|
|
while kill -0 "$browser_pid" 2>/dev/null; do
|
|
window_count="$(visible_window_count || true)"
|
|
if [ -n "${window_count:-}" ] && [ "$window_count" -gt 0 ] 2>/dev/null; then
|
|
seen_window=1
|
|
startup_misses=0
|
|
closed_misses=0
|
|
else
|
|
if [ "$seen_window" -eq 0 ]; then
|
|
startup_misses=$((startup_misses + 1))
|
|
if [ "$startup_misses" -ge 15 ]; then
|
|
kill -TERM "$browser_pid" 2>/dev/null || true
|
|
break
|
|
fi
|
|
else
|
|
closed_misses=$((closed_misses + 1))
|
|
if [ "$closed_misses" -ge 3 ]; then
|
|
kill -TERM "$browser_pid" 2>/dev/null || true
|
|
break
|
|
fi
|
|
fi
|
|
fi
|
|
sleep 2
|
|
done
|
|
|
|
wait "$browser_pid"
|