--- name: chrome_load_extensions kind: function lang: bash domain: browser version: "1.0.0" purity: impure signature: "chrome_load_extensions [--port N] [--profile DIR] --ext PATH [--ext PATH ...] [--proxy URL] [--url URL]" description: "Lanza Chrome con extensiones unpacked via --load-extension (WSL2→Windows chrome.exe, paths traducidos, join sin echo, setsid anti-exit-144). OJO: --load-extension SOLO funciona en Chrome for Testing/Chromium/Dev. En Chrome STABLE 138+ esta DESACTIVADO (feature DisableLoadExtensionCommandLineSwitch + bloqueo duro en 148) y carga 0 extensiones aunque el cmdline sea correcto. Para Chrome stable usar install via Web Store (1-clic, persiste en perfil) o enterprise policy ExtensionInstallForcelist (requiere HKLM/HKCU Policies escribible — denegado en maquinas gestionadas)." tags: [chrome, cdp, browser, extensions, wsl2, navegator] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: [] tested: false tests: [] test_file_path: "" params: - name: "--port N" desc: "Puerto de remote debugging CDP. Default: 9222." - name: "--profile DIR" desc: "Chrome user-data-dir. Acepta ruta Windows (C:\\...) o ruta WSL/Linux (se traduce via wslpath -w). Default: C:\\Users\\\\AppData\\Local\\fn-chrome-cdp-profile (WSL2) o /tmp/fn-chrome-cdp-profile (Linux nativo)." - name: "--ext PATH" desc: "Ruta a un directorio de extensión unpacked. Repetible. Acepta ruta Windows (se pasa intacta) o ruta WSL/Linux (se traduce via wslpath -w). Obligatorio al menos uno." - name: "--proxy URL" desc: "Proxy opcional, ej. http://127.0.0.1:8889. Agrega --proxy-server=URL a Chrome." - name: "--url URL" desc: "URL inicial opcional para abrir con --new-window." output: "PID del proceso Chrome lanzado (stdout). Mensajes de estado en stderr. CDP listo en 127.0.0.1:." file_path: "bash/functions/browser/chrome_load_extensions.sh" --- ## Ejemplo ```bash source bash/functions/browser/chrome_load_extensions.sh chrome_load_extensions \ --port 9222 \ --profile 'C:\Users\lucas\AppData\Local\fn-chrome-cdp-profile' \ --ext 'C:\Users\lucas\hls-dl-ext' \ --ext 'C:\Users\lucas\ubol' \ --proxy http://127.0.0.1:8889 \ --url https://www.gnularetro.cc/ ``` Sin proxy ni URL, sólo extensiones: ```bash source bash/functions/browser/chrome_load_extensions.sh pid=$(chrome_load_extensions \ --ext '/home/lucas/dev/hls-dl-ext' \ --ext '/home/lucas/dev/ubol') # Paths WSL traducidos automáticamente a Windows. # CDP listo en 127.0.0.1:9222. echo "Chrome PID: $pid" ``` ## Cuando usarla Cuando necesites Chrome CDP con extensiones unpacked cargadas (HLS downloader, uBlock Origin, extensiones en desarrollo) y `chrome_launch_go_browser` no sirve porque hardcodea `--disable-extensions`. WSL2→Windows. Ideal para sesiones de navegator con proxy + extensión activa. ## Gotchas - **MUERTO en Chrome STABLE 138+ (validado 2026-05-30, Chrome 148)**: `--load-extension` NO carga nada en el canal stable, ni con `--disable-extensions-except` ni con `--disable-features=DisableLoadExtensionCommandLineSwitch`. `chrome://version` muestra el flag correcto pero `chrome://extensions` sale vacío. Google lo bloqueó duro en stable. La función SOLO sirve en **Chrome for Testing / Chromium / Dev/Canary**, donde el switch sigue activo. Para stable: ver opciones abajo. - **Instalar en Chrome STABLE (las que SÍ funcionan)**: 1. **Web Store 1-clic** — abre la página del store en el perfil CDP, el humano da "Añadir a Chrome". Persiste en el perfil para siempre (futuros lanzamientos ya con la extensión, sin flags). El popup de confirmación es UI del navegador (no DOM) → NO es CDP-clickable, requiere gesto humano. Único método no-admin que persiste por-perfil. 2. **Enterprise policy** `ExtensionInstallForcelist` (HKCU/HKLM `\Software\Policies\Google\Chrome`) — force-install sin clic desde el store, browser-wide. El key `Policies\Google\Chrome` puede dar "Access denied" al escribir (visto 2026-05-30 incluso en máquina personal vía reg.exe/PowerShell desde WSL — Chrome/Windows protege el subárbol Policies). Si funciona, requiere relanzar Chrome para que descargue del store. Método global (afecta todos los perfiles). 3. Extensiones **unpacked custom** (no en store, ej. un HLS downloader propio) en stable: no hay vía no-admin. Empaquetar a CRX + self-host `update_url` + policy, o usar Chrome for Testing. A menudo innecesario si la lógica vive fuera (ej. `grab_stream.py` descarga sin extensión). - **Combo flags (solo Chrome for Testing/dev)**: requiere AMBOS `--load-extension=p1,p2` Y `--disable-extensions-except=p1,p2` juntos + `--disable-features=DisableLoadExtensionCommandLineSwitch`. **NUNCA `--disable-extensions`** (desactiva todo). - **join sin `echo`**: rutas Windows `C:\Users\...` tienen `\U`; el `echo` de zsh (o sh con xpg_echo) lo interpreta como escape unicode y trunca la ruta a `C:`. La función usa acumulador `+=`, no `echo`. Verificable en `chrome://version` (debe verse el path completo, no `--load-extension=C:`). - **exit 144 en Bash tool**: si el proceso Chrome retiene el pipe stdout, la herramienta devuelve exit 144. Esta función lanza con `setsid ... log 2>&1 &` + `disown` para desacoplar completamente. El log queda en `/tmp/chrome_ext_.log`. - **WSL2: traducir paths con `wslpath -w`**: los paths de `--ext` y `--profile` que sean rutas Linux se traducen automáticamente. Las rutas Windows (`C:\...`) se pasan intactas. `wslpath` debe estar disponible (estándar en WSL2 desde Windows 10 1903+). - **Perfil ya abierto**: si Chrome ya tiene ese perfil abierto, relanzar añade una ventana extra a la misma instancia. La función detecta si CDP ya responde en el puerto y avisa por stderr, pero procede igualmente. - **Web Store vs unpacked**: instalar extensiones desde la Web Store (un clic) persiste en el perfil sin necesidad de flags y sobrevive reinicios. Esta función es para extensiones unpacked en desarrollo o que no están en la Web Store. Si usas ambas, los flags no interfieren con las instaladas del store. - **zsh globbing**: `--remote-allow-origins=*` está dentro de comillas en la función, no se expande. Si lo pasas desde la línea de comandos, entrecomillarlo. - **Proxy + extensión**: si usas proxy para captura de tráfico (Burp, mitmproxy, gost), el proxy se aplica a toda la sesión Chrome, incluyendo el tráfico de las extensiones.