Titanium Browser 补丁机制深度剖析:patch.sh 如何用 100+ 条 sed 规则魔改 Chromium 源码
【免费下载链接】android-titanium-browserSecure open-source Android browser with support for extensions项目地址: https://gitcode.com/gh_mirrors/an/android-titanium-browser
Titanium Browser 是一款基于 Chromium 的开源 Android 浏览器,主打安全、开源与桌面级扩展支持。它的核心补丁机制藏在一份 patch.sh 脚本里:不维护完整的 fork 代码树,而是用近百条(for 循环展开后接近 100 条)sed规则,对 Chromium 上游源码做"外科手术式"的定点修改,从而在手机上装扩展、开桌面模式、解锁实验特性。这篇文章带你拆解这套补丁机制的设计思路与每一类规则的具体用途。
一、什么是"不 fork 代码"的补丁机制?
Chromium 源码动辄上亿行,完整 fork 后每次跟上游都是噩梦。Titanium Browser 的策略是分层叠加,README.md 里的实现流程图清晰地展示了三层结构:
| 层次 | 位置 | 职责 |
|---|---|---|
| Vanadium 通用补丁 | vanadium/ | 大批量.patch文件,负责隐私与安全加固 |
| 补丁脚本 | patch.sh | 100+ 条 sed 规则,做细粒度功能开关与体验修复 |
| 构建配置 | args.gn | GN 构建参数,决定编译成什么形态的浏览器 |
patch.sh的特点:规则即注释。每条sed后面往往跟着一行# 用途备注(如# scheme guard、# virt、# ntp),整份脚本就是一份可读性极高的"修改清单",新人也能快速看懂它到底动了 Chromium 的哪些地方。
二、读懂一条 sed 规则:三种基本招式
sed是文本流编辑器,脚本中 80 余条独立sed -i命令(另有 for 循环批量生成的规则)主要用三种写法,理解它们就能读懂整个机制:
- 字符串替换
s|旧文本|新文本|—— 最常用。例如把某处判断条件整体改写,让原本被禁用的功能变为放行; - 删除行
/匹配模式/d—— 干脆利落地删掉不想要的代码行,patch.sh 第 20 行 就是这样删除语言设置页的一个偏好项的; - 插入行
/匹配模式/a\新代码—— 在锚点行后面"塞"进一段新逻辑,第 76 行 就是往下载校验函数里插入了一段允许从第三方扩展商店安装的白名单判断。
💡 这种"锚点定位 + 文本替换"的方式对版本漂移有天然容错:只要上游代码里那个锚点字符串还在,规则就能命中,比维护大段 diff 的 patch 文件更抗漂移。
三、这 100+ 条规则到底改了什么?
3.1 扩展支持:让桌面扩展跑在手机上 🧩
这是 patch.sh 的重头戏,也是浏览器能装 uBlock Origin 等扩展的根本原因,相关规则几乎都集中在# ext:注释分组下:
- 复活 Manifest V2:把 MV2 弃用状态从"硬性禁用"改回
kNone,并将测试开关g_allow_mv2_for_testing置为true,让旧扩展可以安装(patch.sh#L71-L73); - 开放商店外安装:往
download_crx_util.cc里插入一段逻辑,允许从 Opera、Edge 等第三方扩展市场下载.crx(patch.sh#L76); - 工具栏与弹窗:在 XML 布局里插入扩展按钮占位、把弹窗锚点从按钮改为容器视图、手机上让弹窗直接占满全屏(patch.sh#L79-L101);
- 隐私窗口支持:把扩展进程与无痕模式的绑定判断强制放行,让扩展可以在 Incognito 下运行(patch.sh#L111-L112);
- 本地化与加载修复:修复扩展
locales目录以content://URI 打开时路径拼接失败的问题,并跳过安装对话框的父窗口断言(patch.sh#L118-L128)。
上面就是补丁生效后的实际效果:手机浏览器里出现了完整的chrome://extensions管理页,扩展的加载、卸载、详情一应俱全。
3.2 桌面模式与特性解锁 🚀
构建参数 args.gn 第 2 行 设置了is_desktop_android = true,patch.sh 则负责把"桌面形态"真正用起来:
- 批量开启特性:往
chrome_browser_field_trials.cc的桌面特性覆盖块中一次性插入 10 个EnableFeature,包括底部导航栏、画中画、屏幕共享、启动时加载全部标签页等(patch.sh#L35-L48); - 给实验旗标"续命":Chromium 的
chrome://flags实验项到期会自动失效,脚本用一个 for 循环把 10 个实验旗标的expiry_milestone批量改为-1(永不过期),循环一次展开就是 10 条规则(patch.sh#L29-L31); - 地址栏站点搜索:把
kOmniboxSiteSearch从"测试启用/默认关闭"改成"默认启用",让地址栏支持直接搜站内内容(patch.sh#L32-L33); - 开发者入口:强制显示开发者菜单与 DevTools 入口,方便调试扩展(patch.sh#L54-L58)。
3.3 移动端体验细节打磨 🎨
- 扩展页自适应:给
extensions.html注入viewportmeta 标签,把扩展卡片宽度、工具栏输入框从固定像素改成96%,让chrome://extensions在手机竖屏下不再出现横向滚动(patch.sh#L64-L68); - 协议守卫:在启动意图分发链路上插入
URLUtil.isNetworkUrl检查,防止非网络协议(如恶意intent://)劫持打开(patch.sh#L23-L25); - 视频自动播放:直接屏蔽渲染进程侧的自动播放判断,减少移动端视频"动不了"的情况(patch.sh#L61);
- PDF 打开支持:往
AndroidManifest.xml注入application/pdfMIME 类型,让浏览器可以直接接管 PDF 文件(patch.sh#L7)。
3.4 上游 Bug 修复 🐛
脚本中还有一批标注了crbug.com编号的定点修复,说明补丁机制同样承担"上游还没修"的问题:
- 无痕窗口下标签页列表的use-after-free崩溃:新增
HasLiveWebContentsForBrowserContext检查,销毁 OTR Profile 前确认无存活的 WebContents(patch.sh#L156-L162); - 无痕模式返回键行为错误(patch.sh#L151);
- API 31 下混合 Profile 类型导致的兼容问题(patch.sh#L165-L166);
- 存储访问框架(SAF)打开未打包扩展的树形路径兼容(patch.sh#L148)。
3.5 品牌定制:连图标颜色都是"算"出来的 🎨
品牌层同样靠脚本驱动:AndroidManifest.xml注入extractNativeLibs="false"以加快安装(patch.sh#L6);而应用图标则更巧妙——res/icon.sh 用 ImageMagick 从原始 PNG 中采样出深/中/浅三个色值,再用sed把 res/icon.svg 里的占位色号批量替换掉,最终渲染出与品牌色一致的主题化图标。一条脚本链,实现了"换色不换图"。
四、执行流程:版本判断 → 打补丁 → 打标记
补丁脚本的运行时行为由 common.sh 提供支撑:
SCRIPT_DIR定位脚本目录,保证路径可移植;- 版本分支:
version_lt函数(common.sh#L27-L29)比较 Chromium 版本,patch.sh 据此对新旧版本执行不同的锚点规则——比如新标签页(NTP)覆盖判断在 152 版本前后的源码写法不同,第 131~136 行 就是为这种差异准备的 if/else 分支; - 扩展打包:extensions/ 目录把内置扩展打成
bundled.json索引并注入构建(extensions/BUILD.gn),运行时由 extensions/stage_bundled_extensions.inc 读取 APK 内资源、解压到扩展目录并写入偏好,配合 patch.sh 第 13~17 行 对BUILD.gn和external_pref_loader.cc的注入完成"出厂预装"; - 完成标记:最后一行
export PATCHED=1(patch.sh#L168),让构建系统感知补丁已生效,防止重复执行。
五、为什么选 sed,而不是传统 patch 文件?
对比一下就明白了:
- 大改动用 patch,小改动用 sed:Vanadium 层用
patches/*.patch承载成块的新功能代码,patch.sh 只负责"改一行、删一行、插一段"级别的修改,职责边界清晰; - 可审查性极强:每条规则一行 + 注释,代码评审时 10 分钟就能看完全部改动意图;
- 抗版本漂移:锚点字符串命中即成功,失败时
sed静默跳过,配合version_lt分支,跟上游升级的成本极低; - 构建即文档:脚本本身不需要任何解释文档,它就是 Titanium Browser 相对上游的全部差异。
小结
📌 一句话总结:Titanium Browser 的patch.sh用近百条可注释、可审查、抗漂移的 sed 规则,把"手机上装扩展、开桌面模式、修上游 Bug"这类需求变成了 168 行 shell 脚本。对想魔改 Chromium 却不敢 fork 百万行源码的开发者来说,这套"补丁脚本化"的思路非常值得借鉴——改代码之前,先想清楚能不能只改那一行。
项目采用 LICENSE 协议开源,如果你也想动手构建,仓库提供了完整的构建脚本与 args.gn 配置,照着 CI 流程即可在 Ubuntu 上编译出签名 APK。
【免费下载链接】android-titanium-browserSecure open-source Android browser with support for extensions项目地址: https://gitcode.com/gh_mirrors/an/android-titanium-browser
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考