.. _components/featuregates:
=============
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``:
.. code-block:: toml
[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 value:
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:
.. code-block:: toml
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:
.. code-block:: toml
default-value = {default = false, nightly = true}
Values can depend on multiple conditions. For example, to enable a feature
only on Nightly running on Windows:
.. code-block:: toml
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:
.. code-block:: toml
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
. For example in Features.toml:
.. code-block:: 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:
.. code-block:: fluent
experimental-features-demo-feature =
.label = Example Demo Feature
experimental-features-demo-feature-description = Example demo feature that can point to .com links and .org 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
be ``false``. 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`` or
``about:config``. If not provided, the default is to make a feature
private for all channels.
Feature Gate API
================
..
(comment) The below lists should be kept in sync with the contents of the
classes they are documenting. An explicit list is used so that the
methods can be put in a particular order.
.. js:autoclass:: FeatureGate
:members: addObserver, removeObserver, isEnabled, fromId
.. js:autoclass:: FeatureGateImplementation
:members: id, title, description, type, bugNumbers, isPublic, defaultValue, restartRequired, preference, addObserver, removeObserver, removeAllObservers, getValue, isEnabled
Feature implementors should use the methods :func:`fromId`,
:func:`addListener`, :func:`removeListener` and
:func:`removeAllListeners`. Additionally, metadata is available for UI and
analysis.