Centralized settings management

This commit is contained in:
kkapsner 2017-11-07 00:36:44 +01:00
parent 18df3f97fe
commit 2193313980
24 changed files with 917 additions and 912 deletions

View File

@ -13,8 +13,7 @@
}, },
"extends": "eslint:recommended", "extends": "eslint:recommended",
"globals": { "globals": {
"exportFunction": false, "exportFunction": false
"settings": false
}, },
"rules": { "rules": {
"brace-style": ["error", "stroustrup", {"allowSingleLine": true}], "brace-style": ["error", "stroustrup", {"allowSingleLine": true}],

25
.vscode/tasks.json vendored
View File

@ -53,6 +53,31 @@
}, },
"problemMatcher": [] "problemMatcher": []
}, },
{
"taskName": "run current",
"type": "shell",
"windows": {
"command": "web-ext"
},
"linux": {
"command": "web-ext"
},
"osx": {
"command": "web-ext"
},
"args": [
"run",
"--url",
"http://canvasblocker.local/test/"
],
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": []
},
{ {
"taskName": "build", "taskName": "build",
"type": "shell", "type": "shell",

View File

@ -91,39 +91,39 @@
"message": "", "message": "",
"description": "" "description": ""
}, },
"blockMode_options.allow everything": { "blockMode_options.allowEverything": {
"message": "alles erlauben", "message": "alles erlauben",
"description": "" "description": ""
}, },
"blockMode_options.allow only white list": { "blockMode_options.block": {
"message": "nur Einträge der Whitelist erlauben", "message": "nur Einträge der Whitelist erlauben",
"description": "" "description": ""
}, },
"blockMode_options.ask for permission": { "blockMode_options.ask": {
"message": "um Erlaubnis fragen", "message": "um Erlaubnis fragen",
"description": "" "description": ""
}, },
"blockMode_options.ask for readout API permission": { "blockMode_options.askReadout": {
"message": "bei Auslese-API um Erlaubnis fragen", "message": "bei Auslese-API um Erlaubnis fragen",
"description": "" "description": ""
}, },
"blockMode_options.block everything": { "blockMode_options.blockEverything": {
"message": "alles blockieren", "message": "alles blockieren",
"description": "" "description": ""
}, },
"blockMode_options.block only black list": { "blockMode_options.allow": {
"message": "nur Einträge der Blacklist blockieren", "message": "nur Einträge der Blacklist blockieren",
"description": "" "description": ""
}, },
"blockMode_options.block readout API": { "blockMode_options.blockReadout": {
"message": "Auslese-API blockieren", "message": "Auslese-API blockieren",
"description": "" "description": ""
}, },
"blockMode_options.fake readout API": { "blockMode_options.fakeReadout": {
"message": "Auslese-API vortäuschen", "message": "Auslese-API vortäuschen",
"description": "" "description": ""
}, },
"blockMode_options.fake input API": { "blockMode_options.fakeInput": {
"message": "Bei Ausgabe vortäuschen", "message": "Bei Ausgabe vortäuschen",
"description": "" "description": ""
}, },
@ -162,7 +162,7 @@
"message": "konstant", "message": "konstant",
"description": "" "description": ""
}, },
"rng_options.non persistent": { "rng_options.nonPersistent": {
"message": "nicht persistent", "message": "nicht persistent",
"description": "" "description": ""
}, },
@ -185,7 +185,7 @@
"description": "" "description": ""
}, },
"storePersistentRnd_description": { "storePersistentRnd_description": {
"message": "Ob Daten für den persistenten Zufallszahlengenerator gespeichert werden sollen.", "message": "Ob Daten für den persistenten Zufallszahlengenerator gespeichert werden sollen. Ansonsten werden die Daten beim Beenden des Browsers verworfen.",
"description": "" "description": ""
}, },
@ -390,27 +390,27 @@
"message": "Für eine Fehlersuche ist eine detaillierte Aufzeichnung der Addon-Aktivitäten hilfreich. Mit diesem Parameter kann der Grad der Detailliertheit dieser Aufzeichnung eingestellt werden.", "message": "Für eine Fehlersuche ist eine detaillierte Aufzeichnung der Addon-Aktivitäten hilfreich. Mit diesem Parameter kann der Grad der Detailliertheit dieser Aufzeichnung eingestellt werden.",
"description": "" "description": ""
}, },
"logLevel_options.none": { "logLevel_options.0": {
"message": "nichts", "message": "nichts",
"description": "" "description": ""
}, },
"logLevel_options.error": { "logLevel_options.1": {
"message": "Fehler", "message": "Fehler",
"description": "" "description": ""
}, },
"logLevel_options.warning": { "logLevel_options.25": {
"message": "Warnungen", "message": "Warnungen",
"description": "" "description": ""
}, },
"logLevel_options.message": { "logLevel_options.50": {
"message": "Nachrichten", "message": "Nachrichten",
"description": "" "description": ""
}, },
"logLevel_options.notice": { "logLevel_options.75": {
"message": "Notizen", "message": "Notizen",
"description": "" "description": ""
}, },
"logLevel_options.verbose": { "logLevel_options.100": {
"message": "ausführlich", "message": "ausführlich",
"description": "" "description": ""
} }

View File

@ -91,39 +91,39 @@
"message": "", "message": "",
"description": "" "description": ""
}, },
"blockMode_options.allow everything": { "blockMode_options.allowEverything": {
"message": "allow everything", "message": "allow everything",
"description": "" "description": ""
}, },
"blockMode_options.allow only white list": { "blockMode_options.block": {
"message": "allow only white list", "message": "allow only white list",
"description": "" "description": ""
}, },
"blockMode_options.ask for permission": { "blockMode_options.ask": {
"message": "ask for permission", "message": "ask for permission",
"description": "" "description": ""
}, },
"blockMode_options.ask for readout API permission": { "blockMode_options.askReadout": {
"message": "ask for readout API permission", "message": "ask for readout API permission",
"description": "" "description": ""
}, },
"blockMode_options.block everything": { "blockMode_options.blockEverything": {
"message": "block everything", "message": "block everything",
"description": "" "description": ""
}, },
"blockMode_options.block only black list": { "blockMode_options.allow": {
"message": "block only black list", "message": "block only black list",
"description": "" "description": ""
}, },
"blockMode_options.block readout API": { "blockMode_options.blockReadout": {
"message": "block readout API", "message": "block readout API",
"description": "" "description": ""
}, },
"blockMode_options.fake readout API": { "blockMode_options.fakeReadout": {
"message": "fake readout API", "message": "fake readout API",
"description": "" "description": ""
}, },
"blockMode_options.fake input API": { "blockMode_options.fakeInput": {
"message": "fake at input", "message": "fake at input",
"description": "" "description": ""
}, },
@ -162,7 +162,7 @@
"message": "constant", "message": "constant",
"description": "" "description": ""
}, },
"rng_options.non persistent": { "rng_options.nonPersistent": {
"message": "non persistent", "message": "non persistent",
"description": "" "description": ""
}, },
@ -185,7 +185,7 @@
"description": "" "description": ""
}, },
"storePersistentRnd_description": { "storePersistentRnd_description": {
"message": "If data for the persistent random number generator should be stored.", "message": "If data for the persistent random number generator should be stored. Otherwise it is discarded on browser shutdown.",
"description": "" "description": ""
}, },
@ -394,27 +394,27 @@
"message": "To find the cause for an error a detailed logging of the addon activities is helpful. This parameter controls the level of detail of the logging.", "message": "To find the cause for an error a detailed logging of the addon activities is helpful. This parameter controls the level of detail of the logging.",
"description": "" "description": ""
}, },
"logLevel_options.none": { "logLevel_options.0": {
"message": "none", "message": "none",
"description": "" "description": ""
}, },
"logLevel_options.error": { "logLevel_options.1": {
"message": "error", "message": "error",
"description": "" "description": ""
}, },
"logLevel_options.warning": { "logLevel_options.25": {
"message": "warning", "message": "warning",
"description": "" "description": ""
}, },
"logLevel_options.message": { "logLevel_options.50": {
"message": "message", "message": "message",
"description": "" "description": ""
}, },
"logLevel_options.notice": { "logLevel_options.75": {
"message": "notice", "message": "notice",
"description": "" "description": ""
}, },
"logLevel_options.verbose": { "logLevel_options.100": {
"message": "verbose", "message": "verbose",
"description": "" "description": ""
} }

