当前位置: 首页 > ds >正文

从 GRIT 到 WebUI:Chromium 内置资源加载与前端展示的完整链路解析

一、前言

在 Chromium 内核开发过程中,国际化字符串的加载与 WebUI 内置页面的展示,是两个经常被提及但又容易被忽视的核心环节。

  • 一方面,GRIT(Google Resource and Internationalization Tool)承担了整个字符串资源编译、打包和加载的任务,它决定了开发者在 C++ 代码或者 WebUI 前端中看到的 IDS_XXX 字符串是如何被替换成实际文字的。

  • 另一方面,WebUI 内置页(如 chrome://settings/chrome://newtab/)的展示机制,涉及到 C++ 后端和前端 HTML/JS 的对接,GRIT 中的资源如何最终呈现在用户眼前,也是一个完整的链路。

本篇文章将深入剖析 GRIT 的编译链路、运行时加载机制、多语言切换原理、资源 ID 分配,再结合 WebUI 内置页的对接机制,展示一个完整的前端展示流程。

阅读完这篇文章,你将能够回答:

  1. .grd 文件和 .xtb 文件有什么区别?

  2. .grd 如何编译成 .pak 文件,运行时又如何被加载?

  3. 多语言切换的机制是怎样的?

  4. WebUI 内置页如何与这些资源对接?

  5. 一个完整的字符串从 定义 → 编译 → 加载 → 前端展示 的链路是什么?


二、GRIT 资源体系介绍

1. 什么是 GRIT

GRIT,全称 Google Resource and Internationalization Tool,是 Chromium 用来管理字符串、图片、图标等 UI 资源的工具。它的主要职责是:

  • 资源定义:通过 .grd 文件声明一组资源(通常是字符串)。

  • 国际化支持:通过 .xtb 文件为不同语言提供翻译。

  • 资源编译:在构建过程中生成 .h 头文件和 .pak 打包文件。

  • 运行时加载:通过 ui::ResourceBundlel10n_util API 在代码中加载资源。


2. .grd 文件

.grd 文件是资源的“清单文件”,开发者在其中定义需要本地化的字符串,例如:

<message name="IDS_BACKGROUND_APP_INSTALLED_BALLOON_BODY" desc="Balloon content"> <ph name="APP_NAME">$1<ex>Background App</ex></ph> will launch at system startup and continue to run in the background even once you've closed all other <ph name="PRODUCT_NAME">$2<ex>Google Chrome</ex></ph> windows. </message> 

特点:

  • name 定义了字符串 ID(如 IDS_BACKGROUND_APP_INSTALLED_BALLOON_BODY)。

  • desc 用于描述字符串用途,方便翻译。

  • <ph> 表示参数占位符。


3. .xtb 文件

.xtb 文件是 翻译文件,用于为 .grd 中的字符串提供多语言版本。

例如 en-US.xtbzh-CN.xtb,它们内部存放着 <translation> 节点,对应不同语言的翻译。


4. .pak 文件

在编译阶段,GRIT 工具会把 .grd + .xtb 合并,最终生成 .pak 文件。

.pak 文件是一个二进制资源包,存放了 ID → 文本 的映射关系。

例如:

  • IDS_BACKGROUND_APP_INSTALLED_BALLOON_BODY (id=12345)"某某应用将在系统启动时运行"


三、GRIT 的编译流程

我们来看字符串是如何从 .grd 最终进入到 .pak 的。

1. .grd.h

在 GN 构建过程中,.grd 文件会通过 grit.py 工具转换成 C++ 头文件,生成的 .h 文件包含一系列 #define 宏:

#define IDS_BACKGROUND_APP_INSTALLED_BALLOON_BODY 12345 

这样,C++ 代码中使用 IDS_BACKGROUND_APP_INSTALLED_BALLOON_BODY 时,实际上就是在使用 整型 ID


2. .grd + .xtb.pak

构建时,GRIT 工具会:

  • 读取 .grd 中定义的 ID。

  • 根据语言选择,加载对应 .xtb 文件翻译。

  • 生成 .pak 文件,将 ID 和对应的翻译文本打包进去。

例如:

pak 文件 ├── 12345 → "应用将在系统启动时运行" (中文) ├── 12345 → "The app will launch at system startup" (英文) 

3. .pak 文件的安装位置

不同平台下,Chromium 会把 .pak 文件放在:

  • Windows: chrome.pak / resources.pak

  • Linux: out/Default/locales/zh-CN.pak

  • macOS: Chromium.app/Contents/Resources/zh-CN.pak


四、运行时加载机制

1. ui::ResourceBundle

运行时,Chromium 通过 ui::ResourceBundle 加载 .pak 文件。

ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); rb.AddDataPackFromPath(locale_path, ui::SCALE_FACTOR_NONE); 
  • AddDataPackFromPath 会把 .pak 文件加载到内存。

  • 内部使用一个 ResourceMap 存放 ID → 文本的映射。


2. l10n_util API

开发者在 C++ 代码中使用 l10n_util::GetStringUTF16(id) 来获取字符串:

base::string16 text = l10n_util::GetStringUTF16( IDS_BACKGROUND_APP_INSTALLED_BALLOON_BODY); 

流程是:

  • GetStringUTF16 → 查询 ui::ResourceBundle → 找到 ID 对应的文本。

  • 返回 std::u16string,供 UI 展示。


3. 多语言切换

