#!/usr/bin/env bash # install_chromium_proxy_extension — instala una extension desempaquetada de # Chromium en TODOS los perfiles del usuario, de forma persistente, escribiendo # un fragmento en /etc/chromium.d/ que el wrapper de Chromium carga en cada # arranque. # # Por que /etc/chromium.d en vez de managed policy con .crx force_installed: # el wrapper de Chromium de Debian/Ubuntu (xtradeb y derivados), cuando NO se # pasa --enable-remote-extensions, anade --disable-extensions-except= y --disable-background-networking. Eso deshabilita # cualquier extension force_installed por policy y bloquea su update check. La # via fiable es habilitar --enable-remote-extensions y cargar la extension # desempaquetada con --load-extension, ambos inyectados de forma global desde # /etc/chromium.d/, que el wrapper hace `source` en cada lanzamiento. install_chromium_proxy_extension() { local ext_dir="" local name="web_proxy_ext" local stable_dir="$HOME/.web_proxy/extension" local chromiumd="/etc/chromium.d" local uninstall="no" # Permite sudo no interactivo via SUDO_ASKPASS (sudo -A) cuando se ejecuta # sin terminal (agentes, CI). Con terminal interactivo usa sudo normal. local SUDO="sudo" [[ -n "${SUDO_ASKPASS:-}" ]] && SUDO="sudo -A" while [[ $# -gt 0 ]]; do case "$1" in --ext-dir) ext_dir="$2"; shift 2 ;; --name) name="$2"; shift 2 ;; --stable-dir) stable_dir="$2"; shift 2 ;; --uninstall) uninstall="yes"; shift ;; *) echo "ERROR: argumento desconocido: $1" >&2; return 1 ;; esac done if [[ ! -d "$chromiumd" ]]; then echo "ERROR: $chromiumd no existe. Este Chromium no usa el wrapper con /etc/chromium.d." >&2 echo " Comprueba 'head -1 \$(command -v chromium)'; si no es un wrapper shell, usa otra via." >&2 return 1 fi # Desinstalacion: quitar el fragmento global y la copia estable. if [[ "$uninstall" == "yes" ]]; then $SUDO rm -f "${chromiumd}/${name}" || { echo "ERROR: no se pudo eliminar ${chromiumd}/${name} (requiere sudo)." >&2 return 1 } rm -rf "$stable_dir" printf '{"uninstalled": true, "name": "%s"}\n' "$name" return 0 fi # Instalacion: validar la extension de origen. if [[ -z "$ext_dir" || ! -f "${ext_dir}/manifest.json" ]]; then echo "ERROR: --ext-dir debe apuntar a un directorio con manifest.json." >&2 return 1 fi # Copiar la extension a una ubicacion estable, independiente del repo, para # que --load-extension no se rompa si el repo se mueve o se limpia. mkdir -p "$stable_dir" || { echo "ERROR: no se pudo crear $stable_dir." >&2 return 1 } # Vaciar destino y copiar el contenido del origen. rm -rf "${stable_dir:?}/"* 2>/dev/null cp -r "${ext_dir}/." "$stable_dir/" || { echo "ERROR: no se pudo copiar la extension a $stable_dir." >&2 return 1 } # Escribir el fragmento que el wrapper carga en cada arranque. Se hace via # archivo temporal + sudo cp para no exponer el contenido por una tuberia. local tmp tmp="$(mktemp)" printf 'export CHROMIUM_FLAGS="$CHROMIUM_FLAGS --enable-remote-extensions --load-extension=%s"\n' "$stable_dir" > "$tmp" if ! $SUDO cp "$tmp" "${chromiumd}/${name}"; then rm -f "$tmp" echo "ERROR: no se pudo escribir ${chromiumd}/${name} (requiere sudo)." >&2 return 1 fi $SUDO chmod 0644 "${chromiumd}/${name}" 2>/dev/null rm -f "$tmp" # ID de extension desempaquetada (deterministico: sha256 del path estable). local ext_id ext_id="$(python3 - "$stable_dir" <<'PY' 2>/dev/null import hashlib, sys h = hashlib.sha256(sys.argv[1].encode()).hexdigest()[:32] print(''.join(chr(ord('a') + int(c, 16)) for c in h)) PY )" printf '{"installed": true, "name": "%s", "stable_dir": "%s", "chromiumd": "%s/%s", "ext_id": "%s"}\n' \ "$name" "$stable_dir" "$chromiumd" "$name" "$ext_id" } # Ejecutar si se llama directamente (fn run / bash ) if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then install_chromium_proxy_extension "$@" fi