summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/browser.js (renamed from common/browser.mjs)11
-rw-r--r--common/connection_types.js (renamed from common/connection_types.mjs)14
-rw-r--r--common/is_background.mjs17
-rw-r--r--common/lock.js (renamed from common/lock.mjs)60
-rw-r--r--common/once.js44
-rw-r--r--common/once.mjs42
-rw-r--r--common/storage_client.js189
-rw-r--r--common/storage_client.mjs186
-rw-r--r--common/stored_types.js44
-rw-r--r--common/stored_types.mjs38
10 files changed, 329 insertions, 316 deletions
diff --git a/common/browser.mjs b/common/browser.js
index 0d1b233..1d9edda 100644
--- a/common/browser.mjs
+++ b/common/browser.js
@@ -15,4 +15,13 @@
* chrome-based and firefox-based browsers.
*/
-export default (window.browser === undefined) ? chrome : browser;
+(() => {
+ if (window.browser === undefined) {
+ window.browser = window.chrome;
+ window.is_chrome = true;
+ window.is_mozilla = false;
+ } else {
+ window.is_chrome = false;
+ window.is_mozilla = true;
+ }
+})();
diff --git a/common/connection_types.mjs b/common/connection_types.js
index 12d6de3..a01a777 100644
--- a/common/connection_types.mjs
+++ b/common/connection_types.js
@@ -8,14 +8,18 @@
* - GPLv3 or (at your option) any later version
*/
+"use strict";
+
/*
* Those need to be strings so they can be used as 'name' parameter
* to browser.runtime.connect()
*/
-const CONNECTION_TYPE = {
- REMOTE_STORAGE : "0",
- PAGE_ACTIONS : "1"
-};
+(() => {
+ const CONNECTION_TYPE = {
+ REMOTE_STORAGE : "0",
+ PAGE_ACTIONS : "1"
+ };
-export default CONNECTION_TYPE;
+ window.CONNECTION_TYPE = CONNECTION_TYPE;
+})();
diff --git a/common/is_background.mjs b/common/is_background.mjs
deleted file mode 100644
index ef728a7..0000000
--- a/common/is_background.mjs
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
-* Myext programmatic check of where the script is being run
-*
-* Copyright (C) 2021 Wojtek Kosior
-*
-* Dual-licensed under:
-* - 0BSD license
-* - GPLv3 or (at your option) any later version
-*/
-
-/* This needs to be changed if we ever modify the html file path. */
-
-export default function is_background()
-{
- return window.location.protocol === "moz-extension:" &&
- window.location.pathname === "/background/background.html";
-}
diff --git a/common/lock.mjs b/common/lock.js
index 596dd9c..107287f 100644
--- a/common/lock.mjs
+++ b/common/lock.js
@@ -24,32 +24,38 @@
"use strict";
-export function make_lock() {
- return {free: true, queue: []};
-}
-
-function _lock(lock, cb) {
- if (lock.free) {
- lock.free = false;
- setTimeout(cb);
- } else {
- lock.queue.push(cb);
+(() => {
+ function make_lock() {
+ return {free: true, queue: []};
}
-}
-
-export function lock(lock) {
- return new Promise((resolve, reject) => _lock(lock, resolve));
-}
-
-export function unlock(lock) {
- if (lock.free)
- throw new Exception("Attempting to release a free lock");
-
- if (lock.queue.length === 0) {
- lock.free = true;
- } else {
- let cb = lock.queue[0];
- lock.queue.splice(0, 1);
- setTimeout(cb);
+
+ function _lock(lock, cb) {
+ if (lock.free) {
+ lock.free = false;
+ setTimeout(cb);
+ } else {
+ lock.queue.push(cb);
+ }
+ }
+
+ function lock(lock) {
+ return new Promise((resolve, reject) => _lock(lock, resolve));
}
-}
+
+ function unlock(lock) {
+ if (lock.free)
+ throw new Exception("Attempting to release a free lock");
+
+ if (lock.queue.length === 0) {
+ lock.free = true;
+ } else {
+ let cb = lock.queue[0];
+ lock.queue.splice(0, 1);
+ setTimeout(cb);
+ }
+ }
+
+ window.make_lock = make_lock;
+ window.lock = lock;
+ window.unlock = unlock;
+})();
diff --git a/common/once.js b/common/once.js
new file mode 100644
index 0000000..1842a47
--- /dev/null
+++ b/common/once.js
@@ -0,0 +1,44 @@
+/**
+* Myext feature initialization promise
+*
+* Copyright (C) 2021 Wojtek Kosior
+*
+* Dual-licensed under:
+* - 0BSD license
+* - GPLv3 or (at your option) any later version
+*/
+
+"use strict";
+
+/*
+ * This module provides an easy way to wrap an async function into a promise
+ * so that it only gets executed once.
+ */
+
+(() => {
+ async function assign_result(state, result_producer)
+ {
+ state.result = await result_producer();
+ state.ready = true;
+ for (let cb of state.waiting)
+ setTimeout(cb, 0, state.result);
+ state.waiting = undefined;
+ }
+
+ async function get_result(state)
+ {
+ if (state.ready)
+ return state.result;
+
+ return new Promise((resolve, reject) => state.waiting.push(resolve));
+ }
+
+ function make_once(result_producer)
+ {
+ let state = {waiting : [], ready : false, result : undefined};
+ assign_result(state, result_producer);
+ return () => get_result(state);
+ }
+
+ window.make_once = make_once;
+})();
diff --git a/common/once.mjs b/common/once.mjs
deleted file mode 100644
index 0f76366..0000000
--- a/common/once.mjs
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
-* Myext feature initialization promise
-*
-* Copyright (C) 2021 Wojtek Kosior
-*
-* Dual-licensed under:
-* - 0BSD license
-* - GPLv3 or (at your option) any later version
-*/
-
-"use strict";
-
-/*
- * This module provides an easy way to wrap an async function into a promise
- * so that it only gets executed once.
- */
-
-async function assign_result(state, result_producer)
-{
- state.result = await result_producer();
- state.ready = true;
- for (let cb of state.waiting)
- setTimeout(cb, 0, state.result);
- state.waiting = undefined;
-}
-
-async function get_result(state)
-{
- if (state.ready)
- return state.result;
-
- return new Promise((resolve, reject) => state.waiting.push(resolve));
-}
-
-export function make_once(result_producer)
-{
- let state = {waiting : [], ready : false, result : undefined};
- assign_result(state, result_producer);
- return () => get_result(state);
-}
-
-export default make_once;
diff --git a/common/storage_client.js b/common/storage_client.js
new file mode 100644
index 0000000..39ece44
--- /dev/null
+++ b/common/storage_client.js
@@ -0,0 +1,189 @@
+/**
+* Myext storage through connection (client side)
+*
+* Copyright (C) 2021 Wojtek Kosior
+*
+* Dual-licensed under:
+* - 0BSD license
+* - GPLv3 or (at your option) any later version
+*/
+
+"use strict";
+
+(() => {
+ const CONNECTION_TYPE = window.CONNECTION_TYPE;
+ const TYPE_PREFIX = window.TYPE_PREFIX;
+ const list_prefixes = window.list_prefixes;
+ const make_once = window.make_once;
+ const browser = window.browser;
+
+ var call_id = 0;
+ var port;
+ var calls_waiting = new Map();
+
+ function set_call_callback(resolve, reject, func, args)
+ {
+ port.postMessage([call_id, func, args]);
+ calls_waiting.set(call_id++, [resolve, reject]);
+ }
+
+ async function remote_call(func, args)
+ {
+ return new Promise((resolve, reject) =>
+ set_call_callback(resolve, reject, func, args));
+ }
+
+ function handle_message(message)
+ {
+ let callbacks = calls_waiting.get(message.call_id);
+ if (callbacks === undefined) {
+ handle_change(message);
+ return;
+ }
+
+ let [resolve, reject] = callbacks;
+ calls_waiting.delete(message.call_id);
+ if (message.error !== undefined)
+ setTimeout(reject, 0, message.error);
+ else
+ setTimeout(resolve, 0, message.result);
+ }
+
+ function list(name, prefix)
+ {
+ return {prefix, name, listeners : new Set()};
+ }
+
+ var scripts = list("scripts", TYPE_PREFIX.SCRIPT);
+ var bundles = list("bundles", TYPE_PREFIX.BUNDLE);
+ var pages = list("pages", TYPE_PREFIX.PAGE);
+
+ const list_by_prefix = {
+ [TYPE_PREFIX.SCRIPT] : scripts,
+ [TYPE_PREFIX.BUNDLE] : bundles,
+ [TYPE_PREFIX.PAGE] : pages
+ };
+
+ var resolve_init;
+
+ function handle_first_message(message)
+ {
+ for (let prefix of Object.keys(message))
+ list_by_prefix[prefix].map = new Map(message[prefix]);
+
+ port.onMessage.removeListener(handle_first_message);
+ port.onMessage.addListener(handle_message);
+
+ resolve_init();
+ }
+
+ function handle_change(change)
+ {
+ let list = list_by_prefix[change.prefix];
+
+ if (change.new_val === undefined)
+ list.map.delete(change.item);
+ else
+ list.map.set(change.item, change.new_val);
+
+ for (let listener_callback of list.listeners)
+ listener_callback(change);
+ }
+
+ var exports = {};
+
+ function start_connection(resolve)
+ {
+ resolve_init = resolve;
+ port = browser.runtime.connect({name : CONNECTION_TYPE.REMOTE_STORAGE});
+ port.onMessage.addListener(handle_first_message);
+ }
+
+ async function init() {
+ await new Promise((resolve, reject) => start_connection(resolve));
+ return exports;
+ }
+
+ for (let call_name of ["set", "remove", "replace", "clear"])
+ exports [call_name] = (...args) => remote_call(call_name, args);
+
+ // TODO: Much of the code below is copy-pasted from /background/storage.mjs.
+ // This should later be refactored into a separate module
+ // to avoid duplication.
+
+ /*
+ * Facilitate listening to changes
+ */
+
+ exports.add_change_listener = function (cb, prefixes=list_prefixes)
+ {
+ if (typeof(prefixes) === "string")
+ prefixes = [prefixes];
+
+ for (let prefix of prefixes)
+ list_by_prefix[prefix].listeners.add(cb);
+ }
+
+ exports.remove_change_listener = function (cb, prefixes=list_prefixes)
+ {
+ if (typeof(prefixes) === "string")
+ prefixes = [prefixes];
+
+ for (let prefix of prefixes)
+ list_by_prefix[prefix].listeners.delete(cb);
+ }
+
+ /* Prepare some hepler functions to get elements of a list */
+
+ function list_items_it(list, with_values=false)
+ {
+ return with_values ? list.map.entries() : list.map.keys();
+ }
+
+ function list_entries_it(list)
+ {
+ return list_items_it(list, true);
+ }
+
+ function list_items(list, with_values=false)
+ {
+ let array = [];
+
+ for (let item of list_items_it(list, with_values))
+ array.push(item);
+
+ return array;
+ }
+
+ function list_entries(list)
+ {
+ return list_items(list, true);
+ }
+
+ exports.get = function (prefix, item)
+ {
+ return list_by_prefix[prefix].map.get(item);
+ }
+
+ exports.get_all_names = function (prefix)
+ {
+ return list_items(list_by_prefix[prefix]);
+ }
+
+ exports.get_all_names_it = function (prefix)
+ {
+ return list_items_it(list_by_prefix[prefix]);
+ }
+
+ exports.get_all = function (prefix)
+ {
+ return list_entries(list_by_prefix[prefix]);
+ }
+
+ exports.get_all_it = function (prefix)
+ {
+ return list_entries_it(list_by_prefix[prefix]);
+ }
+
+ window.get_storage = make_once(init);
+})();
diff --git a/common/storage_client.mjs b/common/storage_client.mjs
deleted file mode 100644
index 8260ad7..0000000
--- a/common/storage_client.mjs
+++ /dev/null
@@ -1,186 +0,0 @@
-/**
-* Myext storage through connection (client side)
-*
-* Copyright (C) 2021 Wojtek Kosior
-*
-* Dual-licensed under:
-* - 0BSD license
-* - GPLv3 or (at your option) any later version
-*/
-
-"use strict";
-
-import CONNECTION_TYPE from './connection_types.mjs';
-import {TYPE_PREFIX, list_prefixes} from '/common/stored_types.mjs';
-import make_once from './once.mjs';
-import browser from '/common/browser.mjs';
-
-var call_id = 0;
-var port;
-var calls_waiting = new Map();
-
-function set_call_callback(resolve, reject, func, args)
-{
- port.postMessage([call_id, func, args]);
- calls_waiting.set(call_id++, [resolve, reject]);
-}
-
-async function remote_call(func, args)
-{
- return new Promise((resolve, reject) =>
- set_call_callback(resolve, reject, func, args));
-}
-
-function handle_message(message)
-{
- let callbacks = calls_waiting.get(message.call_id);
- if (callbacks === undefined) {
- handle_change(message);
- return;
- }
-
- let [resolve, reject] = callbacks;
- calls_waiting.delete(message.call_id);
- if (message.error !== undefined)
- setTimeout(reject, 0, message.error);
- else
- setTimeout(resolve, 0, message.result);
-}
-
-function list(name, prefix)
-{
- return {prefix, name, listeners : new Set()};
-}
-
-var scripts = list("scripts", TYPE_PREFIX.SCRIPT);
-var bundles = list("bundles", TYPE_PREFIX.BUNDLE);
-var pages = list("pages", TYPE_PREFIX.PAGE);
-
-const list_by_prefix = {
- [TYPE_PREFIX.SCRIPT] : scripts,
- [TYPE_PREFIX.BUNDLE] : bundles,
- [TYPE_PREFIX.PAGE] : pages
-};
-
-var resolve_init;
-
-function handle_first_message(message)
-{
- for (let prefix of Object.keys(message))
- list_by_prefix[prefix].map = new Map(message[prefix]);
-
- port.onMessage.removeListener(handle_first_message);
- port.onMessage.addListener(handle_message);
-
- resolve_init();
-}
-
-function handle_change(change)
-{
- let list = list_by_prefix[change.prefix];
-
- if (change.new_val === undefined)
- list.map.delete(change.item);
- else
- list.map.set(change.item, change.new_val);
-
- for (let listener_callback of list.listeners)
- listener_callback(change);
-}
-
-var exports = {};
-
-function start_connection(resolve)
-{
- resolve_init = resolve;
- port = browser.runtime.connect({name : CONNECTION_TYPE.REMOTE_STORAGE});
- port.onMessage.addListener(handle_first_message);
-}
-
-async function init() {
- await new Promise((resolve, reject) => start_connection(resolve));
- return exports;
-}
-
-for (let call_name of ["set", "remove", "replace", "clear"])
- exports [call_name] = (...args) => remote_call(call_name, args);
-
-// TODO: Much of the code below is copy-pasted from /background/storage.mjs.
-// This should later be refactored into a separate module
-// to avoid duplication.
-
-/*
- * Facilitate listening to changes
- */
-
-exports.add_change_listener = function (cb, prefixes=list_prefixes)
-{
- if (typeof(prefixes) === "string")
- prefixes = [prefixes];
-
- for (let prefix of prefixes)
- list_by_prefix[prefix].listeners.add(cb);
-}
-
-exports.remove_change_listener = function (cb, prefixes=list_prefixes)
-{
- if (typeof(prefixes) === "string")
- prefixes = [prefixes];
-
- for (let prefix of prefixes)
- list_by_prefix[prefix].listeners.delete(cb);
-}
-
-/* Prepare some hepler functions to get elements of a list */
-
-function list_items_it(list, with_values=false)
-{
- return with_values ? list.map.entries() : list.map.keys();
-}
-
-function list_entries_it(list)
-{
- return list_items_it(list, true);
-}
-
-function list_items(list, with_values=false)
-{
- let array = [];
-
- for (let item of list_items_it(list, with_values))
- array.push(item);
-
- return array;
-}
-
-function list_entries(list)
-{
- return list_items(list, true);
-}
-
-exports.get = function (prefix, item)
-{
- return list_by_prefix[prefix].map.get(item);
-}
-
-exports.get_all_names = function (prefix)
-{
- return list_items(list_by_prefix[prefix]);
-}
-
-exports.get_all_names_it = function (prefix)
-{
- return list_items_it(list_by_prefix[prefix]);
-}
-
-exports.get_all = function (prefix)
-{
- return list_entries(list_by_prefix[prefix]);
-}
-
-exports.get_all_it = function (prefix)
-{
- return list_entries_it(list_by_prefix[prefix]);
-}
-
-export default make_once(init);
diff --git a/common/stored_types.js b/common/stored_types.js
new file mode 100644
index 0000000..de0ec71
--- /dev/null
+++ b/common/stored_types.js
@@ -0,0 +1,44 @@
+/**
+ * Myext stored item types "enum"
+ *
+ * Copyright (C) 2021 Wojtek Kosior
+ *
+ * Dual-licensed under:
+ * - 0BSD license
+ * - GPLv3 or (at your option) any later version
+ */
+
+/*
+ * Key for item that is stored in quantity (script, page) is constructed by
+ * prepending its name with first letter of its list name. However, we also
+ * need to store some items that don't belong to any list. Let's call them
+ * persisted variables. In such case item's key is its "name" prepended with
+ * an underscore.
+ */
+
+"use strict";
+
+(() => {
+ const TYPE_PREFIX = {
+ PAGE : "p",
+ BUNDLE : "b",
+ SCRIPT : "s",
+ VAR : "_"
+ };
+
+ const TYPE_NAME = {
+ [TYPE_PREFIX.PAGE] : "page",
+ [TYPE_PREFIX.BUNDLE] : "bundle",
+ [TYPE_PREFIX.SCRIPT] : "script"
+ }
+
+ const list_prefixes = [
+ TYPE_PREFIX.PAGE,
+ TYPE_PREFIX.BUNDLE,
+ TYPE_PREFIX.SCRIPT
+ ];
+
+ window.TYPE_PREFIX = TYPE_PREFIX;
+ window.TYPE_NAME = TYPE_NAME;
+ window.list_prefixes = list_prefixes;
+})();
diff --git a/common/stored_types.mjs b/common/stored_types.mjs
deleted file mode 100644
index 8545d44..0000000
--- a/common/stored_types.mjs
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
-* Myext stored item types "enum"
-*
-* Copyright (C) 2021 Wojtek Kosior
-*
-* Dual-licensed under:
-* - 0BSD license
-* - GPLv3 or (at your option) any later version
-*/
-
-/*
- * Key for item that is stored in quantity (script, page) is constructed by
- * prepending its name with first letter of its list name. However, we also
- * need to store some items that don't belong to any list. Let's call them
- * persisted variables. In such case item's key is its "name" prepended with
- * an underscore.
- */
-
-const TYPE_PREFIX = {
- PAGE : "p",
- BUNDLE : "b",
- SCRIPT : "s",
- VAR : "_"
-};
-
-const TYPE_NAME = {
- [TYPE_PREFIX.PAGE] : "page",
- [TYPE_PREFIX.BUNDLE] : "bundle",
- [TYPE_PREFIX.SCRIPT] : "script"
-}
-
-const list_prefixes = [
- TYPE_PREFIX.PAGE,
- TYPE_PREFIX.BUNDLE,
- TYPE_PREFIX.SCRIPT
-];
-
-export {TYPE_PREFIX, TYPE_NAME, list_prefixes};