浏览器是用来显示在万维网或局域网等内的文字、图像及其他信息的软件,它还可以让用户与这些文件进行交互操作。本文中将介绍为什么我们认为有必要创建自己的浏览器,为什么我们选择了 Firefox 以及为什么我们认为这是正确的决定。
以下为译文:
2015年,我们公司发布了在 Firefox 基础之上构建的桌面Web浏览器。在那之前,我们发行了多个作为 Firefox 插件的搜索和隐私产品。在本文中,我们将介绍为什么我们认为有必要创建自己的浏览器,为什么我们选择了 Firefox 以及为什么我们认为这是正确的决定。
搜索是Web浏览体验不可或缺的一部分,几乎每个浏览会话都从搜索开始。所有现代浏览器用户界面都将搜索直接集成到地址栏中。因此,浏览器是发行搜索产品的主要方式,2000年的时候,Google 通过创建 Chrome 浏览器推动他们的搜索产品时就意识到了这一点。如今我们也意识到了这一点,因此我们希望创建一款浏览器,并通过它发行我们的搜索产品,展示我们的愿景。
此外,拥有平台对于维持用户体验的控制非常重要。回顾我们的亲身经历也证明了这一点:当初我们的 Firefox 浏览器扩展使用的是旧的扩展API,这些 API 拥有很强大的修改浏览器UI方面的功能,我们利用这些功能构建了搜索下拉菜单。2017年的时候,由于这些 API 被弃用,我们也无法再通过 Firefox 发行该功能。幸运的是,这一次我们有了自己的浏览器。
其次,我们可以通过发行浏览器控制更多的用户体验。以前,主流浏览器对用户隐私的关注十分有限。根据构建Web搜索的经验,我们发现用户的数据被收集,然后再由他人放到“自由市场”上出售。我们希望保护用户,让他们免受这种剥削,并在浏览器中贯彻应用隐私设计。
我们认为浏览器是用户代理,“用户代理是代表用户实际动作的软件(软件代理)” 。浏览器代表互联网上的用户,因此我们有责任保护他们的隐私。我们在 Firefox 插件中实现了反跟踪和反钓鱼技术,这些技术可以直接集成到我们的浏览器中。
由于上述种种原因,我们决定构建和发行自己的浏览器。而且很显然,我们无需更改现有浏览器运行良好的功能,而且在渲染性能和安全性方面,与现有浏览器竞争也没有任何价值。相反,我们想在这些浏览器的基础之上构建新功能。因此,我们不得不以现有的某个引擎为基础建立分支(fork)。我们的思路是将该浏览器作为我们自己的新功能的平台。
从长远来看,这项决策可以让我们的工作更加轻松。浏览器的发展非常迅速,我们必须经常更新,才能确保及时发行重要的安全补丁。在这种情况下,维护某个分支是非常艰难的工作,而且我们了解到,持续做好这项工作的唯一办法是尽量减少与上游项目的差异。
最后,我们选择以 Firefox 为基础建立分支,因为我们的大部分代码都是 Firefox 扩展,而且为了跟上 Firefox 上游的变动,我们将尽可能多的代码封装在扩展中了。
如今,以 Chromium 为浏览器的基础已成大势所趋。Opera、Yandex、Brave以及最近的微软等众多公司都朝着这个方向发展。对于我们而言,由于种种原因导致我们不清楚应该做怎样的选择:
• 与 Google 相比,我们更认可 Mozilla 的生存信念。我们与 Mozilla 的大部分价值观都很接近,所以我们认为Mozilla是我们的盟友。在进行分支时,我们需要承担风险, 比如上游维护者终止或修改我们所依赖的功能。我们认为 Mozilla 比 Google 更值得信赖,Mozilla 终止或修改某个功能的可能性更小;
• 考虑到垄断的问题,我们认为支持 Firefox 更有意义。Blink / Gecko(Web渲染器)的市场份额并不是一件小事。如果所有浏览器最终都使用Blink(Google),则Web将会受到重创,因为开发人员只会优化和测试 Blink 渲染引擎。Web刚刚失去了一个独立引擎(EdgeHTML),进一步加剧了这个问题。
还有技术上的原因:
• Firefox 提供了浏览器方方面面的开放API,大部分 Firefox 的“应用程序”代码都是用JavaScript编写的。相反,Chromium 不会暴露某些 Google 业务敏感的区域。最著名的例子就是地址栏。Google 不愿意为其他人控制地址栏提供方便;他们只想保护默认搜索引擎(Google)的流量。当然,我们也可以创造新API,但这意味着我们需要自己编写源代码。创造API不是大问题,我们已经创建过一个原型,但接下来的维护才是大问题;
• 维护任何分支都是一场噩梦,因为项目的所有者(对于 Chromium 来说,大多数代码都来自 Google 员工)可能激进地更改代码,有时甚至破坏已有的集成,强迫他人跟上他们的步伐;
• Chromium不够“稳定”。API的更改以及对旧API的支持缺乏持续性和一致性。以 Manifest v3 为例,它的安全、隐私和性能的基础都不牢靠,因此很有可能会淘汰加强隐私的插件所依赖的一些强大且实用的API,最终会影响到这些插件本身。他们回溯了做出这些更改的初衷,但仍打算将改动继续到底,对依赖这些API的人来说,这就是一场浩劫;
• Chromium 自带很多无法轻易删除的 Google 服务。微软和 Brave 为了删除这些服务,投入了大量资源。而一些其他的API,如屏幕阅读器集成等API都是闭源的。
Chromium 是一款出色浏览器,带有快速的渲染引擎,但维护它的分支需要投入大量资源。我们没有这些资源,也不愿意付出这些代价。事实证明,选择 Firefox 的决定是正确的,因为随着时间的流逝,集成我们的功能越来越容易,而 Chromium 已经弃用了对我们的项目至关重要的一些API。
我们的新浏览器自带一些自家打造的功能,可以帮助用户享受安全的私人Web体验。以下是一些最重要的功能:
• 下拉列表:我们的搜索就在地址栏中。搜索结果会根据用户类型显示在下拉列表中,所以可以为你节省搜索结果页面的时间。显示的结果由我们的独立、私有的搜索后端提供;
• 反跟踪:我们实现了识别并阻止跟踪器以及反复尝试指纹识别的算法,并根据数据不断更新;
• 广告拦截:通过高效的广告拦截,为用户打造快速、无广告和烦扰的Web体验;
• Cookie弹出窗口阻止程序:帮助用户处理网站上弹出的强制同意窗口,自动处理模棱两可的UX。我们会阻止数据的收集,而不仅仅是隐藏弹出窗口;
• 自动“忘记窗口”:对于敏感链接,我们的浏览器将会自动使用“忘记窗口”打开,即使是从普通窗口启动链接时也是如此;用户还可以将URL列入黑名单,从而确保始终在“忘记窗口”中打开它们;
• 反网络钓鱼:防止用户陷入钓鱼网站,时刻确保用户的安全;
• 用户仪表板:显示隐私状态,例如阻止了多少广告以及删除了多少私人数据点。此外,还提供精选新闻,并包括一些实用小程序,例如访问次数最多的网站和书签。
我们建立 Firefox 分支已有四年多了,我们发现 Firefox 非常适合进行分支。它有一系列对分支非常友好的属性:
• 该浏览器的UI能够通过CSS定制主题,因此Web开发人员可以轻松地设计和调整UI;
• 该浏览器是模块化的,基于 pref 的体系结构非常易于配置;
• 该浏览器建立在Web技术之上。开发人员可以更迅速地适应并开展工作。你还可以利用开发者工具调试整个浏览器;
• 该浏览器对于重新打包发行有着一流的支持,因此很容易在其之上建立其他品牌的游览器;
• 该浏览器支持非常强大的扩展,尤其是特权上下文,你甚至可以利用它深入浏览器的内部;
• 该浏览器允许你通过强大的配置脚本进行深度定制。
最初,我们利用原始、低级的浏览器API 开始构建 Firefox 的扩展。然而,在开始构建浏览器后,我们又希望将这些功能发布到 Android 和 iOS 上的移动浏览器中。后来,我们希望在Firefox 57提供的 webextension API 之上运行我们的代码。对于一个规模很小的团队而言,确保环境以及代码库之间的业务逻辑一致是一项难题。
为了解决这个问题,我们决定利用 JavaScript 来构建我们的一切架构。我们利用同构且通用的 JavaScript 编写业务逻辑,并在底层添加平台特定的实现,以处理每个运行时的细节。我们的浏览器核心的代码库包含跨所有平台产品的代码:
• Web扩展、与 Chrome、Firefox 和 Edge的兼容;
• 使用 React-native 的 Android 和 iOS;
• NodeJS,用于测试和 headless 模式。
举个例子,我们有一个搜索模块提供给定查询的结果。这是浏览器核心的一个模块实现的。如前所述,结果的来源之一是浏览器的历史记录。这是平台特有的功能,因此台式机和移动设备上有不同的历史数据库。在构建时,绑定了相应的 JavaScript 实现,因此该搜索模块可以查询平台的数据库。搜索的用户界面也有所不同:在桌面系统中,结果显示在URL栏下方的内联框架中,而在移动设备上,UI是使用 React-Native 实现的。两种情况都会将查询推送到同一个搜索实现中,并从中获取结果。
Android 上的情况与桌面系统略有不同。该操作系统由Google控制,大多数用户都会使用内置的浏览器或 Chrome(与Android一起发行)。幸运的是,用户仍然可以选择。你可以更改默认的浏览器,而且操作系统就会尊重你的选择,在你点击链接时使用选择的浏览器打开。我们构建了多个 Android 浏览器,每次都使用了不同的方法:
Cliqz Android:与许多 Android 浏览器一样,Cliqz Android 是基于 Android WebView 的常规应用程序。不同之处在于它运行的是在React-Native运行时中运行的共享 JavaScript 代码库。我们的隐私保护功能(例如广告拦截和反跟踪功能)在 React-Native 线程中运行,并且还能够拦截系统 WebView 中发送的网络请求。我们通过这种独特的方法提供这些功能,同时又无需派生完整的浏览器引擎。
Ghostery Android:在 Ghostery 与 Cliqz 联合之后,我们决定升级 Ghostery Android 浏览器。我们的目标是在手机上提供完整的 Ghostery 体验,因此我们决定在 Firefox上 构建新版的 Android 浏览器(名为Fennec)。在此次构建中,我们充分利用了 Firefox Android 提供的 WebExtension。这基本上是在模仿我们桌面系统的做法。
Fennec是一项伟大的工程项目,基本来说其本质是 Firefox,只不过是面向移动设备。它拥有 Gecko 渲染引擎和 SpiderMonkey JavaScript 引擎。最重要的是,它具有原生的 Android UI,可提供熟悉的外观。
不幸的是,Fennec 的开发是一个非常复杂的过程。开发人员必须不断地在不同层面和技术之间来回跳转,才能实现新功能或修复bug。没有多少开发人员能够有效地在 C++、JavaScript和 Java 之间切换。
Mozilla 社区都明白 Fennec 架构的局限性,因此该浏览器于2019年退休。
新一代 Cliqz 浏览器:根据 Fennec 的经验,Mozilla 社区创建了一个全新的体系结构来创建 Android 浏览器。它的核心是 GeckoView。这是一款精心封装的浏览器引擎,拥有精心制作的 Java API。任何开发人员都可以借助 GeckoView,创建 Gecko 支持的浏览器,同时又无需编写 JavaScript 或 C++ 代码。GeckoView 只是一个“库”,就像与 Android 一同发布的 WebView。
但是 GeckoView 能够运行 WebExtensions,因此,很适合我们公司。我们可以在 GeckoView之上构建漂亮的浏览器UI,并以 WebExtensions 的形式发布共享的 JavaScript 代码库。这样一来,我们就可以借助我们迅捷的广告拦截器,在速度方面与 Chromium 竞争,并从隐私保护的各个方面超过 Chromium 。
苹果的iOS平台也大不相同。用户无法选择默认浏览器,浏览器供应商也无法构建自己的渲染或 JavaScript 引擎。所有开发人员都必须使用常规的 iOS WebView(WKWebView)。所有浏览器供应商都必须受制于这种限制:Mozilla 甚至 Google 浏览器都“只是” iOS应用程序。
从根本上来看,我们的浏览器没有什么不同。我们利用 Firefox 建立了 iOS分支,为我们的浏览器建立了一个稳定的基础。为什么选择 Firefox?因为这是一个开源、非常可靠、久经考验的项目。但这不是唯一的选择:DuckDuckGo 也将是一个不错的选择。
由于 iOS WebView 不具备运行扩展的功能,因此我们不得不自己动手创建一个。同样,React Native 提供了解决方案:我们创建了一个混合应用程序,该应用程序运行的浏览器核心是经过我们大量修改的 Firefox 代码库中的 React Native。
值得一提的是,我们已经在 Firefox 之上建立了三个 iOS 分支,我们在建立分支时采用了不同的策略:
1. 与上游的同步很少的“软”分支:事实证明,我们所做的实质性更改主要围绕 WebView,因此维护难度非常大。我们选择修改 Firefox 代码,并使用虽然有年头但功能更强大的 UIWebView 来提供隐私功能;
2. 常规同步的“软”分支:失败了,因为这限制了我们根据自己的喜好来设计浏览器的能力;
3. 使用 cherry-pick 方式选择性同步的硬分支(当前版本):这是到目前为止开发人员最喜欢的分支,因为你可以自由修改,同时不必担心与上游发生冲突。
请注意,iOS 版的 Firefox 并不是一个发展速度非常快的项目。因此手动选择安全修复程序仍然可行。
原文:https://0x65.dev/blog/2019-12-17/why-we-forked-firefox-and-not-chromium.html
热 文 推 荐
☞12306 回应软件崩了;微信发布新版本,朋友圈可“斗图”;Ant Design 3.26.4 发布 | 极客头条
☞滴滴开源在2019:十大重点项目盘点,DoKit客户端研发助手首破1万Star
点击阅读原文,即刻参加!