Chromium WebUI 深度解析:src/ui/webui/resources 的架构定位与运行机制

在 Chromium 内核开发中,WebUI 是浏览器原生 UI 的重要组成部分,它既提供了诸如 chrome://settingschrome://downloads 等页面的交互能力,又承担了浏览器安全与权限保护的重任。对于很多开发者来说,src/ui/webui/resources 目录看似只是一个"公共 JS / CSS 库",但实际上,它承载了 Chromium WebUI 的安全、运行时和基础设施职责,是 WebUI 生态的"宪法"。

本文将从历史背景、架构定位、运行机制、安全模型、以及它与业务模块的交互方式等五个层面,做一次工程级深度剖析。


一、历史与背景:为什么会有这个目录?

1️⃣ WebUI 的原始问题

Chromium 的 WebUI 页面是用 HTML / JS 实现的,但它有一个天然矛盾:

  • 运行在 Browser Process:意味着拥有极高权限。

  • 能调用 Mojo / C++ / 系统能力:比如直接操作密码、下载文件等。

  • 天然 XSS 风险:一旦 HTML 被注入恶意内容,整个浏览器都可能被攻破。

在 Chrome 30~40 年代,WebUI 页面非常"野",常见问题包括:

  • i18n 字符串直接 innerHTML 插入页面;

  • 翻译文件可能被翻译人员加入 <a><img><script> 等 HTML 标签;

  • 多语言文件由外包维护,安全审计难度大;

  • 历史上真实发生过安全事故,浏览器被打穿。

2️⃣ Chromium 的战略选择

为了解决这个安全矛盾,Chrome 团队做出了工程化的决定:

WebUI 必须被当成浏览器内核的一部分,而不是普通网页。

因此诞生了 src/ui/webui/resources

  • 定位:WebUI 的"标准库 + 安全基线 + UI 基础设施"。

  • 职责:为所有 WebUI 页面提供统一运行时、i18n 安全处理、DOM 子集约束等功能。

它不是具体业务模块,而是WebUI 的运行时基础设施


二、架构定位:它在 WebUI 中的角色

1️⃣ 它不是业务代码

src/ui/webui/resources 并不属于业务模块,例如:

  • chrome://settings

  • chrome://password-manager

  • chrome://downloads

而是所有 WebUI 页面共同依赖的 runtime。可以类比为:

类比对象 对应
C++ STL WebUI runtime
libc 浏览器 WebUI 基础层
Blink 对 DOM 的限制 WebUI 对 HTML 的限制

2️⃣ 典型目录结构

复制代码
src/ui/webui/resources/
├── js/
│   ├── parse_html_subset.js   ⭐ 安全核心
│   ├── i18n_mixin.js          ⭐ i18n 入口
│   ├── cr.js                  ⭐ 框架 glue
│   ├── util.js
├── cr_elements/               <cr-button> 等
├── css/
├── images/
  • parse_html_subset.js:WebUI 核心安全裁判。

  • i18n_mixin.js:i18n 文案加载和安全插入。

  • cr.js:模块定义和初始化 glue。

  • cr_elements:基础 WebUI 元素组件库。


三、核心机制:它是如何"裁判"的?

1️⃣ 核心设计思想

WebUI 不允许自由 HTML,只允许受控 HTML 子集。

  • parse_html_subset.js 定义白名单;

  • 任何超出范围的 HTML 会被拒绝或抛异常。

2️⃣ parse_html_subset.js 的功能

  • 允许的 tag<b> <i> <br> <p> <a> <span>

  • 允许的 attribute<a href><span class>

  • 禁止的内容<script><img>onClickonLoad、任意未知 tag

  • 禁止 style :默认禁止 style="background:url(...)"

3️⃣ 运行流程示例

业务调用链:

复制代码
i18nAdvanced
└── sanitizeInnerHtml
    └── sanitizeInnerHtmlInternal
        └── parseHtmlSubset
  • 业务模块 调用 i18nAdvanced 生成 HTML;

  • resources 强制 sanitize;

  • 超出白名单 → 抛异常。

注意:这是设计行为,不是 bug。


四、i18n 的安全模型

1️⃣ 为什么 i18n 是重点对象

i18n 字符串来自 .grdp / .xtb 文件,由非工程师翻译。历史上存在翻译文件加入 <img>javascript: 的情况,直接威胁浏览器安全。

2️⃣ i18n API 设计

API 用途
i18n() 纯文本(安全)
i18nAdvanced() 限制 HTML(经过 parse_html_subset)

3️⃣ 为什么 password_manager 常出异常

常见雷区:

  • <a target="_blank">target 不在白名单

  • <br/> → 自闭合形式

  • <span style=...> → style 禁止

  • <strong> → 不在白名单

资源层抛异常是为了集中、早期发现问题,而不是"resources 有 bug"。


五、resources 如何与业务模块交互

1️⃣ 架构模型

