Provides ability to store/load configurations, on Firefox 52 and later.
By the bug 1197346, now we don't have to do inter-sandboxes comunication to read/write configuration values. After the bug, this library is still effective to provide easy access for configuration values.
storage
In manifest.json
, load the file Configs.js
from both the background page and others, like:
{
"background": {
"scripts": [
"path/to/Configs.js",
"path/to/common.js"
]
},
"content_scripts": [
{
"all_frames": true,
"matches": [
"<all_urls>"
],
"js": [
"path/to/Configs.js",
"path/to/common.js",
"..."
],
"run_at": "document_start"
}
],
"options_ui": {
"page": "path/to/options.html",
"chrome_style": true
},
"permissions": [
"storage"
]
}
options.html
is:
<!DOCTYPE html>
<script type="application/javascript" src="./Configs.js"></script>
<script type="application/javascript" src="./common.js"></script>
...
And, define an instance with default values on each namespace like:
// common.js
var configs = new Configs({
enabled: true,
advanced: false,
attributes: 'alt|title',
entries: [],
cache: {}
});
The instance has a built-in property $loaded
. It is a Promise
, so you can do something after all stored user values are loaded:
configs.$loaded.then(function() {
MyService.start();
});
After all values are loaded, you can access loaded values via its own properties same to the given default values:
console.log(configs.enabled); // => true (default value)
console.log(configs.advanced); // => false (default value)
console.log(configs.attributes); // => "alt|title" (default value)
console.log(configs.cache); // => {} (default value)
If you set a new value, it will be notified to the background page, then stored to the local storage as the user value and dispatched to all other namespaces.
// in the options.html
configs.enabled = false;
// in content script
console.log(configs.enabled); // => false (user value)
You still can get default values easily, with a prefix $default.
:
console.log(configs.$default.enabled); // => true (default value)
configs.enabled = configs.$default.enabled; // reset to default
configs.$reset(); // reset all to default
When you hope to update a non-primitive configuration values, note that you must replace the object itself.
For example, deep clone based on JSON.parse()
and JSON.stringify()
will be effective:
var newEntries = JSON.parse(JSON.stringify(configs.entries)); // deep clone
entries.push('added item');
configs.entries = newEntries;
var newCache = JSON.parse(JSON.stringify(configs.cache)); // deep clone
newCache.addedItem = true;
configs.cache = newCache;
In other words, following codes don't work as expected:
// Directly modified object won't be saved.
configs.entries.push('added item');
configs.cache.addedItems = true;
// Simple assignment also uses the object itself,
// so this example is same to the previous.
{
let newEntries = configs.entries;
newEntries.push('added item');
configs.entries = newEntries;
let newCache = configs.cache;
newCache.addedItems = true;
configs.cache = newCache;
}
// Shallow clone is better than above, and it works as expected
// only when all values are primitive.
{
let newEntries = configs.entries.slice(0);
newEntries.push('added item');
configs.entries = newEntries;
let newCache = { ...configs.cache }; // shallow clone
newCache.addedItems = true;
configs.cache = newCache;
}
This library supports storage.managed
. Configuration items which have any value in storage.managed
are treated as locked configuration and they become unchangable. For more details, see the API documentation.
For providing default configs instead of completely managed locked configs, please use :unlock
suffix for each key.
If you define :unlocked
-suffixed key with false
value, the corresponding config will become unlocked, for example:
{
"name": "...",
"description": "...",
"type": "storage",
"data":
{
"color": "#FF0000",
"color:locked", false // <= HERE! This makes "color" unlocked.
}
}
This library supports storage.sync. To use it, set syncKeys
in the optional second parameter of the Configs
constructor to an array of the key names that should be synced:
var configs = new Configs({
enabled: true,
advanced: false,
attributes: 'alt|title'
}, {
syncKeys: ['enabled', 'attributes']
});
Alternately, specify (possibly empty) array of keys which should not be synced in localKeys
:
var configs = new Configs({
enabled: true,
advanced: false,
attributes: 'alt|title'
}, {
localKeys: ['advanced']
});