140 lines
6.1 KiB
ReStructuredText
140 lines
6.1 KiB
ReStructuredText
Utilities for implementing APIs
|
|
===============================
|
|
|
|
This page covers some utility classes that are useful for
|
|
implementing WebExtension APIs:
|
|
|
|
WindowManager
|
|
-------------
|
|
This class manages the mapping between the opaque window identifiers used
|
|
in the `browser.windows <https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/windows>`__ API.
|
|
See the reference docs `here <reference.html#windowmanager-class>`__.
|
|
|
|
TabManager
|
|
----------
|
|
This class manages the mapping between the opaque tab identifiers used
|
|
in the `browser.tabs <https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs>`__ API.
|
|
See the reference docs `here <reference.html#tabmanager-class>`__.
|
|
|
|
ExtensionSettingsStore
|
|
----------------------
|
|
ExtensionSettingsStore (ESS) is used for storing changes to settings that are
|
|
requested by extensions, and for finding out what the current value
|
|
of a setting should be, based on the precedence chain or a specific selection
|
|
made (typically) by the user.
|
|
|
|
When multiple extensions request to make a change to a particular
|
|
setting, the most recently installed extension will be given
|
|
precedence.
|
|
|
|
It is also possible to select a specific extension (or no extension, which
|
|
infers user-set) to control a setting. This will typically only happen via
|
|
ExtensionPreferencesManager described below. When this happens, precedence
|
|
control is not used until either a new extension is installed, or the controlling
|
|
extension is disabled or uninstalled. If user-set is specifically chosen,
|
|
precedence order will only be returned to by installing a new extension that
|
|
takes control of the setting.
|
|
|
|
ESS will manage what has control over a setting through any
|
|
extension state changes (ie. install, uninstall, enable, disable).
|
|
|
|
Notifications:
|
|
^^^^^^^^^^^^^^
|
|
|
|
"extension-setting-changed":
|
|
****************************
|
|
|
|
When a setting changes an event is emitted via the apiManager. It contains
|
|
the following:
|
|
|
|
* *action*: one of select, remove, enable, disable
|
|
|
|
* *id*: the id of the extension for which the setting has changed, may be null
|
|
if the setting has returned to default or user set.
|
|
|
|
* *type*: The type of setting altered. This is defined by the module using ESS.
|
|
If the setting is controlled through the ExtensionPreferencesManager below,
|
|
the value will be "prefs".
|
|
|
|
* *key*: The name of the setting altered.
|
|
|
|
* *item*: The new value, if any that has taken control of the setting.
|
|
|
|
|
|
ExtensionPreferencesManager
|
|
---------------------------
|
|
ExtensionPreferencesManager (EPM) is used to manage what extensions may control a
|
|
setting that results in changing a preference. EPM adds additional logic on top
|
|
of ESS to help manage the preference values based on what is in control of a
|
|
setting.
|
|
|
|
Defining a setting in an API
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
A preference setting is defined in an API module by calling EPM.addSetting. addSetting
|
|
allows the API to use callbacks that can handle setting preferences as needed. Since
|
|
the setting is defined at runtime, the API module must be loaded as necessary by EPM
|
|
to properly manage settings.
|
|
|
|
In the api module definition (e.g. ext-toolkit.json), the api must use `"settings": true`
|
|
so the management code can discover which API modules to load in order to manage a
|
|
setting. See browserSettings[1] as an example.
|
|
|
|
Settings that are exposed to the user in about:preferences also require special handling.
|
|
We typically show that an extension is in control of the preference, and prevent changes
|
|
to the setting. Some settings may allow the user to choose which extension (or none) has
|
|
control of the setting.
|
|
|
|
Preferences behavior
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
To actually set a setting, the module must call EPM.setSetting. This is typically done
|
|
via an extension API, such as browserSettings.settingName.set({ ...value data... }), though
|
|
it may be done at other times, such as during extension startup or install in a modules
|
|
onManifest handler.
|
|
|
|
Preferences are not always changed when an extension uses an API that results in a call
|
|
to EPM.setSetting. When setSetting is called, the values are stored by ESS (above), and if
|
|
the extension currently has control, or the setting is controllable by the extension, then
|
|
the preferences would be updated.
|
|
|
|
The preferences would also potentially be updated when installing, enabling, disabling or
|
|
uninstalling an extension, or by a user action in about:preferences (or other UI that
|
|
allows controlling the preferences). If all extensions that use a preference setting are
|
|
disabled or uninstalled, the prior user-set or default values would be returned to.
|
|
|
|
An extension may watch for changes using the onChange api (e.g. browserSettings.settingName.onChange).
|
|
|
|
[1] https://searchfox.org/mozilla-central/rev/04d8e7629354bab9e6a285183e763410860c5006/toolkit/components/extensions/ext-toolkit.json#19
|
|
|
|
Notifications:
|
|
^^^^^^^^^^^^^^
|
|
|
|
"extension-setting-changed:*name*":
|
|
***********************************
|
|
|
|
When a setting controlled by EPM changes an event is emitted via the apiManager. It contains
|
|
no other data. This is used primarily to implement the onChange API.
|
|
|
|
ESS vs. EPM
|
|
-----------
|
|
An API may use ESS when it needs to allow an extension to store a setting value that
|
|
affects how Firefox works, but does not result in setting a preference. An example
|
|
is allowing an extension to change the newTab value in the newTab service.
|
|
|
|
An API should use EPM when it needs to allow an extension to change a preference.
|
|
|
|
Using ESS/EPM with experimental APIs
|
|
------------------------------------
|
|
|
|
Properly managing settings values depends on the ability to load any modules that
|
|
define a setting. Since experimental APIs are defined inside the extension, there
|
|
are situations where settings defined in experimental APIs may not be correctly
|
|
managed. The could result in a preference remaining set by the extension after
|
|
the extension is disabled or installed, especially when that state is updated during
|
|
safe mode.
|
|
|
|
Extensions making use of settings in an experimental API should practice caution,
|
|
potentially unsetting the values when the extension is shutdown. Values used for
|
|
the setting could be stored in the extensions locale storage, and restored into
|
|
EPM when the extension is started again.
|