View File

@ -12,6 +12,8 @@
window.scope.callingStack = {}; window.scope.callingStack = {};
scope = window.scope.callingStack; scope = window.scope.callingStack;
} }
const settings = require("./settings");
// Translation // Translation
var _ = function(name, replace, translateAPI){ var _ = function(name, replace, translateAPI){

View File

@ -13,6 +13,7 @@
scope = window.scope.check; scope = window.scope.check;
} }
const settings = require("./settings");
const lists = require("./lists"); const lists = require("./lists");
const {parseErrorStack} = require("./callingStack"); const {parseErrorStack} = require("./callingStack");
const logging = require("./logging"); const logging = require("./logging");

View File

@ -1,26 +0,0 @@
const settings = {
logLevel: 1,
whiteList: "",
blackList: "",
blockMode: "fakeReadout",
minFakeSize: 1,
maxFakeSize: 0,
rng: "nonPersistent",
useCanvasCache: true,
ignoreFrequentColors: 0,
fakeAlphaChannel: false,
persistentRndStorage: "",
storePersistentRnd: false,
askOnlyOnce: true,
showNotifications: true,
storeImageForInspection: false,
ignoreList: "",
showCallingFile: false,
showCompleteCallingStack: false,
enableStackList: false,
stackList: "",
displayAdvancedSettings: false,
// indicator if the real settings are loaded already
isStillDefault: true
};

View File

@ -4,6 +4,7 @@
(function(){ (function(){
"use strict"; "use strict";
const settings = require("./settings");
const {intercept} = require("./intercept.js"); const {intercept} = require("./intercept.js");
const {ask} = require("./askForPermission.js"); const {ask} = require("./askForPermission.js");
const lists = require("./lists.js"); const lists = require("./lists.js");
@ -46,6 +47,7 @@
var port = browser.runtime.connect(); var port = browser.runtime.connect();
var tabId; var tabId;
port.onMessage.addListener(function(data){ port.onMessage.addListener(function(data){
message("Got data from port", data);
if (data.hasOwnProperty("tabId")){ if (data.hasOwnProperty("tabId")){
notice("my tab id is", data.tabId); notice("my tab id is", data.tabId);
tabId = data.tabId; tabId = data.tabId;
@ -64,8 +66,6 @@
settings[key] = data.settings[key]; settings[key] = data.settings[key];
}); });
settings.isStillDefault = false; settings.isStillDefault = false;
logging.clearQueue();
lists.updateAll();
} }
}); });
var notifications = []; var notifications = [];
@ -141,22 +141,9 @@
return true; return true;
} }
if (settings.isStillDefault){ settings.onloaded(function(){
message("load settings");
browser.storage.local.get().then(function(data){
Object.keys(data).forEach(function(key){
notice("loaded setting:", key, ":", data[key]);
settings[key] = data[key];
});
settings.isStillDefault = false;
logging.clearQueue();
lists.updateAll();
interceptWindow(window);
});
}
else {
interceptWindow(window); interceptWindow(window);
} });
message("register listener for messages from background script"); message("register listener for messages from background script");
browser.runtime.onMessage.addListener(function(data){ browser.runtime.onMessage.addListener(function(data){
@ -175,15 +162,4 @@
notice("notifications sent"); notice("notifications sent");
} }
}); });
message("register listener for settings changes");
browser.storage.onChanged.addListener(function(change, area){
if (area === "local"){
Object.keys(change).forEach(function(key){
notice("setting changed:", key, ":", change[key].newValue);
settings[key] = change[key].newValue;
});
}
});
}()); }());

View File

@ -16,6 +16,7 @@
const {changedFunctions, setRandomSupply} = require("./modifiedAPI"); const {changedFunctions, setRandomSupply} = require("./modifiedAPI");
const randomSupplies = require("./randomSupplies"); const randomSupplies = require("./randomSupplies");
const getWrapped = require("sdk/getWrapped"); const getWrapped = require("sdk/getWrapped");
const logging = require("./logging");
setRandomSupply(randomSupplies.nonPersistent); setRandomSupply(randomSupplies.nonPersistent);
var apiNames = Object.keys(changedFunctions); var apiNames = Object.keys(changedFunctions);
@ -57,6 +58,7 @@
scope.intercept = function intercept({subject: window}, {check, checkStack, ask, notify, prefs}){ scope.intercept = function intercept({subject: window}, {check, checkStack, ask, notify, prefs}){
var siteStatus = check({url: getURL(window)}); var siteStatus = check({url: getURL(window)});
logging.verbose("status for page", window, siteStatus);
if (siteStatus.mode !== "allow"){ if (siteStatus.mode !== "allow"){
apiNames.forEach(function(name){ apiNames.forEach(function(name){
var changedFunction = changedFunctions[name]; var changedFunction = changedFunctions[name];

View File

@ -15,8 +15,7 @@
scope = window.scope.lists; scope = window.scope.lists;
} }
var preferences = require("sdk/simple-prefs"); var settings = require("./settings");
var prefs = preferences.prefs;
function getDomainRegExpList(domainList){ function getDomainRegExpList(domainList){
@ -66,15 +65,15 @@
function updateList(type, value){ function updateList(type, value){
if (typeof value === "undefined"){ if (typeof value === "undefined"){
value = prefs[type + "List"]; value = settings[type + "List"];
} }
lists[type] = getDomainRegExpList(value); lists[type] = getDomainRegExpList(value);
} }
Object.keys(lists).forEach(function(type){ Object.keys(lists).forEach(function(type){
preferences.on(type + "List", function(value){ settings.on(type + "List", function({newValue}){
updateList(type, value); updateList(type, newValue);
}); });
updateList(type, prefs[type + "List"]); updateList(type, settings[type + "List"]);
}); });
function updateStackList(value){ function updateStackList(value){
@ -99,19 +98,16 @@
lists.stack = list; lists.stack = list;
} }
lists.stack = []; lists.stack = [];
preferences.on("stackList", function(value){ settings.on("stackList", function({newValue}){
updateStackList(value); updateStackList(newValue);
}); });
updateStackList(prefs.stackList); updateStackList(settings.stackList);
scope.get = function getList(type){ scope.get = function getList(type){
return lists[type]; return lists[type];
}; };
scope.appendTo = function appendToList(type, entry){ scope.appendTo = function appendToList(type, entry){
prefs[type + "List"] += (prefs[type + "List"]? ",": "") + entry; settings[type + "List"] += (settings[type + "List"]? ",": "") + entry;
var obj = {};
obj[type + "List"] = prefs[type + "List"];
browser.storage.local.set(obj);
updateList(type); updateList(type);
}; };
scope.update = updateList; scope.update = updateList;
@ -119,6 +115,7 @@
updateList("white"); updateList("white");
updateList("ignore"); updateList("ignore");
updateList("black"); updateList("black");
updateStackList(prefs.stackList); updateStackList(settings.stackList);
}; };
settings.onloaded(scope.updateAll);
}()); }());

View File

@ -9,14 +9,14 @@
if ((typeof exports) !== "undefined"){ if ((typeof exports) !== "undefined"){
scope = exports; scope = exports;
} }
else if (window.scope){ else {
window.scope.logging = {}; if (!window.scope.logging){
window.scope.logging = {};
}
scope = window.scope.logging; scope = window.scope.logging;
} }
else {
window.logging = {}; const settings = require("./settings");
scope = window.logging;
}
var prefix = ""; var prefix = "";
@ -85,9 +85,14 @@
metaLog("logging queue cleared"); metaLog("logging queue cleared");
} }
}; };
settings.on("isStillDefault", scope.clearQueue);
scope.error = error; scope.error = error;
scope.warning = warning; scope.warning = warning;
scope.message = message; scope.message = message;
scope.notice = notice; scope.notice = notice;
scope.verbose = verbose; scope.verbose = verbose;
require.emit("./logging");
metaLog("logging available");
}()); }());

