Feature Gates
A feature gate is a high level tool to turn features on and off. It provides metadata about features, a simple, opinionated API, and avoid many potential pitfalls of other systems, such as using preferences directly. It is designed to be compatible with tools that want to know and affect the state of features in Firefox over time and in the wild.
Feature Definitions
All features must have a definition, specified in
toolkit/components/featuregates/Features.toml
. These definitions include
data such as references to title and description strings (to be shown to users),
and bug numbers (to track the development of the feature over time). Here is an
example feature definition with an id of demo-feature
:
[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}
The references defined in the title and description values point to strings
stored in toolkit/locales/en-US/toolkit/featuregates/features.ftl
. The title
string should specify the user-facing string as the label attribute.
Targeted values
Several fields can take a value that indicates it varies by channel and OS. These are known as targeted values. The simplest computed value is to simply provide the value:
default-value = true
A more interesting example is to make a feature default to true on Nightly, but be disabled otherwise. That would look like this:
default-value = {default = false, nightly = true}
Values can depend on multiple conditions. For example, to enable a feature only on Nightly running on Windows:
default-value = {default = false, "nightly,win" = true}
Multiple sets of conditions can be specified, however use caution here: if
multiple sets could match (except default
), the set chosen is undefined.
An example of safely using multiple conditions:
default-value = {default = false, nightly = true, "beta,win" = true}
The default
condition is required. It is used as a fallback in case no
more-specific case matches. The conditions allowed are
default
release
beta
dev-edition
nightly
esr
win
mac
linux
android
Fields
- title
Required. The string ID of the human readable name for the feature, meant to be shown to users. Should fit onto a single line. The actual string should be defined in
toolkit/locales/en-US/toolkit/featuregates/features.ftl
with the user-facing value defined as the label attribute of the string.- description
Required. The string ID of the human readable description for the feature, meant to be shown to users. Should be at most a paragraph. The actual string should be defined in
toolkit/locales/en-US/toolkit/featuregates/features.ftl
.- description-links
Optional. A dictionary of key-value pairs that are referenced in the description. The key name must appear in the description localization text as <a data-l10n-name=”key-name”>. For example in 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}
and in 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
Required. A list of bug numbers related to this feature. This should likely be the metabug for the the feature, but any related bugs can be included. At least one bug is required.
- restart-required
Required. If this feature requires a the browser to be restarted for changes to take effect, this field should be
true
. Otherwise, the field should befalse
. Features should aspire to not require restarts and react to changes to the preference dynamically.- type
Required. The type of value this feature relates to. The only legal value is
boolean
, but more may be added in the future.- preference
Optional. The preference used to track the feature. If a preference is not provided, one will be automatically generated based on the feature ID. It is not recommended to specify a preference directly, except to integrate with older code. In the future, alternate storage mechanisms may be used if a preference is not supplied.
- default-value
Optional. This is a targeted value describing the value for the feature if no other changes have been made, such as in a fresh profile. If not provided, the default for a boolean type feature gate will be
false
for all profiles.- is-public
Optional. This is a targeted value describing on which branches this feature should be exposed to users. When a feature is made public, it may show up in a future UI that allows users to opt-in to experimental features. This is not related to
about:preferences
orabout:config
. If not provided, the default is to make a feature private for all channels.
Feature Gate API
- class FeatureGate()
A high level control for turning features on and off.
- static FeatureGate.addObserver(id, observer, testDefinitionsUrl)
Add an observer for a feature gate by ID. If the feature is of type boolean and currently enabled, onEnable will be called.
The underlying feature gate instance will be shared with all other callers of this function, and share an observer.
- Arguments:
id (string) – The ID of the feature’s definition in Features.toml.
observer (object) – Functions to be called when the feature changes. All observer functions are optional.
observer.onEnable (function) – Called when the feature becomes enabled.
observer.onDisable (function) – Called when the feature becomes disabled.
observer.onChange (function) – Called when the feature’s state changes to any value. The new value will be passed to the function.
testDefinitionsUrl (string) – A URL from which definitions can be fetched. Only use this in tests.
- Returns:
Promise.<boolean> – The current value of the feature.
- static FeatureGate.removeObserver(id, observer)
Remove an observer of changes from this feature
- Arguments:
id (string) – The ID of the feature’s definition in Features.toml.
observer – Then observer that was passed to addObserver to remove.
- static FeatureGate.isEnabled(id)
An alias of getValue for boolean typed feature gates.
- Arguments:
id (string) – The ID of the feature’s definition in Features.toml.
- Throws:
Error – If the feature is not a boolean.
- Returns:
Promise.<boolean> – A promise for the value associated with this feature.
- static FeatureGate.fromId(id, testDefinitionsUrl)
Constructs a feature gate object that is defined in
Features.toml
. This is the primary way to create aFeatureGate
.- Arguments:
id (string) – The ID of the feature’s definition in Features.toml.
testDefinitionsUrl (string) – A URL from which definitions can be fetched. Only use this in tests.
- Throws:
If the
id
passed is not defined inFeatures.toml
.
- class FeatureGateImplementation()
An individual feature gate that can be re-used for more advanced usage.
Feature implementors should use the methods
fromId()
,addListener()
,removeListener()
andremoveAllListeners()
. Additionally, metadata is available for UI and analysis.- FeatureGateImplementation.id
type: string
A short string used to refer to this feature in code.
- FeatureGateImplementation.title
type: string
A Fluent string ID that will resolve to some text to identify this feature to users.
- FeatureGateImplementation.description
type: string
A Fluent string ID that will resolve to a longer string to show to users that explains the feature.
- FeatureGateImplementation.type
type: string
The type of feature. Currently only booleans are supported. This may be richer than JS types in the future, such as enum values.
- FeatureGateImplementation.bugNumbers
type: Array.<number>
Bug numbers associated with this feature.
- FeatureGateImplementation.isPublic
type: boolean
If this feature should be exposed to users in an advanced settings panel for this build of Firefox.
- FeatureGateImplementation.defaultValue
type: boolean
The default value for the feature gate for this update channel.
- FeatureGateImplementation.restartRequired
type: boolean
Whether this feature requires a browser restart to take effect after toggling.
- FeatureGateImplementation.preference
type: string
The name of the preference that stores the value of this feature.
This preference should not be read directly, but instead its values should be accessed via FeatureGate#addObserver or FeatureGate#getValue. This property is provided for backwards compatibility.
- FeatureGateImplementation.addObserver(observer)
Add an observer for changes to this feature. When the observer is added, onChange will asynchronously be called with the current value of the preference. If the feature is of type boolean and currently enabled, onEnable will additionally be called.
- Arguments:
observer (object) – Functions to be called when the feature changes. All observer functions are optional.
observer.onEnable (function) – Called when the feature becomes enabled.
observer.onDisable (function) – Called when the feature becomes disabled.
- Returns:
Promise.<boolean> – The current value of the feature.
- FeatureGateImplementation.removeObserver(observer)
Remove an observer of changes from this feature
- Arguments:
observer – The observer that was passed to addObserver to remove.
- FeatureGateImplementation.removeAllObservers()
Removes all observers from this instance of the feature gate.
- FeatureGateImplementation.getValue()
Get the current value of this feature gate. Implementors should avoid storing the result to avoid missing changes to the feature’s value. Consider using
addObserver()
if it is necessary to store the value of the feature.- Returns:
Promise.<boolean> – A promise for the value associated with this feature.
- FeatureGateImplementation.isEnabled()
An alias of getValue for boolean typed feature gates.
- Throws:
Error – If the feature is not a boolean.
- Returns:
Promise.<boolean> – A promise for the value associated with this feature.