Chromium 的多语言切换依赖 Locale,即系统语言或者浏览器启动参数:--lang=zh-CN

  • 启动时,ResourceBundle::InitSharedInstanceWithLocale 会选择对应语言的 .pak 文件。

  • 当用户在设置里切换语言时,浏览器需要重启,重新加载另一套 .pak


4. 资源 ID 的编译期分配

值得注意的是,ID 是在编译期固定的整数

例如:

#define IDS_HELLO_WORLD 6001 

无论语言怎么切换,IDS_HELLO_WORLD 始终是 6001,只有 .pak 文件里绑定的翻译会变化。


五、WebUI 内置页的前端对接

字符串加载只是第一步,最终还需要在 WebUI 页里展示。

1. 内置页 WebUI 概念

  • 内置页的访问方式是 chrome://xxx/

  • 底层由 WebUIController 负责加载页面。

  • 前端通常是 HTML + JS + CSS,存放在 resources/ 目录。


2. 字符串注入

C++ 后端会把 .pak 中的字符串传递给前端。常见方式是 LoadTimeData

webui::LocalizedString localized_strings[] = { {"appInstalledBalloonBody", IDS_BACKGROUND_APP_INSTALLED_BALLOON_BODY}, }; AddLocalizedStrings(source, localized_strings); 

这样,前端 HTML 就能通过:

const text = loadTimeData.getString('appInstalledBalloonBody'); 

拿到对应的字符串。


3. 资源绑定流程

整体链路如下:

  1. .grd 定义字符串。

  2. 编译生成 .pak

  3. 运行时 ResourceBundle 加载 .pak

  4. WebUIDataSourceAddLocalizedStrings 注入到前端。

  5. 前端 loadTimeData.getString() 使用。


4. 实际案例

比如 新标签页(New Tab Page, NTP)

  • C++ 端:

    source->AddLocalizedString("title", IDS_NEW_TAB_TITLE); 
  • 前端端:

    <h1 id="title"></h1> <script> document.getElementById("title").textContent = loadTimeData.getString('title'); </script> 

这样,最终 <h1> 会显示 "新标签页""New Tab"


六、GRIT + WebUI 的完整链路

结合上面的分析,我们得到一个完整链路:

  1. 开发者定义

    • .grd 文件中声明字符串 ID。

  2. 构建编译

    • .grd 生成 .h,定义整数 ID。

    • .xtb 翻译合并,生成 .pak

  3. 运行时加载

    • ResourceBundle 加载 .pak

    • l10n_util 根据 ID 获取字符串。

  4. WebUI 注入

    • C++ 后端使用 AddLocalizedStrings 注入前端。

    • 前端用 loadTimeData 获取并展示。


七、对比总结

阶段输入输出工具/接口
编译前.grd / .xtb.h / .pakgrit.py
编译后.pakID → 文本ResourceBundle
运行时ID文本l10n_util::GetStringUTF16
WebUI文本页面展示loadTimeData.getString

八、结语

GRIT 与 WebUI 的结合,是 Chromium 国际化 + 内置页面展示 的关键路径。

  • .grd 文件解决了资源声明与 ID 分配;

  • .xtb 文件提供了多语言翻译支持;

  • .pak 文件把不同语言打包成可分发资源;

  • ui::ResourceBundle 在运行时统一加载;

  • WebUI 内置页通过 AddLocalizedStringsloadTimeData 实现最终展示。

掌握这条链路后,你不仅能理解 字符串是如何出现在页面上的,还能在调试 WebUI 内置页时快速定位问题(如字符串丢失、多语言未生效等)。

http://www.xdnf.cn/news/19057.html

相关文章:

  • AI Agent 发展趋势与架构演进
  • 稳敏双态融合架构--架构师的练就
  • 【MES】工业4.0智能制造数字化工厂(数字车间、MES、ERP)解决方案:智能工厂体系架构、系统集成以及智能设计、生产、管理、仓储物流等
  • uvloop深度实践:从原理到高性能异步应用实战
  • http请求能支持多大内容的请求
  • 通义万相音频驱动视频模型Wan2.2-S2V重磅开源
  • 安卓接入通义千问AI的实现记录
  • 欧盟《人工智能法案》生效一年主要实施进展概览(二)
  • React 组件命名规范:为什么必须大写首字母蛊傲
  • 【Datawhale之Happy-LLM】Encoder-only模型篇 task05精华~
  • 计算神经科学数学建模编程深度前沿方向研究(下)
  • 医疗AI时代的生物医学Go编程:高性能计算与精准医疗的案例分析(一)
  • 卷积神经网络CNN
  • Xposed框架实战指南:从原理到你的第一个模块
  • 面试之JVM
  • Java并发编程深度解析:从互斥锁到StampedLock的高性能锁优化之路
  • 计算机视觉:从 “看见” 到 “理解”,解锁机器感知世界的密码
  • 嵌入式(day34) http协议
  • 快速了解卷积神经网络
  • 【软考论文】论DevOps及其应用
  • C#由Dictionary不正确释放造成的内存泄漏问题与GC代系
  • 红黑树下探玄机:C++ mapmultimap 的幕后之旅
  • Java大厂面试实录:从Spring Boot到Kubernetes的全链路技术突围
  • 【数据结构】单链表详解
  • Linux系统网络管理学习.2
  • Wireshark捕获数据的四种层次
  • IUV5G专网排障(下)
  • git submodule的基本使用
  • 【软考论文】论领域驱动开发方法(DDD)的应用
  • 为什么的中小企业很难承受“大型系统”的成本