docs: define Windows notification-area task
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
| BR-015 | GUI 实例主操作在 Chub 托管运行态提供优雅停止、在可启动状态提供启动;外部关联或未知外部实例不得获得生命周期控制。 | P1 |
|
| BR-015 | GUI 实例主操作在 Chub 托管运行态提供优雅停止、在可启动状态提供启动;外部关联或未知外部实例不得获得生命周期控制。 | P1 |
|
||||||
| BR-016 | 每个已保存实例有独立、持久化的首选远程调试端口;它与运行时实际端口分离,未启动实例仍可在列表看到建议端口。 | P1 |
|
| BR-016 | 每个已保存实例有独立、持久化的首选远程调试端口;它与运行时实际端口分离,未启动实例仍可在列表看到建议端口。 | P1 |
|
||||||
| BR-017 | 用户可以仅通过已验证的 loopback CDP 端点查看 Chub 实例的页面目标(标签页)标题、脱敏 URL 和类型;该功能不得控制页面、关闭标签页或接管外部浏览器。 | P1 |
|
| BR-017 | 用户可以仅通过已验证的 loopback CDP 端点查看 Chub 实例的页面目标(标签页)标题、脱敏 URL 和类型;该功能不得控制页面、关闭标签页或接管外部浏览器。 | P1 |
|
||||||
|
| BR-018 | Chub 运行时提供一个 Windows 通知区域图标,允许显示主窗口、刷新已保存实例状态和显式退出应用;图标及菜单不得绕过实例授权边界或泄露实例路径、URL、代理等敏感信息。 | P1 |
|
||||||
|
|
||||||
## 验收标准
|
## 验收标准
|
||||||
|
|
||||||
@@ -43,7 +44,9 @@
|
|||||||
- 用户从 Chub 发起优雅停止时,不显示“浏览器已退出”意外退出提示;外部已关联、外部占用、未知占用以及应用关闭后无法继续监控的实例均不弹出此提示。
|
- 用户从 Chub 发起优雅停止时,不显示“浏览器已退出”意外退出提示;外部已关联、外部占用、未知占用以及应用关闭后无法继续监控的实例均不弹出此提示。
|
||||||
- 用户只能对“运行中”或“外部已关联”且已有实际、已验证 CDP 端口的实例打开页面目标查看;读取失败时保留实例配置和当前编辑内容,给出可恢复的重试提示。
|
- 用户只能对“运行中”或“外部已关联”且已有实际、已验证 CDP 端口的实例打开页面目标查看;读取失败时保留实例配置和当前编辑内容,给出可恢复的重试提示。
|
||||||
- 页面目标列表只显示标题、类型和移除 userinfo、query、fragment 的 URL;不得保存、记录、发布或展示 CDP WebSocket URL,也不得发送导航、关闭、创建或脚本执行命令。
|
- 页面目标列表只显示标题、类型和移除 userinfo、query、fragment 的 URL;不得保存、记录、发布或展示 CDP WebSocket URL,也不得发送导航、关闭、创建或脚本执行命令。
|
||||||
|
- 通知区域仅显示一个 Chub 图标;Tooltip 仅含非敏感汇总状态。双击或默认菜单项显示并置前主窗口,刷新命令仍只检查已保存实例,退出命令走明确的应用退出协调流程。
|
||||||
|
- 图标创建失败、Explorer 重启、菜单关闭和应用退出不会阻塞 UI 帧,也不会导致浏览器启动、关闭、接管或按进程名枚举。退出时必须移除图标;外部 Chrome/Edge 永远不因通知区域命令被停止。
|
||||||
|
|
||||||
## 不做
|
## 不做
|
||||||
|
|
||||||
全局杀 Chrome/Edge、自动登录、页面操作、验证码处理、平台 API 集成、远程控制和跨用户权限提升;通过 CDP 管理或关闭外部实例。首个 CDP 查看版本不提供物理窗口 ID 或分组,后续仅在经过独立安全评审的 WebSocket CDP 任务中考虑。
|
全局杀 Chrome/Edge、自动登录、页面操作、验证码处理、平台 API 集成、远程控制和跨用户权限提升;通过 CDP 管理或关闭外部实例。首个 CDP 查看版本不提供物理窗口 ID 或分组,后续仅在经过独立安全评审的 WebSocket CDP 任务中考虑。首个通知区域版本不改变窗口关闭语义、不把关闭按钮隐藏到通知区域,也不在菜单中直接启动、停止、重启或删除实例。
|
||||||
|
|||||||
@@ -11,11 +11,12 @@ Platform Windows
|
|||||||
├─ process identity / query
|
├─ process identity / query
|
||||||
├─ graceful close / force kill
|
├─ graceful close / force kill
|
||||||
├─ Job Object
|
├─ Job Object
|
||||||
└─ profile occupancy inspector
|
├─ profile occupancy inspector
|
||||||
├─ loopback CDP endpoint inspector
|
├─ loopback CDP endpoint inspector
|
||||||
├─ loopback CDP target reader (read-only `/json/list`)
|
├─ loopback CDP target reader (read-only `/json/list`)
|
||||||
├─ remote-debug port allocator
|
├─ remote-debug port allocator
|
||||||
└─ instance status refresher
|
├─ instance status refresher
|
||||||
|
└─ notification-area adapter (Windows Shell)
|
||||||
↓
|
↓
|
||||||
Chrome / Edge processes
|
Chrome / Edge processes
|
||||||
```
|
```
|
||||||
@@ -44,6 +45,7 @@ UI/CLI 不直接操作 `exec.Cmd`、Win32 handle 或数据库。Application 层
|
|||||||
- GUI stop:主操作只对 Chub registry 中可验证的托管实例调用 `StopProfile(userDataDir, false)`,随后有限等待 registry 释放。外部关联、占用和未知实例永远不调用停止接口;超时或失败不自动强制关闭。
|
- GUI stop:主操作只对 Chub registry 中可验证的托管实例调用 `StopProfile(userDataDir, false)`,随后有限等待 registry 释放。外部关联、占用和未知实例永远不调用停止接口;超时或失败不自动强制关闭。
|
||||||
- 受管退出监控:仅为当前会话由 Chub 启动并获得进程句柄的实例建立一个 `Wait` 监控任务。退出事件携带实例 ID、启动代次和 PID,UI 仅在三者仍匹配且当前未处于 Chub 请求的停止中时,将运行时状态改为“已退出”并排队显示提示;过期事件、外部实例和应用退出后的监控取消均不得生成意外退出提示。
|
- 受管退出监控:仅为当前会话由 Chub 启动并获得进程句柄的实例建立一个 `Wait` 监控任务。退出事件携带实例 ID、启动代次和 PID,UI 仅在三者仍匹配且当前未处于 Chub 请求的停止中时,将运行时状态改为“已退出”并排队显示提示;过期事件、外部实例和应用退出后的监控取消均不得生成意外退出提示。
|
||||||
- CDP 页面目标查看:UI 仅将当前已保存实例快照交给后台 adapter;adapter 只接受“运行中”或“外部已关联”的有效实际端口,先复核对应 browser kind 的 loopback `/json/version`,再读取同一端口的 `/json/list`。结果 DTO 仅含 target ID、标题、类型和脱敏 URL;UI 以实例 ID、端口和请求代次丢弃过期结果。该链路不建立 WebSocket、不开启页面控制,也不提供物理窗口 ID。
|
- CDP 页面目标查看:UI 仅将当前已保存实例快照交给后台 adapter;adapter 只接受“运行中”或“外部已关联”的有效实际端口,先复核对应 browser kind 的 loopback `/json/version`,再读取同一端口的 `/json/list`。结果 DTO 仅含 target ID、标题、类型和脱敏 URL;UI 以实例 ID、端口和请求代次丢弃过期结果。该链路不建立 WebSocket、不开启页面控制,也不提供物理窗口 ID。
|
||||||
|
- 通知区域:Windows platform adapter 在独立原生消息循环中管理一个图标、Tooltip 和原生菜单,向 `cmd/chub` 发送仅含“显示主窗口 / 刷新状态 / 退出应用”的 typed command。应用 coordinator 决定如何显示 Gio 窗口、发起既有刷新或执行退出清理;adapter 不持有浏览器进程句柄,不调用浏览器启动/停止接口。图标状态仅来自非敏感实例计数;Explorer 重启后重新注册,应用结束前删除图标。首版不拦截 Gio 的窗口关闭消息,也不隐藏主窗口。
|
||||||
|
|
||||||
Chrome 和 Edge 共用大部分 Chromium 参数,但 executable 默认路径、进程名称和安装方式不同,通过 `BrowserDefinition` 封装差异。CDP 端点只绑定 `127.0.0.1`;端口号和 `/json/version` 是诊断数据,WebSocket URL 不进入持久化、事件或普通 UI 文案。`/json/list` 仅用于只读页面目标信息;URL 在 DTO 边界移除 userinfo、query 和 fragment。
|
Chrome 和 Edge 共用大部分 Chromium 参数,但 executable 默认路径、进程名称和安装方式不同,通过 `BrowserDefinition` 封装差异。CDP 端点只绑定 `127.0.0.1`;端口号和 `/json/version` 是诊断数据,WebSocket URL 不进入持久化、事件或普通 UI 文案。`/json/list` 仅用于只读页面目标信息;URL 在 DTO 边界移除 userinfo、query 和 fragment。
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -47,12 +47,13 @@
|
|||||||
| T-309 | 实例首选调试端口与安全推荐分配 | T-302,T-303,T-308 | DONE |
|
| T-309 | 实例首选调试端口与安全推荐分配 | T-302,T-303,T-308 | DONE |
|
||||||
| T-310 | 实例创建与编辑表单边框层级 | T-308,T-309 | DONE |
|
| T-310 | 实例创建与编辑表单边框层级 | T-308,T-309 | DONE |
|
||||||
|
|
||||||
## Phase 4:CDP 只读观察
|
## Phase 4:CDP 只读观察与后台入口
|
||||||
|
|
||||||
| ID | 任务 | 依赖 | 状态 |
|
| ID | 任务 | 依赖 | 状态 |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| T-401 | 已验证实例的 CDP 页面目标只读查看 | T-302,T-303,T-310 | DONE |
|
| T-401 | 已验证实例的 CDP 页面目标只读查看 | T-302,T-303,T-310 | DONE |
|
||||||
|
| T-402 | Windows 通知区域入口与显式退出协调 | T-303,T-305,T-307 | TODO |
|
||||||
|
|
||||||
## Backlog
|
## Backlog
|
||||||
|
|
||||||
CDP tab/window 管理、导入导出启动配置、进程资源监控、多用户权限和远程主机管理。
|
关闭窗口时隐藏到通知区域与单实例激活、CDP tab/window 管理、导入导出启动配置、进程资源监控、多用户权限和远程主机管理。
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
| US-010 | 用户可以通过实例行的同一主操作启动或优雅停止 Chub 托管的浏览器,而不会关闭外部浏览器。 | P1 |
|
| US-010 | 用户可以通过实例行的同一主操作启动或优雅停止 Chub 托管的浏览器,而不会关闭外部浏览器。 | P1 |
|
||||||
| US-011 | 用户手动关闭 Chub 启动的 Chrome/Edge 后,可以立即获知该实例已退出,并重新启动该实例。 | P1 |
|
| US-011 | 用户手动关闭 Chub 启动的 Chrome/Edge 后,可以立即获知该实例已退出,并重新启动该实例。 | P1 |
|
||||||
| US-012 | 用户可以查看已验证运行实例的 CDP 页面目标标题、脱敏 URL 和类型,而不会向浏览器发送控制命令。 | P1 |
|
| US-012 | 用户可以查看已验证运行实例的 CDP 页面目标标题、脱敏 URL 和类型,而不会向浏览器发送控制命令。 | P1 |
|
||||||
|
| US-013 | 用户可以从 Windows 通知区域快速显示 Chub、刷新已保存实例状态或明确退出应用,而不会在菜单中误操作浏览器实例。 | P1 |
|
||||||
|
|
||||||
## 验收场景
|
## 验收场景
|
||||||
|
|
||||||
@@ -52,3 +53,7 @@ CLI/API 返回稳定错误码和结构化数据;未知 PID、身份不匹配
|
|||||||
### US-012 只读 CDP 页面目标
|
### US-012 只读 CDP 页面目标
|
||||||
|
|
||||||
给定一个“运行中”或“外部已关联”实例已经存在经验证的实际 loopback CDP 端口,用户从实例编辑对话框打开“查看标签页”,Chub 在后台再次验证 browser kind 后读取 `/json/list`,并显示页面目标的标题、类型和脱敏 URL。读取中可关闭对话框;请求失败、端点失效或实例状态变化时不改变实例配置或生命周期。给定未启动、启动中、停止中、调试不可用、外部占用或未知占用实例,入口禁用并说明需要已验证端口。页面目标查看不展示 WebSocket URL、物理窗口 ID,也不提供导航、关闭或创建页面命令。
|
给定一个“运行中”或“外部已关联”实例已经存在经验证的实际 loopback CDP 端口,用户从实例编辑对话框打开“查看标签页”,Chub 在后台再次验证 browser kind 后读取 `/json/list`,并显示页面目标的标题、类型和脱敏 URL。读取中可关闭对话框;请求失败、端点失效或实例状态变化时不改变实例配置或生命周期。给定未启动、启动中、停止中、调试不可用、外部占用或未知占用实例,入口禁用并说明需要已验证端口。页面目标查看不展示 WebSocket URL、物理窗口 ID,也不提供导航、关闭或创建页面命令。
|
||||||
|
|
||||||
|
### US-013 Windows 通知区域入口
|
||||||
|
|
||||||
|
给定 Chub 正在运行,Windows 通知区域出现一个 Chub 图标;用户双击图标或选择默认“显示 Chub”命令后,主窗口显示并置前。用户选择“刷新实例状态”后,Chub 沿用页面刷新相同的已保存实例范围和后台去重规则。用户选择“退出 Chub”后,应用进入明确退出协调流程并清理图标;该菜单不列出实例,也不提供启动、停止、重启、删除或外部接管。Explorer 重启后图标会恢复,图标失效仅显示可恢复诊断,不影响窗口和浏览器实例。首版关闭主窗口仍按原退出语义处理,不会自动隐藏到通知区域。
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
| IX-010 | 受管浏览器退出提示 | 受管根进程退出后的状态恢复、提示队列和焦点回归 | 意外退出、Chub 请求停止、多个同时退出、过期事件、编辑/确认弹层打开、应用关闭 | P1 |
|
| IX-010 | 受管浏览器退出提示 | 受管根进程退出后的状态恢复、提示队列和焦点回归 | 意外退出、Chub 请求停止、多个同时退出、过期事件、编辑/确认弹层打开、应用关闭 | P1 |
|
||||||
| IX-011 | 实例首选调试端口 | 新建/编辑端口推荐、列表建议/准备/实际/外部文案、启动回退与保存 | 旧配置迁移、重复/非法端口、外部冲突、启动失败、外部关联、过期结果 | P1 |
|
| IX-011 | 实例首选调试端口 | 新建/编辑端口推荐、列表建议/准备/实际/外部文案、启动回退与保存 | 旧配置迁移、重复/非法端口、外部冲突、启动失败、外部关联、过期结果 | P1 |
|
||||||
| IX-012 | CDP 页面目标查看 | 编辑弹层的“查看标签页”、只读目标列表与关闭 | 无可验证端口、读取中、空列表、读取失败、状态变更、Escape/焦点回归 | P1 |
|
| IX-012 | CDP 页面目标查看 | 编辑弹层的“查看标签页”、只读目标列表与关闭 | 无可验证端口、读取中、空列表、读取失败、状态变更、Escape/焦点回归 | P1 |
|
||||||
|
| IX-013 | Windows 通知区域 | 图标双击/默认显示、原生菜单刷新与退出 | 图标创建失败、Explorer 重启、窗口最小化、菜单关闭、刷新中、应用退出 | P1 |
|
||||||
|
|
||||||
## 通用规则
|
## 通用规则
|
||||||
|
|
||||||
@@ -31,3 +32,4 @@
|
|||||||
- 受管浏览器意外退出是当前会话的异步状态提示,不是用户确认决策:状态先更新为“已退出”,再显示可关闭信息弹层;弹层只含“知道了”,Escape/Enter 均可关闭,关闭后焦点回到对应启动入口。多个退出合并到一个提示;已有编辑、未保存确认或删除确认弹层时排队,不能丢弃输入或叠加模态层。Chub 发起停止、外部实例、代次/PID 不匹配和应用退出取消监控时均不提示。
|
- 受管浏览器意外退出是当前会话的异步状态提示,不是用户确认决策:状态先更新为“已退出”,再显示可关闭信息弹层;弹层只含“知道了”,Escape/Enter 均可关闭,关闭后焦点回到对应启动入口。多个退出合并到一个提示;已有编辑、未保存确认或删除确认弹层时排队,不能丢弃输入或叠加模态层。Chub 发起停止、外部实例、代次/PID 不匹配和应用退出取消监控时均不提示。
|
||||||
- 调试端口的“建议/准备/实际/外部”必须同时以文字和数值表达,不能将首选端口称为已监听端口。创建和停止实例编辑使用首选端口输入;运行中、启动中、停止中和外部关联实例只读。推荐仅基于 Chub 保存实例,系统端口复检与 CDP 校验只在后台启动任务执行;回退不得使用其他 Chub 实例的逻辑预留端口。
|
- 调试端口的“建议/准备/实际/外部”必须同时以文字和数值表达,不能将首选端口称为已监听端口。创建和停止实例编辑使用首选端口输入;运行中、启动中、停止中和外部关联实例只读。推荐仅基于 Chub 保存实例,系统端口复检与 CDP 校验只在后台启动任务执行;回退不得使用其他 Chub 实例的逻辑预留端口。
|
||||||
- CDP 页面目标查看是只读、可关闭的临时对话框:入口仅对已有实际已验证端口的“运行中”或“外部已关联”实例可用;打开后焦点位于关闭按钮,Escape 关闭并回到“查看标签页”入口。读取中、空列表和错误均用文字表达,错误不丢失编辑输入;结果只含标题、类型和脱敏 URL,不能把目标 ID、WebSocket URL 或物理窗口 ID当作控制授权。
|
- CDP 页面目标查看是只读、可关闭的临时对话框:入口仅对已有实际已验证端口的“运行中”或“外部已关联”实例可用;打开后焦点位于关闭按钮,Escape 关闭并回到“查看标签页”入口。读取中、空列表和错误均用文字表达,错误不丢失编辑输入;结果只含标题、类型和脱敏 URL,不能把目标 ID、WebSocket URL 或物理窗口 ID当作控制授权。
|
||||||
|
- 通知区域图标是 Windows 原生的辅助入口,不替代页面内可键盘访问的实例操作。图标默认项为“显示 Chub”,双击同效;右键菜单顺序固定为显示、刷新、分隔线、退出。刷新复用页面刷新命令并在进行中禁用重复项;退出是应用级命令,不能伪装为关闭单个浏览器。Tooltip 使用文字汇总,不含实例名称或敏感字段。菜单关闭不改变状态;图标失效或 Explorer 重启后后台重建,不抢焦点。首版不提供“关闭时隐藏到通知区域”。
|
||||||
|
|||||||
+20
@@ -49,6 +49,26 @@ GUI 将优雅停止封装为异步 `InstanceStopper(ctx, InstanceRow) error` ada
|
|||||||
|
|
||||||
状态刷新、受管进程退出、目录选择和 CDP 页面目标读取必须通过后台 adapter 回到 UI 结果通道;UI frame 不直接做进程、文件或 CDP I/O。受管退出结果至少包含实例 ID、启动代次、受管 PID、退出码和是否为 Chub 请求停止;UI 以实例 ID、代次和 PID 丢弃过期结果。刷新和页面目标读取都不构成外部实例接管授权。
|
状态刷新、受管进程退出、目录选择和 CDP 页面目标读取必须通过后台 adapter 回到 UI 结果通道;UI frame 不直接做进程、文件或 CDP I/O。受管退出结果至少包含实例 ID、启动代次、受管 PID、退出码和是否为 Chub 请求停止;UI 以实例 ID、代次和 PID 丢弃过期结果。刷新和页面目标读取都不构成外部实例接管授权。
|
||||||
|
|
||||||
|
Windows 通知区域使用仅限 platform 的内部 DTO;Gio shell 不直接调用 Shell API:
|
||||||
|
|
||||||
|
```go
|
||||||
|
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。
|
||||||
|
|
||||||
## CLI 当前合约
|
## CLI 当前合约
|
||||||
|
|
||||||
```text
|
```text
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
## 快照
|
## 快照
|
||||||
|
|
||||||
- 日期:2026-07-27
|
- 日期:2026-07-27
|
||||||
- 阶段:Phase 4 CDP 只读观察(T-301 至 T-310、T-201 至 T-208、T-401 已完成)
|
- 阶段:Phase 4 CDP 只读观察与后台入口(T-301 至 T-310、T-201 至 T-208、T-401 已完成;T-402 已规划)
|
||||||
- 代码:已建立 Go module `chub`、`cmd/chub` 入口、logging 测试基座、浏览器 domain/application 合约、Chrome/Edge 参数/发现模块、启动 registry、Windows 身份/占用检查、loopback CDP 端口分配与端点校验、受限 CDP 目标读取、优雅关闭、Job Object、真实 Chrome/Edge smoke、JSON 配置存储、启动恢复、CLI JSON 合约、应用内事件总线、UI 状态测试和 Windows smoke 脚本,T-001 至 T-003、T-101 至 T-104、T-201 至 T-208、T-301 至 T-310、T-401 已完成
|
- 代码:已建立 Go module `chub`、`cmd/chub` 入口、logging 测试基座、浏览器 domain/application 合约、Chrome/Edge 参数/发现模块、启动 registry、Windows 身份/占用检查、loopback CDP 端口分配与端点校验、受限 CDP 目标读取、优雅关闭、Job Object、真实 Chrome/Edge smoke、JSON 配置存储、启动恢复、CLI JSON 合约、应用内事件总线、UI 状态测试和 Windows smoke 脚本,T-001 至 T-003、T-101 至 T-104、T-201 至 T-208、T-301 至 T-310、T-401 已完成
|
||||||
- UI:Gio 双页 Shell 使用左侧“实例/设置”导航;实例页以等宽“新建实例 / 刷新实例状态”命令区开始,窄内容区自动堆叠。列表固定显示实例名称、浏览器类型、用户数据目录、调试端口、状态和带边框的操作列;端口列在未启动/已退出时显示“建议 {端口}”、启动中显示“准备 {端口}”、托管运行显示“实际 {端口}”、外部关联显示“外部 {端口}”,避免将持久首选端口误作监听事实。新建表单从设置的起始端口推荐最低未冲突端口,编辑停止实例可修改首选端口;启动后台优先该端口并避开其他实例的首选/实际端口,成功回退后才保存新的首选值。操作顺序固定为启动/停止(或重新检测)、编辑、删除,删除与相邻操作保持更大间距以降低误点。主操作在已退出时启动,在 Chub 托管运行或调试不可用时显示停止,在启动/停止中禁用,在外部关联、外部占用或未知占用时仅重新检测;优雅停止通过后台 adapter 验证 registry 的 PID/profile 身份并等待其释放,绝不按进程名关闭或接管外部 Chrome/Edge。刷新通过后台回调只检查已保存实例,以配置快照丢弃编辑或删除后的过期结果;它结合 Chub registry、指定 profile 的外部占用证据和 loopback CDP 端点更新状态,但不扫描、接管或关闭其他 Chrome/Edge。双击、Enter 或编辑图标打开实例编辑弹层,支持名称、浏览器类型、User Data Dir、启动 URL、首选端口、完整地址代理选择和只读实际端口;保存保留未公开启动选项,Escape 对脏表单先请求确认,活跃/外部关联实例锁定身份约束字段。设置页使用完整代理地址选择器、地址输入及保存/删除操作;选择会回填地址,保存按稳定 `proxyId` 新增或更新,删除未引用代理前必须确认,仍被实例引用的代理会被拒绝。启动通过异步回调接到 Windows 浏览器启动器:未占用目录从已保存的起始端口(空值默认 9666)选择 loopback CDP 端口,并在启动时按已选代理 ID 解析最新的 `--proxy-server` 参数;同目录外部浏览器只有在 `DevToolsActivePort` 与 CDP 端点可验证时才显示“外部已关联”,且不会接管其生命周期。删除使用确认弹层,只删除 Chub 实例配置而不删除 User Data Dir。新建、编辑和删除实例会保存到本地配置;四个设置路径有独立异步可取消搜索,切换页面后输入和任务状态保留;新建实例表单使用 Label、Windows 原生目录选择器和 Chrome/Edge RadioButton;CLI `list/events` 已可用,`start/stop/restart` 等待 BrowserManager adapter
|
- UI:Gio 双页 Shell 使用左侧“实例/设置”导航;实例页以等宽“新建实例 / 刷新实例状态”命令区开始,窄内容区自动堆叠。列表固定显示实例名称、浏览器类型、用户数据目录、调试端口、状态和带边框的操作列;端口列在未启动/已退出时显示“建议 {端口}”、启动中显示“准备 {端口}”、托管运行显示“实际 {端口}”、外部关联显示“外部 {端口}”,避免将持久首选端口误作监听事实。新建表单从设置的起始端口推荐最低未冲突端口,编辑停止实例可修改首选端口;启动后台优先该端口并避开其他实例的首选/实际端口,成功回退后才保存新的首选值。操作顺序固定为启动/停止(或重新检测)、编辑、删除,删除与相邻操作保持更大间距以降低误点。主操作在已退出时启动,在 Chub 托管运行或调试不可用时显示停止,在启动/停止中禁用,在外部关联、外部占用或未知占用时仅重新检测;优雅停止通过后台 adapter 验证 registry 的 PID/profile 身份并等待其释放,绝不按进程名关闭或接管外部 Chrome/Edge。刷新通过后台回调只检查已保存实例,以配置快照丢弃编辑或删除后的过期结果;它结合 Chub registry、指定 profile 的外部占用证据和 loopback CDP 端点更新状态,但不扫描、接管或关闭其他 Chrome/Edge。双击、Enter 或编辑图标打开实例编辑弹层,支持名称、浏览器类型、User Data Dir、启动 URL、首选端口、完整地址代理选择和只读实际端口;保存保留未公开启动选项,Escape 对脏表单先请求确认,活跃/外部关联实例锁定身份约束字段。设置页使用完整代理地址选择器、地址输入及保存/删除操作;选择会回填地址,保存按稳定 `proxyId` 新增或更新,删除未引用代理前必须确认,仍被实例引用的代理会被拒绝。启动通过异步回调接到 Windows 浏览器启动器:未占用目录从已保存的起始端口(空值默认 9666)选择 loopback CDP 端口,并在启动时按已选代理 ID 解析最新的 `--proxy-server` 参数;同目录外部浏览器只有在 `DevToolsActivePort` 与 CDP 端点可验证时才显示“外部已关联”,且不会接管其生命周期。删除使用确认弹层,只删除 Chub 实例配置而不删除 User Data Dir。新建、编辑和删除实例会保存到本地配置;四个设置路径有独立异步可取消搜索,切换页面后输入和任务状态保留;新建实例表单使用 Label、Windows 原生目录选择器和 Chrome/Edge RadioButton;CLI `list/events` 已可用,`start/stop/restart` 等待 BrowserManager adapter
|
||||||
- T-307:本应用会话启动的受管 Chrome/Edge 根进程由单实例后台 `Wait` 监控;意外退出按 ID、启动代次和 PID 验证后立即变为“已退出”,清空运行时 PID/端口,并以可关闭、可合并的提示告知用户。提示关闭后焦点回到启动操作;Chub 请求停止、外部实例、过期事件和应用关闭取消监控均不提示。
|
- T-307:本应用会话启动的受管 Chrome/Edge 根进程由单实例后台 `Wait` 监控;意外退出按 ID、启动代次和 PID 验证后立即变为“已退出”,清空运行时 PID/端口,并以可关闭、可合并的提示告知用户。提示关闭后焦点回到启动操作;Chub 请求停止、外部实例、过期事件和应用关闭取消监控均不提示。
|
||||||
@@ -12,7 +12,8 @@
|
|||||||
- T-309:实例保存 `PreferredRemoteDebugPort`,旧 JSON 读取时按稳定顺序补齐;配置拒绝无效或重复端口。推荐仅基于保存实例快照,启动后台跳过其他实例的逻辑预留和当前实际端口;成功的本地端口回退会保存为新的首选值。实际 CDP 端点仍是运行时端口唯一事实来源。
|
- T-309:实例保存 `PreferredRemoteDebugPort`,旧 JSON 读取时按稳定顺序补齐;配置拒绝无效或重复端口。推荐仅基于保存实例快照,启动后台跳过其他实例的逻辑预留和当前实际端口;成功的本地端口回退会保存为新的首选值。实际 CDP 端点仍是运行时端口唯一事实来源。
|
||||||
- T-310:实例新建页使用外层工作区、字段组件和操作区三级边框;编辑弹层使用可辨外框,并为字段、运行态信息、反馈和操作区添加一致描边。紧凑窗口下沿用原有路径/操作重排,字段状态和键盘交互未改变。
|
- T-310:实例新建页使用外层工作区、字段组件和操作区三级边框;编辑弹层使用可辨外框,并为字段、运行态信息、反馈和操作区添加一致描边。紧凑窗口下沿用原有路径/操作重排,字段状态和键盘交互未改变。
|
||||||
- T-401:仅在运行中或外部已关联实例已有有效实际端口时,编辑弹层可打开“标签页(CDP 页面目标)”只读模态层。后台先复核 loopback `/json/version` 的浏览器类型,再读取有限的 `/json/list`;只显示 ID、类型、标题和移除 userinfo/query/fragment 的 URL,不暴露 WebSocket 地址、不建立 WebSocket、也不执行浏览器控制。读取、错误、空列表和端口/状态变化都有反馈,Escape/关闭后焦点回到入口。
|
- T-401:仅在运行中或外部已关联实例已有有效实际端口时,编辑弹层可打开“标签页(CDP 页面目标)”只读模态层。后台先复核 loopback `/json/version` 的浏览器类型,再读取有限的 `/json/list`;只显示 ID、类型、标题和移除 userinfo/query/fragment 的 URL,不暴露 WebSocket 地址、不建立 WebSocket、也不执行浏览器控制。读取、错误、空列表和端口/状态变化都有反馈,Escape/关闭后焦点回到入口。
|
||||||
- blocker:无。
|
- T-402:已规划 Windows 通知区域图标、显示主窗口、刷新已保存实例状态和显式退出协调。首版不在托盘菜单中直接操作浏览器,不改变窗口关闭语义,也不实现关闭窗口后隐藏;Windows 原生 Shell adapter、Explorer 重启恢复、图标资源与退出清理将在实施阶段完成。
|
||||||
|
- blocker:无;下一任务为 T-402。
|
||||||
|
|
||||||
## 当前目录
|
## 当前目录
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
id: T-402
|
||||||
|
title: Windows 通知区域入口与显式退出协调
|
||||||
|
phase: 4
|
||||||
|
deps: [T-303, T-305, T-307]
|
||||||
|
status: TODO
|
||||||
|
created: 2026-07-27
|
||||||
|
owner: codex
|
||||||
|
---
|
||||||
|
|
||||||
|
## 需求与背景
|
||||||
|
|
||||||
|
Chub 需要在 Windows 通知区域提供一个低干扰的长期运行入口,方便用户在浏览器实例监控期间重新显示主窗口、刷新已保存实例状态或明确退出应用。Gio `v0.10.1` 不提供通知区域 API,当前 `runWindow` 收到 `DestroyEvent` 后直接结束窗口循环,因此该功能必须以隔离的 Windows platform adapter 接入。
|
||||||
|
|
||||||
|
## 方案与边界
|
||||||
|
|
||||||
|
- 新增 Windows build-tag 的 `internal/platform/tray` adapter:使用 Shell notification-area API 和独立原生消息循环维护一个图标、Tooltip、右键菜单及 Explorer 重启后的重新注册。不得引入浏览器进程控制能力,也不得在 Gio frame 中执行 Win32 I/O。
|
||||||
|
- adapter 只发布 `TrayCommandShow`、`TrayCommandRefresh`、`TrayCommandExit`;`cmd/chub` 作为应用 coordinator 消费命令。显示窗口使用 Gio 已公开的窗口操作;刷新复用现有已保存实例快照与后台去重机制;退出通过统一应用生命周期协调器清理图标、取消监控并等待后台任务安全收束。
|
||||||
|
- 原生菜单固定为“显示 Chub”(默认项)→“刷新实例状态”→分隔线→“退出 Chub”。双击图标与默认项同效。菜单不枚举实例,不提供启动、停止、重启、删除、强制终止、CDP 或外部实例接管入口。
|
||||||
|
- `TrayState` 只携带托管运行、外部关联和需关注的计数;Tooltip 和图标状态不得出现实例名称、路径、URL、PID、端口、代理或其他敏感数据。图标资源需提供适配常用 DPI 的 16/20/24 像素版本,且图标状态不能只凭颜色传达含义。
|
||||||
|
- “退出 Chub”是应用级操作,不是停止某个浏览器。它必须沿用 `CloseOnExit` 的明确策略:仅在用户已启用且流程可安全确认时对 Chub 当前会话、可验证的托管实例发起既有优雅停止;外部关联、外部占用、未知实例绝不停止。若需要确认,先显示主窗口和明确影响数量的对话框,默认安全取消。
|
||||||
|
- 本任务不改变标题栏/Alt+F4 的关闭语义,不实现最小化或关闭窗口后隐藏到通知区域,不提供自启动或单实例激活。该行为待后续独立任务评审 Gio 的窗口消息拦截与多进程协调风险。
|
||||||
|
|
||||||
|
## 验收要点
|
||||||
|
|
||||||
|
- 自动化命令:新增 tray command/coordinator 单元测试;`go test ./...`、`go test -race ./cmd/chub ./internal/ui`、`go vet ./...`、`go build -o build/chub.exe ./cmd/chub` 通过。
|
||||||
|
- Windows smoke:运行 GUI 后通知区域出现一个 Chub 图标;双击/默认项显示并置前窗口;刷新项只检查已保存实例且重复触发被合并;退出项移除图标并按明确策略结束应用。Explorer 重启后图标自动恢复。高 DPI、键盘菜单、菜单关闭及图标创建失败均可恢复。
|
||||||
|
- 交互与无障碍:先更新 `docs/ui/browser-manager.html` 的托盘菜单模拟和 `docs/ui/README.md` 评审场景,再实现 Gio/Win32;页面内命令仍是所有托盘命令的可键盘访问等价入口。原生菜单使用具体动词,默认项为“显示 Chub”。
|
||||||
|
- 安全边界:不执行 `taskkill /IM` 或按浏览器名称的枚举/关闭;不向日志、Tooltip、菜单或 DTO 写入敏感信息;外部浏览器不因通知区域命令获得接管或关闭资格;所有 Win32 handle/回调只留在 platform adapter 内。
|
||||||
|
|
||||||
|
## 执行记录
|
||||||
|
|
||||||
|
- 状态:TODO
|
||||||
|
- 变更:已完成需求、架构、API、交互和验收边界定义;待 HTML 原型确认和代码实施。
|
||||||
|
- 验证:文档链接与 Git diff 检查待本次提交前执行。
|
||||||
|
- 阻塞:无。
|
||||||
|
- 残余风险:Gio 没有原生通知区域或关闭请求钩子;首版通过隔离 Shell adapter 降低影响面,不处理窗口关闭隐藏和单实例激活。
|
||||||
Reference in New Issue
Block a user