aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhackademix <giorgio@maone.net>2018-09-13 00:23:24 +0200
committerhackademix <giorgio@maone.net>2018-09-13 15:47:27 +0200
commita2c93c2663d4f61b3c88d39f27fa492aca999455 (patch)
tree33a1f01c1f92e9e507aa7c67995bf4a97d77cfe2
parent1eac93ab65df6963b464a780b92ff06651ba96d6 (diff)
Support for batch async list operations.
-rw-r--r--bg/ListManager.js35
-rw-r--r--bg/Storage.js62
2 files changed, 62 insertions, 35 deletions
diff --git a/bg/ListManager.js b/bg/ListManager.js
index 34d9531..7284aca 100644
--- a/bg/ListManager.js
+++ b/bg/ListManager.js
@@ -30,20 +30,21 @@ class ListManager {
this.lists = {whitelist, blacklist};
this.builtInHashes = new Set(builtInHashes);
}
- async whitelist(key) {
- await this.lists.blacklist.remove(key);
- await this.lists.whitelist.store(key);
+
+ static async move(fromList, toList, ...keys) {
+ await Promise.all([fromList.remove(...keys), toList.store(...keys)]);
}
- async blacklist(key) {
- await this.lists.whitelist.remove(key);
- await this.lists.blacklist.store(key);
+
+ async whitelist(...keys) {
+ ListManager.move(this.lists.blacklist, this.lists.whitelist, ...keys);
}
- async forget(key) {
- for (let list of Object.values(this.lists)) {
- await list.remove(key);
- }
+ async blacklist(...keys) {
+ ListManager.move(this.lists.whitelist, this.lists.blacklist, ...keys);
}
- /* key is a string representing either a URL or an optional path
+ async forget(...keys) {
+ await Promise.all(Object.values(this.lists).map(l => l.remove(...keys)));
+ }
+ /* key is a string representing either a URL or an optional path
with a trailing (hash).
Returns "blacklisted", "whitelisted" or defValue
*/
@@ -53,16 +54,16 @@ class ListManager {
if (!match) {
let url = ListStore.urlItem(key);
let site = ListStore.siteItem(key);
- return (blacklist.contains(url) || blacklist.contains(site))
+ return (blacklist.contains(url) || blacklist.contains(site))
? "blacklisted"
- : whitelist.contains(url) || whitelist.contains(site)
- ? "whitelisted" : defValue;
+ : whitelist.contains(url) || whitelist.contains(site)
+ ? "whitelisted" : defValue;
}
-
+
let [hashItem, srcHash] = match; // (hash), hash
-
+
return blacklist.contains(hashItem) ? "blacklisted"
- : this.builtInHashes.has(srcHash) || whitelist.contains(hashItem)
+ : this.builtInHashes.has(srcHash) || whitelist.contains(hashItem)
? "whitelisted"
: defValue;
}
diff --git a/bg/Storage.js b/bg/Storage.js
index ecdc9e4..a83ce8f 100644
--- a/bg/Storage.js
+++ b/bg/Storage.js
@@ -23,11 +23,14 @@
A tiny wrapper around extensions storage API, supporting CSV serialization for
retro-compatibility
*/
+"use strict";
var Storage = {
ARRAY: {
- async load(key) {
- let array = (await browser.storage.local.get(key))[key];
+ async load(key, array = undefined) {
+ if (array === undefined) {
+ array = (await browser.storage.local.get(key))[key];
+ }
return array ? new Set(array) : new Set();
},
async save(key, list) {
@@ -40,7 +43,7 @@ var Storage = {
let csv = (await browser.storage.local.get(key))[key];
return csv ? new Set(csv.split(/\s*,\s*/)) : new Set();
},
-
+
async save(key, list) {
return await browser.storage.local.set({[key]: [...list].join(",")});
}
@@ -56,8 +59,13 @@ class ListStore {
this.key = key;
this.storage = storage;
this.items = new Set();
+ browser.storage.onChanged.addListener(changes => {
+ if (!this.saving && this.key in changes) {
+ this.load(changes[this.key].newValue);
+ }
+ });
}
-
+
static hashItem(hash) {
return hash.startsWith("(") ? hash : `(${hash})`;
}
@@ -73,32 +81,50 @@ class ListStore {
return `${url}/*`;
}
}
-
+
async save() {
- return await this.storage.save(this.key, this.items);
+ this._saving = true;
+ try {
+ return await this.storage.save(this.key, this.items);
+ } finally {
+ this._saving = false;
+ }
}
-
- async load() {
+
+ async load(values = undefined) {
try {
- this.items = await this.storage.load(this.key);
+ this.items = await this.storage.load(this.key, values);
} catch (e) {
console.error(e);
}
return this.items;
}
-
- async store(item) {
+
+ async store(...items) {
let size = this.items.size;
- return (size !== this.items.add(item).size) && await this.save();
+ let changed = false;
+ for (let item of items) {
+ if (size !== this.items.add(item).size) {
+ changed = true;
+ }
+ }
+ return changed && await this.save();
}
-
- async remove(item) {
- return this.items.delete(item) && await this.save();
+
+ async remove(...items) {
+ let changed = false;
+ for (let item of items) {
+ if (this.items.delete(item)) {
+ changed = true;
+ }
+ }
+ return changed && await this.save();
}
-
+
contains(item) {
return this.items.has(item);
}
}
-
-module.exports = { ListStore, Storage };
+if (typeof module === "object") {
+ module.exports = { ListStore, Storage };
+}