View File

@ -4,23 +4,16 @@
(function(){ (function(){
"use strict"; "use strict";
const settings = require("./settings");
const logging = require("./logging"); const logging = require("./logging");
const {error, warning, message, notice, verbose, } = logging; const {error, warning, message, notice, verbose, } = logging;
const lists = require("./lists");
logging.setPrefix("main script"); logging.setPrefix("main script");
message("start"); message("start of background script");
message("loading storage"); message("waiting for settings to be loaded");
browser.storage.local.get().then(function(data){ settings.onloaded(function(){
Object.keys(data).forEach(function(key){
settings[key] = data[key];
});
settings.isStillDefault = false;
logging.clearQueue();
return settings;
}).then(function(settings){
notice("everything loaded"); notice("everything loaded");
const lists = require("./lists");
lists.updateAll();
notice("build persistent storage"); notice("build persistent storage");
var persistentRnd = Object.create(null); var persistentRnd = Object.create(null);
@ -66,11 +59,17 @@
verbose("got new domain rnd", data["canvasBlocker-new-domain-rnd"]); verbose("got new domain rnd", data["canvasBlocker-new-domain-rnd"]);
data["canvasBlocker-set-domain-rnd"] = data["canvasBlocker-new-domain-rnd"]; data["canvasBlocker-set-domain-rnd"] = data["canvasBlocker-new-domain-rnd"];
persistentRnd[data["canvasBlocker-new-domain-rnd"].domain] = data["canvasBlocker-new-domain-rnd"].rnd; persistentRnd[data["canvasBlocker-new-domain-rnd"].domain] = data["canvasBlocker-new-domain-rnd"].rnd;
browser.storage.local.get("storePersistentRnd").then(function(prefs){ if (settings.storePersistentRnd){
if (prefs.storePersistentRnd){ settings.persistentRndStorage = JSON.stringify(persistentRnd);
browser.storage.local.set({persistentRndStorage: JSON.stringify(persistentRnd)}); }
} updateContentScripts();
}); }
if (data["canvasBlocker-clear-domain-rnd"]){
verbose("domain rnd cleared");
persistentRnd = Object.create(null);
if (settings.storePersistentRnd){
settings.persistentRndStorage = JSON.stringify(persistentRnd);
}
updateContentScripts(); updateContentScripts();
} }
notice("pass the message to the tabs"); notice("pass the message to the tabs");
@ -86,54 +85,40 @@
notice("got port", port); notice("got port", port);
verbose("send back the tab id", port.sender.tab.id); verbose("send back the tab id", port.sender.tab.id);
verbose("send back the persistent random seeds", persistentRnd); verbose("send back the persistent random seeds", persistentRnd);
verbose("send back the settings", settings);
port.postMessage({ port.postMessage({
tabId: port.sender.tab.id, tabId: port.sender.tab.id,
persistentRnd: persistentRnd, persistentRnd: persistentRnd
settings: settings
}); });
var url = new URL(port.sender.url); var url = new URL(port.sender.url);
port.onMessage.addListener(function(data){ port.onMessage.addListener(function(data){
browser.storage.local.get("showNotifications").then(function(data){ if (data.hasOwnProperty("canvasBlocker-notify")){
if ( if (
( settings.showNotifications &&
!data.hasOwnProperty("showNotifications") ||
data.showNotifications
) &&
!lists.get("ignore").match(url) !lists.get("ignore").match(url)
){ ){
browser.pageAction.show(port.sender.tab.id); browser.pageAction.show(port.sender.tab.id);
} }
}); }
verbose("got data", data, "from port", port); verbose("got data", data, "from port", port);
}); });
}); });
message("register storage change event listener"); message("register storage change event listener");
browser.storage.onChanged.addListener(function(change, area){
if (area === "local"){ settings.on("any", updateContentScripts);
notice("settings changed", change); settings.on("showNotifications", function({newValue}){
notice("update settings object"); if (!newValue){
Object.keys(change).forEach(function(key){ message("notifications were disabled -> hide all page actions");
settings[key] = change[key].newValue; browser.tabs.query({}).then(function(tabs){
tabs.forEach(function(tab){
browser.pageAction.hide(tab.id);
});
}); });
updateContentScripts();
if (change.hasOwnProperty("showNotifications") && !change.showNotifications.newValue){
message("notifications were disabled -> hide all page actions");
browser.tabs.query({}).then(function(tabs){
tabs.forEach(function(tab){
browser.pageAction.hide(tab.id);
});
});
}
if (change.hasOwnProperty("storePersistentRnd")){
browser.storage.local.set({
persistentRndStorage: change.storePersistentRnd.newValue? JSON.stringify(persistentRnd): ""
});
}
} }
}); });
settings.on("storePersistentRnd", function({newValue}){
settings.persistentRndStorage = newValue? JSON.stringify(persistentRnd): "";
});
// hide page action when a tab is refreshed // hide page action when a tab is refreshed
browser.tabs.onUpdated.addListener(function(tabId, data){ browser.tabs.onUpdated.addListener(function(tabId, data){

View File

@ -6,9 +6,15 @@ const require = function(){
"use strict"; "use strict";
window.scope = {}; window.scope = {};
const scope = window.scope; const scope = window.scope;
function getScopeName(module){
var scopeName = module.substr(2).replace(/\..+/, "");
return scopeName;
}
function require(module){ function require(module){
if (module.startsWith("./")){ if (module.startsWith("./")){
var scopeName = module.substr(2).replace(/\..+/, ""); var scopeName = getScopeName(module);
return scope[scopeName]; return scope[scopeName];
} }
else if (module === "sdk/getWrapped"){ else if (module === "sdk/getWrapped"){
@ -27,22 +33,31 @@ const require = function(){
return wrapped; return wrapped;
}; };
} }
else if (module === "sdk/simple-prefs"){
return {
prefs: settings,
on: function(key, callback){
browser.storage.onChanged.addListener(function(changes, area){
if (area === "local"){
if (changes.hasOwnProperty(key)){
callback(changes[key].newValue);
}
}
});
}
};
}
throw new ReferenceError("Unable to get non relative module " + module + "!"); throw new ReferenceError("Unable to get non relative module " + module + "!");
} }
var events = {};
require.on = function(module, callback){
var scopeName = getScopeName(module);
if (scope.hasOwnProperty(scopeName)){
callback(scope[scopeName]);
}
else {
if (!events.hasOwnProperty(scopeName)){
events[scopeName] = [];
}
events[scopeName].push(callback);
}
};
require.emit = function(module){
var scopeName = getScopeName(module);
if (events[scopeName]){
events[scopeName].forEach(function(callback){
callback(scope[scopeName]);
});
events[scopeName] = [];
}
};
return require; return require;
}(); }();

118
lib/settingDefinitions.js Normal file
View File

@ -0,0 +1,118 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
(function(){
"use strict";
var settingDefinitions = [
{
name: "logLevel",
defaultValue: 1,
options: [0, 1, 25, 50, 75, 100]
},
{
name: "whiteList",
defaultValue: ""
},
{
name: "blackList",
defaultValue: ""
},
{
name: "blockMode",
defaultValue: "fakeReadout",
options: [
"blockReadout", "fakeReadout", "fakeInput", "askReadout", null,
"blockEverything", "block", "ask", "allow", "allowEverything"
]
},
{
name: "minFakeSize",
defaultValue: 1
},
{
name: "maxFakeSize",
defaultValue: 0
},
{
name: "rng",
defaultValue: "nonPersistent",
options: ["nonPersistent", "constant", "persistent"]
},
{
name: "useCanvasCache",
defaultValue: true
},
{
name: "ignoreFrequentColors",
defaultValue: 0
},
{
name: "fakeAlphaChannel",
defaultValue: false
},
{
name: "persistentRndStorage",
defaultValue: ""
},
{
name: "storePersistentRnd",
defaultValue: false
},
{
name: "askOnlyOnce",
defaultValue: true
},
{
name: "showNotifications",
defaultValue: true
},
{
name: "storeImageForInspection",
defaultValue: false
},
{
name: "notificationDisplayTime",
defaultValue: 30
},
{
name: "ignoreList",
defaultValue: ""
},
{
name: "showCallingFile",
defaultValue: false
},
{
name: "showCompleteCallingStack",
defaultValue: false
},
{
name: "enableStackList",
defaultValue: false
},
{
name: "stackList",
defaultValue: ""
},
{
name: "displayAdvancedSettings",
defaultValue: false
},
{
name: "isStillDefault",
defaultValue: true
},
{
name: "storageVersion",
defaultValue: 0.1
}
];
if ((typeof module) !== "undefined"){
module.exports = settingDefinitions;
}
else {
window.scope.settingDefinitions = settingDefinitions;
}
}());

View File

@ -1,7 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
(function(){ (function(){
"use strict"; "use strict";
var scope; var scope;
@ -9,138 +9,144 @@
scope = exports; scope = exports;
} }
else { else {
window.scope.settings = {}; scope = {};
scope = window.scope.settings; window.scope.settings = scope;
} }
var settingDefinitions = [ var logging = {};
{ (function(){
name: "logLevel", var loggingQueue = [];
defaultValue: 1 require.on("./logging", function(realLogging){
}, logging = realLogging;
{
name: "whiteList", loggingQueue.forEach(function(logEntry){
defaultValue: "" logging[logEntry.name](...logEntry.args, logEntry.date);
}, });
{ loggingQueue = [];
name: "blackList", });
defaultValue: "" ["error", "warning", "message", "notice", "verbose"].forEach(function(name){
}, logging[name] = function(...args){
{ loggingQueue.push({name, args, date: new Date()});
name: "blockMode", };
defaultValue: "fakeReadout", });
options: ["blockReadout", "fakeReadout", "fakeInput", "askReadout", "blockEverything", "block", "ask", "allow", "allowEverything"] }());
}, const settingDefinitions = require("./settingDefinitions.js");
{
name: "minFakeSize", const eventHandler = {any: []};
defaultValue: 1 eventHandler.all = eventHandler.any;
}, const settings = {};
{
name: "maxFakeSize",
defaultValue: 0
},
{
name: "rng",
defaultValue: "nonPersistent",
options: ["nonPersistent", "constant", "persistent"]
},
{
name: "useCanvasCache",
defaultValue: true
},
{
name: "ignoreFrequentColors",
defaultValue: 0
},
{
name: "fakeAlphaChannel",
defaultValue: false
},
{
name: "persistentRndStorage",
defaultValue: ""
},
{
name: "storePersistentRnd",
defaultValue: false
},
{
name: "askOnlyOnce",
defaultValue: true
},
{
name: "showNotifications",
defaultValue: true
},
{
name: "storeImageForInspection",
defaultValue: false
},
{
name: "notificationDisplayTime",
defaultValue: 30
},
{
name: "ignoreList",
defaultValue: ""
},
{
name: "showCallingFile",
defaultValue: false
},
{
name: "showCompleteCallingStack",
defaultValue: false
},
{
name: "enableStackList",
defaultValue: false
},
{
name: "stackList",
defaultValue: ""
},
{
name: "displayAdvancedSettings",
defaultValue: false
},
{
name: "isStillDefault",
defaultValue: true
}
];
var settings = {};
window.settings = {};
settingDefinitions.forEach(function(settingDefinition){ settingDefinitions.forEach(function(settingDefinition){
var name = settingDefinition.name; var name = settingDefinition.name;
settings[name] = settingDefinition.defaultValue; settings[name] = settingDefinition.defaultValue;
Object.defineProperty( eventHandler[name] = [];
window.settings,
{ settingDefinition.on = function on(callback){
name: name, scope.on(name, callback);
get: function(){ };
return settings[name] settingDefinition.get = function getValue(){
}, return settings[name];
set: function(newValue){ };
if ((typeof newValue) === (typeof settingDefinition.defaultValue)){ settingDefinition.set = function setValue(newValue){
if ( if ((typeof newValue) === (typeof settingDefinition.defaultValue)){
!settingDefinition.options || if (
settingDefinition.options.includes(newValue) !settingDefinition.options ||
){ settingDefinition.options.includes(newValue)
settings[name] = newValue; ){
settings[name] = newValue;
} if (!settingDefinition.transient){
var storeObject = {};
storeObject[name] = newValue;
browser.storage.local.set(storeObject);
} }
} }
else {
logging.warning("Provided value outside specified options for ", name, ":", newValue);
}
}
else {
logging.warning("Wrong type provided for setting", name, ":", newValue);
}
};
Object.defineProperty(
scope,
name,
{
get: settingDefinition.get,
set: settingDefinition.set
} }
); );
}); });
scope.getDefinition = function(name){
var foundDefinitions = settingDefinitions.filter(function(settingDefinition){
return name === settingDefinition.name;
});
if (foundDefinitions.length){
return Object.create(foundDefinitions[0]);
}
else {
return undefined;
}
};
scope.forEach = function forEachSetting(...args){ scope.forEach = function forEachSetting(...args){
settingDefinitions.map(function(settingDefinition){ settingDefinitions.map(function(settingDefinition){
return Object.create(settingDefinition); return Object.create(settingDefinition);
}).forEach(...args); }).forEach(...args);
};
scope.on = function onSettingsChange(name, callback){
if (eventHandler.hasOwnProperty(name)){
eventHandler[name].push(callback);
}
else {
logging.warning("Unable to register event handler for unknown setting", name);
}
};
function changeValue(name, newValue){
var oldValue = settings[name];
settings[name] = newValue;
(eventHandler[name] || []).forEach(function(callback){
callback({name, newValue, oldValue});
});
} }
logging.verbose("registering storage onchange listener");
browser.storage.onChanged.addListener(function(changes, area){
if (area === "local"){
logging.notice("settings changed", changes);
Object.entries(changes).forEach(function(entry){
const [name, change] = entry;
changeValue(name, change.newValue);
});
eventHandler.any.forEach(function(callback){
callback();
});
}
});
logging.verbose("loading settings");
scope.loaded = browser.storage.local.get().then(function(storage){
logging.message("settings loaded");
Object.entries(storage).forEach(function(entry){
const [name, value] = entry;
changeValue(name, value);
});
changeValue("isStillDefault", false);
eventHandler.any.forEach(function(callback){
callback();
});
});
scope.onloaded = function(callback){
if (scope.isStillDefault){
scope.loaded.then(function(){callback();});
}
else {
callback();
}
};
Object.seal(scope);
}()); }());

View File

@ -8,8 +8,9 @@
}, },
"background": { "background": {
"scripts": [ "scripts": [
"lib/defaultSettings.js",
"lib/require.js", "lib/require.js",
"lib/settingDefinitions.js",
"lib/settings.js",
"lib/logging.js", "lib/logging.js",
"lib/lists.js", "lib/lists.js",
"lib/main.js" "lib/main.js"
@ -20,8 +21,9 @@
"all_frames": true, "all_frames": true,
"run_at": "document_start", "run_at": "document_start",
"js": [ "js": [
"lib/defaultSettings.js",
"lib/require.js", "lib/require.js",
"lib/settingDefinitions.js",
"lib/settings.js",
"lib/logging.js", "lib/logging.js",

View File

@ -1,362 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
(function(){
"use strict";
const logging = require("./logging");
var table = document.createElement("table");
table.className = "settings";
document.body.appendChild(table);
[
{
"name": "displayAdvancedSettings",
"title": "Display advanced settings",
"type": "bool",
"value": false
},
{
"name": "blockMode",
"title": "block mode",
"type": "menulist",
"value": "fakeReadout",
"options": [
{
"value": "blockReadout",
"label": "block readout API"
},
{
"value": "fakeReadout",
"label": "fake readout API"
},
{
"value": "fakeInput",
"label": "fake input API"
},
{
"value": "askReadout",
"label": "ask for readout API permission"
},
{
"value": "",
"label": ""
},
{
"value": "blockEverything",
"label": "block everything"
},
{
"value": "block",
"label": "allow only white list"
},
{
"value": "ask",
"label": "ask for permission"
},
{
"value": "allow",
"label": "block only black list"
},
{
"value": "allowEverything",
"label": "allow everything"
}
]
},
{
"name": "whiteList",
"title": "White list",
"type": "string",
"value": "",
"displayDependencies": {
"blockMode": ["blockReadout", "fakeReadout", "fakeInput", "askReadout", "block", "ask"]
}
},
{
"name": "blackList",
"title": "Black list",
"type": "string",
"value": "",
"displayDependencies": {
"blockMode": ["blockReadout", "fakeReadout", "fakeInput", "askReadout", "ask", "allow"]
}
},
{
"name": "minFakeSize",
"title": "Minimal fake size",
"type": "integer",
"value": 1,
"displayDependencies": {
"blockMode": ["fakeReadout", "fakeInput"],
"displayAdvancedSettings": [true]
}
},
{
"name": "maxFakeSize",
"title": "Maximal fake size",
"type": "integer",
"value": 0,
"displayDependencies": {
"blockMode": ["fakeReadout", "fakeInput"],
"displayAdvancedSettings": [true]
}
},
{
"name": "rng",
"title": "Random number generator",
"type": "menulist",
"value": "nonPersistent",
"options": [
{
"value": "nonPersistent",
"label": "non persistent"
},
{
"value": "constant",
"label": "constant"
},
{
"value": "persistent",
"label": "persistent"
}
],
"displayDependencies": {
"blockMode": ["fakeReadout", "fakeInput"],
"displayAdvancedSettings": [true]
}
},
{
"name": "storePersistentRnd",
"title": "Store persistent data",
"type": "bool",
"value": false,
"displayDependencies": {
"blockMode": ["fakeReadout", "fakeInput"],
"rng": ["persistent"],
"displayAdvancedSettings": [true]
}
},
{
"name": "clearPersistentRnd",
"title": "Clear persistent random storage",
"type": "control",
"label": "Clear",
"displayDependencies": {
"blockMode": ["fakeReadout", "fakeInput"],
"rng": ["persistent"],
"displayAdvancedSettings": [true]
}
},
{
"name": "ignoreFrequentColors",
"title": "Ignore most frequent colors",
"type": "integer",
"value": 0,
"displayDependencies": {
"blockMode": ["fakeReadout"],
"displayAdvancedSettings": [true]
}
},
{
"name": "fakeAlphaChannel",
"title": "Fake the alpha channel",
"type": "bool",
"value": false,
"displayDependencies": {
"blockMode": ["fakeReadout"],
"displayAdvancedSettings": [true]
}
},
{
"name": "useCanvasCache",
"title": "Use canvas cache",
"type": "bool",
"value": true,
"displayDependencies": {
"blockMode": ["fakeReadout"],
"displayAdvancedSettings": [true]
}
},
{
"name": "askOnlyOnce",
"title": "Ask only once",
"type": "bool",
"value": true,
"displayDependencies": {
"blockMode": ["askReadout", "ask"]
}
},
{
"name": "showNotifications",
"title": "Show notifications",
"type": "bool",
"value": true,
"displayDependencies": {
"blockMode": ["fakeReadout", "fakeInput"]
}
},
{
"name": "storeImageForInspection",
"title": "Store image for inspection",
"type": "bool",
"value": false,
"displayDependencies": {
"blockMode": ["fakeReadout", "fakeInput"],
"showNotifications": [true],
"displayAdvancedSettings": [true]
}
},
{
"name": "ignoreList",
"title": "Ignore list",
"type": "string",
"value": "",
"displayDependencies": {
"blockMode": ["fakeReadout", "fakeInput"],
"showNotifications": [true]
}
},
{
"name": "showCallingFile",
"title": "Display calling file",
"type": "bool",
"value": false,
"displayDependencies": {
"blockMode": ["askReadout", "ask"],
"displayAdvancedSettings": [true]
}
},
{
"name": "showCompleteCallingStack",
"title": "Display complete calling stack",
"type": "bool",
"value": false,
"displayDependencies": [
{
"blockMode": ["fakeReadout", "fakeInput"],
"showNotifications": [true],
"displayAdvancedSettings": [true]
},
{
"blockMode": ["askReadout", "ask"],
"displayAdvancedSettings": [true]
}
]
},
{
"name": "enableStackList",
"title": "Use file specific scoped white list",
"type": "bool",
"value": false,
"displayDependencies": {
"blockMode": ["blockReadout", "fakeReadout", "fakeInput", "askReadout", "block", "ask"],
"displayAdvancedSettings": [true]
}
},
{
"name": "stackList",
"title": "File specific white list",
"type": "string",
"value": "",
"displayDependencies": {
"enableStackList": [true],
"displayAdvancedSettings": [true]
}
},
{
"name": "showReleaseNotes",
"title": "Release notes",
"type": "control",
"label": "Show"
},
{
"name": "logLevel",
"title": "logging level",
"type": "menulist",
"value": 1,
"options": [
{
"value": 0,
"label": "none"
},
{
"value": 1,
"label": "error"
},
{
"value": 25,
"label": "warning"
},
{
"value": 50,
"label": "message"
},
{
"value": 75,
"label": "notice"
},
{
"value": 100,
"label": "verbose"
}
],
"displayDependencies": {
"displayAdvancedSettings": [true]
}
}
].forEach(function(pref){
var html = "<td><div class=\"content\">" +
"<span class=\"title\">__MSG_" + pref.name + "_title__</span>" +
"<div class=\"description\">__MSG_" + pref.name + "_description__</div>" +
"</div></td><td><div class=\"content\">";
var inputAttributes =
" data-storage-name=\"" + pref.name + "\"" +
" data-storage-type=\"" + pref.type + "\"" +
" class=\"setting\"";
switch (pref.type){
case "integer":
html += "<input type=\"number\"" + inputAttributes + " value=\"" + pref.value + "\">";
break;
case "string":
html += "<input type=\"text\"" + inputAttributes + " value=\"" + pref.value + "\">";
break;
case "bool":
html += "<input type=\"checkbox\" style=\"display: inline\"" +
inputAttributes +
(pref.value? " checked=\"checked\"": "") +
">";
break;
case "menulist":
html += "<select" + inputAttributes + "data-type=\"" + (typeof pref.value) + "\">" +
pref.options.map(function(option){
if (option.value !== ""){
return "<option value=\"" + option.value + "\"" +
(option.value === pref.value? " selected": "") +
">" +
"__MSG_" + pref.name + "_options." + option.label + "__" +
"</option>";
}
else {
return "<option disabled>----------------</option>";
}
}).join("") +
"</select>";
break;
case "control":
html += "<button" + inputAttributes + "\">__MSG_" + pref.name + "_label__</button>";
break;
default:
logging.warning("Unknown preference type: " + pref.type);
}
html += "</div></td>";
var tr = document.createElement("tr");
tr.setting = pref;
tr.className = "settingRow";
tr.innerHTML = html;
logging.verbose(html);
table.appendChild(tr);
});
}());

View File

@ -6,10 +6,12 @@
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head> </head>
<body> <body>
<script src="../lib/defaultSettings.js"></script> <script src="../lib/require.js"></script>
<script src="../lib/require.js"></script> <script src="../lib/settingDefinitions.js"></script>
<script src="../lib/settings.js"></script>
<script src="../lib/logging.js"></script> <script src="../lib/logging.js"></script>
<script src="buildPrefInputs.js"></script> <script src="optionsGui.js"></script>
<script src="settingsDisplay.js"></script>
<script src="options.js"></script> <script src="options.js"></script>
</body> </body>
</html> </html>

View File

@ -5,131 +5,64 @@
"use strict"; "use strict";
const logging = require("./logging"); const logging = require("./logging");
logging.setPrefix("options page");
const optionsGui = require("./optionsGui");
const settings = require("./settings");
const settingsDisplay = require("./settingsDisplay");
browser.storage.local.get().then(function(data){ var callbacks = {
Object.keys(data).forEach(function(key){ showReleaseNotes: function(){
settings[key] = data[key]; logging.verbose("open release notes");
}); window.open("../releaseNotes.txt", "_blank");
settings.isStillDefault = false; },
logging.setPrefix("options page"); clearPersistentRnd: function(){
logging.clearQueue(); logging.message("clear persistent rnd storage");
return settings; logging.notice("empty storage");
}).then(function(settings){ settings.persistentRndStorage = "";
function traverse(node, func){ logging.notice("send message to main script");
func(node); browser.runtime.sendMessage({"canvasBlocker-clear-domain-rnd": true});
Array.from(node.childNodes).forEach(function(child){traverse(child, func);});
} }
};
// getting the translation of all the messages
logging.message("translate all messages"); var table = document.createElement("table");
traverse(document.body, function(node){ table.className = "settings";
if (node.nodeType === 3){ document.body.appendChild(table);
var lines = node.nodeValue.replace(/\b__MSG_(.+)__\b/g, function(m, key){ settingsDisplay.forEach(function(display){
try { var setting = settings.getDefinition(display.name);
return browser.i18n.getMessage(key); if (!setting){
} if (callbacks[display.name]){
catch (e){ setting = {
return "Unknown i18n key: " + key; name: display.name,
} action: callbacks[display.name]
}).split(/\n/g); };
node.nodeValue = lines.shift();
lines.forEach(function(line){
node.parentNode.appendChild(document.createElement("br"));
node.parentNode.appendChild(document.createTextNode(line));
});
} }
}); }
if (setting){
logging.message("register events to store changes in local storage"); var row = optionsGui.createSettingRow(setting);
Array.from(document.querySelectorAll("input.setting, select.setting")).forEach(function(input){ table.appendChild(row);
var storageName = input.dataset.storageName; if (display.displayDependencies){
if (input.type === "checkbox"){ var displayDependencies = display.displayDependencies;
input.checked = settings[storageName]; displayDependencies = Array.isArray(displayDependencies)?
displayDependencies:
input.addEventListener("click", function(){ [displayDependencies];
logging.message("changed setting", storageName, ":", this.checked); var computeDependencies = function(){
var value = this.checked; logging.verbose("evaluate display dependencies for", setting);
var obj = {};
obj[storageName] = value;
browser.storage.local.set(obj);
});
}
else {
input.value = settings[storageName];
input.addEventListener("change", function(){
var value = this.value;
if (this.type === "number" || this.dataset.type === "number"){
value = parseFloat(value);
}
logging.message("changed setting", storageName, ":", value);
var obj = {};
obj[storageName] = value;
browser.storage.local.set(obj);
});
}
});
var callbacks = {
showReleaseNotes: function(){
logging.verbose("open release notes");
window.open("../releaseNotes.txt", "_blank");
},
clearPersistentRnd: function(){
logging.message("clear persistent rnd storage");
logging.notice("empty storage");
browser.storage.local.set({persistentRndStorage: ""});
logging.notice("send message to main script");
browser.runtime.sendMessage({"canvasBlocker-clear-domain-rnd": true});
}
};
Array.from(document.querySelectorAll("button.setting")).forEach(function(button){
var storageName = button.dataset.storageName;
button.addEventListener("click", function(){
if (callbacks[storageName]){
callbacks[storageName]();
}
});
});
function updateDisplay(){
logging.notice("update display");
document.querySelectorAll("tr.settingRow").forEach(function(row){
logging.verbose("evaluate display dependencies for", row.setting);
var displayDependencies = row.setting.displayDependencies;
if (displayDependencies){
row.classList[( row.classList[(
( displayDependencies.some(function(displayDependency){
Array.isArray(displayDependencies)?
displayDependencies:
[displayDependencies]
).some(function(displayDependency){
return Object.keys(displayDependency).every(function(key){ return Object.keys(displayDependency).every(function(key){
return displayDependency[key].indexOf(settings[key]) !== -1; return displayDependency[key].indexOf(settings[key]) !== -1;
}); });
}) })
)? "remove": "add"]("hidden"); )? "remove": "add"]("hidden");
} };
}); computeDependencies();
} displayDependencies.forEach(function(displayDependency){
updateDisplay(); Object.keys(displayDependency).forEach(function(name){
settings.on(name, computeDependencies);
browser.storage.onChanged.addListener(function(change, area){ });
if (area === "local"){
Object.keys(change).forEach(function(key){
settings[key] = change[key].newValue;
var input = document.querySelector(".setting[data-storage-name=" + key + "]");
if (input){
if (input.type === "checkbox"){
input.checked = change[key].newValue;
}
else {
input.value = change[key].newValue;
}
}
}); });
updateDisplay();
} }
}); }
}); });
}()); }());

171
options/optionsGui.js Normal file
View File

@ -0,0 +1,171 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
(function(){
"use strict";
var scope;
if ((typeof exports) !== "undefined"){
scope = exports;
}
else {
scope = {};
window.scope.optionsGui = scope;
}
const logging = require("./logging");
function createDescription(setting){
var c = document.createElement("div");
c.className = "content";
var title = document.createElement("span");
title.className = "title";
title.textContent = browser.i18n.getMessage(setting.name + "_title");
c.appendChild(title);
var description = document.createElement("div");
description.className = "description";
description.textContent = browser.i18n.getMessage(setting.name + "_description");
c.appendChild(description);
return c;
}
function createSelect(setting){
var select = document.createElement("select");
select.dataset.type = typeof setting.defaultValue;
setting.options.forEach(function(value){
var option = document.createElement("option");
if (typeof value === typeof setting.defaultValue){
option.value = value;
if (setting.defaultValue === value){
option.selected = true;
}
option.text = browser.i18n.getMessage(setting.name + "_options." + value) || value;
}
else {
option.disabled = true;
option.text = "\u2500".repeat(20);
}
select.appendChild(option);
});
return select;
}
var inputTypes = {
number: {
input: function(input, value){
input.type = "number";
input.value = value;
return input;
},
updateCallback: function(input, setting){
input.value = setting.get();
return input.value;
},
changeCallback: function(input, setting){
setting.set(parseFloat(input.value));
return parseFloat(input.value);
}
},
string: {
input: function(input, value){
input.type = "text";
input.value = value;
return input;
},
updateCallback: function(input, setting){
input.value = setting.get();
return input.value;
},
changeCallback: function(input, setting){
setting.set(input.value);
return input.value;
}
},
boolean: {
input: function(input, value){
input.type = "checkbox";
input.checked = value;
input.style.display = "inline";
return input;
},
updateCallback: function(input, setting){
input.checked = setting.get();
return input.checked;
},
changeCallback: function(input, setting){
setting.set(input.checked);
return input.checked;
}
}
};
function createInput(setting){
var type = inputTypes[typeof setting.defaultValue];
var input;
if (setting.options){
input = createSelect(setting);
}
else {
input = document.createElement("input");
if (type){
type.input(input, setting.defaultValue);
}
}
if (type){
setting.on(function(){type.updateCallback(input, setting);});
input.addEventListener("change", function(){
var value = type.changeCallback(input, setting);
logging.message("changed setting", setting.name, ":", value);
});
}
return input;
}
function createButton(setting){
var button = document.createElement("button");
button.textContent = browser.i18n.getMessage(setting.name + "_label");
button.addEventListener("click", setting.action);
return button;
}
function createInteraction(setting){
var c = document.createElement("div");
c.className = "content";
var interaction;
if (setting.action){
interaction = createButton(setting);
}
else {
interaction = createInput(setting);
}
interaction.className = "setting";
interaction.dataset.storageName = setting.name;
interaction.dataset.storageType = typeof setting.defaultValue;
c.appendChild(interaction);
return c;
}
function createSettingRow(setting){
var tr = document.createElement("tr");
tr.className = "settingRow";
var left = document.createElement("td");
left.appendChild(createDescription(setting));
tr.appendChild(left);
var right = document.createElement("td");
right.appendChild(createInteraction(setting));
tr.appendChild(right);
return tr;
}
scope.createSettingRow = createSettingRow;
}());

163
options/settingsDisplay.js Normal file
View File

@ -0,0 +1,163 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
(function(){
"use strict";
var settingsDisplay = [
{
"name": "displayAdvancedSettings"
},
{
"name": "blockMode"
},
{
"name": "whiteList",
"displayDependencies": {
"blockMode": ["blockReadout", "fakeReadout", "fakeInput", "askReadout", "block", "ask"]
}
},
{
"name": "blackList",
"displayDependencies": {
"blockMode": ["blockReadout", "fakeReadout", "fakeInput", "askReadout", "ask", "allow"]
}
},
{
"name": "minFakeSize",
"displayDependencies": {
"blockMode": ["fakeReadout", "fakeInput"],
"displayAdvancedSettings": [true]
}
},
{
"name": "maxFakeSize",
"displayDependencies": {
"blockMode": ["fakeReadout", "fakeInput"],
"displayAdvancedSettings": [true]
}
},
{
"name": "rng",
"displayDependencies": {
"blockMode": ["fakeReadout", "fakeInput"],
"displayAdvancedSettings": [true]
}
},
{
"name": "storePersistentRnd",
"displayDependencies": {
"blockMode": ["fakeReadout", "fakeInput"],
"rng": ["persistent"],
"displayAdvancedSettings": [true]
}
},
{
"name": "clearPersistentRnd",
"displayDependencies": {
"blockMode": ["fakeReadout", "fakeInput"],
"rng": ["persistent"],
"displayAdvancedSettings": [true]
}
},
{
"name": "ignoreFrequentColors",
"displayDependencies": {
"blockMode": ["fakeReadout"],
"displayAdvancedSettings": [true]
}
},
{
"name": "fakeAlphaChannel",
"displayDependencies": {
"blockMode": ["fakeReadout"],
"displayAdvancedSettings": [true]
}
},
{
"name": "useCanvasCache",
"displayDependencies": {
"blockMode": ["fakeReadout"],
"displayAdvancedSettings": [true]
}
},
{
"name": "askOnlyOnce",
"displayDependencies": {
"blockMode": ["askReadout", "ask"]
}
},
{
"name": "showNotifications",
"displayDependencies": {
"blockMode": ["fakeReadout", "fakeInput"]
}
},
{
"name": "storeImageForInspection",
"displayDependencies": {
"blockMode": ["fakeReadout", "fakeInput"],
"showNotifications": [true],
"displayAdvancedSettings": [true]
}
},
{
"name": "ignoreList",
"displayDependencies": {
"blockMode": ["fakeReadout", "fakeInput"],
"showNotifications": [true]
}
},
{
"name": "showCallingFile",
"displayDependencies": {
"blockMode": ["askReadout", "ask"],
"displayAdvancedSettings": [true]
}
},
{
"name": "showCompleteCallingStack",
"displayDependencies": [
{
"blockMode": ["fakeReadout", "fakeInput"],
"showNotifications": [true],
"displayAdvancedSettings": [true]
},
{
"blockMode": ["askReadout", "ask"],
"displayAdvancedSettings": [true]
}
]
},
{
"name": "enableStackList",
"displayDependencies": {
"blockMode": ["blockReadout", "fakeReadout", "fakeInput", "askReadout", "block", "ask"],
"displayAdvancedSettings": [true]
}
},
{
"name": "stackList",
"displayDependencies": {
"enableStackList": [true],
"displayAdvancedSettings": [true]
}
},
{
"name": "showReleaseNotes"
},
{
"name": "logLevel",
"displayDependencies": {
"displayAdvancedSettings": [true]
}
}
];
if ((typeof module) !== "undefined"){
module.exports = settingsDisplay;
}
else {
window.scope.settingsDisplay = settingsDisplay;
}
}());

View File

@ -10,9 +10,10 @@
<ul id="prints"> <ul id="prints">
<li>...</li> <li>...</li>
</ul> </ul>
<script src="../lib/defaultSettings.js"></script>
<script src="../lib/require.js"></script> <script src="../lib/require.js"></script>
<script src="../lib/logging.js"></script> <script src="../lib/settingDefinitions.js"></script>
<script src="../lib/settings.js"></script>
<script src="../lib/logging.js"></script>
<script src="../lib/lists.js"></script> <script src="../lib/lists.js"></script>
<script src="../lib/callingStack.js"></script> <script src="../lib/callingStack.js"></script>
<script src="gui.js"></script> <script src="gui.js"></script>

View File

@ -1,149 +1,143 @@
/* This Source Code Form is subject to the terms of the Mozilla Public /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
(function(){
Promise.all([
browser.tabs.query({active: true, currentWindow: true}),
browser.storage.local.get().then(function(data){
"use strict";
Object.keys(data).forEach(function(key){
settings[key] = data[key];
});
settings.isStillDefault = false;
require("./logging").clearQueue();
return settings;
})
]).then(function(values){
"use strict"; "use strict";
const [tabs, settings] = values;
const settings = require("./settings");
const lists = require("./lists");
const {parseErrorStack} = require("./callingStack");
const {error, warning, message, notice, verbose, setPrefix: setLogPrefix} = require("./logging"); const {error, warning, message, notice, verbose, setPrefix: setLogPrefix} = require("./logging");
setLogPrefix("page action script");
const domainNotification = require("./domainNotification"); const domainNotification = require("./domainNotification");
const Notification = require("./Notification"); const Notification = require("./Notification");
const {createActionButtons, modalPrompt} = require("./gui"); const {createActionButtons, modalPrompt} = require("./gui");
setLogPrefix("page action script");
notice("create global action buttons"); Promise.all([
browser.tabs.query({active: true, currentWindow: true}),
settings.loaded
]).then(function(values){
const tabs = values[0];
notice("create global action buttons");
createActionButtons( createActionButtons(
document.getElementById("globalActions"), document.getElementById("globalActions"),
[{ [{
name: "disableNotifications", name: "disableNotifications",
isIcon: true, isIcon: true,
callback: function(){ callback: function(){
browser.storage.local.set({showNotifications: false}); settings.showNotifications = false;
window.close();
}
}],
undefined
);
if (!tabs.length){
throw new Error("noTabsFound");
}
else if (tabs.length > 1){
error(tabs);
throw new Error("tooManyTabsFound");
}
const lists = require("./lists");
lists.updateAll();
const {parseErrorStack} = require("./callingStack");
verbose("registering domain actions");
[
{
name: "ignorelistDomain",
isIcon: true,
callback: function(domain){
modalPrompt(
browser.i18n.getMessage("inputIgnoreDomain"),
domain
).then(function(domain){
if (domain){
lists.appendTo("ignore", domain);
}
window.close(); window.close();
}
}],
undefined
);
if (!tabs.length){
throw new Error("noTabsFound");
}
else if (tabs.length > 1){
error(tabs);
throw new Error("tooManyTabsFound");
}
verbose("registering domain actions");
[
{
name: "ignorelistDomain",
isIcon: true,
callback: function(domain){
modalPrompt(
browser.i18n.getMessage("inputIgnoreDomain"),
domain
).then(function(domain){
if (domain){
lists.appendTo("ignore", domain);
}
window.close();
});
}
},
{
name: "whitelistDomain",
isIcon: true,
callback: function(domain){
modalPrompt(
browser.i18n.getMessage("inputWhitelistURL"),
domain
).then(function(domain){
if (domain){
lists.appendTo("white", domain);
}
window.close();
});
}
}
].forEach(function(domainAction){
domainNotification.addAction(domainAction);
});
verbose("registering notification actions");
[
{
name: "displayFullURL",
isIcon: true,
callback: function({url}){
alert(url.href);
}
},
{
name: "displayCallingStack",
isIcon: true,
callback: function({errorStack}){
alert(parseErrorStack(errorStack));
}
},
{
name: "whitelistURL",
isIcon: true,
callback: function({url}){
modalPrompt(
browser.i18n.getMessage("inputWhitelistDomain"),
"^" + url.href.replace(/([\\+*?[^\]$(){}=!|.])/g, "\\$1") + "$"
).then(function(url){
if (url){
lists.appendTo("white", url);
}
window.close();
});
}
}
].forEach(function(action){
Notification.addAction(action);
});
var tab = tabs[0];
browser.runtime.onMessage.addListener(function(data){
if (Array.isArray(data["canvasBlocker-notifications"])){
message("got notifications");
data["canvasBlocker-notifications"].forEach(function(notification){
verbose(notification);
notification.url = new URL(notification.url);
domainNotification(
notification.url.hostname,
notification.messageId
).addNotification(new Notification(notification));
}); });
} }
}, });
{ message("request notifications from tab", tab.id);
name: "whitelistDomain", browser.tabs.sendMessage(
isIcon: true, tab.id,
callback: function(domain){ {
modalPrompt( "canvasBlocker-sendNotifications": tab.id
browser.i18n.getMessage("inputWhitelistURL"),
domain
).then(function(domain){
if (domain){
lists.appendTo("white", domain);
}
window.close();
});
} }
} );
].forEach(function(domainAction){ notice("waiting for notifications");
domainNotification.addAction(domainAction); }).catch(function(e){
error(e);
}); });
}());
verbose("registering notification actions");
[
{
name: "displayFullURL",
isIcon: true,
callback: function({url}){
alert(url.href);
}
},
{
name: "displayCallingStack",
isIcon: true,
callback: function({errorStack}){
alert(parseErrorStack(errorStack));
}
},
{
name: "whitelistURL",
isIcon: true,
callback: function({url}){
modalPrompt(
browser.i18n.getMessage("inputWhitelistDomain"),
"^" + url.href.replace(/([\\+*?[^\]$(){}=!|.])/g, "\\$1") + "$"
).then(function(url){
if (url){
lists.appendTo("white", url);
}
window.close();
});
}
}
].forEach(function(action){
Notification.addAction(action);
});
var tab = tabs[0];
browser.runtime.onMessage.addListener(function(data){
if (Array.isArray(data["canvasBlocker-notifications"])){
message("got notifications");
data["canvasBlocker-notifications"].forEach(function(notification){
verbose(notification);
notification.url = new URL(notification.url);
domainNotification(
notification.url.hostname,
notification.messageId
).addNotification(new Notification(notification));
});
}
});
message("request notifications from tab", tab.id);
browser.tabs.sendMessage(
tab.id,
{
"canvasBlocker-sendNotifications": tab.id
}
);
notice("waiting for notifications");
}).catch(function(e){
"use strict";
require("./logging").error(e);
});

View File

@ -1,8 +1,4 @@
Version 0.4.1: Version 0.4.1:
todos:
- get rid of the .innerHTML assigments
- better and saver settings system
changes: changes:
- improved design of the page action display - improved design of the page action display
- -