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",
"globals": {
"exportFunction": false,
"settings": false
"exportFunction": false
},
"rules": {
"brace-style": ["error", "stroustrup", {"allowSingleLine": true}],

25
.vscode/tasks.json vendored
View File

@ -53,6 +53,31 @@
},
"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",
"type": "shell",

View File

@ -91,39 +91,39 @@
"message": "",
"description": ""
},
"blockMode_options.allow everything": {
"blockMode_options.allowEverything": {
"message": "alles erlauben",
"description": ""
},
"blockMode_options.allow only white list": {
"blockMode_options.block": {
"message": "nur Einträge der Whitelist erlauben",
"description": ""
},
"blockMode_options.ask for permission": {
"blockMode_options.ask": {
"message": "um Erlaubnis fragen",
"description": ""
},
"blockMode_options.ask for readout API permission": {
"blockMode_options.askReadout": {
"message": "bei Auslese-API um Erlaubnis fragen",
"description": ""
},
"blockMode_options.block everything": {
"blockMode_options.blockEverything": {
"message": "alles blockieren",
"description": ""
},
"blockMode_options.block only black list": {
"blockMode_options.allow": {
"message": "nur Einträge der Blacklist blockieren",
"description": ""
},
"blockMode_options.block readout API": {
"blockMode_options.blockReadout": {
"message": "Auslese-API blockieren",
"description": ""
},
"blockMode_options.fake readout API": {
"blockMode_options.fakeReadout": {
"message": "Auslese-API vortäuschen",
"description": ""
},
"blockMode_options.fake input API": {
"blockMode_options.fakeInput": {
"message": "Bei Ausgabe vortäuschen",
"description": ""
},
@ -162,7 +162,7 @@
"message": "konstant",
"description": ""
},
"rng_options.non persistent": {
"rng_options.nonPersistent": {
"message": "nicht persistent",
"description": ""
},
@ -185,7 +185,7 @@
"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": ""
},
@ -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.",
"description": ""
},
"logLevel_options.none": {
"logLevel_options.0": {
"message": "nichts",
"description": ""
},
"logLevel_options.error": {
"logLevel_options.1": {
"message": "Fehler",
"description": ""
},
"logLevel_options.warning": {
"logLevel_options.25": {
"message": "Warnungen",
"description": ""
},
"logLevel_options.message": {
"logLevel_options.50": {
"message": "Nachrichten",
"description": ""
},
"logLevel_options.notice": {
"logLevel_options.75": {
"message": "Notizen",
"description": ""
},
"logLevel_options.verbose": {
"logLevel_options.100": {
"message": "ausführlich",
"description": ""
}

View File

@ -91,39 +91,39 @@
"message": "",
"description": ""
},
"blockMode_options.allow everything": {
"blockMode_options.allowEverything": {
"message": "allow everything",
"description": ""
},
"blockMode_options.allow only white list": {
"blockMode_options.block": {
"message": "allow only white list",
"description": ""
},
"blockMode_options.ask for permission": {
"blockMode_options.ask": {
"message": "ask for permission",
"description": ""
},
"blockMode_options.ask for readout API permission": {
"blockMode_options.askReadout": {
"message": "ask for readout API permission",
"description": ""
},
"blockMode_options.block everything": {
"blockMode_options.blockEverything": {
"message": "block everything",
"description": ""
},
"blockMode_options.block only black list": {
"blockMode_options.allow": {
"message": "block only black list",
"description": ""
},
"blockMode_options.block readout API": {
"blockMode_options.blockReadout": {
"message": "block readout API",
"description": ""
},
"blockMode_options.fake readout API": {
"blockMode_options.fakeReadout": {
"message": "fake readout API",
"description": ""
},
"blockMode_options.fake input API": {
"blockMode_options.fakeInput": {
"message": "fake at input",
"description": ""
},
@ -162,7 +162,7 @@
"message": "constant",
"description": ""
},
"rng_options.non persistent": {
"rng_options.nonPersistent": {
"message": "non persistent",
"description": ""
},
@ -185,7 +185,7 @@
"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": ""
},
@ -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.",
"description": ""
},
"logLevel_options.none": {
"logLevel_options.0": {
"message": "none",
"description": ""
},
"logLevel_options.error": {
"logLevel_options.1": {
"message": "error",
"description": ""
},
"logLevel_options.warning": {
"logLevel_options.25": {
"message": "warning",
"description": ""
},
"logLevel_options.message": {
"logLevel_options.50": {
"message": "message",
"description": ""
},
"logLevel_options.notice": {
"logLevel_options.75": {
"message": "notice",
"description": ""
},
"logLevel_options.verbose": {
"logLevel_options.100": {
"message": "verbose",
"description": ""
}

View File

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

View File

@ -13,6 +13,7 @@
scope = window.scope.check;
}
const settings = require("./settings");
const lists = require("./lists");
const {parseErrorStack} = require("./callingStack");
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(){
"use strict";
const settings = require("./settings");
const {intercept} = require("./intercept.js");
const {ask} = require("./askForPermission.js");
const lists = require("./lists.js");
@ -46,6 +47,7 @@
var port = browser.runtime.connect();
var tabId;
port.onMessage.addListener(function(data){
message("Got data from port", data);
if (data.hasOwnProperty("tabId")){
notice("my tab id is", data.tabId);
tabId = data.tabId;
@ -64,8 +66,6 @@
settings[key] = data.settings[key];
});
settings.isStillDefault = false;
logging.clearQueue();
lists.updateAll();
}
});
var notifications = [];
@ -141,22 +141,9 @@
return true;
}
if (settings.isStillDefault){
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 {
settings.onloaded(function(){
interceptWindow(window);
}
});
message("register listener for messages from background script");
browser.runtime.onMessage.addListener(function(data){
@ -175,15 +162,4 @@
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 randomSupplies = require("./randomSupplies");
const getWrapped = require("sdk/getWrapped");
const logging = require("./logging");
setRandomSupply(randomSupplies.nonPersistent);
var apiNames = Object.keys(changedFunctions);
@ -57,6 +58,7 @@
scope.intercept = function intercept({subject: window}, {check, checkStack, ask, notify, prefs}){
var siteStatus = check({url: getURL(window)});
logging.verbose("status for page", window, siteStatus);
if (siteStatus.mode !== "allow"){
apiNames.forEach(function(name){
var changedFunction = changedFunctions[name];

View File

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

View File

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

View File

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

View File

@ -6,9 +6,15 @@ const require = function(){
"use strict";
window.scope = {};
const scope = window.scope;
function getScopeName(module){
var scopeName = module.substr(2).replace(/\..+/, "");
return scopeName;
}
function require(module){
if (module.startsWith("./")){
var scopeName = module.substr(2).replace(/\..+/, "");
var scopeName = getScopeName(module);
return scope[scopeName];
}
else if (module === "sdk/getWrapped"){
@ -27,22 +33,31 @@ const require = function(){
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 + "!");
}
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;
}();

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
* 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(){
(function(){
"use strict";
var scope;
@ -9,138 +9,144 @@
scope = exports;
}
else {
window.scope.settings = {};
scope = window.scope.settings;
scope = {};
window.scope.settings = scope;
}
var settingDefinitions = [
{
name: "logLevel",
defaultValue: 1
},
{
name: "whiteList",
defaultValue: ""
},
{
name: "blackList",
defaultValue: ""
},
{
name: "blockMode",
defaultValue: "fakeReadout",
options: ["blockReadout", "fakeReadout", "fakeInput", "askReadout", "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
}
];
var settings = {};
window.settings = {};
var logging = {};
(function(){
var loggingQueue = [];
require.on("./logging", function(realLogging){
logging = realLogging;
loggingQueue.forEach(function(logEntry){
logging[logEntry.name](...logEntry.args, logEntry.date);
});
loggingQueue = [];
});
["error", "warning", "message", "notice", "verbose"].forEach(function(name){
logging[name] = function(...args){
loggingQueue.push({name, args, date: new Date()});
};
});
}());
const settingDefinitions = require("./settingDefinitions.js");
const eventHandler = {any: []};
eventHandler.all = eventHandler.any;
const settings = {};
settingDefinitions.forEach(function(settingDefinition){
var name = settingDefinition.name;
settings[name] = settingDefinition.defaultValue;
Object.defineProperty(
window.settings,
{
name: name,
get: function(){
return settings[name]
},
set: function(newValue){
if ((typeof newValue) === (typeof settingDefinition.defaultValue)){
if (
!settingDefinition.options ||
settingDefinition.options.includes(newValue)
){
settings[name] = newValue;
}
eventHandler[name] = [];
settingDefinition.on = function on(callback){
scope.on(name, callback);
};
settingDefinition.get = function getValue(){
return settings[name];
};
settingDefinition.set = function setValue(newValue){
if ((typeof newValue) === (typeof settingDefinition.defaultValue)){
if (
!settingDefinition.options ||
settingDefinition.options.includes(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){
settingDefinitions.map(function(settingDefinition){
return Object.create(settingDefinition);
}).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": {
"scripts": [
"lib/defaultSettings.js",
"lib/require.js",
"lib/settingDefinitions.js",
"lib/settings.js",
"lib/logging.js",
"lib/lists.js",
"lib/main.js"
@ -20,8 +21,9 @@
"all_frames": true,
"run_at": "document_start",
"js": [
"lib/defaultSettings.js",
"lib/require.js",
"lib/settingDefinitions.js",
"lib/settings.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">
</head>
<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="buildPrefInputs.js"></script>
<script src="optionsGui.js"></script>
<script src="settingsDisplay.js"></script>
<script src="options.js"></script>
</body>
</html>

View File

@ -5,131 +5,64 @@
"use strict";
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){
Object.keys(data).forEach(function(key){
settings[key] = data[key];
});
settings.isStillDefault = false;
logging.setPrefix("options page");
logging.clearQueue();
return settings;
}).then(function(settings){
function traverse(node, func){
func(node);
Array.from(node.childNodes).forEach(function(child){traverse(child, func);});
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");
settings.persistentRndStorage = "";
logging.notice("send message to main script");
browser.runtime.sendMessage({"canvasBlocker-clear-domain-rnd": true});
}
// getting the translation of all the messages
logging.message("translate all messages");
traverse(document.body, function(node){
if (node.nodeType === 3){
var lines = node.nodeValue.replace(/\b__MSG_(.+)__\b/g, function(m, key){
try {
return browser.i18n.getMessage(key);
}
catch (e){
return "Unknown i18n key: " + key;
}
}).split(/\n/g);
node.nodeValue = lines.shift();
lines.forEach(function(line){
node.parentNode.appendChild(document.createElement("br"));
node.parentNode.appendChild(document.createTextNode(line));
});
};
var table = document.createElement("table");
table.className = "settings";
document.body.appendChild(table);
settingsDisplay.forEach(function(display){
var setting = settings.getDefinition(display.name);
if (!setting){
if (callbacks[display.name]){
setting = {
name: display.name,
action: callbacks[display.name]
};
}
});
logging.message("register events to store changes in local storage");
Array.from(document.querySelectorAll("input.setting, select.setting")).forEach(function(input){
var storageName = input.dataset.storageName;
if (input.type === "checkbox"){
input.checked = settings[storageName];
input.addEventListener("click", function(){
logging.message("changed setting", storageName, ":", this.checked);
var value = this.checked;
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){
}
if (setting){
var row = optionsGui.createSettingRow(setting);
table.appendChild(row);
if (display.displayDependencies){
var displayDependencies = display.displayDependencies;
displayDependencies = Array.isArray(displayDependencies)?
displayDependencies:
[displayDependencies];
var computeDependencies = function(){
logging.verbose("evaluate display dependencies for", setting);
row.classList[(
(
Array.isArray(displayDependencies)?
displayDependencies:
[displayDependencies]
).some(function(displayDependency){
displayDependencies.some(function(displayDependency){
return Object.keys(displayDependency).every(function(key){
return displayDependency[key].indexOf(settings[key]) !== -1;
});
})
)? "remove": "add"]("hidden");
}
});
}
updateDisplay();
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;
}
}
};
computeDependencies();
displayDependencies.forEach(function(displayDependency){
Object.keys(displayDependency).forEach(function(name){
settings.on(name, computeDependencies);
});
});
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">
<li>...</li>
</ul>
<script src="../lib/defaultSettings.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/callingStack.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
* 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/. */
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){
(function(){
"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");
setLogPrefix("page action script");
const domainNotification = require("./domainNotification");
const Notification = require("./Notification");
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(
document.getElementById("globalActions"),
[{
name: "disableNotifications",
isIcon: true,
callback: function(){
browser.storage.local.set({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);
}
createActionButtons(
document.getElementById("globalActions"),
[{
name: "disableNotifications",
isIcon: true,
callback: function(){
settings.showNotifications = false;
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));
});
}
},
{
name: "whitelistDomain",
isIcon: true,
callback: function(domain){
modalPrompt(
browser.i18n.getMessage("inputWhitelistURL"),
domain
).then(function(domain){
if (domain){
lists.appendTo("white", domain);
}
window.close();
});
});
message("request notifications from tab", tab.id);
browser.tabs.sendMessage(
tab.id,
{
"canvasBlocker-sendNotifications": tab.id
}
}
].forEach(function(domainAction){
domainNotification.addAction(domainAction);
);
notice("waiting for notifications");
}).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:
todos:
- get rid of the .innerHTML assigments
- better and saver settings system
changes:
- improved design of the page action display
-