Files
kestrove-desktop/native-messaging/install.sh
T
samiandClaude Opus 5.5 95ce03ba06
ci / build (ubuntu-22.04) (push) Canceled after 0s
ci / build (windows-2025) (push) Canceled after 0s
ci / deny (push) Canceled after 0s
Trust the Chrome Web Store extension (pmhfoafjoogobhfadaicklhkldgnafmk)
The store build has its own id, so the native-messaging manifest refused it
and the extension reported the app as not running. Chrome now allows the
store id and the unpacked development id, in the NSIS hook and in both
install scripts; --chrome-id / -ChromeId take a list.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 07:21:09 +04:00

111 lines
4.4 KiB
Bash
Executable File

#!/bin/sh
# Registers the Kestrove native-messaging host with the browsers of the current user (Linux, macOS).
# Windows: install.ps1.
#
# install.sh [--nmh /path/to/kestrove-nmh] [--chrome-id ID[,ID…]] [--firefox-id ID]
# [--browsers chrome,chromium,edge,brave,firefox] [--user-data-dir DIR] [--uninstall]
#
# With neither --browsers nor --user-data-dir it installs for every browser whose profile directory exists.
# --user-data-dir adds a Chromium-style profile dir started with --user-data-dir (Chromium then
# looks for NativeMessagingHosts/ inside it), e.g. for tests.
# allowed_origins / allowed_extensions pin the host to our extension ids (docs/04 A8).
set -eu
HOST=app.kestrove.nmh
HERE=$(cd "$(dirname "$0")" && pwd)
NMH=""
# Chrome: the Chrome Web Store build, then the unpacked development build (pinned by the manifest key in
# kestrove-browser/scripts/build.mjs).
CHROME_IDS="pmhfoafjoogobhfadaicklhkldgnafmk kogapfibnnpeapfcjkkpgjddbhnjfein"
FIREFOX_ID=[email protected]
BROWSERS=""
USER_DATA_DIR=""
UNINSTALL=0
die() { echo "install.sh: $*" >&2; exit 1; }
while [ $# -gt 0 ]; do
case "$1" in
--nmh) NMH=$2; shift 2 ;;
--chrome-id) CHROME_IDS=$(echo "$2" | tr ',' ' '); shift 2 ;;
--firefox-id) FIREFOX_ID=$2; shift 2 ;;
--browsers) BROWSERS=$(echo "$2" | tr ',' ' '); shift 2 ;;
--user-data-dir) USER_DATA_DIR=$2; shift 2 ;;
--uninstall) UNINSTALL=1; shift ;;
-h|--help) sed -n '2,13p' "$0"; exit 0 ;;
*) die "unknown option $1" ;;
esac
done
for id in $CHROME_IDS; do echo "$id" | grep -Eq '^[a-p]{32}$' || die "--chrome-id must be 32 letters a-p"; done
# "chrome-extension://a/", "chrome-extension://b/" (the template supplies the outer quotes).
CHROME_ORIGINS=$(for id in $CHROME_IDS; do printf '%s' "${sep-}chrome-extension://$id/"; sep='", "'; done)
echo "$FIREFOX_ID" | grep -Eq '^[A-Za-z0-9._@{}-]+$' || die "bad --firefox-id"
if [ "$UNINSTALL" = 0 ]; then
if [ -z "$NMH" ]; then
# Next to this script (installed layout), else the cargo build output (development).
for c in "$HERE/kestrove-nmh" "$HERE/../src-tauri/target/release/kestrove-nmh" "$HERE/../src-tauri/target/debug/kestrove-nmh"; do
[ -x "$c" ] && NMH=$c && break
done
fi
[ -n "$NMH" ] || die "kestrove-nmh not found; pass --nmh"
[ -x "$NMH" ] || die "$NMH is not executable"
NMH=$(cd "$(dirname "$NMH")" && pwd)/$(basename "$NMH")
case "$NMH" in *[\"\\\|\&]*) die "the host path may not contain quotes, backslashes, | or &" ;; esac
fi
case "$(uname -s)" in
Darwin)
# The Kestrove Mac app registers its own host on launch; this points the browsers at a desktop dev build.
[ "$UNINSTALL" = 1 ] || echo "note: on macOS the Kestrove app registers itself; re-open it to switch back" >&2
BASE="$HOME/Library/Application Support"
dir_chrome="$BASE/Google/Chrome"
dir_chromium="$BASE/Chromium"
dir_edge="$BASE/Microsoft Edge"
dir_brave="$BASE/BraveSoftware/Brave-Browser"
dir_firefox="$BASE/Mozilla"
ff_sub=NativeMessagingHosts
;;
Linux)
CFG=${XDG_CONFIG_HOME:-$HOME/.config}
dir_chrome="$CFG/google-chrome"
dir_chromium="$CFG/chromium"
dir_edge="$CFG/microsoft-edge"
dir_brave="$CFG/BraveSoftware/Brave-Browser"
dir_firefox="$HOME/.mozilla"
ff_sub=native-messaging-hosts
;;
*) die "unsupported OS $(uname -s); on Windows use install.ps1" ;;
esac
# Auto-detect only when nothing was named: a test run with --user-data-dir must not touch real profiles.
[ -n "$BROWSERS$USER_DATA_DIR" ] || for b in chrome chromium edge brave firefox; do
eval "d=\$dir_$b"
[ -d "$d" ] && BROWSERS="$BROWSERS $b"
done
render() { # template → stdout
sed -e "s|__NMH_PATH__|$NMH|" -e "s|chrome-extension://__CHROME_EXTENSION_ID__/|$CHROME_ORIGINS|" -e "s|__FIREFOX_EXTENSION_ID__|$FIREFOX_ID|" "$HERE/$HOST.$1.json"
}
place() { # flavor dir
if [ "$UNINSTALL" = 1 ]; then
rm -f "$2/$HOST.json" && echo "removed $2/$HOST.json"
else
mkdir -p "$2"
render "$1" > "$2/$HOST.json.tmp" && chmod 644 "$2/$HOST.json.tmp" && mv "$2/$HOST.json.tmp" "$2/$HOST.json"
echo "installed $2/$HOST.json"
fi
}
for b in $BROWSERS; do
case "$b" in
chrome|chromium|edge|brave) eval "d=\$dir_$b"; place chrome "$d/NativeMessagingHosts" ;;
firefox) place firefox "$dir_firefox/$ff_sub" ;;
*) die "unknown browser $b" ;;
esac
done
[ -z "$USER_DATA_DIR" ] || place chrome "$USER_DATA_DIR/NativeMessagingHosts"
[ -n "$BROWSERS$USER_DATA_DIR" ] || echo "no supported browser profile found (use --browsers)"