diff --git a/.eslintrc.json b/.eslintrc.json index f4f0116..aafea81 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -11,15 +11,25 @@ }, "sourceType": "script" }, + "extends": "eslint:recommended", + "globals": { + "exportFunction": false, + "settings": false + }, "rules": { + "brace-style": ["warn", "stroustrup", {"allowSingleLine": true}], + "eqeqeq": "warn", "no-const-assign": "warn", "no-this-before-super": "warn", "no-undef": "warn", "no-unreachable": "warn", - "no-unused-vars": "warn", + "no-unused-vars": "off", + "no-trailing-spaces": ["warn", {"skipBlankLines": true}], + "no-mixed-spaces-and-tabs": ["warn", "smart-tabs"], "constructor-super": "warn", "valid-typeof": "warn", - "brace-style": "warn", + "quotes": ["error", "double"], + "semi": ["error", "always"], "strict": ["warn", "function"] } } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..6c0e27b --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,28 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "taskName": "eslint", + "type": "shell", + "windows": { + "command": "eslint" + }, + "linux": { + "command": "eslint" + }, + "osx": { + "command": "eslint" + }, + "args": ["./"], + "presentation": { + "echo": true, + "reveal": "silent", + "focus": false, + "panel": "shared" + }, + "problemMatcher": "$eslint-stylish" + } + ] +} \ No newline at end of file diff --git a/lib/askForPermission.js b/lib/askForPermission.js index a601373..5fe1201 100644 --- a/lib/askForPermission.js +++ b/lib/askForPermission.js @@ -1,4 +1,3 @@ -/* jslint moz: true */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -25,7 +24,9 @@ try { nodeName = context.nodeName; } - catch (e){} + catch (e){ + nodeName = ""; + } if (nodeName === "CANVAS"){ canvas = context; } diff --git a/lib/callingStack.js b/lib/callingStack.js index 536bb99..7ced11c 100644 --- a/lib/callingStack.js +++ b/lib/callingStack.js @@ -1,5 +1,3 @@ -/* global exports */ -/* jslint moz: true */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -21,7 +19,6 @@ // Translation var translate = require("sdk/l10n").get; var _ = function(name, replace, translateAPI){ - "use strict"; if (!translateAPI){ translateAPI = translate; } @@ -38,8 +35,6 @@ // Stack parsing function parseStackEntry(entry){ - "use strict"; - var m = /@(.*):(\d*):(\d*)$/.exec(entry) || ["", entry, "--", "--"]; return { url: m[1], @@ -67,8 +62,6 @@ // parse calling stack function parseErrorStack(errorStack){ - "use strict"; - var callers = errorStack.trim().split("\n"); var findme = callers.shift(); // Remove us from the stack findme = findme.replace(/(:[0-9]+){1,2}$/, ""); // rm line & column diff --git a/lib/check.js b/lib/check.js index 1aff384..8b032d4 100644 --- a/lib/check.js +++ b/lib/check.js @@ -1,5 +1,3 @@ -/* global console,exports */ -/* jslint moz: true */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -19,7 +17,6 @@ const preferences = require("sdk/simple-prefs"); const prefs = preferences.prefs; const {parseErrorStack} = require("./callingStack"); - const {URL} = require("sdk/url"); const logging = require("./logging"); scope.check = function check({url, errorStack}){ diff --git a/lib/colorStatistics.js b/lib/colorStatistics.js index 513ccc0..7758419 100644 --- a/lib/colorStatistics.js +++ b/lib/colorStatistics.js @@ -1,4 +1,3 @@ -/* jslint moz: true */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -37,24 +36,24 @@ color.count += 1; if (color.count > color.nextColor.count){ // swap colors to remain in right order - // a -> b -> c -> d becomes a -> c -> b -> d - var a = color.previousColor; - var b = color; + // a_ -> b_ -> c -> d becomes a_ -> c -> b_ -> d + var a_ = color.previousColor; + var b_ = color; var c = color.nextColor; var d = color.nextColor.nextColor; - a.nextColor = c; - c.previousColor = a; + a_.nextColor = c; + c.previousColor = a_; - c.nextColor = b; - b.previousColor = c; + c.nextColor = b_; + b_.previousColor = c; - b.nextColor = d; - d.previousColor = b; + b_.nextColor = d; + d.previousColor = b_; } } getMaxColors(n){ - var n = Math.min(n, this.numberOfColors); + n = Math.min(n, this.numberOfColors); var colors = Object.create(null); var current = this.maxBoundary; for (;n && current;n -= 1){ @@ -76,5 +75,5 @@ ); } return statistic; - } + }; }()); \ No newline at end of file diff --git a/lib/defaultSettings.js b/lib/defaultSettings.js index c188a93..5b756bc 100644 --- a/lib/defaultSettings.js +++ b/lib/defaultSettings.js @@ -1,6 +1,4 @@ -"use strict"; - -var settings = { +const settings = { logLevel: 1, whiteList: "", blackList: "", diff --git a/lib/frame.js b/lib/frame.js index 6375a93..5d846f5 100644 --- a/lib/frame.js +++ b/lib/frame.js @@ -1,4 +1,3 @@ -/* jslint moz: true */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -136,7 +135,7 @@ interceptedWindows.set(window, true); return true; - }; + } if (settings.isStillDefault){ message("load settings"); diff --git a/lib/intercept.js b/lib/intercept.js index 256b714..a474ef6 100644 --- a/lib/intercept.js +++ b/lib/intercept.js @@ -1,4 +1,3 @@ -/* jslint moz: true */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -98,7 +97,7 @@ errorStack: error.stack, messageId, timestamp: new Date(), functionName: name, - dataURL: + dataURL: prefs("storeImageForInspection") && prefs("showNotifications") ? diff --git a/lib/lists.js b/lib/lists.js index 984cecc..2acc29e 100644 --- a/lib/lists.js +++ b/lib/lists.js @@ -1,4 +1,3 @@ -/* jslint moz: true */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -21,8 +20,6 @@ function getDomainRegExpList(domainList){ - "use strict"; - var list = domainList .split(",") .map(function(entry){ @@ -35,7 +32,7 @@ var regExp; var domain = !!entry.match(/^[\w.]+$/); if (domain){ - regExp = new RegExp("(?:^|\\.)" + entry.replace(/([\\\+\*\?\[\^\]\$\(\)\{\}\=\!\|\.])/g, "\\$1") + "\\.?$", "i"); + regExp = new RegExp("(?:^|\\.)" + entry.replace(/([\\+*?[^\]$(){}=!|.])/g, "\\$1") + "\\.?$", "i"); } else { regExp = new RegExp(entry, "i"); @@ -68,15 +65,12 @@ }; function updateList(type, value){ - "use strict"; if (typeof value === "undefined"){ value = prefs[type + "List"]; } lists[type] = getDomainRegExpList(value); } Object.keys(lists).forEach(function(type){ - "use strict"; - preferences.on(type + "List", function(value){ updateList(type, value); }); @@ -111,13 +105,9 @@ updateStackList(prefs.stackList); scope.get = function getList(type){ - "use strict"; - return lists[type]; }; scope.appendTo = function appendToList(type, entry){ - "use strict"; - prefs[type + "List"] += (prefs[type + "List"]? ",": "") + entry; var obj = {}; obj[type + "List"] = prefs[type + "List"]; diff --git a/lib/logging.js b/lib/logging.js index 70e4df3..cdceaa9 100644 --- a/lib/logging.js +++ b/lib/logging.js @@ -1,4 +1,4 @@ -/* jslint moz: true */ +/* eslint no-console: off */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -45,9 +45,9 @@ leftPad(date.getDate(), "0", 2) + " " + leftPad(date.getHours(), "0", 2) + ":" + leftPad(date.getMinutes(), "0", 2) + ":" + - leftPad(date.getSeconds(), "0", 2) + "." + + leftPad(date.getSeconds(), "0", 2) + "." + leftPad(date.getMilliseconds(), "0", 3) + - "]" + "]"; if (typeof args[0] === "string"){ args[0] = pre + " " + args[0]; } diff --git a/lib/main.js b/lib/main.js index dc44e78..848b79a 100644 --- a/lib/main.js +++ b/lib/main.js @@ -1,4 +1,3 @@ -/* jslint moz: true */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -32,13 +31,17 @@ if ( Array.isArray(value) && value.length === 128 && - value.every(function(value){return typeof value === "number" && value >= 0 && value < 256;}) + value.every(function(value){ + return typeof value === "number" && value >= 0 && value < 256; + }) ){ persistentRnd[domain] = value; } } } - catch(e){} + catch(e){ + // JSON is not valid -> ignore it + } function updateContentScripts(){ message("update content scripts"); @@ -101,7 +104,7 @@ ){ browser.pageAction.show(port.sender.tab.id); } - }) + }); verbose("got data", data, "from port", port); }); }); diff --git a/lib/modifiedAPI.js b/lib/modifiedAPI.js index f1f828d..4550a78 100644 --- a/lib/modifiedAPI.js +++ b/lib/modifiedAPI.js @@ -1,4 +1,3 @@ -/* jslint moz: true */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -18,8 +17,6 @@ const logging = require("./logging"); const {copyCanvasToWebgl} = require("./webgl"); - // let Cu = require("chrome").Cu; - var randomSupply = null; function getContext(window, canvas){ @@ -82,9 +79,9 @@ var fakeAlphaChannel = prefs("fakeAlphaChannel"); for (var i = 0; i < l; i += 4){ var [r, g, b, a] = rng( - source[i + 0], - source[i + 1], - source[i + 2], + source[i + 0], + source[i + 1], + source[i + 2], source[i + 3], i / 4 ); @@ -134,7 +131,7 @@ return size > minSize & size <= maxSize; } else { - return true + return true; } } @@ -156,7 +153,7 @@ mode: "allow", type: status.type, active: false - } + }; } else if (hasType(status, "context") || hasType(status, "input")){ return { @@ -166,7 +163,7 @@ }; } else { - var status = Object.create(status); + status = Object.create(status); status.active = false; return status; } @@ -182,7 +179,7 @@ toDataURL: { type: "readout", getStatus: function(obj, status){ - var status = Object.create(status); + status = Object.create(status); if (hasType(status, "input")){ var contextType = canvasContextType.get(obj); status.active = contextType !== "2d"; @@ -208,7 +205,7 @@ toBlob: { type: "readout", getStatus: function(obj, status){ - var status = Object.create(status); + status = Object.create(status); if (hasType(status, "input")){ var contextType = canvasContextType.get(obj); status.active = contextType !== "2d"; @@ -235,7 +232,7 @@ mozGetAsFile: { type: "readout", getStatus: function(obj, status){ - var status = Object.create(status); + status = Object.create(status); if (hasType(status, "input")){ var contextType = canvasContextType.get(obj); status.active = contextType !== "2d"; @@ -261,7 +258,7 @@ getImageData: { type: "readout", getStatus: function(obj, status){ - var status = Object.create(status); + status = Object.create(status); if (hasType(status, "input")){ var contextType = canvasContextType.get(obj && obj.canvas); status.active = contextType !== "2d"; @@ -298,7 +295,7 @@ fillText: { type: "input", getStatus: function(obj, status){ - var status = Object.create(status); + status = Object.create(status); status.active = hasType(status, "input"); return status; }, @@ -312,7 +309,9 @@ // "this" is not trustable - it may be not a context oldImageData = getImageData(window, this).imageData; } - catch (e){} + catch (e){ + // nothing to do here + } // if "this" is not a correct context the next line will throw an error var ret = original.apply(this, window.Array.from(arguments)); var newImageData = getImageData(window, this).imageData; @@ -328,7 +327,7 @@ strokeText: { type: "input", getStatus: function(obj, status){ - var status = Object.create(status); + status = Object.create(status); status.active = hasType(status, "input"); return status; }, @@ -342,7 +341,9 @@ // "this" is not trustable - it may be not a context oldImageData = getImageData(window, this).imageData; } - catch (e){} + catch (e){ + // nothing to do here + } // if "this" is not a correct context the next line will throw an error var ret = original.apply(this, window.Array.from(arguments)); var newImageData = getImageData(window, this).imageData; @@ -358,7 +359,7 @@ readPixels: { type: "readout", getStatus: function(obj, status){ - var status = Object.create(status); + status = Object.create(status); status.active = hasType(status, "readout") || hasType(status, "input"); return status; }, diff --git a/lib/randomSupplies.js b/lib/randomSupplies.js index 0c5b95b..e49b433 100644 --- a/lib/randomSupplies.js +++ b/lib/randomSupplies.js @@ -1,4 +1,3 @@ -/* jslint moz: true, bitwise: true */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -48,7 +47,7 @@ browser.runtime.sendMessage({"canvasBlocker-new-domain-rnd": {domain, rnd: Array.from(persistentRnd[domain])}}); } return persistentRnd[domain]; - } + }; }()); scope.persistent = { name: "persistent", @@ -88,7 +87,7 @@ rng(b, baseIndex + 2), rng(a, baseIndex + 3) ]; - } + }; } }; @@ -160,7 +159,7 @@ rng(b, baseIndex + 2), rng(a, baseIndex + 3) ]; - } + }; } }; -}()); \ No newline at end of file +}()); \ No newline at end of file diff --git a/lib/require.js b/lib/require.js index 55a64e7..b2d9d9f 100644 --- a/lib/require.js +++ b/lib/require.js @@ -1,5 +1,11 @@ +/* global settings exportFunction */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + window.scope = {}; function require(module){ + "use strict"; if (module.startsWith("./")){ var scopeName = module.substr(2).replace(/\..+/, ""); return window.scope[scopeName]; @@ -21,22 +27,21 @@ function require(module){ } }); } - } + }; } else if (module === "sdk/l10n"){ return { get: function(key){ return browser.i18n.getMessage(key); } - } + }; } else if (module === "sdk/url"){ return { URL - } + }; } - console.error("Not able to get non relative modules!", module); - return undefined; + throw new ReferenceError("Unable to get non relative module " + module + "!"); } window.scope.require = require; \ No newline at end of file diff --git a/lib/webgl.js b/lib/webgl.js index a92fa07..18583ad 100644 --- a/lib/webgl.js +++ b/lib/webgl.js @@ -1,4 +1,3 @@ -/* jslint moz: true */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -44,8 +43,8 @@ } context.attachShader(program, shader); - var shader = context.createShader(context.FRAGMENT_SHADER); - var fragmenter = "precision mediump float;\nuniform sampler2D u_image;\nvarying vec2 v_texCoord;\nvoid main(){\n\tgl_FragColor = texture2D(u_image, v_texCoord);\n}" + shader = context.createShader(context.FRAGMENT_SHADER); + var fragmenter = "precision mediump float;\nuniform sampler2D u_image;\nvarying vec2 v_texCoord;\nvoid main(){\n\tgl_FragColor = texture2D(u_image, v_texCoord);\n}"; context.shaderSource(shader, fragmenter); context.compileShader(shader); success = context.getShaderParameter(shader, context.COMPILE_STATUS); @@ -112,9 +111,9 @@ context.texImage2D(context.TEXTURE_2D, 0, context.RGBA, context.RGBA, context.UNSIGNED_BYTE, canvas); var primitiveType = context.TRIANGLES; - var offset = 0; + var triangleOffset = 0; var count = 6; - context.drawArrays(primitiveType, offset, count); + context.drawArrays(primitiveType, triangleOffset, count); return {webGlCanvas, context}; }; diff --git a/options/buildPrefInputs.js b/options/buildPrefInputs.js index 61140be..909fded 100644 --- a/options/buildPrefInputs.js +++ b/options/buildPrefInputs.js @@ -1,348 +1,357 @@ -var table = document.createElement("table"); -table.className = "settings"; -document.body.appendChild(table); +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +(function(){ + "use strict"; -[ - { - "name": "displayAdvancedSettings", - "title": "Display advanced settings", - "type": "bool", - "value": false - }, - { - "name": "blockMode", - "title": "block mode", - "type": "menulist", - "value": "fakeReadout", - "options": [ - { - "value": "blockReadout", - "label": "block readout API" - }, - { - "value": "fakeReadout", - "label": "fake readout API" - }, - { - "value": "fakeInput", - "label": "fake input API" - }, - { - "value": "askReadout", - "label": "ask for readout API permission" - }, - { - "value": "", - "label": "" - }, - { - "value": "blockEverything", - "label": "block everything" - }, - { - "value": "block", - "label": "allow only white list" - }, - { - "value": "ask", - "label": "ask for permission" - }, - { - "value": "allow", - "label": "block only black list" - }, - { - "value": "allowEverything", - "label": "allow everything" + const logging = require("./logging"); + + var table = document.createElement("table"); + table.className = "settings"; + document.body.appendChild(table); + + [ + { + "name": "displayAdvancedSettings", + "title": "Display advanced settings", + "type": "bool", + "value": false + }, + { + "name": "blockMode", + "title": "block mode", + "type": "menulist", + "value": "fakeReadout", + "options": [ + { + "value": "blockReadout", + "label": "block readout API" + }, + { + "value": "fakeReadout", + "label": "fake readout API" + }, + { + "value": "fakeInput", + "label": "fake input API" + }, + { + "value": "askReadout", + "label": "ask for readout API permission" + }, + { + "value": "", + "label": "" + }, + { + "value": "blockEverything", + "label": "block everything" + }, + { + "value": "block", + "label": "allow only white list" + }, + { + "value": "ask", + "label": "ask for permission" + }, + { + "value": "allow", + "label": "block only black list" + }, + { + "value": "allowEverything", + "label": "allow everything" + } + ] + }, + { + "name": "whiteList", + "title": "White list", + "type": "string", + "value": "", + "displayDependencies": { + "blockMode": ["blockReadout", "fakeReadout", "fakeInput", "askReadout", "block", "ask"] } - ] - }, - { - "name": "whiteList", - "title": "White list", - "type": "string", - "value": "", - "displayDependencies": { - "blockMode": ["blockReadout", "fakeReadout", "fakeInput", "askReadout", "block", "ask"] - } - }, - { - "name": "blackList", - "title": "Black list", - "type": "string", - "value": "", - "displayDependencies": { - "blockMode": ["blockReadout", "fakeReadout", "fakeInput", "askReadout", "ask", "allow"] - } - }, - { - "name": "minFakeSize", - "title": "Minimal fake size", - "type": "integer", - "value": 1, - "displayDependencies": { - "blockMode": ["fakeReadout", "fakeInput"], - "displayAdvancedSettings": [true] - } - }, - { - "name": "maxFakeSize", - "title": "Maximal fake size", - "type": "integer", - "value": 0, - "displayDependencies": { - "blockMode": ["fakeReadout", "fakeInput"], - "displayAdvancedSettings": [true] - } - }, - { - "name": "rng", - "title": "Random number generator", - "type": "menulist", - "value": "nonPersistent", - "options": [ - { - "value": "nonPersistent", - "label": "non persistent" - }, - { - "value": "constant", - "label": "constant" - }, - { - "value": "persistent", - "label": "persistent" + }, + { + "name": "blackList", + "title": "Black list", + "type": "string", + "value": "", + "displayDependencies": { + "blockMode": ["blockReadout", "fakeReadout", "fakeInput", "askReadout", "ask", "allow"] } - ], - "displayDependencies": { - "blockMode": ["fakeReadout", "fakeInput"], - "displayAdvancedSettings": [true] - } - }, - { - "name": "storePersistentRnd", - "title": "Store persistent data", - "type": "bool", - "value": false, - "displayDependencies": { - "blockMode": ["fakeReadout", "fakeInput"], - "rng": ["persistent"], - "displayAdvancedSettings": [true] - } - }, - { - "name": "clearPersistentRnd", - "title": "Clear persistent random storage", - "type": "control", - "label": "Clear", - "displayDependencies": { - "blockMode": ["fakeReadout", "fakeInput"], - "rng": ["persistent"], - "displayAdvancedSettings": [true] - } - }, - { - "name": "ignoreFrequentColors", - "title": "Ignore most frequent colors", - "type": "integer", - "value": 0, - "displayDependencies": { - "blockMode": ["fakeReadout"], - "displayAdvancedSettings": [true] - } - }, - { - "name": "fakeAlphaChannel", - "title": "Fake the alpha channel", - "type": "bool", - "value": false, - "displayDependencies": { - "blockMode": ["fakeReadout"], - "displayAdvancedSettings": [true] - } - }, - { - "name": "useCanvasCache", - "title": "Use canvas cache", - "type": "bool", - "value": true, - "displayDependencies": { - "blockMode": ["fakeReadout"], - "displayAdvancedSettings": [true] - } - }, - { - "name": "askOnlyOnce", - "title": "Ask only once", - "type": "bool", - "value": true, - "displayDependencies": { - "blockMode": ["askReadout", "ask"] - } - }, - { - "name": "showNotifications", - "title": "Show notifications", - "type": "bool", - "value": true, - "displayDependencies": { - "blockMode": ["fakeReadout", "fakeInput"] - } - }, - { - "name": "storeImageForInspection", - "title": "Store image for inspection", - "type": "bool", - "value": false, - "displayDependencies": { - "blockMode": ["fakeReadout", "fakeInput"], - "showNotifications": [true], - "displayAdvancedSettings": [true] - } - }, - // { - // "name": "notificationDisplayTime", - // "title": "notification display time", - // "type": "integer", - // "value": 30, - // "displayDependencies": { - // "blockMode": ["fakeReadout", "fakeInput"] - // } - // }, - { - "name": "ignoreList", - "title": "Ignore list", - "type": "string", - "value": "", - "displayDependencies": { - "blockMode": ["fakeReadout", "fakeInput"], - "showNotifications": [true] - } - }, - { - "name": "showCallingFile", - "title": "Display calling file", - "type": "bool", - "value": false, - "displayDependencies": { - "blockMode": ["askReadout", "ask"], - "displayAdvancedSettings": [true] - } - }, - { - "name": "showCompleteCallingStack", - "title": "Display complete calling stack", - "type": "bool", - "value": false, - "displayDependencies": [ - { + }, + { + "name": "minFakeSize", + "title": "Minimal fake size", + "type": "integer", + "value": 1, + "displayDependencies": { + "blockMode": ["fakeReadout", "fakeInput"], + "displayAdvancedSettings": [true] + } + }, + { + "name": "maxFakeSize", + "title": "Maximal fake size", + "type": "integer", + "value": 0, + "displayDependencies": { + "blockMode": ["fakeReadout", "fakeInput"], + "displayAdvancedSettings": [true] + } + }, + { + "name": "rng", + "title": "Random number generator", + "type": "menulist", + "value": "nonPersistent", + "options": [ + { + "value": "nonPersistent", + "label": "non persistent" + }, + { + "value": "constant", + "label": "constant" + }, + { + "value": "persistent", + "label": "persistent" + } + ], + "displayDependencies": { + "blockMode": ["fakeReadout", "fakeInput"], + "displayAdvancedSettings": [true] + } + }, + { + "name": "storePersistentRnd", + "title": "Store persistent data", + "type": "bool", + "value": false, + "displayDependencies": { + "blockMode": ["fakeReadout", "fakeInput"], + "rng": ["persistent"], + "displayAdvancedSettings": [true] + } + }, + { + "name": "clearPersistentRnd", + "title": "Clear persistent random storage", + "type": "control", + "label": "Clear", + "displayDependencies": { + "blockMode": ["fakeReadout", "fakeInput"], + "rng": ["persistent"], + "displayAdvancedSettings": [true] + } + }, + { + "name": "ignoreFrequentColors", + "title": "Ignore most frequent colors", + "type": "integer", + "value": 0, + "displayDependencies": { + "blockMode": ["fakeReadout"], + "displayAdvancedSettings": [true] + } + }, + { + "name": "fakeAlphaChannel", + "title": "Fake the alpha channel", + "type": "bool", + "value": false, + "displayDependencies": { + "blockMode": ["fakeReadout"], + "displayAdvancedSettings": [true] + } + }, + { + "name": "useCanvasCache", + "title": "Use canvas cache", + "type": "bool", + "value": true, + "displayDependencies": { + "blockMode": ["fakeReadout"], + "displayAdvancedSettings": [true] + } + }, + { + "name": "askOnlyOnce", + "title": "Ask only once", + "type": "bool", + "value": true, + "displayDependencies": { + "blockMode": ["askReadout", "ask"] + } + }, + { + "name": "showNotifications", + "title": "Show notifications", + "type": "bool", + "value": true, + "displayDependencies": { + "blockMode": ["fakeReadout", "fakeInput"] + } + }, + { + "name": "storeImageForInspection", + "title": "Store image for inspection", + "type": "bool", + "value": false, + "displayDependencies": { "blockMode": ["fakeReadout", "fakeInput"], "showNotifications": [true], "displayAdvancedSettings": [true] - }, - { + } + }, + // { + // "name": "notificationDisplayTime", + // "title": "notification display time", + // "type": "integer", + // "value": 30, + // "displayDependencies": { + // "blockMode": ["fakeReadout", "fakeInput"] + // } + // }, + { + "name": "ignoreList", + "title": "Ignore list", + "type": "string", + "value": "", + "displayDependencies": { + "blockMode": ["fakeReadout", "fakeInput"], + "showNotifications": [true] + } + }, + { + "name": "showCallingFile", + "title": "Display calling file", + "type": "bool", + "value": false, + "displayDependencies": { "blockMode": ["askReadout", "ask"], "displayAdvancedSettings": [true] } - ] - },{ - "name": "enableStackList", - "title": "Use file specific scoped white list", - "type": "bool", - "value": false, - "displayDependencies": { - "blockMode": ["blockReadout", "fakeReadout", "fakeInput", "askReadout", "block", "ask"], - "displayAdvancedSettings": [true] - } - }, - { - "name": "stackList", - "title": "File specific white list", - "type": "string", - "value": "", - "displayDependencies": { - "enableStackList": [true], - "displayAdvancedSettings": [true] - } - - }, - { - "name": "showReleaseNotes", - "title": "Release notes", - "type": "control", - "label": "Show" - }, - { - "name": "logLevel", - "title": "logging level", - "type": "menulist", - "value": 1, - "options": [ - { - "value": 0, - "label": "none" - }, - { - "value": 1, - "label": "error" - }, - { - "value": 25, - "label": "warning" - }, - { - "value": 50, - "label": "message" - }, - { - "value": 75, - "label": "notice" - }, - { - "value": 100, - "label": "verbose" + }, + { + "name": "showCompleteCallingStack", + "title": "Display complete calling stack", + "type": "bool", + "value": false, + "displayDependencies": [ + { + "blockMode": ["fakeReadout", "fakeInput"], + "showNotifications": [true], + "displayAdvancedSettings": [true] + }, + { + "blockMode": ["askReadout", "ask"], + "displayAdvancedSettings": [true] + } + ] + },{ + "name": "enableStackList", + "title": "Use file specific scoped white list", + "type": "bool", + "value": false, + "displayDependencies": { + "blockMode": ["blockReadout", "fakeReadout", "fakeInput", "askReadout", "block", "ask"], + "displayAdvancedSettings": [true] + } + }, + { + "name": "stackList", + "title": "File specific white list", + "type": "string", + "value": "", + "displayDependencies": { + "enableStackList": [true], + "displayAdvancedSettings": [true] + } + + }, + { + "name": "showReleaseNotes", + "title": "Release notes", + "type": "control", + "label": "Show" + }, + { + "name": "logLevel", + "title": "logging level", + "type": "menulist", + "value": 1, + "options": [ + { + "value": 0, + "label": "none" + }, + { + "value": 1, + "label": "error" + }, + { + "value": 25, + "label": "warning" + }, + { + "value": 50, + "label": "message" + }, + { + "value": 75, + "label": "notice" + }, + { + "value": 100, + "label": "verbose" + } + ], + "displayDependencies": { + "displayAdvancedSettings": [true] } - ], - "displayDependencies": { - "displayAdvancedSettings": [true] } - } -].forEach(function(pref){ - var html = '
__MSG_' + pref.name + '_title__
__MSG_' + pref.name + '_description__
'; - var inputAttributes = ' data-storage-name="' + pref.name + '" data-storage-type="' + pref.type + '" class="setting"' - switch (pref.type){ - case "integer": - html += ''; - break; - case "string": - html += ''; - break; - case "bool": - html += ''; - break; - case "menulist": - html += '' + - pref.options.map(function(option){ - if (option.value !== ""){ - return ''; - } - else { - return ''; - } - }).join("") + - ''; - break; - case "control": - html += '__MSG_' + pref.name + '_label__'; - break; - default: - logging.warning("Unknown preference type: " + pref.type); - } - html += "
"; - var tr = document.createElement("tr"); - tr.setting = pref; - tr.className = "settingRow"; - tr.innerHTML = html; - logging.verbose(html); - table.appendChild(tr); -}); \ No newline at end of file + ].forEach(function(pref){ + var html = "
__MSG_" + pref.name + "_title__
__MSG_" + pref.name + "_description__
"; + var inputAttributes = " data-storage-name=\"" + pref.name + "\" data-storage-type=\"" + pref.type + "\" class=\"setting\""; + switch (pref.type){ + case "integer": + html += ""; + break; + case "string": + html += ""; + break; + case "bool": + html += ""; + break; + case "menulist": + html += "" + + pref.options.map(function(option){ + if (option.value !== ""){ + return ""; + } + else { + return ""; + } + }).join("") + + ""; + break; + case "control": + html += "__MSG_" + pref.name + "_label__"; + break; + default: + logging.warning("Unknown preference type: " + pref.type); + } + html += "
"; + var tr = document.createElement("tr"); + tr.setting = pref; + tr.className = "settingRow"; + tr.innerHTML = html; + logging.verbose(html); + table.appendChild(tr); + }); +}()); \ No newline at end of file diff --git a/options/options.html b/options/options.html index 8fe9c9b..8dc3ad0 100644 --- a/options/options.html +++ b/options/options.html @@ -7,6 +7,7 @@ + diff --git a/options/options.js b/options/options.js index f47d9bb..4d94e5c 100644 --- a/options/options.js +++ b/options/options.js @@ -1,130 +1,136 @@ -/* jslint moz: true */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -browser.storage.local.get().then(function(data){ - Object.keys(data).forEach(function(key){ - settings[key] = data[key]; - }); - settings.isStillDefault = false; - logging.setPrefix("options page"); - logging.clearQueue(); - return settings; -}).then(function(settings){ - function traverse(node, func){ - func(node); - Array.from(node.childNodes).forEach(function(child){traverse(child, func);}); - } - - // getting the translation of all the messages - logging.message("transate all messages"); - traverse(document.body, function(node){ - if (node.nodeType == 3){ - var lines = node.nodeValue.replace(/\b__MSG_(.+)__\b/g, function(m, key){ - try { - return browser.i18n.getMessage(key); +(function(){ + "use strict"; + + const logging = require("./logging"); + + browser.storage.local.get().then(function(data){ + Object.keys(data).forEach(function(key){ + settings[key] = data[key]; + }); + settings.isStillDefault = false; + logging.setPrefix("options page"); + logging.clearQueue(); + return settings; + }).then(function(settings){ + function traverse(node, func){ + func(node); + Array.from(node.childNodes).forEach(function(child){traverse(child, func);}); + } + + // getting the translation of all the messages + logging.message("transate all messages"); + traverse(document.body, function(node){ + if (node.nodeType === 3){ + var lines = node.nodeValue.replace(/\b__MSG_(.+)__\b/g, function(m, key){ + try { + return browser.i18n.getMessage(key); + } + catch (e){ + return "Unknown i18n key: " + key; + } + }).split(/\n/g); + node.nodeValue = lines.shift(); + lines.forEach(function(line){ + node.parentNode.appendChild(document.createElement("br")); + node.parentNode.appendChild(document.createTextNode(line)); + }); + } + }); + + logging.message("register events to store changes in local storage"); + Array.from(document.querySelectorAll("input.setting, select.setting")).forEach(function(input){ + var storageName = input.dataset.storageName; + if (input.type === "checkbox"){ + input.checked = settings[storageName]; + + input.addEventListener("click", function(){ + logging.message("changed setting", storageName, ":", this.checked); + var value = this.checked; + var obj = {}; + obj[storageName] = value; + browser.storage.local.set(obj); + }); + } + else { + input.value = settings[storageName]; + + input.addEventListener("change", function(){ + var value = this.value; + if (this.type === "number" || this.dataset.type === "number"){ + value = parseFloat(value); + } + logging.message("changed setting", storageName, ":", value); + var obj = {}; + obj[storageName] = value; + browser.storage.local.set(obj); + }); + } + }); + + var callbacks = { + showReleaseNotes: function(){ + logging.verbose("open release notes"); + window.open("../releaseNotes.txt", "_blank"); + // would be nicer but is not supported in fennec + // browser.windows.create({ + // url: "../releaseNotes.txt", + // type: "popup" + // }); + }, + clearPersistentRnd: function(){ + logging.message("clear persistent rnd storage"); + logging.notice("empty storage"); + browser.storage.local.set({persistentRndStorage: ""}); + logging.notice("send message to main script"); + browser.runtime.sendMessage({"canvasBlocker-clear-domain-rnd": true}); + } + }; + Array.from(document.querySelectorAll("button.setting")).forEach(function(button){ + var storageName = button.dataset.storageName; + button.addEventListener("click", function(){ + if (callbacks[storageName]){ + callbacks[storageName](); } - catch (e){ - return "Unknown i18n key: " + key; + }); + }); + + function updateDisplay(){ + logging.notice("update display"); + document.querySelectorAll("tr.settingRow").forEach(function(row){ + logging.verbose("evaluate display dependencies for", row.setting); + var displayDependencies = row.setting.displayDependencies; + if (displayDependencies){ + row.classList[( + (Array.isArray(displayDependencies)? displayDependencies: [displayDependencies]).some(function(displayDependency){ + return Object.keys(displayDependency).every(function(key){ + return displayDependency[key].indexOf(settings[key]) !== -1; + }); + }) + )? "remove": "add"]("hidden"); } - }).split(/\n/g); - node.nodeValue = lines.shift(); - lines.forEach(function(line){ - node.parentNode.appendChild(document.createElement("br")); - node.parentNode.appendChild(document.createTextNode(line)); }); } - }); - - logging.message("register events to store changes in local storage"); - Array.from(document.querySelectorAll("input.setting, select.setting")).forEach(function(input){ - var storageName = input.dataset.storageName; - if (input.type === "checkbox"){ - input.checked = settings[storageName]; - - input.addEventListener("click", function(){ - logging.message("changed setting", storageName, ":", this.checked); - var value = this.checked; - var obj = {}; - obj[storageName] = value; - browser.storage.local.set(obj); - });} - else { - input.value = settings[storageName]; - - input.addEventListener("change", function(){ - var value = this.value; - if (this.type === "number" || this.dataset.type === "number"){ - value = parseFloat(value); - } - logging.message("changed setting", storageName, ":", value); - var obj = {}; - obj[storageName] = value; - browser.storage.local.set(obj); - }); - } - }); - - var callbacks = { - showReleaseNotes: function(){ - logging.verbose("open release notes"); - window.open("../releaseNotes.txt", "_blank"); - // would be nicer but is not supported in fennec - // browser.windows.create({ - // url: "../releaseNotes.txt", - // type: "popup" - // }); - }, - clearPersistentRnd: function(){ - logging.message("clear persistent rnd storage"); - logging.notice("empty storage"); - browser.storage.local.set({persistentRndStorage: ""}); - logging.notice("send message to main script"); - browser.runtime.sendMessage({"canvasBlocker-clear-domain-rnd": true}); - } - }; - Array.from(document.querySelectorAll("button.setting")).forEach(function(button){ - var storageName = button.dataset.storageName; - button.addEventListener("click", function(){ - if (callbacks[storageName]){ - callbacks[storageName](); + updateDisplay(); + + browser.storage.onChanged.addListener(function(change, area){ + if (area === "local"){ + Object.keys(change).forEach(function(key){ + settings[key] = change[key].newValue; + var input = document.querySelector(".setting[data-storage-name=" + key + "]"); + if (input){ + if (input.type === "checkbox"){ + input.checked = change[key].newValue; + } + else { + input.value = change[key].newValue; + } + } + }); + updateDisplay(); } }); }); - - function updateDisplay(){ - logging.notice("update display"); - document.querySelectorAll("tr.settingRow").forEach(function(row){ - logging.verbose("evaluate display dependencies for", row.setting); - var displayDependencies = row.setting.displayDependencies; - if (displayDependencies){ - row.classList[( - (Array.isArray(displayDependencies)? displayDependencies: [displayDependencies]).some(function(displayDependency){ - return Object.keys(displayDependency).every(function(key){ - return displayDependency[key].indexOf(settings[key]) !== -1; - }); - }) - )? "remove": "add"]("hidden"); - } - }); - } - updateDisplay(); - - browser.storage.onChanged.addListener(function(change, area){ - if (area === "local"){ - Object.keys(change).forEach(function(key){ - settings[key] = change[key].newValue; - var input = document.querySelector(".setting[data-storage-name=" + key + "]"); - if (input){ - if (input.type === "checkbox"){ - input.checked = change[key].newValue; - } - else { - input.value = change[key].newValue; - } - } - }); - updateDisplay(); - } - }); -}); \ No newline at end of file +}()); \ No newline at end of file diff --git a/test/detectionTest.js b/test/detectionTest.js index dd8113b..c03c074 100644 --- a/test/detectionTest.js +++ b/test/detectionTest.js @@ -1,5 +1,7 @@ - +/* eslint no-console: off */ var addTest = (function(){ + "use strict"; + var stati = [ {className: "notRun", text: "not run"}, {className: "loud", text: "CB detected"}, @@ -34,10 +36,12 @@ var addTest = (function(){ statusNode.title = logs.join("\n"); li.appendChild(statusNode); ul.appendChild(li); - } + }; }()); addTest("function length", function(log){ + "use strict"; + if (CanvasRenderingContext2D.prototype.getImageData.length !== 4){ log("expected 4 parameters for getImageData - got", CanvasRenderingContext2D.prototype.getImageData.length); return true; @@ -47,6 +51,8 @@ addTest("function length", function(log){ } }); addTest("function code", function(log){ + "use strict"; + if (!CanvasRenderingContext2D.prototype.getImageData.toString().match(/^\s*function getImageData\s*\(\)\s*\{\s*\[native code\]\s*\}\s*$/)){ log("unexpected function code:", CanvasRenderingContext2D.prototype.getImageData.toString()); return true; @@ -55,9 +61,15 @@ addTest("function code", function(log){ return false; } }); -addTest("function name", function(){return CanvasRenderingContext2D.prototype.getImageData.name !== "getImageData"}); +addTest("function name", function(){ + "use strict"; + + return CanvasRenderingContext2D.prototype.getImageData.name !== "getImageData"; +}); addTest("error provocation 1", function(log){ - var canvas = document.createElement('canvas'); + "use strict"; + + var canvas = document.createElement("canvas"); var ctx = canvas.getContext("2d"); var canvasBlocker = false; try{ @@ -75,7 +87,9 @@ addTest("error provocation 1", function(log){ return canvasBlocker; }); addTest("error provocation 2", function(log){ - var canvas = document.createElement('canvas'); + "use strict"; + + var canvas = document.createElement("canvas"); canvas.width = 0; var ctx = canvas.getContext("2d"); var canvasBlocker = false; @@ -95,6 +109,8 @@ addTest("error provocation 2", function(log){ return canvasBlocker; }); addTest("error provocation 3", function(log){ + "use strict"; + var canvasBlocker = false; try{ CanvasRenderingContext2D.prototype.getImageData.apply(undefined, [0, 0, 1, 1]); @@ -111,6 +127,8 @@ addTest("error provocation 3", function(log){ return canvasBlocker; }); function testKnownPixelValue(size, log){ + "use strict"; + var canvas = document.createElement("canvas"); canvas.height = size; canvas.width = size; @@ -128,16 +146,22 @@ function testKnownPixelValue(size, log){ return false; } addTest("known pixel value test 1", function(log){ + "use strict"; + return testKnownPixelValue(1, log); }); addTest("known pixel value test 10", function(log){ + "use strict"; + return testKnownPixelValue(10, log); }); addTest("double readout test", function(log){ + "use strict"; + var canvas = document.createElement("canvas"); var context = canvas.getContext("2d"); var imageData = context.getImageData(0, 0, canvas.width, canvas.height); - for (var i = 0; i < imageData.data.length; i += 1){ + for (let i = 0; i < imageData.data.length; i += 1){ if (i % 4 !== 3){ imageData.data[i] = Math.floor(256 * Math.random()); } @@ -149,7 +173,7 @@ addTest("double readout test", function(log){ var imageData1 = context.getImageData(0, 0, canvas.width, canvas.height); var imageData2 = context.getImageData(0, 0, canvas.width, canvas.height); - for (var i = 0; i < imageData2.data.length; i += 1){ + for (let i = 0; i < imageData2.data.length; i += 1){ if (imageData1.data[i] !== imageData2.data[i]){ log("mismatch at", i, ":", imageData1.data[i], "(", imageData1.data[i].toString(2), ")", @@ -163,10 +187,12 @@ addTest("double readout test", function(log){ return false; }); addTest("readout - in - out test", function(log){ + "use strict"; + var canvas = document.createElement("canvas"); var context = canvas.getContext("2d"); var imageData = context.getImageData(0, 0, canvas.width, canvas.height); - for (var i = 0; i < imageData.data.length; i += 1){ + for (let i = 0; i < imageData.data.length; i += 1){ if (i % 4 !== 3){ imageData.data[i] = Math.floor(256 * Math.random()); } @@ -181,7 +207,7 @@ addTest("readout - in - out test", function(log){ var context2 = canvas2.getContext("2d"); context2.putImageData(imageData1, 0, 0); var imageData2 = context2.getImageData(0, 0, canvas.width, canvas.height); - for (var i = 0; i < imageData2.data.length; i += 1){ + for (let i = 0; i < imageData2.data.length; i += 1){ if (imageData1.data[i] !== imageData2.data[i]){ log("mismatch at", i, ":", imageData1.data[i], "(", imageData1.data[i].toString(2), ")", diff --git a/test/firstPossibleCall.js b/test/firstPossibleCall.js index 3d1f0e4..4ccd42f 100644 --- a/test/firstPossibleCall.js +++ b/test/firstPossibleCall.js @@ -1 +1,2 @@ +/* eslint no-console: off */ console.log("first possible call"); \ No newline at end of file diff --git a/test/performanceTest.js b/test/performanceTest.js index 6a74eb2..3a22229 100644 --- a/test/performanceTest.js +++ b/test/performanceTest.js @@ -1,5 +1,7 @@ var createLog = function(){ + "use strict"; + var div = document.getElementById("log"); return function createLog(){ @@ -19,6 +21,8 @@ var createLog = function(){ }(); var performTest = function(){ + "use strict"; + return function performTest(name, func, innerRunLength, outerRunLength){ var log = createLog(); log("test " + name); @@ -59,12 +63,14 @@ var performTest = function(){ }(); function draw(canvas){ + "use strict"; + canvas.setAttribute("width", 220); canvas.setAttribute("height", 30); var fp_text = "BrowserLeaks,com 10"; - var ctx = canvas.getContext('2d'); + var ctx = canvas.getContext("2d"); ctx.textBaseline = "top"; ctx.font = "14px 'Arial'"; ctx.textBaseline = "alphabetic"; @@ -79,11 +85,13 @@ function draw(canvas){ } var fingerprintTest = function(){ + "use strict"; + var canvas; return { prepare: function(){ // create window canvas - canvas = document.createElement('canvas'); + canvas = document.createElement("canvas"); // draw image in window canvas draw(canvas); }, @@ -94,6 +102,8 @@ var fingerprintTest = function(){ }(); var randomImageTest = function(){ + "use strict"; + var canvas; return { diff --git a/test/test.js b/test/test.js index 12302df..9484fc6 100644 --- a/test/test.js +++ b/test/test.js @@ -1,5 +1,7 @@ (function(){ + "use strict"; + function show(container, url){ container.querySelector(".display").src = url; var buffer = new TextEncoder("utf-8").encode(url); @@ -23,12 +25,14 @@ }()); function draw(canvas){ + "use strict"; + canvas.setAttribute("width", 220); canvas.setAttribute("height", 30); var fp_text = "BrowserLeaks,com 10"; - var ctx = canvas.getContext('2d'); + var ctx = canvas.getContext("2d"); ctx.textBaseline = "top"; ctx.font = "14px 'Arial'"; ctx.textBaseline = "alphabetic"; @@ -43,26 +47,29 @@ function draw(canvas){ } function topTest(){ + "use strict"; + // create window canvas - var canvas = document.createElement('canvas'); + var canvas = document.createElement("canvas"); // draw image in window canvas draw(canvas); return canvas.toDataURL(); } function iframeTest(){ + "use strict"; // create window canvas - var canvas = document.createElement('canvas'); + var canvas = document.createElement("canvas"); // draw image in window canvas draw(canvas); // create iframe canvas and ctx - var iframe_canvas = document.querySelector("#iframe iframe").contentDocument.createElement('canvas'); + var iframe_canvas = document.querySelector("#iframe iframe").contentDocument.createElement("canvas"); iframe_canvas.setAttribute("width", 220); iframe_canvas.setAttribute("height", 30); - var iframe_ctx = iframe_canvas.getContext('2d'); + var iframe_ctx = iframe_canvas.getContext("2d"); // copy image from window canvas to iframe ctx iframe_ctx.drawImage(canvas, 0, 0); diff --git a/test/webGL-Test.js b/test/webGL-Test.js index 25424f3..858b471 100644 --- a/test/webGL-Test.js +++ b/test/webGL-Test.js @@ -1,8 +1,10 @@ (function(){ - var canvas = document.createElement('canvas'); + "use strict"; + + var canvas = document.createElement("canvas"); canvas.width = 11; canvas.height = 13; - var gl = canvas.getContext('webgl'); + var gl = canvas.getContext("webgl"); // paint it completely black gl.clearColor(0, 0, 0, 1);