特性开关

特性开关是一种高级工具,用于启用和禁用特性。它提供有关特性的元数据、一个简单且有原则的 API,并避免了其他系统(例如直接使用偏好设置)的许多潜在陷阱。它旨在与想要了解并影响 Firefox 中特性状态的工具兼容,包括随时间推移和在现实环境中的状态。

特性定义

所有特性都必须有一个定义,在 toolkit/components/featuregates/Features.toml 中指定。这些定义包括诸如标题和描述字符串的引用(显示给用户)以及 Bug 号码(跟踪特性随时间的开发)等数据。这是一个具有 demo-feature ID 的特性定义示例。

[demo-feature]
title = "experimental-features-demo-feature"
description = "experimental-features-demo-feature-description"
restart-required = false
bug-numbers = [1479127]
type = "boolean"
is-public = {default = false, nightly = true}
default-value = {default = false, nightly = true}

titledescription 值中定义的引用指向存储在 toolkit/locales/en-US/toolkit/featuregates/features.ftl 中的字符串。 title 字符串应将面向用户的字符串指定为 label 属性。

目标值

一些字段可以取一个值,表示它会根据渠道和操作系统而变化。这些被称为目标值。最简单的计算值是直接提供值。

default-value = true

一个更有趣的例子是使特性在 Nightly 上默认为 true,但在其他情况下禁用。这将如下所示。

default-value = {default = false, nightly = true}

值可以依赖于多个条件。例如,仅在 Windows 上运行的 Nightly 上启用特性。

default-value = {default = false, "nightly,win" = true}

可以指定多个条件集,但是在此处要谨慎:如果多个条件集可以匹配(除了 default),则选择的条件集是未定义的。安全使用多个条件的示例。

default-value = {default = false, nightly = true, "beta,win" = true}

default 条件是必需的。如果没有任何更具体的条件匹配,则将其用作后备。允许的条件有:

  • default

  • release

  • beta

  • dev-edition

  • nightly

  • esr

  • win

  • mac

  • linux

  • android

字段

title

必需。特性的可读名称的字符串 ID,用于显示给用户。应适合在一行中显示。实际的字符串应在 toolkit/locales/en-US/toolkit/featuregates/features.ftl 中定义,面向用户的字符串定义为字符串的 label 属性。

description

必需。特性的可读描述的字符串 ID,用于显示给用户。应最多为一段。实际的字符串应在 toolkit/locales/en-US/toolkit/featuregates/features.ftl 中定义。

description-links

可选。键值对的字典,在描述中引用。键名必须出现在描述本地化文本中,如 <a data-l10n-name=”key-name”>。例如在 Features.toml 中

[demo-feature]
title = "experimental-features-demo-feature"
description = "experimental-features-demo-feature-description"
description-links = {exampleCom = "https://example.com", exampleOrg = "https://example.org"}
restart-required = false
bug-numbers = [1479127]
type = "boolean"
is-public = {default = false, nightly = true}
default-value = {default = false, nightly = true}

以及在 features.ftl 中

experimental-features-demo-feature =
    .label = Example Demo Feature
experimental-features-demo-feature-description = Example demo feature that can point to <a data-l10n-name="exampleCom">.com</a> links and <a data-l10n-name="exampleOrg">.org</a> links.
bug-numbers

必需。与此特性相关的 Bug 号码列表。这可能是特性的元 Bug,但可以包含任何相关的 Bug。至少需要一个 Bug。

restart-required

必需。如果此特性需要浏览器重新启动才能使更改生效,则此字段应为 true。否则,此字段应为 false。特性应尽量避免需要重新启动,并动态响应偏好设置的更改。

type

必需。此特性关联的值的类型。唯一合法的值为 boolean,但将来可能会添加更多类型。

preference

可选。用于跟踪特性的偏好设置。如果没有提供偏好设置,则会根据特性 ID 自动生成一个。不建议直接指定偏好设置,除非要与旧代码集成。将来,如果未提供偏好设置,可能会使用其他存储机制。

default-value

可选。这是一个 目标值,描述如果未进行其他更改(例如在新的配置文件中)特性的值。如果未提供,则布尔类型特性开关的所有配置文件的默认值为 false

is-public

可选。这是一个 目标值,描述在哪些分支上此特性应向用户公开。当特性公开后,它可能会出现在未来允许用户选择加入实验性特性的 UI 中。这与 about:preferencesabout:config 无关。如果未提供,则默认为对所有渠道隐藏特性。

特性开关 API

class FeatureGate()

