系统附加组件概述

系统附加组件是向 Firefox 分发扩展的一种方法,

  • 它隐藏在 about:addons UI 中

  • 用户无法禁用

  • 可以基于 Mozilla 设置的标准进行无重启更新

通常,这些被认为是 Firefox 的内置功能,并且它们是扩展并且可以无重启更新的事实,对于用户来说只是实现细节。

如果您想随 Firefox 一起分发附加组件或作为更新(无论是对现有功能的更新还是对野外关键问题的“热修复”),请联系 GoFaster 团队:https://mail.mozilla.org/listinfo/gofaster

附加组件本身要么是传统的 Firefox 附加组件,要么是 WebExtensions。它们必须

  • 无重启

  • 多进程兼容

除了这些限制之外,扩展本身没有任何特殊或不同之处。

可以通过将具有相同 ID 的不同附加组件安装到更高优先级的目录来覆盖已安装的系统附加组件。

可用的位置,从最高优先级开始包括

  1. 临时安装 (about:debugging)

  2. 正常用户安装到配置文件 (about:addons 或 AMO/TestPilot 等)

  3. 系统附加组件更新

  4. 内置系统附加组件

这使得开发人员或用户可以通过从 AMO 或 TestPilot 安装具有相同 ID 的附加组件或作为临时附加组件来覆盖系统附加组件成为可能。

默认的内置系统附加组件

一组**默认**系统附加组件被检入 mozilla-central 中的 ./browser/extensions 目录下。这些在构建时被放置到应用程序目录的 features 目录中。

系统附加组件更新

系统附加组件**更新**通过 Mozilla 的自动更新服务 (AUS,也称为 Balrog) 提供。这些安装到用户配置文件的 features 目录下。

更新必须由 Mozilla 特别签名 - addons.mozilla.org 使用的签名不适用于系统附加组件。

如上所述,这些更新可能会覆盖内置的系统附加组件,或者它们可能是新安装。更新始终作为一组提供 - 如果集合中的任何附加组件无法安装或升级,则整个集合都将失败。这是为了使 Firefox 保持一致的状态。

当 Firefox 应用程序版本更改时,系统附加组件更新将被删除,以避免兼容性问题 - 例如,用户降级到低于更新支持的 Firefox 版本将最终导致更新被禁用,而不是回退到内置版本。

Firefox 系统附加组件更新协议

本节描述了 Firefox 在从 AUS 检索更新时使用的协议,以及基于更新程序服务响应的 Firefox 的预期行为。

更新请求

为了确定要安装哪些更新,Firefox 每天通过以下格式的 URL 向 AUS 发出 HTTP GET 请求一次

https://aus5.mozilla.org/update/3/SystemAddons/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml

% 符号包围的路径段是 Firefox 使用自身和运行环境信息填充的可变字段

VERSION

Firefox 版本号

BUILD_ID

构建 ID

BUILD_TARGET

构建目标

LOCALE

构建区域设置

CHANNEL

更新渠道

OS_VERSION

操作系统版本

DISTRIBUTION

Firefox 发行版

DISTRIBUTION_VERSION

Firefox 发行版版本

更新响应

AUS 应该使用类似于以下内容的 XML 文档进行响应

<?xml version="1.0"?>
<updates>
  <addons>
    <addon id="[email protected]" URL="https://ftp.mozilla.org/pub/system-addons/flyweb/[email protected]" hashFunction="sha512" hashValue="abcdef123" size="1234" version="1.0"/>
    <addon id="[email protected]" URL="https://ftp.mozilla.org/pub/system-addons/pocket/[email protected]" hashFunction="sha512" hashValue="abcdef123" size="1234" version="1.0"/>
  </addons>
</updates>
  • 根元素是 <updates>,用于所有更新程序响应。

  • <updates> 的唯一子元素是 <addons>,它表示要更新的系统附加组件列表。

  • <addons> 中有几个 <addon> 标签,每个标签对应一个要更新的系统附加组件。

<addon> 标签**必须**具有以下属性

id

扩展 ID

URL

要下载的指定附加组件版本的已签名 XPI 的 URL

hashFunction

用于生成 hashValue 属性的哈希函数的标识符。

hashValue

使用 hashValue 属性中指定的函数计算的,链接自 URL 属性的 XPI 文件的哈希值。

size

链接自 URL 属性的 XPI 文件的大小(以字节为单位)。

version

附加组件的版本号

更新行为

