
看到 camofox-browser 这个项目名用在浏览器上有意思的是第一反应很容易联想到 Firefox 火狐毕竟 fox 就在名字里。camofox 是我自己维护的一个基于 Firefox 的定制浏览器项目代号里的 camo 取的是伪装、低调、不张扬的意思整个项目想解决的问题也很简单现在主流的浏览器默认配置太“重”遥测、推荐、个性化广告跟踪一个不少普通用户根本分不清哪些开关该关而真正关注隐私、效率的群体又需要一套开箱即用的默认值不想每次重装系统后都花半小时去 about:config 里翻选项。这个项目不重写内核、不做分叉而是在 Firefox 官方源码和配置机制的基础上用 user.js、autoconfig.cfg、policies.json 这一套配置层组合把浏览器整理成“默认安全、界面干净、行为可控”的定制版本。camofox 适合三类人第一类是给团队或客户分发统一浏览器的运维和开发者第二类是Privacy意识比较强、想折腾 Firefox 配置又怕踩坑的进阶用户第三类是纯粹想搞明白浏览器定制这套玩意的技术爱好者。本文我会把整个项目的设计思路、定制手段、构建过程、配置基线和踩过的坑完整拆开来讲。1. 为什么我决定自己定制一个浏览器1.1 现有浏览器满足不了的那些需求很多人会觉得浏览器这种东西直接用原版不就行了为什么非要自己折腾我刚开始做 camofox 之前也有这个疑问但真做起来之后才发现日常工作中的几个场景是原版浏览器解决不好的。第一个场景是给团队分发同构环境。我所在的小团队需要保证所有成员的浏览器行为一致包括禁用的遥测项、默认的搜索引擎、始终开启的跟踪保护级别。如果人人手上都是手动配置的原版浏览器今天同事 A 误关了某个保护选项明天同事 B 装了款偷偷改主页的扩展整个团队的安全基线就是一句空话。定制浏览器通过配置锁定和默认值统一能把这类问题一次性解决。第二个场景是隐私保护不该依赖用户自觉。原版 Firefox 提供的 Enhanced Tracking Protection 默认只是标准模式只拦截一部分跨站 Cookie 和指纹跟踪想要更强保护需要用户自己进设置里切换。但绝大多数用户根本不知道有这层设置甚至不知道什么叫做“被跟踪”。camofox 的做法是直接把默认拉到严格档位并且通过策略锁死不让用户在不知情的情况下把保护级别改回宽松档。第三个场景是软件分发和品牌统一。公司做内部工具、开源项目或者个人开发者做小众浏览器肯定不想在启动页、新标签页里看到一堆推荐信息流。原版浏览器无论如何配置总会保留一些与产品本身无关的推荐和遥测入口。定制浏览器要做的是把这些跟“用户实际任务”无关的东西全部摘掉只保留浏览器最基本的功能这就是 camofox 名字里 camo、低调、克制这个定位的来源。1.2 为什么不是 Chromium而是选 Firefox这个选择我其实在两年前就先做了对比当时基于 Chromium 的定制方案其实更流行项目体积、文档数量、社区案例都多于 Firefox 阵营。但深入操作下来Firefox 有几个点是 Chromium 替代不了的。首先是配置层级的清晰度。Firefox 的偏好设置分散在 about:config、user.js、autoconfig.cfg、policies.json 几个层面每一层解决的问题非常明确about:config 是运行时偏好user.js 是启动时基线autoconfig.cfg 可以运行脚本逻辑policies.json 是管理员策略锁。Chromium 对应的 policy 机制更偏向企业管控普通开发者想改默认值需要维护一整份 JSON 或重编译门槛高不少。其次是品牌和许可的灵活性。Firefox 使用的是 MPL 2.0 许可基于它做配置层面的定制、品牌替换只要你遵循商标策略不要叫 Firefox、不要用 Firefox Logo 误导用户是走得通的。基于 Chromium 做发行版则要面对更敏感的品牌策略Chromium 这个名字本身虽然可以合法使用但如果你想改成自己品牌又不想保留 Chromium 任何视觉元素实际操作中要做的事情比 Firefox 多很多。最后是 Gestalt 层面的考虑即浏览器引擎多样性。如果一个项目只是要一个“Chromium 背后的骨架”那么价值增量其实不大但如果要做的是对普通用户可讲解、可传播的隐私友好浏览器那么以 Gecko 引擎作为底座反而给了项目一个与众不同的理由。毕竟现在 WebKit 和 Blink 两大引擎几乎瓜分了移动端市场Gecko 是少数能持续提供独立渲染实现的选择。1.3 camofox 这个项目要达到的目标我在写第一版规划文档的时候给 camofox 定了三个硬性目标后续所有配置和代码都围绕这三个目标取舍。第一个目标是默认配置基线必须可审计。项目里的 user.js 和 policies.json 要像代码一样有版本管理、有注释、有来源链接让任何拿到项目的人都能搞明白“这一行配置为什么存在”。我不接受“这是社区某大神分享的优化清单直接抄就行”这种不可追溯的做法。事实上很多流传很广的 Firefox 优化清单里混杂着过时配置甚至有些配置在版本更新后已经不再生效这种配置基线一旦铺开排查起来非常痛苦。第二个目标是开箱即用零配置上手。camofox 的目标用户不是会去折腾配置的重度玩家而是“装完就想用、不想看设置页”的普通用户。所以安装包装好之后新标签页必须干净默认主页必须是一个简单的搜索框书签栏只保留三个核心工具链接所有隐私相关选项都提前设置完毕。第三个目标是可重复构建。项目必须支持一键脚本完成从拉取 Firefox 源码到产出安装包的完整过程不能在构建过程中出现任何手工人肉步骤。这个目标其实挺反人性因为浏览器源码体量大、依赖复杂、编译时间长稍微一个环境差异就会让构建失败。但如果做不到可重复构建就不能称其为一个项目只能叫一堆配置文件。2. 定制浏览器的三大核心手段2.1 user.js把偏好变成启动基线Firefox 的配置文件存放在 profile 目录里ideally 每个 profile 有一个 prefs.js保存了当前所有的偏好设置运行时修改 about:config 项会立刻写进这里。user.js 是一个特殊的文件只要放在 profile 目录下Firefox 每次启动时都会读取它并把其中定义的偏好值覆盖到运行时环境中优先级高于 prefs.js 中已有的设置。这个机制意味着 user.js 可以作为一个很硬的“启动基线”无论用户之前手动改过什么只要 user.js 里设置了同名项重启浏览器后就会被覆盖回来。camofox 项目里把配置项按分类分别维护在 user.js 中比如网络安全类、隐私跟踪类、 UI 精简类、搜索引擎类等每个配置项下面都写了注释说明是干什么用的。下面是我项目里早期版本的一部分配置示例// Disable Firefox remote process recommendation extension recommendations pref(browser.discovery.enabled, false); pref(extensions.getAddons.showPane, false); pref(extensions.htmlaboutaddons.recommendations.enabled, false); // Disable telemetry pref(toolkit.telemetry.enabled, false); pref(toolkit.telemetry.unified, false); pref(datareporting.policy.dataSubmissionEnabled, false); // Disable pocket pref(extensions.pocket.enabled, false); // Strict content blocking pref(browser.contentblocking.category, strict);需要注意的是pref()和lockPref()的区别。user.js 里只能用pref()它表示设置默认值用户后续可以在 about:config 里改掉而lockPref()只能出现在 autoconfig.cfg 里一旦锁定用户在 UI 和 about:config 里都无法修改。如果 camofox 的目标配置是“强制安全基线”那么安全相关的几项都应该通过 autoconfig.cfg 里的lockPref()锁死而不是只丢进 user.js。2.2 policies.json autoconfig.cfg管理员策略的“锁”Firefox 从 60 版本开始支持通过 policies.json 统一管理系统策略这个文件放在安装目录的 distribution 文件夹下。camofox 项目里用 policies.json 实现了几个很关键的控制项{ policies: { DisableAppUpdate: true, DontCheckDefaultBrowser: true, OfferToSaveLogins: false, DisableTelemetry: true, DisableFirefoxScreenshots: true, BlockAboutConfig: true, ExtensionSettings: { *: { installation_mode: blocked, blocked_install_message: Contact your administrator to install extensions. } } } }这里有几个点值得展开讲。BlockAboutConfig设为 true 之后普通用户无法打开 about:config 修改任何高级设置这等于把 user.js 建立的基线保护起来。ExtensionSettings默认全部 blocked是因为很多安全事件都源于用户安装了来路不明的扩展camofox 项目对扩展采用白名单策略只有预先审核通过的扩展才允许安装。autoconfig.cfg 则比 policies.json 更底层。它通过 JavaScript 语法在浏览器启动阶段执行函数可以用defaultPref()、pref()、lockPref()三种方式控制偏好用lockPref()甚至能锁定一些 policies.json 管不到的内部偏好项。它的配置方式是在安装目录下的 defaults/pref 里放一个 autoconfig.js指定执行 autoconfig.cfg// autoconfig.js pref(general.config.filename, autoconfig.cfg); pref(general.config.obscure_value, 0);然后再写 autoconfig.cfg比如强制关闭 DRM 插件或开启根据需求来// autoconfig.cfg lockPref(media.eme.enabled, true); lockPref(media.gmp-manager.url, ); lockPref(extensions.autoDisableScopes, 0);绝大部分项目其实只需要 policies.json 就够了autoconfig.cfg 的存在感更多在于那些 policies.json 没有覆盖的偏好项。我自己在 camofox 里的经验是能用 policies.json 表达的优先用 policies.json因为它是官方推荐、文档完善、未来兼容性最好的方式autoconfig.cfg 只用来处理少量“必须锁定但肯定不会被官方策略覆盖”的偏好比如某些隐藏的 media 设置。2.3 mozconfig从编译期做减法如果你只是想分发一个“配置好的 Firefox”前两节的手段已经完全够了不需要自己编译。但 camofox 项目把步子迈得更大了一点直接构建一个精简的 Gecko 浏览器从源码层面拿掉一些用不到的功能。Firefox 的编译构建系统基于 mach 和 mozconfig 文件。mozconfig 的作用类似 Linux 内核编译时的 .config里面用 ac_add_options 声明各种编译选项。camofox 的 mozconfig 核心内容大致如下ac_add_options --enable-applicationbrowser ac_add_options --enable-optimize ac_add_options --disable-debug ac_add_options --disable-tests mk_add_options MOZ_OBJDIR./obj-camofox mk_add_options MOZ_MAKE_FLAGS-j8这里面的取舍要说明一下。--disable-tests能省下大量编译时间和产出体积日常使用浏览器根本不需要跑测试套件。--enable-optimize编译出的版本性能更好但编译时间更长。MOZ_OBJDIR指定一个单独的构建目录千万不要把源码目录和构建目录混在一起否则后续想要清理重建会很头疼。自己编译的最大价值在于你能彻底去掉那些即使关掉配置也依然残留在二进制里的代码路径。比如某些平台相关的特性模块、某些内置组件、某些网络协议实验开关这些在分发物里的存在本身就是攻击面。从编译期移除后二进制体积更小、启动路径更短、被别人逆向和利用的可能性也显著降低这才是 Firefox 定制项目能够达到的高度。3. 手把手做一次完整构建3.1 环境准备与依赖这一步别偷懒既然 camofox 的目标之一是可重复构建环境准备就必须一次性到位。我在 Ubuntu 22.04 LTS 的干净环境里跑过一遍构建用 root 或 sudo 执行依赖安装sudo apt install -y \ build-essential clang curl llvm \ mercurial git python3 python3-pip \ libgtk-3-dev libasound2-dev libdbus-glib-1-dev \ libxt-dev libpulse-dev libx11-xcb-dev \ libxcb1-dev libxcb-render0-dev libxcb-shm0-dev \ libxcb-composite0-dev libxcb-damage0-dev \ libssl-dev libsqlite3-dev libxml2-dev \ libevent-dev libffi-dev libfontconfig1-dev \ libstartup-notification0-dev libxfixes-dev \ libxext-dev libxrandr-dev libxrender-dev \ zlib1g-dev安装完这些基础依赖后直接进入源码目录执行./mach bootstrap。mach 脚本会自动检测缺失的依赖、安装 rust toolchain、配置 clang 等这一步基本能覆盖 90% 的环境问题。如果 bootstrap 报错优先看它提示缺什么包通过 apt 补上重跑即可。然后拉取 Firefox 源码。Git 方式拉取会比较大Mozilla 官方推荐 Mercurial但 GitHub 上的镜像也维护得非常积极。我用的命令是git clone --depth1 https://github.com/mozilla/gecko-dev.git cd gecko-dev这里必须提醒一句Firefox 源码 Clone 下来就是几个 GB 的量级完整编译还需要额外的 20-40GB 磁盘空间。构建前务必检查磁盘余量最好提前df -h看一眼别编译到一半发现磁盘写满了那只能从头再来。macOS 和 Windows 上同样可以构建macOS 的 bootstrap 只需 Xcode 环境和 Xcode Command Line ToolsWindows 则需要 Visual Studio 2019 或 2022、Python、MozBuild 环境。我自己主力在 Linux 上做 CIWindows 版本只是偶尔在本地验证。3.2 mozconfig 里我最终留下的参数表和取舍逻辑当初我在各种博客上看到不少“编译优化配置”抄过来之后发现很多配置跟当前版本已经对不上否则就是编译时反而引入问题。我最终留下的是下面这张表列一下常用参数和它们的具体作用参数作用我的取舍--enable-applicationbrowser构建 Firefox 浏览器应用层必选对应 desktop 产品--enable-optimize开启编译器优化提升运行速度选 enable代价是编译时间变长--disable-debug关闭调试符号和调试代码必选否则产物体积爆炸--disable-tests不编译测试套件必选日常使用不需要--enable-release启用 release 模式更激进优化视情况release 模式编译更久--with-branding指定品牌资源目录camofox 的核心配置必选--disable-crashreporter禁用崩溃上报按需减少网络请求但也少了崩溃分析数据--disable-parental-controls去掉家长控制模块按需特定平台适用--enable-hardening开启安全加固选项推荐开启需要工具链支持编译指令不需要额外解释直接在源码根目录执行./mach build第一次完整编译会比较煎熬。一个 16 核 32G 内存、NVMe 硬盘的现代机器大约需要 1 到 2 个小时配置弱一些的机器四五个小时也很正常。编译期间 CPU 和内存都会长时间跑满建议不要在这台机器上同时做其他吃资源的任务。最关键的一点是编译过程要保证网络稳定因为构建过程中还会下载部分第三方依赖包。3.3 给浏览器换壳品牌标识与默认主页如果直接用默认品牌信息构建最终产物还是 Firefox 原版的样子这不符合 camofox 的品牌预期。Firefox 的 branding 目录默认在browser/branding/下面Mozilla 官方预置了unofficial、nightly、official几套。camofox 的做法是新建一个目录browser/branding/camofox/放好自己的品牌图标、桌面配置文件、About 页品牌描述和 license 信息然后在 mozconfig 里指定ac_add_options --with-brandingbrowser/branding/camofox需要注意Firefox 的商标政策是明确不允许在分发物里继续使用 Firefox 名称、狐狸 Logo 和任何容易让用户误以为这是官方产品的视觉元素。所以 camofox 的图标我选择了纯粹的橙色圆环 抽象狐狸轮廓文字标识统一写作 camofox Browser避免任何“Mozilla Firefox”字样出现在产品界面里。默认主页和默认搜索引擎这些属于运行时配置理论上不需要写死在源码里用 user.js / policies 就能完成。但 camofox 的构建版本里我把默认新标签页改成了本地 HTML 页面通过browser.newtabpage.activity-stream.feeds.system.topsites配置关掉热门站点推荐再设置一个干净的新标签背景。3.4 构建产物拿到手之后怎么验证构建完成后产物在MOZ_OBJDIR指定的目录下通常结构是obj-camofox/dist/bin/firefox。在 mac 上则是一个Firefox.appWindows 上是firefox.exe。跑一下版本号验证./obj-camofox/dist/bin/firefox --version看到形如camofox-browser 121.0.1的输出就说明编译成功。接下来把前面写的 user.js、policies.json、autoconfig.cfg 配置产物放进软件目录或 profile 目录启动浏览器做几个关键断言about:config 打不开BlockAboutConfig 生效、about:telemetry 显示数据采集已禁用、设置里的跟踪保护显示严格模式。把这条验证路径写成一个 shell 脚本集成进 CI 之后每次构建产物的质量就有保证了。4. 核心配置实战默认安全与隐私基线4.1 安全与隐私相关配置这才是 camofox 的护城河camofox 整套项目最核心的价值不在编译技巧而在那套经过反复验证的配置基线。安全隐私配置经常面对的问题是网上流传的清单里配置项太多很多已经过时你照着抄了一遍之后不仅没用还可能在某个版本升级后因为配置冲突出现各种奇怪问题。我建议按类别只保留那些真正有效的配置。首先是内容阻止级别。把浏览器内容阻止默认设为严格模式pref(browser.contentblocking.category, strict); pref(network.cookie.cookieBehavior, 1); pref(privacy.trackingprotection.enabled, true); pref(privacy.trackingprotection.socialtracking.enabled, true); pref(privacy.trackingprotection.cryptomining.enabled, true); pref(privacy.trackingprotection.fingerprinting.enabled, true);privacy.trackingprotection.fingerprinting.enabled开启后会阻止一些指纹采集脚本但有可能导致部分网站样式轻微错乱。如果在团队内部推广这个开关需要和业务兼容性一起测试我实测下来金融、电商类站点影响比较明显普通内容站点问题不大。其次是禁用遥测与数据上报。Firefox 的遥测体系分很多通道配置项分散在toolkit.telemetry.*、datareporting.*、app.normandy.*等几组前缀下。一次性把见过的遥测配置全部导出pref(toolkit.telemetry.enabled, false); pref(toolkit.telemetry.unified, false); pref(toolkit.telemetry.server, data:,); pref(toolkit.telemetry.archive.enabled, false); pref(datareporting.policy.dataSubmissionEnabled, false); pref(datareporting.healthreport.uploadEnabled, false); pref(app.normandy.enabled, false); pref(app.normandy.api_url, );注意toolkit.telemetry.server直接改成data:,是社区常用的“掐断上传地址”手段但这种方式太 hack新版 Firefox 统一通过数据上报策略开关控制toolkit.telemetry.server在部分版本已经没效果。我建议重点看datareporting.policy.dataSubmissionEnabled和toolkit.telemetry.enabled这两个主开关其他可以不管。第三类是连接层安全项。浏览器在做连接时尽量使用加密 DNSDoH这一项对公共 Wi-Fi 环境下的隐私保护挺有意义pref(network.trr.mode, 3); pref(network.trr.uri, https://mozilla.cloudflare-dns.com/dns-query);DoH 的 mode 有 0-5 几个档位0 表示禁用1 表示备用模式2 表示默认启用3 表示强制启用且不允许回退5 表示显式关闭。camofox 里我用的是 3因为要保证“默认安全”代价是部分内网 DNS 解析可能出问题。团队内部使用的话建议改成 2让系统 DNS 做兜底。4.2 默认搜索引擎与启动体验细节决定“开箱即用”浏览器定制最容易掉链子的地方是“细节差异”。构建出来的 camofox 如果启动后书签栏一片空白、新标签页充斥着推荐信息那前面那些策略配置做得再好用户第一眼观感也拉胯。默认搜索引擎这块我用 policies.json 里的SearchEngines策略维护了一个最小集合必应、百度、DuckDuckGo中文界面下可选再加一个维基百科多余的全删掉。这避免了 Firefox 自带的搜索引擎列表随区域变化而增减的不可预期问题。新标签页和主页保持极简是 camofox 另一个重要的 UI 决策。Firefox 默认的新标签页是一个 content feed会展示“热门站点”“推荐阅读”等内容这些简直是为定制浏览器量身定做的噪音。配置里把信息流关闭pref(browser.newtabpage.activity-stream.feeds.system.topstories, false); pref(browser.newtabpage.activity-stream.feeds.system.topsites, false); pref(browser.newtabpage.activity-stream.feeds.section.topstories, false); pref(browser.newtabpage.activity-stream.showSponsored, false); pref(browser.newtabpage.activity-stream.showSponsoredTopSites, false);再加上自动隐藏书签栏和一键关闭 Pocket新标签页基本就剩下一个搜索框和一个空白背景这才是“浏览器本质是一个跳板工具”的产品理念。4.3 扩展预装与白名单机制浏览器分发时经常会遇到一个需求帮用户预先装好几个插件。在 Firefox 体系里这不算简单的事因为 AMOaddons.mozilla.org对扩展有签名校验未经签名或来源不明的扩展在正式版中默认被禁止安装。v 方案是做扩展白名单管理制度。camofox 的 policies.json 里ExtensionSettings已经把默认安装模式设为 blocked同时针对我自己的扩展 ID 单独配置 allowed{ policies: { ExtensionSettings: { default_blocked_ext: { installation_mode: blocked }, camofox-content-blockercamofox.invalid: { installation_mode: allowed, install_url: https://dist.camofox.invalid/extensions/ } } } }这个白名单机制配合企业级签名证书可以实现只有 camofox 项目内部分发的扩展才能被安装任何从外部下载的 .xpi 都无法安装。对于面向特定人群分发浏览器的场景这是防止扩展供应链攻击比较有效的手段。5. 常见问题与排查技巧实录5.1 编译失败70% 都是依赖和磁盘问题做定制浏览器项目第一个拦路虎必然是编译失败。我在 camofox 项目里遇到过的编译失败排在前三的原因分别是磁盘空间不足。Firefox 源码加构建中间文件在完整构建时能吃掉 30GB 以上很多新手栽在这上面。内存不够。链接阶段需要同时加载大量符号信息8GB 内存的机器跑完整构建基本是煎熬容易 OOM 或者把 swap 打满。编译器版本不匹配。Mozilla 对 clang 版本有一套最低要求系统自带 clang 版本太旧也会直接报错。应对办法比较粗暴但有效编译之前先./mach bootstrap自动装好全部工具链不要在“我机器上已经有 gcc 了”这种错觉下贸然跳过。如果遇到编译中途失败不要直接重头再来./mach build是支持增量构建的它会从上次失败的位置继续修复依赖或配置后再次执行即可。5.2 user.js 设置失效或者被用户改回去camofox 分发初期收到最多的反馈是我明明改好了 user.js为什么用户那边打开看到的还是默认设置或者用户自己在 about:config 里改回去之后我们的安全基线等于白做。这两个问题的根源分别属于不同情况。user.js 失效最常见的原因是 profile 路径不对。Firefox 在安装后第一次启动时会根据安装目录生成 profile如果你把 user.js 放到了另一个 profile 下面它当然不会加载。排查方法是启动浏览器进入 about:profiles查看当前正在使用的 profile 根目录路径把 user.js 放到那个目录里。用户自行改回设置的问题则需要用lockPref()来兜底。user.js 只设默认值lockPref()才是真正的锁。建议的做法是把需要锁定的配置项写进 autoconfig.cfg用lockPref()锁死把允许用户自行调整的项目留在 user.js 里不要一刀切全锁。全锁配置确实安全但会让用户体验变得很僵硬连改个语言都要重新打包。5.3 每次版本升级配置漂移问题如何治理camofox 项目里有一个词叫配置漂移每次上游 Firefox 发布新版本总会有几个自带偏好项的默认值发生变化导致我写的 user.js 里的值和最新版本默认值冲突或者干脆被上游新配置项替代。这种问题不会让浏览器崩溃但会逐步蚕食你搭建的安全基线。我用的治理方案是把配置基线做成一份带版本号的文件每次上游发布 major 版本后跑一次自动对比脚本将上游默认值与 camofox 配置值逐个比对输出差异报告。然后人工审查差异报告中哪些是上游行为变化需要适配哪些是 camofox 有意覆盖。这样每个版本的配置漂移都有记录而不是等用户在线上出了问题再回头查。5.4 分发时的品牌策略别碰“Firefox”这个牌子这里专门提醒一下所有想做浏览器定制项目的同行。Firefox 这个词以及火焰狐狸的 Logo 是 Mozilla 的注册商标Mozilla 对官方品牌的使用有着严格的政策。你基于 Firefox 源码做定制完全可以但分发时如果你继续叫“Firefox”或者在界面里使用官方 Logo很容易收到商标侵权警告。camofox 的品牌和 MPL 许可证层面的处理我特意咨询过相关知识MPL 2.0 保证了你有权使用和修改源码但商标权是独立于版权之外的不随源码自动授予。所以 camofox 的安装包、内页浏览器头图、About 页面、主页图标都不叫 Firefox不出现任何狐狸 Logo 和 Mozilla 字样。项目 README 里也需要写明“这不是 Mozilla 官方产品”避免用户误解。结尾想说的话做了 camofox-browser 之后我最大的体会是浏览器定制的技术门槛其实比大多数人想象的低得多真正的难点全在配置治理、版本跟进和分发合规这些“脏活累活”上。你完全可以不写一行 C仅靠 policies.json、autoconfig.cfg 和 user.js 就做出一个体验完全不输商业浏览器的定制版本想再进一步就去啃 mozconfig 和源码构建那又会发现一个完全不同的世界。最后再分享一个小技巧这个对任何规模的定制项目都有用把你所有修改过、新增过的偏好项单独收集到一个带标记的清单文件里统一注释标明“修改人、修改时间、修改原因、关联 issue”每次版本升级时这个清单就是你的对照表。没有这个清单之前我经常因为某个配置是否被改过而反复翻 prefs.js有了它之后整个项目从个人玩具变成了一个可交接、可维护的工程。