Files
cdp_hub/docs/api.md
T

6.4 KiB
Raw Blame History

API / 模块合约

MVP 首先提供本地 Go application service 和 CLI;是否增加 loopback HTTP/WebSocket 在 T-203 决策。时间使用 RFC3339,路径使用规范化绝对路径。

核心类型

代码权威类型位于 internal/domain/browser.go:BrowserKind、LaunchSpec、InstanceStatus、InstanceView、BrowserEvent 和稳定错误码。LaunchSpec.Normalize() 负责 browser kind、绝对 user data dir、受控的 loopback remote debugging port,以及非空时的 http/https URL 校验;空 URL 表示打开浏览器默认页。

LaunchSpec 使用已分配的 RemoteDebugPort;端口分配不属于 UI,也不允许由 ExtraArgs 覆盖。InstanceView 返回实际关联端口、PID、占用来源和归属。外部关联只公开经 DevToolsActivePort 与 /json/version 验证的端口,不公开 CDP WebSocket URL。

只读 CDP 目标查看使用 platform RemoteDebugTargetInspector:

type RemoteDebugTarget struct {
    ID    string
    Type  string
    Title string
    URL   string // 已移除 userinfo、query 与 fragment
}

type RemoteDebugTargetInspector interface {
    ListRemoteDebugTargets(ctx context.Context, kind BrowserKind, port int) ([]RemoteDebugTarget, error)
}

调用者必须提供当前实例已经验证的实际端口;实现仍会复核 /json/version 的浏览器类型。该接口只请求 loopback HTTP /json/list,不公开或使用 webSocketDebuggerUrl,也不提供导航、关闭、创建 target 或执行脚本的接口。

UI 编辑使用独立的 EditableInstance DTO(ID、名称、浏览器类型、User Data Dir、启动 URL、ProxyID),不将运行时 PID、状态、来源或实际远程调试端口写回配置。ProxyProfile DTO 只包含 ID、必填且大小写无关唯一的显示名称、已校验的无认证端点;不提供认证字段。InstanceRow.ProxyID 是唯一持久关联,列表中的代理名称是按当前代理 DTO 推导的显示值,不持久化副本。状态刷新使用 RefreshInstanceStatus(ctx, []InstanceSnapshot) ([]InstanceStatusResult, error) 形状:每个结果以 ID 和快照版本对应,错误可按行返回;实现只能检查调用方提供的实例范围。

Application service

type BrowserManager interface {
    Start(ctx context.Context, spec LaunchSpec) (InstanceView, error)
    List(ctx context.Context) ([]InstanceView, error)
    Get(ctx context.Context, id string) (InstanceView, error)
    Stop(ctx context.Context, id string, force bool) error
    Restart(ctx context.Context, id string) (InstanceView, error)
}

Stop(force=false) 只执行优雅关闭;强制关闭必须由明确用户动作或 CLI --force 触发。

平台实现通过实例级 StopProfile(userDataDir, force) 执行关闭;force 只对已注册并经过身份绑定的实例生效。

GUI 将优雅停止封装为异步 InstanceStopper(ctx, InstanceRow) error adapter;adapter 只接受当前配置行并执行 force=false,不暴露平台句柄或允许调用方传递任意 PID。

参数数组由 internal/platform/browser.BuildArgs 生成;Chrome/Edge executable 由同包 Discoverer.Resolve 解析。二者都不接收 shell 命令行字符串。CDP 端点检测和端口分配均通过 platform port 执行,UI 只消费 DTO 结果。

状态刷新、受管进程退出、目录选择和 CDP 页面目标读取必须通过后台 adapter 回到 UI 结果通道;UI frame 不直接做进程、文件或 CDP I/O。受管退出结果至少包含实例 ID、启动代次、受管 PID、退出码和是否为 Chub 请求停止;UI 以实例 ID、代次和 PID 丢弃过期结果。刷新和页面目标读取都不构成外部实例接管授权。

Windows 通知区域使用仅限 platform 的内部 DTO;Gio shell 不直接调用 Shell API:

type TrayCommand uint8

const (
    TrayCommandShow TrayCommand = iota
    TrayCommandRefresh
    TrayCommandExit
)

type TrayState struct {
    ManagedRunning int
    ExternalLinked int
    AttentionCount int
}

原生 adapter 通过结果通道发布 TrayCommand,并只接收 TrayState 汇总来更新 Tooltip 或图标状态。不得在 DTO 中放入实例名称、路径、URL、代理、PID、CDP 地址或平台句柄;TrayCommand 不是实例启动、停止、重启、删除或接管 API。

本地配置入口统一为:

func DefaultPath() (string, error) // <dir(os.Executable())>\\config.json
func LegacyPath() (string, error)  // %APPDATA%\\chub\\config.json,仅用于一次迁移
func OpenDefault() (*Store, error) // 目标优先;必要时校验并原子迁移 legacy
func DefaultInstanceUserDataDir(instanceID string) (string, error) // <dir(os.Executable())>\\user_data_dirs\\<instanceID>

调用方不得把当前工作目录作为配置来源,也不得自行复制、删除或合并 legacy 文件。OpenDefault 的迁移是文件级配置迁移,不迁移 UserDataDir、日志目录或浏览器文件;目标文件存在、legacy 缺失时均不产生写入。DefaultInstanceUserDataDir 只生成绝对默认字符串,不创建目录;调用方必须先分配稳定、唯一的实例 ID。迁移失败返回稳定的配置错误,调用方不得改用 legacy 继续写入。

CLI 当前合约

chub start --browser chrome --user-data-dir <dir> [--profile-directory <name>] [--url <url>]
chub list
chub stop <instance-id> [--force]
chub restart <instance-id>
chub events

退出码:0 成功,2 参数错误,3 profile 占用,4 实例不存在,5 身份校验失败,6 系统权限/进程错误。

当前 list 和 events 已输出 JSON;events 输出本地配置快照 JSON,后续 loopback transport 接入后升级为 JSON Lines 持续流。start/stop/restart 已保留稳定命令和错误码,等待 BrowserManager adapter 接入。

事件

事件 触发 负载
browser.started 新实例完成启动 InstanceView
browser.status.changed 状态变化 instance_id、status、pid、remote_debug_port、ownership、error_code
browser.exited Chub 当前会话受管根进程退出 instance_id、launch_generation、pid、exit_code、expected_stop

事件禁止携带密码、Cookie、Token、完整代理认证信息或原始系统堆栈。

应用内 application.EventBus 使用带缓冲的订阅通道,发布不阻塞进程监控;UI 通过订阅刷新状态,取消订阅会关闭对应通道。