Files
navegator/pkg/browser/storage.go
T
Developer 3253828fef
Tests / Lint (push) Has been cancelled
Tests / Unit Tests (push) Has been cancelled
Tests / E2E Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Initial commit: navegator - Chrome CDP automation for LLMs
Add complete navegator system for stealthy browser automation:
- CDP client with WebSocket communication
- Browser API with navigation, storage, network, runtime
- Stealth flags and anti-detection scripts
- Persistent profile support
- Examples and comprehensive documentation

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-24 23:33:07 +01:00

348 lines
8.8 KiB
Go

package browser
import (
"context"
"fmt"
"time"
)
// Cookie representa una cookie.
type Cookie struct {
Name string `json:"name"`
Value string `json:"value"`
Domain string `json:"domain,omitempty"`
Path string `json:"path,omitempty"`
Expires float64 `json:"expires,omitempty"` // Unix timestamp
HTTPOnly bool `json:"httpOnly,omitempty"`
Secure bool `json:"secure,omitempty"`
SameSite string `json:"sameSite,omitempty"` // "Strict", "Lax", "None"
}
// GetCookies obtiene todas las cookies o las de un dominio específico.
func (b *Browser) GetCookies(ctx context.Context, urls ...string) ([]*Cookie, error) {
params := make(map[string]interface{})
if len(urls) > 0 {
params["urls"] = urls
}
var result struct {
Cookies []*Cookie `json:"cookies"`
}
if err := b.cdpClient.Execute(ctx, "Network.getCookies", params, &result); err != nil {
return nil, fmt.Errorf("failed to get cookies: %w", err)
}
return result.Cookies, nil
}
// SetCookie establece una cookie.
func (b *Browser) SetCookie(ctx context.Context, cookie *Cookie) error {
params := map[string]interface{}{
"name": cookie.Name,
"value": cookie.Value,
}
if cookie.Domain != "" {
params["domain"] = cookie.Domain
}
if cookie.Path != "" {
params["path"] = cookie.Path
}
if cookie.Expires > 0 {
params["expires"] = cookie.Expires
}
if cookie.HTTPOnly {
params["httpOnly"] = true
}
if cookie.Secure {
params["secure"] = true
}
if cookie.SameSite != "" {
params["sameSite"] = cookie.SameSite
}
var result struct {
Success bool `json:"success"`
}
if err := b.cdpClient.Execute(ctx, "Network.setCookie", params, &result); err != nil {
return fmt.Errorf("failed to set cookie: %w", err)
}
if !result.Success {
return fmt.Errorf("failed to set cookie: %s", cookie.Name)
}
return nil
}
// SetCookies establece múltiples cookies.
func (b *Browser) SetCookies(ctx context.Context, cookies []*Cookie) error {
for _, cookie := range cookies {
if err := b.SetCookie(ctx, cookie); err != nil {
return err
}
}
return nil
}
// DeleteCookie elimina una cookie específica.
func (b *Browser) DeleteCookie(ctx context.Context, name string, domain string) error {
params := map[string]interface{}{
"name": name,
}
if domain != "" {
params["domain"] = domain
}
return b.cdpClient.Execute(ctx, "Network.deleteCookies", params, nil)
}
// ClearCookies elimina todas las cookies.
func (b *Browser) ClearCookies(ctx context.Context) error {
return b.cdpClient.Execute(ctx, "Network.clearBrowserCookies", nil, nil)
}
// LocalStorageItem representa un item de localStorage.
type LocalStorageItem struct {
Key string `json:"key"`
Value string `json:"value"`
}
// GetLocalStorage obtiene todos los items del localStorage.
func (b *Browser) GetLocalStorage(ctx context.Context) ([]*LocalStorageItem, error) {
script := `
(() => {
const items = [];
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
items.push({ key: key, value: localStorage.getItem(key) });
}
return items;
})()
`
var result struct {
Result struct {
Value []map[string]interface{} `json:"value"`
} `json:"result"`
}
params := map[string]interface{}{
"expression": script,
"returnByValue": true,
}
if err := b.cdpClient.Execute(ctx, "Runtime.evaluate", params, &result); err != nil {
return nil, fmt.Errorf("failed to get localStorage: %w", err)
}
items := make([]*LocalStorageItem, 0, len(result.Result.Value))
for _, item := range result.Result.Value {
items = append(items, &LocalStorageItem{
Key: item["key"].(string),
Value: item["value"].(string),
})
}
return items, nil
}
// SetLocalStorage establece un item en localStorage.
func (b *Browser) SetLocalStorage(ctx context.Context, key, value string) error {
script := fmt.Sprintf(`localStorage.setItem(%q, %q)`, key, value)
params := map[string]interface{}{
"expression": script,
}
return b.cdpClient.Execute(ctx, "Runtime.evaluate", params, nil)
}
// RemoveLocalStorage elimina un item de localStorage.
func (b *Browser) RemoveLocalStorage(ctx context.Context, key string) error {
script := fmt.Sprintf(`localStorage.removeItem(%q)`, key)
params := map[string]interface{}{
"expression": script,
}
return b.cdpClient.Execute(ctx, "Runtime.evaluate", params, nil)
}
// ClearLocalStorage limpia todo el localStorage.
func (b *Browser) ClearLocalStorage(ctx context.Context) error {
params := map[string]interface{}{
"expression": "localStorage.clear()",
}
return b.cdpClient.Execute(ctx, "Runtime.evaluate", params, nil)
}
// GetSessionStorage obtiene todos los items del sessionStorage.
func (b *Browser) GetSessionStorage(ctx context.Context) ([]*LocalStorageItem, error) {
script := `
(() => {
const items = [];
for (let i = 0; i < sessionStorage.length; i++) {
const key = sessionStorage.key(i);
items.push({ key: key, value: sessionStorage.getItem(key) });
}
return items;
})()
`
var result struct {
Result struct {
Value []map[string]interface{} `json:"value"`
} `json:"result"`
}
params := map[string]interface{}{
"expression": script,
"returnByValue": true,
}
if err := b.cdpClient.Execute(ctx, "Runtime.evaluate", params, &result); err != nil {
return nil, fmt.Errorf("failed to get sessionStorage: %w", err)
}
items := make([]*LocalStorageItem, 0, len(result.Result.Value))
for _, item := range result.Result.Value {
items = append(items, &LocalStorageItem{
Key: item["key"].(string),
Value: item["value"].(string),
})
}
return items, nil
}
// SetSessionStorage establece un item en sessionStorage.
func (b *Browser) SetSessionStorage(ctx context.Context, key, value string) error {
script := fmt.Sprintf(`sessionStorage.setItem(%q, %q)`, key, value)
params := map[string]interface{}{
"expression": script,
}
return b.cdpClient.Execute(ctx, "Runtime.evaluate", params, nil)
}
// RemoveSessionStorage elimina un item de sessionStorage.
func (b *Browser) RemoveSessionStorage(ctx context.Context, key string) error {
script := fmt.Sprintf(`sessionStorage.removeItem(%q)`, key)
params := map[string]interface{}{
"expression": script,
}
return b.cdpClient.Execute(ctx, "Runtime.evaluate", params, nil)
}
// ClearSessionStorage limpia todo el sessionStorage.
func (b *Browser) ClearSessionStorage(ctx context.Context) error {
params := map[string]interface{}{
"expression": "sessionStorage.clear()",
}
return b.cdpClient.Execute(ctx, "Runtime.evaluate", params, nil)
}
// StorageType tipo de storage.
type StorageType string
const (
StorageTypeCookies StorageType = "cookies"
StorageTypeLocalStorage StorageType = "local_storage"
StorageTypeSessionStorage StorageType = "session_storage"
StorageTypeIndexedDB StorageType = "indexeddb"
StorageTypeWebSQL StorageType = "websql"
StorageTypeCacheStorage StorageType = "cache_storage"
)
// ClearDataForOrigin limpia datos de un origen específico.
func (b *Browser) ClearDataForOrigin(ctx context.Context, origin string, storageTypes ...StorageType) error {
if len(storageTypes) == 0 {
// Por defecto, limpiar todo
storageTypes = []StorageType{
StorageTypeCookies,
StorageTypeLocalStorage,
StorageTypeSessionStorage,
StorageTypeIndexedDB,
StorageTypeWebSQL,
StorageTypeCacheStorage,
}
}
// Convertir a string separado por comas
types := ""
for i, st := range storageTypes {
if i > 0 {
types += ","
}
types += string(st)
}
params := map[string]interface{}{
"origin": origin,
"storageTypes": types,
}
return b.cdpClient.Execute(ctx, "Storage.clearDataForOrigin", params, nil)
}
// ExportCookies exporta las cookies del perfil a un archivo JSON.
func (b *Browser) ExportCookies(ctx context.Context) ([]*Cookie, error) {
return b.GetCookies(ctx)
}
// ImportCookies importa cookies desde un slice.
func (b *Browser) ImportCookies(ctx context.Context, cookies []*Cookie) error {
return b.SetCookies(ctx, cookies)
}
// CreateCookie crea una cookie helper.
func CreateCookie(name, value, domain string) *Cookie {
return &Cookie{
Name: name,
Value: value,
Domain: domain,
Path: "/",
// Expira en 1 año
Expires: float64(time.Now().Add(365 * 24 * time.Hour).Unix()),
HTTPOnly: false,
Secure: false,
SameSite: "Lax",
}
}
// CreateSessionCookie crea una cookie de sesión (sin expiración).
func CreateSessionCookie(name, value, domain string) *Cookie {
return &Cookie{
Name: name,
Value: value,
Domain: domain,
Path: "/",
HTTPOnly: false,
Secure: false,
SameSite: "Lax",
}
}
// CreateSecureCookie crea una cookie segura (HTTPS only).
func CreateSecureCookie(name, value, domain string) *Cookie {
return &Cookie{
Name: name,
Value: value,
Domain: domain,
Path: "/",
Expires: float64(time.Now().Add(365 * 24 * time.Hour).Unix()),
HTTPOnly: true,
Secure: true,
SameSite: "Strict",
}
}