收到更新响应后,Firefox 会根据以下算法修改**更新**附加组件

  1. 如果响应中的 <addons> 标签为空 (<addons></addons>),则**删除所有系统附加组件更新**。

  2. 如果响应中未指定任何附加组件(即 <addons> 标签不存在),则不执行任何操作并完成。

  3. 如果**更新**附加组件集等于更新响应中指定的附加组件集,则不执行任何操作并完成。

  4. 如果**默认**附加组件集等于更新响应中指定的附加组件集,则删除所有**更新**附加组件并完成。

  5. 下载更新响应中指定的每个附加组件并将它们存储在“已下载附加组件集”中。下载失败**必须**中止整个系统附加组件更新。

  6. 验证已下载的附加组件。以下**必须**对所有已下载的附加组件都为真,否则更新过程将中止

    1. 已下载附加组件的 ID 和版本必须与更新响应中指定的 ID 或版本匹配。

    2. 更新响应中提供的哈希值必须与已下载的附加组件文件匹配。

    3. 已下载的附加组件文件大小必须与更新响应中给出的大小匹配。

    4. 附加组件必须与 Firefox 兼容(即,它不能用于其他应用程序,例如 Thunderbird)。

    5. 附加组件必须被打包(即为 XPI 文件)。

    6. 附加组件必须是无重启的。

    7. 附加组件必须由系统附加组件根证书签名。

  1. 一旦所有已下载的附加组件都经过验证,则将其作为**更新**集的一部分安装到配置文件目录中。

关于更新过程的说明

  • 如果附加组件具有相同的 ID 和版本号,则它们被认为是“相等”的。

示例

以下部分描述了我们已经遇到或预计会遇到的常见情况以及上述协议如何处理它们。

为简单起见,除非另有说明,否则所有示例都假设存在两个系统附加组件:**FlyWeb** 和 **Pocket**。

基本

用户拥有 Firefox 45,它附带了 FlyWeb 1.0 和 Pocket 1.0。我们希望将用户更新到 FlyWeb 2.0。AUS 发送以下更新响应

<updates>
  <addons>
    <addon id="[email protected]" URL="https://ftp.mozilla.org/pub/system-addons/flyweb/[email protected]" hashFunction="sha512" hashValue="abcdef123" size="1234" version="2.0"/>
    <addon id="[email protected]" URL="https://ftp.mozilla.org/pub/system-addons/pocket/[email protected]" hashFunction="sha512" hashValue="abcdef123" size="1234" version="1.0"/>
  </addons>
</updates>

Firefox 将下载 FlyWeb 2.0 和 Pocket 1.0 并将它们存储在配置文件目录中。

缺少附加组件

用户拥有 Firefox 45,它附带了 FlyWeb 1.0 和 Pocket 1.0。我们希望将用户更新到 FlyWeb 2.0,但意外地忘记在更新响应中指定 Pocket。AUS 发送以下内容

<updates>
  <addons>
    <addon id="[email protected]" URL="https://ftp.mozilla.org/pub/system-addons/flyweb/[email protected]" hashFunction="sha512" hashValue="abcdef123" size="1234" version="2.0"/>
  </addons>
</updates>

Firefox 将下载 FlyWeb 2.0 并将其存储在配置文件目录中。将使用来自**默认**位置的 Pocket 1.0。

删除所有系统附加组件更新

来自 AUS 的具有空附加组件集的响应将删除所有系统附加组件更新

<updates>
  <addons></addons>
</updates>

推出

用户拥有 Firefox 45,它附带了 FlyWeb 1.0 和 Pocket 1.0。我们希望以 10% 的抽样率推出 FlyWeb 2.0。10% 的时间,AUS 发送以下内容

<updates>
  <addons>
    <addon id="[email protected]" URL="https://ftp.mozilla.org/pub/system-addons/flyweb/[email protected]" hashFunction="sha512" hashValue="abcdef123" size="1234" version="2.0"/>
    <addon id="[email protected]" URL="https://ftp.mozilla.org/pub/system-addons/pocket/[email protected]" hashFunction="sha512" hashValue="abcdef123" size="1234" version="1.0"/>
  </addons>
</updates>

使用此响应,Firefox 将下载 Pocket 1.0 和 FlyWeb 2.0 并将它们安装到配置文件目录中。

另外 90% 的时间,AUS 发送空响应

<updates></updates>

使用空响应,Firefox 将不会进行任何更改。这意味着尚未看到 10% 更新响应的用户将停留在 FlyWeb 1.0 上,而已经看到更新响应的用户将停留在 FlyWeb 2.0 上。

一旦我们对推出感到满意并希望切换到 100%,AUS 将向 100% 的用户发送 10% 的更新响应,将所有人升级到 FlyWeb 2.0。

回滚

此示例从“推出”示例继续。如果在 10% 的推出过程中,我们发现 FlyWeb 2.0 存在重大问题,我们希望将所有用户回滚到 FlyWeb 1.0。AUS 发送以下内容

<updates>
  <addons>
    <addon id="[email protected]" URL="https://ftp.mozilla.org/pub/system-addons/flyweb/[email protected]" hashFunction="sha512" hashValue="abcdef123" size="1234" version="1.0"/>
    <addon id="[email protected]" URL="https://ftp.mozilla.org/pub/system-addons/pocket/[email protected]" hashFunction="sha512" hashValue="abcdef123" size="1234" version="1.0"/>
  </addons>
</updates>

对于已更新的用户,Firefox 将下载 FlyWeb 1.0 和 Pocket 1.0 并将它们安装到配置文件目录中。对于尚未更新的用户,Firefox 将看到**默认**附加组件集与更新 ping 中的集合匹配,并清除**更新**附加组件集。