From c2530fc59734b16a642723b3a9401f9da5033b2d Mon Sep 17 00:00:00 2001 From: hackademix Date: Thu, 13 Sep 2018 16:18:43 +0200 Subject: Adjust directory layout and packaging to allow Storage.js to be shared with the settings page in the xpi release. --- common/Storage.js | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 common/Storage.js (limited to 'common') diff --git a/common/Storage.js b/common/Storage.js new file mode 100644 index 0000000..a83ce8f --- /dev/null +++ b/common/Storage.js @@ -0,0 +1,130 @@ +/** +* GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript. +* +* Copyright (C) 2018 Giorgio Maone +* +* This file is part of GNU LibreJS. +* +* GNU LibreJS is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GNU LibreJS is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GNU LibreJS. If not, see . +*/ + +/** + A tiny wrapper around extensions storage API, supporting CSV serialization for + retro-compatibility +*/ +"use strict"; + +var Storage = { + ARRAY: { + 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) { + return await browser.storage.local.set({[key]: [...list]}); + }, + }, + + CSV: { + async load(key) { + 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(",")}); + } + } +}; + +/** + A class to hold and persist blacklists and whitelists +*/ + +class ListStore { + constructor(key, storage = Storage.ARRAY) { + 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})`; + } + static urlItem(url) { + let queryPos = url.indexOf("?"); + return queryPos === -1 ? url : url.substring(0, queryPos); + } + static siteItem(url) { + if (url.endsWith("/*")) return url; + try { + return `${new URL(url).origin}/*`; + } catch (e) { + return `${url}/*`; + } + } + + async save() { + this._saving = true; + try { + return await this.storage.save(this.key, this.items); + } finally { + this._saving = false; + } + } + + async load(values = undefined) { + try { + this.items = await this.storage.load(this.key, values); + } catch (e) { + console.error(e); + } + return this.items; + } + + async store(...items) { + let size = this.items.size; + let changed = false; + for (let item of items) { + if (size !== this.items.add(item).size) { + changed = true; + } + } + return changed && 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); + } +} +if (typeof module === "object") { + module.exports = { ListStore, Storage }; +} -- cgit v1.2.3