用于启用和禁用特性的高级控制。

static FeatureGate.addObserver(id, observer, testDefinitionsUrl)

通过 ID 添加特性开关的观察者。如果特性类型为布尔型且当前已启用,则将调用 onEnable

底层的特性开关实例将与该函数的所有其他调用者共享,并共享一个观察者。

参数:
  • id (string) – 特性在 Features.toml 中的定义 ID。

  • observer (object) – 特性状态更改时要调用的函数。所有观察者函数都是可选的。

  • observer.onEnable (function) – 特性启用时调用。

  • observer.onDisable (function) – 特性禁用时调用。

  • observer.onChange (function) – 特性状态更改为任何值时调用。新值将传递给函数。

  • testDefinitionsUrl (string) – 可以从中获取定义的 URL。仅在测试中使用。

返回值:

Promise.<boolean> – 特性的当前值。

static FeatureGate.removeObserver(id, observer)

删除此特性的更改观察者。

参数:
  • id (string) – 特性在 Features.toml 中的定义 ID。

  • observer – 要删除的观察者,该观察者传递给了 addObserver。

static FeatureGate.isEnabled(id)

布尔类型特性开关的 getValue 的别名。

参数:
  • id (string) – 特性在 Features.toml 中的定义 ID。

抛出:

Error – 如果特性不是布尔型。

返回值:

Promise.<boolean> – 与此特性关联的值的 Promise。

static FeatureGate.fromId(id, testDefinitionsUrl)

构造一个在 Features.toml 中定义的特性开关对象。这是创建 FeatureGate 的主要方法。

参数:
  • id (string) – 特性在 Features.toml 中的定义 ID。

  • testDefinitionsUrl (string) – 可以从中获取定义的 URL。仅在测试中使用。

抛出:

如果传递的 idFeatures.toml 中未定义。

class FeatureGateImplementation()

可以重复使用的单个特性开关,用于更高级的用法。

特性实现者应使用 fromId()addListener()removeListener()removeAllListeners() 方法。此外,元数据可用于 UI 和分析。

FeatureGateImplementation.id

类型: string

在代码中引用此特性的简短字符串。

FeatureGateImplementation.title

类型: string

一个 Fluent 字符串 ID,它将解析为一些文本,以识别此特性供用户使用。

FeatureGateImplementation.description

类型: string

一个 Fluent 字符串 ID,它将解析为一个较长的字符串,显示给用户,解释该特性。

FeatureGateImplementation.type

类型: string

特性的类型。目前仅支持布尔型。这将来可能比 JS 类型更丰富,例如枚举值。

FeatureGateImplementation.bugNumbers

类型: Array.<number>

与此特性关联的 Bug 号码。

FeatureGateImplementation.isPublic

类型: boolean

如果此特性应在 Firefox 的此版本的高级设置面板中向用户公开。

FeatureGateImplementation.defaultValue

类型: boolean

此更新渠道中特性开关的默认值。

FeatureGateImplementation.restartRequired

类型: boolean

切换后,此特性是否需要浏览器重新启动才能生效。

FeatureGateImplementation.preference

类型: string

存储此功能值的偏好名称。

不应直接读取此偏好,而应通过 FeatureGate#addObserver 或 FeatureGate#getValue 访问其值。此属性是为了向后兼容而提供的。

FeatureGateImplementation.addObserver(observer)

为此功能的更改添加观察者。添加观察者后,onChange 将异步调用偏好的当前值。如果功能类型为布尔值且当前已启用,则还会额外调用 onEnable

参数:
  • observer (object) – 特性状态更改时要调用的函数。所有观察者函数都是可选的。

  • observer.onEnable (function) – 特性启用时调用。

  • observer.onDisable (function) – 特性禁用时调用。

返回值:

Promise.<boolean> – 特性的当前值。

FeatureGateImplementation.removeObserver(observer)

删除此特性的更改观察者。

参数:
  • observer – 要删除的传递给 addObserver 的观察者。

FeatureGateImplementation.removeAllObservers()

从此功能网关实例中删除所有观察者。

FeatureGateImplementation.getValue()

获取此功能网关的当前值。实现者应避免存储结果,以避免错过功能值的变化。如果需要存储功能的值,请考虑使用 addObserver()

返回值:

Promise.<boolean> – 与此特性关联的值的 Promise。

FeatureGateImplementation.isEnabled()

布尔类型特性开关的 getValue 的别名。

抛出:

Error – 如果特性不是布尔型。

返回值:

Promise.<boolean> – 与此特性关联的值的 Promise。