fix(desktop): 按 owner 隔离 main-view 和 settings WebView - #3414
Conversation
Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b746f44bc9
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
| Filename | Overview |
|---|---|
| apps/desktop/src/main/cindy-brain/ghostWebviewPartition.ts | 新增 Main 权威的 owner-scoped partition 派生与 Renderer claim 解析,非法或无 owner 状态均 fail-closed。 |
| apps/desktop/src/main/cindy-brain/runtime/electronSandboxAdapter.ts | 将协议注册绑定到 owner partition,并对失效 owner、权限、下载和直接网络访问实施拒绝策略。 |
| apps/desktop/src/main/webview-security.ts | attach 时覆盖实际 Electron partition,捕获 owner,并为旧 guest 的手势和导航安装失效检查。 |
| apps/desktop/src/renderer/cindy-brain/GhostSettingsWebview.tsx | settings WebView 按 owner 重挂,并使截图与高度状态使用 owner 作用域且阻止卸载后的异步写入。 |
| apps/desktop/src/renderer/cindy-brain/ghostSettingsSnapshot.ts | settings 快照升级为 owner 分桶的 v2 key,并停止读取旧的无 owner 快照。 |
| apps/desktop/src/main/cindy-brain/ghostExternalLinkNavigation.ts | 外链确认和打开操作在各异步边界前后验证捕获的 owner,避免旧 guest 在切换后继续执行。 |
| apps/desktop/src/main/cindy-brain/ghostPreviewNavigation.ts | 预览查询在 provider 调用前后验证 owner 与 WebContents 状态,避免旧结果推送给新 owner。 |
| apps/desktop/src/main/ghost-panel-window/controller.ts | owner commit 时销毁独立插件窗口并清除 lastOpen,同时保留 detached 偏好。 |
Sequence Diagram
sequenceDiagram
participant R as Renderer
participant M as Electron Main
participant S as Owner Session
participant G as WebView Guest
R->>M: 提交 ghost partition claim
M->>M: 读取当前 mode + dataOwnerId
M->>S: 创建或复用 owner-scoped partition
M->>M: 覆盖 Renderer partition claim
M->>G: 核准 attach 并捕获 owner
G->>S: 请求 cindy-ghost:// 资源
S->>S: 校验当前 owner 与协议作用域
alt owner 仍有效
S-->>G: 返回插件资源
else owner 已变化
S-->>G: 403
M->>G: 拒绝旧 guest 导航及异步副作用
end
Reviews (3): Last reviewed commit: "fix(desktop): close Ghost panels on owne..." | Re-trigger Greptile
|
@fmfsaisai 👋 这个 PR 还有 1 条 review conversation 没 resolve(apps/desktop/src/main/cindy-brain/runtime/electronSandboxAdapter.ts),auto-review 因此暂时跳过、没法继续审查 / 合并。 如果你已经按评论改完或回应了,请到对应 thread 上点 Resolve conversation;全部 resolve 后,下一轮 auto-review 会自动重新审查这个 PR。 |
|
这个 PR 改到了 Ghost WebView 的 owner 隔离,同时碰到产品 UI、安全敏感路径和插件基座,已进入维护者确认。 请维护者直接在本 PR 上 Approve;若要改,Request Changes 即可,作者改完后再 Approve。讨论记录在 #3415。 |
|
命中 UI 路径(apps/desktop/src/renderer/cindy-brain/GhostSettingsWebview.tsx / apps/desktop/src/renderer/cindy-brain/ghostPanels.tsx / apps/desktop/src/renderer/cindy-brain/ghostSettingsSnapshot.ts)但 description 未附界面效果证据——建议补充改动后效果:截图/录屏,或改动后界面的 HTML 页面(```html 代码块、.html 附件或在线预览链接),便于确认界面符合 DESIGN.md 设计规范 |
Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 63e482169a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| // owner B 提交后,owner A 的旧 guest 仍可能短暂存活并新发请求。 | ||
| // 在 URL 路由、body 读取和任何 provider 调用前拒绝旧 Session;已经 | ||
| // 进入 handler 的请求不在这里取消或排空。 | ||
| if (!isGhostProtocolOwnerActive(owner)) { |
There was a problem hiding this comment.
当前校验只发生在进入 protocol handler 时;如果 A 的 /secrets、/oauth 或 /connections 请求先通过这里,随后在 readBodyText()、GH CLI 探测、OAuth 流程或确认弹窗的 await 期间切换到 B,后续 storeGhostSecret 等调用会按全局当前 owner 解析并读写 B 的存储。与已有评论所述“切换后新发请求”不同,新的证据是这里明确允许已进入 handler 的请求继续执行,而这些端点存在跨 owner 切换窗口的异步副作用;应在每个异步继续点及最终读写前重验捕获的 owner,或把捕获的 owner 显式传入存储层。
AGENTS.md reference: AGENTS.md:L30-L31
Useful? React with 👍 / 👎.
| params.partition = resolved.partition; | ||
| webPreferences.partition = resolved.partition; |
There was a problem hiding this comment.
把 guest 固定到 attach 时的 owner partition 后,已打开或隐藏复用的独立插件面板在账号切换时不会自动获得新分区:轻量 ghost-panel-window-entry.tsx 没有 AuthProvider,而 GhostPanelWindowsController.reconcile() 对 B 中仍存在且可分离的同 id 插件直接保留原 BrowserWindow。因此旧 guest 会继续绑定 A,新的协议守卫持续返回 403,面板直到用户合并、重新分离或重启应用前都不可用;owner commit 时应通过现有 controller 销毁并按新 owner 重建这些窗口。
AGENTS.md reference: AGENTS.md:L32-L35
Useful? React with 👍 / 👎.
…leanup-20260825 Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
Signed-off-by: fmfsaisai <fmfsaisai@gmail.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6de8282808
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const { windows } = this.deps.settings.read(); | ||
| this.destroyAllWindows(); | ||
| for (const [ghostId, entry] of Object.entries(windows)) { | ||
| if (entry.lastOpen) this.deps.settings.patchEntry(ghostId, { lastOpen: false }); |
There was a problem hiding this comment.
当 A 有一个已抽离面板且 B 也安装了同 id 插件时,这里销毁窗口后只把 lastOpen 改为 false,却保留了进程级共享的 detached: true;B 的 reconcile() 会因插件仍可抽离而保留该条目,LayoutRoot 又会持续过滤所有 detached 面板。仓库搜索显示重新设为 detached 的唯一入口位于已经被隐藏的 GhostPanel 内,因此 B 既看不到停靠面板,也没有独立窗口或恢复入口,只能重启客户端;owner 切换时应同时清除 detached,或为新 owner 重建可访问的窗口状态。
Useful? React with 👍 / 👎.
|
@fmfsaisai 👋 这个 PR 还有 3 条 review conversation 没 resolve(apps/desktop/src/main/cindy-brain/runtime/electronSandboxAdapter.ts / apps/desktop/src/main/webview-security.ts / apps/desktop/src/main/ghost-panel-window/controller.ts),auto-review 因此暂时跳过、没法继续审查 / 合并。 如果你已经按评论改完或回应了,请到对应 thread 上点 Resolve conversation;全部 resolve 后,下一轮 auto-review 会自动重新审查这个 PR。 |
这次改了什么
摘要
旧 PR #3370 的方案扩大到了账号与协议时序,因此已关闭。本 PR 按收窄后的目标重做,清理 main-view/settings WebView 与独立 Ghost panel 在 data owner 变化后可能残留的 guest session、DOM 与本地状态。
具体包括:
mode + dataOwnerId派生非持久 owner partition,并覆盖 Renderer 提交的 partition claim。协议注册复用同一个 owner 快照;owner 切换完成后,旧 Session 新进入的cindy-ghost://请求会在 URL 路由、body 读取和业务 provider 之前返回 403。mode或dataOwnerId真变化时同步销毁 visible、hidden、prewarmed 独立 Ghost panel 窗口;保留 detached 偏好、把打开状态置为关闭,不在新 owner 下自动恢复,用户下次主动打开时创建新 Session。变更类型
feat新功能fix缺陷修复refactor/perf重构或性能优化docs/test/chore文档、测试或工程维护范围
UI 变化
不涉及视觉样式、布局、文案或动效变化;只调整 WebView owner 生命周期。继续沿用
docs/design-rules/DESIGN.md的 Light/Dark 双模式与语义 token 约束,未新增颜色或单主题分支。docs/design-rules/DESIGN.md双模式交付要求;本 PR 无视觉改动。怎么验证的
自动验证
本地还额外运行了完整
pnpm test:unit。它在当前 macOS 环境中未全绿:codexExecFunctionAdapter.e2e.test.ts第 329 行期望 completedcommandExecution,实际 completed items 只有userMessage与agentMessage。该失败已在完全干净的最新origin/main8c53ec069和原始 #3256 合并提交bffe68140上同样复现,不是本 PR 引入。GitHub CI 仍会在 Linux/Windows 运行完整单测;这里不声称完整test:unit通过。手工验证
Tester 已对同步前的同一收窄 diff 完成真实 Electron 回归:
FAIL=0。BLOCKED=0。已用普通 merge 同步到
origin/mainc0810adc3,无冲突;本次还新增了独立 panel 关闭行为,因此没有伪称同步或 P2 修复后重新跑过该 E2E。未执行的验证
风险
风险分类
影响与回滚
提交前检查
git commit -s,见 DCO)