mirror of
https://github.com/kkapsner/CanvasBlocker
synced 2024-12-22 12:50:36 +01:00
Big linting
This commit is contained in:
parent
b5e6d049ce
commit
aef6bd3d59
104
.eslintrc.json
104
.eslintrc.json
@ -1,40 +1,68 @@
|
|||||||
{
|
{
|
||||||
"env": {
|
"env": {
|
||||||
"browser": true,
|
"browser": true,
|
||||||
"commonjs": true,
|
"commonjs": true,
|
||||||
"es6": true,
|
"es6": true,
|
||||||
"webextensions": true
|
"webextensions": true
|
||||||
},
|
},
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"ecmaFeatures": {
|
"ecmaFeatures": {
|
||||||
"jsx": true
|
"jsx": true
|
||||||
},
|
},
|
||||||
"sourceType": "script"
|
"sourceType": "script"
|
||||||
},
|
},
|
||||||
"extends": "eslint:recommended",
|
"plugins": ["promise", "eslint-comments"],
|
||||||
"globals": {
|
"extends": [
|
||||||
"exportFunction": false
|
"eslint:recommended",
|
||||||
},
|
"plugin:promise/recommended",
|
||||||
"rules": {
|
"plugin:eslint-comments/recommended"
|
||||||
"brace-style": ["error", "stroustrup", {"allowSingleLine": true}],
|
],
|
||||||
"comma-spacing": ["error", { "before": false, "after": true }],
|
"globals": {
|
||||||
"constructor-super": "warn",
|
"exportFunction": false
|
||||||
"eqeqeq": "error",
|
},
|
||||||
"max-len": ["warn", {"code": 120, "tabWidth": 4}],
|
"rules": {
|
||||||
"max-lines": ["warn", {"max": 500, "skipBlankLines": true, "skipComments": true}],
|
"brace-style": ["error", "stroustrup", {"allowSingleLine": true}],
|
||||||
"max-params": ["warn", 4],
|
"comma-spacing": ["error", { "before": false, "after": true }],
|
||||||
"no-const-assign": "warn",
|
"complexity": ["warn", 20],
|
||||||
"no-this-before-super": "warn",
|
"constructor-super": "warn",
|
||||||
"no-undef": "error",
|
"eqeqeq": "error",
|
||||||
"no-unreachable": "warn",
|
"eslint-comments/no-use": ["error", {"allow": ["eslint-disable-next-line"]}],
|
||||||
"no-unused-vars": "off",
|
"indent": ["error", "tab", {"SwitchCase": 1}],
|
||||||
"no-trailing-spaces": ["error", {"skipBlankLines": true}],
|
"max-depth": ["warn", 4],
|
||||||
"no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
|
"max-len": ["warn", {"code": 120, "tabWidth": 4}],
|
||||||
"indent": ["error", "tab", {"SwitchCase": 1}],
|
"max-lines-per-function": ["warn", {"max": 80,"skipBlankLines": true, "skipComments": true}],
|
||||||
"space-in-parens": ["error", "never"],
|
"max-lines": ["warn", {"max": 500, "skipBlankLines": true, "skipComments": true}],
|
||||||
"valid-typeof": "warn",
|
"max-params": ["warn", 4],
|
||||||
"quotes": ["error", "double"],
|
"no-console": "error",
|
||||||
"semi": ["error", "always"],
|
"no-const-assign": "error",
|
||||||
"strict": ["error", "function"]
|
"no-inner-declarations": "warn",
|
||||||
}
|
"no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
|
||||||
|
"no-prototype-builtins": "off",
|
||||||
|
"no-this-before-super": "warn",
|
||||||
|
"no-trailing-spaces": ["error", {"skipBlankLines": true}],
|
||||||
|
"no-undef": "error",
|
||||||
|
"no-unreachable": "warn",
|
||||||
|
"no-unused-vars": "off",
|
||||||
|
"no-use-before-define": ["error", {"functions": false}],
|
||||||
|
"no-var": "error",
|
||||||
|
"quotes": ["error", "double"],
|
||||||
|
"semi": ["error", "always"],
|
||||||
|
"space-in-parens": ["error", "never"],
|
||||||
|
"strict": ["error", "function"],
|
||||||
|
"valid-typeof": "warn"
|
||||||
|
},
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["detectionTest.js", "modifiedCanvasAPI.js", "options.js", "settingsDisplay.js"],
|
||||||
|
"rules": {
|
||||||
|
"max-lines": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["test/*.js"],
|
||||||
|
"rules": {
|
||||||
|
"no-var": "off"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
@ -11,7 +11,7 @@
|
|||||||
logging.message("Opened browser action");
|
logging.message("Opened browser action");
|
||||||
|
|
||||||
settings.onloaded(function(){
|
settings.onloaded(function(){
|
||||||
var actions = document.getElementById("actions");
|
const actions = document.getElementById("actions");
|
||||||
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -54,10 +54,10 @@
|
|||||||
logging.verbose("Hiding advanced action");
|
logging.verbose("Hiding advanced action");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var actionButton = document.createElement("button");
|
const actionButton = document.createElement("button");
|
||||||
actionButton.className = "action";
|
actionButton.className = "action";
|
||||||
|
|
||||||
var icon = document.createElement("span");
|
const icon = document.createElement("span");
|
||||||
icon.className = "icon";
|
icon.className = "icon";
|
||||||
icon.style.maskImage = "url(" + action.icon + ")";
|
icon.style.maskImage = "url(" + action.icon + ")";
|
||||||
|
|
||||||
@ -72,7 +72,7 @@
|
|||||||
actions.appendChild(actionButton);
|
actions.appendChild(actionButton);
|
||||||
});
|
});
|
||||||
|
|
||||||
var search = document.createElement("input");
|
const search = document.createElement("input");
|
||||||
search.placeholder = extension.getTranslation("search");
|
search.placeholder = extension.getTranslation("search");
|
||||||
search.className = "search action";
|
search.className = "search action";
|
||||||
actions.appendChild(search);
|
actions.appendChild(search);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* 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;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -15,15 +15,15 @@
|
|||||||
|
|
||||||
// Check canvas appearance
|
// Check canvas appearance
|
||||||
function canvasAppearance(window, api, context){
|
function canvasAppearance(window, api, context){
|
||||||
var oldBorder = false;
|
let oldBorder = false;
|
||||||
var canvas = false;
|
let canvas = false;
|
||||||
var inDOM = null;
|
let inDOM = null;
|
||||||
if (api === "canvas" && context){
|
if (api === "canvas" && context){
|
||||||
var nodeName;
|
let nodeName;
|
||||||
try {
|
try {
|
||||||
nodeName = context.nodeName;
|
nodeName = context.nodeName;
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
nodeName = "";
|
nodeName = "";
|
||||||
}
|
}
|
||||||
if (nodeName === "CANVAS"){
|
if (nodeName === "CANVAS"){
|
||||||
@ -45,17 +45,17 @@
|
|||||||
canvas: canvas,
|
canvas: canvas,
|
||||||
askCategory: canvas? (inDOM? "visible": "invisible"): (api === "canvas"? "nocanvas": api),
|
askCategory: canvas? (inDOM? "visible": "invisible"): (api === "canvas"? "nocanvas": api),
|
||||||
get text(){
|
get text(){
|
||||||
var text = canvas? (this.visible? "visible": "invisible"): (api === "canvas"? "nocanvas": api);
|
const text = canvas? (this.visible? "visible": "invisible"): (api === "canvas"? "nocanvas": api);
|
||||||
Object.defineProperty(this, "text", {value: text});
|
Object.defineProperty(this, "text", {value: text});
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
inDom: inDOM,
|
inDom: inDOM,
|
||||||
get visible(){
|
get visible(){
|
||||||
var visible = inDOM;
|
let visible = inDOM;
|
||||||
if (inDOM){
|
if (inDOM){
|
||||||
canvas.scrollIntoView();
|
canvas.scrollIntoView();
|
||||||
var rect = canvas.getBoundingClientRect();
|
const rect = canvas.getBoundingClientRect();
|
||||||
var foundEl = window.document.elementFromPoint(
|
const foundEl = window.document.elementFromPoint(
|
||||||
rect.left + rect.width / 2,
|
rect.left + rect.width / 2,
|
||||||
rect.top + rect.height / 2
|
rect.top + rect.height / 2
|
||||||
);
|
);
|
||||||
@ -72,9 +72,9 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var modes = new WeakMap();
|
const modes = new WeakMap();
|
||||||
function getAskMode(window, type, _){
|
function getAskMode(window, type, _){
|
||||||
var mode = modes.get(window);
|
let mode = modes.get(window);
|
||||||
if (mode){
|
if (mode){
|
||||||
return mode[type];
|
return mode[type];
|
||||||
}
|
}
|
||||||
@ -132,11 +132,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
scope.ask = function({window, type, api, canvas, errorStack}, {_, prefs}){
|
scope.ask = function({window, type, api, canvas, errorStack}, {_, prefs}){
|
||||||
var answer;
|
let answer;
|
||||||
var askMode = getAskMode(window, type, _);
|
const askMode = getAskMode(window, type, _);
|
||||||
var askStatus = askMode.askStatus;
|
const askStatus = askMode.askStatus;
|
||||||
var appearance = canvasAppearance(window, api, canvas);
|
const appearance = canvasAppearance(window, api, canvas);
|
||||||
var category = appearance.askCategory;
|
let category = appearance.askCategory;
|
||||||
if (prefs("askOnlyOnce") !== "no" && askStatus.alreadyAsked[category]){
|
if (prefs("askOnlyOnce") !== "no" && askStatus.alreadyAsked[category]){
|
||||||
// already asked
|
// already asked
|
||||||
appearance.reset();
|
appearance.reset();
|
||||||
@ -146,7 +146,6 @@
|
|||||||
let imgContainer = null;
|
let imgContainer = null;
|
||||||
if (type === "readout" && prefs("showCanvasWhileAsking") && canvas){
|
if (type === "readout" && prefs("showCanvasWhileAsking") && canvas){
|
||||||
try {
|
try {
|
||||||
let content = canvas.toDataURL();
|
|
||||||
let document = window.top.document;
|
let document = window.top.document;
|
||||||
imgContainer = document.createElement("div");
|
imgContainer = document.createElement("div");
|
||||||
imgContainer.style.cssText = `
|
imgContainer.style.cssText = `
|
||||||
@ -177,12 +176,12 @@
|
|||||||
imgContainer.appendChild(img);
|
imgContainer.appendChild(img);
|
||||||
document.body.appendChild(imgContainer);
|
document.body.appendChild(imgContainer);
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
// unable to read the canvas
|
// unable to read the canvas
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// asking
|
// asking
|
||||||
var msg = askMode.askText[appearance.text];
|
let msg = askMode.askText[appearance.text];
|
||||||
|
|
||||||
// visible vs invisible is only calculated here correctly
|
// visible vs invisible is only calculated here correctly
|
||||||
category = appearance.text;
|
category = appearance.text;
|
||||||
@ -196,8 +195,8 @@
|
|||||||
|
|
||||||
if (prefs("askOnlyOnce") === "combined"){
|
if (prefs("askOnlyOnce") === "combined"){
|
||||||
["context", "readout", "input"].forEach(function(type){
|
["context", "readout", "input"].forEach(function(type){
|
||||||
var askMode = getAskMode(window, type, _);
|
const askMode = getAskMode(window, type, _);
|
||||||
var askStatus = askMode.askStatus;
|
const askStatus = askMode.askStatus;
|
||||||
askStatus.alreadyAsked[category] = true;
|
askStatus.alreadyAsked[category] = true;
|
||||||
askStatus.answer[category] = answer;
|
askStatus.answer[category] = answer;
|
||||||
});
|
});
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -16,12 +16,12 @@
|
|||||||
const extension = require("./extension");
|
const extension = require("./extension");
|
||||||
|
|
||||||
// Translation
|
// Translation
|
||||||
var _ = function(name, replace, translateAPI){
|
const _ = function(name, replace, translateAPI){
|
||||||
if (!translateAPI){
|
if (!translateAPI){
|
||||||
translateAPI = extension.getTranslation;
|
translateAPI = extension.getTranslation;
|
||||||
}
|
}
|
||||||
|
|
||||||
var str = translateAPI(name) || name;
|
let str = translateAPI(name) || name;
|
||||||
if (replace){
|
if (replace){
|
||||||
// replace generic content in the translation by given parameter
|
// replace generic content in the translation by given parameter
|
||||||
Object.keys(replace).forEach(function(name){
|
Object.keys(replace).forEach(function(name){
|
||||||
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
// Stack parsing
|
// Stack parsing
|
||||||
function parseStackEntry(entry){
|
function parseStackEntry(entry){
|
||||||
var m = /@(.*):(\d*):(\d*)$/.exec(entry) || ["", entry, "--", "--"];
|
const m = /@(.*):(\d*):(\d*)$/.exec(entry) || ["", entry, "--", "--"];
|
||||||
return {
|
return {
|
||||||
url: m[1],
|
url: m[1],
|
||||||
line: parseInt(m[2], 10),
|
line: parseInt(m[2], 10),
|
||||||
@ -61,13 +61,12 @@
|
|||||||
// parse calling stack
|
// parse calling stack
|
||||||
const extensionID = extension.extensionID;
|
const extensionID = extension.extensionID;
|
||||||
function parseErrorStack(errorStack){
|
function parseErrorStack(errorStack){
|
||||||
var callers = errorStack.trim().split("\n");
|
const callers = errorStack.trim().split("\n").map(parseStackEntry).filter(function(caller){
|
||||||
callers = callers.map(parseStackEntry).filter(function(caller){
|
|
||||||
return !caller.url.startsWith(extensionID);
|
return !caller.url.startsWith(extensionID);
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
toString: function(translateAPI){
|
toString: function(translateAPI){
|
||||||
var msg = "";
|
let msg = "";
|
||||||
msg += "\n\n" + _("sourceOutput", undefined, translateAPI) + ": ";
|
msg += "\n\n" + _("sourceOutput", undefined, translateAPI) + ": ";
|
||||||
if (settings.showCompleteCallingStack){
|
if (settings.showCompleteCallingStack){
|
||||||
msg += callers.reduce(function(stack, c){
|
msg += callers.reduce(function(stack, c){
|
||||||
@ -82,7 +81,7 @@
|
|||||||
},
|
},
|
||||||
match: function(stackRule){
|
match: function(stackRule){
|
||||||
if (typeof stackRule.stackPosition !== "undefined"){
|
if (typeof stackRule.stackPosition !== "undefined"){
|
||||||
var pos = stackRule.stackPosition;
|
let pos = stackRule.stackPosition;
|
||||||
if (pos < 0){
|
if (pos < 0){
|
||||||
pos += callers.length;
|
pos += callers.length;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
scope.check = function check({url, errorStack}){
|
scope.check = function check({url, errorStack}){
|
||||||
url = new URL(url || "about:blank");
|
url = new URL(url || "about:blank");
|
||||||
var match = checkBoth(errorStack, url, settings.get("blockMode", url)).match(
|
const match = checkBoth(errorStack, url, settings.get("blockMode", url)).match(
|
||||||
/^(block|allow|fake|ask)(|Everything|Internal)$/
|
/^(block|allow|fake|ask)(|Everything|Internal)$/
|
||||||
);
|
);
|
||||||
if (match){
|
if (match){
|
||||||
@ -63,7 +63,7 @@
|
|||||||
return "allowInternal";
|
return "allowInternal";
|
||||||
}
|
}
|
||||||
|
|
||||||
var mode = "block";
|
let mode = "block";
|
||||||
switch (blockMode){
|
switch (blockMode){
|
||||||
case "blockEverything":
|
case "blockEverything":
|
||||||
mode = "block";
|
mode = "block";
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -23,8 +23,8 @@
|
|||||||
this.minBoundary.nextColor = this.maxBoundary;
|
this.minBoundary.nextColor = this.maxBoundary;
|
||||||
}
|
}
|
||||||
addColor(r, g, b, a){
|
addColor(r, g, b, a){
|
||||||
var index = String.fromCharCode(r, g, b, a);
|
const index = String.fromCharCode(r, g, b, a);
|
||||||
var color = this.colors[index];
|
let color = this.colors[index];
|
||||||
if (!color){
|
if (!color){
|
||||||
color = {
|
color = {
|
||||||
index,
|
index,
|
||||||
@ -42,10 +42,10 @@
|
|||||||
if (color.count > color.nextColor.count){
|
if (color.count > color.nextColor.count){
|
||||||
// swap colors to remain in right order
|
// swap colors to remain in right order
|
||||||
// a_ -> b_ -> c -> d becomes a_ -> c -> b_ -> d
|
// a_ -> b_ -> c -> d becomes a_ -> c -> b_ -> d
|
||||||
var a_ = color.previousColor;
|
const a_ = color.previousColor;
|
||||||
var b_ = color;
|
const b_ = color;
|
||||||
var c = color.nextColor;
|
const c = color.nextColor;
|
||||||
var d = color.nextColor.nextColor;
|
const d = color.nextColor.nextColor;
|
||||||
|
|
||||||
a_.nextColor = c;
|
a_.nextColor = c;
|
||||||
c.previousColor = a_;
|
c.previousColor = a_;
|
||||||
@ -59,8 +59,8 @@
|
|||||||
}
|
}
|
||||||
getMaxColors(n){
|
getMaxColors(n){
|
||||||
n = Math.min(n, this.numberOfColors);
|
n = Math.min(n, this.numberOfColors);
|
||||||
var colors = Object.create(null);
|
const colors = Object.create(null);
|
||||||
var current = this.maxBoundary;
|
let current = this.maxBoundary;
|
||||||
for (;n && current;n -= 1){
|
for (;n && current;n -= 1){
|
||||||
current = current.previousColor;
|
current = current.previousColor;
|
||||||
colors[current.index] = current;
|
colors[current.index] = current;
|
||||||
@ -70,8 +70,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
scope.compute = function computeColorStatistics(rawData){
|
scope.compute = function computeColorStatistics(rawData){
|
||||||
var statistic = new Statistic();
|
const statistic = new Statistic();
|
||||||
for (var i = 0, l = rawData.length; i < l; i += 4){
|
for (let i = 0, l = rawData.length; i < l; i += 4){
|
||||||
statistic.addColor(
|
statistic.addColor(
|
||||||
rawData[i + 0],
|
rawData[i + 0],
|
||||||
rawData[i + 1],
|
rawData[i + 1],
|
||||||
@ -86,10 +86,10 @@
|
|||||||
return statistic.numberOfColors > threshold;
|
return statistic.numberOfColors > threshold;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var colors = Object.create(null);
|
const colors = Object.create(null);
|
||||||
var count = 0;
|
let count = 0;
|
||||||
for (var i = 0, l = rawData.length; i < l; i += 4){
|
for (let i = 0, l = rawData.length; i < l; i += 4){
|
||||||
var index = String.fromCharCode(
|
const index = String.fromCharCode(
|
||||||
rawData[i + 0],
|
rawData[i + 0],
|
||||||
rawData[i + 1],
|
rawData[i + 1],
|
||||||
rawData[i + 2],
|
rawData[i + 2],
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -21,6 +21,10 @@
|
|||||||
const mainVersion = parseInt(info.version.replace(/\..+/, ""), 10);
|
const mainVersion = parseInt(info.version.replace(/\..+/, ""), 10);
|
||||||
canMergeHeader = mainVersion > 59;
|
canMergeHeader = mainVersion > 59;
|
||||||
blockBlob = mainVersion < 60;
|
blockBlob = mainVersion < 60;
|
||||||
|
return canMergeHeader;
|
||||||
|
}).catch(function(){
|
||||||
|
canMergeHeader = false;
|
||||||
|
blockBlob = true;
|
||||||
});
|
});
|
||||||
function setHeader(headers, header){
|
function setHeader(headers, header){
|
||||||
if (canMergeHeader){
|
if (canMergeHeader){
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
|
53
lib/frame.js
53
lib/frame.js
@ -14,13 +14,12 @@
|
|||||||
const iframeProtection = require("./iframeProtection");
|
const iframeProtection = require("./iframeProtection");
|
||||||
|
|
||||||
const logging = require("./logging");
|
const logging = require("./logging");
|
||||||
const {error, warning, message, notice, verbose, setPrefix: setLogPrefix} = logging;
|
logging.setPrefix("frame script");
|
||||||
setLogPrefix("frame script");
|
|
||||||
|
|
||||||
// Variable to "unload" the script
|
// Variable to "unload" the script
|
||||||
var enabled = true;
|
let enabled = true;
|
||||||
|
|
||||||
message("starting", location.href);
|
logging.message("starting", location.href);
|
||||||
|
|
||||||
function check(message){
|
function check(message){
|
||||||
if (enabled){
|
if (enabled){
|
||||||
@ -72,38 +71,38 @@
|
|||||||
}
|
}
|
||||||
computeExtensionSecret();
|
computeExtensionSecret();
|
||||||
|
|
||||||
message("open port to background script");
|
logging.message("open port to background script");
|
||||||
var port = browser.runtime.connect();
|
const port = browser.runtime.connect();
|
||||||
if (window === window.top){
|
if (window === window.top){
|
||||||
message("Is top level window -> tab had navigation -> clear page action");
|
logging.message("Is top level window -> tab had navigation -> clear page action");
|
||||||
port.postMessage({"canvasBlocker-clear-page-action": true});
|
port.postMessage({"canvasBlocker-clear-page-action": true});
|
||||||
}
|
}
|
||||||
var tabId;
|
let tabId;
|
||||||
port.onMessage.addListener(function(data){
|
port.onMessage.addListener(function(data){
|
||||||
message("Got data from port", data);
|
logging.message("Got data from port", data);
|
||||||
if (data.hasOwnProperty("tabId")){
|
if (data.hasOwnProperty("tabId")){
|
||||||
notice("my tab id is", data.tabId);
|
logging.notice("my tab id is", data.tabId);
|
||||||
tabId = data.tabId;
|
tabId = data.tabId;
|
||||||
}
|
}
|
||||||
if (data.hasOwnProperty("cookieStoreId")){
|
if (data.hasOwnProperty("cookieStoreId")){
|
||||||
notice("my tab cookie store id is", data.cookieStoreId);
|
logging.notice("my tab cookie store id is", data.cookieStoreId);
|
||||||
const {persistent: persistentRnd} = require("./randomSupplies");
|
const {persistent: persistentRnd} = require("./randomSupplies");
|
||||||
persistentRnd.setCookieStoreId(data.cookieStoreId);
|
persistentRnd.setCookieStoreId(data.cookieStoreId);
|
||||||
}
|
}
|
||||||
const persistentRndName = "persistent" + (extension.inIncognitoContext? "Incognito": "") + "Rnd";
|
const persistentRndName = "persistent" + (extension.inIncognitoContext? "Incognito": "") + "Rnd";
|
||||||
if (data.hasOwnProperty(persistentRndName)){
|
if (data.hasOwnProperty(persistentRndName)){
|
||||||
const persistentRndValue = data[persistentRndName];
|
const persistentRndValue = data[persistentRndName];
|
||||||
notice("got persistent random data", persistentRndValue);
|
logging.notice("got persistent random data", persistentRndValue);
|
||||||
const {persistent: persistentRnd} = require("./randomSupplies");
|
const {persistent: persistentRnd} = require("./randomSupplies");
|
||||||
Object.keys(persistentRndValue).forEach(function(domain){
|
Object.keys(persistentRndValue).forEach(function(domain){
|
||||||
verbose("random data for", domain, persistentRndValue[domain]);
|
logging.verbose("random data for", domain, persistentRndValue[domain]);
|
||||||
persistentRnd.setDomainRnd(domain, persistentRndValue[domain]);
|
persistentRnd.setDomainRnd(domain, persistentRndValue[domain]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var notifications = [];
|
const notifications = [];
|
||||||
var notificationCounter = {};
|
const notificationCounter = {};
|
||||||
var sentAPIs = {};
|
const sentAPIs = {};
|
||||||
function notify(data){
|
function notify(data){
|
||||||
if (!settings.ignoredAPIs[data.api]){
|
if (!settings.ignoredAPIs[data.api]){
|
||||||
if (settings.storeNotificationData){
|
if (settings.storeNotificationData){
|
||||||
@ -128,16 +127,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var interceptedWindows = new WeakMap();
|
const interceptedWindows = new WeakMap();
|
||||||
function interceptWindow(window){
|
function interceptWindow(window){
|
||||||
|
let wrappedTry;
|
||||||
try {
|
try {
|
||||||
var href = window.location.href;
|
// eslint-disable-next-line no-unused-vars
|
||||||
var wrappedTry = getWrapped(window);
|
const href = window.location.href;
|
||||||
|
wrappedTry = getWrapped(window);
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
// we are unable to read the location due to SOP
|
// we are unable to read the location due to SOP
|
||||||
// therefore we also can not intercept anything.
|
// therefore we also can not intercept anything.
|
||||||
notice("NOT intercepting window due to SOP", window);
|
logging.notice("NOT intercepting window due to SOP", window);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const wrappedWindow = wrappedTry;
|
const wrappedWindow = wrappedTry;
|
||||||
@ -150,12 +151,12 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
message("intercepting window", window);
|
logging.message("intercepting window", window);
|
||||||
intercept(
|
intercept(
|
||||||
{subject: window},
|
{subject: window},
|
||||||
{check, checkStack, ask: askWrapper, notify, prefs}
|
{check, checkStack, ask: askWrapper, notify, prefs}
|
||||||
);
|
);
|
||||||
message("prepare to intercept (i)frames.");
|
logging.message("prepare to intercept (i)frames.");
|
||||||
|
|
||||||
function interceptAllFrames(){
|
function interceptAllFrames(){
|
||||||
const currentLength = window.length;
|
const currentLength = window.length;
|
||||||
@ -185,7 +186,7 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
message("register listener for messages from background script");
|
logging.message("register listener for messages from background script");
|
||||||
extension.message.on(function(data){
|
extension.message.on(function(data){
|
||||||
if (data["canvasBlocker-unload"]){
|
if (data["canvasBlocker-unload"]){
|
||||||
enabled = false;
|
enabled = false;
|
||||||
@ -194,14 +195,14 @@
|
|||||||
data.hasOwnProperty("canvasBlocker-sendNotifications") &&
|
data.hasOwnProperty("canvasBlocker-sendNotifications") &&
|
||||||
data["canvasBlocker-sendNotifications"] === tabId
|
data["canvasBlocker-sendNotifications"] === tabId
|
||||||
){
|
){
|
||||||
notice("sending notifications:", notifications);
|
logging.notice("sending notifications:", notifications);
|
||||||
extension.message.send({
|
extension.message.send({
|
||||||
sender: tabId,
|
sender: tabId,
|
||||||
url: window.location.href,
|
url: window.location.href,
|
||||||
"canvasBlocker-notificationCounter": notificationCounter,
|
"canvasBlocker-notificationCounter": notificationCounter,
|
||||||
"canvasBlocker-notifications": notifications
|
"canvasBlocker-notifications": notifications
|
||||||
});
|
});
|
||||||
notice("notifications sent");
|
logging.notice("notifications sent");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
44
lib/hash.js
44
lib/hash.js
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -20,11 +20,11 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
scope.sumXor = function(inputByteArray){
|
scope.sumXor = function(inputByteArray){
|
||||||
var hash = new Uint32Array(4);
|
const hash = new Uint32Array(4);
|
||||||
var sum = new Float64Array(hash.buffer, 8, 1);
|
// const sum = new Float64Array(hash.buffer, 8, 1);
|
||||||
var intView = new Uint32Array(inputByteArray.buffer);
|
const intView = new Uint32Array(inputByteArray.buffer);
|
||||||
var floatView = new Float32Array(inputByteArray.buffer);
|
// const floatView = new Float32Array(inputByteArray.buffer);
|
||||||
var length = intView.length;
|
const length = intView.length;
|
||||||
for (let i = 0; i < length; i += 1){
|
for (let i = 0; i < length; i += 1){
|
||||||
// sum[0] += floatView[i];
|
// sum[0] += floatView[i];
|
||||||
hash[0] ^= intView[i];
|
hash[0] ^= intView[i];
|
||||||
@ -34,11 +34,11 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
scope.hashCode = function(inputByteArray){
|
scope.hashCode = function(inputByteArray){
|
||||||
var hash = new Uint32Array(1);
|
const hash = new Uint32Array(1);
|
||||||
var intView = new Uint32Array(inputByteArray.buffer);
|
const intView = new Uint32Array(inputByteArray.buffer);
|
||||||
var length = intView.length;
|
const length = intView.length;
|
||||||
for (let i = 0; i < length; i += 1){
|
for (let i = 0; i < length; i += 1){
|
||||||
var v = hash[0];
|
const v = hash[0];
|
||||||
hash[0] = ((v << 5) - v) + intView[i];
|
hash[0] = ((v << 5) - v) + intView[i];
|
||||||
}
|
}
|
||||||
return hash;
|
return hash;
|
||||||
@ -81,21 +81,21 @@
|
|||||||
return function md5(inputByteArray){
|
return function md5(inputByteArray){
|
||||||
h.set(hInitial);
|
h.set(hInitial);
|
||||||
|
|
||||||
var length = inputByteArray.buffer.byteLength;
|
const length = inputByteArray.buffer.byteLength;
|
||||||
var messageBitLength = length * 8;
|
const messageBitLength = length * 8;
|
||||||
|
|
||||||
// create byte array with length dividable by 64 (512 bit)
|
// create byte array with length dividable by 64 (512 bit)
|
||||||
var neededLength = Math.ceil((length + 1 + 8) / 64) * 64;
|
const neededLength = Math.ceil((length + 1 + 8) / 64) * 64;
|
||||||
var messageByteArray = new Uint8Array(neededLength);
|
const messageByteArray = new Uint8Array(neededLength);
|
||||||
messageByteArray.set(new Uint8Array(inputByteArray.buffer));
|
messageByteArray.set(new Uint8Array(inputByteArray.buffer));
|
||||||
var view = new DataView(messageByteArray.buffer);
|
const view = new DataView(messageByteArray.buffer);
|
||||||
|
|
||||||
// append 10...000000
|
// append 10...000000
|
||||||
messageByteArray[length] = 0x80;
|
messageByteArray[length] = 0x80;
|
||||||
// append size in 64 bit big endian
|
// append size in 64 bit big endian
|
||||||
view.setUint32(neededLength - 8, messageBitLength, true);
|
view.setUint32(neededLength - 8, messageBitLength, true);
|
||||||
|
|
||||||
for (var i = 0; i < neededLength; i += 64){
|
for (let i = 0; i < neededLength; i += 64){
|
||||||
for (let j = 0; j < 64; j += 4){
|
for (let j = 0; j < 64; j += 4){
|
||||||
w[j / 4] = view.getUint32(i + j, true);
|
w[j / 4] = view.getUint32(i + j, true);
|
||||||
}
|
}
|
||||||
@ -118,7 +118,7 @@
|
|||||||
temp[4] = (temp[2] ^ (temp[1] | (~ temp[3])));
|
temp[4] = (temp[2] ^ (temp[1] | (~ temp[3])));
|
||||||
temp[5] = (7*j) % 16;
|
temp[5] = (7*j) % 16;
|
||||||
}
|
}
|
||||||
var temp_ = temp[3];
|
const temp_ = temp[3];
|
||||||
temp[3] = temp[2];
|
temp[3] = temp[2];
|
||||||
temp[2] = temp[1];
|
temp[2] = temp[1];
|
||||||
temp[1] = (leftRotate(temp[0] + temp[4] + k[j] + w[temp[5]], r[j]) + temp[1]);
|
temp[1] = (leftRotate(temp[0] + temp[4] + k[j] + w[temp[5]], r[j]) + temp[1]);
|
||||||
@ -165,14 +165,14 @@
|
|||||||
|
|
||||||
h.set(hInitial);
|
h.set(hInitial);
|
||||||
|
|
||||||
var length = inputByteArray.buffer.byteLength;
|
const length = inputByteArray.buffer.byteLength;
|
||||||
var messageBitLength = length * 8;
|
const messageBitLength = length * 8;
|
||||||
|
|
||||||
// create byte array with length dividable by 64 (512 bit)
|
// create byte array with length dividable by 64 (512 bit)
|
||||||
var neededLength = Math.ceil((length + 1 + 8) / 64) * 64;
|
const neededLength = Math.ceil((length + 1 + 8) / 64) * 64;
|
||||||
var messageByteArray = new Uint8Array(neededLength);
|
const messageByteArray = new Uint8Array(neededLength);
|
||||||
messageByteArray.set(new Uint8Array(inputByteArray.buffer));
|
messageByteArray.set(new Uint8Array(inputByteArray.buffer));
|
||||||
var view = new DataView(messageByteArray.buffer);
|
const view = new DataView(messageByteArray.buffer);
|
||||||
|
|
||||||
// append 10...000000
|
// append 10...000000
|
||||||
messageByteArray[length] = 0x80;
|
messageByteArray[length] = 0x80;
|
||||||
|
@ -19,8 +19,7 @@
|
|||||||
return lists.get("white").match(url) || settings.get("blockMode", url).startsWith("allow");
|
return lists.get("white").match(url) || settings.get("blockMode", url).startsWith("allow");
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.protect = function protect(window, wrappedWindow, singleCallback, allCallback){
|
function createChangeProperty(window){
|
||||||
|
|
||||||
function changeProperty(object, name, type, changed){
|
function changeProperty(object, name, type, changed){
|
||||||
const descriptor = Object.getOwnPropertyDescriptor(object, name);
|
const descriptor = Object.getOwnPropertyDescriptor(object, name);
|
||||||
const original = descriptor[type];
|
const original = descriptor[type];
|
||||||
@ -49,7 +48,10 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return changeProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
function protectFrameProperties({window, wrappedWindow, changeProperty, singleCallback}){
|
||||||
["HTMLIFrameElement", "HTMLFrameElement"].forEach(function(constructorName){
|
["HTMLIFrameElement", "HTMLFrameElement"].forEach(function(constructorName){
|
||||||
const constructor = window[constructorName];
|
const constructor = window[constructorName];
|
||||||
const wrappedConstructor = wrappedWindow[constructorName];
|
const wrappedConstructor = wrappedWindow[constructorName];
|
||||||
@ -61,7 +63,7 @@
|
|||||||
const originalContentWindowGetter = contentWindowDescriptor.get;
|
const originalContentWindowGetter = contentWindowDescriptor.get;
|
||||||
const contentWindowTemp = {
|
const contentWindowTemp = {
|
||||||
get contentWindow(){
|
get contentWindow(){
|
||||||
var window = originalContentWindowGetter.call(this);
|
const window = originalContentWindowGetter.call(this);
|
||||||
if (window){
|
if (window){
|
||||||
singleCallback(window);
|
singleCallback(window);
|
||||||
}
|
}
|
||||||
@ -80,7 +82,7 @@
|
|||||||
const originalContentDocumentGetter = contentDocumentDescriptor.get;
|
const originalContentDocumentGetter = contentDocumentDescriptor.get;
|
||||||
const contentDocumentTemp = {
|
const contentDocumentTemp = {
|
||||||
get contentDocument(){
|
get contentDocument(){
|
||||||
var document = originalContentDocumentGetter.call(this);
|
const document = originalContentDocumentGetter.call(this);
|
||||||
if (document){
|
if (document){
|
||||||
singleCallback(document.defaultView);
|
singleCallback(document.defaultView);
|
||||||
}
|
}
|
||||||
@ -92,6 +94,9 @@
|
|||||||
window
|
window
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function protectDOMModifications({window, wrappedWindow, changeProperty, allCallback}){
|
||||||
[
|
[
|
||||||
// useless as length could be obtained before the iframe is created and window.frames === window
|
// useless as length could be obtained before the iframe is created and window.frames === window
|
||||||
// {
|
// {
|
||||||
@ -161,31 +166,31 @@
|
|||||||
));
|
));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// MutationObserver to intercept iFrames while generating the DOM.
|
function enableMutationObserver({window, allCallback}){
|
||||||
const observe = function(){
|
const observer = new MutationObserver(allCallback);
|
||||||
var observer = new MutationObserver(allCallback);
|
let observing = false;
|
||||||
var observing = false;
|
function observe(){
|
||||||
function observe(){
|
if (
|
||||||
if (
|
!observing &&
|
||||||
!observing &&
|
window.document
|
||||||
window.document
|
){
|
||||||
){
|
observer.observe(window.document, {subtree: true, childList: true});
|
||||||
observer.observe(window.document, {subtree: true, childList: true});
|
observing = true;
|
||||||
observing = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
observe();
|
}
|
||||||
window.document.addEventListener("DOMContentLoaded", function(){
|
observe();
|
||||||
if (observing){
|
window.document.addEventListener("DOMContentLoaded", function(){
|
||||||
observer.disconnect();
|
if (observing){
|
||||||
observing = false;
|
observer.disconnect();
|
||||||
}
|
observing = false;
|
||||||
});
|
}
|
||||||
return observe;
|
});
|
||||||
}();
|
return observe;
|
||||||
|
}
|
||||||
|
|
||||||
// MutationObserver does not trigger fast enough when document.write is used
|
function protectDocumentWrite({window, wrappedWindow, changeProperty, observe, allCallback}){
|
||||||
const documentWriteDescriptorOnHTMLDocument = Object.getOwnPropertyDescriptor(
|
const documentWriteDescriptorOnHTMLDocument = Object.getOwnPropertyDescriptor(
|
||||||
wrappedWindow.HTMLDocument.prototype,
|
wrappedWindow.HTMLDocument.prototype,
|
||||||
"write"
|
"write"
|
||||||
@ -199,6 +204,7 @@
|
|||||||
documentWriteDescriptorOnHTMLDocument?
|
documentWriteDescriptorOnHTMLDocument?
|
||||||
wrappedWindow.HTMLDocument.prototype:
|
wrappedWindow.HTMLDocument.prototype:
|
||||||
wrappedWindow.Document.prototype,
|
wrappedWindow.Document.prototype,
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
"write", "value", exportFunction(function write(markup){
|
"write", "value", exportFunction(function write(markup){
|
||||||
for (let i = 0, l = arguments.length; i < l; i += 1){
|
for (let i = 0, l = arguments.length; i < l; i += 1){
|
||||||
const str = "" + arguments[i];
|
const str = "" + arguments[i];
|
||||||
@ -234,6 +240,7 @@
|
|||||||
wrappedWindow.HTMLDocument.prototype:
|
wrappedWindow.HTMLDocument.prototype:
|
||||||
wrappedWindow.Document.prototype,
|
wrappedWindow.Document.prototype,
|
||||||
"writeln", "value", exportFunction(
|
"writeln", "value", exportFunction(
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
function writeln(markup){
|
function writeln(markup){
|
||||||
for (let i = 0, l = arguments.length; i < l; i += 1){
|
for (let i = 0, l = arguments.length; i < l; i += 1){
|
||||||
const str = "" + arguments[i];
|
const str = "" + arguments[i];
|
||||||
@ -253,5 +260,21 @@
|
|||||||
window
|
window
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.protect = function protect(window, wrappedWindow, singleCallback, allCallback){
|
||||||
|
const changeProperty = createChangeProperty(window);
|
||||||
|
|
||||||
|
const api = {window, wrappedWindow, changeProperty, singleCallback, allCallback};
|
||||||
|
|
||||||
|
protectFrameProperties(api);
|
||||||
|
|
||||||
|
protectDOMModifications(api);
|
||||||
|
|
||||||
|
// MutationObserver to intercept iFrames while generating the DOM.
|
||||||
|
api.observe = enableMutationObserver(api);
|
||||||
|
|
||||||
|
// MutationObserver does not trigger fast enough when document.write is used
|
||||||
|
protectDocumentWrite(api);
|
||||||
};
|
};
|
||||||
}());
|
}());
|
676
lib/intercept.js
676
lib/intercept.js
@ -41,380 +41,394 @@
|
|||||||
setRandomSupplyByType(settings.rng);
|
setRandomSupplyByType(settings.rng);
|
||||||
});
|
});
|
||||||
|
|
||||||
function getURL(window){
|
function getURL(windowToProcess){
|
||||||
let href;
|
let href;
|
||||||
try {
|
try {
|
||||||
href = window.location.href;
|
href = windowToProcess.location.href;
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
// unable to read location due to SOP
|
// unable to read location due to SOP
|
||||||
// since we are not able to do anything in that case we can allow everything
|
// since we are not able to do anything in that case we can allow everything
|
||||||
return "about:SOP";
|
return "about:SOP";
|
||||||
}
|
}
|
||||||
if (!href || href === "about:blank"){
|
if (!href || href === "about:blank"){
|
||||||
if (window !== window.parent){
|
if (windowToProcess !== windowToProcess.parent){
|
||||||
return getURL(window.parent);
|
return getURL(windowToProcess.parent);
|
||||||
}
|
}
|
||||||
else if (window.opener){
|
else if (windowToProcess.opener){
|
||||||
return getURL(window.opener);
|
return getURL(windowToProcess.opener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return href;
|
return href;
|
||||||
}
|
}
|
||||||
|
const getAllFunctionObjects = function(windowToProcess, changedFunction){
|
||||||
|
return (
|
||||||
|
Array.isArray(changedFunction.object)?
|
||||||
|
changedFunction.object:
|
||||||
|
[changedFunction.object]
|
||||||
|
).map(function(name){
|
||||||
|
if (name){
|
||||||
|
const constructor = getWrapped(windowToProcess)[name];
|
||||||
|
if (constructor){
|
||||||
|
return constructor.prototype;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).concat(
|
||||||
|
changedFunction.objectGetters?
|
||||||
|
changedFunction.objectGetters.map(function(objectGetter){
|
||||||
|
return objectGetter(getWrapped(windowToProcess));
|
||||||
|
}):
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const forEachFunction = function(windowToProcess, callback){
|
||||||
|
apiNames.forEach(function(name){
|
||||||
|
const changedFunction = changedFunctions[name];
|
||||||
|
getAllFunctionObjects(windowToProcess, changedFunction).forEach(function(object){
|
||||||
|
if (object){
|
||||||
|
callback({name, object: object, changedFunction});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const forEachGetter = function(windowToProcess, callback){
|
||||||
|
changedGetters.forEach(function(changedGetter){
|
||||||
|
const name = changedGetter.name;
|
||||||
|
changedGetter.objectGetters.forEach(function(changedGetter){
|
||||||
|
const object = changedGetter(getWrapped(windowToProcess));
|
||||||
|
if (object){
|
||||||
|
callback({name, object, objectGetter: changedGetter});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
scope.preIntercept = function preIntercept({subject: window}, apis){
|
const forEach = function(windowToProcess, callback){
|
||||||
if (!settings.isStillDefault){
|
forEachFunction(windowToProcess, callback);
|
||||||
logging.message("settings already loaded -> no need to pre intercept");
|
forEachGetter(windowToProcess, callback);
|
||||||
scope.intercept({subject: window}, apis);
|
};
|
||||||
|
|
||||||
|
const doRealIntercept = function(windowToProcess, apis, state){
|
||||||
|
if (!state.intercepted){
|
||||||
|
scope.intercept({subject: windowToProcess}, apis);
|
||||||
|
state.intercepted = true;
|
||||||
}
|
}
|
||||||
else {
|
};
|
||||||
logging.message("settings not loaded -> need to pre intercept");
|
const doPreIntercept = function(windowToProcess, apis, state){
|
||||||
let forceLoad = true;
|
const forceLoad = true;
|
||||||
let preIntercepted = false;
|
const originalPropertyDescriptors = {};
|
||||||
let intercepted = false;
|
const undoPreIntercept = function(){
|
||||||
const forEachFunction = function(callback){
|
if (state.preIntercepted){
|
||||||
apiNames.forEach(function(name){
|
state.preIntercepted = false;
|
||||||
const changedFunction = changedFunctions[name];
|
forEach(windowToProcess, function({name, object}){
|
||||||
(
|
const originalPropertyDescriptor = originalPropertyDescriptors[name].get(object);
|
||||||
Array.isArray(changedFunction.object)?
|
if (originalPropertyDescriptor){
|
||||||
changedFunction.object:
|
|
||||||
[changedFunction.object]
|
|
||||||
).map(function(name){
|
|
||||||
if (name){
|
|
||||||
const constructor = getWrapped(window)[name];
|
|
||||||
if (constructor){
|
|
||||||
return constructor.prototype;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}).concat(
|
|
||||||
changedFunction.objectGetters?
|
|
||||||
changedFunction.objectGetters.map(function(objectGetter){
|
|
||||||
return objectGetter(getWrapped(window));
|
|
||||||
}):
|
|
||||||
[]
|
|
||||||
).forEach(function(object){
|
|
||||||
if (object){
|
|
||||||
callback({name, object: object});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
changedGetters.forEach(function(changedGetter){
|
|
||||||
const name = changedGetter.name;
|
|
||||||
changedGetter.objectGetters.forEach(function(objectGetter){
|
|
||||||
const object = objectGetter(getWrapped(window));
|
|
||||||
if (object){
|
|
||||||
callback({name, object});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
let originalPropertyDescriptors = {};
|
|
||||||
const doPreIntercept = function(){
|
|
||||||
if (!preIntercepted){
|
|
||||||
forEachFunction(function({name, object}){
|
|
||||||
const map = originalPropertyDescriptors[name] || new WeakMap();
|
|
||||||
originalPropertyDescriptors[name] = map;
|
|
||||||
|
|
||||||
const originalPropertyDescriptor = Object.getOwnPropertyDescriptor(object, name);
|
|
||||||
if (!originalPropertyDescriptor){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
map.set(object, originalPropertyDescriptor);
|
|
||||||
Object.defineProperty(
|
Object.defineProperty(
|
||||||
object,
|
object,
|
||||||
name,
|
name,
|
||||||
{
|
originalPropertyDescriptor
|
||||||
enumerable: true,
|
|
||||||
configurable: true,
|
|
||||||
get: exportFunction(function(){
|
|
||||||
if (forceLoad){
|
|
||||||
logging.warning("force load the settings. Calling stack:", (new Error()).stack);
|
|
||||||
undoPreIntercept();
|
|
||||||
settings.forceLoad();
|
|
||||||
doRealIntercept();
|
|
||||||
const descriptor = Object.getOwnPropertyDescriptor(object, name);
|
|
||||||
return descriptor.value || descriptor.get.call(this);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
logging.notice("API blocked (%s)", name);
|
|
||||||
const url = getURL(window);
|
|
||||||
if (!url){
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
const error = new Error();
|
|
||||||
apis.notify({
|
|
||||||
url,
|
|
||||||
errorStack: error.stack,
|
|
||||||
messageId: "preBlock",
|
|
||||||
timestamp: new Date(),
|
|
||||||
functionName: name,
|
|
||||||
dataURL: false
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}, window),
|
|
||||||
set: exportFunction(function(){}, window)
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
preIntercepted = true;
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const undoPreIntercept = function(){
|
if (!state.preIntercepted){
|
||||||
if (preIntercepted){
|
forEach(windowToProcess, function({name, object}){
|
||||||
preIntercepted = false;
|
const map = originalPropertyDescriptors[name] || new WeakMap();
|
||||||
forEachFunction(function({name, object}){
|
originalPropertyDescriptors[name] = map;
|
||||||
const originalPropertyDescriptor = originalPropertyDescriptors[name].get(object);
|
|
||||||
if (originalPropertyDescriptor){
|
const originalPropertyDescriptor = Object.getOwnPropertyDescriptor(object, name);
|
||||||
Object.defineProperty(
|
if (!originalPropertyDescriptor){
|
||||||
object,
|
return;
|
||||||
name,
|
|
||||||
originalPropertyDescriptor
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const doRealIntercept = function(){
|
|
||||||
if (!intercepted){
|
|
||||||
scope.intercept({subject: window}, apis);
|
|
||||||
intercepted = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
map.set(object, originalPropertyDescriptor);
|
||||||
|
Object.defineProperty(
|
||||||
|
object,
|
||||||
|
name,
|
||||||
|
{
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
get: exportFunction(function(){
|
||||||
|
if (forceLoad){
|
||||||
|
logging.warning("force load the settings. Calling stack:", (new Error()).stack);
|
||||||
|
undoPreIntercept();
|
||||||
|
settings.forceLoad();
|
||||||
|
doRealIntercept(windowToProcess, apis, state);
|
||||||
|
const descriptor = Object.getOwnPropertyDescriptor(object, name);
|
||||||
|
return descriptor.value || descriptor.get.call(this);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logging.notice("API blocked (%s)", name);
|
||||||
|
const url = getURL(windowToProcess);
|
||||||
|
if (!url){
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
const error = new Error();
|
||||||
|
apis.notify({
|
||||||
|
url,
|
||||||
|
errorStack: error.stack,
|
||||||
|
messageId: "preBlock",
|
||||||
|
timestamp: new Date(),
|
||||||
|
functionName: name,
|
||||||
|
dataURL: false
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}, windowToProcess),
|
||||||
|
set: exportFunction(function(){}, windowToProcess)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
state.preIntercepted = true;
|
||||||
|
}
|
||||||
|
return undoPreIntercept;
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.preIntercept = function preIntercept({subject: windowToProcess}, apis){
|
||||||
|
if (!settings.isStillDefault){
|
||||||
|
logging.message("settings already loaded -> no need to pre intercept");
|
||||||
|
scope.intercept({subject: windowToProcess}, apis);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logging.message("settings not loaded -> need to pre intercept");
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
preIntercepted: false,
|
||||||
|
intercepted: false
|
||||||
};
|
};
|
||||||
|
|
||||||
doPreIntercept();
|
const undoPreIntercept = doPreIntercept(windowToProcess, apis, state);
|
||||||
settings.onloaded(function(){
|
settings.onloaded(function(){
|
||||||
undoPreIntercept();
|
undoPreIntercept();
|
||||||
doRealIntercept();
|
doRealIntercept(windowToProcess, apis, state);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getDataURL(object, prefs){
|
||||||
|
return (
|
||||||
|
object &&
|
||||||
|
prefs("storeImageForInspection") &&
|
||||||
|
prefs("showNotifications")?
|
||||||
|
(
|
||||||
|
object instanceof HTMLCanvasElement?
|
||||||
|
object.toDataURL():
|
||||||
|
(
|
||||||
|
object.canvas instanceof HTMLCanvasElement?
|
||||||
|
object.canvas.toDataURL():
|
||||||
|
false
|
||||||
|
)
|
||||||
|
):
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let extensionID = extension.extensionID;
|
let extensionID = extension.extensionID;
|
||||||
scope.intercept = function intercept({subject: window}, {check, checkStack, ask, notify, prefs}){
|
|
||||||
function getDataURL(object, prefs){
|
|
||||||
return (
|
|
||||||
object &&
|
|
||||||
prefs("storeImageForInspection") &&
|
|
||||||
prefs("showNotifications")?
|
|
||||||
(
|
|
||||||
object instanceof HTMLCanvasElement?
|
|
||||||
object.toDataURL():
|
|
||||||
(
|
|
||||||
object.canvas instanceof HTMLCanvasElement?
|
|
||||||
object.canvas.toDataURL():
|
|
||||||
false
|
|
||||||
)
|
|
||||||
):
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
function generateChecker(name, changedFunction, siteStatus, original){
|
|
||||||
return function checker(callingDepth = 2){
|
|
||||||
const error = new Error();
|
|
||||||
const errorStack = error.stack;
|
|
||||||
|
|
||||||
try {
|
function generateChecker({
|
||||||
// return original if the extension itself requested the function
|
name, changedFunction, siteStatus, original,
|
||||||
if (
|
window: windowToProcess, prefs, notify, checkStack, ask
|
||||||
errorStack
|
}){
|
||||||
.split("\n", callingDepth + 2)[callingDepth + 1]
|
return function checker(callingDepth = 2){
|
||||||
.split("@", callingDepth + 1)[1]
|
const errorStack = (new Error()).stack;
|
||||||
.startsWith(extensionID)
|
|
||||||
){
|
|
||||||
return {allow: true, original, window};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
// stack had an unknown form
|
|
||||||
}
|
|
||||||
if (checkStack(errorStack)){
|
|
||||||
return {allow: true, original, window};
|
|
||||||
}
|
|
||||||
const funcStatus = changedFunction.getStatus(this, siteStatus, prefs);
|
|
||||||
|
|
||||||
const This = this;
|
try {
|
||||||
function notifyCallback(messageId){
|
// return original if the extension itself requested the function
|
||||||
notify({
|
if (
|
||||||
url: getURL(window),
|
errorStack
|
||||||
errorStack,
|
.split("\n", callingDepth + 2)[callingDepth + 1]
|
||||||
messageId,
|
.split("@", callingDepth + 1)[1]
|
||||||
timestamp: new Date(),
|
.startsWith(extensionID)
|
||||||
functionName: name,
|
){
|
||||||
|
return {allow: true, original, window: windowToProcess};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
// stack had an unknown form
|
||||||
|
}
|
||||||
|
if (checkStack(errorStack)){
|
||||||
|
return {allow: true, original, window: windowToProcess};
|
||||||
|
}
|
||||||
|
const funcStatus = changedFunction.getStatus(this, siteStatus, prefs);
|
||||||
|
|
||||||
|
const This = this;
|
||||||
|
function notifyCallback(messageId){
|
||||||
|
notify({
|
||||||
|
url: getURL(windowToProcess),
|
||||||
|
errorStack,
|
||||||
|
messageId,
|
||||||
|
timestamp: new Date(),
|
||||||
|
functionName: name,
|
||||||
|
api: changedFunction.api,
|
||||||
|
dataURL: getDataURL(This, prefs)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const protectedAPIFeatures = prefs("protectedAPIFeatures");
|
||||||
|
if (
|
||||||
|
funcStatus.active &&
|
||||||
|
(
|
||||||
|
!protectedAPIFeatures.hasOwnProperty(name + " @ " + changedFunction.api) ||
|
||||||
|
protectedAPIFeatures[name + " @ " + changedFunction.api]
|
||||||
|
)
|
||||||
|
){
|
||||||
|
if (funcStatus.mode === "ask"){
|
||||||
|
funcStatus.mode = ask({
|
||||||
|
window: windowToProcess,
|
||||||
|
type: changedFunction.type,
|
||||||
api: changedFunction.api,
|
api: changedFunction.api,
|
||||||
dataURL: getDataURL(This, prefs)
|
canvas: this instanceof HTMLCanvasElement?
|
||||||
|
this:
|
||||||
|
(
|
||||||
|
this &&
|
||||||
|
(this.canvas instanceof HTMLCanvasElement)?
|
||||||
|
this.canvas:
|
||||||
|
false
|
||||||
|
),
|
||||||
|
errorStack
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const protectedAPIFeatures = prefs("protectedAPIFeatures");
|
switch (funcStatus.mode){
|
||||||
if (
|
case "allow":
|
||||||
funcStatus.active &&
|
return {allow: true, original, window: windowToProcess};
|
||||||
(
|
case "fake":
|
||||||
!protectedAPIFeatures.hasOwnProperty(name + " @ " + changedFunction.api) ||
|
return {
|
||||||
protectedAPIFeatures[name + " @ " + changedFunction.api]
|
allow: "fake",
|
||||||
)
|
prefs,
|
||||||
){
|
notify: notifyCallback,
|
||||||
if (funcStatus.mode === "ask"){
|
window: windowToProcess,
|
||||||
funcStatus.mode = ask({
|
original
|
||||||
window: window,
|
};
|
||||||
type: changedFunction.type,
|
//case "block":
|
||||||
api: changedFunction.api,
|
default:
|
||||||
canvas: this instanceof HTMLCanvasElement?
|
return {allow: false, notify: notifyCallback};
|
||||||
this:
|
|
||||||
(
|
|
||||||
this &&
|
|
||||||
(this.canvas instanceof HTMLCanvasElement)?
|
|
||||||
this.canvas:
|
|
||||||
false
|
|
||||||
),
|
|
||||||
errorStack
|
|
||||||
});
|
|
||||||
}
|
|
||||||
switch (funcStatus.mode){
|
|
||||||
case "allow":
|
|
||||||
return {allow: true, original, window};
|
|
||||||
case "fake":
|
|
||||||
return {
|
|
||||||
allow: "fake",
|
|
||||||
prefs,
|
|
||||||
notify: notifyCallback,
|
|
||||||
window,
|
|
||||||
original
|
|
||||||
};
|
|
||||||
//case "block":
|
|
||||||
default:
|
|
||||||
return {
|
|
||||||
allow: false,
|
|
||||||
notify: notifyCallback
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
return {allow: true, original, window};
|
else {
|
||||||
}
|
return {allow: true, original, window: windowToProcess};
|
||||||
};
|
}
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const siteStatus = check({url: getURL(window)});
|
function interceptFunctions(windowToProcess, siteStatus, {checkStack, ask, notify, prefs}){
|
||||||
logging.verbose("status for page", window, siteStatus);
|
apiNames.forEach(function(name){
|
||||||
if (siteStatus.mode !== "allow"){
|
const changedFunction = changedFunctions[name];
|
||||||
apiNames.forEach(function(name){
|
const functionStatus = changedFunction.getStatus(undefined, siteStatus, prefs);
|
||||||
const changedFunction = changedFunctions[name];
|
logging.verbose("status for", name, ":", functionStatus);
|
||||||
const functionStatus = changedFunction.getStatus(undefined, siteStatus, prefs);
|
if (functionStatus.active){
|
||||||
logging.verbose("status for", name, ":", functionStatus);
|
getAllFunctionObjects(windowToProcess, changedFunction).forEach(function(object){
|
||||||
if (functionStatus.active){
|
if (object){
|
||||||
(
|
const original = object[name];
|
||||||
Array.isArray(changedFunction.object)?
|
const checker = generateChecker({
|
||||||
changedFunction.object:
|
name, changedFunction, siteStatus, original,
|
||||||
[changedFunction.object]
|
window: windowToProcess, prefs, checkStack, ask, notify
|
||||||
).map(function(name){
|
});
|
||||||
if (name){
|
const descriptor = Object.getOwnPropertyDescriptor(object, name);
|
||||||
const constructor = getWrapped(window)[name];
|
if (descriptor){
|
||||||
if (constructor){
|
if (descriptor.hasOwnProperty("value")){
|
||||||
return constructor.prototype;
|
if (changedFunction.fakeGenerator){
|
||||||
}
|
descriptor.value = exportFunction(
|
||||||
}
|
changedFunction.fakeGenerator(checker, original, windowToProcess),
|
||||||
return false;
|
windowToProcess
|
||||||
}).concat(
|
);
|
||||||
changedFunction.objectGetters?
|
|
||||||
changedFunction.objectGetters.map(function(objectGetter){
|
|
||||||
return objectGetter(getWrapped(window));
|
|
||||||
}):
|
|
||||||
[]
|
|
||||||
).forEach(function(object){
|
|
||||||
if (object){
|
|
||||||
const original = object[name];
|
|
||||||
const checker = generateChecker(name, changedFunction, siteStatus, original);
|
|
||||||
const descriptor = Object.getOwnPropertyDescriptor(object, name);
|
|
||||||
if (descriptor){
|
|
||||||
if (descriptor.hasOwnProperty("value")){
|
|
||||||
if (changedFunction.fakeGenerator){
|
|
||||||
descriptor.value = exportFunction(
|
|
||||||
changedFunction.fakeGenerator(checker, original, window),
|
|
||||||
window
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
descriptor.value = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
descriptor.get = exportFunction(function(){
|
descriptor.value = null;
|
||||||
return exportFunction(
|
|
||||||
changedFunction.fakeGenerator(checker),
|
|
||||||
window
|
|
||||||
);
|
|
||||||
}, window);
|
|
||||||
}
|
|
||||||
Object.defineProperty(object, name, descriptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
changedGetters.forEach(function(changedGetter){
|
|
||||||
const name = changedGetter.name;
|
|
||||||
const functionStatus = changedGetter.getStatus(undefined, siteStatus, prefs);
|
|
||||||
logging.verbose("status for", changedGetter, ":", functionStatus);
|
|
||||||
if (functionStatus.active){
|
|
||||||
changedGetter.objectGetters.forEach(function(objectGetter){
|
|
||||||
const object = objectGetter(getWrapped(window));
|
|
||||||
if (object){
|
|
||||||
const descriptor = Object.getOwnPropertyDescriptor(object, name);
|
|
||||||
if (descriptor && descriptor.hasOwnProperty("get")){
|
|
||||||
const original = descriptor.get;
|
|
||||||
const checker = generateChecker(name, changedGetter, siteStatus, original);
|
|
||||||
const getter = changedGetter.getterGenerator(checker, original, window);
|
|
||||||
descriptor.get = exportFunction(getter, window);
|
|
||||||
|
|
||||||
if (descriptor.hasOwnProperty("set") && changedGetter.setterGenerator){
|
|
||||||
const setter = changedGetter.setterGenerator(window, descriptor.set, prefs);
|
|
||||||
descriptor.set = exportFunction(setter, window);
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(object, name, descriptor);
|
|
||||||
}
|
|
||||||
else if (
|
|
||||||
changedGetter.valueGenerator &&
|
|
||||||
descriptor && descriptor.hasOwnProperty("value")
|
|
||||||
){
|
|
||||||
const protectedAPIFeatures = prefs("protectedAPIFeatures");
|
|
||||||
if (
|
|
||||||
functionStatus.active &&
|
|
||||||
(
|
|
||||||
!protectedAPIFeatures.hasOwnProperty(name + " @ " + changedGetter.api) ||
|
|
||||||
protectedAPIFeatures[name + " @ " + changedGetter.api]
|
|
||||||
)
|
|
||||||
){
|
|
||||||
switch (functionStatus.mode){
|
|
||||||
case "ask": case "block": case "fake":
|
|
||||||
descriptor.value = changedGetter.valueGenerator({
|
|
||||||
mode: functionStatus.mode,
|
|
||||||
original: descriptor.value,
|
|
||||||
notify: function notifyCallback(messageId){
|
|
||||||
notify({
|
|
||||||
url: getURL(window),
|
|
||||||
errorStack: (new Error()).stack,
|
|
||||||
messageId,
|
|
||||||
timestamp: new Date(),
|
|
||||||
functionName: name,
|
|
||||||
api: changedGetter.api
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(object, name, descriptor);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
logging.error("Try to fake non getter property:", changedGetter);
|
descriptor.get = exportFunction(function(){
|
||||||
|
return exportFunction(
|
||||||
|
changedFunction.fakeGenerator(checker),
|
||||||
|
windowToProcess
|
||||||
|
);
|
||||||
|
}, windowToProcess);
|
||||||
|
}
|
||||||
|
Object.defineProperty(object, name, descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function interceptGetters(windowToProcess, siteStatus, {checkStack, ask, notify, prefs}){
|
||||||
|
changedGetters.forEach(function(changedGetter){
|
||||||
|
const name = changedGetter.name;
|
||||||
|
const functionStatus = changedGetter.getStatus(undefined, siteStatus, prefs);
|
||||||
|
logging.verbose("status for", changedGetter, ":", functionStatus);
|
||||||
|
if (functionStatus.active){
|
||||||
|
changedGetter.objectGetters.forEach(function(objectGetter){
|
||||||
|
const object = objectGetter(getWrapped(windowToProcess));
|
||||||
|
if (object){
|
||||||
|
const descriptor = Object.getOwnPropertyDescriptor(object, name);
|
||||||
|
if (descriptor && descriptor.hasOwnProperty("get")){
|
||||||
|
const original = descriptor.get;
|
||||||
|
const checker = generateChecker({
|
||||||
|
name, changedFunction: changedGetter, siteStatus, original,
|
||||||
|
window: windowToProcess, prefs, checkStack, ask, notify
|
||||||
|
});
|
||||||
|
const getter = changedGetter.getterGenerator(checker, original, windowToProcess);
|
||||||
|
descriptor.get = exportFunction(getter, windowToProcess);
|
||||||
|
|
||||||
|
if (descriptor.hasOwnProperty("set") && changedGetter.setterGenerator){
|
||||||
|
const setter = changedGetter.setterGenerator(
|
||||||
|
windowToProcess,
|
||||||
|
descriptor.set,
|
||||||
|
prefs
|
||||||
|
);
|
||||||
|
descriptor.set = exportFunction(setter, windowToProcess);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(object, name, descriptor);
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
changedGetter.valueGenerator &&
|
||||||
|
descriptor && descriptor.hasOwnProperty("value")
|
||||||
|
){
|
||||||
|
const protectedAPIFeatures = prefs("protectedAPIFeatures");
|
||||||
|
if (
|
||||||
|
functionStatus.active &&
|
||||||
|
(
|
||||||
|
!protectedAPIFeatures.hasOwnProperty(name + " @ " + changedGetter.api) ||
|
||||||
|
protectedAPIFeatures[name + " @ " + changedGetter.api]
|
||||||
|
)
|
||||||
|
){
|
||||||
|
switch (functionStatus.mode){
|
||||||
|
case "ask": case "block": case "fake":
|
||||||
|
descriptor.value = changedGetter.valueGenerator({
|
||||||
|
mode: functionStatus.mode,
|
||||||
|
original: descriptor.value,
|
||||||
|
notify: function notifyCallback(messageId){
|
||||||
|
notify({
|
||||||
|
url: getURL(windowToProcess),
|
||||||
|
errorStack: (new Error()).stack,
|
||||||
|
messageId,
|
||||||
|
timestamp: new Date(),
|
||||||
|
functionName: name,
|
||||||
|
api: changedGetter.api
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.defineProperty(object, name, descriptor);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
else {
|
||||||
}
|
logging.error("Try to fake non getter property:", changedGetter);
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
scope.intercept = function intercept({subject: windowToProcess}, apis){
|
||||||
|
const siteStatus = apis.check({url: getURL(windowToProcess)});
|
||||||
|
logging.verbose("status for page", windowToProcess, siteStatus);
|
||||||
|
if (siteStatus.mode !== "allow"){
|
||||||
|
interceptFunctions(windowToProcess, siteStatus, apis);
|
||||||
|
interceptGetters(windowToProcess, siteStatus, apis);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}());
|
}());
|
22
lib/lists.js
22
lib/lists.js
@ -6,7 +6,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -14,11 +14,11 @@
|
|||||||
scope = require.register("./lists", {});
|
scope = require.register("./lists", {});
|
||||||
}
|
}
|
||||||
|
|
||||||
var settings = require("./settings");
|
const settings = require("./settings");
|
||||||
|
|
||||||
|
|
||||||
function getDomainRegExpList(domainList){
|
function getDomainRegExpList(domainList){
|
||||||
var list = domainList
|
const list = domainList
|
||||||
.split(",")
|
.split(",")
|
||||||
.map(function(entry){
|
.map(function(entry){
|
||||||
return entry.replace(/^\s+|\s+$/g, "");
|
return entry.replace(/^\s+|\s+$/g, "");
|
||||||
@ -27,8 +27,8 @@
|
|||||||
return !!entry.length;
|
return !!entry.length;
|
||||||
})
|
})
|
||||||
.map(function(entry){
|
.map(function(entry){
|
||||||
var regExp;
|
let regExp;
|
||||||
var domain = !!entry.match(/^[A-Za-z0-9_.-]+$/);
|
const domain = !!entry.match(/^[A-Za-z0-9_.-]+$/);
|
||||||
if (domain){
|
if (domain){
|
||||||
regExp = new RegExp("(?:^|\\.)" + entry.replace(/([\\+*?[^\]$(){}=!|.])/g, "\\$1") + "\\.?$", "i");
|
regExp = new RegExp("(?:^|\\.)" + entry.replace(/([\\+*?[^\]$(){}=!|.])/g, "\\$1") + "\\.?$", "i");
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
var lists = {
|
const lists = {
|
||||||
white: [],
|
white: [],
|
||||||
sessionWhite: [],
|
sessionWhite: [],
|
||||||
"ignore": [],
|
"ignore": [],
|
||||||
@ -81,9 +81,9 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
function updateStackList(value){
|
function updateStackList(value){
|
||||||
var list;
|
let list;
|
||||||
try {
|
try {
|
||||||
var data = JSON.parse(value);
|
let data = JSON.parse(value);
|
||||||
if (!Array.isArray(data)){
|
if (!Array.isArray(data)){
|
||||||
data = [data];
|
data = [data];
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@
|
|||||||
return typeof entry === "object" && typeof entry.url === "string";
|
return typeof entry === "object" && typeof entry.url === "string";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch(e){
|
catch(error){
|
||||||
list = [];
|
list = [];
|
||||||
}
|
}
|
||||||
list.match = function(stack){
|
list.match = function(stack){
|
||||||
@ -109,13 +109,13 @@
|
|||||||
|
|
||||||
scope.get = function getList(type){
|
scope.get = function getList(type){
|
||||||
if (type === "white"){
|
if (type === "white"){
|
||||||
var combined = lists.white.slice().concat(lists.sessionWhite);
|
const combined = lists.white.slice().concat(lists.sessionWhite);
|
||||||
return addMatchToList(combined);
|
return addMatchToList(combined);
|
||||||
}
|
}
|
||||||
return lists[type];
|
return lists[type];
|
||||||
};
|
};
|
||||||
scope.appendTo = function appendToList(type, entry){
|
scope.appendTo = function appendToList(type, entry){
|
||||||
var oldValue = settings[type + "List"];
|
const oldValue = settings[type + "List"];
|
||||||
return settings.set(type + "List", oldValue + (oldValue? ",": "") + entry).then(function(){
|
return settings.set(type + "List", oldValue + (oldValue? ",": "") + entry).then(function(){
|
||||||
return updateList(type);
|
return updateList(type);
|
||||||
});
|
});
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
/* eslint no-console: off */
|
|
||||||
/* 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;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -17,21 +16,21 @@
|
|||||||
scope.setSettings = function(realSettings){
|
scope.setSettings = function(realSettings){
|
||||||
if (!settings){
|
if (!settings){
|
||||||
settings = realSettings;
|
settings = realSettings;
|
||||||
settings.loaded.then(scope.clearQueue);
|
return settings.loaded.then(scope.clearQueue);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
warning("logging: Settings can only be set once.");
|
warning("logging: Settings can only be set once.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var prefix = "";
|
let prefix = "";
|
||||||
|
|
||||||
function leftPad(str, char, pad){
|
function leftPad(str, char, pad){
|
||||||
str = "" + str;
|
str = "" + str;
|
||||||
return char.repeat(pad - str.length) + str;
|
return char.repeat(pad - str.length) + str;
|
||||||
}
|
}
|
||||||
|
|
||||||
var colors = {
|
const colors = {
|
||||||
1: "color: red",
|
1: "color: red",
|
||||||
25: "color: orange",
|
25: "color: orange",
|
||||||
50: "",
|
50: "",
|
||||||
@ -40,7 +39,7 @@
|
|||||||
999: "background-color: lightgray"
|
999: "background-color: lightgray"
|
||||||
};
|
};
|
||||||
|
|
||||||
var queue = [];
|
let queue = [];
|
||||||
function performLog(level, args, date){
|
function performLog(level, args, date){
|
||||||
if (!date){
|
if (!date){
|
||||||
date = new Date();
|
date = new Date();
|
||||||
@ -50,7 +49,7 @@
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (settings.logLevel >= level){
|
if (settings.logLevel >= level){
|
||||||
var pre = "%c[CanvasBlocker] ";
|
let pre = "%c[CanvasBlocker] ";
|
||||||
if (prefix){
|
if (prefix){
|
||||||
pre += prefix + ": ";
|
pre += prefix + ": ";
|
||||||
}
|
}
|
||||||
@ -71,6 +70,7 @@
|
|||||||
args.unshift(colors[level] || "");
|
args.unshift(colors[level] || "");
|
||||||
args.unshift(pre);
|
args.unshift(pre);
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.log.apply(console, args);
|
console.log.apply(console, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,7 +94,7 @@
|
|||||||
scope.clearQueue = function(){
|
scope.clearQueue = function(){
|
||||||
if (queue.length){
|
if (queue.length){
|
||||||
metaLog("clear logging queue");
|
metaLog("clear logging queue");
|
||||||
var tmp = queue;
|
const tmp = queue;
|
||||||
queue = [];
|
queue = [];
|
||||||
tmp.forEach(function(item){
|
tmp.forEach(function(item){
|
||||||
performLog(item.level, item.args, item.date);
|
performLog(item.level, item.args, item.date);
|
||||||
|
162
lib/main.js
162
lib/main.js
@ -6,25 +6,81 @@
|
|||||||
|
|
||||||
const settings = require("./settings");
|
const settings = require("./settings");
|
||||||
const logging = require("./logging");
|
const logging = require("./logging");
|
||||||
const {error, warning, message, notice, verbose, } = logging;
|
|
||||||
logging.setPrefix("main script");
|
logging.setPrefix("main script");
|
||||||
const persistentRndStorage = require("./persistentRndStorage");
|
const persistentRndStorage = require("./persistentRndStorage");
|
||||||
const notification = require("./notification");
|
const notification = require("./notification");
|
||||||
|
|
||||||
message("start of background script");
|
const registerSettingsContentScript = (function(){
|
||||||
message("waiting for settings to be loaded");
|
let unregisterSettingsContentScript = function(){};
|
||||||
settings.onloaded(function(){
|
let lastRegistering;
|
||||||
notice("everything loaded");
|
return function registerSettingsContentScript(){
|
||||||
|
logging.message("Register content script for the settings.");
|
||||||
|
logging.verbose("Unregister old content script, if present.");
|
||||||
|
unregisterSettingsContentScript();
|
||||||
|
const data = {};
|
||||||
|
settings.forEach(function(def){
|
||||||
|
data[def.name] = def.get();
|
||||||
|
});
|
||||||
|
lastRegistering = data;
|
||||||
|
browser.contentScripts.register({
|
||||||
|
matches: ["<all_urls>"],
|
||||||
|
matchAboutBlank: true,
|
||||||
|
allFrames: true,
|
||||||
|
runAt: "document_start",
|
||||||
|
js: [{
|
||||||
|
code: `(function(settingsData){
|
||||||
|
if (typeof require !== "undefined"){
|
||||||
|
const settings = require("./settings");
|
||||||
|
const logging = require("./logging");
|
||||||
|
if (settings.init(settingsData)){
|
||||||
|
logging.message("Initialized settings by dynamic content script.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logging.warning("Dynamic content script was too late to provide settings.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!window.scope){
|
||||||
|
window.scope = {};
|
||||||
|
}
|
||||||
|
window.scope.settingsData = settingsData;
|
||||||
|
console.warn(
|
||||||
|
"[CanvasBlocker] invalid content script order: require not defined at",
|
||||||
|
window.location.href
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}(${JSON.stringify(data)}))`
|
||||||
|
}]
|
||||||
|
}).then(function(api){
|
||||||
|
logging.verbose("Content script registered.");
|
||||||
|
if (data !== lastRegistering){
|
||||||
|
logging.verbose("Multiple content scripts registered at once. Remove unnecessary one.");
|
||||||
|
api.unregister();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unregisterSettingsContentScript = api.unregister;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
logging.warning("Unable to register content script:", error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
|
||||||
message("perform startup reset");
|
logging.message("start of background script");
|
||||||
|
logging.message("waiting for settings to be loaded");
|
||||||
|
settings.onloaded(function(){
|
||||||
|
logging.notice("everything loaded");
|
||||||
|
|
||||||
|
logging.message("perform startup reset");
|
||||||
settings.startupReset();
|
settings.startupReset();
|
||||||
|
|
||||||
persistentRndStorage.init();
|
persistentRndStorage.init();
|
||||||
|
|
||||||
message("register non port message listener");
|
logging.message("register non port message listener");
|
||||||
browser.runtime.onMessage.addListener(function(data){
|
browser.runtime.onMessage.addListener(function(data){
|
||||||
notice("got data without port", data);
|
logging.notice("got data without port", data);
|
||||||
var keys = Object.keys(data);
|
const keys = Object.keys(data);
|
||||||
if (data["canvasBlocker-new-domain-rnd"]){
|
if (data["canvasBlocker-new-domain-rnd"]){
|
||||||
persistentRndStorage.setDomainData(
|
persistentRndStorage.setDomainData(
|
||||||
data["canvasBlocker-new-domain-rnd"].domain,
|
data["canvasBlocker-new-domain-rnd"].domain,
|
||||||
@ -47,31 +103,34 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notice("pass the message to the tabs");
|
logging.notice("pass the message to the tabs");
|
||||||
browser.tabs.query({}).then(function(tabs){
|
browser.tabs.query({}).then(function(tabs){
|
||||||
tabs.forEach(function(tab){
|
tabs.forEach(function(tab){
|
||||||
browser.tabs.sendMessage(tab.id, data);
|
browser.tabs.sendMessage(tab.id, data);
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
logging.warning("Unable to get browser tabs:", error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
message("register port listener");
|
logging.message("register port listener");
|
||||||
browser.runtime.onConnect.addListener(function(port){
|
browser.runtime.onConnect.addListener(function(port){
|
||||||
notice("got port", port);
|
logging.notice("got port", port);
|
||||||
if (!port.sender.tab){
|
if (!port.sender.tab){
|
||||||
notice("got port without tab = Firefox bug:", port);
|
logging.notice("got port without tab = Firefox bug:", port);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
verbose("send back the tab id", port.sender.tab.id);
|
logging.verbose("send back the tab id", port.sender.tab.id);
|
||||||
verbose("send back the tab cookie store id", port.sender.tab.cookieStoreId);
|
logging.verbose("send back the tab cookie store id", port.sender.tab.cookieStoreId);
|
||||||
verbose("send back the persistent random seeds", persistentRndStorage.persistentRnd);
|
logging.verbose("send back the persistent random seeds", persistentRndStorage.persistentRnd);
|
||||||
port.postMessage({
|
port.postMessage({
|
||||||
tabId: port.sender.tab.id,
|
tabId: port.sender.tab.id,
|
||||||
cookieStoreId: port.sender.tab.cookieStoreId,
|
cookieStoreId: port.sender.tab.cookieStoreId,
|
||||||
persistentRnd: persistentRndStorage.persistentRnd,
|
persistentRnd: persistentRndStorage.persistentRnd,
|
||||||
persistentIncognitoRnd: persistentRndStorage.persistentIncognitoRnd
|
persistentIncognitoRnd: persistentRndStorage.persistentIncognitoRnd
|
||||||
});
|
});
|
||||||
var url = new URL(port.sender.url);
|
const url = new URL(port.sender.url);
|
||||||
port.onMessage.addListener(function(data){
|
port.onMessage.addListener(function(data){
|
||||||
if (data.hasOwnProperty("canvasBlocker-notify")){
|
if (data.hasOwnProperty("canvasBlocker-notify")){
|
||||||
notification.show(port.sender.tab.id, url, data["canvasBlocker-notify"].api);
|
notification.show(port.sender.tab.id, url, data["canvasBlocker-notify"].api);
|
||||||
@ -79,76 +138,25 @@
|
|||||||
if (data.hasOwnProperty("canvasBlocker-clear-page-action")){
|
if (data.hasOwnProperty("canvasBlocker-clear-page-action")){
|
||||||
notification.hide(port.sender.tab.id, url);
|
notification.hide(port.sender.tab.id, url);
|
||||||
}
|
}
|
||||||
verbose("got data", data, "from port", port);
|
logging.verbose("got data", data, "from port", port);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
message("register storage change event listener");
|
logging.message("register storage change event listener");
|
||||||
|
|
||||||
if (browser.contentScripts){
|
if (browser.contentScripts){
|
||||||
let unregister = function(){};
|
registerSettingsContentScript();
|
||||||
let lastRegistering;
|
settings.on("any", registerSettingsContentScript);
|
||||||
const register = function register(){
|
|
||||||
logging.message("Register content script for the settings.");
|
|
||||||
logging.verbose("Unregister old content script, if present.");
|
|
||||||
unregister();
|
|
||||||
var data = {};
|
|
||||||
settings.forEach(function(def){
|
|
||||||
data[def.name] = def.get();
|
|
||||||
});
|
|
||||||
lastRegistering = data;
|
|
||||||
browser.contentScripts.register({
|
|
||||||
matches: ["<all_urls>"],
|
|
||||||
matchAboutBlank: true,
|
|
||||||
allFrames: true,
|
|
||||||
runAt: "document_start",
|
|
||||||
js: [{
|
|
||||||
code: `(function(settingsData){
|
|
||||||
if (typeof require !== "undefined"){
|
|
||||||
const settings = require("./settings");
|
|
||||||
const logging = require("./logging");
|
|
||||||
if (settings.init(settingsData)){
|
|
||||||
logging.message("Initialized settings by dynamic content script.");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
logging.warning("Dynamic content script was too late to provide settings.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!window.scope){
|
|
||||||
window.scope = {};
|
|
||||||
}
|
|
||||||
window.scope.settingsData = settingsData;
|
|
||||||
console.warn(
|
|
||||||
"[CanvasBlocker] invalid content script order: require not defined at",
|
|
||||||
window.location.href
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}(${JSON.stringify(data)}))`
|
|
||||||
}]
|
|
||||||
}).then(function(api){
|
|
||||||
logging.verbose("Content script registered.");
|
|
||||||
if (data !== lastRegistering){
|
|
||||||
logging.verbose("Multiple content scripts registered at once. Remove unnecessary one.");
|
|
||||||
api.unregister();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
unregister = api.unregister;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
register();
|
|
||||||
settings.on("any", register);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
logging.error("Old Firefox does not support browser.contentScript.register()");
|
logging.error("Old Firefox does not support browser.contentScript.register()");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
message("Initialize data-URL workaround.");
|
logging.message("Initialize data-URL workaround.");
|
||||||
require("./dataUrls").init();
|
require("./dataUrls").init();
|
||||||
|
|
||||||
message("Initialize navigator HTTP header protection.");
|
logging.message("Initialize navigator HTTP header protection.");
|
||||||
require("./navigator").init();
|
require("./navigator").init();
|
||||||
|
|
||||||
browser.runtime.onInstalled.addListener(function(details){
|
browser.runtime.onInstalled.addListener(function(details){
|
||||||
@ -165,7 +173,7 @@
|
|||||||
}
|
}
|
||||||
switch (details.reason){
|
switch (details.reason){
|
||||||
case "install":
|
case "install":
|
||||||
message("CanvasBlocker installed");
|
logging.message("CanvasBlocker installed");
|
||||||
openOptions(details.reason);
|
openOptions(details.reason);
|
||||||
browser.tabs.create({
|
browser.tabs.create({
|
||||||
url: browser.extension.getURL("options/presets.html?notice=" + details.reason)
|
url: browser.extension.getURL("options/presets.html?notice=" + details.reason)
|
||||||
@ -174,12 +182,12 @@
|
|||||||
case "update":
|
case "update":
|
||||||
settings.onloaded(function(){
|
settings.onloaded(function(){
|
||||||
if (!settings.dontShowOptionsOnUpdate){
|
if (!settings.dontShowOptionsOnUpdate){
|
||||||
message("CanvasBlocker updated");
|
logging.message("CanvasBlocker updated");
|
||||||
openOptions(details.reason);
|
openOptions(details.reason);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
message("end");
|
logging.message("end");
|
||||||
}());
|
}());
|
||||||
|
@ -96,8 +96,7 @@
|
|||||||
const parentTop = getGlobalOffsetTop(parent) - getGlobalScrollTop(parent);
|
const parentTop = getGlobalOffsetTop(parent) - getGlobalScrollTop(parent);
|
||||||
const parentHeight = parent.offsetHeight;
|
const parentHeight = parent.offsetHeight;
|
||||||
const height = dialog.offsetHeight;
|
const height = dialog.offsetHeight;
|
||||||
const top = Math.max(
|
const top = Math.max(0,
|
||||||
0,
|
|
||||||
Math.min(
|
Math.min(
|
||||||
container.offsetHeight - height,
|
container.offsetHeight - height,
|
||||||
parentTop + parentHeight / 2 - height / 2
|
parentTop + parentHeight / 2 - height / 2
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
scope.setFunctionProperties = function setFunctionProperties(functions, data){
|
scope.setFunctionProperties = function setFunctionProperties(functions, data){
|
||||||
Object.keys(functions).forEach(function(key){
|
Object.keys(functions).forEach(function(key){
|
||||||
var func = functions[key];
|
const func = functions[key];
|
||||||
["type", "api", "getStatus"].forEach(function(property){
|
["type", "api", "getStatus"].forEach(function(property){
|
||||||
if (data[property] && !func[property]){
|
if (data[property] && !func[property]){
|
||||||
func[property] = data[property];
|
func[property] = data[property];
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -12,25 +12,24 @@
|
|||||||
scope = require.register("./modifiedAudioAPI", {});
|
scope = require.register("./modifiedAudioAPI", {});
|
||||||
}
|
}
|
||||||
|
|
||||||
const logging = require("./logging");
|
|
||||||
const {sha256String: hashing} = require("./hash");
|
const {sha256String: hashing} = require("./hash");
|
||||||
const {checkerWrapper} = require("./modifiedAPIFunctions");
|
const {checkerWrapper} = require("./modifiedAPIFunctions");
|
||||||
|
|
||||||
var randomSupply = null;
|
let randomSupply = null;
|
||||||
|
|
||||||
const getAudioFakeRate = function(){
|
const getAudioFakeRate = function(){
|
||||||
const audioFakeRate = {
|
const audioFakeRate = {
|
||||||
"1": function(array){return 1;},
|
"1": function(){return 1;},
|
||||||
"10": function(array){return 10;},
|
"10": function(){return 10;},
|
||||||
"100": function(array){return 100;},
|
"100": function(){return 100;},
|
||||||
"1000": function(array){return 1000;},
|
"1000": function(){return 1000;},
|
||||||
"0.1%": function(array){return array.length / 1000;},
|
"0.1%": function(array){return array.length / 1000;},
|
||||||
"1%": function(array){return array.length / 100;},
|
"1%": function(array){return array.length / 100;},
|
||||||
"10%": function(array){return array.length / 10;},
|
"10%": function(array){return array.length / 10;},
|
||||||
"100%": function(array){return array.length;},
|
"100%": function(array){return array.length;},
|
||||||
};
|
};
|
||||||
return function getAudioFakeRate(array, prefs){
|
return function getAudioFakeRate(array, prefs){
|
||||||
var func = audioFakeRate[prefs("audioFakeRate")];
|
const func = audioFakeRate[prefs("audioFakeRate")];
|
||||||
if (typeof func === "function"){
|
if (typeof func === "function"){
|
||||||
return func(array);
|
return func(array);
|
||||||
}
|
}
|
||||||
@ -66,18 +65,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function forEachIndex(array, prefs, callback){
|
function forEachIndex(array, prefs, callback){
|
||||||
var length = array.length;
|
const length = array.length;
|
||||||
var rate = getAudioFakeRate(array, prefs);
|
const rate = getAudioFakeRate(array, prefs);
|
||||||
var start = 0;
|
let start = 0;
|
||||||
forEachFixedIndex(prefs, function(index){
|
forEachFixedIndex(prefs, function(index){
|
||||||
callback(index, start);
|
callback(index, start);
|
||||||
start += 1;
|
start += 1;
|
||||||
});
|
});
|
||||||
if (start < rate){
|
if (start < rate){
|
||||||
var delta = Math.floor(length / (rate - start));
|
const delta = Math.floor(length / (rate - start));
|
||||||
var indexRng = randomSupply.getIndexRng(1, length - delta * (rate - start - 1), window);
|
const indexRng = randomSupply.getIndexRng(1, length - delta * (rate - start - 1), window);
|
||||||
var offset = indexRng(0);
|
let offset = indexRng(0);
|
||||||
for (var i = start; i < rate; i += 1){
|
for (let i = start; i < rate; i += 1){
|
||||||
callback(offset, i);
|
callback(offset, i);
|
||||||
offset += delta;
|
offset += delta;
|
||||||
}
|
}
|
||||||
@ -88,7 +87,7 @@
|
|||||||
const intCache = Object.create(null);
|
const intCache = Object.create(null);
|
||||||
|
|
||||||
function arrayHasAnyNonZero(array){
|
function arrayHasAnyNonZero(array){
|
||||||
for (var i = 0, l = array.length; i < l; i += 1){
|
for (let i = 0, l = array.length; i < l; i += 1){
|
||||||
if (array[i]){
|
if (array[i]){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -105,9 +104,9 @@
|
|||||||
cached = floatCache[hash];
|
cached = floatCache[hash];
|
||||||
}
|
}
|
||||||
if (!cached){
|
if (!cached){
|
||||||
var rate = getAudioFakeRate(array, prefs);
|
const rate = getAudioFakeRate(array, prefs);
|
||||||
var noiseLevel = getAudioNoiseLevel(prefs);
|
const noiseLevel = getAudioNoiseLevel(prefs);
|
||||||
var rng = randomSupply.getRng(rate, window);
|
const rng = randomSupply.getRng(rate, window);
|
||||||
forEachIndex(array, prefs, function(index, i){
|
forEachIndex(array, prefs, function(index, i){
|
||||||
let value;
|
let value;
|
||||||
if (array[index] !== 0){
|
if (array[index] !== 0){
|
||||||
@ -137,8 +136,8 @@
|
|||||||
cached = intCache[hash];
|
cached = intCache[hash];
|
||||||
}
|
}
|
||||||
if (!cached){
|
if (!cached){
|
||||||
var rate = getAudioFakeRate(array, prefs);
|
const rate = getAudioFakeRate(array, prefs);
|
||||||
var rng = randomSupply.getValueRng(rate, window);
|
const rng = randomSupply.getValueRng(rate, window);
|
||||||
forEachIndex(array, prefs, function(index, i){
|
forEachIndex(array, prefs, function(index, i){
|
||||||
array[index] = rng(array[index], i);
|
array[index] = rng(array[index], i);
|
||||||
});
|
});
|
||||||
@ -171,9 +170,9 @@
|
|||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
return function getFloatFrequencyData(array){
|
return function getFloatFrequencyData(array){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {prefs, notify, window, original} = check;
|
||||||
notify("fakedAudioReadout");
|
notify("fakedAudioReadout");
|
||||||
var ret = original.apply(this, window.Array.from(args));
|
const ret = original.apply(this, window.Array.from(args));
|
||||||
fakeFloat32Array(array, window, prefs);
|
fakeFloat32Array(array, window, prefs);
|
||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
@ -185,9 +184,9 @@
|
|||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
return function getByteFrequencyData(array){
|
return function getByteFrequencyData(array){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {prefs, notify, window, original} = check;
|
||||||
notify("fakedAudioReadout");
|
notify("fakedAudioReadout");
|
||||||
var ret = original.apply(this, window.Array.from(args));
|
const ret = original.apply(this, window.Array.from(args));
|
||||||
fakeUint8Array(array, window, prefs);
|
fakeUint8Array(array, window, prefs);
|
||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
@ -199,9 +198,9 @@
|
|||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
return function getFloatTimeDomainData(array){
|
return function getFloatTimeDomainData(array){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {prefs, notify, window, original} = check;
|
||||||
notify("fakedAudioReadout");
|
notify("fakedAudioReadout");
|
||||||
var ret = original.apply(this, window.Array.from(args));
|
const ret = original.apply(this, window.Array.from(args));
|
||||||
fakeFloat32Array(array, window, prefs);
|
fakeFloat32Array(array, window, prefs);
|
||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
@ -213,9 +212,9 @@
|
|||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
return function getByteTimeDomainData(array){
|
return function getByteTimeDomainData(array){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {prefs, notify, window, original} = check;
|
||||||
notify("fakedAudioReadout");
|
notify("fakedAudioReadout");
|
||||||
var ret = original.apply(this, window.Array.from(args));
|
const ret = original.apply(this, window.Array.from(args));
|
||||||
fakeUint8Array(array, window, prefs);
|
fakeUint8Array(array, window, prefs);
|
||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
@ -225,10 +224,11 @@
|
|||||||
getChannelData: {
|
getChannelData: {
|
||||||
object: ["AudioBuffer"],
|
object: ["AudioBuffer"],
|
||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
return function getChannelData(channel){
|
return function getChannelData(channel){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {prefs, notify, window, original} = check;
|
||||||
var ret = original.apply(this, window.Array.from(args));
|
const ret = original.apply(this, window.Array.from(args));
|
||||||
if (!getChannelDataAlreadyFakedArrays.get(ret)){
|
if (!getChannelDataAlreadyFakedArrays.get(ret)){
|
||||||
notify("fakedAudioReadout");
|
notify("fakedAudioReadout");
|
||||||
fakeFloat32Array(ret, window, prefs);
|
fakeFloat32Array(ret, window, prefs);
|
||||||
@ -242,16 +242,17 @@
|
|||||||
copyFromChannel: {
|
copyFromChannel: {
|
||||||
object: ["AudioBuffer"],
|
object: ["AudioBuffer"],
|
||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
return function copyFromChannel(destination, channelNumber, startInChannel){
|
return function copyFromChannel(destination, channelNumber, startInChannel){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {prefs, notify, window, original} = check;
|
||||||
var channelData = this.getChannelData(channelNumber);
|
const channelData = this.getChannelData(channelNumber);
|
||||||
if (!getChannelDataAlreadyFakedArrays.get(channelData)){
|
if (!getChannelDataAlreadyFakedArrays.get(channelData)){
|
||||||
notify("fakedAudioReadout");
|
notify("fakedAudioReadout");
|
||||||
fakeFloat32Array(channelData, window, prefs);
|
fakeFloat32Array(channelData, window, prefs);
|
||||||
getChannelDataAlreadyFakedArrays.set(channelData, true);
|
getChannelDataAlreadyFakedArrays.set(channelData, true);
|
||||||
}
|
}
|
||||||
var ret = original.apply(this, window.Array.from(args));
|
const ret = original.apply(this, window.Array.from(args));
|
||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -260,11 +261,12 @@
|
|||||||
getFrequencyResponse: {
|
getFrequencyResponse: {
|
||||||
object: ["BiquadFilterNode", "IIRFilterNode"],
|
object: ["BiquadFilterNode", "IIRFilterNode"],
|
||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
return function getFrequencyResponse(frequencyArray, magResponseOutput, phaseResponseOutput){
|
return function getFrequencyResponse(frequencyArray, magResponseOutput, phaseResponseOutput){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {prefs, notify, window, original} = check;
|
||||||
notify("fakedAudioReadout");
|
notify("fakedAudioReadout");
|
||||||
var ret = original.apply(this, window.Array.from(args));
|
const ret = original.apply(this, window.Array.from(args));
|
||||||
fakeFloat32Array(magResponseOutput, window, prefs);
|
fakeFloat32Array(magResponseOutput, window, prefs);
|
||||||
fakeFloat32Array(phaseResponseOutput, window, prefs);
|
fakeFloat32Array(phaseResponseOutput, window, prefs);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
const {copyCanvasToWebgl} = require("./webgl");
|
const {copyCanvasToWebgl} = require("./webgl");
|
||||||
const {getWrapped, checkerWrapper} = require("./modifiedAPIFunctions");
|
const {getWrapped, checkerWrapper} = require("./modifiedAPIFunctions");
|
||||||
|
|
||||||
var randomSupply = null;
|
let randomSupply = null;
|
||||||
|
|
||||||
function getContext(window, canvas){
|
function getContext(window, canvas){
|
||||||
return window.HTMLCanvasElement.prototype.getContext.call(canvas, "2d") ||
|
return window.HTMLCanvasElement.prototype.getContext.call(canvas, "2d") ||
|
||||||
@ -20,8 +20,8 @@
|
|||||||
window.HTMLCanvasElement.prototype.getContext.call(canvas, "experimental-webgl2");
|
window.HTMLCanvasElement.prototype.getContext.call(canvas, "experimental-webgl2");
|
||||||
}
|
}
|
||||||
function getImageData(window, context){
|
function getImageData(window, context){
|
||||||
var imageData;
|
let imageData;
|
||||||
var source;
|
let source;
|
||||||
if ((context.canvas.width || 0) * (context.canvas.height || 0) === 0){
|
if ((context.canvas.width || 0) * (context.canvas.height || 0) === 0){
|
||||||
imageData = new (getWrapped(window).ImageData)(0, 0);
|
imageData = new (getWrapped(window).ImageData)(0, 0);
|
||||||
source = new (getWrapped(window).ImageData)(0, 0);
|
source = new (getWrapped(window).ImageData)(0, 0);
|
||||||
@ -54,24 +54,25 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var canvasCache = Object.create(null);
|
const canvasCache = Object.create(null);
|
||||||
function getFakeCanvas(window, original, prefs){
|
function getFakeCanvas(window, original, prefs){
|
||||||
try {
|
try {
|
||||||
|
let originalDataURL;
|
||||||
if (prefs("useCanvasCache")){
|
if (prefs("useCanvasCache")){
|
||||||
var originalDataURL = original.toDataURL();
|
originalDataURL = original.toDataURL();
|
||||||
var cached = canvasCache[originalDataURL];
|
const cached = canvasCache[originalDataURL];
|
||||||
if (cached){
|
if (cached){
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// original may not be a canvas -> we must not leak an error
|
// original may not be a canvas -> we must not leak an error
|
||||||
var context = getContext(window, original);
|
let context = getContext(window, original);
|
||||||
var {imageData, source} = getImageData(window, context);
|
const {imageData, source} = getImageData(window, context);
|
||||||
var desc = imageData.data;
|
const desc = imageData.data;
|
||||||
var l = desc.length;
|
const l = desc.length;
|
||||||
|
|
||||||
var ignoredColors = {};
|
let ignoredColors = {};
|
||||||
var statistic;
|
let statistic;
|
||||||
if (prefs("ignoreFrequentColors")){
|
if (prefs("ignoreFrequentColors")){
|
||||||
statistic = colorStatistics.compute(source);
|
statistic = colorStatistics.compute(source);
|
||||||
ignoredColors = statistic.getMaxColors(prefs("ignoreFrequentColors"));
|
ignoredColors = statistic.getMaxColors(prefs("ignoreFrequentColors"));
|
||||||
@ -82,10 +83,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var rng = randomSupply.getPixelRng(l, window, ignoredColors);
|
const rng = randomSupply.getPixelRng(l, window, ignoredColors);
|
||||||
var fakeAlphaChannel = prefs("fakeAlphaChannel");
|
const fakeAlphaChannel = prefs("fakeAlphaChannel");
|
||||||
for (var i = 0; i < l; i += 4){
|
for (let i = 0; i < l; i += 4){
|
||||||
var [r, g, b, a] = rng(
|
const [r, g, b, a] = rng(
|
||||||
source[i + 0],
|
source[i + 0],
|
||||||
source[i + 1],
|
source[i + 1],
|
||||||
source[i + 2],
|
source[i + 2],
|
||||||
@ -97,7 +98,7 @@
|
|||||||
desc[i + 2] = b;
|
desc[i + 2] = b;
|
||||||
desc[i + 3] = fakeAlphaChannel? a: source[i + 3];
|
desc[i + 3] = fakeAlphaChannel? a: source[i + 3];
|
||||||
}
|
}
|
||||||
var canvas = original.cloneNode(true);
|
const canvas = original.cloneNode(true);
|
||||||
context = window.HTMLCanvasElement.prototype.getContext.call(canvas, "2d");
|
context = window.HTMLCanvasElement.prototype.getContext.call(canvas, "2d");
|
||||||
context.putImageData(imageData, 0, 0);
|
context.putImageData(imageData, 0, 0);
|
||||||
if (prefs("useCanvasCache")){
|
if (prefs("useCanvasCache")){
|
||||||
@ -106,25 +107,25 @@
|
|||||||
}
|
}
|
||||||
return canvas;
|
return canvas;
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
logging.warning("Error while faking:", e);
|
logging.warning("Error while faking:", error);
|
||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function randomMixImageData(window, imageData1, imageData2){
|
function randomMixImageData(window, imageData1, imageData2){
|
||||||
var data1 = imageData1.data;
|
const data1 = imageData1.data;
|
||||||
var data2 = imageData2.data;
|
const data2 = imageData2.data;
|
||||||
var l = data1.length;
|
const l = data1.length;
|
||||||
if (l === data2.length){
|
if (l === data2.length){
|
||||||
var rng = randomSupply.getPixelRng(l, window, {});
|
const rng = randomSupply.getPixelRng(l, window, {});
|
||||||
|
|
||||||
for (var i = 0; i < l; i += 4){
|
for (let i = 0; i < l; i += 4){
|
||||||
const signR = data1[i + 0] > data2[i + 0]? -1: 1;
|
const signR = data1[i + 0] > data2[i + 0]? -1: 1;
|
||||||
const signG = data1[i + 1] > data2[i + 1]? -1: 1;
|
const signG = data1[i + 1] > data2[i + 1]? -1: 1;
|
||||||
const signB = data1[i + 2] > data2[i + 2]? -1: 1;
|
const signB = data1[i + 2] > data2[i + 2]? -1: 1;
|
||||||
const signA = data1[i + 3] > data2[i + 3]? -1: 1;
|
const signA = data1[i + 3] > data2[i + 3]? -1: 1;
|
||||||
|
|
||||||
var [deltaR, deltaG, deltaB, deltaA] = rng(
|
const [deltaR, deltaG, deltaB, deltaA] = rng(
|
||||||
signR * (data2[i + 0] - data1[i + 0]),
|
signR * (data2[i + 0] - data1[i + 0]),
|
||||||
signG * (data2[i + 1] - data1[i + 1]),
|
signG * (data2[i + 1] - data1[i + 1]),
|
||||||
signB * (data2[i + 2] - data1[i + 2]),
|
signB * (data2[i + 2] - data1[i + 2]),
|
||||||
@ -142,9 +143,9 @@
|
|||||||
|
|
||||||
function canvasSizeShouldBeFaked(canvas, prefs){
|
function canvasSizeShouldBeFaked(canvas, prefs){
|
||||||
if (canvas){
|
if (canvas){
|
||||||
var size = canvas.height * canvas.width;
|
const size = canvas.height * canvas.width;
|
||||||
var maxSize = prefs("maxFakeSize") || Number.POSITIVE_INFINITY;
|
const maxSize = prefs("maxFakeSize") || Number.POSITIVE_INFINITY;
|
||||||
var minSize = prefs("minFakeSize") || 0;
|
const minSize = prefs("minFakeSize") || 0;
|
||||||
return size > minSize && size <= maxSize;
|
return size > minSize && size <= maxSize;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -181,7 +182,98 @@
|
|||||||
scope.setRandomSupply = function(supply){
|
scope.setRandomSupply = function(supply){
|
||||||
randomSupply = supply;
|
randomSupply = supply;
|
||||||
};
|
};
|
||||||
var canvasContextType = new WeakMap();
|
|
||||||
|
|
||||||
|
function getNumber(originalValue, max, index, window){
|
||||||
|
const bitLength = Math.floor(Math.log2(max) + 1);
|
||||||
|
const rng = randomSupply.getBitRng(bitLength, window);
|
||||||
|
let value = 0;
|
||||||
|
for (let i = 0; i < bitLength; i += 1){
|
||||||
|
value <<= 1;
|
||||||
|
value ^= rng(originalValue, index + i);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parameterFakeTypes = {
|
||||||
|
decimal: function(originalValue, definition, window){
|
||||||
|
const int = Math.floor(originalValue);
|
||||||
|
if (int !== originalValue){
|
||||||
|
const decimal = originalValue - int;
|
||||||
|
const rng = randomSupply.getRng(1, window);
|
||||||
|
const newDecimal = decimal * (rng(definition.pname) / 0xFFFFFFFF);
|
||||||
|
return int + newDecimal;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return originalValue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
shift: function(originalValue, definition, window){
|
||||||
|
const value = getNumber(originalValue, definition.max, definition.pname, window);
|
||||||
|
return originalValue >>> value;
|
||||||
|
},
|
||||||
|
"-": function(originalValue, definition, window){
|
||||||
|
const value = getNumber(originalValue, definition.max, definition.pname, window) *
|
||||||
|
(definition.factor || 1);
|
||||||
|
if (value > originalValue){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return originalValue - value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const parameterChangeDefinition = {
|
||||||
|
2928: {name: "DEPTH_RANGE", type: "decimal", isArray: true},
|
||||||
|
3379: {name: "MAX_TEXTURE_SIZE", type: "shift", max: 1},
|
||||||
|
3386: {name: "MAX_VIEWPORT_DIMS", type: "shift", max: 1, isArray: true},
|
||||||
|
32883: {name: "MAX_3D_TEXTURE_SIZE", type: "shift", max: 1},
|
||||||
|
33000: {name: "MAX_ELEMENTS_VERTICES", type: "-", max: 3, factor: 50},
|
||||||
|
33001: {name: "MAX_ELEMENTS_INDICES", type: "-", max: 3, factor: 50},
|
||||||
|
33901: {name: "ALIASED_POINT_SIZE_RANGE", type: "decimal", isArray: true},
|
||||||
|
33902: {name: "ALIASED_LINE_WIDTH_RANGE", type: "decimal", isArray: true},
|
||||||
|
34024: {name: "MAX_RENDERBUFFER_SIZE", type: "shift", max: 1},
|
||||||
|
34045: {name: "MAX_TEXTURE_LOD_BIAS", type: "-", max: 1, factor: 1},
|
||||||
|
34076: {name: "MAX_CUBE_MAP_TEXTURE_SIZE", type: "shift", max: 1},
|
||||||
|
34921: {name: "MAX_VERTEX_ATTRIBS", type: "shift", max: 1},
|
||||||
|
34930: {name: "MAX_TEXTURE_IMAGE_UNITS", type: "shift", max: 1},
|
||||||
|
35071: {name: "MAX_ARRAY_TEXTURE_LAYERS", type: "shift", max: 1},
|
||||||
|
35371: {name: "MAX_VERTEX_UNIFORM_BLOCKS", type: "-", max: 1, factor: 1},
|
||||||
|
35373: {name: "MAX_FRAGMENT_UNIFORM_BLOCKS", type: "-", max: 1, factor: 1},
|
||||||
|
35374: {name: "MAX_COMBINED_UNIFORM_BLOCKS", type: "-", max: 3, factor: 1},
|
||||||
|
35375: {name: "MAX_UNIFORM_BUFFER_BINDINGS", type: "-", max: 3, factor: 1},
|
||||||
|
35376: {name: "MAX_UNIFORM_BLOCK_SIZE", type: "shift", max: 1},
|
||||||
|
35377: {name: "MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS", type: "-", max: 7, factor: 10},
|
||||||
|
35379: {name: "MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS", type: "-", max: 7, factor: 10},
|
||||||
|
35657: {name: "MAX_FRAGMENT_UNIFORM_COMPONENTS", type: "shift", max: 1},
|
||||||
|
35658: {name: "MAX_VERTEX_UNIFORM_COMPONENTS", type: "shift", max: 1},
|
||||||
|
35659: {name: "MAX_VARYING_COMPONENTS", type: "shift", max: 1},
|
||||||
|
35660: {name: "MAX_VERTEX_TEXTURE_IMAGE_UNITS", type: "shift", max: 1},
|
||||||
|
35661: {name: "MAX_COMBINED_TEXTURE_IMAGE_UNITS", type: "-", max: 1, factor: 2},
|
||||||
|
35968: {name: "MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS", type: "shift", max: 1},
|
||||||
|
35978: {name: "MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS", type: "shift", max: 1},
|
||||||
|
36203: {name: "MAX_ELEMENT_INDEX", type: "-", max: 15, factor: 1},
|
||||||
|
36347: {name: "MAX_VERTEX_UNIFORM_VECTORS", type: "shift", max: 1},
|
||||||
|
36348: {name: "MAX_VARYING_VECTORS", type: "shift", max: 1},
|
||||||
|
36349: {name: "MAX_FRAGMENT_UNIFORM_VECTORS", type: "shift", max: 1},
|
||||||
|
37154: {name: "MAX_VERTEX_OUTPUT_COMPONENTS", type: "shift", max: 1},
|
||||||
|
37157: {name: "MAX_FRAGMENT_INPUT_COMPONENTS", type: "shift", max: 1},
|
||||||
|
7936: {name: "VENDOR", fake: function(originalValue, window, prefs){
|
||||||
|
const settingValue = prefs("webGLVendor") || originalValue;
|
||||||
|
return {value: settingValue, faked: settingValue === originalValue};
|
||||||
|
}},
|
||||||
|
7937: {name: "RENDERER", fake: function(originalValue, window, prefs){
|
||||||
|
const settingValue = prefs("webGLRenderer") || originalValue;
|
||||||
|
return {value: settingValue, faked: settingValue === originalValue};
|
||||||
|
}},
|
||||||
|
37445: {name: "UNMASKED_VENDOR_WEBGL", fake: function(originalValue, window, prefs){
|
||||||
|
const settingValue = prefs("webGLUnmaskedVendor") || originalValue;
|
||||||
|
return {value: settingValue, faked: settingValue === originalValue};
|
||||||
|
}},
|
||||||
|
37446: {name: "UNMASKED_RENDERER_WEBGL", fake: function(originalValue, window, prefs){
|
||||||
|
const settingValue = prefs("webGLUnmaskedRenderer") || originalValue;
|
||||||
|
return {value: settingValue, faked: settingValue === originalValue};
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
const canvasContextType = new WeakMap();
|
||||||
// changed functions and their fakes
|
// changed functions and their fakes
|
||||||
scope.changedFunctions = {
|
scope.changedFunctions = {
|
||||||
getContext: {
|
getContext: {
|
||||||
@ -209,9 +301,10 @@
|
|||||||
},
|
},
|
||||||
object: "HTMLCanvasElement",
|
object: "HTMLCanvasElement",
|
||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
return function(context, contextAttributes){
|
return function(context, contextAttributes){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {window, original} = check;
|
||||||
canvasContextType.set(this, context);
|
canvasContextType.set(this, context);
|
||||||
return original.apply(this, window.Array.from(args));
|
return original.apply(this, window.Array.from(args));
|
||||||
});
|
});
|
||||||
@ -225,7 +318,7 @@
|
|||||||
status = Object.create(status);
|
status = Object.create(status);
|
||||||
status.active = protectedPartChecker("readout");
|
status.active = protectedPartChecker("readout");
|
||||||
if (!status.active && protectedPartChecker("input")){
|
if (!status.active && protectedPartChecker("input")){
|
||||||
var contextType = canvasContextType.get(obj);
|
const contextType = canvasContextType.get(obj);
|
||||||
status.active = contextType !== "2d";
|
status.active = contextType !== "2d";
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
@ -234,9 +327,9 @@
|
|||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
return function toDataURL(){
|
return function toDataURL(){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {prefs, notify, window, original} = check;
|
||||||
if (canvasSizeShouldBeFaked(this, prefs)){
|
if (canvasSizeShouldBeFaked(this, prefs)){
|
||||||
var fakeCanvas = getFakeCanvas(window, this, prefs);
|
const fakeCanvas = getFakeCanvas(window, this, prefs);
|
||||||
if (fakeCanvas !== this){
|
if (fakeCanvas !== this){
|
||||||
notify("fakedReadout");
|
notify("fakedReadout");
|
||||||
}
|
}
|
||||||
@ -256,18 +349,19 @@
|
|||||||
status = Object.create(status);
|
status = Object.create(status);
|
||||||
status.active = protectedPartChecker("readout");
|
status.active = protectedPartChecker("readout");
|
||||||
if (!status.active && protectedPartChecker("input")){
|
if (!status.active && protectedPartChecker("input")){
|
||||||
var contextType = canvasContextType.get(obj);
|
const contextType = canvasContextType.get(obj);
|
||||||
status.active = contextType !== "2d";
|
status.active = contextType !== "2d";
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
},
|
},
|
||||||
object: "HTMLCanvasElement",
|
object: "HTMLCanvasElement",
|
||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
return function toBlob(callback){
|
return function toBlob(callback){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {prefs, notify, window, original} = check;
|
||||||
if (canvasSizeShouldBeFaked(this, prefs)){
|
if (canvasSizeShouldBeFaked(this, prefs)){
|
||||||
var fakeCanvas = getFakeCanvas(window, this, prefs);
|
const fakeCanvas = getFakeCanvas(window, this, prefs);
|
||||||
if (fakeCanvas !== this){
|
if (fakeCanvas !== this){
|
||||||
notify("fakedReadout");
|
notify("fakedReadout");
|
||||||
}
|
}
|
||||||
@ -288,18 +382,19 @@
|
|||||||
status = Object.create(status);
|
status = Object.create(status);
|
||||||
status.active = protectedPartChecker("readout");
|
status.active = protectedPartChecker("readout");
|
||||||
if (!status.active && protectedPartChecker("input")){
|
if (!status.active && protectedPartChecker("input")){
|
||||||
var contextType = canvasContextType.get(obj);
|
const contextType = canvasContextType.get(obj);
|
||||||
status.active = contextType !== "2d";
|
status.active = contextType !== "2d";
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
},
|
},
|
||||||
object: "HTMLCanvasElement",
|
object: "HTMLCanvasElement",
|
||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
return function mozGetAsFile(callback){
|
return function mozGetAsFile(callback){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {prefs, notify, window, original} = check;
|
||||||
if (canvasSizeShouldBeFaked(this, prefs)){
|
if (canvasSizeShouldBeFaked(this, prefs)){
|
||||||
var fakeCanvas = getFakeCanvas(window, this, prefs);
|
const fakeCanvas = getFakeCanvas(window, this, prefs);
|
||||||
if (fakeCanvas !== this){
|
if (fakeCanvas !== this){
|
||||||
notify("fakedReadout");
|
notify("fakedReadout");
|
||||||
}
|
}
|
||||||
@ -322,12 +417,13 @@
|
|||||||
},
|
},
|
||||||
object: "CanvasRenderingContext2D",
|
object: "CanvasRenderingContext2D",
|
||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
return function getImageData(sx, sy, sw, sh){
|
return function getImageData(sx, sy, sw, sh){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {prefs, notify, window, original} = check;
|
||||||
if (!this || canvasSizeShouldBeFaked(this.canvas, prefs)){
|
if (!this || canvasSizeShouldBeFaked(this.canvas, prefs)){
|
||||||
var fakeCanvas;
|
let fakeCanvas;
|
||||||
var context = this;
|
let context = this;
|
||||||
if (this && this.canvas) {
|
if (this && this.canvas) {
|
||||||
fakeCanvas = getFakeCanvas(window, this.canvas, prefs);
|
fakeCanvas = getFakeCanvas(window, this.canvas, prefs);
|
||||||
}
|
}
|
||||||
@ -359,12 +455,12 @@
|
|||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
return function isPointInPath(x, y){
|
return function isPointInPath(x, y){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {notify, window, original} = check;
|
||||||
var rng = randomSupply.getValueRng(1, window);
|
const rng = randomSupply.getValueRng(1, window);
|
||||||
var originalValue = original.apply(this, window.Array.from(args));
|
const originalValue = original.apply(this, window.Array.from(args));
|
||||||
if ((typeof originalValue) === "boolean"){
|
if ((typeof originalValue) === "boolean"){
|
||||||
notify("fakedReadout");
|
notify("fakedReadout");
|
||||||
var index = x + this.width * y;
|
const index = x + this.width * y;
|
||||||
return original.call(this, rng(x, index), rng(y, index), args[2]);
|
return original.call(this, rng(x, index), rng(y, index), args[2]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -386,9 +482,9 @@
|
|||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
return function isPointInStroke(x, y){
|
return function isPointInStroke(x, y){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {notify, window, original} = check;
|
||||||
var rng = randomSupply.getValueRng(1, window);
|
const rng = randomSupply.getValueRng(1, window);
|
||||||
var originalValue = original.apply(this, window.Array.from(args));
|
const originalValue = original.apply(this, window.Array.from(args));
|
||||||
if ((typeof originalValue) === "boolean"){
|
if ((typeof originalValue) === "boolean"){
|
||||||
notify("fakedReadout");
|
notify("fakedReadout");
|
||||||
if (x instanceof window.Path2D){
|
if (x instanceof window.Path2D){
|
||||||
@ -420,22 +516,23 @@
|
|||||||
},
|
},
|
||||||
object: "CanvasRenderingContext2D",
|
object: "CanvasRenderingContext2D",
|
||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
return function fillText(str, x, y){
|
return function fillText(str, x, y){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {prefs, notify, window, original} = check;
|
||||||
if (!this || canvasSizeShouldBeFaked(this.canvas, prefs)){
|
if (!this || canvasSizeShouldBeFaked(this.canvas, prefs)){
|
||||||
notify("fakedInput");
|
notify("fakedInput");
|
||||||
var oldImageData;
|
let oldImageData;
|
||||||
try {
|
try {
|
||||||
// "this" is not trustable - it may be not a context
|
// "this" is not trustable - it may be not a context
|
||||||
oldImageData = getImageData(window, this).imageData;
|
oldImageData = getImageData(window, this).imageData;
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
// nothing to do here
|
// nothing to do here
|
||||||
}
|
}
|
||||||
// if "this" is not a correct context the next line will throw an error
|
// if "this" is not a correct context the next line will throw an error
|
||||||
var ret = original.apply(this, window.Array.from(args));
|
const ret = original.apply(this, window.Array.from(args));
|
||||||
var newImageData = getImageData(window, this).imageData;
|
const newImageData = getImageData(window, this).imageData;
|
||||||
this.putImageData(randomMixImageData(window, oldImageData, newImageData), 0, 0);
|
this.putImageData(randomMixImageData(window, oldImageData, newImageData), 0, 0);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -456,22 +553,23 @@
|
|||||||
},
|
},
|
||||||
object: "CanvasRenderingContext2D",
|
object: "CanvasRenderingContext2D",
|
||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
return function strokeText(str, x, y){
|
return function strokeText(str, x, y){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {prefs, notify, window, original} = check;
|
||||||
if (!this || canvasSizeShouldBeFaked(this.canvas, prefs)){
|
if (!this || canvasSizeShouldBeFaked(this.canvas, prefs)){
|
||||||
notify("fakedInput");
|
notify("fakedInput");
|
||||||
var oldImageData;
|
let oldImageData;
|
||||||
try {
|
try {
|
||||||
// "this" is not trustable - it may be not a context
|
// "this" is not trustable - it may be not a context
|
||||||
oldImageData = getImageData(window, this).imageData;
|
oldImageData = getImageData(window, this).imageData;
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
// nothing to do here
|
// nothing to do here
|
||||||
}
|
}
|
||||||
// if "this" is not a correct context the next line will throw an error
|
// if "this" is not a correct context the next line will throw an error
|
||||||
var ret = original.apply(this, window.Array.from(args));
|
const ret = original.apply(this, window.Array.from(args));
|
||||||
var newImageData = getImageData(window, this).imageData;
|
const newImageData = getImageData(window, this).imageData;
|
||||||
this.putImageData(randomMixImageData(window, oldImageData, newImageData), 0, 0);
|
this.putImageData(randomMixImageData(window, oldImageData, newImageData), 0, 0);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -492,13 +590,14 @@
|
|||||||
},
|
},
|
||||||
object: ["WebGLRenderingContext", "WebGL2RenderingContext"],
|
object: ["WebGLRenderingContext", "WebGL2RenderingContext"],
|
||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
return function readPixels(x, y, width, height, format, type, pixels){ // eslint-disable-line max-params
|
// eslint-disable-next-line max-params, no-unused-vars
|
||||||
|
return function readPixels(x, y, width, height, format, type, pixels){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {prefs, notify, window, original} = check;
|
||||||
if (!this || canvasSizeShouldBeFaked(this.canvas, prefs)){
|
if (!this || canvasSizeShouldBeFaked(this.canvas, prefs)){
|
||||||
notify("fakedReadout");
|
notify("fakedReadout");
|
||||||
var fakeCanvas = getFakeCanvas(window, this.canvas, prefs);
|
const fakeCanvas = getFakeCanvas(window, this.canvas, prefs);
|
||||||
var {context} = copyCanvasToWebgl(
|
const {context} = copyCanvasToWebgl(
|
||||||
window,
|
window,
|
||||||
fakeCanvas,
|
fakeCanvas,
|
||||||
this instanceof window.WebGLRenderingContext? "webgl": "webgl2"
|
this instanceof window.WebGLRenderingContext? "webgl": "webgl2"
|
||||||
@ -522,111 +621,22 @@
|
|||||||
},
|
},
|
||||||
object: ["WebGLRenderingContext", "WebGL2RenderingContext"],
|
object: ["WebGLRenderingContext", "WebGL2RenderingContext"],
|
||||||
fakeGenerator: function(checker){
|
fakeGenerator: function(checker){
|
||||||
function getNumber(originalValue, max, index, window){
|
Object.keys(parameterChangeDefinition).forEach(function(parameterName){
|
||||||
const bitLength = Math.floor(Math.log2(max) + 1);
|
const definition = parameterChangeDefinition[parameterName];
|
||||||
const rng = randomSupply.getBitRng(bitLength, window);
|
|
||||||
let value = 0;
|
|
||||||
for (let i = 0; i < bitLength; i += 1){
|
|
||||||
value <<= 1;
|
|
||||||
value ^= rng(originalValue, index + i);
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
const types = {
|
|
||||||
decimal: function(originalValue, definition, window){
|
|
||||||
const int = Math.floor(originalValue);
|
|
||||||
if (int !== originalValue){
|
|
||||||
const decimal = originalValue - int;
|
|
||||||
const rng = randomSupply.getRng(1, window);
|
|
||||||
const newDecimal = decimal * (rng(definition.pname) / 0xFFFFFFFF);
|
|
||||||
return int + newDecimal;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return originalValue;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
shift: function(originalValue, definition, window){
|
|
||||||
const value = getNumber(originalValue, definition.max, definition.pname, window);
|
|
||||||
return originalValue >>> value;
|
|
||||||
},
|
|
||||||
"-": function(originalValue, definition, window){
|
|
||||||
const value = getNumber(originalValue, definition.max, definition.pname, window) *
|
|
||||||
(definition.factor || 1);
|
|
||||||
if (value > originalValue){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return originalValue - value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const changeDefinition = {
|
|
||||||
2928: {name: "DEPTH_RANGE", type: "decimal", isArray: true},
|
|
||||||
3379: {name: "MAX_TEXTURE_SIZE", type: "shift", max: 1},
|
|
||||||
3386: {name: "MAX_VIEWPORT_DIMS", type: "shift", max: 1, isArray: true},
|
|
||||||
32883: {name: "MAX_3D_TEXTURE_SIZE", type: "shift", max: 1},
|
|
||||||
33000: {name: "MAX_ELEMENTS_VERTICES", type: "-", max: 3, factor: 50},
|
|
||||||
33001: {name: "MAX_ELEMENTS_INDICES", type: "-", max: 3, factor: 50},
|
|
||||||
33901: {name: "ALIASED_POINT_SIZE_RANGE", type: "decimal", isArray: true},
|
|
||||||
33902: {name: "ALIASED_LINE_WIDTH_RANGE", type: "decimal", isArray: true},
|
|
||||||
34024: {name: "MAX_RENDERBUFFER_SIZE", type: "shift", max: 1},
|
|
||||||
34045: {name: "MAX_TEXTURE_LOD_BIAS", type: "-", max: 1, factor: 1},
|
|
||||||
34076: {name: "MAX_CUBE_MAP_TEXTURE_SIZE", type: "shift", max: 1},
|
|
||||||
34921: {name: "MAX_VERTEX_ATTRIBS", type: "shift", max: 1},
|
|
||||||
34930: {name: "MAX_TEXTURE_IMAGE_UNITS", type: "shift", max: 1},
|
|
||||||
35071: {name: "MAX_ARRAY_TEXTURE_LAYERS", type: "shift", max: 1},
|
|
||||||
35371: {name: "MAX_VERTEX_UNIFORM_BLOCKS", type: "-", max: 1, factor: 1},
|
|
||||||
35373: {name: "MAX_FRAGMENT_UNIFORM_BLOCKS", type: "-", max: 1, factor: 1},
|
|
||||||
35374: {name: "MAX_COMBINED_UNIFORM_BLOCKS", type: "-", max: 3, factor: 1},
|
|
||||||
35375: {name: "MAX_UNIFORM_BUFFER_BINDINGS", type: "-", max: 3, factor: 1},
|
|
||||||
35376: {name: "MAX_UNIFORM_BLOCK_SIZE", type: "shift", max: 1},
|
|
||||||
35377: {name: "MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS", type: "-", max: 7, factor: 10},
|
|
||||||
35379: {name: "MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS", type: "-", max: 7, factor: 10},
|
|
||||||
35657: {name: "MAX_FRAGMENT_UNIFORM_COMPONENTS", type: "shift", max: 1},
|
|
||||||
35658: {name: "MAX_VERTEX_UNIFORM_COMPONENTS", type: "shift", max: 1},
|
|
||||||
35659: {name: "MAX_VARYING_COMPONENTS", type: "shift", max: 1},
|
|
||||||
35660: {name: "MAX_VERTEX_TEXTURE_IMAGE_UNITS", type: "shift", max: 1},
|
|
||||||
35661: {name: "MAX_COMBINED_TEXTURE_IMAGE_UNITS", type: "-", max: 1, factor: 2},
|
|
||||||
35968: {name: "MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS", type: "shift", max: 1},
|
|
||||||
35978: {name: "MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS", type: "shift", max: 1},
|
|
||||||
36203: {name: "MAX_ELEMENT_INDEX", type: "-", max: 15, factor: 1},
|
|
||||||
36347: {name: "MAX_VERTEX_UNIFORM_VECTORS", type: "shift", max: 1},
|
|
||||||
36348: {name: "MAX_VARYING_VECTORS", type: "shift", max: 1},
|
|
||||||
36349: {name: "MAX_FRAGMENT_UNIFORM_VECTORS", type: "shift", max: 1},
|
|
||||||
37154: {name: "MAX_VERTEX_OUTPUT_COMPONENTS", type: "shift", max: 1},
|
|
||||||
37157: {name: "MAX_FRAGMENT_INPUT_COMPONENTS", type: "shift", max: 1},
|
|
||||||
7936: {name: "VENDOR", fake: function(originalValue, window, prefs){
|
|
||||||
const settingValue = prefs("webGLVendor") || originalValue;
|
|
||||||
return {value: settingValue, faked: settingValue === originalValue};
|
|
||||||
}},
|
|
||||||
7937: {name: "RENDERER", fake: function(originalValue, window, prefs){
|
|
||||||
const settingValue = prefs("webGLRenderer") || originalValue;
|
|
||||||
return {value: settingValue, faked: settingValue === originalValue};
|
|
||||||
}},
|
|
||||||
37445: {name: "UNMASKED_VENDOR_WEBGL", fake: function(originalValue, window, prefs){
|
|
||||||
const settingValue = prefs("webGLUnmaskedVendor") || originalValue;
|
|
||||||
return {value: settingValue, faked: settingValue === originalValue};
|
|
||||||
}},
|
|
||||||
37446: {name: "UNMASKED_RENDERER_WEBGL", fake: function(originalValue, window, prefs){
|
|
||||||
const settingValue = prefs("webGLUnmaskedRenderer") || originalValue;
|
|
||||||
return {value: settingValue, faked: settingValue === originalValue};
|
|
||||||
}}
|
|
||||||
};
|
|
||||||
const parameterNames = Object.keys(changeDefinition);
|
|
||||||
parameterNames.forEach(function(parameterName){
|
|
||||||
const definition = changeDefinition[parameterName];
|
|
||||||
definition.pname = parameterName;
|
definition.pname = parameterName;
|
||||||
if (!definition.fake){
|
if (!definition.fake){
|
||||||
definition.fake = definition.isArray?
|
definition.fake = definition.isArray?
|
||||||
function fake(originalValue, window){
|
function fake(originalValue, window){
|
||||||
let faked = false;
|
let faked = false;
|
||||||
let fakedValue = [];
|
let fakedValue = [];
|
||||||
for (var i = 0; i < originalValue.length; i += 1){
|
for (let i = 0; i < originalValue.length; i += 1){
|
||||||
fakedValue[i] = types[this.type](originalValue[i], this, window);
|
fakedValue[i] = parameterFakeTypes[this.type](originalValue[i], this, window);
|
||||||
faked |= originalValue[i] === fakedValue[i];
|
faked |= originalValue[i] === fakedValue[i];
|
||||||
originalValue[i] = fakedValue[i];
|
originalValue[i] = fakedValue[i];
|
||||||
}
|
}
|
||||||
this.fake = function(originalValue){
|
this.fake = function(originalValue){
|
||||||
if (faked){
|
if (faked){
|
||||||
for (var i = 0; i < originalValue.length; i += 1){
|
for (let i = 0; i < originalValue.length; i += 1){
|
||||||
originalValue[i] = fakedValue[i];
|
originalValue[i] = fakedValue[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -641,7 +651,7 @@
|
|||||||
};
|
};
|
||||||
}:
|
}:
|
||||||
function fake(originalValue, window){
|
function fake(originalValue, window){
|
||||||
let value = types[this.type](originalValue, this, window);
|
let value = parameterFakeTypes[this.type](originalValue, this, window);
|
||||||
let faked = value === originalValue;
|
let faked = value === originalValue;
|
||||||
this.fake = function(){
|
this.fake = function(){
|
||||||
return {value, faked};
|
return {value, faked};
|
||||||
@ -652,10 +662,10 @@
|
|||||||
});
|
});
|
||||||
return function getParameter(pname){
|
return function getParameter(pname){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
var {prefs, notify, window, original} = check;
|
const {prefs, notify, window, original} = check;
|
||||||
const originalValue = original.apply(this, window.Array.from(args));
|
const originalValue = original.apply(this, window.Array.from(args));
|
||||||
if (changeDefinition[pname]){
|
if (parameterChangeDefinition[pname]){
|
||||||
const definition = changeDefinition[pname];
|
const definition = parameterChangeDefinition[pname];
|
||||||
const {value, faked} = definition.fake(originalValue, window, prefs);
|
const {value, faked} = definition.fake(originalValue, window, prefs);
|
||||||
if (faked){
|
if (faked){
|
||||||
notify("fakedReadout");
|
notify("fakedReadout");
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -23,7 +23,7 @@
|
|||||||
const temp = eval(`({
|
const temp = eval(`({
|
||||||
get ${property}(){
|
get ${property}(){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
const {prefs, notify, window, original} = check;
|
const {notify, window, original} = check;
|
||||||
const originalValue = original.apply(this, window.Array.from(args));
|
const originalValue = original.apply(this, window.Array.from(args));
|
||||||
const returnValue = navigator.getNavigatorValue("${property}");
|
const returnValue = navigator.getNavigatorValue("${property}");
|
||||||
if (originalValue !== returnValue){
|
if (originalValue !== returnValue){
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -177,7 +177,7 @@
|
|||||||
const temp = {
|
const temp = {
|
||||||
get availLeft(){
|
get availLeft(){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
const {prefs, notify, window, original} = check;
|
const {notify, window, original} = check;
|
||||||
const originalValue = original.apply(this, window.Array.from(args));
|
const originalValue = original.apply(this, window.Array.from(args));
|
||||||
if (originalValue !== 0){
|
if (originalValue !== 0){
|
||||||
notify("fakedScreenReadout");
|
notify("fakedScreenReadout");
|
||||||
@ -196,7 +196,7 @@
|
|||||||
const temp = {
|
const temp = {
|
||||||
get availTop(){
|
get availTop(){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
const {prefs, notify, window, original} = check;
|
const {notify, window, original} = check;
|
||||||
const originalValue = original.apply(this, window.Array.from(args));
|
const originalValue = original.apply(this, window.Array.from(args));
|
||||||
if (originalValue !== 0){
|
if (originalValue !== 0){
|
||||||
notify("fakedScreenReadout");
|
notify("fakedScreenReadout");
|
||||||
@ -215,7 +215,7 @@
|
|||||||
const temp = {
|
const temp = {
|
||||||
get outerWidth(){
|
get outerWidth(){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
const {prefs, notify, window, original} = check;
|
const {notify, window, original} = check;
|
||||||
const originalValue = original.apply(this, window.Array.from(args));
|
const originalValue = original.apply(this, window.Array.from(args));
|
||||||
const returnValue = window.innerWidth;
|
const returnValue = window.innerWidth;
|
||||||
if (originalValue !== returnValue){
|
if (originalValue !== returnValue){
|
||||||
@ -235,7 +235,7 @@
|
|||||||
const temp = {
|
const temp = {
|
||||||
get outerHeight(){
|
get outerHeight(){
|
||||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||||
const {prefs, notify, window, original} = check;
|
const {notify, window, original} = check;
|
||||||
const originalValue = original.apply(this, window.Array.from(args));
|
const originalValue = original.apply(this, window.Array.from(args));
|
||||||
const returnValue = window.innerHeight;
|
const returnValue = window.innerHeight;
|
||||||
if (originalValue !== returnValue){
|
if (originalValue !== returnValue){
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@
|
|||||||
settings.protectedAPIFeatures["userAgent @ navigator"]
|
settings.protectedAPIFeatures["userAgent @ navigator"]
|
||||||
)
|
)
|
||||||
){
|
){
|
||||||
for (var header of details.requestHeaders){
|
for (let header of details.requestHeaders){
|
||||||
if (header.name.toLowerCase() === "user-agent"){
|
if (header.name.toLowerCase() === "user-agent"){
|
||||||
header.value = getValue("userAgent");
|
header.value = getValue("userAgent");
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -170,6 +170,9 @@
|
|||||||
tabs.forEach(function(tab){
|
tabs.forEach(function(tab){
|
||||||
browser.pageAction.hide(tab.id);
|
browser.pageAction.hide(tab.id);
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
logging.warning("Unable to get browser tabs:", error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -188,6 +191,9 @@
|
|||||||
text: ""
|
text: ""
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
logging.warning("Unable to get browser tabs:", error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
scope.persistentRnd = Object.create(null);
|
scope.persistentRnd = Object.create(null);
|
||||||
scope.persistentIncognitoRnd = Object.create(null);
|
scope.persistentIncognitoRnd = Object.create(null);
|
||||||
|
let clearTimeout;
|
||||||
scope.init = function init(){
|
scope.init = function init(){
|
||||||
logging.message("initializing persistent rng storage");
|
logging.message("initializing persistent rng storage");
|
||||||
|
|
||||||
@ -26,8 +27,8 @@
|
|||||||
if (settings.storePersistentRnd){
|
if (settings.storePersistentRnd){
|
||||||
try {
|
try {
|
||||||
let storedData = JSON.parse(settings.persistentRndStorage);
|
let storedData = JSON.parse(settings.persistentRndStorage);
|
||||||
for (var domain in storedData){
|
for (let domain in storedData){
|
||||||
var value = storedData[domain];
|
const value = storedData[domain];
|
||||||
if (
|
if (
|
||||||
Array.isArray(value) &&
|
Array.isArray(value) &&
|
||||||
value.length === 128 &&
|
value.length === 128 &&
|
||||||
@ -39,7 +40,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
// JSON is not valid -> ignore it
|
// JSON is not valid -> ignore it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,7 +75,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getInterval = function(){
|
const getInterval = function(){
|
||||||
var units = {
|
const units = {
|
||||||
seconds: 1000,
|
seconds: 1000,
|
||||||
minutes: 60 * 1000,
|
minutes: 60 * 1000,
|
||||||
hours: 60 * 60 * 1000,
|
hours: 60 * 60 * 1000,
|
||||||
@ -95,18 +96,20 @@
|
|||||||
})){
|
})){
|
||||||
clearIncognito();
|
clearIncognito();
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
logging.warning("Unable to get browser windows:", error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let clearTimeout;
|
|
||||||
function registerTimeout(){
|
function registerTimeout(){
|
||||||
var interval = getInterval();
|
const interval = getInterval();
|
||||||
if (interval > 0){
|
if (interval > 0){
|
||||||
var timeout = settings.lastPersistentRndClearing + interval - Date.now();
|
const timeout = settings.lastPersistentRndClearing + interval - Date.now();
|
||||||
logging.message("registering persistent rng data clearing timeout. Clearing in ", timeout, "ms");
|
logging.message("registering persistent rng data clearing timeout. Clearing in ", timeout, "ms");
|
||||||
if (timeout > 1073741824){
|
if (timeout > 1073741824){
|
||||||
// window.setTimeout can only handle delays up to 32 bit.
|
// window.setTimeout can only handle delays up to 32 bit.
|
||||||
// Therefore we repeat the registering afert 2^30 = 1073741824 seconds
|
// Therefore we repeat the registering after 2^30 = 1073741824 seconds
|
||||||
clearTimeout = window.setTimeout(registerTimeout, 1073741824);
|
clearTimeout = window.setTimeout(registerTimeout, 1073741824);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -119,6 +122,9 @@
|
|||||||
tabs.forEach(function(tab){
|
tabs.forEach(function(tab){
|
||||||
browser.tabs.sendMessage(tab.id, data);
|
browser.tabs.sendMessage(tab.id, data);
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
logging.warning("Unable to get browser tabs:", error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function clearIncognito(){
|
function clearIncognito(){
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -15,7 +15,6 @@
|
|||||||
const rngTemplate = {
|
const rngTemplate = {
|
||||||
getBitRng: function(length, window){
|
getBitRng: function(length, window){
|
||||||
const rng = this.getRng(Math.ceil(length / 32), window);
|
const rng = this.getRng(Math.ceil(length / 32), window);
|
||||||
let bitIndex = 32;
|
|
||||||
let rnd = 0;
|
let rnd = 0;
|
||||||
let mask = 0xffffffff * 2;
|
let mask = 0xffffffff * 2;
|
||||||
return function(value, i){
|
return function(value, i){
|
||||||
@ -38,20 +37,21 @@
|
|||||||
getValueRng: function(length, window){
|
getValueRng: function(length, window){
|
||||||
const rng = this.getBitRng(length, window);
|
const rng = this.getBitRng(length, window);
|
||||||
return function(value, i){
|
return function(value, i){
|
||||||
var rnd = rng(value, i);
|
const rnd = rng(value, i);
|
||||||
|
|
||||||
// XOR the last bit to alter it... or not
|
// XOR the last bit to alter it... or not
|
||||||
return value ^ (rnd & 0x01);
|
return value ^ (rnd & 0x01);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getPixelRng: function(length, window, ignoredColors){
|
getPixelRng: function(length, window, ignoredColors){
|
||||||
var rng = this.getValueRng(length, window);
|
const rng = this.getValueRng(length, window);
|
||||||
return function(r, g, b, a, i){ // eslint-disable-line max-params
|
// eslint-disable-next-line max-params
|
||||||
var index = String.fromCharCode(r, g, b, a);
|
return function(r, g, b, a, i){
|
||||||
|
const index = String.fromCharCode(r, g, b, a);
|
||||||
if (ignoredColors[index]){
|
if (ignoredColors[index]){
|
||||||
return [r, g, b, a];
|
return [r, g, b, a];
|
||||||
}
|
}
|
||||||
var baseIndex = i * 4;
|
const baseIndex = i * 4;
|
||||||
return [
|
return [
|
||||||
rng(r, baseIndex + 0),
|
rng(r, baseIndex + 0),
|
||||||
rng(g, baseIndex + 1),
|
rng(g, baseIndex + 1),
|
||||||
@ -81,7 +81,7 @@
|
|||||||
return window.location.host;
|
return window.location.host;
|
||||||
}
|
}
|
||||||
|
|
||||||
var persistentRnd = Object.create(null);
|
let persistentRnd = Object.create(null);
|
||||||
let cookieStoreId = false;
|
let cookieStoreId = false;
|
||||||
settings.onloaded(function(){
|
settings.onloaded(function(){
|
||||||
try {
|
try {
|
||||||
@ -90,8 +90,8 @@
|
|||||||
settings.persistentIncognitoRndStorage:
|
settings.persistentIncognitoRndStorage:
|
||||||
settings.persistentRndStorage
|
settings.persistentRndStorage
|
||||||
);
|
);
|
||||||
for (var domain in storedData){
|
for (let domain in storedData){
|
||||||
var value = storedData[domain];
|
const value = storedData[domain];
|
||||||
if (
|
if (
|
||||||
Array.isArray(value) &&
|
Array.isArray(value) &&
|
||||||
value.length === 128 &&
|
value.length === 128 &&
|
||||||
@ -103,7 +103,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
// JSON is not valid -> ignore it
|
// JSON is not valid -> ignore it
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -111,7 +111,7 @@
|
|||||||
|
|
||||||
extension.message.on(function(data){
|
extension.message.on(function(data){
|
||||||
if (data["canvasBlocker-set-domain-rnd"]){
|
if (data["canvasBlocker-set-domain-rnd"]){
|
||||||
var {domain, incognito, rnd} = data["canvasBlocker-set-domain-rnd"];
|
const {domain, incognito, rnd} = data["canvasBlocker-set-domain-rnd"];
|
||||||
if (incognito === extension.inIncognitoContext){
|
if (incognito === extension.inIncognitoContext){
|
||||||
persistentRnd[domain] = new Uint8Array(rnd);
|
persistentRnd[domain] = new Uint8Array(rnd);
|
||||||
}
|
}
|
||||||
@ -130,11 +130,11 @@
|
|||||||
xhr.send();
|
xhr.send();
|
||||||
xhr = null;
|
xhr = null;
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
logging.verbose("Error in XHR:", e);
|
logging.verbose("Error in XHR:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var domain = cookieStoreId + getDomain(window);
|
const domain = cookieStoreId + getDomain(window);
|
||||||
if (!persistentRnd[domain]){
|
if (!persistentRnd[domain]){
|
||||||
// create the (sub-)domains random numbers if not existing
|
// create the (sub-)domains random numbers if not existing
|
||||||
persistentRnd[domain] = new Uint8Array(128);
|
persistentRnd[domain] = new Uint8Array(128);
|
||||||
@ -165,26 +165,26 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
scope.persistent.getRng = function(length, window){
|
scope.persistent.getRng = function(length, window){
|
||||||
var bitSet = new Uint32Array(getPersistentRnd(window).buffer);
|
const bitSet = new Uint32Array(getPersistentRnd(window).buffer);
|
||||||
var bitSetLength = bitSet.length;
|
const bitSetLength = bitSet.length;
|
||||||
return function(i){
|
return function(i){
|
||||||
return bitSet[i % bitSetLength];
|
return bitSet[i % bitSetLength];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
scope.persistent.getBitRng = function(length, window){
|
scope.persistent.getBitRng = function(length, window){
|
||||||
var bitSet = getPersistentRnd(window);
|
const bitSet = getPersistentRnd(window);
|
||||||
|
|
||||||
return function(value, i){
|
return function(value, i){
|
||||||
// use the last 7 bits from the value for the index of the
|
// use the last 7 bits from the value for the index of the
|
||||||
// random number
|
// random number
|
||||||
var index = value & 0x7F;
|
const index = value & 0x7F;
|
||||||
|
|
||||||
// use the last 3 bits from the position and the first bit from
|
// use the last 3 bits from the position and the first bit from
|
||||||
// from the value to get bit to use from the random number
|
// from the value to get bit to use from the random number
|
||||||
var bitIndex = ((i & 0x03) << 1) | (value >>> 7);
|
const bitIndex = ((i & 0x03) << 1) | (value >>> 7);
|
||||||
|
|
||||||
// extract the bit
|
// extract the bit
|
||||||
var bit = (bitSet[index] >>> bitIndex) & 0x01;
|
const bit = (bitSet[index] >>> bitIndex) & 0x01;
|
||||||
|
|
||||||
return bit;
|
return bit;
|
||||||
};
|
};
|
||||||
@ -196,16 +196,17 @@
|
|||||||
return scope.nonPersistent.getRng(length, window);
|
return scope.nonPersistent.getRng(length, window);
|
||||||
};
|
};
|
||||||
scope.constant.getPixelRng = (function(){
|
scope.constant.getPixelRng = (function(){
|
||||||
var colors = Object.create(null);
|
const colors = Object.create(null);
|
||||||
return function getConstantPixelRng(length, window, ignoredColors){
|
return function getConstantPixelRng(length, window, ignoredColors){
|
||||||
var rng = scope.nonPersistent.getValueRng(1024, window);
|
const rng = scope.nonPersistent.getValueRng(1024, window);
|
||||||
|
|
||||||
return function(r, g, b, a, i){ // eslint-disable-line max-params
|
// eslint-disable-next-line max-params, no-unused-vars
|
||||||
var index = String.fromCharCode(r, g, b, a);
|
return function(r, g, b, a, i){
|
||||||
|
const index = String.fromCharCode(r, g, b, a);
|
||||||
if (ignoredColors[index]){
|
if (ignoredColors[index]){
|
||||||
return [r, g, b, a];
|
return [r, g, b, a];
|
||||||
}
|
}
|
||||||
var color = colors[index];
|
let color = colors[index];
|
||||||
if (!color){
|
if (!color){
|
||||||
color = [
|
color = [
|
||||||
rng(r, 0),
|
rng(r, 0),
|
||||||
@ -224,8 +225,8 @@
|
|||||||
scope.nonPersistent.name = "nonPersistent";
|
scope.nonPersistent.name = "nonPersistent";
|
||||||
scope.nonPersistent.getRng = function(length, window){
|
scope.nonPersistent.getRng = function(length, window){
|
||||||
const maxLength = 0x4000;
|
const maxLength = 0x4000;
|
||||||
var randomI = maxLength;
|
let randomI = maxLength;
|
||||||
var randomNumbers = new Uint32Array(Math.min(maxLength, length));
|
let randomNumbers = new Uint32Array(Math.min(maxLength, length));
|
||||||
return function(i){
|
return function(i){
|
||||||
if (randomI >= randomNumbers.length){
|
if (randomI >= randomNumbers.length){
|
||||||
// refill the random number bucket if empty
|
// refill the random number bucket if empty
|
||||||
@ -235,7 +236,7 @@
|
|||||||
}
|
}
|
||||||
window.crypto.getRandomValues(randomNumbers);
|
window.crypto.getRandomValues(randomNumbers);
|
||||||
}
|
}
|
||||||
var rnd = randomNumbers[randomI];
|
const rnd = randomNumbers[randomI];
|
||||||
randomI += 1;
|
randomI += 1;
|
||||||
|
|
||||||
return rnd;
|
return rnd;
|
||||||
|
@ -10,14 +10,14 @@ const require = function(){
|
|||||||
const scope = window.scope;
|
const scope = window.scope;
|
||||||
|
|
||||||
function getScopeName(module){
|
function getScopeName(module){
|
||||||
var scopeName = module.replace(/^\..*\//, "").replace(/\..+/, "");
|
const scopeName = module.replace(/^\..*\//, "").replace(/\..+/, "");
|
||||||
// console.log(scopeName);
|
// console.log(scopeName);
|
||||||
return scopeName;
|
return scopeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
function require(module){
|
function require(module){
|
||||||
if (module.startsWith(".")){
|
if (module.startsWith(".")){
|
||||||
var scopeName = getScopeName(module);
|
const scopeName = getScopeName(module);
|
||||||
return scope[scopeName];
|
return scope[scopeName];
|
||||||
}
|
}
|
||||||
throw new ReferenceError("Unable to get non relative module " + module + "!");
|
throw new ReferenceError("Unable to get non relative module " + module + "!");
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -35,7 +35,7 @@
|
|||||||
if (resultSets.length){
|
if (resultSets.length){
|
||||||
return Array.from(
|
return Array.from(
|
||||||
resultSets.reduce(function(previousSet, set){
|
resultSets.reduce(function(previousSet, set){
|
||||||
var andSet = new Set();
|
const andSet = new Set();
|
||||||
set.forEach(function(entry){
|
set.forEach(function(entry){
|
||||||
if (previousSet.has(entry)){
|
if (previousSet.has(entry)){
|
||||||
andSet.add(entry);
|
andSet.add(entry);
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -19,7 +19,7 @@
|
|||||||
scope.expandContainer = null;
|
scope.expandContainer = null;
|
||||||
|
|
||||||
scope.getUrlValueContainer = function(name, url){
|
scope.getUrlValueContainer = function(name, url){
|
||||||
var matching = scope.urlContainer.get().filter(function(urlSetting){
|
const matching = scope.urlContainer.get().filter(function(urlSetting){
|
||||||
return urlSetting.hasOwnProperty(name);
|
return urlSetting.hasOwnProperty(name);
|
||||||
}).filter(function(urlSetting){
|
}).filter(function(urlSetting){
|
||||||
return urlSetting.match(url);
|
return urlSetting.match(url);
|
||||||
@ -32,8 +32,8 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
scope.setUrlValue = function(name, value, url){
|
scope.setUrlValue = function(name, value, url){
|
||||||
var urlContainerValue = scope.urlContainer.get();
|
const urlContainerValue = scope.urlContainer.get();
|
||||||
var matching = urlContainerValue.filter(function(urlSetting){
|
let matching = urlContainerValue.filter(function(urlSetting){
|
||||||
return urlSetting.match(url);
|
return urlSetting.match(url);
|
||||||
});
|
});
|
||||||
if (!matching.length){
|
if (!matching.length){
|
||||||
@ -46,8 +46,8 @@
|
|||||||
return scope.urlContainer.set(urlContainerValue);
|
return scope.urlContainer.set(urlContainerValue);
|
||||||
};
|
};
|
||||||
scope.resetUrlValue = function(name, url){
|
scope.resetUrlValue = function(name, url){
|
||||||
var urlContainerValue = scope.urlContainer.get();
|
let urlContainerValue = scope.urlContainer.get();
|
||||||
var matching = urlContainerValue.filter(function(urlSetting){
|
const matching = urlContainerValue.filter(function(urlSetting){
|
||||||
return urlSetting.match(url);
|
return urlSetting.match(url);
|
||||||
});
|
});
|
||||||
if (matching.length){
|
if (matching.length){
|
||||||
@ -61,6 +61,92 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function processHideContainer(settingDefinition){
|
||||||
|
scope.hideContainer = settingDefinition;
|
||||||
|
let changeListeners = {};
|
||||||
|
settingDefinition.setHideByName = function(name, value){
|
||||||
|
logging.verbose("set hide of", name, "to", value);
|
||||||
|
const hideStore = settingDefinition.get();
|
||||||
|
hideStore[name] = value;
|
||||||
|
settingDefinition.set(hideStore);
|
||||||
|
(changeListeners[name] || []).forEach(function(listener){
|
||||||
|
listener(value);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
settingDefinition.getHideByName = function(name){
|
||||||
|
const hideStore = settingDefinition.get();
|
||||||
|
return hideStore[name] || false;
|
||||||
|
};
|
||||||
|
settingDefinition.onHideChange = function(name, listener){
|
||||||
|
if (!changeListeners[name]){
|
||||||
|
changeListeners[name] = [];
|
||||||
|
}
|
||||||
|
changeListeners[name].push(listener);
|
||||||
|
};
|
||||||
|
settingDefinition.on(function(event){
|
||||||
|
const value = event.newValue;
|
||||||
|
Object.keys(value).forEach(function(name){
|
||||||
|
(changeListeners[name] || []).forEach(function(listener){
|
||||||
|
listener(value[name]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const oldValue = event.oldValue;
|
||||||
|
Object.keys(oldValue).filter(function(name){
|
||||||
|
return !value.hasOwnProperty(name);
|
||||||
|
}).forEach(function(name){
|
||||||
|
(changeListeners[name] || []).forEach(function(listener){
|
||||||
|
listener(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
settingDefinition.hideAble = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function processExpandContainer(settingDefinition){
|
||||||
|
scope.expandContainer = settingDefinition;
|
||||||
|
let changeListeners = {};
|
||||||
|
settingDefinition.setExpandByName = function(name, value){
|
||||||
|
logging.verbose("set expand of", name, "to", value);
|
||||||
|
const expandStore = settingDefinition.get();
|
||||||
|
expandStore[name] = value;
|
||||||
|
settingDefinition.set(expandStore);
|
||||||
|
(changeListeners[name] || []).forEach(function(listener){
|
||||||
|
listener(value);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
settingDefinition.getExpandByName = function(name, defaultValue = false){
|
||||||
|
const expandStore = settingDefinition.get();
|
||||||
|
if ((typeof expandStore[name]) !== "undefined"){
|
||||||
|
return expandStore[name] || false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
settingDefinition.onExpandChange = function(name, listener){
|
||||||
|
if (!changeListeners[name]){
|
||||||
|
changeListeners[name] = [];
|
||||||
|
}
|
||||||
|
changeListeners[name].push(listener);
|
||||||
|
};
|
||||||
|
settingDefinition.on(function(event){
|
||||||
|
const value = event.newValue;
|
||||||
|
Object.keys(value).forEach(function(name){
|
||||||
|
(changeListeners[name] || []).forEach(function(listener){
|
||||||
|
listener(value[name]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const oldValue = event.oldValue;
|
||||||
|
Object.keys(oldValue).filter(function(name){
|
||||||
|
return !value.hasOwnProperty(name);
|
||||||
|
}).forEach(function(name){
|
||||||
|
(changeListeners[name] || []).forEach(function(listener){
|
||||||
|
listener(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
scope.check = function(settingDefinition){
|
scope.check = function(settingDefinition){
|
||||||
if (settingDefinition.isUrlContainer){
|
if (settingDefinition.isUrlContainer){
|
||||||
scope.urlContainer = settingDefinition;
|
scope.urlContainer = settingDefinition;
|
||||||
@ -70,89 +156,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (settingDefinition.isHideContainer){
|
if (settingDefinition.isHideContainer){
|
||||||
scope.hideContainer = settingDefinition;
|
processHideContainer(settingDefinition);
|
||||||
let changeListeners = {};
|
|
||||||
settingDefinition.setHideByName = function(name, value){
|
|
||||||
logging.verbose("set hide of", name, "to", value);
|
|
||||||
const hideStore = settingDefinition.get();
|
|
||||||
hideStore[name] = value;
|
|
||||||
settingDefinition.set(hideStore);
|
|
||||||
(changeListeners[name] || []).forEach(function(listener){
|
|
||||||
listener(value);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
settingDefinition.getHideByName = function(name){
|
|
||||||
const hideStore = settingDefinition.get();
|
|
||||||
return hideStore[name] || false;
|
|
||||||
};
|
|
||||||
settingDefinition.onHideChange = function(name, listener){
|
|
||||||
if (!changeListeners[name]){
|
|
||||||
changeListeners[name] = [];
|
|
||||||
}
|
|
||||||
changeListeners[name].push(listener);
|
|
||||||
};
|
|
||||||
settingDefinition.on(function(event){
|
|
||||||
const value = event.newValue;
|
|
||||||
Object.keys(value).forEach(function(name){
|
|
||||||
(changeListeners[name] || []).forEach(function(listener){
|
|
||||||
listener(value[name]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const oldValue = event.oldValue;
|
|
||||||
Object.keys(oldValue).filter(function(name){
|
|
||||||
return !value.hasOwnProperty(name);
|
|
||||||
}).forEach(function(name){
|
|
||||||
(changeListeners[name] || []).forEach(function(listener){
|
|
||||||
listener(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
settingDefinition.hideAble = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingDefinition.isExpandContainer){
|
if (settingDefinition.isExpandContainer){
|
||||||
scope.expandContainer = settingDefinition;
|
processExpandContainer(settingDefinition);
|
||||||
let changeListeners = {};
|
|
||||||
settingDefinition.setExpandByName = function(name, value){
|
|
||||||
logging.verbose("set expand of", name, "to", value);
|
|
||||||
const expandStore = settingDefinition.get();
|
|
||||||
expandStore[name] = value;
|
|
||||||
settingDefinition.set(expandStore);
|
|
||||||
(changeListeners[name] || []).forEach(function(listener){
|
|
||||||
listener(value);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
settingDefinition.getExpandByName = function(name, defaultValue = false){
|
|
||||||
const expandStore = settingDefinition.get();
|
|
||||||
if ((typeof expandStore[name]) !== "undefined"){
|
|
||||||
return expandStore[name] || false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
settingDefinition.onExpandChange = function(name, listener){
|
|
||||||
if (!changeListeners[name]){
|
|
||||||
changeListeners[name] = [];
|
|
||||||
}
|
|
||||||
changeListeners[name].push(listener);
|
|
||||||
};
|
|
||||||
settingDefinition.on(function(event){
|
|
||||||
const value = event.newValue;
|
|
||||||
Object.keys(value).forEach(function(name){
|
|
||||||
(changeListeners[name] || []).forEach(function(listener){
|
|
||||||
listener(value[name]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const oldValue = event.oldValue;
|
|
||||||
Object.keys(oldValue).filter(function(name){
|
|
||||||
return !value.hasOwnProperty(name);
|
|
||||||
}).forEach(function(name){
|
|
||||||
(changeListeners[name] || []).forEach(function(listener){
|
|
||||||
listener(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -160,8 +168,8 @@
|
|||||||
if (scope.urlContainer){
|
if (scope.urlContainer){
|
||||||
scope.urlContainer.on(function({newValue, oldValue}){
|
scope.urlContainer.on(function({newValue, oldValue}){
|
||||||
newValue.forEach(function(urlSetting){
|
newValue.forEach(function(urlSetting){
|
||||||
var regExp;
|
let regExp;
|
||||||
var domain = !!urlSetting.url.match(/^[A-Za-z0-9_.-]+$/);
|
const domain = !!urlSetting.url.match(/^[A-Za-z0-9_.-]+$/);
|
||||||
if (domain){
|
if (domain){
|
||||||
regExp = new RegExp(
|
regExp = new RegExp(
|
||||||
"(?:^|\\.)" + urlSetting.url.replace(/([\\+*?[^\]$(){}=!|.])/g, "\\$1") + "\\.?$",
|
"(?:^|\\.)" + urlSetting.url.replace(/([\\+*?[^\]$(){}=!|.])/g, "\\$1") + "\\.?$",
|
||||||
@ -200,9 +208,9 @@
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
var newUrls = newValue.map(function(entry){return entry.url;});
|
const newUrls = newValue.map(function(entry){return entry.url;});
|
||||||
var oldUrls = oldValue.map(function(entry){return entry.url;});
|
const oldUrls = oldValue.map(function(entry){return entry.url;});
|
||||||
var matching = {};
|
const matching = {};
|
||||||
newUrls.forEach(function(url, i){
|
newUrls.forEach(function(url, i){
|
||||||
matching[url] = {new: i, old: oldUrls.indexOf(url)};
|
matching[url] = {new: i, old: oldUrls.indexOf(url)};
|
||||||
});
|
});
|
||||||
@ -212,12 +220,12 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
Object.keys(matching).forEach(function(url){
|
Object.keys(matching).forEach(function(url){
|
||||||
var oldEntry = oldValue[matching[url].old] || {};
|
const oldEntry = oldValue[matching[url].old] || {};
|
||||||
var newEntry = newValue[matching[url].new] || {};
|
const newEntry = newValue[matching[url].new] || {};
|
||||||
scope.urlContainer.entries.forEach(function(settingDefinition){
|
scope.urlContainer.entries.forEach(function(settingDefinition){
|
||||||
var name = settingDefinition.name;
|
const name = settingDefinition.name;
|
||||||
var oldValue = oldEntry[name];
|
const oldValue = oldEntry[name];
|
||||||
var newValue = newEntry[name];
|
const newValue = newEntry[name];
|
||||||
|
|
||||||
if (oldValue !== newValue){
|
if (oldValue !== newValue){
|
||||||
((eventHandler[name] || {})[url] || []).forEach(function(callback){
|
((eventHandler[name] || {})[url] || []).forEach(function(callback){
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var settingDefinitions = [
|
const settingDefinitions = [
|
||||||
{
|
{
|
||||||
name: "logLevel",
|
name: "logLevel",
|
||||||
defaultValue: 1,
|
defaultValue: 1,
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(require){
|
(function(require){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@
|
|||||||
if (!Array.isArray(newValue)){
|
if (!Array.isArray(newValue)){
|
||||||
return "wrongType";
|
return "wrongType";
|
||||||
}
|
}
|
||||||
var entriesInvalid = newValue.reduce(function(v, entry){
|
const entriesInvalid = newValue.reduce(function(v, entry){
|
||||||
v = v || settingDefinition.entries.reduce(function(v, entryDefinition){
|
v = v || settingDefinition.entries.reduce(function(v, entryDefinition){
|
||||||
return v || isDefinitionInvalid(entryDefinition, entry[entryDefinition.name]);
|
return v || isDefinitionInvalid(entryDefinition, entry[entryDefinition.name]);
|
||||||
}, false);
|
}, false);
|
||||||
@ -74,7 +74,7 @@
|
|||||||
else if (settingDefinition.urlSpecific){
|
else if (settingDefinition.urlSpecific){
|
||||||
return function getValue(url){
|
return function getValue(url){
|
||||||
if (url){
|
if (url){
|
||||||
var match = settingContainers.getUrlValueContainer(settingDefinition.name, url);
|
const match = settingContainers.getUrlValueContainer(settingDefinition.name, url);
|
||||||
if (match){
|
if (match){
|
||||||
return match[settingDefinition.name];
|
return match[settingDefinition.name];
|
||||||
}
|
}
|
||||||
@ -105,13 +105,13 @@
|
|||||||
function createSetter(settingDefinition){
|
function createSetter(settingDefinition){
|
||||||
if (settingDefinition.dynamic){
|
if (settingDefinition.dynamic){
|
||||||
return function setValue(newValue){
|
return function setValue(newValue){
|
||||||
settingDefinition.setter(scope);
|
settingDefinition.setter(scope, newValue);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const name = settingDefinition.name;
|
const name = settingDefinition.name;
|
||||||
const isValid = function isValid(newValue){
|
const isValid = function isValid(newValue){
|
||||||
var invalid = settingDefinition.invalid(newValue);
|
const invalid = settingDefinition.invalid(newValue);
|
||||||
if (invalid){
|
if (invalid){
|
||||||
if (invalid === "fixed"){
|
if (invalid === "fixed"){
|
||||||
logging.warning("Trying to set the fixed setting", name, ":", newValue);
|
logging.warning("Trying to set the fixed setting", name, ":", newValue);
|
||||||
@ -133,13 +133,14 @@
|
|||||||
logging.verbose("Trying to store new value for %s", name, newValue);
|
logging.verbose("Trying to store new value for %s", name, newValue);
|
||||||
settings[name] = newValue;
|
settings[name] = newValue;
|
||||||
if (!settingDefinition.transient){
|
if (!settingDefinition.transient){
|
||||||
var storeObject = {};
|
const storeObject = {};
|
||||||
storeObject[name] = newValue;
|
storeObject[name] = newValue;
|
||||||
var promise = browser.storage.local.set(storeObject);
|
const promise = browser.storage.local.set(storeObject);
|
||||||
promise.then(function(){
|
promise.then(function(){
|
||||||
logging.verbose("New value stored for %s:", name, newValue);
|
logging.verbose("New value stored for %s:", name, newValue);
|
||||||
}, function(err){
|
return;
|
||||||
logging.error("Unable to store new value for %s:", name, newValue, err);
|
}).catch(function(error){
|
||||||
|
logging.error("Unable to store new value for %s:", name, newValue, error);
|
||||||
});
|
});
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
@ -227,7 +228,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
settingDefinitions.forEach(function(settingDefinition){
|
settingDefinitions.forEach(function(settingDefinition){
|
||||||
var name = settingDefinition.name;
|
const name = settingDefinition.name;
|
||||||
definitionsByName[name] = settingDefinition;
|
definitionsByName[name] = settingDefinition;
|
||||||
if (typeof settingDefinition.defaultValue === "function"){
|
if (typeof settingDefinition.defaultValue === "function"){
|
||||||
settingDefinition.defaultValue = settingDefinition.defaultValue();
|
settingDefinition.defaultValue = settingDefinition.defaultValue();
|
||||||
@ -282,7 +283,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
scope.getDefinition = function(name){
|
scope.getDefinition = function(name){
|
||||||
var foundDefinition = definitionsByName[name];
|
const foundDefinition = definitionsByName[name];
|
||||||
if (foundDefinition){
|
if (foundDefinition){
|
||||||
return Object.create(foundDefinition);
|
return Object.create(foundDefinition);
|
||||||
}
|
}
|
||||||
@ -300,7 +301,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
scope.set = function(name, ...args){
|
scope.set = function(name, ...args){
|
||||||
var foundDefinition = definitionsByName[name];
|
const foundDefinition = definitionsByName[name];
|
||||||
if (foundDefinition){
|
if (foundDefinition){
|
||||||
return foundDefinition.set(...args);
|
return foundDefinition.set(...args);
|
||||||
}
|
}
|
||||||
@ -309,7 +310,7 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
scope.get = function(name, ...args){
|
scope.get = function(name, ...args){
|
||||||
var foundDefinition = definitionsByName[name];
|
const foundDefinition = definitionsByName[name];
|
||||||
if (foundDefinition){
|
if (foundDefinition){
|
||||||
return foundDefinition.get(...args);
|
return foundDefinition.get(...args);
|
||||||
}
|
}
|
||||||
@ -328,9 +329,9 @@
|
|||||||
|
|
||||||
const resetSymbol = Symbol("reset");
|
const resetSymbol = Symbol("reset");
|
||||||
function changeValue(name, newValue){
|
function changeValue(name, newValue){
|
||||||
var settingDefinition = scope.getDefinition(name);
|
const settingDefinition = scope.getDefinition(name);
|
||||||
if (settingDefinition){
|
if (settingDefinition){
|
||||||
var oldValue = settings[name];
|
const oldValue = settings[name];
|
||||||
if (newValue === resetSymbol){
|
if (newValue === resetSymbol){
|
||||||
newValue = getDefaultValue(settingDefinition);
|
newValue = getDefaultValue(settingDefinition);
|
||||||
}
|
}
|
||||||
@ -355,7 +356,7 @@
|
|||||||
browser.storage.onChanged.addListener(function(changes, area){
|
browser.storage.onChanged.addListener(function(changes, area){
|
||||||
if (area === "local"){
|
if (area === "local"){
|
||||||
logging.notice("settings changed", changes);
|
logging.notice("settings changed", changes);
|
||||||
var delayedChange = [];
|
const delayedChange = [];
|
||||||
Object.entries(changes).forEach(function(entry){
|
Object.entries(changes).forEach(function(entry){
|
||||||
const [name, change] = entry;
|
const [name, change] = entry;
|
||||||
if (settingContainers.urlContainer && name === settingContainers.urlContainer.name){
|
if (settingContainers.urlContainer && name === settingContainers.urlContainer.name){
|
||||||
@ -407,7 +408,7 @@
|
|||||||
{settings, logging, changeValue, urlContainer: settingContainers.urlContainer}
|
{settings, logging, changeValue, urlContainer: settingContainers.urlContainer}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
var delayedChange = [];
|
const delayedChange = [];
|
||||||
Object.entries(storage).forEach(function(entry){
|
Object.entries(storage).forEach(function(entry){
|
||||||
const [name, value] = entry;
|
const [name, value] = entry;
|
||||||
if (settingContainers.urlContainer && name === settingContainers.urlContainer.name){
|
if (settingContainers.urlContainer && name === settingContainers.urlContainer.name){
|
||||||
@ -451,8 +452,8 @@
|
|||||||
xhr.send();
|
xhr.send();
|
||||||
xhr = null;
|
xhr = null;
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
logging.verbose("Error in XHR:", e);
|
logging.verbose("Error in XHR:", error);
|
||||||
}
|
}
|
||||||
logging.message("settings still default?", settings.isStillDefault);
|
logging.message("settings still default?", settings.isStillDefault);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -17,13 +17,14 @@
|
|||||||
|
|
||||||
scope.validVersions = [undefined, 0.1, 0.2, 0.3, 0.4, 0.5];
|
scope.validVersions = [undefined, 0.1, 0.2, 0.3, 0.4, 0.5];
|
||||||
scope.transitions = {
|
scope.transitions = {
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
"": function(oldStorage){
|
"": function(oldStorage){
|
||||||
return {
|
return {
|
||||||
storageVersion: 0.5
|
storageVersion: 0.5
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
0.1: function(oldStorage){
|
0.1: function(oldStorage){
|
||||||
var newStorage = {
|
const newStorage = {
|
||||||
storageVersion: 0.2
|
storageVersion: 0.2
|
||||||
};
|
};
|
||||||
if (oldStorage.hasOwnProperty("askOnlyOnce")){
|
if (oldStorage.hasOwnProperty("askOnlyOnce")){
|
||||||
@ -32,7 +33,7 @@
|
|||||||
return newStorage;
|
return newStorage;
|
||||||
},
|
},
|
||||||
0.2: function(oldStorage){
|
0.2: function(oldStorage){
|
||||||
var newStorage = {
|
const newStorage = {
|
||||||
storageVersion: 0.3,
|
storageVersion: 0.3,
|
||||||
urlSettings: (
|
urlSettings: (
|
||||||
oldStorage.urlSettings &&
|
oldStorage.urlSettings &&
|
||||||
@ -40,13 +41,13 @@
|
|||||||
)? oldStorage.urlSettings: []
|
)? oldStorage.urlSettings: []
|
||||||
};
|
};
|
||||||
|
|
||||||
var urlSettings = {};
|
const urlSettings = {};
|
||||||
|
|
||||||
(oldStorage.blackList || "").split(",")
|
(oldStorage.blackList || "").split(",")
|
||||||
.map(function(url){return url.trim();})
|
.map(function(url){return url.trim();})
|
||||||
.filter(function(url){return !!url;})
|
.filter(function(url){return !!url;})
|
||||||
.forEach(function(url){
|
.forEach(function(url){
|
||||||
var entry = urlSettings[url];
|
let entry = urlSettings[url];
|
||||||
if (!entry){
|
if (!entry){
|
||||||
entry = {url, blockMode: "block"};
|
entry = {url, blockMode: "block"};
|
||||||
urlSettings[url] = entry;
|
urlSettings[url] = entry;
|
||||||
@ -57,7 +58,7 @@
|
|||||||
.map(function(url){return url.trim();})
|
.map(function(url){return url.trim();})
|
||||||
.filter(function(url){return !!url;})
|
.filter(function(url){return !!url;})
|
||||||
.forEach(function(url){
|
.forEach(function(url){
|
||||||
var entry = urlSettings[url];
|
let entry = urlSettings[url];
|
||||||
if (!entry){
|
if (!entry){
|
||||||
entry = {url, blockMode: "allow"};
|
entry = {url, blockMode: "allow"};
|
||||||
urlSettings[url] = entry;
|
urlSettings[url] = entry;
|
||||||
@ -68,7 +69,7 @@
|
|||||||
.map(function(url){return url.trim();})
|
.map(function(url){return url.trim();})
|
||||||
.filter(function(url){return !!url;})
|
.filter(function(url){return !!url;})
|
||||||
.forEach(function(url){
|
.forEach(function(url){
|
||||||
var entry = urlSettings[url];
|
let entry = urlSettings[url];
|
||||||
if (!entry){
|
if (!entry){
|
||||||
entry = {url, showNotifications: false};
|
entry = {url, showNotifications: false};
|
||||||
urlSettings[url] = entry;
|
urlSettings[url] = entry;
|
||||||
@ -87,7 +88,7 @@
|
|||||||
return newStorage;
|
return newStorage;
|
||||||
},
|
},
|
||||||
0.3: function(oldStorage){
|
0.3: function(oldStorage){
|
||||||
var newStorage = {
|
const newStorage = {
|
||||||
storageVersion: 0.4
|
storageVersion: 0.4
|
||||||
};
|
};
|
||||||
if (oldStorage.hasOwnProperty("apiWhiteList")){
|
if (oldStorage.hasOwnProperty("apiWhiteList")){
|
||||||
@ -100,7 +101,7 @@
|
|||||||
return newStorage;
|
return newStorage;
|
||||||
},
|
},
|
||||||
0.4: function(oldStorage){
|
0.4: function(oldStorage){
|
||||||
var newStorage = {
|
const newStorage = {
|
||||||
storageVersion: 0.5
|
storageVersion: 0.5
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -134,7 +135,7 @@
|
|||||||
return newStorage;
|
return newStorage;
|
||||||
},
|
},
|
||||||
0.5: function(oldStorage){
|
0.5: function(oldStorage){
|
||||||
var newStorage = {
|
const newStorage = {
|
||||||
storageVersion: 0.6
|
storageVersion: 0.6
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -159,7 +160,7 @@
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
scope.check = function(storage, {settings, logging, changeValue, urlContainer}){
|
scope.check = function(storage, {settings, logging}){
|
||||||
|
|
||||||
if (!storage.storageVersion){
|
if (!storage.storageVersion){
|
||||||
logging.message("No storage version found. Initializing storage.");
|
logging.message("No storage version found. Initializing storage.");
|
||||||
@ -168,13 +169,13 @@
|
|||||||
browser.storage.local.set(storage);
|
browser.storage.local.set(storage);
|
||||||
}
|
}
|
||||||
else if (storage.storageVersion !== settings.storageVersion){
|
else if (storage.storageVersion !== settings.storageVersion){
|
||||||
var toChange = {};
|
const toChange = {};
|
||||||
while (storage.storageVersion !== settings.storageVersion){
|
while (storage.storageVersion !== settings.storageVersion){
|
||||||
logging.message("Old storage found (",
|
logging.message("Old storage found (",
|
||||||
storage.storageVersion, "expected", settings.storageVersion,
|
storage.storageVersion, "expected", settings.storageVersion,
|
||||||
")");
|
")");
|
||||||
if (scope.transitions[storage.storageVersion]){
|
if (scope.transitions[storage.storageVersion]){
|
||||||
var changes = scope.transitions[storage.storageVersion](storage);
|
const changes = scope.transitions[storage.storageVersion](storage);
|
||||||
Object.entries(changes).forEach(function(entry){
|
Object.entries(changes).forEach(function(entry){
|
||||||
const [name, value] = entry;
|
const [name, value] = entry;
|
||||||
toChange[name] = value;
|
toChange[name] = value;
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
scope.init = function(page){
|
scope.init = function(page){
|
||||||
const basePath = browser.extension.getURL("themes");
|
const basePath = browser.extension.getURL("themes");
|
||||||
|
|
||||||
var baseLink = document.createElement("link");
|
const baseLink = document.createElement("link");
|
||||||
baseLink.href = `${basePath}/base/layout.css`;
|
baseLink.href = `${basePath}/base/layout.css`;
|
||||||
baseLink.rel = "stylesheet";
|
baseLink.rel = "stylesheet";
|
||||||
baseLink.type = "text/css";
|
baseLink.type = "text/css";
|
||||||
@ -25,7 +25,7 @@
|
|||||||
const links = ["layout", page].filter(function(file){
|
const links = ["layout", page].filter(function(file){
|
||||||
return file;
|
return file;
|
||||||
}).map(function(file){
|
}).map(function(file){
|
||||||
var link = document.createElement("link");
|
const link = document.createElement("link");
|
||||||
link.cbFile = file;
|
link.cbFile = file;
|
||||||
link.rel = "alternative";
|
link.rel = "alternative";
|
||||||
link.type = "text/css";
|
link.type = "text/css";
|
||||||
|
71
lib/webgl.js
71
lib/webgl.js
@ -4,9 +4,9 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var logging = require("./logging");
|
const logging = require("./logging");
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -15,9 +15,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
scope.copyCanvasToWebgl = function copyCanvasToWebgl(window, canvas, webGLVersion = "webgl"){
|
scope.copyCanvasToWebgl = function copyCanvasToWebgl(window, canvas, webGLVersion = "webgl"){
|
||||||
var webGlCanvas = canvas.cloneNode(true);
|
const webGlCanvas = canvas.cloneNode(true);
|
||||||
var success;
|
const context =
|
||||||
var context =
|
|
||||||
window.HTMLCanvasElement.prototype.getContext.call(webGlCanvas, webGLVersion) ||
|
window.HTMLCanvasElement.prototype.getContext.call(webGlCanvas, webGLVersion) ||
|
||||||
window.HTMLCanvasElement.prototype.getContext.call(webGlCanvas, "experimental-" + webGLVersion);
|
window.HTMLCanvasElement.prototype.getContext.call(webGlCanvas, "experimental-" + webGLVersion);
|
||||||
if (!context){
|
if (!context){
|
||||||
@ -28,37 +27,34 @@
|
|||||||
|
|
||||||
context.viewport(0, 0, webGlCanvas.width, webGlCanvas.height);
|
context.viewport(0, 0, webGlCanvas.width, webGlCanvas.height);
|
||||||
|
|
||||||
var program = context.createProgram();
|
const program = context.createProgram();
|
||||||
|
|
||||||
var shader = context.createShader(context.VERTEX_SHADER);
|
const vertexShader = context.createShader(context.VERTEX_SHADER);
|
||||||
var vertex = "attribute vec4 a_position;\nattribute vec2 a_texCoord;\nvarying vec2 v_texCoord;\n" +
|
const vertex = "attribute vec4 a_position;\nattribute vec2 a_texCoord;\nvarying vec2 v_texCoord;\n" +
|
||||||
"void main(){\n\tgl_Position = a_position;\n\tv_texCoord = a_texCoord;\n}";
|
"void main(){\n\tgl_Position = a_position;\n\tv_texCoord = a_texCoord;\n}";
|
||||||
context.shaderSource(shader, vertex);
|
context.shaderSource(vertexShader, vertex);
|
||||||
context.compileShader(shader);
|
context.compileShader(vertexShader);
|
||||||
success = context.getShaderParameter(shader, context.COMPILE_STATUS);
|
if (!context.getShaderParameter(vertexShader, context.COMPILE_STATUS)){
|
||||||
if (!success){
|
context.deleteShader(vertexShader);
|
||||||
context.deleteShader(shader);
|
|
||||||
logging.warning("webgl: failed to compile vertex shader.");
|
logging.warning("webgl: failed to compile vertex shader.");
|
||||||
return {canvas: false, context: false};
|
return {canvas: false, context: false};
|
||||||
}
|
}
|
||||||
context.attachShader(program, shader);
|
context.attachShader(program, vertexShader);
|
||||||
|
|
||||||
shader = context.createShader(context.FRAGMENT_SHADER);
|
const fragmentShader = context.createShader(context.FRAGMENT_SHADER);
|
||||||
var fragmenter = "precision mediump float;\nuniform sampler2D u_image;\nvarying vec2 v_texCoord;\n" +
|
const fragmenter = "precision mediump float;\nuniform sampler2D u_image;\nvarying vec2 v_texCoord;\n" +
|
||||||
"void main(){\n\tgl_FragColor = texture2D(u_image, v_texCoord);\n}";
|
"void main(){\n\tgl_FragColor = texture2D(u_image, v_texCoord);\n}";
|
||||||
context.shaderSource(shader, fragmenter);
|
context.shaderSource(fragmentShader, fragmenter);
|
||||||
context.compileShader(shader);
|
context.compileShader(fragmentShader);
|
||||||
success = context.getShaderParameter(shader, context.COMPILE_STATUS);
|
if (!context.getShaderParameter(fragmentShader, context.COMPILE_STATUS)){
|
||||||
if (!success){
|
context.deleteShader(fragmentShader);
|
||||||
context.deleteShader(shader);
|
|
||||||
logging.warning("webgl: failed to compile fragmenter shader.");
|
logging.warning("webgl: failed to compile fragmenter shader.");
|
||||||
return {canvas: false, context: false};
|
return {canvas: false, context: false};
|
||||||
}
|
}
|
||||||
context.attachShader(program, shader);
|
context.attachShader(program, fragmentShader);
|
||||||
|
|
||||||
context.linkProgram(program);
|
context.linkProgram(program);
|
||||||
success = context.getProgramParameter(program, context.LINK_STATUS);
|
if (!context.getProgramParameter(program, context.LINK_STATUS)){
|
||||||
if (!success){
|
|
||||||
context.deleteProgram(program);
|
context.deleteProgram(program);
|
||||||
logging.warning("webgl: failed to link program.");
|
logging.warning("webgl: failed to link program.");
|
||||||
return {canvas: false, context: false};
|
return {canvas: false, context: false};
|
||||||
@ -66,8 +62,7 @@
|
|||||||
|
|
||||||
context.useProgram(program);
|
context.useProgram(program);
|
||||||
|
|
||||||
var positionAttributeLocation = context.getAttribLocation(program, "a_position");
|
const positionBuffer = context.createBuffer();
|
||||||
var positionBuffer = context.createBuffer();
|
|
||||||
context.bindBuffer(context.ARRAY_BUFFER, positionBuffer);
|
context.bindBuffer(context.ARRAY_BUFFER, positionBuffer);
|
||||||
context.bufferData(context.ARRAY_BUFFER, new Float32Array([
|
context.bufferData(context.ARRAY_BUFFER, new Float32Array([
|
||||||
-1, -1,
|
-1, -1,
|
||||||
@ -76,21 +71,21 @@
|
|||||||
1, 1,
|
1, 1,
|
||||||
-1, 1,
|
-1, 1,
|
||||||
1, -1
|
1, -1
|
||||||
|
|
||||||
]), context.STATIC_DRAW);
|
]), context.STATIC_DRAW);
|
||||||
|
|
||||||
|
const positionAttributeLocation = context.getAttribLocation(program, "a_position");
|
||||||
context.enableVertexAttribArray(positionAttributeLocation);
|
context.enableVertexAttribArray(positionAttributeLocation);
|
||||||
var size = 2; // 2 components per iteration
|
const size = 2; // 2 components per iteration
|
||||||
var type = context.FLOAT; // the data is 32bit floats
|
const type = context.FLOAT; // the data is 32bit floats
|
||||||
var normalize = false; // don't normalize the data
|
const normalize = false; // don't normalize the data
|
||||||
var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position
|
const stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position
|
||||||
var offset = 0; // start at the beginning of the buffer
|
const offset = 0; // start at the beginning of the buffer
|
||||||
context.vertexAttribPointer(positionAttributeLocation, size, type, normalize, stride, offset);
|
context.vertexAttribPointer(positionAttributeLocation, size, type, normalize, stride, offset);
|
||||||
|
|
||||||
var texCoordLocation = context.getAttribLocation(program, "a_texCoord");
|
const texCoordLocation = context.getAttribLocation(program, "a_texCoord");
|
||||||
|
|
||||||
// provide texture coordinates for the rectangle.
|
// provide texture coordinates for the rectangle.
|
||||||
var texCoordBuffer = context.createBuffer();
|
const texCoordBuffer = context.createBuffer();
|
||||||
context.bindBuffer(context.ARRAY_BUFFER, texCoordBuffer);
|
context.bindBuffer(context.ARRAY_BUFFER, texCoordBuffer);
|
||||||
context.bufferData(context.ARRAY_BUFFER, new Float32Array([
|
context.bufferData(context.ARRAY_BUFFER, new Float32Array([
|
||||||
0, 1,
|
0, 1,
|
||||||
@ -103,18 +98,14 @@
|
|||||||
context.enableVertexAttribArray(texCoordLocation);
|
context.enableVertexAttribArray(texCoordLocation);
|
||||||
context.vertexAttribPointer(texCoordLocation, 2, context.FLOAT, false, 0, 0);
|
context.vertexAttribPointer(texCoordLocation, 2, context.FLOAT, false, 0, 0);
|
||||||
|
|
||||||
var texture = context.createTexture();
|
context.bindTexture(context.TEXTURE_2D, context.createTexture());
|
||||||
context.bindTexture(context.TEXTURE_2D, texture);
|
|
||||||
context.texParameteri(context.TEXTURE_2D, context.TEXTURE_WRAP_S, context.CLAMP_TO_EDGE);
|
context.texParameteri(context.TEXTURE_2D, context.TEXTURE_WRAP_S, context.CLAMP_TO_EDGE);
|
||||||
context.texParameteri(context.TEXTURE_2D, context.TEXTURE_WRAP_T, context.CLAMP_TO_EDGE);
|
context.texParameteri(context.TEXTURE_2D, context.TEXTURE_WRAP_T, context.CLAMP_TO_EDGE);
|
||||||
context.texParameteri(context.TEXTURE_2D, context.TEXTURE_MIN_FILTER, context.NEAREST);
|
context.texParameteri(context.TEXTURE_2D, context.TEXTURE_MIN_FILTER, context.NEAREST);
|
||||||
context.texParameteri(context.TEXTURE_2D, context.TEXTURE_MAG_FILTER, context.NEAREST);
|
context.texParameteri(context.TEXTURE_2D, context.TEXTURE_MAG_FILTER, context.NEAREST);
|
||||||
context.texImage2D(context.TEXTURE_2D, 0, context.RGBA, context.RGBA, context.UNSIGNED_BYTE, canvas);
|
context.texImage2D(context.TEXTURE_2D, 0, context.RGBA, context.RGBA, context.UNSIGNED_BYTE, canvas);
|
||||||
|
|
||||||
var primitiveType = context.TRIANGLES;
|
context.drawArrays(context.TRIANGLES /*primitiveType*/, 0 /*triangleOffset*/, 6 /*count*/);
|
||||||
var triangleOffset = 0;
|
|
||||||
var count = 6;
|
|
||||||
context.drawArrays(primitiveType, triangleOffset, count);
|
|
||||||
|
|
||||||
return {webGlCanvas, context};
|
return {webGlCanvas, context};
|
||||||
};
|
};
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
require("../lib/theme").init();
|
require("../lib/theme").init();
|
||||||
const input = document.getElementById("settings");
|
const input = document.getElementById("settings");
|
||||||
settings.onloaded(function(){
|
settings.onloaded(function(){
|
||||||
var data = {};
|
const data = {};
|
||||||
settings.forEach(function(def){
|
settings.forEach(function(def){
|
||||||
data[def.name] = def.get();
|
data[def.name] = def.get();
|
||||||
});
|
});
|
||||||
@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
input.addEventListener("input", function(){
|
input.addEventListener("input", function(){
|
||||||
try {
|
try {
|
||||||
var newSettings = JSON.parse(this.value);
|
let newSettings = JSON.parse(this.value);
|
||||||
var isValid = true;
|
let isValid = true;
|
||||||
|
|
||||||
while (settingsMigration.transitions.hasOwnProperty(newSettings.storageVersion)){
|
while (settingsMigration.transitions.hasOwnProperty(newSettings.storageVersion)){
|
||||||
let oldVersion = newSettings.storageVersion;
|
let oldVersion = newSettings.storageVersion;
|
||||||
@ -57,14 +57,14 @@
|
|||||||
this.classList.add("invalid");
|
this.classList.add("invalid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
logging.warning("Invalid JSON:", e);
|
logging.warning("Invalid JSON:", error);
|
||||||
this.classList.add("invalid");
|
this.classList.add("invalid");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
input.addEventListener("blur", function(){
|
input.addEventListener("blur", function(){
|
||||||
if (!this.classList.contains("invalid")){
|
if (!this.classList.contains("invalid")){
|
||||||
var data = {};
|
const data = {};
|
||||||
settings.forEach(function(def){
|
settings.forEach(function(def){
|
||||||
data[def.name] = def.get();
|
data[def.name] = def.get();
|
||||||
});
|
});
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
require("./theme").init("options");
|
require("./theme").init("options");
|
||||||
const modal = require("../lib/modal");
|
const modal = require("../lib/modal");
|
||||||
|
|
||||||
var callbacks = {
|
const callbacks = {
|
||||||
openNavigatorSettings: function(){
|
openNavigatorSettings: function(){
|
||||||
logging.verbose("open navigator settings");
|
logging.verbose("open navigator settings");
|
||||||
window.open("navigator.html", "_blank");
|
window.open("navigator.html", "_blank");
|
||||||
@ -36,7 +36,7 @@
|
|||||||
},
|
},
|
||||||
clearPersistentRndForContainer: function(){
|
clearPersistentRndForContainer: function(){
|
||||||
browser.contextualIdentities.query({}).then(function(identities){
|
browser.contextualIdentities.query({}).then(function(identities){
|
||||||
modal.select(
|
return modal.select(
|
||||||
extension.getTranslation("clearPersistentRndForContainer_title"),
|
extension.getTranslation("clearPersistentRndForContainer_title"),
|
||||||
identities.map(function(identity){
|
identities.map(function(identity){
|
||||||
return {
|
return {
|
||||||
@ -44,9 +44,12 @@
|
|||||||
object: identity
|
object: identity
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
).then(function(identity){
|
);
|
||||||
extension.message.send({"canvasBlocker-clear-container-rnd": identity.cookieStoreId});
|
}).then(function(identity){
|
||||||
}, ()=>{});
|
extension.message.send({"canvasBlocker-clear-container-rnd": identity.cookieStoreId});
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
logging.warning("Unable to clear persistent rnd for container:", error);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
inspectSettings: function(){
|
inspectSettings: function(){
|
||||||
@ -73,7 +76,7 @@
|
|||||||
link.target = "_blank";
|
link.target = "_blank";
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
function format(number, digits){
|
function format(number, digits){
|
||||||
var str = number.toFixed(0);
|
const str = number.toFixed(0);
|
||||||
return "0".repeat(digits - str.length) + str;
|
return "0".repeat(digits - str.length) + str;
|
||||||
}
|
}
|
||||||
link.download = "CanvasBlocker-settings_" +
|
link.download = "CanvasBlocker-settings_" +
|
||||||
@ -99,13 +102,12 @@
|
|||||||
input.type = "file";
|
input.type = "file";
|
||||||
input.addEventListener("change", function(){
|
input.addEventListener("change", function(){
|
||||||
if (this.files.length){
|
if (this.files.length){
|
||||||
var file = this.files[0];
|
const reader = new FileReader();
|
||||||
var reader = new FileReader();
|
reader.onload = function(){
|
||||||
reader.onload = function(result){
|
|
||||||
resolve(this.result);
|
resolve(this.result);
|
||||||
};
|
};
|
||||||
reader.onerror = function(err){
|
reader.onerror = function(error){
|
||||||
reject(err);
|
reject(error);
|
||||||
};
|
};
|
||||||
reader.readAsText(this.files[0]);
|
reader.readAsText(this.files[0]);
|
||||||
}
|
}
|
||||||
@ -134,8 +136,9 @@
|
|||||||
keys.forEach(function(key){
|
keys.forEach(function(key){
|
||||||
settings[key] = json[key];
|
settings[key] = json[key];
|
||||||
});
|
});
|
||||||
}).catch(function(err){
|
return;
|
||||||
alert(err);
|
}).catch(function(error){
|
||||||
|
alert(error);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
resetSettings: function(){
|
resetSettings: function(){
|
||||||
@ -149,6 +152,9 @@
|
|||||||
if (clear){
|
if (clear){
|
||||||
browser.storage.local.clear();
|
browser.storage.local.clear();
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
logging.warning("Unable to reset settings:", error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -224,22 +230,25 @@
|
|||||||
linkDiv.appendChild(link);
|
linkDiv.appendChild(link);
|
||||||
head.appendChild(linkDiv);
|
head.appendChild(linkDiv);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
logging.warning("Unable to identify tab:", error);
|
||||||
});
|
});
|
||||||
|
|
||||||
var groupTabs = document.createElement("div");
|
const groupTabs = document.createElement("div");
|
||||||
groupTabs.classList = "groupTabs";
|
groupTabs.classList = "groupTabs";
|
||||||
document.body.appendChild(groupTabs);
|
document.body.appendChild(groupTabs);
|
||||||
|
|
||||||
var groups = document.createElement("ul");
|
const groups = document.createElement("ul");
|
||||||
groups.className = "groups";
|
groups.className = "groups";
|
||||||
groupTabs.appendChild(groups);
|
groupTabs.appendChild(groups);
|
||||||
|
|
||||||
var table = document.createElement("table");
|
const table = document.createElement("table");
|
||||||
table.className = "settings " + (settings.displayDescriptions? "display": "hide") + "Descriptions";
|
table.className = "settings " + (settings.displayDescriptions? "display": "hide") + "Descriptions";
|
||||||
settings.on("displayDescriptions", function(){
|
settings.on("displayDescriptions", function(){
|
||||||
table.className = "settings " + (settings.displayDescriptions? "display": "hide") + "Descriptions";
|
table.className = "settings " + (settings.displayDescriptions? "display": "hide") + "Descriptions";
|
||||||
});
|
});
|
||||||
var tableContainer = document.createElement("div");
|
const tableContainer = document.createElement("div");
|
||||||
tableContainer.classList = "tabContents";
|
tableContainer.classList = "tabContents";
|
||||||
groupTabs.appendChild(tableContainer);
|
groupTabs.appendChild(tableContainer);
|
||||||
|
|
||||||
@ -277,41 +286,6 @@
|
|||||||
|
|
||||||
const {hide: hideContainer, expand: expandContainer} = settings.getContainers();
|
const {hide: hideContainer, expand: expandContainer} = settings.getContainers();
|
||||||
|
|
||||||
const addGroup = function addGroup(groupDefinition){
|
|
||||||
const sections = [];
|
|
||||||
const group = {
|
|
||||||
select: function(){
|
|
||||||
groups.querySelectorAll(".selected").forEach(function(group){
|
|
||||||
group.classList.remove("selected");
|
|
||||||
});
|
|
||||||
table.querySelectorAll("tbody").forEach(function(section){
|
|
||||||
section.classList.remove("selectedGroup");
|
|
||||||
});
|
|
||||||
sections.forEach(function(section){
|
|
||||||
section.node.classList.add("selectedGroup");
|
|
||||||
});
|
|
||||||
name.classList.add("selected");
|
|
||||||
},
|
|
||||||
addSection: function(sectionDefinition){
|
|
||||||
const section = addSection(sectionDefinition.name);
|
|
||||||
sections.push(section);
|
|
||||||
return section;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const groupIndex = groups.childNodes.length;
|
|
||||||
const name = document.createElement("li");
|
|
||||||
name.textContent = extension.getTranslation("group_" + groupDefinition.name);
|
|
||||||
name.className = "groupName group" + groupIndex;
|
|
||||||
|
|
||||||
|
|
||||||
name.addEventListener("click", group.select);
|
|
||||||
|
|
||||||
groups.appendChild(name);
|
|
||||||
|
|
||||||
return group;
|
|
||||||
};
|
|
||||||
|
|
||||||
const addSection = function addSection(name){
|
const addSection = function addSection(name){
|
||||||
const body = document.createElement("tbody");
|
const body = document.createElement("tbody");
|
||||||
body.className = "sectionBody";
|
body.className = "sectionBody";
|
||||||
@ -356,9 +330,9 @@
|
|||||||
},
|
},
|
||||||
updateDisplay: function(){
|
updateDisplay: function(){
|
||||||
const searchMode = document.body.classList.contains("searching");
|
const searchMode = document.body.classList.contains("searching");
|
||||||
var anyVisible = false;
|
let anyVisible = false;
|
||||||
rows.forEach(function(row){
|
rows.forEach(function(row){
|
||||||
var isHidden = row.classList.contains("hidden");
|
const isHidden = row.classList.contains("hidden");
|
||||||
if (!isHidden){
|
if (!isHidden){
|
||||||
if (searchMode){
|
if (searchMode){
|
||||||
if (!row.classList.contains("found")){
|
if (!row.classList.contains("found")){
|
||||||
@ -382,13 +356,160 @@
|
|||||||
return section;
|
return section;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const addGroup = function addGroup(groupDefinition){
|
||||||
|
const sections = [];
|
||||||
|
|
||||||
|
const groupIndex = groups.childNodes.length;
|
||||||
|
const name = document.createElement("li");
|
||||||
|
name.textContent = extension.getTranslation("group_" + groupDefinition.name);
|
||||||
|
name.className = "groupName group" + groupIndex;
|
||||||
|
|
||||||
|
const group = {
|
||||||
|
select: function(){
|
||||||
|
groups.querySelectorAll(".selected").forEach(function(group){
|
||||||
|
group.classList.remove("selected");
|
||||||
|
});
|
||||||
|
table.querySelectorAll("tbody").forEach(function(section){
|
||||||
|
section.classList.remove("selectedGroup");
|
||||||
|
});
|
||||||
|
sections.forEach(function(section){
|
||||||
|
section.node.classList.add("selectedGroup");
|
||||||
|
});
|
||||||
|
name.classList.add("selected");
|
||||||
|
},
|
||||||
|
addSection: function(sectionDefinition){
|
||||||
|
const section = addSection(sectionDefinition.name);
|
||||||
|
sections.push(section);
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
name.addEventListener("click", group.select);
|
||||||
|
|
||||||
|
groups.appendChild(name);
|
||||||
|
|
||||||
|
return group;
|
||||||
|
};
|
||||||
|
|
||||||
const beforeChangeEventListeners = {};
|
const beforeChangeEventListeners = {};
|
||||||
|
function setupSetterForDisplay(setting){
|
||||||
|
let originalSet = setting.set;
|
||||||
|
setting.originalSet = originalSet;
|
||||||
|
if (originalSet){
|
||||||
|
const eventListeners = [];
|
||||||
|
beforeChangeEventListeners[setting.name] = eventListeners;
|
||||||
|
setting.set = function(...args){
|
||||||
|
if (eventListeners.every(function(listener){
|
||||||
|
return listener.call(setting, ...args);
|
||||||
|
})){
|
||||||
|
return originalSet.apply(this, args);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupHideForDisplay(setting){
|
||||||
|
const display = setting.display;
|
||||||
|
const hideChangeListeners = [];
|
||||||
|
setting.setHide = function setHide(value){
|
||||||
|
if (hideContainer){
|
||||||
|
hideContainer.setHideByName(display.name, value);
|
||||||
|
if (setting.computeDependencies){
|
||||||
|
setting.computeDependencies();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
setting.onHideChange = function(listener){
|
||||||
|
hideChangeListeners.push(listener);
|
||||||
|
};
|
||||||
|
setting.getHide = function getHide(){
|
||||||
|
if (hideContainer){
|
||||||
|
return hideContainer.getHideByName(display.name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (hideContainer){
|
||||||
|
hideContainer.onHideChange(display.name, function(value){
|
||||||
|
if (setting.computeDependencies){
|
||||||
|
setting.computeDependencies();
|
||||||
|
}
|
||||||
|
hideChangeListeners.forEach(function(listener){
|
||||||
|
listener(value);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function setupExpandForDisplay(setting){
|
||||||
|
const display = setting.display;
|
||||||
|
const expandChangeListeners = [];
|
||||||
|
setting.setExpand = function setExpand(value){
|
||||||
|
if (expandContainer){
|
||||||
|
expandContainer.setExpandByName(display.name, value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
setting.onExpandChange = function(listener){
|
||||||
|
expandChangeListeners.push(listener);
|
||||||
|
};
|
||||||
|
setting.getExpand = function getExpand(){
|
||||||
|
if (expandContainer){
|
||||||
|
return expandContainer.getExpandByName(display.name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (expandContainer){
|
||||||
|
expandContainer.onExpandChange(display.name, function(value){
|
||||||
|
expandChangeListeners.forEach(function(listener){
|
||||||
|
listener(value);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupComputeDependenciesForDisplay(setting, section, row){
|
||||||
|
let displayDependencies = setting.display.displayDependencies || [{}];
|
||||||
|
displayDependencies = Array.isArray(displayDependencies)?
|
||||||
|
displayDependencies:
|
||||||
|
[displayDependencies];
|
||||||
|
setting.computeDependencies = function computeDependencies(){
|
||||||
|
logging.verbose("evaluate display dependencies for", setting);
|
||||||
|
row.classList[(
|
||||||
|
(
|
||||||
|
displayHidden.get() ||
|
||||||
|
!setting.getHide()
|
||||||
|
) &&
|
||||||
|
displayDependencies.some(function(displayDependency){
|
||||||
|
return Object.keys(displayDependency).every(function(key){
|
||||||
|
return displayDependency[key].indexOf(settings[key]) !== -1;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
)? "remove": "add"]("hidden");
|
||||||
|
section.updateDisplay();
|
||||||
|
};
|
||||||
|
|
||||||
|
displayDependencies.forEach(function(displayDependency){
|
||||||
|
Object.keys(displayDependency).forEach(function(name){
|
||||||
|
settings.on(name, setting.computeDependencies);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
setting.computeDependencies();
|
||||||
|
displayHidden.on(setting.computeDependencies);
|
||||||
|
}
|
||||||
|
|
||||||
settingsDisplay.map(function(groupDefinition){
|
settingsDisplay.map(function(groupDefinition){
|
||||||
const group = addGroup(groupDefinition);
|
const group = addGroup(groupDefinition);
|
||||||
groupDefinition.sections.forEach(function(sectionDefinition){
|
groupDefinition.sections.forEach(function(sectionDefinition){
|
||||||
const section = group.addSection(sectionDefinition);
|
const section = group.addSection(sectionDefinition);
|
||||||
sectionDefinition.settings.forEach(function(display){
|
sectionDefinition.settings.forEach(function(display){
|
||||||
var setting = settings.getDefinition(display.name);
|
let setting = settings.getDefinition(display.name);
|
||||||
if (!setting){
|
if (!setting){
|
||||||
if (display.inputs){
|
if (display.inputs){
|
||||||
setting = {
|
setting = {
|
||||||
@ -419,113 +540,17 @@
|
|||||||
if (setting){
|
if (setting){
|
||||||
setting.display = display;
|
setting.display = display;
|
||||||
|
|
||||||
let originalSet = setting.set;
|
setupSetterForDisplay(setting);
|
||||||
setting.originalSet = originalSet;
|
setupHideForDisplay(setting);
|
||||||
if (originalSet){
|
setupExpandForDisplay(setting);
|
||||||
const eventListeners = [];
|
|
||||||
beforeChangeEventListeners[setting.name] = eventListeners;
|
|
||||||
setting.set = function(...args){
|
|
||||||
if (eventListeners.every(function(listener){
|
|
||||||
return listener.call(setting, ...args);
|
|
||||||
})){
|
|
||||||
return originalSet.apply(this, args);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let hideChangeListeners = [];
|
const row = optionsGui.createSettingRow(setting);
|
||||||
setting.setHide = function setHide(value){
|
|
||||||
if (hideContainer){
|
|
||||||
hideContainer.setHideByName(display.name, value);
|
|
||||||
if (computeDependencies){
|
|
||||||
computeDependencies();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
setting.onHideChange = function(listener){
|
|
||||||
hideChangeListeners.push(listener);
|
|
||||||
};
|
|
||||||
setting.getHide = function getHide(){
|
|
||||||
if (hideContainer){
|
|
||||||
return hideContainer.getHideByName(display.name);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (hideContainer){
|
|
||||||
hideContainer.onHideChange(display.name, function(value){
|
|
||||||
if (computeDependencies){
|
|
||||||
computeDependencies();
|
|
||||||
}
|
|
||||||
hideChangeListeners.forEach(function(listener){
|
|
||||||
listener(value);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let expandChangeListeners = [];
|
|
||||||
setting.setExpand = function setExpand(value){
|
|
||||||
if (expandContainer){
|
|
||||||
expandContainer.setExpandByName(display.name, value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
setting.onExpandChange = function(listener){
|
|
||||||
expandChangeListeners.push(listener);
|
|
||||||
};
|
|
||||||
setting.getExpand = function getExpand(){
|
|
||||||
if (expandContainer){
|
|
||||||
return expandContainer.getExpandByName(display.name);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (expandContainer){
|
|
||||||
expandContainer.onExpandChange(display.name, function(value){
|
|
||||||
expandChangeListeners.forEach(function(listener){
|
|
||||||
listener(value);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var row = optionsGui.createSettingRow(setting);
|
|
||||||
settingStrings.getStrings(setting).forEach(function(string){
|
settingStrings.getStrings(setting).forEach(function(string){
|
||||||
search.register(string, row);
|
search.register(string, row);
|
||||||
});
|
});
|
||||||
section.addRow(row);
|
section.addRow(row);
|
||||||
if (!display.displayDependencies){
|
|
||||||
display.displayDependencies = {};
|
setupComputeDependenciesForDisplay(setting, section, row);
|
||||||
}
|
|
||||||
var displayDependencies = display.displayDependencies;
|
|
||||||
displayDependencies = Array.isArray(displayDependencies)?
|
|
||||||
displayDependencies:
|
|
||||||
[displayDependencies];
|
|
||||||
var computeDependencies = function(){
|
|
||||||
logging.verbose("evaluate display dependencies for", setting);
|
|
||||||
row.classList[(
|
|
||||||
(
|
|
||||||
displayHidden.get() ||
|
|
||||||
!setting.getHide()
|
|
||||||
) &&
|
|
||||||
displayDependencies.some(function(displayDependency){
|
|
||||||
return Object.keys(displayDependency).every(function(key){
|
|
||||||
return displayDependency[key].indexOf(settings[key]) !== -1;
|
|
||||||
});
|
|
||||||
})
|
|
||||||
)? "remove": "add"]("hidden");
|
|
||||||
section.updateDisplay();
|
|
||||||
};
|
|
||||||
computeDependencies();
|
|
||||||
displayDependencies.forEach(function(displayDependency){
|
|
||||||
Object.keys(displayDependency).forEach(function(name){
|
|
||||||
settings.on(name, computeDependencies);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
displayHidden.on(computeDependencies);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -538,6 +563,9 @@
|
|||||||
return response.json();
|
return response.json();
|
||||||
}).then(function(manifest){
|
}).then(function(manifest){
|
||||||
version.textContent = "Version " + manifest.version;
|
version.textContent = "Version " + manifest.version;
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
version.textContent = "Unable to get version: " + error;
|
||||||
});
|
});
|
||||||
document.body.appendChild(version);
|
document.body.appendChild(version);
|
||||||
|
|
||||||
@ -567,6 +595,9 @@
|
|||||||
if (addException){
|
if (addException){
|
||||||
settings.set("protectWindow", false, reCaptchaEntry);
|
settings.set("protectWindow", false, reCaptchaEntry);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
logging.warning("Error while adding reCaptcha exception:", error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -581,8 +612,11 @@
|
|||||||
}
|
}
|
||||||
).then((reallyShare) => {
|
).then((reallyShare) => {
|
||||||
if (reallyShare){
|
if (reallyShare){
|
||||||
this.originalSet(value, ...args);
|
return this.originalSet(value, ...args);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
logging.warning("Unable to set sharePersistentRndBetweenDomains:", error);
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -16,15 +16,15 @@
|
|||||||
const logging = require("../lib/logging");
|
const logging = require("../lib/logging");
|
||||||
|
|
||||||
function createDescription(setting){
|
function createDescription(setting){
|
||||||
var c = document.createElement("div");
|
const c = document.createElement("div");
|
||||||
c.className = "content";
|
c.className = "content";
|
||||||
|
|
||||||
var title = document.createElement("span");
|
const title = document.createElement("span");
|
||||||
title.className = "title";
|
title.className = "title";
|
||||||
title.textContent = extension.getTranslation(setting.name + "_title");
|
title.textContent = extension.getTranslation(setting.name + "_title");
|
||||||
c.appendChild(title);
|
c.appendChild(title);
|
||||||
|
|
||||||
var descriptionText = extension.getTranslation(setting.name + "_description");
|
let descriptionText = extension.getTranslation(setting.name + "_description");
|
||||||
if (setting.urlSpecific){
|
if (setting.urlSpecific){
|
||||||
const urlSpecificDescription = extension.getTranslation(setting.name + "_urlSpecific");
|
const urlSpecificDescription = extension.getTranslation(setting.name + "_urlSpecific");
|
||||||
if (urlSpecificDescription){
|
if (urlSpecificDescription){
|
||||||
@ -32,11 +32,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (descriptionText){
|
if (descriptionText){
|
||||||
var info = document.createElement("div");
|
const info = document.createElement("div");
|
||||||
info.className = "info";
|
info.className = "info";
|
||||||
c.appendChild(info);
|
c.appendChild(info);
|
||||||
|
|
||||||
var description = document.createElement("div");
|
const description = document.createElement("div");
|
||||||
description.className = "description";
|
description.className = "description";
|
||||||
description.textContent = descriptionText;
|
description.textContent = descriptionText;
|
||||||
info.appendChild(description);
|
info.appendChild(description);
|
||||||
@ -45,10 +45,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createSelect(setting){
|
function createSelect(setting){
|
||||||
var select = document.createElement("select");
|
const select = document.createElement("select");
|
||||||
select.dataset.type = typeof setting.defaultValue;
|
select.dataset.type = typeof setting.defaultValue;
|
||||||
setting.options.forEach(function(value){
|
setting.options.forEach(function(value){
|
||||||
var option = document.createElement("option");
|
const option = document.createElement("option");
|
||||||
if (typeof value === typeof setting.defaultValue){
|
if (typeof value === typeof setting.defaultValue){
|
||||||
option.value = value;
|
option.value = value;
|
||||||
if (setting.defaultValue === value){
|
if (setting.defaultValue === value){
|
||||||
@ -65,7 +65,7 @@
|
|||||||
return select;
|
return select;
|
||||||
}
|
}
|
||||||
|
|
||||||
var inputTypes = {
|
const inputTypes = {
|
||||||
number: {
|
number: {
|
||||||
input: function(value){
|
input: function(value){
|
||||||
const input = document.createElement("input");
|
const input = document.createElement("input");
|
||||||
@ -122,9 +122,191 @@
|
|||||||
object: false
|
object: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function createKeyInput(setting, url){
|
||||||
|
const input = document.createElement("table");
|
||||||
|
let inSection = false;
|
||||||
|
setting.keys.forEach(function(key){
|
||||||
|
if (setting.display.displayedSection){
|
||||||
|
if (typeof key === "object"){
|
||||||
|
if (key.level === 1){
|
||||||
|
inSection = key.name === setting.display.displayedSection;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!inSection){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let row = document.createElement("tr");
|
||||||
|
if (typeof key === "object"){
|
||||||
|
let cell = document.createElement("td");
|
||||||
|
cell.colSpan = 2;
|
||||||
|
let h = document.createElement("h" + (2 + (key.level || 1)));
|
||||||
|
h.textContent = key.message? extension.getTranslation(key.message): key.name;
|
||||||
|
cell.appendChild(h);
|
||||||
|
row.appendChild(cell);
|
||||||
|
input.appendChild(row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let nameCell = document.createElement("td");
|
||||||
|
nameCell.textContent = setting.display.replaceKeyPattern?
|
||||||
|
key.replace(setting.display.replaceKeyPattern, ""):
|
||||||
|
key;
|
||||||
|
row.appendChild(nameCell);
|
||||||
|
|
||||||
|
let keyType = inputTypes[typeof setting.defaultKeyValue];
|
||||||
|
let keyInput = keyType.input(setting.defaultKeyValue);
|
||||||
|
|
||||||
|
let inputCell = document.createElement("td");
|
||||||
|
inputCell.appendChild(keyInput);
|
||||||
|
row.appendChild(inputCell);
|
||||||
|
|
||||||
|
setting.on(function(){
|
||||||
|
const container = setting.get(url);
|
||||||
|
keyType.updateCallback(
|
||||||
|
keyInput,
|
||||||
|
container && container.hasOwnProperty(key)?
|
||||||
|
container[key]:
|
||||||
|
setting.defaultKeyValue,
|
||||||
|
url
|
||||||
|
);
|
||||||
|
});
|
||||||
|
keyInput.addEventListener("change", function(){
|
||||||
|
const value = keyType.getValue(keyInput);
|
||||||
|
let container = setting.get(url);
|
||||||
|
if (!container){
|
||||||
|
container = setting.defaultValue;
|
||||||
|
}
|
||||||
|
container[key] = value;
|
||||||
|
if (setting.set(container, url)){
|
||||||
|
logging.message("changed setting", setting.name, "(", key, "):", value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
container = setting.get(url);
|
||||||
|
keyType.updateCallback(
|
||||||
|
keyInput,
|
||||||
|
container && container.hasOwnProperty(key)?
|
||||||
|
container[key]:
|
||||||
|
setting.defaultKeyValue,
|
||||||
|
url
|
||||||
|
);
|
||||||
|
logging.message("setting", setting.name, "(", key, ") was not changed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
input.appendChild(row);
|
||||||
|
});
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPopulateUrlTable(setting, type, body){
|
||||||
|
return function populateUrlTable({newValue}){
|
||||||
|
body.innerHTML = "";
|
||||||
|
newValue.forEach(function(entry){
|
||||||
|
let row = document.createElement("tr");
|
||||||
|
let urlCell = document.createElement("td");
|
||||||
|
urlCell.classList.add("url");
|
||||||
|
urlCell.addEventListener("click", function(){
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.classList.add("urlInput");
|
||||||
|
input.style.width = urlCell.clientWidth + "px";
|
||||||
|
input.style.height = urlCell.clientHeight + "px";
|
||||||
|
urlCell.innerHTML = "";
|
||||||
|
urlCell.appendChild(input);
|
||||||
|
input.title = extension.getTranslation("inputURL");
|
||||||
|
input.value = entry.url;
|
||||||
|
input.focus();
|
||||||
|
input.addEventListener("blur", function(){
|
||||||
|
const url = input.value.trim();
|
||||||
|
if (url){
|
||||||
|
entry.url = url;
|
||||||
|
setting.urlContainer.refresh();
|
||||||
|
}
|
||||||
|
urlCell.removeChild(input);
|
||||||
|
urlCell.textContent = entry.url;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
urlCell.textContent = entry.url;
|
||||||
|
row.appendChild(urlCell);
|
||||||
|
let input = createInput(setting, entry.url);
|
||||||
|
type.updateCallback(input, setting.get(entry.url));
|
||||||
|
if (!entry.hasOwnProperty(setting.name)){
|
||||||
|
input.classList.add("notSpecifiedForUrl");
|
||||||
|
}
|
||||||
|
let inputCell = document.createElement("td");
|
||||||
|
inputCell.appendChild(input);
|
||||||
|
row.appendChild(inputCell);
|
||||||
|
let clearCell = document.createElement("td");
|
||||||
|
let clearButton = document.createElement("button");
|
||||||
|
clearButton.className = "reset";
|
||||||
|
clearButton.textContent = "\xD7";
|
||||||
|
clearButton.addEventListener("click", function(){
|
||||||
|
setting.reset(entry.url);
|
||||||
|
});
|
||||||
|
clearCell.appendChild(clearButton);
|
||||||
|
row.appendChild(clearCell);
|
||||||
|
body.appendChild(row);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function createUrlSpecificInput(setting, input, type){
|
||||||
|
const container = document.createElement("div");
|
||||||
|
container.className = "urlValues " + (setting.getExpand()? "expanded": "collapsed");
|
||||||
|
container.appendChild(input);
|
||||||
|
const collapser = document.createElement("button");
|
||||||
|
collapser.classList.add("collapser");
|
||||||
|
container.appendChild(collapser);
|
||||||
|
collapser.addEventListener("click", function(){
|
||||||
|
setting.setExpand(!setting.getExpand());
|
||||||
|
});
|
||||||
|
setting.onExpandChange(function(value){
|
||||||
|
container.classList[value? "remove": "add"]("collapsed");
|
||||||
|
container.classList[value? "add": "remove"]("expanded");
|
||||||
|
});
|
||||||
|
let urlTable = document.createElement("table");
|
||||||
|
let caption = document.createElement("caption");
|
||||||
|
caption.textContent = extension.getTranslation(setting.urlContainer.name + "_title");
|
||||||
|
urlTable.appendChild(caption);
|
||||||
|
let body = document.createElement("tbody");
|
||||||
|
urlTable.appendChild(body);
|
||||||
|
let foot = document.createElement("tfoot");
|
||||||
|
let footRow = document.createElement("tr");
|
||||||
|
let footCell = document.createElement("td");
|
||||||
|
footCell.colSpan = 3;
|
||||||
|
let newInput = document.createElement("input");
|
||||||
|
newInput.className = "inputURL";
|
||||||
|
newInput.title = extension.getTranslation("inputURL");
|
||||||
|
const addURLSetting = function(){
|
||||||
|
const url = newInput.value.trim();
|
||||||
|
if (url){
|
||||||
|
setting.set(setting.get(url), url);
|
||||||
|
newInput.value = "";
|
||||||
|
newInput.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
newInput.addEventListener("keypress", function(event){
|
||||||
|
if ([10, 13].indexOf(event.keyCode) !== -1){
|
||||||
|
addURLSetting();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
footCell.appendChild(newInput);
|
||||||
|
let footPlus = document.createElement("button");
|
||||||
|
footPlus.classList.add("add");
|
||||||
|
footPlus.textContent = "+";
|
||||||
|
footPlus.addEventListener("click", addURLSetting);
|
||||||
|
footCell.appendChild(footPlus);
|
||||||
|
footRow.appendChild(footCell);
|
||||||
|
foot.appendChild(footRow);
|
||||||
|
urlTable.appendChild(foot);
|
||||||
|
container.appendChild(urlTable);
|
||||||
|
|
||||||
|
setting.urlContainer.on(getPopulateUrlTable(setting, type, body));
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
function createInput(setting, url = ""){
|
function createInput(setting, url = ""){
|
||||||
var type = inputTypes[typeof setting.defaultValue];
|
const type = inputTypes[typeof setting.defaultValue];
|
||||||
var input;
|
let input;
|
||||||
if (setting.options){
|
if (setting.options){
|
||||||
input = createSelect(setting);
|
input = createSelect(setting);
|
||||||
}
|
}
|
||||||
@ -136,7 +318,7 @@
|
|||||||
if (type){
|
if (type){
|
||||||
setting.on(function(){type.updateCallback(input, setting.get(url));}, url);
|
setting.on(function(){type.updateCallback(input, setting.get(url));}, url);
|
||||||
input.addEventListener("change", function(){
|
input.addEventListener("change", function(){
|
||||||
var value = type.getValue(input);
|
const value = type.getValue(input);
|
||||||
if (setting.set(value, url)){
|
if (setting.set(value, url)){
|
||||||
logging.message("changed setting", setting.name, ":", value);
|
logging.message("changed setting", setting.name, ":", value);
|
||||||
}
|
}
|
||||||
@ -147,211 +329,41 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (setting.keys){
|
else if (setting.keys){
|
||||||
input = document.createElement("table");
|
input = createKeyInput(setting, url);
|
||||||
let inSection = false;
|
|
||||||
setting.keys.forEach(function(key){
|
|
||||||
if (setting.display.displayedSection){
|
|
||||||
if (typeof key === "object"){
|
|
||||||
if (key.level === 1){
|
|
||||||
inSection = key.name === setting.display.displayedSection;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!inSection){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let row = document.createElement("tr");
|
|
||||||
if (typeof key === "object"){
|
|
||||||
let cell = document.createElement("td");
|
|
||||||
cell.colSpan = 2;
|
|
||||||
let h = document.createElement("h" + (2 + (key.level || 1)));
|
|
||||||
h.textContent = key.message? extension.getTranslation(key.message): key.name;
|
|
||||||
cell.appendChild(h);
|
|
||||||
row.appendChild(cell);
|
|
||||||
input.appendChild(row);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let nameCell = document.createElement("td");
|
|
||||||
nameCell.textContent = setting.display.replaceKeyPattern?
|
|
||||||
key.replace(setting.display.replaceKeyPattern, ""):
|
|
||||||
key;
|
|
||||||
row.appendChild(nameCell);
|
|
||||||
|
|
||||||
let keyType = inputTypes[typeof setting.defaultKeyValue];
|
|
||||||
let keyInput = keyType.input(setting.defaultKeyValue);
|
|
||||||
|
|
||||||
let inputCell = document.createElement("td");
|
|
||||||
inputCell.appendChild(keyInput);
|
|
||||||
row.appendChild(inputCell);
|
|
||||||
|
|
||||||
setting.on(function(){
|
|
||||||
var container = setting.get(url);
|
|
||||||
keyType.updateCallback(
|
|
||||||
keyInput,
|
|
||||||
container && container.hasOwnProperty(key)?
|
|
||||||
container[key]:
|
|
||||||
setting.defaultKeyValue,
|
|
||||||
url
|
|
||||||
);
|
|
||||||
});
|
|
||||||
keyInput.addEventListener("change", function(){
|
|
||||||
var value = keyType.getValue(keyInput);
|
|
||||||
var container = setting.get(url);
|
|
||||||
if (!container){
|
|
||||||
container = setting.defaultValue;
|
|
||||||
}
|
|
||||||
container[key] = value;
|
|
||||||
if (setting.set(container, url)){
|
|
||||||
logging.message("changed setting", setting.name, "(", key, "):", value);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
container = setting.get(url);
|
|
||||||
keyType.updateCallback(
|
|
||||||
keyInput,
|
|
||||||
container && container.hasOwnProperty(key)?
|
|
||||||
container[key]:
|
|
||||||
setting.defaultKeyValue,
|
|
||||||
url
|
|
||||||
);
|
|
||||||
logging.message("setting", setting.name, "(", key, ") was not changed");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
input.appendChild(row);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setting.urlSpecific && url === ""){
|
if (setting.urlSpecific && url === ""){
|
||||||
let container = document.createElement("div");
|
return createUrlSpecificInput(setting, input, type);
|
||||||
container.className = "urlValues " + (setting.getExpand()? "expanded": "collapsed");
|
|
||||||
container.appendChild(input);
|
|
||||||
var collapser = document.createElement("button");
|
|
||||||
collapser.classList.add("collapser");
|
|
||||||
container.appendChild(collapser);
|
|
||||||
collapser.addEventListener("click", function(){
|
|
||||||
setting.setExpand(!setting.getExpand());
|
|
||||||
});
|
|
||||||
setting.onExpandChange(function(value){
|
|
||||||
container.classList[value? "remove": "add"]("collapsed");
|
|
||||||
container.classList[value? "add": "remove"]("expanded");
|
|
||||||
});
|
|
||||||
let urlTable = document.createElement("table");
|
|
||||||
let caption = document.createElement("caption");
|
|
||||||
caption.textContent = extension.getTranslation(setting.urlContainer.name + "_title");
|
|
||||||
urlTable.appendChild(caption);
|
|
||||||
let body = document.createElement("tbody");
|
|
||||||
urlTable.appendChild(body);
|
|
||||||
let foot = document.createElement("tfoot");
|
|
||||||
let footRow = document.createElement("tr");
|
|
||||||
let footCell = document.createElement("td");
|
|
||||||
footCell.colSpan = 3;
|
|
||||||
let newInput = document.createElement("input");
|
|
||||||
newInput.className = "inputURL";
|
|
||||||
newInput.title = extension.getTranslation("inputURL");
|
|
||||||
const addURLSetting = function(){
|
|
||||||
var url = newInput.value.trim();
|
|
||||||
if (url){
|
|
||||||
setting.set(setting.get(url), url);
|
|
||||||
newInput.value = "";
|
|
||||||
newInput.focus();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
newInput.addEventListener("keypress", function(event){
|
|
||||||
if ([10, 13].indexOf(event.keyCode) !== -1){
|
|
||||||
addURLSetting();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
footCell.appendChild(newInput);
|
|
||||||
let footPlus = document.createElement("button");
|
|
||||||
footPlus.classList.add("add");
|
|
||||||
footPlus.textContent = "+";
|
|
||||||
footPlus.addEventListener("click", addURLSetting);
|
|
||||||
footCell.appendChild(footPlus);
|
|
||||||
footRow.appendChild(footCell);
|
|
||||||
foot.appendChild(footRow);
|
|
||||||
urlTable.appendChild(foot);
|
|
||||||
container.appendChild(urlTable);
|
|
||||||
|
|
||||||
setting.urlContainer.on(function({newValue}){
|
|
||||||
body.innerHTML = "";
|
|
||||||
newValue.forEach(function(entry){
|
|
||||||
let row = document.createElement("tr");
|
|
||||||
let urlCell = document.createElement("td");
|
|
||||||
urlCell.classList.add("url");
|
|
||||||
urlCell.addEventListener("click", function(){
|
|
||||||
var input = document.createElement("input");
|
|
||||||
input.classList.add("urlInput");
|
|
||||||
input.style.width = urlCell.clientWidth + "px";
|
|
||||||
input.style.height = urlCell.clientHeight + "px";
|
|
||||||
urlCell.innerHTML = "";
|
|
||||||
urlCell.appendChild(input);
|
|
||||||
input.title = extension.getTranslation("inputURL");
|
|
||||||
input.value = entry.url;
|
|
||||||
input.focus();
|
|
||||||
input.addEventListener("blur", function(){
|
|
||||||
var url = input.value.trim();
|
|
||||||
if (url){
|
|
||||||
entry.url = url;
|
|
||||||
setting.urlContainer.refresh();
|
|
||||||
}
|
|
||||||
urlCell.removeChild(input);
|
|
||||||
urlCell.textContent = entry.url;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
urlCell.textContent = entry.url;
|
|
||||||
row.appendChild(urlCell);
|
|
||||||
let input = createInput(setting, entry.url);
|
|
||||||
type.updateCallback(input, setting.get(entry.url));
|
|
||||||
if (!entry.hasOwnProperty(setting.name)){
|
|
||||||
input.classList.add("notSpecifiedForUrl");
|
|
||||||
}
|
|
||||||
let inputCell = document.createElement("td");
|
|
||||||
inputCell.appendChild(input);
|
|
||||||
row.appendChild(inputCell);
|
|
||||||
let clearCell = document.createElement("td");
|
|
||||||
let clearButton = document.createElement("button");
|
|
||||||
clearButton.className = "reset";
|
|
||||||
clearButton.textContent = "\xD7";
|
|
||||||
clearButton.addEventListener("click", function(){
|
|
||||||
setting.reset(entry.url);
|
|
||||||
});
|
|
||||||
clearCell.appendChild(clearButton);
|
|
||||||
row.appendChild(clearCell);
|
|
||||||
body.appendChild(row);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return container;
|
|
||||||
}
|
}
|
||||||
return input || document.createElement("span");
|
return input || document.createElement("span");
|
||||||
}
|
}
|
||||||
|
|
||||||
function createButton(setting){
|
function createButton(setting){
|
||||||
var button = document.createElement("button");
|
const button = document.createElement("button");
|
||||||
button.textContent = extension.getTranslation(setting.name + "_label");
|
button.textContent = extension.getTranslation(setting.name + "_label");
|
||||||
button.addEventListener("click", setting.action);
|
button.addEventListener("click", setting.action);
|
||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createInteraction(setting){
|
function createInteraction(setting){
|
||||||
var c = document.createElement("div");
|
const c = document.createElement("div");
|
||||||
c.className = "content";
|
c.className = "content";
|
||||||
|
|
||||||
var interaction;
|
let interaction;
|
||||||
if (setting.action){
|
if (setting.action){
|
||||||
interaction = createButton(setting);
|
interaction = createButton(setting);
|
||||||
}
|
}
|
||||||
else if (setting.actions){
|
else if (setting.actions){
|
||||||
interaction = document.createElement("span");
|
interaction = document.createElement("span");
|
||||||
setting.actions.forEach(function(action){
|
setting.actions.forEach(function(action){
|
||||||
var button = createButton(action);
|
const button = createButton(action);
|
||||||
interaction.appendChild(button);
|
interaction.appendChild(button);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (setting.inputs){
|
else if (setting.inputs){
|
||||||
interaction = document.createElement("span");
|
interaction = document.createElement("span");
|
||||||
setting.inputs.forEach(function(inputSetting){
|
setting.inputs.forEach(function(inputSetting){
|
||||||
var input = createInput(inputSetting);
|
const input = createInput(inputSetting);
|
||||||
input.classList.add("multiple" + setting.inputs.length);
|
input.classList.add("multiple" + setting.inputs.length);
|
||||||
interaction.appendChild(input);
|
interaction.appendChild(input);
|
||||||
});
|
});
|
||||||
@ -369,10 +381,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createHide(setting){
|
function createHide(setting){
|
||||||
var label = document.createElement("label");
|
const label = document.createElement("label");
|
||||||
label.className = "content hideContent";
|
label.className = "content hideContent";
|
||||||
label.title = extension.getTranslation("hideSetting");
|
label.title = extension.getTranslation("hideSetting");
|
||||||
var input = document.createElement("input");
|
const input = document.createElement("input");
|
||||||
input.type = "checkbox";
|
input.type = "checkbox";
|
||||||
input.className = "hide";
|
input.className = "hide";
|
||||||
input.checked = setting.getHide();
|
input.checked = setting.getHide();
|
||||||
@ -384,26 +396,26 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
label.appendChild(input);
|
label.appendChild(input);
|
||||||
var display = document.createElement("span");
|
const display = document.createElement("span");
|
||||||
display.className = "display";
|
display.className = "display";
|
||||||
label.appendChild(display);
|
label.appendChild(display);
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSettingRow(setting){
|
function createSettingRow(setting){
|
||||||
var tr = document.createElement("tr");
|
const tr = document.createElement("tr");
|
||||||
tr.className = "settingRow";
|
tr.className = "settingRow";
|
||||||
|
|
||||||
var hide = document.createElement("td");
|
const hide = document.createElement("td");
|
||||||
hide.className = "hideColumn";
|
hide.className = "hideColumn";
|
||||||
hide.appendChild(createHide(setting));
|
hide.appendChild(createHide(setting));
|
||||||
tr.appendChild(hide);
|
tr.appendChild(hide);
|
||||||
|
|
||||||
var left = document.createElement("td");
|
const left = document.createElement("td");
|
||||||
left.appendChild(createDescription(setting));
|
left.appendChild(createDescription(setting));
|
||||||
tr.appendChild(left);
|
tr.appendChild(left);
|
||||||
|
|
||||||
var right = document.createElement("td");
|
const right = document.createElement("td");
|
||||||
right.appendChild(createInteraction(setting));
|
right.appendChild(createInteraction(setting));
|
||||||
tr.appendChild(right);
|
tr.appendChild(right);
|
||||||
|
|
||||||
@ -434,7 +446,7 @@
|
|||||||
displayHiddenDescription.appendChild(createDescription(displayHidden));
|
displayHiddenDescription.appendChild(createDescription(displayHidden));
|
||||||
displayHiddenRow.appendChild(displayHiddenDescription);
|
displayHiddenRow.appendChild(displayHiddenDescription);
|
||||||
|
|
||||||
var displayHiddenInteraction = document.createElement("td");
|
const displayHiddenInteraction = document.createElement("td");
|
||||||
displayHiddenInteraction.appendChild(createInteraction(displayHidden));
|
displayHiddenInteraction.appendChild(createInteraction(displayHidden));
|
||||||
displayHiddenRow.appendChild(displayHiddenInteraction);
|
displayHiddenRow.appendChild(displayHiddenInteraction);
|
||||||
tHead.appendChild(displayHiddenRow);
|
tHead.appendChild(displayHiddenRow);
|
||||||
|
@ -12,93 +12,103 @@
|
|||||||
const searchParameters = new URLSearchParams(window.location.search);
|
const searchParameters = new URLSearchParams(window.location.search);
|
||||||
require("./theme").init("presets");
|
require("./theme").init("presets");
|
||||||
|
|
||||||
|
function buildPresetSettingGui(setting, value){
|
||||||
|
function valueToText(value){
|
||||||
|
switch (typeof value){
|
||||||
|
case "string":
|
||||||
|
return extension.getTranslation(`${setting}_options.${value}`);
|
||||||
|
case "boolean":
|
||||||
|
return value? "\u2713": "\u00D7";
|
||||||
|
default:
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const container = document.createElement("li");
|
||||||
|
container.textContent = extension.getTranslation(`${setting}_title`) + ": ";
|
||||||
|
if ((typeof value) === "object"){
|
||||||
|
const urlValues = document.createElement("ul");
|
||||||
|
Object.keys(value).map(function(url){
|
||||||
|
const container = document.createElement("li");
|
||||||
|
container.className = "urlValue";
|
||||||
|
container.textContent = url + ": " +
|
||||||
|
valueToText(value[url]) +
|
||||||
|
" (" + valueToText(settings.get(setting, url)) +")";
|
||||||
|
return container;
|
||||||
|
|
||||||
|
}).forEach(function(node){
|
||||||
|
urlValues.appendChild(node);
|
||||||
|
});
|
||||||
|
container.appendChild(urlValues);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
container.appendChild(document.createTextNode(
|
||||||
|
`${valueToText(value)} (${valueToText(settings.get(setting))})`
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildPresetGui(presetName, preset){
|
||||||
|
const container = document.createElement("div");
|
||||||
|
container.className = "preset " + presetName;
|
||||||
|
const title = document.createElement("h1");
|
||||||
|
title.className = "title";
|
||||||
|
title.textContent = extension.getTranslation(`preset_${presetName}_title`);
|
||||||
|
container.appendChild(title);
|
||||||
|
|
||||||
|
const description = document.createElement("div");
|
||||||
|
description.className = "description";
|
||||||
|
description.textContent = extension.getTranslation(`preset_${presetName}_description`);
|
||||||
|
container.appendChild(description);
|
||||||
|
|
||||||
|
const settingsList = document.createElement("ul");
|
||||||
|
settingsList.className = "settings";
|
||||||
|
container.appendChild(settingsList);
|
||||||
|
|
||||||
|
Object.keys(preset).map(function(settingName){
|
||||||
|
return buildPresetSettingGui(settingName, preset[settingName]);
|
||||||
|
}).forEach(function(node){
|
||||||
|
settingsList.appendChild(node);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (settingsList.childNodes.length){
|
||||||
|
const button = document.createElement("button");
|
||||||
|
button.textContent = extension.getTranslation("apply");
|
||||||
|
button.addEventListener("click", function(){
|
||||||
|
Promise.all(Object.keys(preset).map(function(settingName){
|
||||||
|
const value = preset[settingName];
|
||||||
|
if ((typeof value) === "object"){
|
||||||
|
return Promise.all(Object.keys(value).map(function(url){
|
||||||
|
return settings.set(settingName, value[url], url);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return settings.set(settingName, value);
|
||||||
|
}
|
||||||
|
})).then(function(){
|
||||||
|
window.location.reload();
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
logging.warning("Unable to apply preset:", error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
container.appendChild(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
Promise.all([
|
Promise.all([
|
||||||
settings.loaded,
|
settings.loaded,
|
||||||
fetch("presets.json").then(function(data){
|
fetch("presets.json").then(function(data){
|
||||||
return data.json();
|
return data.json();
|
||||||
})
|
})
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
]).then(function([settingsLoaded, presets]){
|
]).then(function([settingsLoaded, presets]){
|
||||||
Object.keys(presets).map(function(presetName){
|
Object.keys(presets).map(function(presetName){
|
||||||
const preset = presets[presetName];
|
return buildPresetGui(presetName, presets[presetName]);
|
||||||
const container = document.createElement("div");
|
|
||||||
container.className = "preset " + presetName;
|
|
||||||
const title = document.createElement("h1");
|
|
||||||
title.className = "title";
|
|
||||||
title.textContent = extension.getTranslation(`preset_${presetName}_title`);
|
|
||||||
container.appendChild(title);
|
|
||||||
|
|
||||||
const description = document.createElement("div");
|
|
||||||
description.className = "description";
|
|
||||||
description.textContent = extension.getTranslation(`preset_${presetName}_description`);
|
|
||||||
container.appendChild(description);
|
|
||||||
|
|
||||||
const settingsList = document.createElement("ul");
|
|
||||||
settingsList.className = "settings";
|
|
||||||
container.appendChild(settingsList);
|
|
||||||
|
|
||||||
Object.keys(preset).map(function(settingName){
|
|
||||||
function valueToText(value){
|
|
||||||
switch (typeof value){
|
|
||||||
case "string":
|
|
||||||
return extension.getTranslation(`${settingName}_options.${value}`);
|
|
||||||
case "boolean":
|
|
||||||
return value? "\u2713": "\u00D7";
|
|
||||||
default:
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const value = preset[settingName];
|
|
||||||
const container = document.createElement("li");
|
|
||||||
container.textContent = extension.getTranslation(`${settingName}_title`) + ": ";
|
|
||||||
if ((typeof value) === "object"){
|
|
||||||
const urlValues = document.createElement("ul");
|
|
||||||
Object.keys(value).map(function(url){
|
|
||||||
var container = document.createElement("li");
|
|
||||||
container.className = "urlValue";
|
|
||||||
container.textContent = url + ": " +
|
|
||||||
valueToText(value[url]) +
|
|
||||||
" (" + valueToText(settings.get(settingName, url)) +")";
|
|
||||||
return container;
|
|
||||||
|
|
||||||
}).forEach(function(node){
|
|
||||||
urlValues.appendChild(node);
|
|
||||||
});
|
|
||||||
container.appendChild(urlValues);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
container.appendChild(document.createTextNode(
|
|
||||||
`${valueToText(value)} (${valueToText(settings.get(settingName))})`
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}).forEach(function(node){
|
|
||||||
settingsList.appendChild(node);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (settingsList.childNodes.length){
|
|
||||||
const button = document.createElement("button");
|
|
||||||
button.textContent = extension.getTranslation("apply");
|
|
||||||
button.addEventListener("click", function(){
|
|
||||||
Promise.all(Object.keys(preset).map(function(settingName){
|
|
||||||
const value = preset[settingName];
|
|
||||||
if ((typeof value) === "object"){
|
|
||||||
return Promise.all(Object.keys(value).map(function(url){
|
|
||||||
return settings.set(settingName, value[url], url);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return settings.set(settingName, value);
|
|
||||||
}
|
|
||||||
})).then(function(){
|
|
||||||
window.location.reload();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
container.appendChild(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}).forEach(function(node){
|
}).forEach(function(node){
|
||||||
document.body.appendChild(node);
|
document.body.appendChild(node);
|
||||||
});
|
});
|
||||||
@ -131,6 +141,9 @@
|
|||||||
document.body.style.fontSize = fontSize + "px";
|
document.body.style.fontSize = fontSize + "px";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
logging.warning("Unable to setup presets:", error);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.querySelector("head title").textContent = extension.getTranslation("presets_title");
|
document.querySelector("head title").textContent = extension.getTranslation("presets_title");
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var scope;
|
let scope;
|
||||||
if ((typeof exports) !== "undefined"){
|
if ((typeof exports) !== "undefined"){
|
||||||
scope = exports;
|
scope = exports;
|
||||||
}
|
}
|
||||||
@ -84,8 +84,6 @@
|
|||||||
{mainFlag: "protectScreen", section: "Screen-API"},
|
{mainFlag: "protectScreen", section: "Screen-API"},
|
||||||
].forEach(function(api){
|
].forEach(function(api){
|
||||||
if (settings.get(api.mainFlag) !== (api.mainFlagDisabledValue || false)){
|
if (settings.get(api.mainFlag) !== (api.mainFlagDisabledValue || false)){
|
||||||
let inSection = false;
|
|
||||||
let anyActive = false;
|
|
||||||
if (getSectionKeys(api.section).every(function(key){
|
if (getSectionKeys(api.section).every(function(key){
|
||||||
return protectedFeaturesValue.hasOwnProperty(key) &&
|
return protectedFeaturesValue.hasOwnProperty(key) &&
|
||||||
!protectedFeaturesValue[key];
|
!protectedFeaturesValue[key];
|
||||||
|
@ -9,12 +9,12 @@
|
|||||||
require("../lib/theme").init("sanitize");
|
require("../lib/theme").init("sanitize");
|
||||||
const sanitationRules = require("./sanitationRules");
|
const sanitationRules = require("./sanitationRules");
|
||||||
|
|
||||||
var title = document.createElement("h1");
|
const title = document.createElement("h1");
|
||||||
title.className = "title";
|
title.className = "title";
|
||||||
title.textContent = extension.getTranslation("sanitation_title");
|
title.textContent = extension.getTranslation("sanitation_title");
|
||||||
document.body.appendChild(title);
|
document.body.appendChild(title);
|
||||||
|
|
||||||
var description = document.createElement("div");
|
const description = document.createElement("div");
|
||||||
description.className = "description";
|
description.className = "description";
|
||||||
description.textContent = extension.getTranslation("sanitation_description");
|
description.textContent = extension.getTranslation("sanitation_description");
|
||||||
document.body.appendChild(description);
|
document.body.appendChild(description);
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
/* 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/. */
|
||||||
/* eslint max-lines: off*/
|
|
||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
var settingsDisplay = [
|
const settingsDisplay = [
|
||||||
{
|
{
|
||||||
name: "general",
|
name: "general",
|
||||||
sections: [
|
sections: [
|
||||||
|
@ -11,13 +11,59 @@
|
|||||||
const searchParameters = new URLSearchParams(window.location.search);
|
const searchParameters = new URLSearchParams(window.location.search);
|
||||||
|
|
||||||
|
|
||||||
var title = document.createElement("h1");
|
const title = document.createElement("h1");
|
||||||
title.className = "title";
|
title.className = "title";
|
||||||
title.textContent = extension.getTranslation("whitelist_inspection_title");
|
title.textContent = extension.getTranslation("whitelist_inspection_title");
|
||||||
document.body.appendChild(title);
|
document.body.appendChild(title);
|
||||||
|
|
||||||
document.querySelector("head title").textContent = title.textContent;
|
document.querySelector("head title").textContent = title.textContent;
|
||||||
|
|
||||||
|
|
||||||
|
const whitelistSettings = [
|
||||||
|
{
|
||||||
|
title: extension.getTranslation("whitelist_all_apis"),
|
||||||
|
name: "blockMode",
|
||||||
|
whitelistValue: "allow",
|
||||||
|
protectedValue: "fake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: extension.getTranslation("section_canvas-api"),
|
||||||
|
name: "protectedCanvasPart",
|
||||||
|
whitelistValue: "nothing",
|
||||||
|
protectedValue: "readout"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: extension.getTranslation("section_audio-api"),
|
||||||
|
name: "protectAudio",
|
||||||
|
whitelistValue: false,
|
||||||
|
protectedValue: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: extension.getTranslation("section_history-api"),
|
||||||
|
name: "historyLengthThreshold",
|
||||||
|
whitelistValue: 10000,
|
||||||
|
protectedValue: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: extension.getTranslation("section_window-api"),
|
||||||
|
name: "protectWindow",
|
||||||
|
whitelistValue: false,
|
||||||
|
protectedValue: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: extension.getTranslation("section_DOMRect-api"),
|
||||||
|
name: "protectDOMRect",
|
||||||
|
whitelistValue: false,
|
||||||
|
protectedValue: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: extension.getTranslation("section_navigator-api"),
|
||||||
|
name: "protectNavigator",
|
||||||
|
whitelistValue: false,
|
||||||
|
protectedValue: true
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
settings.onloaded(function(){
|
settings.onloaded(function(){
|
||||||
const sets = settingContainers.urlContainer.get();
|
const sets = settingContainers.urlContainer.get();
|
||||||
|
|
||||||
@ -47,51 +93,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const whitelistSettings = [
|
|
||||||
{
|
|
||||||
title: extension.getTranslation("whitelist_all_apis"),
|
|
||||||
name: "blockMode",
|
|
||||||
whitelistValue: "allow",
|
|
||||||
protectedValue: "fake"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: extension.getTranslation("section_canvas-api"),
|
|
||||||
name: "protectedCanvasPart",
|
|
||||||
whitelistValue: "nothing",
|
|
||||||
protectedValue: "readout"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: extension.getTranslation("section_audio-api"),
|
|
||||||
name: "protectAudio",
|
|
||||||
whitelistValue: false,
|
|
||||||
protectedValue: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: extension.getTranslation("section_history-api"),
|
|
||||||
name: "historyLengthThreshold",
|
|
||||||
whitelistValue: 10000,
|
|
||||||
protectedValue: 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: extension.getTranslation("section_window-api"),
|
|
||||||
name: "protectWindow",
|
|
||||||
whitelistValue: false,
|
|
||||||
protectedValue: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: extension.getTranslation("section_DOMRect-api"),
|
|
||||||
name: "protectDOMRect",
|
|
||||||
whitelistValue: false,
|
|
||||||
protectedValue: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: extension.getTranslation("section_navigator-api"),
|
|
||||||
name: "protectNavigator",
|
|
||||||
whitelistValue: false,
|
|
||||||
protectedValue: true
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const table = document.createElement("table");
|
const table = document.createElement("table");
|
||||||
whitelistSettings.forEach(function(setting){
|
whitelistSettings.forEach(function(setting){
|
||||||
const row = document.createElement("tr");
|
const row = document.createElement("tr");
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
const addToContainer = function(){
|
const addToContainer = function(){
|
||||||
const container = document.getElementById("prints");
|
const container = document.getElementById("prints");
|
||||||
container.querySelector("li").textContent = extension.getTranslation("pleaseWait");
|
container.querySelector("li").textContent = extension.getTranslation("pleaseWait");
|
||||||
var first = true;
|
let first = true;
|
||||||
|
|
||||||
return function addToContainer(domainNotification){
|
return function addToContainer(domainNotification){
|
||||||
if (first){
|
if (first){
|
||||||
@ -105,10 +105,10 @@
|
|||||||
this.textNode = function(){
|
this.textNode = function(){
|
||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
var messageParts = extension.getTranslation(this.messageId).split(/\{url\}/g);
|
const messageParts = extension.getTranslation(this.messageId).split(/\{url\}/g);
|
||||||
node.appendChild(document.createTextNode(messageParts.shift()));
|
node.appendChild(document.createTextNode(messageParts.shift()));
|
||||||
while (messageParts.length){
|
while (messageParts.length){
|
||||||
var urlSpan = document.createElement("span");
|
const urlSpan = document.createElement("span");
|
||||||
urlSpan.textContent = this.domain || extension.getTranslation("localFile");
|
urlSpan.textContent = this.domain || extension.getTranslation("localFile");
|
||||||
urlSpan.className = "url hasHiddenActions";
|
urlSpan.className = "url hasHiddenActions";
|
||||||
urlSpan.appendChild(this.actionsNode());
|
urlSpan.appendChild(this.actionsNode());
|
||||||
@ -116,7 +116,7 @@
|
|||||||
node.appendChild(document.createTextNode(messageParts.shift()));
|
node.appendChild(document.createTextNode(messageParts.shift()));
|
||||||
}
|
}
|
||||||
node.appendChild(document.createTextNode(" ("));
|
node.appendChild(document.createTextNode(" ("));
|
||||||
var countSpan = document.createElement("span");
|
const countSpan = document.createElement("span");
|
||||||
countSpan.className = "count";
|
countSpan.className = "count";
|
||||||
countSpan.textContent = "0";
|
countSpan.textContent = "0";
|
||||||
node.appendChild(countSpan);
|
node.appendChild(countSpan);
|
||||||
@ -168,7 +168,7 @@
|
|||||||
const domains = new Map();
|
const domains = new Map();
|
||||||
const domainNotification = function(url, messageId, count = 0, api = ""){
|
const domainNotification = function(url, messageId, count = 0, api = ""){
|
||||||
const domain = url.hostname;
|
const domain = url.hostname;
|
||||||
var domainNotification = domains.get(domain + messageId);
|
let domainNotification = domains.get(domain + messageId);
|
||||||
if (!domainNotification){
|
if (!domainNotification){
|
||||||
domainNotification = new DomainNotification(url, messageId, count, api);
|
domainNotification = new DomainNotification(url, messageId, count, api);
|
||||||
domains.set(domain + messageId, domainNotification);
|
domains.set(domain + messageId, domainNotification);
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
scope = require.register("./gui", {});
|
scope = require.register("./gui", {});
|
||||||
}
|
}
|
||||||
|
|
||||||
const {error, warning, message, notice, verbose, setPrefix: setLogPrefix} = require("../lib/logging");
|
const logging = require("../lib/logging");
|
||||||
const extension = require("../lib/extension");
|
const extension = require("../lib/extension");
|
||||||
|
|
||||||
scope.createCollapser = function(){
|
scope.createCollapser = function(){
|
||||||
@ -23,11 +23,11 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
return function createCollapser(container){
|
return function createCollapser(container){
|
||||||
var collapser = document.createElement("span");
|
const collapser = document.createElement("span");
|
||||||
collapser.className = "collapser";
|
collapser.className = "collapser";
|
||||||
|
|
||||||
["more", "less"].forEach(function(type){
|
["more", "less"].forEach(function(type){
|
||||||
var span = document.createElement("span");
|
const span = document.createElement("span");
|
||||||
span.className = type;
|
span.className = type;
|
||||||
span.textContent = messages[type];
|
span.textContent = messages[type];
|
||||||
collapser.appendChild(span);
|
collapser.appendChild(span);
|
||||||
@ -44,13 +44,13 @@
|
|||||||
|
|
||||||
|
|
||||||
scope.createActionButtons = function createActionButtons(container, actions, data, horizontal){
|
scope.createActionButtons = function createActionButtons(container, actions, data, horizontal){
|
||||||
actions.forEach(function(action, i){
|
actions.forEach(function(action){
|
||||||
var button = document.createElement("button");
|
const button = document.createElement("button");
|
||||||
button.className = action.name + " action";
|
button.className = action.name + " action";
|
||||||
button.title = extension.getTranslation(action.name);
|
button.title = extension.getTranslation(action.name);
|
||||||
if (action.isIcon || action.icon){
|
if (action.isIcon || action.icon){
|
||||||
button.classList.add("isIcon");
|
button.classList.add("isIcon");
|
||||||
var img = document.createElement("img");
|
const img = document.createElement("img");
|
||||||
button.appendChild(img);
|
button.appendChild(img);
|
||||||
img.src = "../icons/" + (action.icon || `pageAction-${action.name}.svg`);
|
img.src = "../icons/" + (action.icon || `pageAction-${action.name}.svg`);
|
||||||
}
|
}
|
||||||
@ -66,8 +66,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
scope.modalChoice = function modalChoice(messageText, choices){
|
scope.modalChoice = function modalChoice(messageText, choices){
|
||||||
message("open modal choice");
|
logging.message("open modal choice");
|
||||||
return new Promise(function(resolve, reject){
|
return new Promise(function(resolve){
|
||||||
document.body.innerHTML = "";
|
document.body.innerHTML = "";
|
||||||
document.body.className = "modal";
|
document.body.className = "modal";
|
||||||
document.body.appendChild(document.createTextNode(messageText));
|
document.body.appendChild(document.createTextNode(messageText));
|
||||||
@ -77,7 +77,7 @@
|
|||||||
const button = document.createElement("button");
|
const button = document.createElement("button");
|
||||||
button.addEventListener("click", function(){
|
button.addEventListener("click", function(){
|
||||||
resolve(choice.value || choice);
|
resolve(choice.value || choice);
|
||||||
message("modal choice closed with value", choice.value || choice);
|
logging.message("modal choice closed with value", choice.value || choice);
|
||||||
});
|
});
|
||||||
button.appendChild(document.createTextNode(choice.text || choice));
|
button.appendChild(document.createTextNode(choice.text || choice));
|
||||||
stack.appendChild(button);
|
stack.appendChild(button);
|
||||||
@ -87,8 +87,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
scope.modalPrompt = function modalPrompt(messageText, defaultValue){
|
scope.modalPrompt = function modalPrompt(messageText, defaultValue){
|
||||||
message("open modal prompt");
|
logging.message("open modal prompt");
|
||||||
return new Promise(function(resolve, reject){
|
return new Promise(function(resolve){
|
||||||
document.body.innerHTML = "";
|
document.body.innerHTML = "";
|
||||||
document.body.className = "modal";
|
document.body.className = "modal";
|
||||||
document.body.appendChild(document.createTextNode(messageText));
|
document.body.appendChild(document.createTextNode(messageText));
|
||||||
@ -101,7 +101,7 @@
|
|||||||
button.textContent = "OK";
|
button.textContent = "OK";
|
||||||
button.addEventListener("click", function(){
|
button.addEventListener("click", function(){
|
||||||
resolve(input.value);
|
resolve(input.value);
|
||||||
message("modal prompt closed with value", input.value);
|
logging.message("modal prompt closed with value", input.value);
|
||||||
});
|
});
|
||||||
stack.appendChild(button);
|
stack.appendChild(button);
|
||||||
document.body.append(stack);
|
document.body.append(stack);
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
const extension = require("../lib/extension");
|
const extension = require("../lib/extension");
|
||||||
const settings = require("../lib/settings");
|
const settings = require("../lib/settings");
|
||||||
const {parseErrorStack} = require("../lib/callingStack");
|
const {parseErrorStack} = require("../lib/callingStack");
|
||||||
const {error, warning, message, notice, verbose, setPrefix: setLogPrefix} = require("../lib/logging");
|
const logging = require("../lib/logging");
|
||||||
setLogPrefix("page action script");
|
logging.setPrefix("page action script");
|
||||||
|
|
||||||
const domainNotification = require("./domainNotification");
|
const domainNotification = require("./domainNotification");
|
||||||
const Notification = require("./Notification");
|
const Notification = require("./Notification");
|
||||||
@ -16,13 +16,8 @@
|
|||||||
const lists = require("../lib/lists");
|
const lists = require("../lib/lists");
|
||||||
require("../lib/theme").init("pageAction");
|
require("../lib/theme").init("pageAction");
|
||||||
|
|
||||||
Promise.all([
|
function registerActionButtons(){
|
||||||
browser.tabs.query({active: true, currentWindow: true}),
|
logging.notice("create global action buttons");
|
||||||
settings.loaded
|
|
||||||
]).then(function(values){
|
|
||||||
const tabs = values[0];
|
|
||||||
|
|
||||||
notice("create global action buttons");
|
|
||||||
|
|
||||||
createActionButtons(
|
createActionButtons(
|
||||||
document.getElementById("globalActions"),
|
document.getElementById("globalActions"),
|
||||||
@ -44,7 +39,9 @@
|
|||||||
isIcon: true,
|
isIcon: true,
|
||||||
callback: function(){
|
callback: function(){
|
||||||
settings.set("showNotifications", false).then(function(){
|
settings.set("showNotifications", false).then(function(){
|
||||||
window.close();
|
return window.close();
|
||||||
|
}).catch(function(error){
|
||||||
|
logging.warning("Unable to disable notifications:", error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,164 +49,130 @@
|
|||||||
undefined,
|
undefined,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (!tabs.length){
|
const domainActions = [
|
||||||
throw new Error("noTabsFound");
|
{
|
||||||
}
|
name: "ignorelist",
|
||||||
else if (tabs.length > 1){
|
isIcon: true,
|
||||||
error(tabs);
|
callback: function({domain, urls}){
|
||||||
throw new Error("tooManyTabsFound");
|
return domainOrUrlPicker(
|
||||||
}
|
domain,
|
||||||
|
urls,
|
||||||
|
extension.getTranslation("selectIgnore"),
|
||||||
|
extension.getTranslation("inputIgnoreURL")
|
||||||
|
).then(function(choice){
|
||||||
|
if (choice){
|
||||||
|
return settings.set("showNotifications", false, choice);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}).then(function(){
|
||||||
|
return window.close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "whitelist",
|
||||||
|
isIcon: true,
|
||||||
|
callback: function({domain, urls, api}){
|
||||||
|
const whitelistingSettings = {
|
||||||
|
all: {name: "blockMode", value: "allow"},
|
||||||
|
canvas: {name: "protectedCanvasPart", value: "nothing"},
|
||||||
|
audio: {name: "protectAudio", value: false},
|
||||||
|
domRect: {name: "protectDOMRect", value: false},
|
||||||
|
history: {name: "historyLengthThreshold", value: 10000},
|
||||||
|
navigator: {name: "protectNavigator", value: false},
|
||||||
|
windows: {name: "protectWindow", value: false}
|
||||||
|
|
||||||
function domainOrUrlPicker(domain, urls, selectText, urlInputText){
|
|
||||||
const choices = Array.from(urls).map(function(url){
|
|
||||||
return {
|
|
||||||
text: url,
|
|
||||||
value: "^" + url.replace(/([\\+*?[^\]$(){}=!|.])/g, "\\$1") + "$"
|
|
||||||
};
|
};
|
||||||
});
|
return domainOrUrlPicker(
|
||||||
if (domain){
|
domain,
|
||||||
choices.unshift(domain);
|
urls,
|
||||||
|
extension.getTranslation("selectWhitelist"),
|
||||||
|
extension.getTranslation("inputWhitelistURL")
|
||||||
|
).then(function(choice){
|
||||||
|
if (
|
||||||
|
api &&
|
||||||
|
whitelistingSettings[api]
|
||||||
|
){
|
||||||
|
// eslint-disable-next-line promise/no-nesting
|
||||||
|
return modalChoice(
|
||||||
|
extension.getTranslation("selectWhitelistScope"),
|
||||||
|
[
|
||||||
|
{
|
||||||
|
text: extension.getTranslation("whitelistOnlyAPI")
|
||||||
|
.replace(
|
||||||
|
/\{api\}/g,
|
||||||
|
extension.getTranslation("section_" + api + "-api")
|
||||||
|
),
|
||||||
|
value: api
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: extension.getTranslation("whitelistAllAPIs"),
|
||||||
|
value: "all"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
).then(function(selection){
|
||||||
|
return {choice, setting: whitelistingSettings[selection]};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return {choice, setting: whitelistingSettings.all};
|
||||||
|
}
|
||||||
|
}).then(function({choice, setting}){
|
||||||
|
if (choice){
|
||||||
|
return settings.set(setting.name, setting.value, choice);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}).then(function(){
|
||||||
|
return window.close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "whitelistTemporarily",
|
||||||
|
isIcon: true,
|
||||||
|
callback: function({domain, urls}){
|
||||||
|
return domainOrUrlPicker(
|
||||||
|
domain,
|
||||||
|
urls,
|
||||||
|
extension.getTranslation("selectSessionWhitelist"),
|
||||||
|
extension.getTranslation("inputSessionWhitelistURL")
|
||||||
|
).then(function(choice){
|
||||||
|
if (choice){
|
||||||
|
return lists.appendTo("sessionWhite", choice);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}).then(function(){
|
||||||
|
return window.close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "inspectWhitelist",
|
||||||
|
isIcon: true,
|
||||||
|
callback: function({domain, urls}){
|
||||||
|
window.open(
|
||||||
|
browser.extension.getURL(
|
||||||
|
"options/whitelist.html?domain=" +
|
||||||
|
encodeURIComponent(domain) +
|
||||||
|
"&urls=" +
|
||||||
|
encodeURIComponent(JSON.stringify(Array.from(urls.values())))
|
||||||
|
),
|
||||||
|
"_blank"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return modalChoice(
|
|
||||||
selectText,
|
|
||||||
choices
|
|
||||||
).then(function(choice){
|
|
||||||
if (choice.startsWith("^")){
|
|
||||||
return modalPrompt(
|
|
||||||
urlInputText,
|
|
||||||
choice
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return choice;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
];
|
||||||
verbose("registering domain actions");
|
function registerDomainActions(){
|
||||||
[
|
logging.verbose("registering domain actions");
|
||||||
{
|
domainActions.forEach(function(domainAction){
|
||||||
name: "ignorelist",
|
|
||||||
isIcon: true,
|
|
||||||
callback: function({domain, urls}){
|
|
||||||
domainOrUrlPicker(
|
|
||||||
domain,
|
|
||||||
urls,
|
|
||||||
extension.getTranslation("selectIgnore"),
|
|
||||||
extension.getTranslation("inputIgnoreURL")
|
|
||||||
).then(function(choice){
|
|
||||||
if (choice){
|
|
||||||
settings.set("showNotifications", false, choice).then(function(){
|
|
||||||
window.close();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
window.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "whitelist",
|
|
||||||
isIcon: true,
|
|
||||||
callback: function({domain, urls, api}){
|
|
||||||
const whitelistingSettings = {
|
|
||||||
all: {name: "blockMode", value: "allow"},
|
|
||||||
canvas: {name: "protectedCanvasPart", value: "nothing"},
|
|
||||||
audio: {name: "protectAudio", value: false},
|
|
||||||
domRect: {name: "protectDOMRect", value: false},
|
|
||||||
history: {name: "historyLengthThreshold", value: 10000},
|
|
||||||
navigator: {name: "protectNavigator", value: false},
|
|
||||||
windows: {name: "protectWindow", value: false}
|
|
||||||
|
|
||||||
};
|
|
||||||
domainOrUrlPicker(
|
|
||||||
domain,
|
|
||||||
urls,
|
|
||||||
extension.getTranslation("selectWhitelist"),
|
|
||||||
extension.getTranslation("inputWhitelistURL")
|
|
||||||
).then(function(choice){
|
|
||||||
if (
|
|
||||||
api &&
|
|
||||||
whitelistingSettings[api]
|
|
||||||
){
|
|
||||||
return modalChoice(
|
|
||||||
extension.getTranslation("selectWhitelistScope"),
|
|
||||||
[
|
|
||||||
{
|
|
||||||
text: extension.getTranslation("whitelistOnlyAPI")
|
|
||||||
.replace(
|
|
||||||
/\{api\}/g,
|
|
||||||
extension.getTranslation("section_" + api + "-api")
|
|
||||||
),
|
|
||||||
value: api
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: extension.getTranslation("whitelistAllAPIs"),
|
|
||||||
value: "all"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
).then(function(selection){
|
|
||||||
return {choice, setting: whitelistingSettings[selection]};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return {choice, setting: whitelistingSettings.all};
|
|
||||||
}
|
|
||||||
}).then(function({choice, setting}){
|
|
||||||
if (choice){
|
|
||||||
settings.set(setting.name, setting.value, choice).then(function(){
|
|
||||||
window.close();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
window.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "whitelistTemporarily",
|
|
||||||
isIcon: true,
|
|
||||||
callback: function({domain, urls}){
|
|
||||||
domainOrUrlPicker(
|
|
||||||
domain,
|
|
||||||
urls,
|
|
||||||
extension.getTranslation("selectSessionWhitelist"),
|
|
||||||
extension.getTranslation("inputSessionWhitelistURL")
|
|
||||||
).then(function(choice){
|
|
||||||
if (choice){
|
|
||||||
lists.appendTo("sessionWhite", choice).then(function(){
|
|
||||||
window.close();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
window.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "inspectWhitelist",
|
|
||||||
isIcon: true,
|
|
||||||
callback: function({domain, urls}){
|
|
||||||
window.open(
|
|
||||||
browser.extension.getURL(
|
|
||||||
"options/whitelist.html?domain=" +
|
|
||||||
encodeURIComponent(domain) +
|
|
||||||
"&urls=" +
|
|
||||||
encodeURIComponent(JSON.stringify(Array.from(urls.values())))
|
|
||||||
),
|
|
||||||
"_blank"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
].forEach(function(domainAction){
|
|
||||||
domainNotification.addAction(domainAction);
|
domainNotification.addAction(domainAction);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
verbose("registering notification actions");
|
function registerNotificationActions(){
|
||||||
|
logging.verbose("registering notification actions");
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
name: "displayFullURL",
|
name: "displayFullURL",
|
||||||
@ -228,13 +191,60 @@
|
|||||||
].forEach(function(action){
|
].forEach(function(action){
|
||||||
Notification.addAction(action);
|
Notification.addAction(action);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var tab = tabs[0];
|
function domainOrUrlPicker(domain, urls, selectText, urlInputText){
|
||||||
|
const choices = Array.from(urls).map(function(url){
|
||||||
|
return {
|
||||||
|
text: url,
|
||||||
|
value: "^" + url.replace(/([\\+*?[^\]$(){}=!|.])/g, "\\$1") + "$"
|
||||||
|
};
|
||||||
|
});
|
||||||
|
if (domain){
|
||||||
|
choices.unshift(domain);
|
||||||
|
}
|
||||||
|
return modalChoice(
|
||||||
|
selectText,
|
||||||
|
choices
|
||||||
|
).then(function(choice){
|
||||||
|
if (choice.startsWith("^")){
|
||||||
|
return modalPrompt(
|
||||||
|
urlInputText,
|
||||||
|
choice
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return choice;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise.all([
|
||||||
|
browser.tabs.query({active: true, currentWindow: true}),
|
||||||
|
settings.loaded
|
||||||
|
]).then(function(values){
|
||||||
|
const tabs = values[0];
|
||||||
|
|
||||||
|
if (!tabs.length){
|
||||||
|
throw new Error("noTabsFound");
|
||||||
|
}
|
||||||
|
else if (tabs.length > 1){
|
||||||
|
logging.error(tabs);
|
||||||
|
throw new Error("tooManyTabsFound");
|
||||||
|
}
|
||||||
|
|
||||||
|
registerActionButtons();
|
||||||
|
|
||||||
|
registerDomainActions();
|
||||||
|
|
||||||
|
registerNotificationActions();
|
||||||
|
|
||||||
|
const tab = tabs[0];
|
||||||
extension.message.on(function(data){
|
extension.message.on(function(data){
|
||||||
if (data["canvasBlocker-notificationCounter"]){
|
if (data["canvasBlocker-notificationCounter"]){
|
||||||
const url = new URL(data.url);
|
const url = new URL(data.url);
|
||||||
Object.keys(data["canvasBlocker-notificationCounter"]).forEach(function(key){
|
Object.keys(data["canvasBlocker-notificationCounter"]).forEach(function(key){
|
||||||
const notification = domainNotification(
|
domainNotification(
|
||||||
url,
|
url,
|
||||||
key,
|
key,
|
||||||
data["canvasBlocker-notificationCounter"][key].count,
|
data["canvasBlocker-notificationCounter"][key].count,
|
||||||
@ -246,7 +256,7 @@
|
|||||||
Array.isArray(data["canvasBlocker-notifications"]) &&
|
Array.isArray(data["canvasBlocker-notifications"]) &&
|
||||||
data["canvasBlocker-notifications"].length
|
data["canvasBlocker-notifications"].length
|
||||||
){
|
){
|
||||||
message("got notifications");
|
logging.message("got notifications");
|
||||||
const notifications = data["canvasBlocker-notifications"];
|
const notifications = data["canvasBlocker-notifications"];
|
||||||
let i = 0;
|
let i = 0;
|
||||||
const length = notifications.length;
|
const length = notifications.length;
|
||||||
@ -255,13 +265,14 @@
|
|||||||
window.clearInterval(tick);
|
window.clearInterval(tick);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (var delta = 0; delta < 20 && i + delta < length; delta += 1){
|
let delta = 0;
|
||||||
|
for (; delta < 20 && i + delta < length; delta += 1){
|
||||||
let notification = notifications[i + delta];
|
let notification = notifications[i + delta];
|
||||||
verbose(notification);
|
logging.verbose(notification);
|
||||||
if (settings.ignoredAPIs[notification.api]){
|
if (settings.ignoredAPIs[notification.api]){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
verbose(notification);
|
logging.verbose(notification);
|
||||||
notification.url = new URL(notification.url);
|
notification.url = new URL(notification.url);
|
||||||
domainNotification(
|
domainNotification(
|
||||||
notification.url,
|
notification.url,
|
||||||
@ -275,15 +286,16 @@
|
|||||||
}, 1);
|
}, 1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
message("request notifications from tab", tab.id);
|
logging.message("request notifications from tab", tab.id);
|
||||||
browser.tabs.sendMessage(
|
browser.tabs.sendMessage(
|
||||||
tab.id,
|
tab.id,
|
||||||
{
|
{
|
||||||
"canvasBlocker-sendNotifications": tab.id
|
"canvasBlocker-sendNotifications": tab.id
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
notice("waiting for notifications");
|
logging.notice("waiting for notifications");
|
||||||
}).catch(function(e){
|
return;
|
||||||
error(e);
|
}).catch(function(error){
|
||||||
|
error(error);
|
||||||
});
|
});
|
||||||
}());
|
}());
|
@ -43,7 +43,8 @@
|
|||||||
|
|
||||||
crypto.subtle.digest("SHA-256", data).then(function(hash){
|
crypto.subtle.digest("SHA-256", data).then(function(hash){
|
||||||
hashNode.textContent = byteArrayToHex(hash);
|
hashNode.textContent = byteArrayToHex(hash);
|
||||||
}, function(error){
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
hashNode.textContent = error;
|
hashNode.textContent = error;
|
||||||
});
|
});
|
||||||
hashSets[set].appendChild(container);
|
hashSets[set].appendChild(container);
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
/* eslint no-console: off, max-lines: off */
|
|
||||||
var addTest = (function(){
|
var addTest = (function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
@ -18,8 +17,9 @@ var addTest = (function(){
|
|||||||
try {
|
try {
|
||||||
status = func(log)? 1: 2;
|
status = func(log)? 1: 2;
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
console.log(e);
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
status = 3;
|
status = 3;
|
||||||
}
|
}
|
||||||
var li = document.createElement("li");
|
var li = document.createElement("li");
|
||||||
@ -214,6 +214,7 @@ addTest("property descriptor", function(log){
|
|||||||
object: CanvasRenderingContext2D.prototype,
|
object: CanvasRenderingContext2D.prototype,
|
||||||
name: "getImageData",
|
name: "getImageData",
|
||||||
descriptor: {
|
descriptor: {
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
value: function getImageData(x, y, w, h){},
|
value: function getImageData(x, y, w, h){},
|
||||||
writable: true,
|
writable: true,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
@ -255,12 +256,12 @@ addTest("error provocation 1", function(log){
|
|||||||
try{
|
try{
|
||||||
ctx.getImageData(0, 0, 0, 0);
|
ctx.getImageData(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
catch (err){
|
catch (error){
|
||||||
try {
|
try {
|
||||||
log(err.name);
|
log(error.name);
|
||||||
log(err.toString());
|
log(error.toString());
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
canvasBlocker = true;
|
canvasBlocker = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,12 +278,12 @@ addTest("error provocation 2", function(log){
|
|||||||
ctx.getImageData(0, 0, 1, 1);
|
ctx.getImageData(0, 0, 1, 1);
|
||||||
log("no error provoked");
|
log("no error provoked");
|
||||||
}
|
}
|
||||||
catch (err){
|
catch (error){
|
||||||
try {
|
try {
|
||||||
log(err.name);
|
log(error.name);
|
||||||
log(err.toString());
|
log(error.toString());
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
canvasBlocker = true;
|
canvasBlocker = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,12 +296,12 @@ addTest("error provocation 3", function(log){
|
|||||||
try{
|
try{
|
||||||
CanvasRenderingContext2D.prototype.getImageData.apply(undefined, [0, 0, 1, 1]);
|
CanvasRenderingContext2D.prototype.getImageData.apply(undefined, [0, 0, 1, 1]);
|
||||||
}
|
}
|
||||||
catch (err){
|
catch (error){
|
||||||
try {
|
try {
|
||||||
log(err.name);
|
log(error.name);
|
||||||
log(err.toString());
|
log(error.toString());
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
canvasBlocker = true;
|
canvasBlocker = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,26 +314,26 @@ addTest("error properties", function(log){
|
|||||||
try{
|
try{
|
||||||
CanvasRenderingContext2D.prototype.getImageData.apply(undefined, [0, 0, 1, 1]);
|
CanvasRenderingContext2D.prototype.getImageData.apply(undefined, [0, 0, 1, 1]);
|
||||||
}
|
}
|
||||||
catch (err){
|
catch (error){
|
||||||
try {
|
try {
|
||||||
var name = "TypeError";
|
var name = "TypeError";
|
||||||
if (err.name !== name && err instanceof TypeError){
|
if (error.name !== name && error instanceof TypeError){
|
||||||
log("Error name wrong. Expected: ", name, "- got:", err.name);
|
log("Error name wrong. Expected: ", name, "- got:", error.name);
|
||||||
canvasBlocker = true;
|
canvasBlocker = true;
|
||||||
}
|
}
|
||||||
var start = "@" + location.href.replace(/\.html$/, ".js");
|
var start = "@" + location.href.replace(/\.html$/, ".js");
|
||||||
if (!err.stack.startsWith(start)){
|
if (!error.stack.startsWith(start)){
|
||||||
log("Error stack starts wrong. Expected:", start, "- got :", err.stack.split(/\n/g, 2)[0]);
|
log("Error stack starts wrong. Expected:", start, "- got :", error.stack.split(/\n/g, 2)[0]);
|
||||||
canvasBlocker = true;
|
canvasBlocker = true;
|
||||||
}
|
}
|
||||||
var message = "'getImageData' called on an object that " +
|
var message = "'getImageData' called on an object that " +
|
||||||
"does not implement interface CanvasRenderingContext2D.";
|
"does not implement interface CanvasRenderingContext2D.";
|
||||||
if (err.message !== message){
|
if (error.message !== message){
|
||||||
log("Error message wrong. Expected: ", message, "- got:", err.message);
|
log("Error message wrong. Expected: ", message, "- got:", error.message);
|
||||||
canvasBlocker = true;
|
canvasBlocker = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
canvasBlocker = true;
|
canvasBlocker = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,66 +21,78 @@
|
|||||||
return Array.from(doc.querySelectorAll(".testRect"));
|
return Array.from(doc.querySelectorAll(".testRect"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatNumber(number){
|
||||||
|
const str = number.toString();
|
||||||
|
return "<span class=small>" + str.substring(0, str.length - 2) + "</span>" +
|
||||||
|
str.substring(str.length - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const properties = ["x", "y", "width", "height", "top", "left", "right", "bottom"];
|
||||||
|
function performTest(output, callback){
|
||||||
|
const rects = getElements().map(function(element){
|
||||||
|
return {
|
||||||
|
name: element.dataset.name,
|
||||||
|
data: callback(element)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const data = new Float64Array(rects.length * properties.length);
|
||||||
|
rects.forEach(function(rect, i){
|
||||||
|
properties.forEach(function(property, j){
|
||||||
|
data[i * properties.length + j] = rect.data[property];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
crypto.subtle.digest("SHA-256", data)
|
||||||
|
.then(function(hash){
|
||||||
|
output.querySelector(".hash").textContent = byteArrayToHex(hash);
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
output.querySelector(".hash").textContent = "Unable to compute hash: " + error;
|
||||||
|
});
|
||||||
|
|
||||||
|
var dataNode = output.querySelector(".data");
|
||||||
|
dataNode.innerHTML = "<table><tr><th></th>" +
|
||||||
|
rects.map(function(rect){
|
||||||
|
return "<th>" + rect.name + "</th>";
|
||||||
|
}).join("") +
|
||||||
|
"</tr><tr><th>hash</th>" +
|
||||||
|
rects.map(function(rect){
|
||||||
|
return "<td class=\"rectHash\" data-name=\"" + rect.name + "\"></td>";
|
||||||
|
}).join("") +
|
||||||
|
"</tr>" +
|
||||||
|
properties.map(function(property){
|
||||||
|
return "<tr><th>" + property + "</th>" + rects.map(function(rect){
|
||||||
|
return "<td class=\"value\" title=\"" + rect.data[property] + "\">" +
|
||||||
|
formatNumber(rect.data[property]) +
|
||||||
|
"</td>";
|
||||||
|
}).join("") + "</tr>";
|
||||||
|
}).join("") +
|
||||||
|
"</table>";
|
||||||
|
rects.forEach(function(rect){
|
||||||
|
const data = new Float64Array(properties.length);
|
||||||
|
properties.forEach(function(property, i){
|
||||||
|
data[i] = rect.data[property];
|
||||||
|
});
|
||||||
|
|
||||||
|
crypto.subtle.digest("SHA-256", data).then(function(hash){
|
||||||
|
dataNode.querySelector(
|
||||||
|
".rectHash[data-name=\"" + rect.name + "\"]"
|
||||||
|
).textContent = byteArrayToHex(hash);
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
dataNode.querySelector(
|
||||||
|
".rectHash[data-name=\"" + rect.name + "\"]"
|
||||||
|
).textContent = "Unable to compute hash: " + error;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function createTest(title, callback){
|
function createTest(title, callback){
|
||||||
const properties = ["x", "y", "width", "height", "top", "left", "right", "bottom"];
|
|
||||||
function performTest(){
|
|
||||||
const rects = getElements().map(function(element){
|
|
||||||
return {
|
|
||||||
name: element.dataset.name,
|
|
||||||
data: callback(element)
|
|
||||||
};
|
|
||||||
});
|
|
||||||
const data = new Float64Array(rects.length * properties.length);
|
|
||||||
rects.forEach(function(rect, i){
|
|
||||||
properties.forEach(function(property, j){
|
|
||||||
data[i * properties.length + j] = rect.data[property];
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
crypto.subtle.digest("SHA-256", data)
|
|
||||||
.then(function(hash){
|
|
||||||
output.querySelector(".hash").textContent = byteArrayToHex(hash);
|
|
||||||
});
|
|
||||||
|
|
||||||
function formatNumber(number){
|
|
||||||
const str = number.toString();
|
|
||||||
return "<span class=small>" + str.substring(0, str.length - 2) + "</span>" +
|
|
||||||
str.substring(str.length - 2);
|
|
||||||
}
|
|
||||||
var dataNode = output.querySelector(".data");
|
|
||||||
dataNode.innerHTML = "<table><tr><th></th>" +
|
|
||||||
rects.map(function(rect){
|
|
||||||
return "<th>" + rect.name + "</th>";
|
|
||||||
}).join("") +
|
|
||||||
"</tr><tr><th>hash</th>" +
|
|
||||||
rects.map(function(rect){
|
|
||||||
return "<td class=\"rectHash\" data-name=\"" + rect.name + "\"></td>";
|
|
||||||
}).join("") +
|
|
||||||
"</tr>" +
|
|
||||||
properties.map(function(property){
|
|
||||||
return "<tr><th>" + property + "</th>" + rects.map(function(rect){
|
|
||||||
return "<td class=\"value\" title=\"" + rect.data[property] + "\">" +
|
|
||||||
formatNumber(rect.data[property]) +
|
|
||||||
"</td>";
|
|
||||||
}).join("") + "</tr>";
|
|
||||||
}).join("") +
|
|
||||||
"</table>";
|
|
||||||
rects.forEach(function(rect){
|
|
||||||
const data = new Float64Array(properties.length);
|
|
||||||
properties.forEach(function(property, i){
|
|
||||||
data[i] = rect.data[property];
|
|
||||||
});
|
|
||||||
|
|
||||||
crypto.subtle.digest("SHA-256", data).then(function(hash){
|
|
||||||
dataNode.querySelector(
|
|
||||||
".rectHash[data-name=\"" + rect.name + "\"]"
|
|
||||||
).textContent = byteArrayToHex(hash);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const output = template.cloneNode(true);
|
const output = template.cloneNode(true);
|
||||||
output.querySelector(".title").textContent = title;
|
output.querySelector(".title").textContent = title;
|
||||||
output.querySelector(".refresh").addEventListener("click", performTest);
|
output.querySelector(".refresh").addEventListener("click", function(){
|
||||||
|
performTest(output, callback);
|
||||||
|
});
|
||||||
output.querySelector(".performance").addEventListener("click", function(){
|
output.querySelector(".performance").addEventListener("click", function(){
|
||||||
let count = 200;
|
let count = 200;
|
||||||
let totalCount = 0;
|
let totalCount = 0;
|
||||||
@ -122,7 +134,7 @@
|
|||||||
}());
|
}());
|
||||||
|
|
||||||
container.appendChild(output);
|
container.appendChild(output);
|
||||||
performTest();
|
performTest(output, callback);
|
||||||
}
|
}
|
||||||
iframe.addEventListener("load", function(){
|
iframe.addEventListener("load", function(){
|
||||||
createTest("Element.getClientRects", function(element){
|
createTest("Element.getClientRects", function(element){
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
/* eslint no-console: off */
|
// eslint-disable-next-line no-console
|
||||||
console.log("first possible call");
|
console.log("first possible call");
|
@ -1,6 +1,14 @@
|
|||||||
var log = function(){
|
var log = function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
return function log(...str){
|
return function log(...str){
|
||||||
|
if (str[str.length - 1] === "match"){
|
||||||
|
str.unshift("color: green");
|
||||||
|
str.unshift("%cOK");
|
||||||
|
}
|
||||||
|
else if (str[str.length - 1].substr(0, 9) === "missmatch"){
|
||||||
|
str.unshift("color: red");
|
||||||
|
str.unshift("%cX");
|
||||||
|
}
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(...str);
|
console.log(...str);
|
||||||
};
|
};
|
||||||
@ -32,7 +40,7 @@ function test(window){
|
|||||||
// create window canvas
|
// create window canvas
|
||||||
var canvas = document.createElement("canvas");
|
var canvas = document.createElement("canvas");
|
||||||
// draw image in window canvas
|
// draw image in window canvas
|
||||||
var ctx = draw(canvas);
|
draw(canvas);
|
||||||
return window.HTMLCanvasElement.prototype.toDataURL.call(canvas);
|
return window.HTMLCanvasElement.prototype.toDataURL.call(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,12 +63,13 @@ function hash(string){
|
|||||||
function compare(string1, string2, alwaysOutputHashes){
|
function compare(string1, string2, alwaysOutputHashes){
|
||||||
"use strict";
|
"use strict";
|
||||||
function outputHashes(message){
|
function outputHashes(message){
|
||||||
Promise.all([
|
return Promise.all([
|
||||||
hash(string1),
|
hash(string1),
|
||||||
hash(string2)
|
hash(string2)
|
||||||
]).then(function(hashes){
|
]).then(function(hashes){
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(message, ...hashes);
|
console.log(message, ...hashes);
|
||||||
|
return;
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -98,4 +107,9 @@ hash(reference).then(function(hash){
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
log("reference hash:", hash);
|
log("reference hash:", hash);
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
log("%cX", "color: red", "Unable to compute reference hash:", error);
|
||||||
});
|
});
|
@ -36,6 +36,7 @@ var performTest = function(){
|
|||||||
var log = createLog();
|
var log = createLog();
|
||||||
log.createLine("test " + name, "h3");
|
log.createLine("test " + name, "h3");
|
||||||
var line = log.createLine("");
|
var line = log.createLine("");
|
||||||
|
var line2;
|
||||||
var time = 0;
|
var time = 0;
|
||||||
var time2 = 0;
|
var time2 = 0;
|
||||||
var min = Number.POSITIVE_INFINITY;
|
var min = Number.POSITIVE_INFINITY;
|
||||||
@ -80,7 +81,7 @@ var performTest = function(){
|
|||||||
}
|
}
|
||||||
window.setTimeout(run, 10);
|
window.setTimeout(run, 10);
|
||||||
});
|
});
|
||||||
var line2 = log.createLine("");
|
line2 = log.createLine("");
|
||||||
};
|
};
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ function addConsistencyTest(title, callback){
|
|||||||
consistent.textContent = "computing";
|
consistent.textContent = "computing";
|
||||||
callback().then(function(value){
|
callback().then(function(value){
|
||||||
consistent.textContent = value? "OK": "not OK";
|
consistent.textContent = value? "OK": "not OK";
|
||||||
|
return;
|
||||||
}).catch(function(error){
|
}).catch(function(error){
|
||||||
consistent.classList.add("failed");
|
consistent.classList.add("failed");
|
||||||
if (Array.isArray(error)){
|
if (Array.isArray(error)){
|
||||||
@ -141,6 +142,7 @@ function addResolutionTest(title, callback){
|
|||||||
number.textContent = "computing";
|
number.textContent = "computing";
|
||||||
callback(type).then(function(value){
|
callback(type).then(function(value){
|
||||||
number.textContent = value;
|
number.textContent = value;
|
||||||
|
return;
|
||||||
}).catch(function(error){
|
}).catch(function(error){
|
||||||
number.classList.add("failed");
|
number.classList.add("failed");
|
||||||
number.textContent = error;
|
number.textContent = error;
|
||||||
@ -214,15 +216,14 @@ function searchValue(tester){
|
|||||||
return minValue;
|
return minValue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// eslint-disable-next-line promise/no-nesting
|
||||||
return tester(maxValue).then(function(testResult){
|
return tester(maxValue).then(function(testResult){
|
||||||
if (testResult.isEqual){
|
if (testResult.isEqual){
|
||||||
return maxValue;
|
return maxValue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return Promise.reject(
|
throw "Search could not find exact value." +
|
||||||
"Search could not find exact value." +
|
" It's between " + minValue + " and " + maxValue + ".";
|
||||||
" It's between " + minValue + " and " + maxValue + "."
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,8 @@
|
|||||||
try {
|
try {
|
||||||
var firstFingerprint = fingerPrint();
|
var firstFingerprint = fingerPrint();
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
console.log(new Date(), e);
|
console.log(new Date(), error);
|
||||||
var firstFingerprint = false;
|
var firstFingerprint = false;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
25
test/test.js
25
test/test.js
@ -1,4 +1,3 @@
|
|||||||
/* eslint no-console: off */
|
|
||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
@ -24,25 +23,35 @@
|
|||||||
container.querySelector(".hash").textContent =
|
container.querySelector(".hash").textContent =
|
||||||
hashToString(hashes[0]) + " / " +
|
hashToString(hashes[0]) + " / " +
|
||||||
hashToString(hashes[1]);
|
hashToString(hashes[1]);
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
container.querySelector(".hash").textContent = "Error while calculating hash: " + error;
|
||||||
});
|
});
|
||||||
container.querySelector(".isPointInPath").textContent = isPointInPath;
|
container.querySelector(".isPointInPath").textContent = isPointInPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (location.search !== "?notInitial"){
|
if (location.search !== "?notInitial"){
|
||||||
try {show(document.getElementById("top"), topTest());}
|
try {show(document.getElementById("top"), topTest());}
|
||||||
catch (e){console.error(e);}
|
// eslint-disable-next-line no-console
|
||||||
|
catch (error){console.error(error);}
|
||||||
try {show(document.getElementById("iframe"), iframeTest(document.querySelector("#iframe iframe")));}
|
try {show(document.getElementById("iframe"), iframeTest(document.querySelector("#iframe iframe")));}
|
||||||
catch (e){console.error(e);}
|
// eslint-disable-next-line no-console
|
||||||
|
catch (error){console.error(error);}
|
||||||
try {show(document.getElementById("iframe2"), iframeTest(document.querySelector("#iframe2 iframe")));}
|
try {show(document.getElementById("iframe2"), iframeTest(document.querySelector("#iframe2 iframe")));}
|
||||||
catch (e){console.error(e);}
|
// eslint-disable-next-line no-console
|
||||||
|
catch (error){console.error(error);}
|
||||||
try {show(document.getElementById("iframe3"), iframeTest(document.querySelector("#iframe3 iframe")));}
|
try {show(document.getElementById("iframe3"), iframeTest(document.querySelector("#iframe3 iframe")));}
|
||||||
catch (e){console.error(e);}
|
// eslint-disable-next-line no-console
|
||||||
|
catch (error){console.error(error);}
|
||||||
try {show(document.getElementById("iframe4"), dynamicIframeTest1());}
|
try {show(document.getElementById("iframe4"), dynamicIframeTest1());}
|
||||||
catch (e){console.error(e);}
|
// eslint-disable-next-line no-console
|
||||||
|
catch (error){console.error(error);}
|
||||||
try {show(document.getElementById("iframe5"), dynamicIframeTest2());}
|
try {show(document.getElementById("iframe5"), dynamicIframeTest2());}
|
||||||
catch (e){console.error(e);}
|
// eslint-disable-next-line no-console
|
||||||
|
catch (error){console.error(error);}
|
||||||
try {show(document.getElementById("iframe6"), dynamicIframeTest3());}
|
try {show(document.getElementById("iframe6"), dynamicIframeTest3());}
|
||||||
catch (e){console.error(e);}
|
// eslint-disable-next-line no-console
|
||||||
|
catch (error){console.error(error);}
|
||||||
}
|
}
|
||||||
document.querySelector("#top button").addEventListener("click", function(){
|
document.querySelector("#top button").addEventListener("click", function(){
|
||||||
show(document.getElementById("top"), topTest());
|
show(document.getElementById("top"), topTest());
|
||||||
|
@ -1,6 +1,50 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
function getParameters(context){
|
||||||
|
const parameters = [];
|
||||||
|
for (var name in context){
|
||||||
|
if (name.toUpperCase() === name){
|
||||||
|
var value = context.getParameter(context[name]);
|
||||||
|
if (value !== null){
|
||||||
|
parameters.push({name: name, value: value});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const debugExtension = context.getExtension("WEBGL_debug_renderer_info");
|
||||||
|
|
||||||
|
for (name in debugExtension){
|
||||||
|
if (name.toUpperCase() === name){
|
||||||
|
value = context.getParameter(debugExtension[name]);
|
||||||
|
if (value !== null){
|
||||||
|
parameters.push({name: name, value: value});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var frontParameters = ["VENDOR", "RENDERER", "UNMASKED_VENDOR_WEBGL", "UNMASKED_RENDERER_WEBGL"];
|
||||||
|
parameters.sort(function(a, b){
|
||||||
|
var frontA = frontParameters.indexOf(a.name);
|
||||||
|
var frontB = frontParameters.indexOf(b.name);
|
||||||
|
if (frontA !== -1){
|
||||||
|
if (frontB !== -1){
|
||||||
|
return frontA - frontB;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (frontB !== -1){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return a.name < b.name? -1: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
["webgl", "webgl2"].forEach(function(context, index){
|
["webgl", "webgl2"].forEach(function(context, index){
|
||||||
var output = document.createElement("div");
|
var output = document.createElement("div");
|
||||||
document.getElementById("output").appendChild(output);
|
document.getElementById("output").appendChild(output);
|
||||||
@ -22,46 +66,8 @@
|
|||||||
values[pixels[i]] = (values[pixels[i]] || 0) + 1;
|
values[pixels[i]] = (values[pixels[i]] || 0) + 1;
|
||||||
max = Math.max(max, values[pixels[i]]);
|
max = Math.max(max, values[pixels[i]]);
|
||||||
}
|
}
|
||||||
const parameters = [];
|
|
||||||
for (var name in gl){
|
|
||||||
if (name.toUpperCase() === name){
|
|
||||||
var value = gl.getParameter(gl[name]);
|
|
||||||
if (value !== null){
|
|
||||||
parameters.push({name: name, value: value});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const debugExtension = gl.getExtension("WEBGL_debug_renderer_info");
|
|
||||||
|
|
||||||
for (name in debugExtension){
|
const parameters = getParameters(gl);
|
||||||
if (name.toUpperCase() === name){
|
|
||||||
value = gl.getParameter(debugExtension[name]);
|
|
||||||
if (value !== null){
|
|
||||||
parameters.push({name: name, value: value});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var frontParameters = ["VENDOR", "RENDERER", "UNMASKED_VENDOR_WEBGL", "UNMASKED_RENDERER_WEBGL"];
|
|
||||||
parameters.sort(function(a, b){
|
|
||||||
var frontA = frontParameters.indexOf(a.name);
|
|
||||||
var frontB = frontParameters.indexOf(b.name);
|
|
||||||
if (frontA !== -1){
|
|
||||||
if (frontB !== -1){
|
|
||||||
return frontA - frontB;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (frontB !== -1){
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return a.name < b.name? -1: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (context === "webgl2"){
|
if (context === "webgl2"){
|
||||||
var parameterOutput = document.createElement("table");
|
var parameterOutput = document.createElement("table");
|
||||||
document.getElementById("parameters").appendChild(parameterOutput);
|
document.getElementById("parameters").appendChild(parameterOutput);
|
||||||
@ -87,11 +93,14 @@
|
|||||||
(max !== 3 * values[255]? "": "not ") + "supported " +
|
(max !== 3 * values[255]? "": "not ") + "supported " +
|
||||||
"(parameter hash: " + hash + ")";
|
"(parameter hash: " + hash + ")";
|
||||||
output.title = JSON.stringify(values);
|
output.title = JSON.stringify(values);
|
||||||
|
return;
|
||||||
|
}).catch(function(error){
|
||||||
|
output.textContent = "Error while calculating hash: " + error;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (error){
|
||||||
output.textContent = context + ": ERROR";
|
output.textContent = context + ": ERROR";
|
||||||
output.title = e;
|
output.title = error;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}());
|
}());
|
Loading…
x
Reference in New Issue
Block a user