1Utilities for implementing APIs
2===============================
3
4This page covers some utility classes that are useful for
5implementing WebExtension APIs:
6
7WindowManager
8-------------
9This class manages the mapping between the opaque window identifiers used
10in the `browser.windows <https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/windows>`__ API.
11See the reference docs `here <reference.html#windowmanager-class>`__.
12
13TabManager
14----------
15This class manages the mapping between the opaque tab identifiers used
16in the `browser.tabs <https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs>`__ API.
17See the reference docs `here <reference.html#tabmanager-class>`__.
18
19ExtensionSettingsStore
20----------------------
21ExtensionSettingsStore (ESS) is used for storing changes to settings that are
22requested by extensions, and for finding out what the current value
23of a setting should be, based on the precedence chain or a specific selection
24made (typically) by the user.
25
26When multiple extensions request to make a change to a particular
27setting, the most recently installed extension will be given
28precedence.
29
30It is also possible to select a specific extension (or no extension, which
31infers user-set) to control a setting.  This will typically only happen via
32ExtensionPreferencesManager described below.  When this happens, precedence
33control is not used until either a new extension is installed, or the controlling
34extension is disabled or uninstalled.  If user-set is specifically chosen,
35precedence order will only be returned to by installing a new extension that
36takes control of the setting.
37
38ESS will manage what has control over a setting through any
39extension state changes (ie. install, uninstall, enable, disable).
40
41Notifications:
42^^^^^^^^^^^^^^
43
44"extension-setting-changed":
45****************************
46
47  When a setting changes an event is emitted via the apiManager. It contains
48  the following:
49
50  * *action*: one of select, remove, enable, disable
51
52  * *id*: the id of the extension for which the setting has changed, may be null
53    if the setting has returned to default or user set.
54
55  * *type*: The type of setting altered.  This is defined by the module using ESS.
56    If the setting is controlled through the ExtensionPreferencesManager below,
57    the value will be "prefs".
58
59  * *key*: The name of the setting altered.
60
61  * *item*: The new value, if any that has taken control of the setting.
62
63
64ExtensionPreferencesManager
65---------------------------
66ExtensionPreferencesManager (EPM) is used to manage what extensions may control a
67setting that results in changing a preference.  EPM adds additional logic on top
68of ESS to help manage the preference values based on what is in control of a
69setting.
70
71Defining a setting in an API
72^^^^^^^^^^^^^^^^^^^^^^^^^^^^
73
74A preference setting is defined in an API module by calling EPM.addSetting.  addSetting
75allows the API to use callbacks that can handle setting preferences as needed.  Since
76the setting is defined at runtime, the API module must be loaded as necessary by EPM
77to properly manage settings.
78
79In the api module definition (e.g. ext-toolkit.json), the api must use `"settings": true`
80so the management code can discover which API modules to load in order to manage a
81setting.  See browserSettings[1] as an example.
82
83Settings that are exposed to the user in about:preferences also require special handling.
84We typically show that an extension is in control of the preference, and prevent changes
85to the setting.  Some settings may allow the user to choose which extension (or none) has
86control of the setting.
87
88Preferences behavior
89^^^^^^^^^^^^^^^^^^^^
90
91To actually set a setting, the module must call EPM.setSetting.  This is typically done
92via an extension API, such as browserSettings.settingName.set({ ...value data... }), though
93it may be done at other times, such as during extension startup or install in a modules
94onManifest handler.
95
96Preferences are not always changed when an extension uses an API that results in a call
97to EPM.setSetting.  When setSetting is called, the values are stored by ESS (above), and if
98the extension currently has control, or the setting is controllable by the extension, then
99the preferences would be updated.
100
101The preferences would also potentially be updated when installing, enabling, disabling or
102uninstalling an extension, or by a user action in about:preferences (or other UI that
103allows controlling the preferences).  If all extensions that use a preference setting are
104disabled or uninstalled, the prior user-set or default values would be returned to.
105
106An extension may watch for changes using the onChange api (e.g. browserSettings.settingName.onChange).
107
108[1] https://searchfox.org/mozilla-central/rev/04d8e7629354bab9e6a285183e763410860c5006/toolkit/components/extensions/ext-toolkit.json#19
109
110Notifications:
111^^^^^^^^^^^^^^
112
113"extension-setting-changed:*name*":
114***********************************
115
116  When a setting controlled by EPM changes an event is emitted via the apiManager. It contains
117  no other data.  This is used primarily to implement the onChange API.
118
119ESS vs. EPM
120-----------
121An API may use ESS when it needs to allow an extension to store a setting value that
122affects how Firefox works, but does not result in setting a preference.  An example
123is allowing an extension to change the newTab value in the newTab service.
124
125An API should use EPM when it needs to allow an extension to change a preference.
126
127Using ESS/EPM with experimental APIs
128------------------------------------
129
130Properly managing settings values depends on the ability to load any modules that
131define a setting.  Since experimental APIs are defined inside the extension, there
132are situations where settings defined in experimental APIs may not be correctly
133managed.  The could result in a preference remaining set by the extension after
134the extension is disabled or installed, especially when that state is updated during
135safe mode.
136
137Extensions making use of settings in an experimental API should practice caution,
138potentially unsetting the values when the extension is shutdown.  Values used for
139the setting could be stored in the extensions locale storage, and restored into
140EPM when the extension is started again.
141