复制代码
Browser Process (C++)
├── WebUIController
├── WebUIMessageHandler ◄── Mojo / IPC
└── DataSource (strings)
          │
          │ JS bindings (chrome.send / mojo)
WebUI 页面(业务模块)
├── password_manager.js
├── settings.js
└── downloads.js
        ▲
        │ import / mixin
    i18nAdvanced()
    cr.js
    parse_html_subset.js
└─────────────┬──────────────┘
src/ui/webui/resources (runtime / infra)
  • 调用方向:业务 → resources

  • 资源目录不主动通信;

  • 它是 WebUI 的 runtime / 标准库。

2️⃣ 三种交互方式

1️⃣ Mixin / Base Class 注入

复制代码
export const I18nMixin = (superClass) => class extends superClass {
  i18n(id, ...args) {
    return loadTimeData.getString(id, args);
  }

  i18nAdvanced(id, ...args) {
    return sanitizeInnerHtml(
      loadTimeData.getString(id, args));
  }
};
  • 业务模块继承 mixin;

  • runtime 改变行为;

  • 编译期 + 运行期融合。

2️⃣ 全局函数 / 约定

  • sanitizeInnerHtml

  • parseHtmlSubset

  • cr.define()

  • loadTimeData

提前注入 WebUI JS 全局,可视为"系统调用接口"。

3️⃣ WebUIDataSource + JS runtime 协作

  • C++ 侧注入字符串:WebUIDataSource::AddLocalizedString

  • JS 侧通过 loadTimeData.getString() 获取;

  • i18n / i18nAdvanced 基于 resources 提供的 runtime 处理。

C++ 不直接和业务 JS 通信,resources 是中介层。


六、为什么不让业务模块直接通信?

  • 防止野生前端:自由 innerHTML → XSS 风险

  • 统一 runtime:保证安全模型一致

  • 统一通信方式:集中管理 C++ / Mojo 调用


七、和 C++ / Mojo 的关系

  • resources 不直接调用 Mojo

  • 不 import 业务接口

  • 它只提供封装、约束和防护。

业务模块需要调用 C++ / Mojo,必须走 WebUIController + WebUIMessageHandler → Mojo → resources 提供的 runtime 接口。


八、工程级总结

  • src/ui/webui/resources 是 WebUI 的"宪法",业务模块只能遵守,不能挑战。

  • 它提供 runtime / 安全裁决 / i18n 支持,但不主动通信。

  • 所有异常堆栈指向它,是"最后门卫",而不是问题根源。

  • 修改它必须谨慎,否则破坏浏览器安全模型。


九、工程建议

  • 遇到 WebUI 页面抛异常,不要改 resources;

  • 修正 业务文案 或降级 i18nAdvanced → i18n;

  • 避免非法 HTML,遵循 parse_html_subset 白名单。


十、附录:核心目录与机制复盘

文件 功能
parse_html_subset.js HTML 白名单裁决
i18n_mixin.js i18n / i18nAdvanced 封装
cr.js 模块 glue,注册全局定义
util.js 常用工具函数
cr_elements/ <cr-button> 等 WebUI 基础组件
css/ 公共样式
images/ 公共资源

调用顺序:

  1. 业务 JS 生成 HTML 文案 → i18nAdvanced()

  2. parse_html_subset.js 校验合法性

  3. sanitizeInnerHtml 处理异常

  4. 注入 DOM


十一、工程师视角结论

  • 业务模块 = 用户

  • resources = 系统调用接口 + runtime + 审查机制

  • parse_html_subset = 内核裁决

理解这一点,你才能:

  • 不再误认为 resources 是"功能模块"

  • 正确定位问题根源在业务文案或调用方式

  • 安全地扩展 WebUI 功能


🔥 工程金句
src/ui/webui/resources 是 WebUI 的宪法,业务模块只能遵守,不能挑战。

parse_html_subset.js 是 WebUI 的内核裁决,不是 bug 根源。

相关推荐
@淡 定2 小时前
Dubbo + Nacos 完整示例项目
前端·chrome·dubbo
Godspeed Zhao3 小时前
现代智能汽车中的无线技术4——蜂窝移动通信技术(3)
架构·汽车·信息与通信
想用offer打牌3 小时前
你真的懂Thread.currentThread().interrupt()吗?
java·后端·架构
左灯右行的爱情4 小时前
Kafka专辑- 整体架构
分布式·架构·kafka
萧曵 丶4 小时前
订单超时解决方案详解
面试·架构·高并发·大厂
Maiko Star4 小时前
RocketMQ的运行架构&理解RocketMQ的消息模型
架构·rocketmq·java-rocketmq
小马过河R4 小时前
混元世界模型1.5架构原理初探
人工智能·语言模型·架构·nlp
曲幽5 小时前
手把手搞定FastAPI静态文件:安全、上传与访问
css·python·fastapi·web·js·favicon·staticfiles
山上春6 小时前
Odoo 分布式单体与微服务模式深度对比研究报告
分布式·微服务·架构