GLIC / ARCHITECTURE NOTE
Chromium main 2026-10-27 Gemini in Chrome

理解纠正 · 宿主与内容

WebUI 是壳,
Gemini 是客。

Glic 不是把 chrome://glic 这个 WebUI 塞进 Gemini 在线页面里。方向正好相反: Chrome 的 WebUI 宿主承载一个来自 https://gemini.google.com/glic 的远端 Web 客户端。

01 / 方向

WebUI 是父级,在线页面是 guest

你在 DevTools 里看到 frame 关系,并不意味着 DOM 里一定有一个 <iframe>。旧路径里的 guest 是 <webview>,新路径里的 guest 是 PrivilegedWebContents。两者都在 WebUI 或浏览器宿主的管理下。

不成立的理解

远端 Gemini 页面 parent
https://gemini.google.com/glic 如果它是父级,WebUI 反而成了它的子页面。
内嵌 iframe
chrome://glic child
WebUI / privileged 这会把特权内容放进远端页面的控制范围,信任边界方向反了。

如果真这样设计,远端代码就获得了更高的父级位置,安全模型很难成立。

实际结构

Glic WebUI 外壳 trusted
chrome://glic 本地 HTML/CSS/JS,负责加载、错误、权限、窗口和 Mojo 桥接。
guest WebContents
Gemini Web 客户端 remote
https://gemini.google.com/glic 远端产品 UI 和会话逻辑,通过注入的 Glic API 获得有限能力。

因此,WebUI 是宿主,在线页面是 guest。不是“在线页面里套 WebUI”。

02 / 两种承载路径

同一个产品,两种宿主形态

当前源码同时存在旧路径和新路径。它们都在承载远端 Gemini, 区别在于用哪种 Chromium 机制把 guest 放进 Glic 面板。

Browser process Glic service / host
Mojo + 生命周期管理
chrome://glic WebUI top-level

本地 loading / error / offline 面板、窗口控制和 guest 容器。

<webview> guest persist:glicpart

独立的远端 WebContents,加载 Gemini web client。

https://gemini.google.com/glic
顶层 URL 仍是 chrome://glic

WebUI 外壳 + <webview> guest

这是更早的形态:WebUI 里创建一个 <webview>, 把远端 Gemini 作为独立 guest WebContents 加载。DevTools 会显示 一个 guest frame,但它不是普通的 HTML <iframe>。

  • 顶层宿主chrome://glic
  • 远端 URLhttps://gemini.google.com/glic
  • 存储分区persist:glicpart
  • API 注入postMessage({type: "glic-bootstrap"})
  • 权限模型WebUI 外壳 + guest 隔离

远端页面在 guest 内,WebUI 永远不是它的子 iframe。

03 / 网络状态

断网时,本地壳还在工作

在线 Gemini 不能提供完整的离线对话能力,但 Glic 的宿主和状态页面 不依赖远端 HTML。断网时,用户看到的不是整块空白,而是本地的离线、 错误和重试界面。

正常加载

remote available
Browser Glic host
WebUI / PWC 本地宿主
Gemini guest gemini.google.com
本地壳

可用。 loading、error、offline 面板和窗口控制都在本地。

local
远端 guest

可用。 Gemini 页面、会话和模型请求通过 HTTPS 到达远端。

network
用户感受

正常时主要看到 Gemini 页面;启动较慢时先看到本地 loading 骨架。

ready

本地仍然可用的部分

窗口 chrome、loading 骨架、错误/离线提示、重试、权限和策略提示、设置入口。

必须依赖网络的部分

Gemini 页面、模型调用、远端会话、账号 entitlement 和服务端实验配置。

04 / 地址栏

地址栏显示什么,取决于当前 WebContents

PrivilegedWebContents 不会把 HTTPS“改名”成 chrome://glic。它只是让远端 Gemini 成为一个由 Glic 独占的 WebContents。地址栏或 DevTools 显示的是当前主内容的 URL。

看到 HTTPS 的几种情况

01

PWC 主内容

GlicNoWebviewContentsManager 创建 PWC 后, 直接把 https://gemini.google.com/glic 加载为这个 WebContents 的主 frame。当前 WebContents 是远端, 所以 URL 显示 HTTPS。

02

旧路径的 guest

旧路径的顶层仍是 chrome://glic,但 <webview> 里的 guest frame 是 HTTPS。 如果你查看的是 guest、DevTools frame 或单独打开的页面,看到的也会是 HTTPS。

03

普通 Glic 面板没有地址栏

Glic 的浮窗和侧栏嵌入在 Chrome 的 views::WebView 里,没有自己的 omnibox。正常面板里看到的浏览器地址栏,通常来自普通 tab、 测试窗口或 DevTools 视图。

PWC 的加载与授权链路

01

创建专用 WebContents

PrivilegedWebContents::Create() 创建并独占一个 content::WebContents,不是 tab,也不能转交所有权。 它使用默认 StoragePartition,共享实时 cookie jar。

02

加载远端 URL

Glic 通过 NavigationController::LoadURLWithParams() 加载 GetGuestURL(profile)。主 frame 的 URL 从头到尾都是 HTTPS。

03

导航白名单

PwcNavigationThrottle 拦截主 frame 的请求、重定向和无 URL loader 的导航, 只允许策略允许的 HTTPS origin,阻止 about:blank 等绕过方式。

04

能力 gate

PwcApiBinder 只允许满足这些条件的 frame 绑定能力: PWC 的 primary main frame、提交为 HTTPS capability origin、运行在 origin-keyed 进程。 不满足时默认拒绝,结构性违规会终止 renderer。

05

API、权限和窗口

远端页面通过注入的 Glic API 和 Mojo 请求能力。权限由 PWC permission delegate 逐项判断,未处理的权限默认拒绝;PWC 不创建关联窗口,新窗口按策略变成无 opener 的普通 tab。

地址栏的 scheme 不是权限本身。HTTPS 说明它是远端内容; 真正的特权来自浏览器侧的导航策略、进程隔离和 capability gate。

05 / 设计动因

为什么不把所有东西都做成 WebUI

WebUI 是一套宿主和权限模型,不是“所有资源必须从 Chrome 本地加载”。 对 Glic 来说,把产品表面留在远端,才能同时满足迭代速度、账号体系和信任边界。

01

产品迭代速度

Gemini 的交互、实验和提示词经常变化。远端部署不必等待 Chrome 发版,也能和 Gemini Web 共用前端。

02

账号、订阅与策略在服务端

登录态、地区资格、订阅权益、企业策略和后端能力都在 Google 服务侧。在线客户端天然接近这些状态。

03

信任边界

远端代码不能直接获得 chrome:// 的 WebUI bindings。它必须通过注入 API 和有限的 Mojo 接口请求能力。

04

Provider 复用与启动性能

同一套外壳可以承载消费者 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 说明。

在 DevTools 里怎么判断

  1. 旧路径:顶层是 chrome://glic,guest frame 是 https://gemini.google.com/glic。
  2. 新路径:主内容 URL 是远端 Gemini,本地 overlay 是 chrome://glic/overlay。
  3. Network 面板出现发往 gemini.google.com 的请求,是正常现象。
  4. 看 chrome://glic/internals 可以观察 WebUI、guest 和 WebClient 状态。