763e06c127
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
95 lines
3.4 KiB
Bash
95 lines
3.4 KiB
Bash
#!/usr/bin/env bash
|
|
# focus_cdp_tab_window — trae al frente la pestaña + la ventana del SO de un Chrome con CDP
|
|
#
|
|
# Handoff humano de captcha: activa la tab del captcha (opcional, via CDP) y levanta
|
|
# la ventana X11 del proceso browser principal de ese puerto para que un humano resuelva
|
|
# el captcha a mano. Best-effort y robusto: cada paso continua aunque uno falle.
|
|
|
|
focus_cdp_tab_window() {
|
|
set -uo pipefail
|
|
|
|
local port="${1:-}"
|
|
local target_id="${2:-}"
|
|
|
|
# 1. Validacion de entorno y dependencias.
|
|
if [[ -z "$port" ]]; then
|
|
echo "focus_cdp_tab_window: falta el puerto CDP (uso: focus_cdp_tab_window <port> [target_id])" >&2
|
|
return 2
|
|
fi
|
|
if [[ -z "${DISPLAY:-}" ]]; then
|
|
echo "focus_cdp_tab_window: sin entorno grafico (DISPLAY vacio)" >&2
|
|
return 3
|
|
fi
|
|
if ! command -v wmctrl >/dev/null 2>&1 || ! command -v xdotool >/dev/null 2>&1; then
|
|
echo "focus_cdp_tab_window: falta wmctrl/xdotool" >&2
|
|
return 4
|
|
fi
|
|
|
|
# 2. Activar la tab del captcha dentro del browser (best-effort, no aborta).
|
|
if [[ -n "$target_id" ]]; then
|
|
curl -sf "http://127.0.0.1:${port}/json/activate/${target_id}" >/dev/null 2>&1 || true
|
|
fi
|
|
|
|
# 3. Encontrar el PID del proceso BROWSER principal de ese puerto.
|
|
# De las lineas que matchean el flag de debugging, el browser process es el que
|
|
# NO lleva --type= (los renderers/gpu/utility/zygote son procesos hijos).
|
|
local browser_pid=""
|
|
local line
|
|
while IFS= read -r line; do
|
|
[[ -z "$line" ]] && continue
|
|
if [[ "$line" == *"--type="* ]]; then
|
|
continue
|
|
fi
|
|
# pgrep -af antepone el PID seguido de la cmdline.
|
|
browser_pid="${line%% *}"
|
|
break
|
|
done < <(pgrep -af -- "remote-debugging-port=${port}" 2>/dev/null)
|
|
|
|
if [[ -z "$browser_pid" ]]; then
|
|
echo "focus_cdp_tab_window: no hay chromium en el puerto ${port}" >&2
|
|
return 5
|
|
fi
|
|
|
|
# 4. Resolver el window id top-level.
|
|
# Primero por wmctrl -lp (columna 3 = PID). Fallback xdotool si el main no expone _NET_WM_PID.
|
|
local wid=""
|
|
while IFS= read -r line; do
|
|
[[ -z "$line" ]] && continue
|
|
# Formato: <wid> <desktop> <pid> <host> <title...>
|
|
local w_id w_pid
|
|
w_id="$(awk '{print $1}' <<<"$line")"
|
|
w_pid="$(awk '{print $3}' <<<"$line")"
|
|
if [[ "$w_pid" == "$browser_pid" ]]; then
|
|
wid="$w_id"
|
|
break
|
|
fi
|
|
done < <(wmctrl -lp 2>/dev/null)
|
|
|
|
if [[ -z "$wid" ]]; then
|
|
wid="$(xdotool search --pid "$browser_pid" --onlyvisible 2>/dev/null | head -n1)"
|
|
fi
|
|
|
|
if [[ -z "$wid" ]]; then
|
|
echo "focus_cdp_tab_window: no se encontro ventana top-level para pid ${browser_pid} (puerto ${port})" >&2
|
|
return 6
|
|
fi
|
|
|
|
# 5. Traer al frente con REINTENTO (xfwm de XFCE pisa el primer activate/raise).
|
|
# Espera no bloqueante con read -t en vez de sleep.
|
|
local attempt
|
|
for attempt in 1 2; do
|
|
xdotool windowactivate "$wid" >/dev/null 2>&1 || true
|
|
read -r -t 0.2 _ < /dev/zero 2>/dev/null || true
|
|
xdotool windowraise "$wid" >/dev/null 2>&1 || true
|
|
done
|
|
|
|
# 6. Salida legible y JSON-parseable simple.
|
|
echo "focus_cdp_tab_window: focused win=${wid} pid=${browser_pid} port=${port} tab=${target_id:--}"
|
|
return 0
|
|
}
|
|
|
|
# Permitir ejecucion directa: focus_cdp_tab_window <port> [target_id]
|
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
focus_cdp_tab_window "$@"
|
|
fi
|