763e06c127
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
67 lines
2.2 KiB
Go
67 lines
2.2 KiB
Go
package browser
|
|
|
|
import "fmt"
|
|
|
|
// CdpNewTabBackground abre una pestaña nueva via Target.createTarget con el
|
|
// parametro "background": true, de forma que la pestaña se crea SIN activarse y
|
|
// SIN elevar la ventana del navegador (no roba el foco del WM).
|
|
//
|
|
// Es el drop-in sin-foco de CdpNewTab: misma firma, mismo CdpTab de retorno.
|
|
// La diferencia tecnica es el mecanismo:
|
|
// - CdpNewTab usa el endpoint HTTP PUT /json/new, que NO admite background y
|
|
// por tanto SIEMPRE eleva la ventana (roba foco al usuario).
|
|
// - Aqui usamos el comando CDP browser-level Target.createTarget con
|
|
// "background": true, que en Linux/Chromium crea la pestaña en segundo plano.
|
|
//
|
|
// host vacio = "localhost". startURL vacio = "about:blank".
|
|
func CdpNewTabBackground(host string, port int, startURL string) (CdpTab, error) {
|
|
if host == "" {
|
|
host = "localhost"
|
|
}
|
|
if startURL == "" {
|
|
startURL = "about:blank"
|
|
}
|
|
|
|
// Target.createTarget debe ejecutarse contra el browser target (no una page),
|
|
// por eso resolvemos el webSocketDebuggerUrl browser-level via /json/version.
|
|
wsURL, err := cdpGetWSURL(port)
|
|
if err != nil {
|
|
return CdpTab{}, fmt.Errorf("cdp new tab background: %w", err)
|
|
}
|
|
|
|
conn, err := cdpConnectWS(wsURL, port)
|
|
if err != nil {
|
|
return CdpTab{}, fmt.Errorf("cdp new tab background: conectar: %w", err)
|
|
}
|
|
// Soltar solo el WebSocket; dejar el navegador vivo.
|
|
defer CdpDisconnect(conn)
|
|
|
|
res, err := conn.sendCDP("Target.createTarget", map[string]any{
|
|
"url": startURL,
|
|
"background": true,
|
|
})
|
|
if err != nil {
|
|
return CdpTab{}, fmt.Errorf("cdp new tab background: createTarget: %w", err)
|
|
}
|
|
|
|
targetID, _ := res["targetId"].(string)
|
|
if targetID == "" {
|
|
return CdpTab{}, fmt.Errorf("cdp new tab background: createTarget no devolvio targetId")
|
|
}
|
|
|
|
// Resolver el CdpTab completo (con webSocketDebuggerUrl, title, etc.) buscando
|
|
// el target recien creado en /json.
|
|
tabs, err := CdpListTabs(host, port)
|
|
if err == nil {
|
|
for _, t := range tabs {
|
|
if t.ID == targetID {
|
|
return t, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fallback en caso de carrera (el target aun no aparece en /json): devolvemos
|
|
// un CdpTab minimo con el id, tipo y URL inicial conocidos.
|
|
return CdpTab{ID: targetID, Type: "page", URL: startURL}, nil
|
|
}
|