The remote-settings.js module offers the ability to fetch remote settings that are kept in sync with Mozilla servers.
const { RemoteSettings } = ChromeUtils.import("resource://services-common/remote-settings.js", {});
const data = await RemoteSettings("a-key").get();
/*
data == [
{label: "Yahoo", enabled: true, weight: 10, id: "d0782d8d", last_modified: 1522764475905},
{label: "Google", enabled: true, weight: 20, id: "8883955f", last_modified: 1521539068414},
{label: "Ecosia", enabled: false, weight: 5, id: "337c865d", last_modified: 1520527480321},
]
*/
for(const entry of data) {
// Do something with entry, e.g:
// await InternalAPI.load(entry.id, entry.label, entry.weight);
});
Note
The id
and last_modified
(timestamp) attributes are assigned by the server.
The list can optionally be filtered or ordered:
const subset = await RemoteSettings("a-key").get({
filters: {
"enabled": true,
},
order: "-weight"
});
In order to deliver settings to subsets of the population, targets are defined for each entry (platform, language, channel, version range, …).
When the list is retrieved on the client side with RemoteSettings("key").get()
, each target is evaluated and entries are filtered.
Note
The behaviour is similar to what is done for the Normandy/SHIELD recipes.
The change
event allows to be notified when the remote settings are changed. The event data
attribute contains the new list of settings.
RemoteSettings("a-key").on("change", (event) => {
const { data } = event;
for(const entry of data) {
// Do something with entry...
}
});
Note
Currently, the update of remote settings is triggered by the nsBlocklistService (~ every 24H). But this could change to be more frequent, and even integrated within our Push service.
The create
, update
, and delete
events work the same way. Except that the event data
attribute only contains the list of entries that were created, updated, or deleted:
RemoteSettings("a-key").on("delete", async ({ data }) => {
for(const deleted of data) {
await InternalAPI.unload(deleted.id);
}
});
When an entry has a file attached to it, it has an attachment
attribute, which contains the file related information (url, hash, size, mimetype, etc.). Remote files are not downloaded automatically.
const data = await RemoteSettings("a-key").get();
data.filter(d => d.attachment)
.forEach(async ({ attachment: { url, filename, size } }) => {
if (size < OS.freeDiskSpace) {
await downloadLocally(url, filename);
}
});
Some uptake telemetry <telemetry/collection/uptake>
is collected in order to monitor how remote settings are propagated.
It is submitted to a single keyed histogram <histogram-type-keyed>
whose id is UPTAKE_REMOTE_CONTENT_RESULT_1
and the key is prefixed with main/
(eg. main/a-key
with the example above).
Staff members can create new kinds of remote settings, following this documentation.
It basically consists in:
- Choosing a key (eg.
search-providers
) - Assigning collaborators to editors and reviewers groups
- (optional) Define a JSONSchema to validate entries
- (optional) Allow attachments on entries
And once done:
- Create, modify or delete entries and let reviewers approve the changes
- Wait for Firefox to pick-up the changes for your settings key