不成立的理解
https://gemini.google.com/glic
如果它是父级,WebUI 反而成了它的子页面。
WebUI / privileged
这会把特权内容放进远端页面的控制范围,信任边界方向反了。
如果真这样设计,远端代码就获得了更高的父级位置,安全模型很难成立。
理解纠正 · 宿主与内容
Glic 不是把 chrome://glic 这个 WebUI 塞进
Gemini 在线页面里。方向正好相反:
Chrome 的 WebUI 宿主承载一个来自
https://gemini.google.com/glic 的远端 Web 客户端。
01 / 方向
你在 DevTools 里看到 frame 关系,并不意味着 DOM 里一定有一个
<iframe>。旧路径里的 guest 是
<webview>,新路径里的 guest 是
PrivilegedWebContents。两者都在 WebUI 或浏览器宿主的管理下。
不成立的理解
https://gemini.google.com/glic
如果它是父级,WebUI 反而成了它的子页面。
WebUI / privileged
这会把特权内容放进远端页面的控制范围,信任边界方向反了。
如果真这样设计,远端代码就获得了更高的父级位置,安全模型很难成立。
实际结构
chrome://glic
本地 HTML/CSS/JS,负责加载、错误、权限、窗口和 Mojo 桥接。
https://gemini.google.com/glic
远端产品 UI 和会话逻辑,通过注入的 Glic API 获得有限能力。
因此,WebUI 是宿主,在线页面是 guest。不是“在线页面里套 WebUI”。
02 / 两种承载路径
当前源码同时存在旧路径和新路径。它们都在承载远端 Gemini, 区别在于用哪种 Chromium 机制把 guest 放进 Glic 面板。
top-level
本地 loading / error / offline 面板、窗口控制和 guest 容器。
persist:glicpart
独立的远端 WebContents,加载 Gemini web client。
https://gemini.google.com/glic
这是更早的形态:WebUI 里创建一个 <webview>,
把远端 Gemini 作为独立 guest WebContents 加载。DevTools 会显示
一个 guest frame,但它不是普通的 HTML <iframe>。
chrome://glichttps://gemini.google.com/glicpersist:glicpartpostMessage({type: "glic-bootstrap"})WebUI 外壳 + guest 隔离远端页面在 guest 内,WebUI 永远不是它的子 iframe。
remote main content
由 Glic 独占的远端 WebContents,不是普通 tab,也不能变成 tab。
https://gemini.google.com/glic
GlicNoWebview 路径正在移除对 <webview>
的依赖。远端 Gemini 变成由 Glic 独占的
PrivilegedWebContents,本地 WebUI 则退到 overlay 层,
专门处理加载、错误和权限状态。
PrivilegedWebContentshttps://gemini.google.com/glicchrome://glic/overlay默认 profile 分区,共享 cookie jarisolated world 注入 + Mojo新路径去掉的是 <webview>,不是“把远端 UI 变成纯 WebUI”。
03 / 网络状态
在线 Gemini 不能提供完整的离线对话能力,但 Glic 的宿主和状态页面 不依赖远端 HTML。断网时,用户看到的不是整块空白,而是本地的离线、 错误和重试界面。
可用。 loading、error、offline 面板和窗口控制都在本地。
local可用。 Gemini 页面、会话和模型请求通过 HTTPS 到达远端。
network正常时主要看到 Gemini 页面;启动较慢时先看到本地 loading 骨架。
ready保留。 旧路径进入 offlinePanel;新路径显示本地 overlay。
stays不可用。 不加载远端 HTML,不能提供完整对话或模型推理。
offline可以看到离线提示和重试入口;关闭面板或等待网络恢复都不会丢失宿主。
retry旧路径监听 online 事件,把状态切回 kBeginLoad。
重新加载。 guest 需要重新建立页面、API 连接和远端会话。
reload可能重新做 cookie 同步、权限检查和加载等待;已加载的页面不会自动变成离线应用。
sync窗口 chrome、loading 骨架、错误/离线提示、重试、权限和策略提示、设置入口。
Gemini 页面、模型调用、远端会话、账号 entitlement 和服务端实验配置。
04 / 地址栏
PrivilegedWebContents 不会把 HTTPS“改名”成
chrome://glic。它只是让远端 Gemini 成为一个由 Glic
独占的 WebContents。地址栏或 DevTools 显示的是当前主内容的 URL。
看到 HTTPS 的几种情况
GlicNoWebviewContentsManager 创建 PWC 后,
直接把 https://gemini.google.com/glic
加载为这个 WebContents 的主 frame。当前 WebContents 是远端,
所以 URL 显示 HTTPS。
旧路径的顶层仍是 chrome://glic,但
<webview> 里的 guest frame 是 HTTPS。
如果你查看的是 guest、DevTools frame 或单独打开的页面,看到的也会是 HTTPS。
Glic 的浮窗和侧栏嵌入在 Chrome 的 views::WebView
里,没有自己的 omnibox。正常面板里看到的浏览器地址栏,通常来自普通 tab、
测试窗口或 DevTools 视图。
PWC 的加载与授权链路
PrivilegedWebContents::Create() 创建并独占一个
content::WebContents,不是 tab,也不能转交所有权。
它使用默认 StoragePartition,共享实时 cookie jar。
Glic 通过 NavigationController::LoadURLWithParams()
加载 GetGuestURL(profile)。主 frame 的 URL 从头到尾都是 HTTPS。
PwcNavigationThrottle 拦截主 frame 的请求、重定向和无 URL loader 的导航,
只允许策略允许的 HTTPS origin,阻止 about:blank 等绕过方式。
PwcApiBinder 只允许满足这些条件的 frame 绑定能力:
PWC 的 primary main frame、提交为 HTTPS capability origin、运行在 origin-keyed 进程。
不满足时默认拒绝,结构性违规会终止 renderer。
远端页面通过注入的 Glic API 和 Mojo 请求能力。权限由 PWC permission delegate 逐项判断,未处理的权限默认拒绝;PWC 不创建关联窗口,新窗口按策略变成无 opener 的普通 tab。
地址栏的 scheme 不是权限本身。HTTPS 说明它是远端内容; 真正的特权来自浏览器侧的导航策略、进程隔离和 capability gate。
05 / 设计动因
WebUI 是一套宿主和权限模型,不是“所有资源必须从 Chrome 本地加载”。 对 Glic 来说,把产品表面留在远端,才能同时满足迭代速度、账号体系和信任边界。
Gemini 的交互、实验和提示词经常变化。远端部署不必等待 Chrome 发版,也能和 Gemini Web 共用前端。
登录态、地区资格、订阅权益、企业策略和后端能力都在 Google 服务侧。在线客户端天然接近这些状态。
远端代码不能直接获得 chrome:// 的 WebUI bindings。它必须通过注入 API 和有限的 Mojo 接口请求能力。
同一套外壳可以承载消费者 Gemini 或 Gemini Enterprise 的 guest URL,同时保留预热、加载和错误处理的宿主逻辑。
“WebUI”描述的是 Chrome UI 的实现方式和权限上下文,不是内容的托管位置。 Glic 的选择是:外壳本地、内容远端、能力过桥。
06 / 源码证据
以下来自 Chromium main 的公开源码。实现仍在演进,尤其是
GlicNoWebview 路径,阅读时以当前分支为准。
| 文件 | 它说明了什么 |
|---|---|
| glic_ui.cc | 注册 chrome://glic WebUI,并加载本地资源。 |
| glic.html | 本地 loading、offline、error 面板和 guest 容器。 |
| webview.ts | 创建 <webview>、设置分区、加载远端 URL、发送 bootstrap。 |
| chrome_features.cc | 默认 guest URL:https://gemini.google.com/glic。 |
| glic_no_webview_contents_manager.cc | 新路径用 PrivilegedWebContents 承载远端内容,本地 overlay 处理状态。 |
| privileged_web_contents.h | PWC 承载远端内容,不是 tab,由组件独占并受策略约束。 |
| pwc_component_policy.h | 导航 allowlist 与 capability allowlist 的两层策略,以及 HTTPS 结构约束。 |
| pwc_navigation_throttle.cc | 拦截主 frame 请求、重定向和空文档导航,只允许策略内的 URL。 |
| pwc_api_binder.h | 能力 bridge 的 gate:primary main frame、HTTPS capability origin、origin-keyed 进程。 |
| glic_view.h | Glic 面板把 WebContents 放进 views::WebView,面板本身没有地址栏。 |
| glic_api_impl/README.md | 注入到 web client 的 API 通过 Mojo 与浏览器通信。 |
| webui_explainer.md | Chromium 对 WebUI 的定义和特权 bindings 说明。 |
chrome://glic,guest frame 是 https://gemini.google.com/glic。chrome://glic/overlay。gemini.google.com 的请求,是正常现象。chrome://glic/internals 可以观察 WebUI、guest 和 WebClient 状态。