#!/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 [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: 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 [target_id] if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then focus_cdp_tab_window "$@" fi