aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2021-06-30 12:28:05 +0200
committerWojtek Kosior <koszko@koszko.org>2021-06-30 12:28:05 +0200
commit261548ff184926567a623e90df7954aeef842d59 (patch)
tree9b5697a77c758eaae969a8fba8b4edea5ecf59d4
parent83a8d263f6efddf4f742bf7a687d10bfd1907ef8 (diff)
downloadbrowser-extension-261548ff184926567a623e90df7954aeef842d59.tar.gz
browser-extension-261548ff184926567a623e90df7954aeef842d59.zip
emply an sh-based build system; make some changes to blocking
-rw-r--r--README.txt9
-rw-r--r--TODOS.org23
-rw-r--r--background/main.js262
-rw-r--r--background/message_server.js41
-rw-r--r--background/page_actions_server.js264
-rw-r--r--background/policy_injector.js114
-rw-r--r--background/settings_query.js204
-rw-r--r--background/storage.js654
-rw-r--r--background/storage_server.js95
-rwxr-xr-xbuild.sh289
-rw-r--r--common/browser.js24
-rw-r--r--common/connection_types.js18
-rw-r--r--common/gen_unique.js42
-rw-r--r--common/lock.js68
-rw-r--r--common/once.js50
-rw-r--r--common/sha256.js673
-rw-r--r--common/storage_client.js360
-rw-r--r--common/stored_types.js46
-rw-r--r--common/url_item.js22
-rw-r--r--content/freezer.js98
-rw-r--r--content/main.js221
-rw-r--r--content/page_actions.js92
-rw-r--r--copyright4
-rw-r--r--html/display-panel.html4
-rw-r--r--html/display-panel.js14
-rw-r--r--html/options.html9
-rw-r--r--html/options_main.js1262
-rw-r--r--manifest.json52
28 files changed, 2664 insertions, 2350 deletions
diff --git a/README.txt b/README.txt
index acff789..1342ca4 100644
--- a/README.txt
+++ b/README.txt
@@ -6,16 +6,17 @@ together. Such facility is necessary to enable browsing World Wide Web
without executing nonfree software.
Currently, the target browsers for this extension are Ungoogled Chromium
-and various forks of Firefox Quantum (57+).
+and various forks of Firefox (version 60+).
This extension is still in an early stage. See TODOS.org. Also see
`https://git.koszko.org/browser-extension-doc/' for documentation in
development.
## Installation ##
-The extension can be loaded into Ungoogled Chromium or a modern Gecko-based
-browser as unpacked extension. As of now, project's main directory is also
-the extension directory.
+The extension can be "built" with `./build.sh mozilla' or `./build.sh chromium'.
+This creates directories build_mozilla/ and build_chromium/, respectively.
+Such directory can be loaded into Ungoogled Chromium or a modern Gecko-based
+browser as unpacked extension.
## Copyright ##
All copyright information is gathered in the `copyright' file which follows
diff --git a/TODOS.org b/TODOS.org
index 63f7985..13b9207 100644
--- a/TODOS.org
+++ b/TODOS.org
@@ -20,20 +20,15 @@ TODO:
- make script bag components re-orderable (via drag&drop in options page) -- CRUCIAL
- find some way not to require each chrome user to modify manifest.json
- test with more browser forks (Abrowser, Parabola IceWeasel, LibreWolf)
- - also see if browsers based on pre-quantum FF support enough of
- WebExtensions for easy porting
- make sure page's own csp in <head> doesn't block our scripts
-- find out how and make it possible to whitelist non-https urls and
- whether we can inject csp to them
- create a repository to host scripts
- enable the extension to automatically fetch script substitutes from the repo
- make it possible to inject scripts to arbitrary places in DOM
- make script blocking code omit those scripts
- check if prerendering has to be blocked -- CRUCIAL
- block prefetch
-- rearrange files in extension, add some mechanism to build the extension
-- all solutions to modularize js code SUCK; come up with own simple DSL
- to manage imports/exports
+- rearrange files in extension
+- supplement the build script with a makefile, also produce zipped arifacts
- perform never-ending refactoring of already-written code
- also implement support for whitelisting of non-https urls
- validate data entered in settings
@@ -49,11 +44,21 @@ TODO:
(unless someone suggests another good name before we do so)
- add an option to disable script blocking globally
- Add support to settings_query for non-standard URLs
- (e.g. file:// and about:)
+ (e.g. file:// and ftp://)
- Process HTML files in data: URLs instead of just blocking them
+- improve CSP injection for pathological cases like <script> before <head>
+- Fix FF script blocking and whitelisting (FF seems to be by itself repeatedly
+ injecting CSP headers that were injected once, this makes it impossible to
+ whielist site that was unwhitelisted before; FF also seems to be removing our
+ injected script's nonce for no reason 🙁)
DONE:
-- make blocking more torough -- DONE 2021-06-28
+- find out if we can successfully use CSP to block file:// under FF -- DONE 2021-06-30
+- come up with own simple DSL to manage imports/exports -- DONE 2021-06-30
+- add some mechanism to build the extension -- DONE 2021-06-30
+- see if browsers based on pre-quantum FF support enough of -- DONE 2021-06-29
+ WebExtensions for easy porting (no, those we know dropped the support)
+- make blocking more thorough -- DONE 2021-06-28
- mind the data: urls -- CRUCIAL
- employ copyright file in Debian format -- DONE 2021-06-25
- find out what causes storage sometimes not to get initialized under IceCat 60 -- DONE 2021-06-23
diff --git a/background/main.js b/background/main.js
index ca56e37..aec25b6 100644
--- a/background/main.js
+++ b/background/main.js
@@ -5,127 +5,128 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"use strict";
-
-(() => {
- const TYPE_PREFIX = window.TYPE_PREFIX;
- const get_storage = window.get_storage;
- const start_storage_server = window.start_storage_server;
- const start_page_actions_server = window.start_page_actions_server;
- const start_policy_injector = window.start_policy_injector;
- const browser = window.browser;
-
- start_storage_server();
- start_page_actions_server();
- start_policy_injector();
-
- async function init_myext(install_details)
- {
- console.log("details:", install_details);
- if (install_details.reason != "install")
- return;
-
- let storage = await get_storage();
-
- await storage.clear();
-
- /*
- * Below we add sample settings to the extension.
- * Those should be considered example values for viewing in the options
- * page. They won't make my.fsf.org work. The only scripts that does
- * something useful right now is the opencores one.
- */
-
- let components = [];
- for (let script_data of [
- {url: "http://127.0.0.1:8000/myfsf_define_CRM.js",
- hash:"bf0cc81c7e8d5f800877b4bc3f14639f946f5ac6d4dc120255ffac5eba5e48fe"},
- {url: "https://my.fsf.org/misc/jquery.js?v=1.4.4",
- hash:"261ae472fa0cbf27c80c9200a1599a60fde581a0e652eee4bf41def8cb61f2d0"},
- {url: "https://my.fsf.org/misc/jquery-extend-3.4.0.js?v=1.4.4",
- hash:"c54103ba57ee210ca55c052e70415402707548a4e6a68dd6efb3895019bee392"},
- {url: "https://my.fsf.org/misc/jquery-html-prefilter-3.5.0-backport.js?v=1.4.4",
- hash:"fad84efa145fb507e5df9b582fa01b1c4e6313de7f72ebdd55726d92fa4dbf06"},
- {url: "https://my.fsf.org/misc/jquery.once.js?v=1.2",
- hash:"1430f42c0d760ba8e05bb3762480502e541f654fec5739ee40625ab22dc38c4f"},
- {url: "https://my.fsf.org/misc/drupal.js?qmaukd",
- hash:"2e08dccbd4d8b728a6871562995a4636b89bfe0ed3b8fb0138191c922228b116"},
- {url: "https://my.fsf.org/sites/all/modules/civicrm/bower_components/jquery/dist/jquery.min.js?qmaukd",
- hash:"a6d01520d28d15dbe476de84eea90eb3ee2d058722efc062ec73cb5fad78a17b"},
- {url: "https://my.fsf.org/sites/all/modules/civicrm/bower_components/jquery-ui/jquery-ui.min.js?qmaukd",
- hash:"28ce75d953678c4942df47a11707a15e3c756021cf89090e3e6aa7ad6b6971c3"},
- {url: "https://my.fsf.org/sites/all/modules/civicrm/bower_components/lodash-compat/lodash.min.js?qmaukd",
- hash:"f2871cc80c52fe8c04c582c4a49797c9c8fd80391cf1452e47f7fe97835ed5cc"},
- {url: "https://my.fsf.org/sites/all/modules/civicrm/packages/jquery/plugins/jquery.mousewheel.min.js?qmaukd",
- hash:"f50233e84c2ac7ada37a094d3f7d3b3f7c97716d6b7b47bf69619d93ee4ac1ce"},
- {url: "https://my.fsf.org/sites/all/modules/civicrm/bower_components/select2/select2.min.js?qmaukd",
- hash:"ce61298fb9aa4ec49ccd4172d097e36a9e5db3af06a7b82796659368f15b7c1b"},
- {url: "https://my.fsf.org/sites/all/modules/civi crm/packages/jquery/plugins/jquery.form.min.js?qmaukd",
- hash:"c90f0e501d2948fbc2b61bffd654fa4ab64741fd48923782419eeb14d3816fb8"},
- {url: "https://my.fsf.org/sites/all/modules/civicrm/packages/jquery/plugins/jquery.timeentry.min.js?qmaukd",
- hash:"8e85df981e8ad7049d06dfb075277d038734d36a7097c7f021021b2bdccfe9bb"},
- {url: "https://my.fsf.org/sites/all/modules/civicrm/packages/jquery/plugins/jquery.blockUI.min.js?qmaukd",
- hash:"806aedff52ac822f2adc5797073e1e5c5cec32eb9f15f2319cb32a347dcd232b"},
- {url: "https://my.fsf.org/sites/all/modules/civicrm/bower_components/datatables/media/js/jquery.dataTables.min.js?qmaukd",
- hash:"b796504d9b1b422f0dc6ccc2d740ac78a8c9e5078cc3934836d39742b1121925"},
- {url: "https://my.fsf.org/sites/all/modules/civicrm/bower_components/jquery-validation/dist/jquery.validate.min.js?qmaukd",
- hash:"f0f5373ad203101ea91bf826c5a7ef8f7cd74887f06bad2cb9277a504503b9e2"},
- {url: "https://my.fsf.org/sites/all/modules/civicrm/packages/jquery/plugins/jquery.ui.datepicker.validation.min.js?qmaukd",
- hash:"c6e6f6bf7f8fff25cca338045774e267e8eaa2d48ac9100540f3d59a6d2b3c61"},
- {url: "https://my.fsf.org/sites/all/modules/civicrm/js/Common.js?qmaukd",
- hash:"17aa222a3af2e8958be16accb5e77ef39f67009cb3b500718d8fffd45b399148"},
- {url: "https://my.fsf.org/sites/all/modules/civicrm/js/crm.datepicker.js?qmaukd",
- hash:"9bd8d10208aa99c156325f7819da6f0dd62ba221ac4119c3ccd4834e2cf36535"},
- {url: "https://my.fsf.org/sites/all/modules/civicrm/js/crm.ajax.js?qmaukd",
- hash:"6401a4e257b7499ae4a00be2c200e4504a2c9b3d6b278a830c31a7b63374f0fe"},
- {url: "https://my.fsf.org/sites/all/modules/civicrm/js/wysiwyg/crm.wysiwyg.js?qmaukd",
- hash:"fa962356072a36672c3b4b25bdeb657f020995a067e20a29cd5bb84b05157762"},
- {url: "https://my.fsf.org/sites/all/modules/civicrm/js/noconflict.js?qmaukd",
- hash:"58d6d9f496a235d23cf891926d71f2104e4f2afe1d14bb4e2b5233f646c35e62"},
- {url: "https://my.fsf.org/sites/all/modules/matomo/matomo.js?qmaukd",
- hash:"7f39ccd085f348189cd2fb62ea4d4a658d96f6bba266265880b98605e777e2de"},
- {url: "https://my.fsf.org/sites/all/themes/fsf_venture/js/global.js?qmaukd",
- hash:"aa7983f6b902f9f4415cfc8346e0c3f194cc95b78f52f2ad09ec7effa1326b9c"},
- {url: "https://my.fsf.org/sites/all/themes/fsf_venture/js/jquery.superfish.min.js?qmaukd",
- hash:"5ef1f93bf3901227056bf9ed0ed93a148eec4dda30f419756b12bedd1098815e"},
- {url: "https://my.fsf.org/sites/all/themes/fsf_venture/js/jquery.sidr.min.js?qmaukd",
- hash:"c4914d415826676c6af2e61f16edb72c5388f8600ba6de9049892aee49d980a0"},
- {url: "https://my.fsf.org/sites/all/themes/fsf_venture/js/jquery.flexslider.min.js?qmaukd",
- hash:"cefaf715761b4494913851249b9d40dacb4a8cb61242b0efc859dc586d56e0d4"},
- {url: "http://127.0.0.1:8000/myfsf_crap.js",
- hash:"d91ccf21592d0f861ea0ba946bc257fc5d88269327cad0a91387da6cb8ff633e"},
- {url: "https://my.fsf.org/sites/all/modules/civicrm/templates/CRM/Core/BillingBlock.js?r=lp7Di",
- hash:"2f25d35e7a0c0060ab0a444a577f09dd3c9934ae898a7ee0eb20b6c986ab5a1c"},
- {url: "https://my.fsf.org/extensions/com.aghstrategies.giftmemberships/js/giftpricefield.js?r=lp7Di",
- hash:"f86080e6bd306fe46474039aeca2808235005bce5a2a29416d08210022039a45"},
- {url: "https://my.fsf.org/extensions/com.ginkgostreet.negativenegator/js/negativenegator.js?r=lp7Di",
- hash:"d0e87bac832856db70947d82a7ab4e0b7c8b1070d5f1a32335345e033ece3a14"}
- ]) {
- let name_regex = /\/([^/]+)\.js/;
- let name = name_regex.exec(script_data.url)[1];
- await storage.set(TYPE_PREFIX.SCRIPT, name, script_data);
- components.push([TYPE_PREFIX.SCRIPT, name]);
- }
-
- await storage.set(TYPE_PREFIX.BAG, "myfsf_join", components);
-
- await storage.set(TYPE_PREFIX.PAGE, "https://my.fsf.org/join", {
- components: [TYPE_PREFIX.BAG, "myfsf_join"]
- });
-
- let hello_script = {
- text: "console.log(\"hello, every1!\");\n"
- };
- await storage.set(TYPE_PREFIX.SCRIPT, "hello", hello_script);
- await storage.set(TYPE_PREFIX.BAG, "hello",
- [[TYPE_PREFIX.SCRIPT, "hello"]]);
- await storage.set(TYPE_PREFIX.PAGE, "https://my.fsf.org/", {
- components: [TYPE_PREFIX.BAG, "hello"],
- allow: true
- });
-
- let opencores_script = {
- text: `\
+/*
+ * IMPORTS_START
+ * IMPORT TYPE_PREFIX
+ * IMPORT get_storage
+ * IMPORT start_storage_server
+ * IMPORT start_page_actions_server
+ * IMPORT start_policy_injector
+ * IMPORT browser
+ * IMPORTS_END
+ */
+
+start_storage_server();
+start_page_actions_server();
+start_policy_injector();
+
+async function init_myext(install_details)
+{
+ console.log("details:", install_details);
+ if (install_details.reason != "install")
+ return;
+
+ let storage = await get_storage();
+
+ await storage.clear();
+
+ /*
+ * Below we add sample settings to the extension.
+ * Those should be considered example values for viewing in the options
+ * page. They won't make my.fsf.org work. The only scripts that does
+ * something useful right now is the opencores one.
+ */
+
+ let components = [];
+ for (let script_data of [
+ {url: "http://127.0.0.1:8000/myfsf_define_CRM.js",
+ hash:"bf0cc81c7e8d5f800877b4bc3f14639f946f5ac6d4dc120255ffac5eba5e48fe"},
+ {url: "https://my.fsf.org/misc/jquery.js?v=1.4.4",
+ hash:"261ae472fa0cbf27c80c9200a1599a60fde581a0e652eee4bf41def8cb61f2d0"},
+ {url: "https://my.fsf.org/misc/jquery-extend-3.4.0.js?v=1.4.4",
+ hash:"c54103ba57ee210ca55c052e70415402707548a4e6a68dd6efb3895019bee392"},
+ {url: "https://my.fsf.org/misc/jquery-html-prefilter-3.5.0-backport.js?v=1.4.4",
+ hash:"fad84efa145fb507e5df9b582fa01b1c4e6313de7f72ebdd55726d92fa4dbf06"},
+ {url: "https://my.fsf.org/misc/jquery.once.js?v=1.2",
+ hash:"1430f42c0d760ba8e05bb3762480502e541f654fec5739ee40625ab22dc38c4f"},
+ {url: "https://my.fsf.org/misc/drupal.js?qmaukd",
+ hash:"2e08dccbd4d8b728a6871562995a4636b89bfe0ed3b8fb0138191c922228b116"},
+ {url: "https://my.fsf.org/sites/all/modules/civicrm/bower_components/jquery/dist/jquery.min.js?qmaukd",
+ hash:"a6d01520d28d15dbe476de84eea90eb3ee2d058722efc062ec73cb5fad78a17b"},
+ {url: "https://my.fsf.org/sites/all/modules/civicrm/bower_components/jquery-ui/jquery-ui.min.js?qmaukd",
+ hash:"28ce75d953678c4942df47a11707a15e3c756021cf89090e3e6aa7ad6b6971c3"},
+ {url: "https://my.fsf.org/sites/all/modules/civicrm/bower_components/lodash-compat/lodash.min.js?qmaukd",
+ hash:"f2871cc80c52fe8c04c582c4a49797c9c8fd80391cf1452e47f7fe97835ed5cc"},
+ {url: "https://my.fsf.org/sites/all/modules/civicrm/packages/jquery/plugins/jquery.mousewheel.min.js?qmaukd",
+ hash:"f50233e84c2ac7ada37a094d3f7d3b3f7c97716d6b7b47bf69619d93ee4ac1ce"},
+ {url: "https://my.fsf.org/sites/all/modules/civicrm/bower_components/select2/select2.min.js?qmaukd",
+ hash:"ce61298fb9aa4ec49ccd4172d097e36a9e5db3af06a7b82796659368f15b7c1b"},
+ {url: "https://my.fsf.org/sites/all/modules/civi crm/packages/jquery/plugins/jquery.form.min.js?qmaukd",
+ hash:"c90f0e501d2948fbc2b61bffd654fa4ab64741fd48923782419eeb14d3816fb8"},
+ {url: "https://my.fsf.org/sites/all/modules/civicrm/packages/jquery/plugins/jquery.timeentry.min.js?qmaukd",
+ hash:"8e85df981e8ad7049d06dfb075277d038734d36a7097c7f021021b2bdccfe9bb"},
+ {url: "https://my.fsf.org/sites/all/modules/civicrm/packages/jquery/plugins/jquery.blockUI.min.js?qmaukd",
+ hash:"806aedff52ac822f2adc5797073e1e5c5cec32eb9f15f2319cb32a347dcd232b"},
+ {url: "https://my.fsf.org/sites/all/modules/civicrm/bower_components/datatables/media/js/jquery.dataTables.min.js?qmaukd",
+ hash:"b796504d9b1b422f0dc6ccc2d740ac78a8c9e5078cc3934836d39742b1121925"},
+ {url: "https://my.fsf.org/sites/all/modules/civicrm/bower_components/jquery-validation/dist/jquery.validate.min.js?qmaukd",
+ hash:"f0f5373ad203101ea91bf826c5a7ef8f7cd74887f06bad2cb9277a504503b9e2"},
+ {url: "https://my.fsf.org/sites/all/modules/civicrm/packages/jquery/plugins/jquery.ui.datepicker.validation.min.js?qmaukd",
+ hash:"c6e6f6bf7f8fff25cca338045774e267e8eaa2d48ac9100540f3d59a6d2b3c61"},
+ {url: "https://my.fsf.org/sites/all/modules/civicrm/js/Common.js?qmaukd",
+ hash:"17aa222a3af2e8958be16accb5e77ef39f67009cb3b500718d8fffd45b399148"},
+ {url: "https://my.fsf.org/sites/all/modules/civicrm/js/crm.datepicker.js?qmaukd",
+ hash:"9bd8d10208aa99c156325f7819da6f0dd62ba221ac4119c3ccd4834e2cf36535"},
+ {url: "https://my.fsf.org/sites/all/modules/civicrm/js/crm.ajax.js?qmaukd",
+ hash:"6401a4e257b7499ae4a00be2c200e4504a2c9b3d6b278a830c31a7b63374f0fe"},
+ {url: "https://my.fsf.org/sites/all/modules/civicrm/js/wysiwyg/crm.wysiwyg.js?qmaukd",
+ hash:"fa962356072a36672c3b4b25bdeb657f020995a067e20a29cd5bb84b05157762"},
+ {url: "https://my.fsf.org/sites/all/modules/civicrm/js/noconflict.js?qmaukd",
+ hash:"58d6d9f496a235d23cf891926d71f2104e4f2afe1d14bb4e2b5233f646c35e62"},
+ {url: "https://my.fsf.org/sites/all/modules/matomo/matomo.js?qmaukd",
+ hash:"7f39ccd085f348189cd2fb62ea4d4a658d96f6bba266265880b98605e777e2de"},
+ {url: "https://my.fsf.org/sites/all/themes/fsf_venture/js/global.js?qmaukd",
+ hash:"aa7983f6b902f9f4415cfc8346e0c3f194cc95b78f52f2ad09ec7effa1326b9c"},
+ {url: "https://my.fsf.org/sites/all/themes/fsf_venture/js/jquery.superfish.min.js?qmaukd",
+ hash:"5ef1f93bf3901227056bf9ed0ed93a148eec4dda30f419756b12bedd1098815e"},
+ {url: "https://my.fsf.org/sites/all/themes/fsf_venture/js/jquery.sidr.min.js?qmaukd",
+ hash:"c4914d415826676c6af2e61f16edb72c5388f8600ba6de9049892aee49d980a0"},
+ {url: "https://my.fsf.org/sites/all/themes/fsf_venture/js/jquery.flexslider.min.js?qmaukd",
+ hash:"cefaf715761b4494913851249b9d40dacb4a8cb61242b0efc859dc586d56e0d4"},
+ {url: "http://127.0.0.1:8000/myfsf_crap.js",
+ hash:"d91ccf21592d0f861ea0ba946bc257fc5d88269327cad0a91387da6cb8ff633e"},
+ {url: "https://my.fsf.org/sites/all/modules/civicrm/templates/CRM/Core/BillingBlock.js?r=lp7Di",
+ hash:"2f25d35e7a0c0060ab0a444a577f09dd3c9934ae898a7ee0eb20b6c986ab5a1c"},
+ {url: "https://my.fsf.org/extensions/com.aghstrategies.giftmemberships/js/giftpricefield.js?r=lp7Di",
+ hash:"f86080e6bd306fe46474039aeca2808235005bce5a2a29416d08210022039a45"},
+ {url: "https://my.fsf.org/extensions/com.ginkgostreet.negativenegator/js/negativenegator.js?r=lp7Di",
+ hash:"d0e87bac832856db70947d82a7ab4e0b7c8b1070d5f1a32335345e033ece3a14"}
+ ]) {
+ let name_regex = /\/([^/]+)\.js/;
+ let name = name_regex.exec(script_data.url)[1];
+ await storage.set(TYPE_PREFIX.SCRIPT, name, script_data);
+ components.push([TYPE_PREFIX.SCRIPT, name]);
+ }
+
+ await storage.set(TYPE_PREFIX.BAG, "myfsf_join", components);
+
+ await storage.set(TYPE_PREFIX.PAGE, "https://my.fsf.org/join", {
+ components: [TYPE_PREFIX.BAG, "myfsf_join"]
+ });
+
+ let hello_script = {
+ text: "console.log(\"hello, every1!\");\n"
+ };
+ await storage.set(TYPE_PREFIX.SCRIPT, "hello", hello_script);
+ await storage.set(TYPE_PREFIX.BAG, "hello",
+ [[TYPE_PREFIX.SCRIPT, "hello"]]);
+ await storage.set(TYPE_PREFIX.PAGE, "https://my.fsf.org/", {
+ components: [TYPE_PREFIX.BAG, "hello"],
+ allow: true
+ });
+
+ let opencores_script = {
+ text: `\
let data = JSON.parse(document.getElementById("__NEXT_DATA__").textContent);
let sections = {};
for (let h1 of document.getElementsByClassName("cMJCrc")) {
@@ -154,16 +155,15 @@ for (let prop of data.props.pageProps.list) {
ul.appendChild(li);
}
`
- };
+ };
- await storage.set(TYPE_PREFIX.SCRIPT, "opencores", opencores_script);
- await storage.set(TYPE_PREFIX.PAGE, "https://opencores.org/projects", {
- components: [TYPE_PREFIX.SCRIPT, "opencores"],
- allow: false
- });
- }
+ await storage.set(TYPE_PREFIX.SCRIPT, "opencores", opencores_script);
+ await storage.set(TYPE_PREFIX.PAGE, "https://opencores.org/projects", {
+ components: [TYPE_PREFIX.SCRIPT, "opencores"],
+ allow: false
+ });
+}
- browser.runtime.onInstalled.addListener(init_myext);
+browser.runtime.onInstalled.addListener(init_myext);
- console.log("hello, myext");
-})();
+console.log("hello, myext");
diff --git a/background/message_server.js b/background/message_server.js
index 358e9d5..a541a04 100644
--- a/background/message_server.js
+++ b/background/message_server.js
@@ -5,28 +5,33 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"use strict";
-
-(() => {
- const browser = window.browser;
+/*
+ * IMPORTS_START
+ * IMPORT browser
+ * IMPORTS_END
+ */
- var listeners = {};
+var listeners = {};
- /* magic should be one of the constants from /common/connection_types.js */
+/* magic should be one of the constants from /common/connection_types.js */
- function listen_for_connection(magic, cb)
- {
- listeners[magic] = cb;
- }
+function listen_for_connection(magic, cb)
+{
+ listeners[magic] = cb;
+}
- function raw_listen(port) {
- if (listeners[port.name] === undefined)
- return;
+function raw_listen(port)
+{
+ if (listeners[port.name] === undefined)
+ return;
- listeners[port.name](port);
- }
+ listeners[port.name](port);
+}
- browser.runtime.onConnect.addListener(raw_listen);
+browser.runtime.onConnect.addListener(raw_listen);
- window.listen_for_connection = listen_for_connection;
-})();
+/*
+ * EXPORTS_START
+ * EXPORT listen_for_connection
+ * EXPORTS_END
+ */
diff --git a/background/page_actions_server.js b/background/page_actions_server.js
index dbf4db3..f9773f6 100644
--- a/background/page_actions_server.js
+++ b/background/page_actions_server.js
@@ -5,145 +5,149 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"use strict";
-
-(() => {
- const get_storage = window.get_storage;
- const TYPE_PREFIX = window.TYPE_PREFIX;
- const CONNECTION_TYPE = window.CONNECTION_TYPE;
- const browser = window.browser;
- const listen_for_connection = window.listen_for_connection;
- const sha256 = window.sha256;
- const get_query_best = window.get_query_best;
-
- var storage;
- var query_best;
- var handler;
-
- function send_scripts(url, port)
- {
- let [pattern, settings] = query_best(url);
- if (settings === undefined)
- return;
-
- let components = settings.components;
- let processed_bags = new Set();
-
- if (components !== undefined)
- send_scripts_rec([components], port, processed_bags);
- }
+/*
+ * IMPORTS_START
+ * IMPORT get_storage
+ * IMPORT TYPE_PREFIX
+ * IMPORT CONNECTION_TYPE
+ * IMPORT browser
+ * IMPORT listen_for_connection
+ * IMPORT sha256
+ * IMPORT get_query_best
+ * IMPORTS_END
+ */
- // TODO: parallelize script fetching
- async function send_scripts_rec(components, port, processed_bags)
- {
- for (let [prefix, name] of components) {
- if (prefix === TYPE_PREFIX.BAG) {
- if (processed_bags.has(name)) {
- console.log(`preventing recursive inclusion of bag ${name}`);
- continue;
- }
-
- var bag = storage.get(TYPE_PREFIX.BAG, name);
-
- if (bag === undefined) {
- console.log(`no bag in storage for key ${name}`);
- continue;
- }
-
- processed_bags.add(name);
- await send_scripts_rec(bag, port, processed_bags);
- processed_bags.delete(name);
- } else {
- let script_text = await get_script_text(name);
- if (script_text === undefined)
- continue;
-
- port.postMessage({inject : [script_text]});
+var storage;
+var query_best;
+var handler;
+
+function send_scripts(url, port)
+{
+ let [pattern, settings] = query_best(url);
+ if (settings === undefined)
+ return;
+
+ let components = settings.components;
+ let processed_bags = new Set();
+
+ if (components !== undefined)
+ send_scripts_rec([components], port, processed_bags);
+}
+
+// TODO: parallelize script fetching
+async function send_scripts_rec(components, port, processed_bags)
+{
+ for (let [prefix, name] of components) {
+ if (prefix === TYPE_PREFIX.BAG) {
+ if (processed_bags.has(name)) {
+ console.log(`preventing recursive inclusion of bag ${name}`);
+ continue;
}
- }
- }
- async function get_script_text(script_name)
- {
- try {
- let script_data = storage.get(TYPE_PREFIX.SCRIPT, script_name);
- if (script_data === undefined) {
- console.log(`missing data for ${script_name}`);
- return;
+ var bag = storage.get(TYPE_PREFIX.BAG, name);
+
+ if (bag === undefined) {
+ console.log(`no bag in storage for key ${name}`);
+ continue;
}
- let script_text = script_data.text;
- if (!script_text)
- script_text = await fetch_remote_script(script_data);
- return script_text;
- } catch (e) {
- console.log(e);
- }
- }
- function ajax_callback()
- {
- if (this.readyState == 4)
- this.resolve_callback(this);
- }
+ processed_bags.add(name);
+ await send_scripts_rec(bag, port, processed_bags);
+ processed_bags.delete(name);
+ } else {
+ let script_text = await get_script_text(name);
+ if (script_text === undefined)
+ continue;
- function initiate_ajax_request(resolve, method, url)
- {
- var xhttp = new XMLHttpRequest();
- xhttp.resolve_callback = resolve;
- xhttp.onreadystatechange = ajax_callback;
- xhttp.open(method, url, true);
- xhttp.send();
+ port.postMessage({inject : [script_text]});
+ }
}
-
- function make_ajax_request(method, url)
- {
- return new Promise((resolve, reject) =>
- initiate_ajax_request(resolve, method, url));
+}
+
+async function get_script_text(script_name)
+{
+ try {
+ let script_data = storage.get(TYPE_PREFIX.SCRIPT, script_name);
+ if (script_data === undefined) {
+ console.log(`missing data for ${script_name}`);
+ return;
+ }
+ let script_text = script_data.text;
+ if (!script_text)
+ script_text = await fetch_remote_script(script_data);
+ return script_text;
+ } catch (e) {
+ console.log(e);
}
-
- async function fetch_remote_script(script_data)
- {
- try {
- let xhttp = await make_ajax_request("GET", script_data.url);
- if (xhttp.status === 200) {
- let computed_hash = sha256(xhttp.responseText);
- if (computed_hash !== script_data.hash) {
- console.log(`Bad hash for ${script_data.url}\n got ${computed_hash} instead of ${script_data.hash}`);
- return;
- }
- return xhttp.responseText;
- } else {
- console.log("script not fetched: " + script_data.url);
+}
+
+function ajax_callback()
+{
+ if (this.readyState == 4)
+ this.resolve_callback(this);
+}
+
+function initiate_ajax_request(resolve, method, url)
+{
+ var xhttp = new XMLHttpRequest();
+ xhttp.resolve_callback = resolve;
+ xhttp.onreadystatechange = ajax_callback;
+ xhttp.open(method, url, true);
+ xhttp.send();
+}
+
+function make_ajax_request(method, url)
+{
+ return new Promise((resolve, reject) =>
+ initiate_ajax_request(resolve, method, url));
+}
+
+async function fetch_remote_script(script_data)
+{
+ try {
+ let xhttp = await make_ajax_request("GET", script_data.url);
+ if (xhttp.status === 200) {
+ let computed_hash = sha256(xhttp.responseText);
+ if (computed_hash !== script_data.hash) {
+ console.log(`Bad hash for ${script_data.url}\n got ${computed_hash} instead of ${script_data.hash}`);
return;
}
- } catch (e) {
- console.log(e);
+ return xhttp.responseText;
+ } else {
+ console.log("script not fetched: " + script_data.url);
+ return;
}
+ } catch (e) {
+ console.log(e);
}
-
- function handle_message(port, message, handler)
- {
- port.onMessage.removeListener(handler[0]);
- let url = message.url;
- console.log({url});
- send_scripts(url, port);
- }
-
- function new_connection(port)
- {
- console.log("new page actions connection!");
- let handler = [];
- handler.push(m => handle_message(port, m, handler));
- port.onMessage.addListener(handler[0]);
- }
-
- async function start()
- {
- storage = await get_storage();
- query_best = await get_query_best();
-
- listen_for_connection(CONNECTION_TYPE.PAGE_ACTIONS, new_connection);
- }
-
- window.start_page_actions_server = start;
-})();
+}
+
+function handle_message(port, message, handler)
+{
+ port.onMessage.removeListener(handler[0]);
+ let url = message.url;
+ console.log({url});
+ send_scripts(url, port);
+}
+
+function new_connection(port)
+{
+ console.log("new page actions connection!");
+ let handler = [];
+ handler.push(m => handle_message(port, m, handler));
+ port.onMessage.addListener(handler[0]);
+}
+
+async function start_page_actions_server()
+{
+ storage = await get_storage();
+ query_best = await get_query_best();
+
+ listen_for_connection(CONNECTION_TYPE.PAGE_ACTIONS, new_connection);
+}
+
+/*
+ * EXPORTS_START
+ * EXPORT start_page_actions_server
+ * EXPORTS_END
+ */
diff --git a/background/policy_injector.js b/background/policy_injector.js
index d4d22b6..f05a422 100644
--- a/background/policy_injector.js
+++ b/background/policy_injector.js
@@ -5,71 +5,77 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"use strict";
+/*
+ * IMPORTS_START
+ * IMPORT TYPE_PREFIX
+ * IMPORT get_storage
+ * IMPORT browser
+ * IMPORT is_chrome
+ * IMPORT gen_unique
+ * IMPORT url_item
+ * IMPORT get_query_best
+ * IMPORTS_END
+ */
-(() => {
- const TYPE_PREFIX = window.TYPE_PREFIX;
- const get_storage = window.get_storage;
- const browser = window.browser;
- const is_chrome = window.is_chrome;
- const gen_unique = window.gen_unique;
- const url_item = window.url_item;
- const get_query_best = window.get_query_best;
+var storage;
+var query_best;
- var storage;
- var query_best;
+let csp_header_names = {
+ "content-security-policy" : true,
+ "x-webkit-csp" : true,
+ "x-content-security-policy" : true
+};
- let csp_header_names = {
- "content-security-policy" : true,
- "x-webkit-csp" : true,
- "x-content-security-policy" : true
- };
+function is_noncsp_header(header)
+{
+ return !csp_header_names[header.name.toLowerCase()];
+}
- function is_noncsp_header(header)
- {
- return !csp_header_names[header.name.toLowerCase()];
- }
+function inject(details)
+{
+ let url = url_item(details.url);
- function inject(details)
- {
- let url = url_item(details.url);
+ let [pattern, settings] = query_best(url);
- let [pattern, settings] = query_best(url);
+ if (settings !== undefined && settings.allow)
+ return {cancel : false};
- if (settings !== undefined && settings.allow) {
- console.log("allowing", url);
- return {cancel : false};
- }
+ let nonce = gen_unique(url).substring(1);
+ let headers = details.responseHeaders.filter(is_noncsp_header);
- let nonce = gen_unique(url).substring(1);
- let headers = details.responseHeaders.filter(is_noncsp_header);
- headers.push({
- name : "content-security-policy",
- value : `script-src 'nonce-${nonce}'; script-src-elem 'nonce-${nonce}';`
- });
+ let rule = `script-src 'nonce-${nonce}';`;
+ if (is_chrome)
+ rule += `script-src-elem 'nonce-${nonce}';`;
- console.log("modified headers", url, headers);
+ headers.push({
+ name : "content-security-policy",
+ value : rule
+ });
- return {responseHeaders: headers};
- }
+ return {responseHeaders: headers};
+}
- async function start() {
- storage = await get_storage();
- query_best = await get_query_best();
+async function start_policy_injector()
+{
+ storage = await get_storage();
+ query_best = await get_query_best();
- let extra_opts = ["blocking", "responseHeaders"];
- if (is_chrome)
- extra_opts.push("extraHeaders");
+ let extra_opts = ["blocking", "responseHeaders"];
+ if (is_chrome)
+ extra_opts.push("extraHeaders");
- browser.webRequest.onHeadersReceived.addListener(
- inject,
- {
- urls: ["<all_urls>"],
- types: ["main_frame", "sub_frame"]
- },
- extra_opts
- );
- }
+ browser.webRequest.onHeadersReceived.addListener(
+ inject,
+ {
+ urls: ["<all_urls>"],
+ types: ["main_frame", "sub_frame"]
+ },
+ extra_opts
+ );
+}
- window.start_policy_injector = start;
-})();
+/*
+ * EXPORTS_START
+ * EXPORT start_policy_injector
+ * EXPORTS_END
+ */
diff --git a/background/settings_query.js b/background/settings_query.js
index 43538d5..ce01b80 100644
--- a/background/settings_query.js
+++ b/background/settings_query.js
@@ -5,32 +5,34 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"use strict";
-
-(() => {
- const make_once = window.make_once;
- const get_storage = window.get_storage;
+/*
+ * IMPORTS_START
+ * IMPORT make_once
+ * IMPORT get_storage
+ * IMPORT TYPE_PREFIX
+ * IMPORTS_END
+ */
- var storage;
+var storage;
- var exports = {};
+var exports = {};
- async function init(fun)
- {
- storage = await get_storage();
+async function init(fun)
+{
+ storage = await get_storage();
- return fun;
- }
+ return fun;
+}
- // TODO: also support urls with specified ports as well as `data:' urls
- function query(url, multiple)
- {
- let proto_re = "[a-zA-Z]*:\/\/";
- let domain_re = "[^/?#]+";
- let segments_re = "/[^?#]*";
- let query_re = "\\?[^#]*";
+// TODO: also support urls with specified ports
+function query(url, multiple)
+{
+ let proto_re = "[a-zA-Z]*:\/\/";
+ let domain_re = "[^/?#]+";
+ let segments_re = "/[^?#]*";
+ let query_re = "\\?[^#]*";
- let url_regex = new RegExp(`\
+ let url_regex = new RegExp(`\
^\
(${proto_re})\
(${domain_re})\
@@ -39,89 +41,95 @@
#?.*\$\
`);
- let regex_match = url_regex.exec(url);
- if (regex_match === null) {
- console.log("bad url format", url);
- return multiple ? [] : [undefined, undefined];
- }
+ let regex_match = url_regex.exec(url);
+ if (regex_match === null) {
+ console.log("bad url format", url);
+ return multiple ? [] : [undefined, undefined];
+ }
+
+ let [_, proto, domain, segments, query] = regex_match;
+
+ domain = domain.split(".");
+ let segments_trailing_dash =
+ segments && segments[segments.length - 1] === "/";
+ segments = (segments || "").split("/").filter(s => s !== "");
+ segments.unshift("");
+
+ let matched = [];
+
+ for (let d_slice = 0; d_slice < domain.length; d_slice++) {
+ let domain_part = domain.slice(d_slice).join(".");
+ let domain_wildcards = [];
+ if (d_slice === 0)
+ domain_wildcards.push("");
+ if (d_slice === 1)
+ domain_wildcards.push("*.");
+ if (d_slice > 0)
+ domain_wildcards.push("**.");
+ domain_wildcards.push("***.");
+
+ for (let domain_wildcard of domain_wildcards) {
+ let domain_pattern = domain_wildcard + domain_part;
+
+ for (let s_slice = segments.length; s_slice > 0; s_slice--) {
+ let segments_part = segments.slice(0, s_slice).join("/");
+ let segments_wildcards = [];
+ if (s_slice === segments.length) {
+ if (segments_trailing_dash)
+ segments_wildcards.push("/");
+ segments_wildcards.push("");
+ }
+ if (s_slice === segments.length - 1) {
+ if (segments[s_slice] !== "*")
+ segments_wildcards.push("/*");
+ }
+ if (s_slice < segments.length &&
+ (segments[s_slice] !== "**" ||
+ s_slice < segments.length - 1))
+ segments_wildcards.push("/**");
+ if (segments[s_slice] !== "***" ||
+ s_slice < segments.length)
+ segments_wildcards.push("/***");
+
+ for (let segments_wildcard of segments_wildcards) {
+ let segments_pattern =
+ segments_part + segments_wildcard;
- let [_, proto, domain, segments, query] = regex_match;
-
- domain = domain.split(".");
- let segments_trailing_dash =
- segments && segments[segments.length - 1] === "/";
- segments = (segments || "").split("/").filter(s => s !== "");
- segments.unshift("");
-
- let matched = [];
-
- for (let d_slice = 0; d_slice < domain.length; d_slice++) {
- let domain_part = domain.slice(d_slice).join(".");
- let domain_wildcards = [];
- if (d_slice === 0)
- domain_wildcards.push("");
- if (d_slice === 1)
- domain_wildcards.push("*.");
- if (d_slice > 0)
- domain_wildcards.push("**.");
- domain_wildcards.push("***.");
-
- for (let domain_wildcard of domain_wildcards) {
- let domain_pattern = domain_wildcard + domain_part;
-
- for (let s_slice = segments.length; s_slice > 0; s_slice--) {
- let segments_part = segments.slice(0, s_slice).join("/");
- let segments_wildcards = [];
- if (s_slice === segments.length) {
- if (segments_trailing_dash)
- segments_wildcards.push("/");
- segments_wildcards.push("");
- }
- if (s_slice === segments.length - 1) {
- if (segments[s_slice] !== "*")
- segments_wildcards.push("/*");
- }
- if (s_slice < segments.length &&
- (segments[s_slice] !== "**" ||
- s_slice < segments.length - 1))
- segments_wildcards.push("/**");
- if (segments[s_slice] !== "***" ||
- s_slice < segments.length)
- segments_wildcards.push("/***");
-
- for (let segments_wildcard of segments_wildcards) {
- let segments_pattern =
- segments_part + segments_wildcard;
-
- let pattern = proto + domain_pattern + segments_pattern;
- console.log("trying", pattern);
- let settings = storage.get(TYPE_PREFIX.PAGE, pattern);
-
- if (settings === undefined)
- continue;
-
- if (!multiple)
- return [pattern, settings];
-
- matched.push([pattern, settings]);
- }
+ let pattern = proto + domain_pattern + segments_pattern;
+ console.log("trying", pattern);
+ let settings = storage.get(TYPE_PREFIX.PAGE, pattern);
+
+ if (settings === undefined)
+ continue;
+
+ if (!multiple)
+ return [pattern, settings];
+
+ matched.push([pattern, settings]);
}
}
}
-
- return multiple ? matched : [undefined, undefined];
}
- function query_best(url)
- {
- return query(url, false);
- }
+ return multiple ? matched : [undefined, undefined];
+}
- function query_all(url)
- {
- return query(url, true);
- }
+function query_best(url)
+{
+ return query(url, false);
+}
+
+function query_all(url)
+{
+ return query(url, true);
+}
- window.get_query_best = make_once(() => init(query_best));
- window.get_query_all = make_once(() => init(query_all));
-})();
+const get_query_best = make_once(() => init(query_best));
+const get_query_all = make_once(() => init(query_all));
+
+/*
+ * EXPORTS_START
+ * EXPORT get_query_best
+ * EXPORT get_query_all
+ * EXPORTS_END
+ */
diff --git a/background/storage.js b/background/storage.js
index f3f08c9..48e4e52 100644
--- a/background/storage.js
+++ b/background/storage.js
@@ -5,390 +5,396 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"use strict";
-
-(() => {
- const TYPE_PREFIX = window.TYPE_PREFIX;
- const TYPE_NAME = window.TYPE_NAME;
- const list_prefixes = window.list_prefixes;
- const make_lock = window.make_lock;
- const lock = window.lock;
- const unlock = window.unlock;
- const make_once = window.make_once;
- const browser = window.browser;
- const is_chrome = window.is_chrome;
-
- var exports = {};
-
- /* We're yet to decide how to handle errors... */
-
- /* Here are some basic wrappers for storage API functions */
-
- async function get(key)
- {
- try {
- /* Fix for fact that Chrome does not use promises here */
- let promise = is_chrome ?
- new Promise((resolve, reject) =>
- chrome.storage.local.get(key,
- val => resolve(val))) :
- browser.storage.local.get(key);
-
- return (await promise)[key];
- } catch (e) {
- console.log(e);
- }
- }
+/*
+ * IMPORTS_START
+ * IMPORT TYPE_PREFIX
+ * IMPORT TYPE_NAME
+ * IMPORT list_prefixes
+ * IMPORT make_lock
+ * IMPORT lock
+ * IMPORT unlock
+ * IMPORT make_once
+ * IMPORT browser
+ * IMPORT is_chrome
+ * IMPORTS_END
+ */
- async function set(key, value)
- {
- try {
- return browser.storage.local.set({[key]: value});
- } catch (e) {
- console.log(e);
- }
- }
+var exports = {};
- async function setn(keys_and_values)
- {
- let obj = Object();
- while (keys_and_values.length > 1) {
- let value = keys_and_values.pop();
- let key = keys_and_values.pop();
- obj[key] = value;
- }
+/* We're yet to decide how to handle errors... */
- try {
- return browser.storage.local.set(obj);
- } catch (e) {
- console.log(e);
- }
- }
+/* Here are some basic wrappers for storage API functions */
- async function set_var(name, value)
- {
- return set(TYPE_PREFIX.VAR + name, value);
- }
+async function get(key)
+{
+ try {
+ /* Fix for fact that Chrome does not use promises here */
+ let promise = is_chrome ?
+ new Promise((resolve, reject) =>
+ chrome.storage.local.get(key,
+ val => resolve(val))) :
+ browser.storage.local.get(key);
- async function get_var(name)
- {
- return get(TYPE_PREFIX.VAR + name);
+ return (await promise)[key];
+ } catch (e) {
+ console.log(e);
+ }
+}
+
+async function set(key, value)
+{
+ try {
+ return browser.storage.local.set({[key]: value});
+ } catch (e) {
+ console.log(e);
+ }
+}
+
+async function setn(keys_and_values)
+{
+ let obj = Object();
+ while (keys_and_values.length > 1) {
+ let value = keys_and_values.pop();
+ let key = keys_and_values.pop();
+ obj[key] = value;
}
- /*
- * A special case of persisted variable is one that contains list
- * of items.
- */
-
- async function get_list_var(name)
- {
- let list = await get_var(name);
-
- return list === undefined ? [] : list;
+ try {
+ return browser.storage.local.set(obj);
+ } catch (e) {
+ console.log(e);
}
+}
- /* We maintain in-memory copies of some stored lists. */
+async function set_var(name, value)
+{
+ return set(TYPE_PREFIX.VAR + name, value);
+}
- async function list(prefix)
- {
- let name = TYPE_NAME[prefix] + "s"; /* Make plural. */
- let map = new Map();
+async function get_var(name)
+{
+ return get(TYPE_PREFIX.VAR + name);
+}
- for (let item of await get_list_var(name))
- map.set(item, await get(prefix + item));
+/*
+ * A special case of persisted variable is one that contains list
+ * of items.
+ */
- return {map, prefix, name, listeners : new Set(), lock : make_lock()};
- }
+async function get_list_var(name)
+{
+ let list = await get_var(name);
- var pages;
- var bags;
- var scripts;
+ return list === undefined ? [] : list;
+}
- var list_by_prefix = {};
+/* We maintain in-memory copies of some stored lists. */
- async function init()
- {
- for (let prefix of list_prefixes)
- list_by_prefix[prefix] = await list(prefix);
+async function list(prefix)
+{
+ let name = TYPE_NAME[prefix] + "s"; /* Make plural. */
+ let map = new Map();
- return exports;
- }
+ for (let item of await get_list_var(name))
+ map.set(item, await get(prefix + item));
- /*
- * Facilitate listening to changes
- */
+ return {map, prefix, name, listeners : new Set(), lock : make_lock()};
+}
- exports.add_change_listener = function (cb, prefixes=list_prefixes)
- {
- if (typeof(prefixes) === "string")
- prefixes = [prefixes];
+var pages;
+var bags;
+var scripts;
- for (let prefix of prefixes)
- list_by_prefix[prefix].listeners.add(cb);
- }
+var list_by_prefix = {};
- exports.remove_change_listener = function (cb, prefixes=list_prefixes)
- {
- if (typeof(prefixes) === "string")
- prefixes = [prefixes];
+async function init()
+{
+ for (let prefix of list_prefixes)
+ list_by_prefix[prefix] = await list(prefix);
- for (let prefix of prefixes)
- list_by_prefix[prefix].listeners.delete(cb);
- }
+ return exports;
+}
- function broadcast_change(change, list)
- {
- for (let listener_callback of list.listeners)
- listener_callback(change);
- }
+/*
+ * Facilitate listening to changes
+ */
- /* Prepare some hepler functions to get elements of a list */
+exports.add_change_listener = function (cb, prefixes=list_prefixes)
+{
+ if (typeof(prefixes) === "string")
+ prefixes = [prefixes];
- function list_items_it(list, with_values=false)
- {
- return with_values ? list.map.entries() : list.map.keys();
- }
+ for (let prefix of prefixes)
+ list_by_prefix[prefix].listeners.add(cb);
+}
- function list_entries_it(list)
- {
- return list_items_it(list, true);
- }
+exports.remove_change_listener = function (cb, prefixes=list_prefixes)
+{
+ if (typeof(prefixes) === "string")
+ prefixes = [prefixes];
- function list_items(list, with_values=false)
- {
- let array = [];
+ for (let prefix of prefixes)
+ list_by_prefix[prefix].listeners.delete(cb);
+}
- for (let item of list_items_it(list, with_values))
- array.push(item);
+function broadcast_change(change, list)
+{
+ for (let listener_callback of list.listeners)
+ listener_callback(change);
+}
- return array;
- }
+/* Prepare some hepler functions to get elements of a list */
- function list_entries(list)
- {
- return list_items(list, true);
- }
+function list_items_it(list, with_values=false)
+{
+ return with_values ? list.map.entries() : list.map.keys();
+}
- /*
- * Below we make additional effort to update map of given kind of items
- * every time an item is added/removed to keep everything coherent.
- */
- async function set_item(item, value, list)
- {
- await lock(list.lock);
- let result = await _set_item(...arguments);
- unlock(list.lock)
- return result;
- }
- async function _set_item(item, value, list)
- {
- let key = list.prefix + item;
- let old_val = list.map.get(item);
- if (old_val === undefined) {
- let items = list_items(list);
- items.push(item);
- await setn([key, value, "_" + list.name, items]);
- } else {
- await set(key, value);
- }
+function list_entries_it(list)
+{
+ return list_items_it(list, true);
+}
- list.map.set(item, value)
+function list_items(list, with_values=false)
+{
+ let array = [];
- let change = {
- prefix : list.prefix,
- item,
- old_val,
- new_val : value
- };
+ for (let item of list_items_it(list, with_values))
+ array.push(item);
- broadcast_change(change, list);
+ return array;
+}
- return old_val;
- }
+function list_entries(list)
+{
+ return list_items(list, true);
+}
- // TODO: The actual idea to set value to undefined is good - this way we can
- // also set a new list of items in the same API call. But such key
- // is still stored in the storage. We need to somehow remove it later.
- // For that, we're going to have to store 1 more list of each kind.
- async function remove_item(item, list)
- {
- await lock(list.lock);
- let result = await _remove_item(...arguments);
- unlock(list.lock)
- return result;
+/*
+ * Below we make additional effort to update map of given kind of items
+ * every time an item is added/removed to keep everything coherent.
+ */
+async function set_item(item, value, list)
+{
+ await lock(list.lock);
+ let result = await _set_item(...arguments);
+ unlock(list.lock)
+ return result;
+}
+async function _set_item(item, value, list)
+{
+ let key = list.prefix + item;
+ let old_val = list.map.get(item);
+ if (old_val === undefined) {
+ let items = list_items(list);
+ items.push(item);
+ await setn([key, value, "_" + list.name, items]);
+ } else {
+ await set(key, value);
}
- async function _remove_item(item, list)
- {
- let old_val = list.map.get(item);
+
+ list.map.set(item, value)
+
+ let change = {
+ prefix : list.prefix,
+ item,
+ old_val,
+ new_val : value
+ };
+
+ broadcast_change(change, list);
+
+ return old_val;
+}
+
+// TODO: The actual idea to set value to undefined is good - this way we can
+// also set a new list of items in the same API call. But such key
+// is still stored in the storage. We need to somehow remove it later.
+// For that, we're going to have to store 1 more list of each kind.
+async function remove_item(item, list)
+{
+ await lock(list.lock);
+ let result = await _remove_item(...arguments);
+ unlock(list.lock)
+ return result;
+}
+async function _remove_item(item, list)
+{
+ let old_val = list.map.get(item);
+ if (old_val === undefined)
+ return;
+
+ let key = list.prefix + item;
+ let items = list_items(list);
+ let index = items.indexOf(item);
+ items.splice(index, 1);
+
+ await setn([key, undefined, "_" + list.name, items]);
+
+ list.map.delete(item);
+
+ let change = {
+ prefix : list.prefix,
+ item,
+ old_val,
+ new_val : undefined
+ };
+
+ broadcast_change(change, list);
+
+ return old_val;
+}
+
+// TODO: same as above applies here
+async function replace_item(old_item, new_item, list, new_val=undefined)
+{
+ await lock(list.lock);
+ let result = await _replace_item(...arguments);
+ unlock(list.lock)
+ return result;
+}
+async function _replace_item(old_item, new_item, list, new_val=undefined)
+{
+ let old_val = list.map.get(old_item);
+ if (new_val === undefined) {
if (old_val === undefined)
return;
-
- let key = list.prefix + item;
- let items = list_items(list);
- let index = items.indexOf(item);
- items.splice(index, 1);
-
- await setn([key, undefined, "_" + list.name, items]);
-
- list.map.delete(item);
-
- let change = {
- prefix : list.prefix,
- item,
- old_val,
- new_val : undefined
- };
-
- broadcast_change(change, list);
-
+ new_val = old_val
+ } else if (new_val === old_val && new_item === old_item) {
return old_val;
}
- // TODO: same as above applies here
- async function replace_item(old_item, new_item, list, new_val=undefined)
- {
- await lock(list.lock);
- let result = await _replace_item(...arguments);
- unlock(list.lock)
- return result;
+ if (old_item === new_item || old_val === undefined) {
+ await _set_item(new_item, new_val, list);
+ return old_val;
}
- async function _replace_item(old_item, new_item, list, new_val=undefined)
- {
- let old_val = list.map.get(old_item);
- if (new_val === undefined) {
- if (old_val === undefined)
- return;
- new_val = old_val
- } else if (new_val === old_val && new_item === old_item) {
- return old_val;
- }
- if (old_item === new_item || old_val === undefined) {
- await _set_item(new_item, new_val, list);
- return old_val;
- }
+ let new_key = list.prefix + new_item;
+ let old_key = list.prefix + old_item;
+ let items = list_items(list);
+ let index = items.indexOf(old_item);
+ items[index] = new_item;
+ await setn([old_key, undefined, new_key, new_val,
+ "_" + list.name, items]);
- let new_key = list.prefix + new_item;
- let old_key = list.prefix + old_item;
- let items = list_items(list);
- let index = items.indexOf(old_item);
- items[index] = new_item;
- await setn([old_key, undefined, new_key, new_val,
- "_" + list.name, items]);
+ list.map.delete(old_item);
- list.map.delete(old_item);
+ let change = {
+ prefix : list.prefix,
+ item : old_item,
+ old_val,
+ new_val : undefined
+ };
- let change = {
- prefix : list.prefix,
- item : old_item,
- old_val,
- new_val : undefined
- };
+ broadcast_change(change, list);
- broadcast_change(change, list);
+ list.map.set(new_item, new_val);
- list.map.set(new_item, new_val);
+ change.item = new_item;
+ change.old_val = undefined;
+ change.new_val = new_val;
- change.item = new_item;
- change.old_val = undefined;
- change.new_val = new_val;
+ broadcast_change(change, list);
- broadcast_change(change, list);
-
- return old_val;
- }
+ return old_val;
+}
- /*
- * For scripts, item name is chosen by user, data should be
- * an object containing:
- * - script's url and hash or
- * - script's text or
- * - all three
- */
-
- /*
- * For bags, item name is chosen by user, data is an array of 2-element
- * arrays with type prefix and script/bag names.
- */
-
- /*
- * For pages data argument is an object with properties `allow'
- * and `components'. Item name is url.
- */
-
- exports.set = async function (prefix, item, data)
- {
- return set_item(item, data, list_by_prefix[prefix]);
- }
+/*
+ * For scripts, item name is chosen by user, data should be
+ * an object containing:
+ * - script's url and hash or
+ * - script's text or
+ * - all three
+ */
- exports.get = function (prefix, item)
- {
- return list_by_prefix[prefix].map.get(item);
- }
+/*
+ * For bags, item name is chosen by user, data is an array of 2-element
+ * arrays with type prefix and script/bag names.
+ */
- exports.remove = async function (prefix, item)
- {
- return remove_item(item, list_by_prefix[prefix]);
- }
+/*
+ * For pages data argument is an object with properties `allow'
+ * and `components'. Item name is url.
+ */
- exports.replace = async function (prefix, old_item, new_item,
- new_data=undefined)
- {
- return replace_item(old_item, new_item, list_by_prefix[prefix],
- new_data);
- }
+exports.set = async function (prefix, item, data)
+{
+ return set_item(item, data, list_by_prefix[prefix]);
+}
+
+exports.get = function (prefix, item)
+{
+ return list_by_prefix[prefix].map.get(item);
+}
+
+exports.remove = async function (prefix, item)
+{
+ return remove_item(item, list_by_prefix[prefix]);
+}
+
+exports.replace = async function (prefix, old_item, new_item,
+ new_data=undefined)
+{
+ return replace_item(old_item, new_item, list_by_prefix[prefix],
+ new_data);
+}
+
+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]);
+}
+
+/* Finally, a quick way to wipe all the data. */
+// TODO: maybe delete items in such order that none of them ever references
+// an already-deleted one?
+exports.clear = async function ()
+{
+ let lists = list_prefixes.map((p) => list_by_prefix[p]);
+
+ for (let list of lists)
+ await lock(list.lock);
- exports.get_all_names = function (prefix)
- {
- return list_items(list_by_prefix[prefix]);
- }
+ for (let list of lists) {
- exports.get_all_names_it = function (prefix)
- {
- return list_items_it(list_by_prefix[prefix]);
- }
+ let change = {
+ prefix : list.prefix,
+ new_val : undefined
+ };
- exports.get_all = function (prefix)
- {
- return list_entries(list_by_prefix[prefix]);
- }
+ for (let [item, val] of list_entries_it(list)) {
+ change.item = item;
+ change.old_val = val;
+ broadcast_change(change, list);
+ }
- exports.get_all_it = function (prefix)
- {
- return list_entries_it(list_by_prefix[prefix]);
+ list.map = new Map();
}
- /* Finally, a quick way to wipe all the data. */
- // TODO: maybe delete items in such order that none of them ever references
- // an already-deleted one?
- exports.clear = async function ()
- {
- let lists = list_prefixes.map((p) => list_by_prefix[p]);
-
- for (let list of lists)
- await lock(list.lock);
-
- for (let list of lists) {
-
- let change = {
- prefix : list.prefix,
- new_val : undefined
- };
+ await browser.storage.local.clear();
- for (let [item, val] of list_entries_it(list)) {
- change.item = item;
- change.old_val = val;
- broadcast_change(change, list);
- }
+ for (let list of lists)
+ unlock(list.lock);
+}
- list.map = new Map();
- }
-
- await browser.storage.local.clear();
+const get_storage = make_once(init);
- for (let list of lists)
- unlock(list.lock);
- }
-
- window.get_storage = make_once(init);
-})();
+/*
+ * EXPORTS_START
+ * EXPORT get_storage
+ * EXPORTS_END
+ */
diff --git a/background/storage_server.js b/background/storage_server.js
index acdca27..d39898d 100644
--- a/background/storage_server.js
+++ b/background/storage_server.js
@@ -5,58 +5,63 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"use strict";
-
-(() => {
- const listen_for_connection = window.listen_for_connection;
- const get_storage = window.get_storage;
- const TYPE_PREFIX = window.TYPE_PREFIX;
- const CONNECTION_TYPE = window.CONNECTION_TYPE;
-
- var storage;
-
- async function handle_remote_call(port, message)
- {
- let [call_id, func, args] = message;
-
- try {
- let result = await Promise.resolve(storage[func](...args));
- port.postMessage({call_id, result});
- } catch (error) {
- error = error + '';
- port.postMessage({call_id, error});
- }
- }
+/*
+ * IMPORTS_START
+ * IMPORT listen_for_connection
+ * IMPORT get_storage
+ * IMPORT TYPE_PREFIX
+ * IMPORT CONNECTION_TYPE
+ * IMPORTS_END
+ */
+
+var storage;
+
+async function handle_remote_call(port, message)
+{
+ let [call_id, func, args] = message;
- function remove_storage_listener(cb) {
- storage.remove_change_listener(cb);
+ try {
+ let result = await Promise.resolve(storage[func](...args));
+ port.postMessage({call_id, result});
+ } catch (error) {
+ error = error + '';
+ port.postMessage({call_id, error});
}
+}
- function new_connection(port)
- {
- console.log("new remote storage connection!");
+function remove_storage_listener(cb)
+{
+ storage.remove_change_listener(cb);
+}
- port.postMessage({
- [TYPE_PREFIX.SCRIPT] : storage.get_all(TYPE_PREFIX.SCRIPT),
- [TYPE_PREFIX.BAG] : storage.get_all(TYPE_PREFIX.BAG),
- [TYPE_PREFIX.PAGE] : storage.get_all(TYPE_PREFIX.PAGE)
- });
+function new_connection(port)
+{
+ console.log("new remote storage connection!");
- let handle_change = change => port.postMessage(change);
+ port.postMessage({
+ [TYPE_PREFIX.SCRIPT] : storage.get_all(TYPE_PREFIX.SCRIPT),
+ [TYPE_PREFIX.BAG] : storage.get_all(TYPE_PREFIX.BAG),
+ [TYPE_PREFIX.PAGE] : storage.get_all(TYPE_PREFIX.PAGE)
+ });
- storage.add_change_listener(handle_change);
+ let handle_change = change => port.postMessage(change);
- port.onMessage.addListener(m => handle_remote_call(port, m));
- port.onDisconnect.addListener(() =>
- remove_storage_listener(handle_change));
- }
+ storage.add_change_listener(handle_change);
- async function start()
- {
- storage = await get_storage();
+ port.onMessage.addListener(m => handle_remote_call(port, m));
+ port.onDisconnect.addListener(() =>
+ remove_storage_listener(handle_change));
+}
- listen_for_connection(CONNECTION_TYPE.REMOTE_STORAGE, new_connection);
- }
+async function start_storage_server()
+{
+ storage = await get_storage();
- window.start_storage_server = start;
-})();
+ listen_for_connection(CONNECTION_TYPE.REMOTE_STORAGE, new_connection);
+}
+
+/*
+ * EXPORTS_START
+ * EXPORT start_storage_server
+ * EXPORTS_END
+ */
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..efa53f5
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,289 @@
+#!/bin/sh
+
+# Copyright (C) 2021 Wojtek Kosior
+# Redistribution terms are gathered in the `copyright' file.
+
+ENDL="
+"
+
+errcho() {
+ echo "$@" >&2
+}
+
+map_set_instr() {
+ echo "$1__$2='$3'"
+}
+
+map_set() {
+ eval "$(map_set_instr "$@")"
+}
+
+map_get() {
+ eval "echo \"\$$1__$2\""
+}
+
+map_del_instr() {
+ echo "unset $1__$2"
+}
+
+map_del() {
+ eval "$(map_del_instr "$@")"
+}
+
+sanitize() {
+ echo "$1" | tr /.- _
+}
+
+handle_export_line() {
+ if [ "x$1" = "xEXPORTS_START" ]; then
+ if [ "$STATE" = "before_block" ]; then
+ STATE="in_block"
+ fi
+ elif [ "x$1" = "xEXPORT" ]; then
+ if [ "$STATE" != "in_block" ]; then
+ return
+ fi
+
+ EXPORTCODE="${EXPORTCODE}window.killtheweb.$2 = $2;$ENDL"
+
+ PREVIOUS_FILE="$(map_get EXPORTS $2)"
+ if [ "x$PREVIOUS_FILE" != "x" ]; then
+ errcho "export $2 present in both $PREVIOUS_FILE and $FILE"
+ return 1
+ fi
+
+ map_set_instr EXPORTS $2 "$FILE"
+
+ elif [ "x$1" = "xEXPORTS_END" ]; then
+ if [ "$STATE" = "in_block" ]; then
+ STATE="after_block"
+ fi
+ fi
+}
+
+translate_exports() {
+ STATE="before_block"
+ EXPORTCODE=''
+
+ while read EXPORT_LINE; do
+ handle_export_line $EXPORT_LINE || return 1
+ done
+
+ map_set_instr EXPORTCODES $FILEKEY "$EXPORTCODE"
+}
+
+add_exports() {
+ FILE="$1"
+ FILEKEY="$(sanitize "$FILE")"
+
+ eval "$(grep -o 'EXPORT.\+' "$1" | translate_exports || exit 1)"
+}
+
+handle_import_line() {
+ if [ "x$1" = "xIMPORTS_START" ]; then
+ if [ "$STATE" = "before_block" ]; then
+ STATE="in_block"
+ fi
+ elif [ "x$1" = "xIMPORT" ]; then
+ if [ "$STATE" != "in_block" ]; then
+ return
+ fi
+
+ IMPORTCODE="${IMPORTCODE}const $2 = window.killtheweb.$2;$ENDL"
+
+ IMPORTS="$IMPORTS $2"
+
+ elif [ "x$1" = "xIMPORTS_END" ]; then
+ if [ "$STATE" = "in_block" ]; then
+ STATE="after_block"
+ fi
+ fi
+}
+
+translate_imports() {
+ STATE="before_block"
+ IMPORTCODE=''
+ IMPORTS=''
+
+ while read IMPORT_LINE; do
+ handle_import_line $IMPORT_LINE || return 1
+ done
+
+ map_set_instr IMPORTCODES $FILEKEY "$IMPORTCODE"
+ map_set_instr IMPORTS $FILEKEY "$IMPORTS"
+}
+
+add_imports() {
+ FILE="$1"
+ FILEKEY="$(sanitize "$FILE")"
+
+ eval "$(grep -o 'IMPORT.\+' "$1" | translate_imports || exit 1)"
+}
+
+compute_scripts_list_rec() {
+ local FILE="$1"
+ local FILEKEY=$(sanitize "$1")
+
+ local FILESTATE="$(map_get FILESTATES $FILEKEY)"
+ if [ "xprocessed" = "x$FILESTATE" ]; then
+ return
+ fi
+ if [ "xprocessing" = "x$FILESTATE" ]; then
+ errcho "import loop on $FILE"
+ return 1
+ fi
+
+ USED="$USED $FILEKEY"
+
+ map_set FILESTATES $FILEKEY "processing"
+
+ local IMPORT
+ for IMPORT in $(map_get IMPORTS $FILEKEY); do
+ NEXT_FILE="$(map_get EXPORTS $IMPORT)"
+ if [ "x" = "x$NEXT_FILE" ]; then
+ errcho "nothing exports $IMPORT, required by $FILE"
+ return 1
+ fi
+ if ! compute_scripts_list_rec "$NEXT_FILE"; then
+ errcho "when satisfying $IMPORT for $FILE"
+ return 1
+ fi
+ done
+
+ echo $FILE
+ map_set FILESTATES $FILEKEY "processed"
+}
+
+compute_scripts_list() {
+ USED=''
+ echo COMPUTED_SCRIPTS=\"exports_init.js
+ compute_scripts_list_rec "$1"
+ echo \"
+
+ for FILEKEY in $USED; do
+ map_set_instr USED $FILEKEY yes
+ done
+}
+
+as_json_list() {
+ while true; do
+ if [ "x" = "x$2" ]; then
+ echo -n '\\n'"\t\t\"$1\""'\\n\t'
+ return
+ fi
+ echo -n '\\n'"\t\t\"$1\","
+ shift
+ done
+}
+
+as_html_list() {
+ while [ "x" != "x$1" ]; do
+ echo -n '\\n'" <script src=\"/$1\"></script>"
+ shift
+ done
+}
+
+set_browser() {
+ if [ "x$1" = "xmozilla" -o "x$1" = "xchromium" ]; then
+ BROWSER="$1"
+ else
+ errcho "usage: $0 mozilla|chromium"
+ exit 1
+ fi
+}
+
+main() {
+ set_browser "$1"
+
+ SCRIPTDIRS='background html common content'
+
+ SCRIPTS=$(find $SCRIPTDIRS -name '*.js')
+
+ for SCRIPT in $SCRIPTS; do
+ add_exports $SCRIPT
+ add_imports $SCRIPT
+ done
+
+ eval "$(compute_scripts_list background/main.js || exit 1)"
+ BGSCRIPTS="$(as_json_list $COMPUTED_SCRIPTS)"
+ eval "$(compute_scripts_list content/main.js || exit 1)"
+ CONTENTSCRIPTS="$(as_json_list $COMPUTED_SCRIPTS)"
+ eval "$(compute_scripts_list html/display-panel.js || exit 1)"
+ POPUPSCRIPTS="$(as_html_list $COMPUTED_SCRIPTS)"
+ eval "$(compute_scripts_list html/options_main.js || exit 1)"
+ OPTIONSSCRIPTS="$(as_html_list $COMPUTED_SCRIPTS)"
+
+ BUILDDIR=build_$BROWSER
+ rm -rf $BUILDDIR
+ mkdir $BUILDDIR
+ for DIR in $(find $SCRIPTDIRS -type d); do
+ mkdir -p $BUILDDIR/$DIR
+ done
+
+ CHROMIUM_KEY=''
+ GECKO_APPLICATIONS=''
+
+ if [ "$BROWSER" = "chromium" ]; then
+ CHROMIUM_KEY="\n\
+\n\
+ // WARNING!!!\n\
+ // EACH USER SHOULD REPLACE \"key\" WITH A UNIQUE VALUE!!!\n\
+ // OTHERWISE, SECURITY CAN BE TRIVIALLY COMPROMISED!\n\
+ //\n\
+ // A unique key can be generated with:\n\
+ // $ ssh-keygen -f /path/to/new/key.pem -t rsa -b 1024\n\
+ //\n\
+ // Only relevant to users of chrome-based browsers.\n\
+ // Users of Firefox forks are safe.\n\
+\n\
+ \"key\": \"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAlwAAAAdzc2gtcnNhAAAAAwEAAQAAAIEA+0GT5WNmRRo8e5tL9+BmNtY6aBPwLIgbPnLShYBMSR40iYwLTsccrkwBXb3bs1o4p6q5WJugI8Lsia+GXZc/XHGFkq7D1aWiTxlJLs8z0JC2TQ2/yatYmBMchogYGeeUfP7aI7JJZwpATts+VhIvgga/4FYj+DijMIEpwdckqFEAAAII4Dh7HOA4exwAAAAHc3NoLXJzYQAAAIEA+0GT5WNmRRo8e5tL9+BmNtY6aBPwLIgbPnLShYBMSR40iYwLTsccrkwBXb3bs1o4p6q5WJugI8Lsia+GXZc/XHGFkq7D1aWiTxlJLs8z0JC2TQ2/yatYmBMchogYGeeUfP7aI7JJZwpATts+VhIvgga/4FYj+DijMIEpwdckqFEAAAADAQABAAAAgEHB5/MhEKMFOs8e1cMJ97ZiWubiUPlWpcqyQmauLUj1nspg3JTBh8AWJEVkaxuFgU5gYCHQmRjC6yUdywyziOEkFA4r/WpX4WmbIe+GQHRHhitLN0dgF8N6/fVNOoa5StTdfZqyl23pVXyepoDNjrJFKyupqPMmpwfH5lGr9RwBAAAAQG76HflB/5j8P2YgIYX6dQT4Ei0SqiIjNVy7jFJUQDKSJg/PYkedE02JZJBJPcMYxEJUxXtMgq+upamNILfkmY0AAABBAP4v0O5dqjy16xDDFzb4DPNAcw5Za9KJaXKVkUuKXMNZOKTR0RC/upjNTmttY980RKdIx5zA25dO8cx563bSDIsAAABBAP0MaOpBiai/eRmLqhlthHODa+Mur6W3uc9PyhWhgDBjLNMR/doaYeyfVKxtIiN3a+HkN++G+vbokRweQv++bhMAAAANdXJ6QGxvY2FsaG9zdAECAwQFBg==\","
+ else
+ GECKO_APPLICATIONS="\n\
+ \"applications\": {\n\
+ \"gecko\": {\n\
+ \"id\": \"{6fe13369-88e9-440f-b837-5012fb3bedec}\",\n\
+ \"strict_min_version\": \"60.0\"\n\
+ }\n\
+ },"
+ fi
+
+ sed "\
+s^_GECKO_APPLICATIONS_^$GECKO_APPLICATIONS^
+s^_CHROMIUM_KEY_^$CHROMIUM_KEY^
+s^_BGSCRIPTS_^$BGSCRIPTS^
+s^_CONTENTSCRIPTS_^$CONTENTSCRIPTS^" \
+ < manifest.json > $BUILDDIR/manifest.json
+
+ sed "s^_POPUPSCRIPTS_^$POPUPSCRIPTS^" \
+ < html/display-panel.html > $BUILDDIR/html/display-panel.html
+
+ sed "s^_OPTIONSSCRIPTS_^$OPTIONSSCRIPTS^" \
+ < html/options.html > $BUILDDIR/html/options.html
+
+ for FILE in $SCRIPTS; do
+ FILEKEY=$(sanitize "$FILE")
+ if [ "xyes" != "x$(map_get USED $FILEKEY)" ]; then
+ errcho "WARNING! $FILE not used"
+ else
+ (echo "\
+\"use strict\";
+
+(() => {
+$(map_get IMPORTCODES $FILEKEY)
+
+"; cat $FILE; echo "
+
+$(map_get EXPORTCODES $FILEKEY)
+})();") > $BUILDDIR/$FILE
+ fi
+ done
+
+ echo "\
+window.killtheweb={};
+window.browser = this.browser; /* fix for stupid Firefox */
+" > $BUILDDIR/exports_init.js
+
+ cp -r icons/ copyright licenses/ $BUILDDIR
+}
+
+main "$@"
diff --git a/common/browser.js b/common/browser.js
index 0ff3510..e50a121 100644
--- a/common/browser.js
+++ b/common/browser.js
@@ -5,21 +5,19 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"use strict";
-
/*
* This module normalizes access to WebExtension apis between
* chrome-based and firefox-based browsers.
*/
-(() => {
- if (typeof browser === "object") {
- window.browser = browser;
- window.is_chrome = false;
- window.is_mozilla = true;
- } else {
- window.browser = window.chrome;
- window.is_chrome = true;
- window.is_mozilla = false;
- }
-})();
+const is_mozilla = typeof window.browser === "object";
+const is_chrome = !is_mozilla;
+const browser = window[is_chrome ? "chrome" : "browser"];
+
+/*
+ * EXPORTS_START
+ * EXPORT browser
+ * EXPORT is_chrome
+ * EXPORT is_mozilla
+ * EXPORTS_END
+ */
diff --git a/common/connection_types.js b/common/connection_types.js
index cc3c976..e227532 100644
--- a/common/connection_types.js
+++ b/common/connection_types.js
@@ -5,18 +5,18 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"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"
+};
- window.CONNECTION_TYPE = CONNECTION_TYPE;
-})();
+/*
+ * EXPORTS_START
+ * EXPORT CONNECTION_TYPE
+ * EXPORTS_END
+ */
diff --git a/common/gen_unique.js b/common/gen_unique.js
index 4bcfd67..7ec8b4a 100644
--- a/common/gen_unique.js
+++ b/common/gen_unique.js
@@ -5,25 +5,29 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"use strict";
-
-(() => {
- const sha256 = window.sha256;
- const browser = window.browser;
- const is_chrome = window.is_chrome;
+/*
+ * IMPORTS_START
+ * IMPORT sha256
+ * IMPORT browser
+ * IMPORT is_chrome
+ * IMPORTS_END
+ */
- function get_id()
- {
- if (is_chrome)
- return browser.runtime.getManifest().key.substring(0, 50);
- else
- return browser.runtime.getURL("dummy");
- }
+function get_id()
+{
+ if (is_chrome)
+ return browser.runtime.getManifest().key.substring(0, 50);
+ else
+ return browser.runtime.getURL("dummy");
+}
- function gen_unique(url)
- {
- return "#" + sha256(get_id() + url);
- }
+function gen_unique(url)
+{
+ return "#" + sha256(get_id() + url);
+}
- window.gen_unique = gen_unique;
-})();
+/*
+ * EXPORTS_START
+ * EXPORT gen_unique
+ * EXPORTS_END
+ */
diff --git a/common/lock.js b/common/lock.js
index 3358393..1130762 100644
--- a/common/lock.js
+++ b/common/lock.js
@@ -19,40 +19,40 @@
* in a promise.
*/
-"use strict";
-
-(() => {
- function make_lock() {
- return {free: true, queue: []};
+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 _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);
}
+}
- 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;
-})();
+/*
+ * EXPORTS_START
+ * EXPORT make_lock
+ * EXPORT lock
+ * EXPORT unlock
+ * EXPORTS_END
+ */
diff --git a/common/once.js b/common/once.js
index d56b3c8..e3e6dbe 100644
--- a/common/once.js
+++ b/common/once.js
@@ -5,37 +5,37 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"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 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;
+async function get_result(state)
+{
+ if (state.ready)
+ return state.result;
- return new Promise((resolve, reject) => state.waiting.push(resolve));
- }
+ 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);
- }
+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;
-})();
+/*
+ * EXPORTS_START
+ * EXPORT make_once
+ * EXPORTS_END
+ */
diff --git a/common/sha256.js b/common/sha256.js
index 271ec87..4fa07b5 100644
--- a/common/sha256.js
+++ b/common/sha256.js
@@ -7,32 +7,28 @@
* @license MIT
*/
-"use strict";
+var fake_window = {};
-(() => {
- var fake_window = {};
-
- console.log('hello, crypto!');
- var ERROR = 'input is invalid type';
- var WINDOW = typeof window === 'object';
- var root = /*WINDOW ? window : {}*/ fake_window;
- if (root.JS_SHA256_NO_WINDOW) {
+var ERROR = 'input is invalid type';
+var WINDOW = typeof fake_window === 'object';
+var root = /*WINDOW ? window : {}*/ fake_window;
+if (root.JS_SHA256_NO_WINDOW) {
WINDOW = false;
- }
- var WEB_WORKER = !WINDOW && typeof self === 'object';
- var NODE_JS = !root.JS_SHA256_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;
- if (NODE_JS) {
+}
+var WEB_WORKER = !WINDOW && typeof self === 'object';
+var NODE_JS = !root.JS_SHA256_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;
+if (NODE_JS) {
root = global;
- } else if (WEB_WORKER) {
+} else if (WEB_WORKER) {
root = self;
- }
- var COMMON_JS = !root.JS_SHA256_NO_COMMON_JS && typeof module === 'object' && module.exports;
- var AMD = typeof define === 'function' && define.amd;
- var ARRAY_BUFFER = !root.JS_SHA256_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';
- var HEX_CHARS = '0123456789abcdef'.split('');
- var EXTRA = [-2147483648, 8388608, 32768, 128];
- var SHIFT = [24, 16, 8, 0];
- var K = [
+}
+var COMMON_JS = !root.JS_SHA256_NO_COMMON_JS && typeof module === 'object' && module.exports;
+var AMD = typeof define === 'function' && define.amd;
+var ARRAY_BUFFER = !root.JS_SHA256_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';
+var HEX_CHARS = '0123456789abcdef'.split('');
+var EXTRA = [-2147483648, 8388608, 32768, 128];
+var SHIFT = [24, 16, 8, 0];
+var K = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
@@ -41,209 +37,209 @@
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
- ];
- var OUTPUT_TYPES = ['hex', 'array', 'digest', 'arrayBuffer'];
+];
+var OUTPUT_TYPES = ['hex', 'array', 'digest', 'arrayBuffer'];
- var blocks = [];
+var blocks = [];
- if (root.JS_SHA256_NO_NODE_JS || !Array.isArray) {
+if (root.JS_SHA256_NO_NODE_JS || !Array.isArray) {
Array.isArray = function (obj) {
- return Object.prototype.toString.call(obj) === '[object Array]';
+ return Object.prototype.toString.call(obj) === '[object Array]';
};
- }
+}
- if (ARRAY_BUFFER && (root.JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) {
+if (ARRAY_BUFFER && (root.JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) {
ArrayBuffer.isView = function (obj) {
- return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer;
+ return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer;
};
- }
+}
- var createOutputMethod = function (outputType, is224) {
+var createOutputMethod = function (outputType, is224) {
return function (message) {
- return new Sha256(is224, true).update(message)[outputType]();
+ return new Sha256(is224, true).update(message)[outputType]();
};
- };
+};
- var createMethod = function (is224) {
+var createMethod = function (is224) {
var method = createOutputMethod('hex', is224);
if (NODE_JS) {
- method = nodeWrap(method, is224);
+ method = nodeWrap(method, is224);
}
method.create = function () {
- return new Sha256(is224);
+ return new Sha256(is224);
};
method.update = function (message) {
- return method.create().update(message);
+ return method.create().update(message);
};
for (var i = 0; i < OUTPUT_TYPES.length; ++i) {
- var type = OUTPUT_TYPES[i];
- method[type] = createOutputMethod(type, is224);
+ var type = OUTPUT_TYPES[i];
+ method[type] = createOutputMethod(type, is224);
}
return method;
- };
+};
- var nodeWrap = function (method, is224) {
+var nodeWrap = function (method, is224) {
var crypto = eval("require('crypto')");
var Buffer = eval("require('buffer').Buffer");
var algorithm = is224 ? 'sha224' : 'sha256';
var nodeMethod = function (message) {
- if (typeof message === 'string') {
- return crypto.createHash(algorithm).update(message, 'utf8').digest('hex');
- } else {
- if (message === null || message === undefined) {
- throw new Error(ERROR);
- } else if (message.constructor === ArrayBuffer) {
- message = new Uint8Array(message);
- }
- }
- if (Array.isArray(message) || ArrayBuffer.isView(message) ||
- message.constructor === Buffer) {
- return crypto.createHash(algorithm).update(new Buffer(message)).digest('hex');
- } else {
- return method(message);
- }
+ if (typeof message === 'string') {
+ return crypto.createHash(algorithm).update(message, 'utf8').digest('hex');
+ } else {
+ if (message === null || message === undefined) {
+ throw new Error(ERROR);
+ } else if (message.constructor === ArrayBuffer) {
+ message = new Uint8Array(message);
+ }
+ }
+ if (Array.isArray(message) || ArrayBuffer.isView(message) ||
+ message.constructor === Buffer) {
+ return crypto.createHash(algorithm).update(new Buffer(message)).digest('hex');
+ } else {
+ return method(message);
+ }
};
return nodeMethod;
- };
+};
- var createHmacOutputMethod = function (outputType, is224) {
+var createHmacOutputMethod = function (outputType, is224) {
return function (key, message) {
- return new HmacSha256(key, is224, true).update(message)[outputType]();
+ return new HmacSha256(key, is224, true).update(message)[outputType]();
};
- };
+};
- var createHmacMethod = function (is224) {
+var createHmacMethod = function (is224) {
var method = createHmacOutputMethod('hex', is224);
method.create = function (key) {
- return new HmacSha256(key, is224);
+ return new HmacSha256(key, is224);
};
method.update = function (key, message) {
- return method.create(key).update(message);
+ return method.create(key).update(message);
};
for (var i = 0; i < OUTPUT_TYPES.length; ++i) {
- var type = OUTPUT_TYPES[i];
- method[type] = createHmacOutputMethod(type, is224);
+ var type = OUTPUT_TYPES[i];
+ method[type] = createHmacOutputMethod(type, is224);
}
return method;
- };
+};
- function Sha256(is224, sharedMemory) {
+function Sha256(is224, sharedMemory) {
if (sharedMemory) {
- blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] =
- blocks[4] = blocks[5] = blocks[6] = blocks[7] =
- blocks[8] = blocks[9] = blocks[10] = blocks[11] =
- blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
- this.blocks = blocks;
+ blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] =
+ blocks[4] = blocks[5] = blocks[6] = blocks[7] =
+ blocks[8] = blocks[9] = blocks[10] = blocks[11] =
+ blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
+ this.blocks = blocks;
} else {
- this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
}
if (is224) {
- this.h0 = 0xc1059ed8;
- this.h1 = 0x367cd507;
- this.h2 = 0x3070dd17;
- this.h3 = 0xf70e5939;
- this.h4 = 0xffc00b31;
- this.h5 = 0x68581511;
- this.h6 = 0x64f98fa7;
- this.h7 = 0xbefa4fa4;
+ this.h0 = 0xc1059ed8;
+ this.h1 = 0x367cd507;
+ this.h2 = 0x3070dd17;
+ this.h3 = 0xf70e5939;
+ this.h4 = 0xffc00b31;
+ this.h5 = 0x68581511;
+ this.h6 = 0x64f98fa7;
+ this.h7 = 0xbefa4fa4;
} else { // 256
- this.h0 = 0x6a09e667;
- this.h1 = 0xbb67ae85;
- this.h2 = 0x3c6ef372;
- this.h3 = 0xa54ff53a;
- this.h4 = 0x510e527f;
- this.h5 = 0x9b05688c;
- this.h6 = 0x1f83d9ab;
- this.h7 = 0x5be0cd19;
+ this.h0 = 0x6a09e667;
+ this.h1 = 0xbb67ae85;
+ this.h2 = 0x3c6ef372;
+ this.h3 = 0xa54ff53a;
+ this.h4 = 0x510e527f;
+ this.h5 = 0x9b05688c;
+ this.h6 = 0x1f83d9ab;
+ this.h7 = 0x5be0cd19;
}
this.block = this.start = this.bytes = this.hBytes = 0;
this.finalized = this.hashed = false;
this.first = true;
this.is224 = is224;
- }
+}
- Sha256.prototype.update = function (message) {
+Sha256.prototype.update = function (message) {
if (this.finalized) {
- return;
+ return;
}
var notString, type = typeof message;
if (type !== 'string') {
- if (type === 'object') {
- if (message === null) {
- throw new Error(ERROR);
- } else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {
- message = new Uint8Array(message);
- } else if (!Array.isArray(message)) {
- if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) {
+ if (type === 'object') {
+ if (message === null) {
+ throw new Error(ERROR);
+ } else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {
+ message = new Uint8Array(message);
+ } else if (!Array.isArray(message)) {
+ if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) {
+ throw new Error(ERROR);
+ }
+ }
+ } else {
throw new Error(ERROR);
- }
- }
- } else {
- throw new Error(ERROR);
- }
- notString = true;
+ }
+ notString = true;
}
var code, index = 0, i, length = message.length, blocks = this.blocks;
while (index < length) {
- if (this.hashed) {
- this.hashed = false;
- blocks[0] = this.block;
- blocks[16] = blocks[1] = blocks[2] = blocks[3] =
- blocks[4] = blocks[5] = blocks[6] = blocks[7] =
- blocks[8] = blocks[9] = blocks[10] = blocks[11] =
- blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
- }
-
- if (notString) {
- for (i = this.start; index < length && i < 64; ++index) {
- blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
- }
- } else {
- for (i = this.start; index < length && i < 64; ++index) {
- code = message.charCodeAt(index);
- if (code < 0x80) {
- blocks[i >> 2] |= code << SHIFT[i++ & 3];
- } else if (code < 0x800) {
- blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
- blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
- } else if (code < 0xd800 || code >= 0xe000) {
- blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
- blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
- blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
- } else {
- code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
- blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
- blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
- blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
- blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
- }
- }
- }
-
- this.lastByteIndex = i;
- this.bytes += i - this.start;
- if (i >= 64) {
- this.block = blocks[16];
- this.start = i - 64;
- this.hash();
- this.hashed = true;
- } else {
- this.start = i;
- }
+ if (this.hashed) {
+ this.hashed = false;
+ blocks[0] = this.block;
+ blocks[16] = blocks[1] = blocks[2] = blocks[3] =
+ blocks[4] = blocks[5] = blocks[6] = blocks[7] =
+ blocks[8] = blocks[9] = blocks[10] = blocks[11] =
+ blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
+ }
+
+ if (notString) {
+ for (i = this.start; index < length && i < 64; ++index) {
+ blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
+ }
+ } else {
+ for (i = this.start; index < length && i < 64; ++index) {
+ code = message.charCodeAt(index);
+ if (code < 0x80) {
+ blocks[i >> 2] |= code << SHIFT[i++ & 3];
+ } else if (code < 0x800) {
+ blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
+ blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
+ } else if (code < 0xd800 || code >= 0xe000) {
+ blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
+ blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
+ blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
+ } else {
+ code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
+ blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
+ blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
+ blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
+ blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
+ }
+ }
+ }
+
+ this.lastByteIndex = i;
+ this.bytes += i - this.start;
+ if (i >= 64) {
+ this.block = blocks[16];
+ this.start = i - 64;
+ this.hash();
+ this.hashed = true;
+ } else {
+ this.start = i;
+ }
}
if (this.bytes > 4294967295) {
- this.hBytes += this.bytes / 4294967296 << 0;
- this.bytes = this.bytes % 4294967296;
+ this.hBytes += this.bytes / 4294967296 << 0;
+ this.bytes = this.bytes % 4294967296;
}
return this;
- };
+};
- Sha256.prototype.finalize = function () {
+Sha256.prototype.finalize = function () {
if (this.finalized) {
- return;
+ return;
}
this.finalized = true;
var blocks = this.blocks, i = this.lastByteIndex;
@@ -251,86 +247,86 @@
blocks[i >> 2] |= EXTRA[i & 3];
this.block = blocks[16];
if (i >= 56) {
- if (!this.hashed) {
- this.hash();
- }
- blocks[0] = this.block;
- blocks[16] = blocks[1] = blocks[2] = blocks[3] =
- blocks[4] = blocks[5] = blocks[6] = blocks[7] =
- blocks[8] = blocks[9] = blocks[10] = blocks[11] =
- blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
+ if (!this.hashed) {
+ this.hash();
+ }
+ blocks[0] = this.block;
+ blocks[16] = blocks[1] = blocks[2] = blocks[3] =
+ blocks[4] = blocks[5] = blocks[6] = blocks[7] =
+ blocks[8] = blocks[9] = blocks[10] = blocks[11] =
+ blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
}
blocks[14] = this.hBytes << 3 | this.bytes >>> 29;
blocks[15] = this.bytes << 3;
this.hash();
- };
+};
- Sha256.prototype.hash = function () {
+Sha256.prototype.hash = function () {
var a = this.h0, b = this.h1, c = this.h2, d = this.h3, e = this.h4, f = this.h5, g = this.h6,
- h = this.h7, blocks = this.blocks, j, s0, s1, maj, t1, t2, ch, ab, da, cd, bc;
+ h = this.h7, blocks = this.blocks, j, s0, s1, maj, t1, t2, ch, ab, da, cd, bc;
for (j = 16; j < 64; ++j) {
- // rightrotate
- t1 = blocks[j - 15];
- s0 = ((t1 >>> 7) | (t1 << 25)) ^ ((t1 >>> 18) | (t1 << 14)) ^ (t1 >>> 3);
- t1 = blocks[j - 2];
- s1 = ((t1 >>> 17) | (t1 << 15)) ^ ((t1 >>> 19) | (t1 << 13)) ^ (t1 >>> 10);
- blocks[j] = blocks[j - 16] + s0 + blocks[j - 7] + s1 << 0;
+ // rightrotate
+ t1 = blocks[j - 15];
+ s0 = ((t1 >>> 7) | (t1 << 25)) ^ ((t1 >>> 18) | (t1 << 14)) ^ (t1 >>> 3);
+ t1 = blocks[j - 2];
+ s1 = ((t1 >>> 17) | (t1 << 15)) ^ ((t1 >>> 19) | (t1 << 13)) ^ (t1 >>> 10);
+ blocks[j] = blocks[j - 16] + s0 + blocks[j - 7] + s1 << 0;
}
bc = b & c;
for (j = 0; j < 64; j += 4) {
- if (this.first) {
- if (this.is224) {
- ab = 300032;
- t1 = blocks[0] - 1413257819;
- h = t1 - 150054599 << 0;
- d = t1 + 24177077 << 0;
- } else {
- ab = 704751109;
- t1 = blocks[0] - 210244248;
- h = t1 - 1521486534 << 0;
- d = t1 + 143694565 << 0;
- }
- this.first = false;
- } else {
- s0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10));
- s1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7));
- ab = a & b;
- maj = ab ^ (a & c) ^ bc;
- ch = (e & f) ^ (~e & g);
- t1 = h + s1 + ch + K[j] + blocks[j];
- t2 = s0 + maj;
- h = d + t1 << 0;
- d = t1 + t2 << 0;
- }
- s0 = ((d >>> 2) | (d << 30)) ^ ((d >>> 13) | (d << 19)) ^ ((d >>> 22) | (d << 10));
- s1 = ((h >>> 6) | (h << 26)) ^ ((h >>> 11) | (h << 21)) ^ ((h >>> 25) | (h << 7));
- da = d & a;
- maj = da ^ (d & b) ^ ab;
- ch = (h & e) ^ (~h & f);
- t1 = g + s1 + ch + K[j + 1] + blocks[j + 1];
- t2 = s0 + maj;
- g = c + t1 << 0;
- c = t1 + t2 << 0;
- s0 = ((c >>> 2) | (c << 30)) ^ ((c >>> 13) | (c << 19)) ^ ((c >>> 22) | (c << 10));
- s1 = ((g >>> 6) | (g << 26)) ^ ((g >>> 11) | (g << 21)) ^ ((g >>> 25) | (g << 7));
- cd = c & d;
- maj = cd ^ (c & a) ^ da;
- ch = (g & h) ^ (~g & e);
- t1 = f + s1 + ch + K[j + 2] + blocks[j + 2];
- t2 = s0 + maj;
- f = b + t1 << 0;
- b = t1 + t2 << 0;
- s0 = ((b >>> 2) | (b << 30)) ^ ((b >>> 13) | (b << 19)) ^ ((b >>> 22) | (b << 10));
- s1 = ((f >>> 6) | (f << 26)) ^ ((f >>> 11) | (f << 21)) ^ ((f >>> 25) | (f << 7));
- bc = b & c;
- maj = bc ^ (b & d) ^ cd;
- ch = (f & g) ^ (~f & h);
- t1 = e + s1 + ch + K[j + 3] + blocks[j + 3];
- t2 = s0 + maj;
- e = a + t1 << 0;
- a = t1 + t2 << 0;
+ if (this.first) {
+ if (this.is224) {
+ ab = 300032;
+ t1 = blocks[0] - 1413257819;
+ h = t1 - 150054599 << 0;
+ d = t1 + 24177077 << 0;
+ } else {
+ ab = 704751109;
+ t1 = blocks[0] - 210244248;
+ h = t1 - 1521486534 << 0;
+ d = t1 + 143694565 << 0;
+ }
+ this.first = false;
+ } else {
+ s0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10));
+ s1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7));
+ ab = a & b;
+ maj = ab ^ (a & c) ^ bc;
+ ch = (e & f) ^ (~e & g);
+ t1 = h + s1 + ch + K[j] + blocks[j];
+ t2 = s0 + maj;
+ h = d + t1 << 0;
+ d = t1 + t2 << 0;
+ }
+ s0 = ((d >>> 2) | (d << 30)) ^ ((d >>> 13) | (d << 19)) ^ ((d >>> 22) | (d << 10));
+ s1 = ((h >>> 6) | (h << 26)) ^ ((h >>> 11) | (h << 21)) ^ ((h >>> 25) | (h << 7));
+ da = d & a;
+ maj = da ^ (d & b) ^ ab;
+ ch = (h & e) ^ (~h & f);
+ t1 = g + s1 + ch + K[j + 1] + blocks[j + 1];
+ t2 = s0 + maj;
+ g = c + t1 << 0;
+ c = t1 + t2 << 0;
+ s0 = ((c >>> 2) | (c << 30)) ^ ((c >>> 13) | (c << 19)) ^ ((c >>> 22) | (c << 10));
+ s1 = ((g >>> 6) | (g << 26)) ^ ((g >>> 11) | (g << 21)) ^ ((g >>> 25) | (g << 7));
+ cd = c & d;
+ maj = cd ^ (c & a) ^ da;
+ ch = (g & h) ^ (~g & e);
+ t1 = f + s1 + ch + K[j + 2] + blocks[j + 2];
+ t2 = s0 + maj;
+ f = b + t1 << 0;
+ b = t1 + t2 << 0;
+ s0 = ((b >>> 2) | (b << 30)) ^ ((b >>> 13) | (b << 19)) ^ ((b >>> 22) | (b << 10));
+ s1 = ((f >>> 6) | (f << 26)) ^ ((f >>> 11) | (f << 21)) ^ ((f >>> 25) | (f << 7));
+ bc = b & c;
+ maj = bc ^ (b & d) ^ cd;
+ ch = (f & g) ^ (~f & h);
+ t1 = e + s1 + ch + K[j + 3] + blocks[j + 3];
+ t2 = s0 + maj;
+ e = a + t1 << 0;
+ a = t1 + t2 << 0;
}
this.h0 = this.h0 + a << 0;
@@ -341,77 +337,77 @@
this.h5 = this.h5 + f << 0;
this.h6 = this.h6 + g << 0;
this.h7 = this.h7 + h << 0;
- };
+};
- Sha256.prototype.hex = function () {
+Sha256.prototype.hex = function () {
this.finalize();
var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4, h5 = this.h5,
- h6 = this.h6, h7 = this.h7;
+ h6 = this.h6, h7 = this.h7;
var hex = HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] +
- HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] +
- HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] +
- HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] +
- HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] +
- HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] +
- HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] +
- HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] +
- HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] +
- HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] +
- HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] +
- HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] +
- HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F] +
- HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] +
- HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] +
- HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] +
- HEX_CHARS[(h4 >> 28) & 0x0F] + HEX_CHARS[(h4 >> 24) & 0x0F] +
- HEX_CHARS[(h4 >> 20) & 0x0F] + HEX_CHARS[(h4 >> 16) & 0x0F] +
- HEX_CHARS[(h4 >> 12) & 0x0F] + HEX_CHARS[(h4 >> 8) & 0x0F] +
- HEX_CHARS[(h4 >> 4) & 0x0F] + HEX_CHARS[h4 & 0x0F] +
- HEX_CHARS[(h5 >> 28) & 0x0F] + HEX_CHARS[(h5 >> 24) & 0x0F] +
- HEX_CHARS[(h5 >> 20) & 0x0F] + HEX_CHARS[(h5 >> 16) & 0x0F] +
- HEX_CHARS[(h5 >> 12) & 0x0F] + HEX_CHARS[(h5 >> 8) & 0x0F] +
- HEX_CHARS[(h5 >> 4) & 0x0F] + HEX_CHARS[h5 & 0x0F] +
- HEX_CHARS[(h6 >> 28) & 0x0F] + HEX_CHARS[(h6 >> 24) & 0x0F] +
- HEX_CHARS[(h6 >> 20) & 0x0F] + HEX_CHARS[(h6 >> 16) & 0x0F] +
- HEX_CHARS[(h6 >> 12) & 0x0F] + HEX_CHARS[(h6 >> 8) & 0x0F] +
- HEX_CHARS[(h6 >> 4) & 0x0F] + HEX_CHARS[h6 & 0x0F];
+ HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] +
+ HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] +
+ HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] +
+ HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] +
+ HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] +
+ HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] +
+ HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] +
+ HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] +
+ HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] +
+ HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] +
+ HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] +
+ HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F] +
+ HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] +
+ HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] +
+ HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] +
+ HEX_CHARS[(h4 >> 28) & 0x0F] + HEX_CHARS[(h4 >> 24) & 0x0F] +
+ HEX_CHARS[(h4 >> 20) & 0x0F] + HEX_CHARS[(h4 >> 16) & 0x0F] +
+ HEX_CHARS[(h4 >> 12) & 0x0F] + HEX_CHARS[(h4 >> 8) & 0x0F] +
+ HEX_CHARS[(h4 >> 4) & 0x0F] + HEX_CHARS[h4 & 0x0F] +
+ HEX_CHARS[(h5 >> 28) & 0x0F] + HEX_CHARS[(h5 >> 24) & 0x0F] +
+ HEX_CHARS[(h5 >> 20) & 0x0F] + HEX_CHARS[(h5 >> 16) & 0x0F] +
+ HEX_CHARS[(h5 >> 12) & 0x0F] + HEX_CHARS[(h5 >> 8) & 0x0F] +
+ HEX_CHARS[(h5 >> 4) & 0x0F] + HEX_CHARS[h5 & 0x0F] +
+ HEX_CHARS[(h6 >> 28) & 0x0F] + HEX_CHARS[(h6 >> 24) & 0x0F] +
+ HEX_CHARS[(h6 >> 20) & 0x0F] + HEX_CHARS[(h6 >> 16) & 0x0F] +
+ HEX_CHARS[(h6 >> 12) & 0x0F] + HEX_CHARS[(h6 >> 8) & 0x0F] +
+ HEX_CHARS[(h6 >> 4) & 0x0F] + HEX_CHARS[h6 & 0x0F];
if (!this.is224) {
- hex += HEX_CHARS[(h7 >> 28) & 0x0F] + HEX_CHARS[(h7 >> 24) & 0x0F] +
- HEX_CHARS[(h7 >> 20) & 0x0F] + HEX_CHARS[(h7 >> 16) & 0x0F] +
- HEX_CHARS[(h7 >> 12) & 0x0F] + HEX_CHARS[(h7 >> 8) & 0x0F] +
- HEX_CHARS[(h7 >> 4) & 0x0F] + HEX_CHARS[h7 & 0x0F];
+ hex += HEX_CHARS[(h7 >> 28) & 0x0F] + HEX_CHARS[(h7 >> 24) & 0x0F] +
+ HEX_CHARS[(h7 >> 20) & 0x0F] + HEX_CHARS[(h7 >> 16) & 0x0F] +
+ HEX_CHARS[(h7 >> 12) & 0x0F] + HEX_CHARS[(h7 >> 8) & 0x0F] +
+ HEX_CHARS[(h7 >> 4) & 0x0F] + HEX_CHARS[h7 & 0x0F];
}
return hex;
- };
+};
- Sha256.prototype.toString = Sha256.prototype.hex;
+Sha256.prototype.toString = Sha256.prototype.hex;
- Sha256.prototype.digest = function () {
+Sha256.prototype.digest = function () {
this.finalize();
var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4, h5 = this.h5,
- h6 = this.h6, h7 = this.h7;
+ h6 = this.h6, h7 = this.h7;
var arr = [
- (h0 >> 24) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 8) & 0xFF, h0 & 0xFF,
- (h1 >> 24) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 8) & 0xFF, h1 & 0xFF,
- (h2 >> 24) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 8) & 0xFF, h2 & 0xFF,
- (h3 >> 24) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 8) & 0xFF, h3 & 0xFF,
- (h4 >> 24) & 0xFF, (h4 >> 16) & 0xFF, (h4 >> 8) & 0xFF, h4 & 0xFF,
- (h5 >> 24) & 0xFF, (h5 >> 16) & 0xFF, (h5 >> 8) & 0xFF, h5 & 0xFF,
- (h6 >> 24) & 0xFF, (h6 >> 16) & 0xFF, (h6 >> 8) & 0xFF, h6 & 0xFF
+ (h0 >> 24) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 8) & 0xFF, h0 & 0xFF,
+ (h1 >> 24) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 8) & 0xFF, h1 & 0xFF,
+ (h2 >> 24) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 8) & 0xFF, h2 & 0xFF,
+ (h3 >> 24) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 8) & 0xFF, h3 & 0xFF,
+ (h4 >> 24) & 0xFF, (h4 >> 16) & 0xFF, (h4 >> 8) & 0xFF, h4 & 0xFF,
+ (h5 >> 24) & 0xFF, (h5 >> 16) & 0xFF, (h5 >> 8) & 0xFF, h5 & 0xFF,
+ (h6 >> 24) & 0xFF, (h6 >> 16) & 0xFF, (h6 >> 8) & 0xFF, h6 & 0xFF
];
if (!this.is224) {
- arr.push((h7 >> 24) & 0xFF, (h7 >> 16) & 0xFF, (h7 >> 8) & 0xFF, h7 & 0xFF);
+ arr.push((h7 >> 24) & 0xFF, (h7 >> 16) & 0xFF, (h7 >> 8) & 0xFF, h7 & 0xFF);
}
return arr;
- };
+};
- Sha256.prototype.array = Sha256.prototype.digest;
+Sha256.prototype.array = Sha256.prototype.digest;
- Sha256.prototype.arrayBuffer = function () {
+Sha256.prototype.arrayBuffer = function () {
this.finalize();
var buffer = new ArrayBuffer(this.is224 ? 28 : 32);
@@ -424,60 +420,60 @@
dataView.setUint32(20, this.h5);
dataView.setUint32(24, this.h6);
if (!this.is224) {
- dataView.setUint32(28, this.h7);
+ dataView.setUint32(28, this.h7);
}
return buffer;
- };
+};
- function HmacSha256(key, is224, sharedMemory) {
+function HmacSha256(key, is224, sharedMemory) {
var i, type = typeof key;
if (type === 'string') {
- var bytes = [], length = key.length, index = 0, code;
- for (i = 0; i < length; ++i) {
- code = key.charCodeAt(i);
- if (code < 0x80) {
- bytes[index++] = code;
- } else if (code < 0x800) {
- bytes[index++] = (0xc0 | (code >> 6));
- bytes[index++] = (0x80 | (code & 0x3f));
- } else if (code < 0xd800 || code >= 0xe000) {
- bytes[index++] = (0xe0 | (code >> 12));
- bytes[index++] = (0x80 | ((code >> 6) & 0x3f));
- bytes[index++] = (0x80 | (code & 0x3f));
- } else {
- code = 0x10000 + (((code & 0x3ff) << 10) | (key.charCodeAt(++i) & 0x3ff));
- bytes[index++] = (0xf0 | (code >> 18));
- bytes[index++] = (0x80 | ((code >> 12) & 0x3f));
- bytes[index++] = (0x80 | ((code >> 6) & 0x3f));
- bytes[index++] = (0x80 | (code & 0x3f));
- }
- }
- key = bytes;
+ var bytes = [], length = key.length, index = 0, code;
+ for (i = 0; i < length; ++i) {
+ code = key.charCodeAt(i);
+ if (code < 0x80) {
+ bytes[index++] = code;
+ } else if (code < 0x800) {
+ bytes[index++] = (0xc0 | (code >> 6));
+ bytes[index++] = (0x80 | (code & 0x3f));
+ } else if (code < 0xd800 || code >= 0xe000) {
+ bytes[index++] = (0xe0 | (code >> 12));
+ bytes[index++] = (0x80 | ((code >> 6) & 0x3f));
+ bytes[index++] = (0x80 | (code & 0x3f));
+ } else {
+ code = 0x10000 + (((code & 0x3ff) << 10) | (key.charCodeAt(++i) & 0x3ff));
+ bytes[index++] = (0xf0 | (code >> 18));
+ bytes[index++] = (0x80 | ((code >> 12) & 0x3f));
+ bytes[index++] = (0x80 | ((code >> 6) & 0x3f));
+ bytes[index++] = (0x80 | (code & 0x3f));
+ }
+ }
+ key = bytes;
} else {
- if (type === 'object') {
- if (key === null) {
- throw new Error(ERROR);
- } else if (ARRAY_BUFFER && key.constructor === ArrayBuffer) {
- key = new Uint8Array(key);
- } else if (!Array.isArray(key)) {
- if (!ARRAY_BUFFER || !ArrayBuffer.isView(key)) {
+ if (type === 'object') {
+ if (key === null) {
+ throw new Error(ERROR);
+ } else if (ARRAY_BUFFER && key.constructor === ArrayBuffer) {
+ key = new Uint8Array(key);
+ } else if (!Array.isArray(key)) {
+ if (!ARRAY_BUFFER || !ArrayBuffer.isView(key)) {
+ throw new Error(ERROR);
+ }
+ }
+ } else {
throw new Error(ERROR);
- }
- }
- } else {
- throw new Error(ERROR);
- }
+ }
}
if (key.length > 64) {
- key = (new Sha256(is224, true)).update(key).array();
+ key = (new Sha256(is224, true)).update(key).array();
}
var oKeyPad = [], iKeyPad = [];
for (i = 0; i < 64; ++i) {
- var b = key[i] || 0;
- oKeyPad[i] = 0x5c ^ b;
- iKeyPad[i] = 0x36 ^ b;
+ var b = key[i] || 0;
+ oKeyPad[i] = 0x5c ^ b;
+ iKeyPad[i] = 0x36 ^ b;
}
Sha256.call(this, is224, sharedMemory);
@@ -486,38 +482,43 @@
this.oKeyPad = oKeyPad;
this.inner = true;
this.sharedMemory = sharedMemory;
- }
- HmacSha256.prototype = new Sha256();
+}
+HmacSha256.prototype = new Sha256();
- HmacSha256.prototype.finalize = function () {
+HmacSha256.prototype.finalize = function () {
Sha256.prototype.finalize.call(this);
if (this.inner) {
- this.inner = false;
- var innerHash = this.array();
- Sha256.call(this, this.is224, this.sharedMemory);
- this.update(this.oKeyPad);
- this.update(innerHash);
- Sha256.prototype.finalize.call(this);
+ this.inner = false;
+ var innerHash = this.array();
+ Sha256.call(this, this.is224, this.sharedMemory);
+ this.update(this.oKeyPad);
+ this.update(innerHash);
+ Sha256.prototype.finalize.call(this);
}
- };
+};
- var exports = createMethod();
- exports.sha256 = exports;
- exports.sha224 = createMethod(true);
- exports.sha256.hmac = createHmacMethod();
- exports.sha224.hmac = createHmacMethod(true);
+var exports = createMethod();
+exports.sha256 = exports;
+exports.sha224 = createMethod(true);
+exports.sha256.hmac = createHmacMethod();
+exports.sha224.hmac = createHmacMethod(true);
- if (COMMON_JS) {
+if (COMMON_JS) {
module.exports = exports;
- } else {
+} else {
root.sha256 = exports.sha256;
root.sha224 = exports.sha224;
if (AMD) {
- define(function () {
- return exports;
- });
+ define(function () {
+ return exports;
+ });
}
- }
+}
+
+const sha256 = fake_window.sha256;
- window.sha256 = fake_window.sha256;
-})();
+/*
+ * EXPORTS_START
+ * EXPORT sha256
+ * EXPORTS_END
+ */
diff --git a/common/storage_client.js b/common/storage_client.js
index 1bc9a88..2bbddb6 100644
--- a/common/storage_client.js
+++ b/common/storage_client.js
@@ -5,182 +5,188 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"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 bags = list("bags", TYPE_PREFIX.BAG);
- var pages = list("pages", TYPE_PREFIX.PAGE);
-
- const list_by_prefix = {
- [TYPE_PREFIX.SCRIPT] : scripts,
- [TYPE_PREFIX.BAG] : bags,
- [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]);
- }
+/*
+ * IMPORTS_START
+ * IMPORT CONNECTION_TYPE
+ * IMPORT TYPE_PREFIX
+ * IMPORT list_prefixes
+ * IMPORT make_once
+ * IMPORT browser
+ * IMPORTS_END
+ */
- exports.get_all_it = function (prefix)
- {
- return list_entries_it(list_by_prefix[prefix]);
- }
+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 bags = list("bags", TYPE_PREFIX.BAG);
+var pages = list("pages", TYPE_PREFIX.PAGE);
+
+const list_by_prefix = {
+ [TYPE_PREFIX.SCRIPT] : scripts,
+ [TYPE_PREFIX.BAG] : bags,
+ [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
+ */
- window.get_storage = make_once(init);
-})();
+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]);
+}
+
+const get_remote_storage = make_once(init);
+
+/*
+ * EXPORTS_START
+ * EXPORT get_remote_storage
+ * EXPORTS_END
+ */
diff --git a/common/stored_types.js b/common/stored_types.js
index e043777..ef1339f 100644
--- a/common/stored_types.js
+++ b/common/stored_types.js
@@ -13,29 +13,29 @@
* an underscore.
*/
-"use strict";
+const TYPE_PREFIX = {
+ PAGE : "p",
+ BAG : "b",
+ SCRIPT : "s",
+ VAR : "_"
+};
-(() => {
- const TYPE_PREFIX = {
- PAGE : "p",
- BAG : "b",
- SCRIPT : "s",
- VAR : "_"
- };
+const TYPE_NAME = {
+ [TYPE_PREFIX.PAGE] : "page",
+ [TYPE_PREFIX.BAG] : "bag",
+ [TYPE_PREFIX.SCRIPT] : "script"
+}
- const TYPE_NAME = {
- [TYPE_PREFIX.PAGE] : "page",
- [TYPE_PREFIX.BAG] : "bag",
- [TYPE_PREFIX.SCRIPT] : "script"
- }
+const list_prefixes = [
+ TYPE_PREFIX.PAGE,
+ TYPE_PREFIX.BAG,
+ TYPE_PREFIX.SCRIPT
+];
- const list_prefixes = [
- TYPE_PREFIX.PAGE,
- TYPE_PREFIX.BAG,
- TYPE_PREFIX.SCRIPT
- ];
-
- window.TYPE_PREFIX = TYPE_PREFIX;
- window.TYPE_NAME = TYPE_NAME;
- window.list_prefixes = list_prefixes;
-})();
+/*
+ * EXPORTS_START
+ * EXPORT TYPE_PREFIX
+ * EXPORT TYPE_NAME
+ * EXPORT list_prefixes
+ * EXPORTS_END
+ */
diff --git a/common/url_item.js b/common/url_item.js
index 9f4b118..102f117 100644
--- a/common/url_item.js
+++ b/common/url_item.js
@@ -5,15 +5,15 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"use strict";
+function url_item(url)
+{
+ let url_re = /^([^?#]*).*$/;
+ let match = url_re.exec(url);
+ return match[1];
+}
-(() => {
- function url_item(url)
- {
- let url_re = /^([^?#]*).*$/;
- let match = url_re.exec(url);
- return match[1];
- }
-
- window.url_item = url_item;
-})();
+/*
+ * EXPORTS_START
+ * EXPORT url_item
+ * EXPORTS_END
+ */
diff --git a/content/freezer.js b/content/freezer.js
index cdd0709..1696f53 100644
--- a/content/freezer.js
+++ b/content/freezer.js
@@ -6,58 +6,60 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"use strict";
+const loaderAttributes = ["href", "src", "data"];
+const jsOrDataUrlRx = /^(?:data:(?:[^,;]*ml|unknown-content-type)|javascript:)/i;
-(() => {
- const loaderAttributes = ["href", "src", "data"];
- const jsOrDataUrlRx = /^(?:data:(?:[^,;]*ml|unknown-content-type)|javascript:)/i;
+function sanitize_attributes(element) {
+ if (element._frozen)
+ return;
+ let fa = [];
+ let loaders = [];
+ let attributes = element.attributes || [];
- function sanitizeAttributes(element) {
- if (element._frozen)
- return;
- let fa = [];
- let loaders = [];
- for (let a of element.attributes) {
- let name = a.localName.toLowerCase();
- if (loaderAttributes.includes(name))
- if (jsOrDataUrlRx.test(a.value))
- loaders.push(a);
+ for (let a of attributes) {
+ let name = a.localName.toLowerCase();
+ if (loaderAttributes.includes(name))
+ if (jsOrDataUrlRx.test(a.value))
+ loaders.push(a);
- else if (name.startsWith("on")) {
- console.debug("Removing", a, element.outerHTML);
- fa.push(a.cloneNode());
- a.value = "";
- element[name] = null;
- }
+ else if (name.startsWith("on")) {
+ console.debug("Removing", a, element.outerHTML);
+ fa.push(a.cloneNode());
+ a.value = "";
+ element[name] = null;
}
- if (loaders.length) {
- for (let a of loaders) {
- fa.push(a.cloneNode());
- a.value = "javascript://frozen";
- }
- if ("contentWindow" in element)
- element.replaceWith(element = element.cloneNode(true));
-
+ }
+ if (loaders.length) {
+ for (let a of loaders) {
+ fa.push(a.cloneNode());
+ a.value = "javascript://frozen";
}
- if (fa.length)
- element._frozenAttributes = fa;
- element._frozen = true;
+ if ("contentWindow" in element)
+ element.replaceWith(element = element.cloneNode(true));
+
}
-
- function scriptSuppressor(nonce) {
- const blockExecute = e => {
- if (document.readyState === 'complete') {
- removeEventListener('beforescriptexecute', blockExecute, true);
- return;
- }
- else if (e.isTrusted && e.target.getAttribute('nonce') !== nonce) { // Prevent blocking of injected scripts
- e.preventDefault();
- console.log('Suppressed script', e.target);
- }
- };
- return blockExecute;
+ if (fa.length)
+ element._frozenAttributes = fa;
+ element._frozen = true;
+}
+
+function script_suppressor(nonce) {
+ const blockExecute = e => {
+ if (document.readyState === 'complete') {
+ removeEventListener('beforescriptexecute', blockExecute, true);
+ return;
+ }
+ else if (e.isTrusted && e.target.getAttribute('nonce') !== nonce) { // Prevent blocking of injected scripts
+ e.preventDefault();
+ console.log('Suppressed script', e.target);
+ }
};
-
- window.scriptSuppressor = scriptSuppressor;
- window.sanitize_attributes = sanitizeAttributes;
-})();
+ return blockExecute;
+};
+
+/*
+ * EXPORTS_START
+ * EXPORT script_suppressor
+ * EXPORT sanitize_attributes
+ * EXPORTS_END
+ */
diff --git a/content/main.js b/content/main.js
index 2a46c7e..d55ee2e 100644
--- a/content/main.js
+++ b/content/main.js
@@ -5,113 +5,133 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"use strict";
+/*
+ * IMPORTS_START
+ * IMPORT handle_page_actions
+ * IMPORT url_item
+ * IMPORT gen_unique
+ * IMPORT sanitize_attributes
+ * IMPORT script_suppressor
+ * IMPORT is_chrome
+ * IMPORT is_mozilla
+ * IMPORTS_END
+ */
-(() => {
- const handle_page_actions = window.handle_page_actions;
- const url_item = window.url_item;
- const gen_unique = window.gen_unique;
- const sanitize_attributes = window.sanitize_attributes;
+/*
+ * Due to some technical limitations the chosen method of whitelisting sites
+ * is to smuggle whitelist indicator in page's url as a "magical" string
+ * after '#'. Right now this is not needed in HTTP(s) pages where native
+ * script blocking happens through CSP header injection but is needed for
+ * protocols like ftp:// and file://.
+ *
+ * The code that actually injects the magical string into ftp:// and file://
+ * urls has not yet been added to the extension.
+ */
- /*
- * Due to some technical limitations the chosen method of whitelisting sites
- * is to smuggle whitelist indicator in page's url as a "magical" string
- * after '#'. Right now this is not needed in HTTP(s) pages where native
- * script blocking happens through CSP header injection but is needed for
- * protocols like ftp:// and file://.
- *
- * The code that actually injects the magical string into ftp:// and file://
- * urls has not yet been added to the extension.
- */
+let url = url_item(document.URL);
+let unique = gen_unique(url);
+let nonce = unique.substring(1);
- let url = url_item(document.URL);
- let unique = gen_unique(url);
- let nonce = unique.substring(1);
-
- const scriptSuppressor = window.scriptSuppressor(nonce);
-
- function needs_blocking()
- {
- if (url.startsWith("https://") || url.startsWith("http://"))
- return false;
-
- let url_re = /^([^#]*)((#[^#]*)(#.*)?)?$/;
- let match = url_re.exec(document.URL);
- let base_url = match[1];
- let first_target = match[3];
- let second_target = match[4];
-
- if (first_target !== undefined &&
- first_target === unique) {
- if (second_target !== undefined)
- window.location.href = base_url + second_target;
- else
- history.replaceState(null, "", base_url);
-
- console.log(["allowing whitelisted", document.URL]);
- return false;
- }
-
- console.log(["disallowing", document.URL]);
- return true;
- }
+const suppressor = script_suppressor(nonce);
+
+function needs_blocking()
+{
+ if (url.startsWith("https://") || url.startsWith("http://"))
+ return false;
- function handle_mutation(mutations, observer)
- {
- if (document.readyState === 'complete') {
- console.log("complete");
- observer.disconnect();
- return;
- }
- for (let mutation of mutations) {
- for (let node of mutation.addedNodes) {
- /*
- * Modifying <script> element doesn't always prevent its
- * execution in some Mozilla browsers. Additional blocking
- * through CSP meta tag injection is required.
- */
- if (node.tagName === "SCRIPT") {
- block_script(node);
- continue;
- }
-
- sanitize_attributes(node);
-
- if (node.tagName === "HEAD")
- inject_csp(node);
- }
- }
+ let url_re = /^([^#]*)((#[^#]*)(#.*)?)?$/;
+ let match = url_re.exec(document.URL);
+ let base_url = match[1];
+ let first_target = match[3];
+ let second_target = match[4];
+
+ if (first_target !== undefined &&
+ first_target === unique) {
+ if (second_target !== undefined)
+ window.location.href = base_url + second_target;
+ else
+ history.replaceState(null, "", base_url);
+
+ console.log(["allowing whitelisted", document.URL]);
+ return false;
}
- function block_script(node)
- {
- console.log(node);
-
- /*
- * Disabling scripts this way allows them to still be relatively
- * easily accessed in case they contain some useful data.
- */
- if (node.hasAttribute("type"))
- node.setAttribute("blocked-type", node.getAttribute("type"));
- node.setAttribute("type", "application/json");
+ console.log(["disallowing", document.URL]);
+ return true;
+}
+
+function handle_mutation(mutations, observer)
+{
+ if (document.readyState === 'complete') {
+ console.log("mutation handling complete");
+ observer.disconnect();
+ return;
}
+ for (const mutation of mutations) {
+ for (const node of mutation.addedNodes)
+ block_node(node);
+ }
+}
+
+function block_nodes_recursively(node)
+{
+ block_node(node);
+ for (const child of node.children)
+ block_nodes_recursively(child);
+}
- function inject_csp(node)
- {
- console.log('injecting CSP');
- let meta = document.createElement("meta");
- meta.setAttribute("http-equiv", "Content-Security-Policy");
- meta.setAttribute("content", `\
-script-src 'nonce-${nonce}'; \
-script-src-elem 'nonce-${nonce}';\
-`);
- node.appendChild(meta);
+function block_node(node)
+{
+ /*
+ * Modifying <script> element doesn't always prevent its
+ * execution in some Mozilla browsers. Additional blocking
+ * through CSP meta tag injection is required.
+ */
+ if (node.tagName === "SCRIPT") {
+ block_script(node);
+ return;
}
- if (needs_blocking()) {
- // Script blocking for Gecko
- addEventListener('beforescriptexecute', scriptSuppressor, true);
-
+ sanitize_attributes(node);
+
+ if (node.tagName === "HEAD")
+ inject_csp(node);
+}
+
+function block_script(node)
+{
+ /*
+ * Disabling scripts this way allows them to still be relatively
+ * easily accessed in case they contain some useful data.
+ */
+ if (node.hasAttribute("type"))
+ node.setAttribute("blocked-type", node.getAttribute("type"));
+ node.setAttribute("type", "application/json");
+}
+
+function inject_csp(head)
+{
+ console.log('injecting CSP');
+
+ let meta = document.createElement("meta");
+ meta.setAttribute("http-equiv", "Content-Security-Policy");
+
+ let rule = `script-src 'nonce-${nonce}'; `;
+ if (is_chrome)
+ rule += `script-src-elem 'nonce-${nonce}';`;
+
+ meta.setAttribute("content", rule);
+
+ if (head.firstElementChild === null)
+ head.appendChild(meta);
+ else
+ head.insertBefore(meta, head.firstElementChild);
+}
+
+if (needs_blocking()) {
+ block_nodes_recursively(document.documentElement);
+
+ if (is_chrome) {
var observer = new MutationObserver(handle_mutation);
observer.observe(document.documentElement, {
attributes: true,
@@ -120,5 +140,8 @@ script-src-elem 'nonce-${nonce}';\
});
}
- handle_page_actions(nonce);
-})();
+ if (is_mozilla)
+ addEventListener('beforescriptexecute', suppressor, true);
+}
+
+handle_page_actions(nonce);
diff --git a/content/page_actions.js b/content/page_actions.js
index 88332a8..bc65449 100644
--- a/content/page_actions.js
+++ b/content/page_actions.js
@@ -5,60 +5,60 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"use strict";
-
-(() => {
- const CONNECTION_TYPE = window.CONNECTION_TYPE;
- const browser = window.browser;
-
- var port;
- var loaded = false;
- var scripts_awaiting = [];
- var nonce;
+/*
+ * IMPORTS_START
+ * IMPORT CONNECTION_TYPE
+ * IMPORT browser
+ * IMPORTS_END
+ */
- function handle_message(message)
- {
- console.log(["message", message]);
+var port;
+var loaded = false;
+var scripts_awaiting = [];
+var nonce;
- if (message.inject === undefined)
- return;
+function handle_message(message)
+{
+ if (message.inject === undefined)
+ return;
- for (let script_text of message.inject) {
- if (loaded)
- add_script(script_text);
- else
- scripts_awaiting.push(script_text);
- }
+ for (let script_text of message.inject) {
+ if (loaded)
+ add_script(script_text);
+ else
+ scripts_awaiting.push(script_text);
}
+}
- function document_loaded(event)
- {
- console.log("loaded");
-
- loaded = true;
+function document_loaded(event)
+{
+ loaded = true;
- for (let script_text of scripts_awaiting)
- add_script(script_text);
+ for (let script_text of scripts_awaiting)
+ add_script(script_text);
- scripts_awaiting = undefined;
- }
+ scripts_awaiting = undefined;
+}
- function add_script(script_text)
- {
- let script = document.createElement("script");
- script.textContent = script_text;
- script.setAttribute("nonce", nonce);
- document.body.appendChild(script);
- }
+function add_script(script_text)
+{
+ let script = document.createElement("script");
+ script.textContent = script_text;
+ script.setAttribute("nonce", nonce);
+ document.body.appendChild(script);
+}
- function handle_page_actions(script_nonce) {
- document.addEventListener("DOMContentLoaded", document_loaded);
- port = browser.runtime.connect({name : CONNECTION_TYPE.PAGE_ACTIONS});
- port.onMessage.addListener(handle_message);
- port.postMessage({url: document.URL});
+function handle_page_actions(script_nonce) {
+ document.addEventListener("DOMContentLoaded", document_loaded);
+ port = browser.runtime.connect({name : CONNECTION_TYPE.PAGE_ACTIONS});
+ port.onMessage.addListener(handle_message);
+ port.postMessage({url: document.URL});
- nonce = script_nonce;
- }
+ nonce = script_nonce;
+}
- window.handle_page_actions = handle_page_actions;
-})();
+/*
+ * EXPORTS_START
+ * EXPORT handle_page_actions
+ * EXPORTS_END
+ */
diff --git a/copyright b/copyright
index 5dce864..a01c1fe 100644
--- a/copyright
+++ b/copyright
@@ -6,6 +6,10 @@ Files: *
Copyright: 2021 Wojtek Kosior <koszko@koszko.org>
License: GPL-3+-javascript or Alicense-1.0
+Files: build.sh
+Copyright: 2021 Wojtek Kosior <koszko@koszko.org>
+License: CC0
+
Files: manifest.json
Copyright: 2021 Wojtek Kosior <koszko@koszko.org>
2021 jahoti <jahoti@tilde.team>
diff --git a/html/display-panel.html b/html/display-panel.html
index 40bb535..5e5580e 100644
--- a/html/display-panel.html
+++ b/html/display-panel.html
@@ -9,8 +9,6 @@
<title>Myext popup</title>
</head>
<body>
- <button id="settings_but" type="button">Settings</button>
- <script src="/common/browser.js"></script>
- <script src="./display-panel.js"></script>
+ <button id="settings_but" type="button">Settings</button>_POPUPSCRIPTS_
</body>
</html>
diff --git a/html/display-panel.js b/html/display-panel.js
index 9bd683c..4a4cdcd 100644
--- a/html/display-panel.js
+++ b/html/display-panel.js
@@ -5,11 +5,11 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"use strict";
-
-(() => {
- const browser = window.browser;
+/*
+ * IMPORTS_START
+ * IMPORT browser
+ * IMPORTS_END
+ */
- document.getElementById("settings_but")
- .addEventListener("click", (e) => browser.runtime.openOptionsPage());
-})();
+document.getElementById("settings_but")
+ .addEventListener("click", (e) => browser.runtime.openOptionsPage());
diff --git a/html/options.html b/html/options.html
index c380fc4..03978c7 100644
--- a/html/options.html
+++ b/html/options.html
@@ -249,13 +249,6 @@
<a id="file_downloader" class="hide"></a>
<form id="file_opener_form" style="visibility: hidden;">
<input type="file" id="file_opener"></input>
- </form>
-
- <script src="/common/connection_types.js"></script>
- <script src="/common/stored_types.js"></script>
- <script src="/common/once.js"></script>
- <script src="/common/browser.js"></script>
- <script src="/common/storage_client.js"></script>
- <script src="./options_main.js"></script>
+ </form>_OPTIONSSCRIPTS_
</body>
</html>
diff --git a/html/options_main.js b/html/options_main.js
index ef01e60..6f203fa 100644
--- a/html/options_main.js
+++ b/html/options_main.js
@@ -5,746 +5,746 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-"use strict";
-
-(() => {
- const get_storage = window.get_storage;
- const TYPE_PREFIX = window.TYPE_PREFIX;
- const TYPE_NAME = window.TYPE_NAME;
- const list_prefixes = window.list_prefixes;
-
- var storage;
- function by_id(id)
- {
- return document.getElementById(id);
- }
-
- function nice_name(prefix, name)
- {
- return `${name} (${TYPE_NAME[prefix]})`;
- }
-
- const item_li_template = by_id("item_li_template");
- const bag_component_li_template = by_id("bag_component_li_template");
- const chbx_component_li_template = by_id("chbx_component_li_template");
- const radio_component_li_template = by_id("radio_component_li_template");
- const import_li_template = by_id("import_li_template");
- /* Make sure they are later cloned without id. */
- item_li_template.removeAttribute("id");
- bag_component_li_template.removeAttribute("id");
- chbx_component_li_template.removeAttribute("id");
- radio_component_li_template.removeAttribute("id");
- import_li_template.removeAttribute("id");
-
- function item_li_id(prefix, item)
- {
- return `li_${prefix}_${item}`;
- }
-
- /* Insert into list of bags/pages/scripts */
- function add_li(prefix, item, at_the_end=false)
- {
- let ul = ul_by_prefix[prefix];
- let li = item_li_template.cloneNode(true);
- li.id = item_li_id(prefix, item);
-
- let span = li.firstElementChild;
- span.textContent = item;
-
- let edit_button = span.nextElementSibling;
- edit_button.addEventListener("click", () => edit_item(prefix, item));
-
- let remove_button = edit_button.nextElementSibling;
- remove_button.addEventListener("click",
- () => storage.remove(prefix, item));
-
- let export_button = remove_button.nextElementSibling;
- export_button.addEventListener("click",
- () => export_item(prefix, item));
+/*
+ * IMPORTS_START
+ * IMPORT get_remote_storage
+ * IMPORT TYPE_PREFIX
+ * IMPORT TYPE_NAME
+ * IMPORT list_prefixes
+ * IMPORTS_END
+ */
- if (!at_the_end) {
- for (let element of ul.ul.children) {
- if (element.id < li.id || element.id.startsWith("work_"))
- continue;
+var storage;
+function by_id(id)
+{
+ return document.getElementById(id);
+}
+
+function nice_name(prefix, name)
+{
+ return `${name} (${TYPE_NAME[prefix]})`;
+}
+
+const item_li_template = by_id("item_li_template");
+const bag_component_li_template = by_id("bag_component_li_template");
+const chbx_component_li_template = by_id("chbx_component_li_template");
+const radio_component_li_template = by_id("radio_component_li_template");
+const import_li_template = by_id("import_li_template");
+/* Make sure they are later cloned without id. */
+item_li_template.removeAttribute("id");
+bag_component_li_template.removeAttribute("id");
+chbx_component_li_template.removeAttribute("id");
+radio_component_li_template.removeAttribute("id");
+import_li_template.removeAttribute("id");
+
+function item_li_id(prefix, item)
+{
+ return `li_${prefix}_${item}`;
+}
+
+/* Insert into list of bags/pages/scripts */
+function add_li(prefix, item, at_the_end=false)
+{
+ let ul = ul_by_prefix[prefix];
+ let li = item_li_template.cloneNode(true);
+ li.id = item_li_id(prefix, item);
+
+ let span = li.firstElementChild;
+ span.textContent = item;
+
+ let edit_button = span.nextElementSibling;
+ edit_button.addEventListener("click", () => edit_item(prefix, item));
+
+ let remove_button = edit_button.nextElementSibling;
+ remove_button.addEventListener("click",
+ () => storage.remove(prefix, item));
+
+ let export_button = remove_button.nextElementSibling;
+ export_button.addEventListener("click",
+ () => export_item(prefix, item));
+
+ if (!at_the_end) {
+ for (let element of ul.ul.children) {
+ if (element.id < li.id || element.id.startsWith("work_"))
+ continue;
- ul.ul.insertBefore(li, element);
- return;
- }
+ ul.ul.insertBefore(li, element);
+ return;
}
-
- ul.ul.appendChild(li);
}
- const chbx_components_ul = by_id("chbx_components_ul");
- const radio_components_ul = by_id("radio_components_ul");
+ ul.ul.appendChild(li);
+}
- function chbx_li_id(prefix, item)
- {
- return `cli_${prefix}_${item}`;
- }
+const chbx_components_ul = by_id("chbx_components_ul");
+const radio_components_ul = by_id("radio_components_ul");
- function radio_li_id(prefix, item)
- {
- return `rli_${prefix}_${item}`;
- }
+function chbx_li_id(prefix, item)
+{
+ return `cli_${prefix}_${item}`;
+}
- //TODO: refactor the 2 functions below
+function radio_li_id(prefix, item)
+{
+ return `rli_${prefix}_${item}`;
+}
- function add_chbx_li(prefix, name)
- {
- if (prefix === TYPE_PREFIX.PAGE)
- return;
+//TODO: refactor the 2 functions below
- let li = chbx_component_li_template.cloneNode(true);
- li.id = chbx_li_id(prefix, name);
- li.setAttribute("data-prefix", prefix);
- li.setAttribute("data-name", name);
-
- let chbx = li.firstElementChild;
- let span = chbx.nextElementSibling;
-
- span.textContent = nice_name(prefix, name);
-
- chbx_components_ul.appendChild(li);
- }
-
- var radio_component_none_li = by_id("radio_component_none_li");
+function add_chbx_li(prefix, name)
+{
+ if (prefix === TYPE_PREFIX.PAGE)
+ return;
- function add_radio_li(prefix, name)
- {
- if (prefix === TYPE_PREFIX.PAGE)
- return;
+ let li = chbx_component_li_template.cloneNode(true);
+ li.id = chbx_li_id(prefix, name);
+ li.setAttribute("data-prefix", prefix);
+ li.setAttribute("data-name", name);
- let li = radio_component_li_template.cloneNode(true);
- li.id = radio_li_id(prefix, name);
- li.setAttribute("data-prefix", prefix);
- li.setAttribute("data-name", name);
+ let chbx = li.firstElementChild;
+ let span = chbx.nextElementSibling;
- let radio = li.firstElementChild;
- let span = radio.nextElementSibling;
+ span.textContent = nice_name(prefix, name);
- span.textContent = nice_name(prefix, name);
+ chbx_components_ul.appendChild(li);
+}
- radio_components_ul.insertBefore(li, radio_component_none_li);
- }
-
- const page_payload_span = by_id("page_payload");
-
- function set_page_components(components)
- {
- if (components === undefined) {
- page_payload_span.setAttribute("data-payload", "no");
- page_payload_span.textContent = "(None)";
- } else {
- page_payload_span.setAttribute("data-payload", "yes");
- let [prefix, name] = components;
- page_payload_span.setAttribute("data-prefix", prefix);
- page_payload_span.setAttribute("data-name", name);
- page_payload_span.textContent = nice_name(prefix, name);
- }
- }
+var radio_component_none_li = by_id("radio_component_none_li");
- const page_allow_chbx = by_id("page_allow_chbx");
+function add_radio_li(prefix, name)
+{
+ if (prefix === TYPE_PREFIX.PAGE)
+ return;
- /* Used to reset edited page. */
- function reset_work_page_li(ul, item, settings)
- {
- ul.work_name_input.value = maybe_string(item);
- settings = settings || {allow: false, components: undefined};
- page_allow_chbx.checked = !!settings.allow;
+ let li = radio_component_li_template.cloneNode(true);
+ li.id = radio_li_id(prefix, name);
+ li.setAttribute("data-prefix", prefix);
+ li.setAttribute("data-name", name);
- set_page_components(settings.components);
- }
+ let radio = li.firstElementChild;
+ let span = radio.nextElementSibling;
- function work_page_li_components()
- {
- if (page_payload_span.getAttribute("data-payload") === "no")
- return undefined;
+ span.textContent = nice_name(prefix, name);
- let prefix = page_payload_span.getAttribute("data-prefix");
- let name = page_payload_span.getAttribute("data-name");
- return [prefix, name];
- }
+ radio_components_ul.insertBefore(li, radio_component_none_li);
+}
- /* Used to get edited page data for saving. */
- function work_page_li_data(ul)
- {
- let url = ul.work_name_input.value;
- let settings = {
- components : work_page_li_components(),
- allow : !!page_allow_chbx.checked
- };
+const page_payload_span = by_id("page_payload");
- return [url, settings];
+function set_page_components(components)
+{
+ if (components === undefined) {
+ page_payload_span.setAttribute("data-payload", "no");
+ page_payload_span.textContent = "(None)";
+ } else {
+ page_payload_span.setAttribute("data-payload", "yes");
+ let [prefix, name] = components;
+ page_payload_span.setAttribute("data-prefix", prefix);
+ page_payload_span.setAttribute("data-name", name);
+ page_payload_span.textContent = nice_name(prefix, name);
}
+}
- const empty_bag_component_li = by_id("empty_bag_component_li");
- var bag_components_ul = by_id("bag_components_ul");
-
- /* Used to construct and update components list of edited bag. */
- function add_bag_components(components)
- {
- for (let component of components) {
- let [prefix, name] = component;
- let li = bag_component_li_template.cloneNode(true);
- li.setAttribute("data-prefix", prefix);
- li.setAttribute("data-name", name);
- let span = li.firstElementChild;
- span.textContent = nice_name(prefix, name);
- let remove_but = span.nextElementSibling;
- remove_but.addEventListener("click", () =>
- bag_components_ul.removeChild(li));
- bag_components_ul.appendChild(li);
- }
-
- bag_components_ul.appendChild(empty_bag_component_li);
- }
+const page_allow_chbx = by_id("page_allow_chbx");
- /* Used to reset edited bag. */
- function reset_work_bag_li(ul, item, components)
- {
- components = components || [];
+/* Used to reset edited page. */
+function reset_work_page_li(ul, item, settings)
+{
+ ul.work_name_input.value = maybe_string(item);
+ settings = settings || {allow: false, components: undefined};
+ page_allow_chbx.checked = !!settings.allow;
- ul.work_name_input.value = maybe_string(item);
- let old_components_ul = bag_components_ul;
- bag_components_ul = old_components_ul.cloneNode(false);
+ set_page_components(settings.components);
+}
- ul.work_li.insertBefore(bag_components_ul, old_components_ul);
- ul.work_li.removeChild(old_components_ul);
+function work_page_li_components()
+{
+ if (page_payload_span.getAttribute("data-payload") === "no")
+ return undefined;
- add_bag_components(components);
- }
+ let prefix = page_payload_span.getAttribute("data-prefix");
+ let name = page_payload_span.getAttribute("data-name");
+ return [prefix, name];
+}
- /* Used to get edited bag data for saving. */
- function work_bag_li_data(ul)
- {
- let components_ul = ul.work_name_input.nextElementSibling;
- let component_li = components_ul.firstElementChild;
+/* Used to get edited page data for saving. */
+function work_page_li_data(ul)
+{
+ let url = ul.work_name_input.value;
+ let settings = {
+ components : work_page_li_components(),
+ allow : !!page_allow_chbx.checked
+ };
- let components = [];
+ return [url, settings];
+}
- /* Last list element is empty li with id set. */
- while (component_li.id === '') {
- components.push([component_li.getAttribute("data-prefix"),
- component_li.getAttribute("data-name")]);
- component_li = component_li.nextElementSibling;
- }
+const empty_bag_component_li = by_id("empty_bag_component_li");
+var bag_components_ul = by_id("bag_components_ul");
- return [ul.work_name_input.value, components];
+/* Used to construct and update components list of edited bag. */
+function add_bag_components(components)
+{
+ for (let component of components) {
+ let [prefix, name] = component;
+ let li = bag_component_li_template.cloneNode(true);
+ li.setAttribute("data-prefix", prefix);
+ li.setAttribute("data-name", name);
+ let span = li.firstElementChild;
+ span.textContent = nice_name(prefix, name);
+ let remove_but = span.nextElementSibling;
+ remove_but.addEventListener("click", () =>
+ bag_components_ul.removeChild(li));
+ bag_components_ul.appendChild(li);
}
- const script_url_input = by_id("script_url_field");
- const script_sha256_input = by_id("script_sha256_field");
- const script_contents_field = by_id("script_contents_field");
+ bag_components_ul.appendChild(empty_bag_component_li);
+}
- function maybe_string(maybe_defined)
- {
- return maybe_defined === undefined ? "" : maybe_defined + "";
- }
+/* Used to reset edited bag. */
+function reset_work_bag_li(ul, item, components)
+{
+ components = components || [];
- /* Used to reset edited script. */
- function reset_work_script_li(ul, name, data)
- {
- ul.work_name_input.value = maybe_string(name);
- if (data === undefined)
- data = {};
- script_url_input.value = maybe_string(data.url);
- script_sha256_input.value = maybe_string(data.hash);
- script_contents_field.value = maybe_string(data.text);
- }
+ ul.work_name_input.value = maybe_string(item);
+ let old_components_ul = bag_components_ul;
+ bag_components_ul = old_components_ul.cloneNode(false);
- /* Used to get edited script data for saving. */
- function work_script_li_data(ul)
- {
- return [ul.work_name_input.value, {
- url : script_url_input.value,
- hash : script_sha256_input.value,
- text : script_contents_field.value
- }];
- }
+ ul.work_li.insertBefore(bag_components_ul, old_components_ul);
+ ul.work_li.removeChild(old_components_ul);
- function cancel_work(prefix)
- {
- let ul = ul_by_prefix[prefix];
+ add_bag_components(components);
+}
- if (ul.state === UL_STATE.IDLE)
- return;
+/* Used to get edited bag data for saving. */
+function work_bag_li_data(ul)
+{
+ let components_ul = ul.work_name_input.nextElementSibling;
+ let component_li = components_ul.firstElementChild;
- if (ul.state === UL_STATE.EDITING_ENTRY) {
- add_li(prefix, ul.edited_item);
- }
+ let components = [];
- ul.work_li.classList.add("hide");
- ul.state = UL_STATE.IDLE;
+ /* Last list element is empty li with id set. */
+ while (component_li.id === '') {
+ components.push([component_li.getAttribute("data-prefix"),
+ component_li.getAttribute("data-name")]);
+ component_li = component_li.nextElementSibling;
}
- function save_work(prefix)
- {
- let ul = ul_by_prefix[prefix];
+ return [ul.work_name_input.value, components];
+}
- if (ul.state === UL_STATE.IDLE)
- return;
+const script_url_input = by_id("script_url_field");
+const script_sha256_input = by_id("script_sha256_field");
+const script_contents_field = by_id("script_contents_field");
- let [item, data] = ul.get_work_li_data(ul);
+function maybe_string(maybe_defined)
+{
+ return maybe_defined === undefined ? "" : maybe_defined + "";
+}
- /* Here we fire promises and return without waiting. */
+/* Used to reset edited script. */
+function reset_work_script_li(ul, name, data)
+{
+ ul.work_name_input.value = maybe_string(name);
+ if (data === undefined)
+ data = {};
+ script_url_input.value = maybe_string(data.url);
+ script_sha256_input.value = maybe_string(data.hash);
+ script_contents_field.value = maybe_string(data.text);
+}
- if (ul.state === UL_STATE.EDITING_ENTRY)
- storage.replace(prefix, ul.edited_item, item, data);
- if (ul.state === UL_STATE.ADDING_ENTRY)
- storage.set(prefix, item, data);
+/* Used to get edited script data for saving. */
+function work_script_li_data(ul)
+{
+ return [ul.work_name_input.value, {
+ url : script_url_input.value,
+ hash : script_sha256_input.value,
+ text : script_contents_field.value
+ }];
+}
- cancel_work(prefix);
- }
+function cancel_work(prefix)
+{
+ let ul = ul_by_prefix[prefix];
- function edit_item(prefix, item)
- {
- cancel_work(prefix);
+ if (ul.state === UL_STATE.IDLE)
+ return;
- let ul = ul_by_prefix[prefix];
- let li = by_id(item_li_id(prefix, item));
- ul.reset_work_li(ul, item, storage.get(prefix, item));
- ul.ul.insertBefore(ul.work_li, li);
- ul.ul.removeChild(li);
- ul.work_li.classList.remove("hide");
-
- ul.state = UL_STATE.EDITING_ENTRY;
- ul.edited_item = item;
+ if (ul.state === UL_STATE.EDITING_ENTRY) {
+ add_li(prefix, ul.edited_item);
}
- const file_downloader = by_id("file_downloader");
+ ul.work_li.classList.add("hide");
+ ul.state = UL_STATE.IDLE;
+}
- function recursively_export_item(prefix, name, added_items, items_data)
- {
- let key = prefix + name;
+function save_work(prefix)
+{
+ let ul = ul_by_prefix[prefix];
- if (added_items.has(key))
- return;
+ if (ul.state === UL_STATE.IDLE)
+ return;
- let data = storage.get(prefix, name);
- if (data === undefined) {
- console.log(`${TYPE_NAME[prefix]} '${name}' for export not found`);
- return;
- }
+ let [item, data] = ul.get_work_li_data(ul);
- if (prefix !== TYPE_PREFIX.SCRIPT) {
- let components = prefix === TYPE_PREFIX.BAG ?
- data : [data.components];
+ /* Here we fire promises and return without waiting. */
- for (let [comp_prefix, comp_name] of components) {
- recursively_export_item(comp_prefix, comp_name,
- added_items, items_data);
- }
- }
+ if (ul.state === UL_STATE.EDITING_ENTRY)
+ storage.replace(prefix, ul.edited_item, item, data);
+ if (ul.state === UL_STATE.ADDING_ENTRY)
+ storage.set(prefix, item, data);
- items_data.push({[key]: data});
- added_items.add(key);
- }
+ cancel_work(prefix);
+}
- function export_item(prefix, name)
- {
- let added_items = new Set();
- let items_data = [];
- recursively_export_item(prefix, name, added_items, items_data);
- let file = new Blob([JSON.stringify(items_data)],
- {type: "application/json"});
- let url = URL.createObjectURL(file);
- file_downloader.setAttribute("href", url);
- file_downloader.setAttribute("download", prefix + name + ".json");
- file_downloader.click();
- file_downloader.removeAttribute("href");
- URL.revokeObjectURL(url);
- }
+function edit_item(prefix, item)
+{
+ cancel_work(prefix);
- function add_new_item(prefix)
- {
- cancel_work(prefix);
+ let ul = ul_by_prefix[prefix];
+ let li = by_id(item_li_id(prefix, item));
+ ul.reset_work_li(ul, item, storage.get(prefix, item));
+ ul.ul.insertBefore(ul.work_li, li);
+ ul.ul.removeChild(li);
+ ul.work_li.classList.remove("hide");
- let ul = ul_by_prefix[prefix];
- ul.reset_work_li(ul);
- ul.work_li.classList.remove("hide");
- ul.ul.appendChild(ul.work_li);
+ ul.state = UL_STATE.EDITING_ENTRY;
+ ul.edited_item = item;
+}
- ul.state = UL_STATE.ADDING_ENTRY;
- }
+const file_downloader = by_id("file_downloader");
- const chbx_components_window = by_id("chbx_components_window");
+function recursively_export_item(prefix, name, added_items, items_data)
+{
+ let key = prefix + name;
- function bag_components()
- {
- chbx_components_window.classList.remove("hide");
- radio_components_window.classList.add("hide");
+ if (added_items.has(key))
+ return;
- for (let li of chbx_components_ul.children) {
- let chbx = li.firstElementChild;
- chbx.checked = false;
- }
+ let data = storage.get(prefix, name);
+ if (data === undefined) {
+ console.log(`${TYPE_NAME[prefix]} '${name}' for export not found`);
+ return;
}
- function commit_bag_components()
- {
- let selected = [];
-
- for (let li of chbx_components_ul.children) {
- let chbx = li.firstElementChild;
- if (!chbx.checked)
- continue;
-
- selected.push([li.getAttribute("data-prefix"),
- li.getAttribute("data-name")]);
+ if (prefix !== TYPE_PREFIX.SCRIPT) {
+ let components = prefix === TYPE_PREFIX.BAG ?
+ data : [data.components];
+
+ for (let [comp_prefix, comp_name] of components) {
+ recursively_export_item(comp_prefix, comp_name,
+ added_items, items_data);
}
-
- add_bag_components(selected);
- cancel_components();
}
- const radio_components_window = by_id("radio_components_window");
- var radio_component_none_input = by_id("radio_component_none_input");
-
- function page_components()
- {
- radio_components_window.classList.remove("hide");
- chbx_components_window.classList.add("hide");
+ items_data.push({[key]: data});
+ added_items.add(key);
+}
+
+function export_item(prefix, name)
+{
+ let added_items = new Set();
+ let items_data = [];
+ recursively_export_item(prefix, name, added_items, items_data);
+ let file = new Blob([JSON.stringify(items_data)],
+ {type: "application/json"});
+ let url = URL.createObjectURL(file);
+ file_downloader.setAttribute("href", url);
+ file_downloader.setAttribute("download", prefix + name + ".json");
+ file_downloader.click();
+ file_downloader.removeAttribute("href");
+ URL.revokeObjectURL(url);
+}
+
+function add_new_item(prefix)
+{
+ cancel_work(prefix);
+
+ let ul = ul_by_prefix[prefix];
+ ul.reset_work_li(ul);
+ ul.work_li.classList.remove("hide");
+ ul.ul.appendChild(ul.work_li);
+
+ ul.state = UL_STATE.ADDING_ENTRY;
+}
+
+const chbx_components_window = by_id("chbx_components_window");
+
+function bag_components()
+{
+ chbx_components_window.classList.remove("hide");
+ radio_components_window.classList.add("hide");
+
+ for (let li of chbx_components_ul.children) {
+ let chbx = li.firstElementChild;
+ chbx.checked = false;
+ }
+}
- radio_component_none_input.checked = true;
+function commit_bag_components()
+{
+ let selected = [];
- let components = work_page_li_components();
- if (components === undefined)
- return;
+ for (let li of chbx_components_ul.children) {
+ let chbx = li.firstElementChild;
+ if (!chbx.checked)
+ continue;
- let [prefix, item] = components;
- let li = by_id(radio_li_id(prefix, item));
- if (li === null)
- radio_component_none_input.checked = false;
- else
- li.firstElementChild.checked = true;
+ selected.push([li.getAttribute("data-prefix"),
+ li.getAttribute("data-name")]);
}
- function commit_page_components()
- {
- let components = null;
+ add_bag_components(selected);
+ cancel_components();
+}
- for (let li of radio_components_ul.children) {
- let radio = li.firstElementChild;
- if (!radio.checked)
- continue;
+const radio_components_window = by_id("radio_components_window");
+var radio_component_none_input = by_id("radio_component_none_input");
- components = [li.getAttribute("data-prefix"),
- li.getAttribute("data-name")];
+function page_components()
+{
+ radio_components_window.classList.remove("hide");
+ chbx_components_window.classList.add("hide");
- if (radio.id === "radio_component_none_input")
- components = undefined;
+ radio_component_none_input.checked = true;
- break;
- }
+ let components = work_page_li_components();
+ if (components === undefined)
+ return;
- if (components !== null)
- set_page_components(components);
- cancel_components();
- }
+ let [prefix, item] = components;
+ let li = by_id(radio_li_id(prefix, item));
+ if (li === null)
+ radio_component_none_input.checked = false;
+ else
+ li.firstElementChild.checked = true;
+}
- function cancel_components()
- {
- chbx_components_window.classList.add("hide");
- radio_components_window.classList.add("hide");
- }
+function commit_page_components()
+{
+ let components = null;
- const UL_STATE = {
- EDITING_ENTRY : 0,
- ADDING_ENTRY : 1,
- IDLE : 2
- };
-
- const ul_by_prefix = {
- [TYPE_PREFIX.PAGE] : {
- ul : by_id("pages_ul"),
- work_li : by_id("work_page_li"),
- work_name_input : by_id("page_url_field"),
- reset_work_li : reset_work_page_li,
- get_work_li_data : work_page_li_data,
- select_components : page_components,
- commit_components : commit_page_components,
- state : UL_STATE.IDLE,
- edited_item : undefined,
- },
- [TYPE_PREFIX.BAG] : {
- ul : by_id("bags_ul"),
- work_li : by_id("work_bag_li"),
- work_name_input : by_id("bag_name_field"),
- reset_work_li : reset_work_bag_li,
- get_work_li_data : work_bag_li_data,
- select_components : bag_components,
- commit_components : commit_bag_components,
- state : UL_STATE.IDLE,
- edited_item : undefined,
- },
- [TYPE_PREFIX.SCRIPT] : {
- ul : by_id("scripts_ul"),
- work_li : by_id("work_script_li"),
- work_name_input : by_id("script_name_field"),
- reset_work_li : reset_work_script_li,
- get_work_li_data : work_script_li_data,
- state : UL_STATE.IDLE,
- edited_item : undefined,
- }
- }
+ for (let li of radio_components_ul.children) {
+ let radio = li.firstElementChild;
+ if (!radio.checked)
+ continue;
+
+ components = [li.getAttribute("data-prefix"),
+ li.getAttribute("data-name")];
+
+ if (radio.id === "radio_component_none_input")
+ components = undefined;
+
+ break;
+ }
+
+ if (components !== null)
+ set_page_components(components);
+ cancel_components();
+}
+
+function cancel_components()
+{
+ chbx_components_window.classList.add("hide");
+ radio_components_window.classList.add("hide");
+}
+
+const UL_STATE = {
+ EDITING_ENTRY : 0,
+ ADDING_ENTRY : 1,
+ IDLE : 2
+};
+
+const ul_by_prefix = {
+ [TYPE_PREFIX.PAGE] : {
+ ul : by_id("pages_ul"),
+ work_li : by_id("work_page_li"),
+ work_name_input : by_id("page_url_field"),
+ reset_work_li : reset_work_page_li,
+ get_work_li_data : work_page_li_data,
+ select_components : page_components,
+ commit_components : commit_page_components,
+ state : UL_STATE.IDLE,
+ edited_item : undefined,
+ },
+ [TYPE_PREFIX.BAG] : {
+ ul : by_id("bags_ul"),
+ work_li : by_id("work_bag_li"),
+ work_name_input : by_id("bag_name_field"),
+ reset_work_li : reset_work_bag_li,
+ get_work_li_data : work_bag_li_data,
+ select_components : bag_components,
+ commit_components : commit_bag_components,
+ state : UL_STATE.IDLE,
+ edited_item : undefined,
+ },
+ [TYPE_PREFIX.SCRIPT] : {
+ ul : by_id("scripts_ul"),
+ work_li : by_id("work_script_li"),
+ work_name_input : by_id("script_name_field"),
+ reset_work_li : reset_work_script_li,
+ get_work_li_data : work_script_li_data,
+ state : UL_STATE.IDLE,
+ edited_item : undefined,
+ }
+}
+
+const import_window = by_id("import_window");
+const import_loading_radio = by_id("import_loading_radio");
+const import_failed_radio = by_id("import_failed_radio");
+const import_selection_radio = by_id("import_selection_radio");
+const bad_file_errormsg = by_id("bad_file_errormsg");
+
+/*
+ * Newer browsers could utilise `text' method of File objects.
+ * Older ones require FileReader.
+ */
- const import_window = by_id("import_window");
- const import_loading_radio = by_id("import_loading_radio");
- const import_failed_radio = by_id("import_failed_radio");
- const import_selection_radio = by_id("import_selection_radio");
- const bad_file_errormsg = by_id("bad_file_errormsg");
+function _read_file(file, resolve, reject)
+{
+ let reader = new FileReader();
+
+ reader.onload = () => resolve(reader.result);
+ reader.onerror = () => reject(reader.error);
+ reader.readAsText(file);
+}
+
+function read_file(file)
+{
+ return new Promise((resolve, reject) =>
+ _read_file(file, resolve, reject));
+}
+
+async function import_from_file(event)
+{
+ let files = event.target.files;
+ if (files.length < 1)
+ return;
+
+ import_window.classList.remove("hide");
+ import_loading_radio.checked = true;
+
+ let result = undefined;
+
+ try {
+ result = JSON.parse(await read_file(files[0]));
+ } catch(e) {
+ bad_file_errormsg.textContent = "" + e;
+ import_failed_radio.checked = true;
+ return;
+ }
+
+ let errormsg = validate_settings(result);
+ if (errormsg !== false) {
+ bad_file_errormsg.textContent = errormsg;
+ import_failed_radio.checked = true;
+ return;
+ }
+
+ populate_import_list(result);
+ import_selection_radio.checked = true;
+}
+
+function validate_settings(settings)
+{
+ // TODO
+ return false;
+}
+
+function import_li_id(prefix, item)
+{
+ return `ili_${prefix}_${item}`;
+}
+
+let import_ul = by_id("import_ul");
+let import_chbxs_colliding = undefined;
+let settings_import_map = undefined;
+
+function populate_import_list(settings)
+{
+ let old_children = import_ul.children;
+ while (old_children[0] !== undefined)
+ import_ul.removeChild(old_children[0]);
+
+ import_chbxs_colliding = [];
+ settings_import_map = new Map();
+
+ for (let setting of settings) {
+ let [key, value] = Object.entries(setting)[0];
+ let prefix = key[0];
+ let name = key.substring(1);
+ add_import_li(prefix, name);
+ settings_import_map.set(key, value);
+ }
+}
+
+function add_import_li(prefix, name)
+{
+ let li = import_li_template.cloneNode(true);
+ let name_span = li.firstElementChild;
+ let chbx = name_span.nextElementSibling;
+ let warning_span = chbx.nextElementSibling;
+
+ li.setAttribute("data-prefix", prefix);
+ li.setAttribute("data-name", name);
+ li.id = import_li_id(prefix, name);
+ name_span.textContent = nice_name(prefix, name);
+
+ if (storage.get(prefix, name) !== undefined) {
+ import_chbxs_colliding.push(chbx);
+ warning_span.textContent = "(will overwrite existing setting!)";
+ }
+
+ import_ul.appendChild(li);
+}
+
+function check_all_imports()
+{
+ for (let li of import_ul.children)
+ li.firstElementChild.nextElementSibling.checked = true;
+}
+
+function uncheck_all_imports()
+{
+ for (let li of import_ul.children)
+ li.firstElementChild.nextElementSibling.checked = false;
+}
+
+function uncheck_colliding_imports()
+{
+ for (let chbx of import_chbxs_colliding)
+ chbx.checked = false;
+}
+
+const file_opener_form = by_id("file_opener_form");
+
+function hide_import_window()
+{
+ import_window.classList.add("hide");
+ /* Let GC free some memory */
+ import_chbxs_colliding = undefined;
+ settings_import_map = undefined;
/*
- * Newer browsers could utilise `text' method of File objects.
- * Older ones require FileReader.
+ * Reset file <input>. Without this, a second attempt to import the same
+ * file would result in "change" event on happening on <input> element.
*/
+ file_opener_form.reset();
+}
- function _read_file(file, resolve, reject)
- {
- let reader = new FileReader();
+function commit_import()
+{
+ for (let li of import_ul.children) {
+ let chbx = li.firstElementChild.nextElementSibling;
- reader.onload = () => resolve(reader.result);
- reader.onerror = () => reject(reader.error);
- reader.readAsText(file);
- }
-
- function read_file(file)
- {
- return new Promise((resolve, reject) =>
- _read_file(file, resolve, reject));
- }
+ if (!chbx.checked)
+ continue;
- async function import_from_file(event)
- {
- let files = event.target.files;
- if (files.length < 1)
- return;
-
- import_window.classList.remove("hide");
- import_loading_radio.checked = true;
-
- let result = undefined;
-
- try {
- result = JSON.parse(await read_file(files[0]));
- } catch(e) {
- bad_file_errormsg.textContent = "" + e;
- import_failed_radio.checked = true;
- return;
- }
-
- let errormsg = validate_settings(result);
- if (errormsg !== false) {
- bad_file_errormsg.textContent = errormsg;
- import_failed_radio.checked = true;
- return;
+ let prefix = li.getAttribute("data-prefix");
+ let name = li.getAttribute("data-name");
+ let key = prefix + name;
+ let value = settings_import_map.get(key);
+ storage.set(prefix, name, value);
+ }
+
+ hide_import_window();
+}
+
+function initialize_import_facility()
+{
+ let import_but = by_id("import_but");
+ let file_opener = by_id("file_opener");
+ let import_failok_but = by_id("import_failok_but");
+ let check_all_import_but = by_id("check_all_import_but");
+ let uncheck_all_import_but = by_id("uncheck_all_import_but");
+ let uncheck_existing_import_but = by_id("uncheck_existing_import_but");
+ let commit_import_but = by_id("commit_import_but");
+ let cancel_import_but = by_id("cancel_import_but");
+ import_but.addEventListener("click", () => file_opener.click());
+ file_opener.addEventListener("change", import_from_file);
+ import_failok_but.addEventListener("click", hide_import_window);
+ check_all_import_but.addEventListener("click", check_all_imports);
+ uncheck_all_import_but.addEventListener("click", uncheck_all_imports);
+ uncheck_colliding_import_but
+ .addEventListener("click", uncheck_colliding_imports);
+ commit_import_but.addEventListener("click", commit_import);
+ cancel_import_but.addEventListener("click", hide_import_window);
+}
+
+async function main()
+{
+ storage = await get_remote_storage();
+
+ for (let prefix of list_prefixes) {
+ for (let item of storage.get_all_names(prefix).sort()) {
+ add_li(prefix, item, true);
+ add_chbx_li(prefix, item);
+ add_radio_li(prefix, item);
}
- populate_import_list(result);
- import_selection_radio.checked = true;
- }
-
- function validate_settings(settings)
- {
- // TODO
- return false;
- }
+ let name = TYPE_NAME[prefix];
- function import_li_id(prefix, item)
- {
- return `ili_${prefix}_${item}`;
- }
+ let add_but = by_id(`add_${name}_but`);
+ let discard_but = by_id(`discard_${name}_but`);
+ let save_but = by_id(`save_${name}_but`);
- let import_ul = by_id("import_ul");
- let import_chbxs_colliding = undefined;
- let settings_import_map = undefined;
-
- function populate_import_list(settings)
- {
- let old_children = import_ul.children;
- while (old_children[0] !== undefined)
- import_ul.removeChild(old_children[0]);
-
- import_chbxs_colliding = [];
- settings_import_map = new Map();
-
- for (let setting of settings) {
- let [key, value] = Object.entries(setting)[0];
- let prefix = key[0];
- let name = key.substring(1);
- add_import_li(prefix, name);
- settings_import_map.set(key, value);
- }
- }
+ add_but.addEventListener("click", () => add_new_item(prefix));
+ discard_but.addEventListener("click", () => cancel_work(prefix));
+ save_but.addEventListener("click", () => save_work(prefix));
- function add_import_li(prefix, name)
- {
- let li = import_li_template.cloneNode(true);
- let name_span = li.firstElementChild;
- let chbx = name_span.nextElementSibling;
- let warning_span = chbx.nextElementSibling;
+ if (prefix === TYPE_PREFIX.SCRIPT)
+ continue;
- li.setAttribute("data-prefix", prefix);
- li.setAttribute("data-name", name);
- li.id = import_li_id(prefix, name);
- name_span.textContent = nice_name(prefix, name);
-
- if (storage.get(prefix, name) !== undefined) {
- import_chbxs_colliding.push(chbx);
- warning_span.textContent = "(will overwrite existing setting!)";
- }
+ let ul = ul_by_prefix[prefix];
- import_ul.appendChild(li);
- }
+ let commit_components_but = by_id(`commit_${name}_components_but`);
+ let cancel_components_but = by_id(`cancel_${name}_components_but`);
+ let select_components_but = by_id(`select_${name}_components_but`);
- function check_all_imports()
- {
- for (let li of import_ul.children)
- li.firstElementChild.nextElementSibling.checked = true;
+ commit_components_but
+ .addEventListener("click", ul.commit_components);
+ select_components_but
+ .addEventListener("click", ul.select_components);
+ cancel_components_but.addEventListener("click", cancel_components);
}
- function uncheck_all_imports()
- {
- for (let li of import_ul.children)
- li.firstElementChild.nextElementSibling.checked = false;
- }
-
- function uncheck_colliding_imports()
- {
- for (let chbx of import_chbxs_colliding)
- chbx.checked = false;
- }
+ initialize_import_facility();
- const file_opener_form = by_id("file_opener_form");
+ storage.add_change_listener(handle_change);
+}
- function hide_import_window()
- {
- import_window.classList.add("hide");
- /* Let GC free some memory */
- import_chbxs_colliding = undefined;
- settings_import_map = undefined;
+function handle_change(change)
+{
+ if (change.old_val === undefined) {
+ add_li(change.prefix, change.item);
+ add_chbx_li(change.prefix, change.item);
+ add_radio_li(change.prefix, change.item);
- /*
- * Reset file <input>. Without this, a second attempt to import the same
- * file would result in "change" event on happening on <input> element.
- */
- file_opener_form.reset();
+ return;
}
- function commit_import()
- {
- for (let li of import_ul.children) {
- let chbx = li.firstElementChild.nextElementSibling;
-
- if (!chbx.checked)
- continue;
-
- let prefix = li.getAttribute("data-prefix");
- let name = li.getAttribute("data-name");
- let key = prefix + name;
- let value = settings_import_map.get(key);
- storage.set(prefix, name, value);
- }
-
- hide_import_window();
- }
+ if (change.new_val !== undefined)
+ return;
- function initialize_import_facility()
- {
- let import_but = by_id("import_but");
- let file_opener = by_id("file_opener");
- let import_failok_but = by_id("import_failok_but");
- let check_all_import_but = by_id("check_all_import_but");
- let uncheck_all_import_but = by_id("uncheck_all_import_but");
- let uncheck_existing_import_but = by_id("uncheck_existing_import_but");
- let commit_import_but = by_id("commit_import_but");
- let cancel_import_but = by_id("cancel_import_but");
- import_but.addEventListener("click", () => file_opener.click());
- file_opener.addEventListener("change", import_from_file);
- import_failok_but.addEventListener("click", hide_import_window);
- check_all_import_but.addEventListener("click", check_all_imports);
- uncheck_all_import_but.addEventListener("click", uncheck_all_imports);
- uncheck_colliding_import_but
- .addEventListener("click", uncheck_colliding_imports);
- commit_import_but.addEventListener("click", commit_import);
- cancel_import_but.addEventListener("click", hide_import_window);
+ let ul = ul_by_prefix[change.prefix];
+ if (ul.state === UL_STATE.EDITING_ENTRY &&
+ ul.edited_item === change.item) {
+ ul.state = UL_STATE.ADDING_ENTRY;
+ return;
}
- async function main()
- {
- storage = await get_storage();
-
- for (let prefix of list_prefixes) {
- for (let item of storage.get_all_names(prefix).sort()) {
- add_li(prefix, item, true);
- add_chbx_li(prefix, item);
- add_radio_li(prefix, item);
- }
-
- let name = TYPE_NAME[prefix];
-
- let add_but = by_id(`add_${name}_but`);
- let discard_but = by_id(`discard_${name}_but`);
- let save_but = by_id(`save_${name}_but`);
-
- add_but.addEventListener("click", () => add_new_item(prefix));
- discard_but.addEventListener("click", () => cancel_work(prefix));
- save_but.addEventListener("click", () => save_work(prefix));
-
- if (prefix === TYPE_PREFIX.SCRIPT)
- continue;
-
- let ul = ul_by_prefix[prefix];
-
- let commit_components_but = by_id(`commit_${name}_components_but`);
- let cancel_components_but = by_id(`cancel_${name}_components_but`);
- let select_components_but = by_id(`select_${name}_components_but`);
-
- commit_components_but
- .addEventListener("click", ul.commit_components);
- select_components_but
- .addEventListener("click", ul.select_components);
- cancel_components_but.addEventListener("click", cancel_components);
- }
-
- initialize_import_facility();
+ let uls_creators = [[ul.ul, item_li_id]];
- storage.add_change_listener(handle_change);
+ if (change.prefix !== TYPE_PREFIX.PAGE) {
+ uls_creators.push([chbx_components_ul, chbx_li_id]);
+ uls_creators.push([radio_components_ul, radio_li_id]);
}
- function handle_change(change)
- {
- if (change.old_val === undefined) {
- add_li(change.prefix, change.item);
- add_chbx_li(change.prefix, change.item);
- add_radio_li(change.prefix, change.item);
-
- return;
- }
-
- if (change.new_val !== undefined)
- return;
-
- let ul = ul_by_prefix[change.prefix];
- if (ul.state === UL_STATE.EDITING_ENTRY &&
- ul.edited_item === change.item) {
- ul.state = UL_STATE.ADDING_ENTRY;
- return;
- }
-
- let uls_creators = [[ul.ul, item_li_id]];
-
- if (change.prefix !== TYPE_PREFIX.PAGE) {
- uls_creators.push([chbx_components_ul, chbx_li_id]);
- uls_creators.push([radio_components_ul, radio_li_id]);
- }
-
- for (let [components_ul, id_creator] of uls_creators) {
- let li = by_id(id_creator(change.prefix, change.item));
- components_ul.removeChild(li);
- }
+ for (let [components_ul, id_creator] of uls_creators) {
+ let li = by_id(id_creator(change.prefix, change.item));
+ components_ul.removeChild(li);
}
+}
- main();
-})();
+main();
diff --git a/manifest.json b/manifest.json
index 3984dc6..ab74523 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,31 +1,12 @@
// Copyright (C) 2021 Wojtek Kosior
-// Copyright (C) 2021 jahoti
// Redistribution terms are gathered in the `copyright' file.
{
"manifest_version": 2,
"name": "My extension",
"short_name": "Myext",
- "version": "0.0.0",
-
- // WARNING!!!
- // EACH USER SHOULD REPLACE "key" WITH UNIQUE VALUE!!!
- // OTHERWISE SECURITY CAN BE TRIVIALLY COMPROMISED!
- //
- // A unique key can be generated with:
- // $ ssh-keygen -f /path/to/new/key.pem -t rsa -b 1024
- //
- // Only relevant to users of chrome-based browsers.
- // Users of FireFox forks are safe.
-
- "key": "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAlwAAAAdzc2gtcnNhAAAAAwEAAQAAAIEA+0GT5WNmRRo8e5tL9+BmNtY6aBPwLIgbPnLShYBMSR40iYwLTsccrkwBXb3bs1o4p6q5WJugI8Lsia+GXZc/XHGFkq7D1aWiTxlJLs8z0JC2TQ2/yatYmBMchogYGeeUfP7aI7JJZwpATts+VhIvgga/4FYj+DijMIEpwdckqFEAAAII4Dh7HOA4exwAAAAHc3NoLXJzYQAAAIEA+0GT5WNmRRo8e5tL9+BmNtY6aBPwLIgbPnLShYBMSR40iYwLTsccrkwBXb3bs1o4p6q5WJugI8Lsia+GXZc/XHGFkq7D1aWiTxlJLs8z0JC2TQ2/yatYmBMchogYGeeUfP7aI7JJZwpATts+VhIvgga/4FYj+DijMIEpwdckqFEAAAADAQABAAAAgEHB5/MhEKMFOs8e1cMJ97ZiWubiUPlWpcqyQmauLUj1nspg3JTBh8AWJEVkaxuFgU5gYCHQmRjC6yUdywyziOEkFA4r/WpX4WmbIe+GQHRHhitLN0dgF8N6/fVNOoa5StTdfZqyl23pVXyepoDNjrJFKyupqPMmpwfH5lGr9RwBAAAAQG76HflB/5j8P2YgIYX6dQT4Ei0SqiIjNVy7jFJUQDKSJg/PYkedE02JZJBJPcMYxEJUxXtMgq+upamNILfkmY0AAABBAP4v0O5dqjy16xDDFzb4DPNAcw5Za9KJaXKVkUuKXMNZOKTR0RC/upjNTmttY980RKdIx5zA25dO8cx563bSDIsAAABBAP0MaOpBiai/eRmLqhlthHODa+Mur6W3uc9PyhWhgDBjLNMR/doaYeyfVKxtIiN3a+HkN++G+vbokRweQv++bhMAAAANdXJ6QGxvY2FsaG9zdAECAwQFBg==",
+ "version": "0.0.0",_CHROMIUM_KEY_
"author": "various",
- "description": "Kill the web&js",
- "applications": {
- "gecko": {
- "id": "{6fe13369-88e9-440f-b837-5012fb3bedec}",
- "strict_min_version": "60.0"
- }
- },
+ "description": "Kill the web&js",_GECKO_APPLICATIONS_
"icons":{
"64": "icons/myext.png"
},
@@ -56,23 +37,7 @@
],
"background": {
"persistent": true,
- "scripts": [
- "common/stored_types.js",
- "common/lock.js",
- "common/once.js",
- "common/browser.js",
- "background/storage.js",
- "background/message_server.js",
- "common/connection_types.js",
- "background/storage_server.js",
- "common/url_item.js",
- "common/sha256.js",
- "background/settings_query.js",
- "background/page_actions_server.js",
- "common/gen_unique.js",
- "background/policy_injector.js",
- "background/main.js"
- ]
+ "scripts": [_BGSCRIPTS_]
},
"content_scripts": [
{
@@ -80,16 +45,7 @@
"matches": ["<all_urls>"],
"match_about_blank": true,
"all_frames": true,
- "js": [
- "content/freezer.js",
- "common/browser.js",
- "common/connection_types.js",
- "content/page_actions.js",
- "common/url_item.js",
- "common/sha256.js",
- "common/gen_unique.js",
- "content/main.js"
- ]
+ "js": [_CONTENTSCRIPTS_]
}
]
}