mirror of
https://github.com/kkapsner/CanvasBlocker
synced 2025-07-04 20:46:39 +02:00
Big linting
This commit is contained in:
parent
b5e6d049ce
commit
aef6bd3d59
58 changed files with 2074 additions and 1856 deletions
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
(function(){
|
||||
"use strict";
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -15,15 +15,15 @@
|
|||
|
||||
// Check canvas appearance
|
||||
function canvasAppearance(window, api, context){
|
||||
var oldBorder = false;
|
||||
var canvas = false;
|
||||
var inDOM = null;
|
||||
let oldBorder = false;
|
||||
let canvas = false;
|
||||
let inDOM = null;
|
||||
if (api === "canvas" && context){
|
||||
var nodeName;
|
||||
let nodeName;
|
||||
try {
|
||||
nodeName = context.nodeName;
|
||||
}
|
||||
catch (e){
|
||||
catch (error){
|
||||
nodeName = "";
|
||||
}
|
||||
if (nodeName === "CANVAS"){
|
||||
|
@ -45,17 +45,17 @@
|
|||
canvas: canvas,
|
||||
askCategory: canvas? (inDOM? "visible": "invisible"): (api === "canvas"? "nocanvas": api),
|
||||
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});
|
||||
return text;
|
||||
},
|
||||
inDom: inDOM,
|
||||
get visible(){
|
||||
var visible = inDOM;
|
||||
let visible = inDOM;
|
||||
if (inDOM){
|
||||
canvas.scrollIntoView();
|
||||
var rect = canvas.getBoundingClientRect();
|
||||
var foundEl = window.document.elementFromPoint(
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const foundEl = window.document.elementFromPoint(
|
||||
rect.left + rect.width / 2,
|
||||
rect.top + rect.height / 2
|
||||
);
|
||||
|
@ -72,9 +72,9 @@
|
|||
};
|
||||
}
|
||||
|
||||
var modes = new WeakMap();
|
||||
const modes = new WeakMap();
|
||||
function getAskMode(window, type, _){
|
||||
var mode = modes.get(window);
|
||||
let mode = modes.get(window);
|
||||
if (mode){
|
||||
return mode[type];
|
||||
}
|
||||
|
@ -132,11 +132,11 @@
|
|||
}
|
||||
|
||||
scope.ask = function({window, type, api, canvas, errorStack}, {_, prefs}){
|
||||
var answer;
|
||||
var askMode = getAskMode(window, type, _);
|
||||
var askStatus = askMode.askStatus;
|
||||
var appearance = canvasAppearance(window, api, canvas);
|
||||
var category = appearance.askCategory;
|
||||
let answer;
|
||||
const askMode = getAskMode(window, type, _);
|
||||
const askStatus = askMode.askStatus;
|
||||
const appearance = canvasAppearance(window, api, canvas);
|
||||
let category = appearance.askCategory;
|
||||
if (prefs("askOnlyOnce") !== "no" && askStatus.alreadyAsked[category]){
|
||||
// already asked
|
||||
appearance.reset();
|
||||
|
@ -146,7 +146,6 @@
|
|||
let imgContainer = null;
|
||||
if (type === "readout" && prefs("showCanvasWhileAsking") && canvas){
|
||||
try {
|
||||
let content = canvas.toDataURL();
|
||||
let document = window.top.document;
|
||||
imgContainer = document.createElement("div");
|
||||
imgContainer.style.cssText = `
|
||||
|
@ -177,12 +176,12 @@
|
|||
imgContainer.appendChild(img);
|
||||
document.body.appendChild(imgContainer);
|
||||
}
|
||||
catch (e){
|
||||
catch (error){
|
||||
// unable to read the canvas
|
||||
}
|
||||
}
|
||||
// asking
|
||||
var msg = askMode.askText[appearance.text];
|
||||
let msg = askMode.askText[appearance.text];
|
||||
|
||||
// visible vs invisible is only calculated here correctly
|
||||
category = appearance.text;
|
||||
|
@ -196,8 +195,8 @@
|
|||
|
||||
if (prefs("askOnlyOnce") === "combined"){
|
||||
["context", "readout", "input"].forEach(function(type){
|
||||
var askMode = getAskMode(window, type, _);
|
||||
var askStatus = askMode.askStatus;
|
||||
const askMode = getAskMode(window, type, _);
|
||||
const askStatus = askMode.askStatus;
|
||||
askStatus.alreadyAsked[category] = true;
|
||||
askStatus.answer[category] = answer;
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -16,12 +16,12 @@
|
|||
const extension = require("./extension");
|
||||
|
||||
// Translation
|
||||
var _ = function(name, replace, translateAPI){
|
||||
const _ = function(name, replace, translateAPI){
|
||||
if (!translateAPI){
|
||||
translateAPI = extension.getTranslation;
|
||||
}
|
||||
|
||||
var str = translateAPI(name) || name;
|
||||
let str = translateAPI(name) || name;
|
||||
if (replace){
|
||||
// replace generic content in the translation by given parameter
|
||||
Object.keys(replace).forEach(function(name){
|
||||
|
@ -33,7 +33,7 @@
|
|||
|
||||
// Stack parsing
|
||||
function parseStackEntry(entry){
|
||||
var m = /@(.*):(\d*):(\d*)$/.exec(entry) || ["", entry, "--", "--"];
|
||||
const m = /@(.*):(\d*):(\d*)$/.exec(entry) || ["", entry, "--", "--"];
|
||||
return {
|
||||
url: m[1],
|
||||
line: parseInt(m[2], 10),
|
||||
|
@ -61,13 +61,12 @@
|
|||
// parse calling stack
|
||||
const extensionID = extension.extensionID;
|
||||
function parseErrorStack(errorStack){
|
||||
var callers = errorStack.trim().split("\n");
|
||||
callers = callers.map(parseStackEntry).filter(function(caller){
|
||||
const callers = errorStack.trim().split("\n").map(parseStackEntry).filter(function(caller){
|
||||
return !caller.url.startsWith(extensionID);
|
||||
});
|
||||
return {
|
||||
toString: function(translateAPI){
|
||||
var msg = "";
|
||||
let msg = "";
|
||||
msg += "\n\n" + _("sourceOutput", undefined, translateAPI) + ": ";
|
||||
if (settings.showCompleteCallingStack){
|
||||
msg += callers.reduce(function(stack, c){
|
||||
|
@ -82,7 +81,7 @@
|
|||
},
|
||||
match: function(stackRule){
|
||||
if (typeof stackRule.stackPosition !== "undefined"){
|
||||
var pos = stackRule.stackPosition;
|
||||
let pos = stackRule.stackPosition;
|
||||
if (pos < 0){
|
||||
pos += callers.length;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
|||
|
||||
scope.check = function check({url, errorStack}){
|
||||
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)$/
|
||||
);
|
||||
if (match){
|
||||
|
@ -63,7 +63,7 @@
|
|||
return "allowInternal";
|
||||
}
|
||||
|
||||
var mode = "block";
|
||||
let mode = "block";
|
||||
switch (blockMode){
|
||||
case "blockEverything":
|
||||
mode = "block";
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"use strict";
|
||||
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -23,8 +23,8 @@
|
|||
this.minBoundary.nextColor = this.maxBoundary;
|
||||
}
|
||||
addColor(r, g, b, a){
|
||||
var index = String.fromCharCode(r, g, b, a);
|
||||
var color = this.colors[index];
|
||||
const index = String.fromCharCode(r, g, b, a);
|
||||
let color = this.colors[index];
|
||||
if (!color){
|
||||
color = {
|
||||
index,
|
||||
|
@ -42,10 +42,10 @@
|
|||
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;
|
||||
var c = color.nextColor;
|
||||
var d = color.nextColor.nextColor;
|
||||
const a_ = color.previousColor;
|
||||
const b_ = color;
|
||||
const c = color.nextColor;
|
||||
const d = color.nextColor.nextColor;
|
||||
|
||||
a_.nextColor = c;
|
||||
c.previousColor = a_;
|
||||
|
@ -59,8 +59,8 @@
|
|||
}
|
||||
getMaxColors(n){
|
||||
n = Math.min(n, this.numberOfColors);
|
||||
var colors = Object.create(null);
|
||||
var current = this.maxBoundary;
|
||||
const colors = Object.create(null);
|
||||
let current = this.maxBoundary;
|
||||
for (;n && current;n -= 1){
|
||||
current = current.previousColor;
|
||||
colors[current.index] = current;
|
||||
|
@ -70,8 +70,8 @@
|
|||
}
|
||||
|
||||
scope.compute = function computeColorStatistics(rawData){
|
||||
var statistic = new Statistic();
|
||||
for (var i = 0, l = rawData.length; i < l; i += 4){
|
||||
const statistic = new Statistic();
|
||||
for (let i = 0, l = rawData.length; i < l; i += 4){
|
||||
statistic.addColor(
|
||||
rawData[i + 0],
|
||||
rawData[i + 1],
|
||||
|
@ -86,10 +86,10 @@
|
|||
return statistic.numberOfColors > threshold;
|
||||
}
|
||||
else {
|
||||
var colors = Object.create(null);
|
||||
var count = 0;
|
||||
for (var i = 0, l = rawData.length; i < l; i += 4){
|
||||
var index = String.fromCharCode(
|
||||
const colors = Object.create(null);
|
||||
let count = 0;
|
||||
for (let i = 0, l = rawData.length; i < l; i += 4){
|
||||
const index = String.fromCharCode(
|
||||
rawData[i + 0],
|
||||
rawData[i + 1],
|
||||
rawData[i + 2],
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -21,6 +21,10 @@
|
|||
const mainVersion = parseInt(info.version.replace(/\..+/, ""), 10);
|
||||
canMergeHeader = mainVersion > 59;
|
||||
blockBlob = mainVersion < 60;
|
||||
return canMergeHeader;
|
||||
}).catch(function(){
|
||||
canMergeHeader = false;
|
||||
blockBlob = true;
|
||||
});
|
||||
function setHeader(headers, header){
|
||||
if (canMergeHeader){
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
|
53
lib/frame.js
53
lib/frame.js
|
@ -14,13 +14,12 @@
|
|||
const iframeProtection = require("./iframeProtection");
|
||||
|
||||
const logging = require("./logging");
|
||||
const {error, warning, message, notice, verbose, setPrefix: setLogPrefix} = logging;
|
||||
setLogPrefix("frame script");
|
||||
logging.setPrefix("frame script");
|
||||
|
||||
// Variable to "unload" the script
|
||||
var enabled = true;
|
||||
let enabled = true;
|
||||
|
||||
message("starting", location.href);
|
||||
logging.message("starting", location.href);
|
||||
|
||||
function check(message){
|
||||
if (enabled){
|
||||
|
@ -72,38 +71,38 @@
|
|||
}
|
||||
computeExtensionSecret();
|
||||
|
||||
message("open port to background script");
|
||||
var port = browser.runtime.connect();
|
||||
logging.message("open port to background script");
|
||||
const port = browser.runtime.connect();
|
||||
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});
|
||||
}
|
||||
var tabId;
|
||||
let tabId;
|
||||
port.onMessage.addListener(function(data){
|
||||
message("Got data from port", data);
|
||||
logging.message("Got data from port", data);
|
||||
if (data.hasOwnProperty("tabId")){
|
||||
notice("my tab id is", data.tabId);
|
||||
logging.notice("my tab id is", data.tabId);
|
||||
tabId = data.tabId;
|
||||
}
|
||||
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");
|
||||
persistentRnd.setCookieStoreId(data.cookieStoreId);
|
||||
}
|
||||
const persistentRndName = "persistent" + (extension.inIncognitoContext? "Incognito": "") + "Rnd";
|
||||
if (data.hasOwnProperty(persistentRndName)){
|
||||
const persistentRndValue = data[persistentRndName];
|
||||
notice("got persistent random data", persistentRndValue);
|
||||
logging.notice("got persistent random data", persistentRndValue);
|
||||
const {persistent: persistentRnd} = require("./randomSupplies");
|
||||
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]);
|
||||
});
|
||||
}
|
||||
});
|
||||
var notifications = [];
|
||||
var notificationCounter = {};
|
||||
var sentAPIs = {};
|
||||
const notifications = [];
|
||||
const notificationCounter = {};
|
||||
const sentAPIs = {};
|
||||
function notify(data){
|
||||
if (!settings.ignoredAPIs[data.api]){
|
||||
if (settings.storeNotificationData){
|
||||
|
@ -128,16 +127,18 @@
|
|||
}
|
||||
|
||||
|
||||
var interceptedWindows = new WeakMap();
|
||||
const interceptedWindows = new WeakMap();
|
||||
function interceptWindow(window){
|
||||
let wrappedTry;
|
||||
try {
|
||||
var href = window.location.href;
|
||||
var wrappedTry = getWrapped(window);
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const href = window.location.href;
|
||||
wrappedTry = getWrapped(window);
|
||||
}
|
||||
catch (e){
|
||||
catch (error){
|
||||
// we are unable to read the location due to SOP
|
||||
// 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;
|
||||
}
|
||||
const wrappedWindow = wrappedTry;
|
||||
|
@ -150,12 +151,12 @@
|
|||
return false;
|
||||
}
|
||||
|
||||
message("intercepting window", window);
|
||||
logging.message("intercepting window", window);
|
||||
intercept(
|
||||
{subject: window},
|
||||
{check, checkStack, ask: askWrapper, notify, prefs}
|
||||
);
|
||||
message("prepare to intercept (i)frames.");
|
||||
logging.message("prepare to intercept (i)frames.");
|
||||
|
||||
function interceptAllFrames(){
|
||||
const currentLength = window.length;
|
||||
|
@ -185,7 +186,7 @@
|
|||
return true;
|
||||
}
|
||||
|
||||
message("register listener for messages from background script");
|
||||
logging.message("register listener for messages from background script");
|
||||
extension.message.on(function(data){
|
||||
if (data["canvasBlocker-unload"]){
|
||||
enabled = false;
|
||||
|
@ -194,14 +195,14 @@
|
|||
data.hasOwnProperty("canvasBlocker-sendNotifications") &&
|
||||
data["canvasBlocker-sendNotifications"] === tabId
|
||||
){
|
||||
notice("sending notifications:", notifications);
|
||||
logging.notice("sending notifications:", notifications);
|
||||
extension.message.send({
|
||||
sender: tabId,
|
||||
url: window.location.href,
|
||||
"canvasBlocker-notificationCounter": notificationCounter,
|
||||
"canvasBlocker-notifications": notifications
|
||||
});
|
||||
notice("notifications sent");
|
||||
logging.notice("notifications sent");
|
||||
}
|
||||
});
|
||||
|
||||
|
|
44
lib/hash.js
44
lib/hash.js
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -20,11 +20,11 @@
|
|||
};
|
||||
|
||||
scope.sumXor = function(inputByteArray){
|
||||
var hash = new Uint32Array(4);
|
||||
var sum = new Float64Array(hash.buffer, 8, 1);
|
||||
var intView = new Uint32Array(inputByteArray.buffer);
|
||||
var floatView = new Float32Array(inputByteArray.buffer);
|
||||
var length = intView.length;
|
||||
const hash = new Uint32Array(4);
|
||||
// const sum = new Float64Array(hash.buffer, 8, 1);
|
||||
const intView = new Uint32Array(inputByteArray.buffer);
|
||||
// const floatView = new Float32Array(inputByteArray.buffer);
|
||||
const length = intView.length;
|
||||
for (let i = 0; i < length; i += 1){
|
||||
// sum[0] += floatView[i];
|
||||
hash[0] ^= intView[i];
|
||||
|
@ -34,11 +34,11 @@
|
|||
};
|
||||
|
||||
scope.hashCode = function(inputByteArray){
|
||||
var hash = new Uint32Array(1);
|
||||
var intView = new Uint32Array(inputByteArray.buffer);
|
||||
var length = intView.length;
|
||||
const hash = new Uint32Array(1);
|
||||
const intView = new Uint32Array(inputByteArray.buffer);
|
||||
const length = intView.length;
|
||||
for (let i = 0; i < length; i += 1){
|
||||
var v = hash[0];
|
||||
const v = hash[0];
|
||||
hash[0] = ((v << 5) - v) + intView[i];
|
||||
}
|
||||
return hash;
|
||||
|
@ -81,21 +81,21 @@
|
|||
return function md5(inputByteArray){
|
||||
h.set(hInitial);
|
||||
|
||||
var length = inputByteArray.buffer.byteLength;
|
||||
var messageBitLength = length * 8;
|
||||
const length = inputByteArray.buffer.byteLength;
|
||||
const messageBitLength = length * 8;
|
||||
|
||||
// create byte array with length dividable by 64 (512 bit)
|
||||
var neededLength = Math.ceil((length + 1 + 8) / 64) * 64;
|
||||
var messageByteArray = new Uint8Array(neededLength);
|
||||
const neededLength = Math.ceil((length + 1 + 8) / 64) * 64;
|
||||
const messageByteArray = new Uint8Array(neededLength);
|
||||
messageByteArray.set(new Uint8Array(inputByteArray.buffer));
|
||||
var view = new DataView(messageByteArray.buffer);
|
||||
const view = new DataView(messageByteArray.buffer);
|
||||
|
||||
// append 10...000000
|
||||
messageByteArray[length] = 0x80;
|
||||
// append size in 64 bit big endian
|
||||
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){
|
||||
w[j / 4] = view.getUint32(i + j, true);
|
||||
}
|
||||
|
@ -118,7 +118,7 @@
|
|||
temp[4] = (temp[2] ^ (temp[1] | (~ temp[3])));
|
||||
temp[5] = (7*j) % 16;
|
||||
}
|
||||
var temp_ = temp[3];
|
||||
const temp_ = temp[3];
|
||||
temp[3] = temp[2];
|
||||
temp[2] = 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);
|
||||
|
||||
var length = inputByteArray.buffer.byteLength;
|
||||
var messageBitLength = length * 8;
|
||||
const length = inputByteArray.buffer.byteLength;
|
||||
const messageBitLength = length * 8;
|
||||
|
||||
// create byte array with length dividable by 64 (512 bit)
|
||||
var neededLength = Math.ceil((length + 1 + 8) / 64) * 64;
|
||||
var messageByteArray = new Uint8Array(neededLength);
|
||||
const neededLength = Math.ceil((length + 1 + 8) / 64) * 64;
|
||||
const messageByteArray = new Uint8Array(neededLength);
|
||||
messageByteArray.set(new Uint8Array(inputByteArray.buffer));
|
||||
var view = new DataView(messageByteArray.buffer);
|
||||
const view = new DataView(messageByteArray.buffer);
|
||||
|
||||
// append 10...000000
|
||||
messageByteArray[length] = 0x80;
|
||||
|
|
|
@ -19,8 +19,7 @@
|
|||
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){
|
||||
const descriptor = Object.getOwnPropertyDescriptor(object, name);
|
||||
const original = descriptor[type];
|
||||
|
@ -49,7 +48,10 @@
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return changeProperty;
|
||||
}
|
||||
|
||||
function protectFrameProperties({window, wrappedWindow, changeProperty, singleCallback}){
|
||||
["HTMLIFrameElement", "HTMLFrameElement"].forEach(function(constructorName){
|
||||
const constructor = window[constructorName];
|
||||
const wrappedConstructor = wrappedWindow[constructorName];
|
||||
|
@ -61,7 +63,7 @@
|
|||
const originalContentWindowGetter = contentWindowDescriptor.get;
|
||||
const contentWindowTemp = {
|
||||
get contentWindow(){
|
||||
var window = originalContentWindowGetter.call(this);
|
||||
const window = originalContentWindowGetter.call(this);
|
||||
if (window){
|
||||
singleCallback(window);
|
||||
}
|
||||
|
@ -80,7 +82,7 @@
|
|||
const originalContentDocumentGetter = contentDocumentDescriptor.get;
|
||||
const contentDocumentTemp = {
|
||||
get contentDocument(){
|
||||
var document = originalContentDocumentGetter.call(this);
|
||||
const document = originalContentDocumentGetter.call(this);
|
||||
if (document){
|
||||
singleCallback(document.defaultView);
|
||||
}
|
||||
|
@ -92,6 +94,9 @@
|
|||
window
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
function protectDOMModifications({window, wrappedWindow, changeProperty, allCallback}){
|
||||
[
|
||||
// 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.
|
||||
const observe = function(){
|
||||
var observer = new MutationObserver(allCallback);
|
||||
var observing = false;
|
||||
function observe(){
|
||||
if (
|
||||
!observing &&
|
||||
window.document
|
||||
){
|
||||
observer.observe(window.document, {subtree: true, childList: true});
|
||||
observing = true;
|
||||
}
|
||||
}
|
||||
|
||||
function enableMutationObserver({window, allCallback}){
|
||||
const observer = new MutationObserver(allCallback);
|
||||
let observing = false;
|
||||
function observe(){
|
||||
if (
|
||||
!observing &&
|
||||
window.document
|
||||
){
|
||||
observer.observe(window.document, {subtree: true, childList: true});
|
||||
observing = true;
|
||||
}
|
||||
observe();
|
||||
window.document.addEventListener("DOMContentLoaded", function(){
|
||||
if (observing){
|
||||
observer.disconnect();
|
||||
observing = false;
|
||||
}
|
||||
});
|
||||
return observe;
|
||||
}();
|
||||
|
||||
// MutationObserver does not trigger fast enough when document.write is used
|
||||
}
|
||||
observe();
|
||||
window.document.addEventListener("DOMContentLoaded", function(){
|
||||
if (observing){
|
||||
observer.disconnect();
|
||||
observing = false;
|
||||
}
|
||||
});
|
||||
return observe;
|
||||
}
|
||||
|
||||
function protectDocumentWrite({window, wrappedWindow, changeProperty, observe, allCallback}){
|
||||
const documentWriteDescriptorOnHTMLDocument = Object.getOwnPropertyDescriptor(
|
||||
wrappedWindow.HTMLDocument.prototype,
|
||||
"write"
|
||||
|
@ -199,6 +204,7 @@
|
|||
documentWriteDescriptorOnHTMLDocument?
|
||||
wrappedWindow.HTMLDocument.prototype:
|
||||
wrappedWindow.Document.prototype,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
"write", "value", exportFunction(function write(markup){
|
||||
for (let i = 0, l = arguments.length; i < l; i += 1){
|
||||
const str = "" + arguments[i];
|
||||
|
@ -234,6 +240,7 @@
|
|||
wrappedWindow.HTMLDocument.prototype:
|
||||
wrappedWindow.Document.prototype,
|
||||
"writeln", "value", exportFunction(
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function writeln(markup){
|
||||
for (let i = 0, l = arguments.length; i < l; i += 1){
|
||||
const str = "" + arguments[i];
|
||||
|
@ -253,5 +260,21 @@
|
|||
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);
|
||||
};
|
||||
}());
|
680
lib/intercept.js
680
lib/intercept.js
|
@ -41,380 +41,394 @@
|
|||
setRandomSupplyByType(settings.rng);
|
||||
});
|
||||
|
||||
function getURL(window){
|
||||
function getURL(windowToProcess){
|
||||
let href;
|
||||
try {
|
||||
href = window.location.href;
|
||||
href = windowToProcess.location.href;
|
||||
}
|
||||
catch (e){
|
||||
catch (error){
|
||||
// unable to read location due to SOP
|
||||
// since we are not able to do anything in that case we can allow everything
|
||||
return "about:SOP";
|
||||
}
|
||||
if (!href || href === "about:blank"){
|
||||
if (window !== window.parent){
|
||||
return getURL(window.parent);
|
||||
if (windowToProcess !== windowToProcess.parent){
|
||||
return getURL(windowToProcess.parent);
|
||||
}
|
||||
else if (window.opener){
|
||||
return getURL(window.opener);
|
||||
else if (windowToProcess.opener){
|
||||
return getURL(windowToProcess.opener);
|
||||
}
|
||||
}
|
||||
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){
|
||||
if (!settings.isStillDefault){
|
||||
logging.message("settings already loaded -> no need to pre intercept");
|
||||
scope.intercept({subject: window}, apis);
|
||||
const forEach = function(windowToProcess, callback){
|
||||
forEachFunction(windowToProcess, callback);
|
||||
forEachGetter(windowToProcess, callback);
|
||||
};
|
||||
|
||||
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");
|
||||
let forceLoad = true;
|
||||
let preIntercepted = false;
|
||||
let intercepted = false;
|
||||
const forEachFunction = function(callback){
|
||||
apiNames.forEach(function(name){
|
||||
const changedFunction = changedFunctions[name];
|
||||
(
|
||||
Array.isArray(changedFunction.object)?
|
||||
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);
|
||||
};
|
||||
const doPreIntercept = function(windowToProcess, apis, state){
|
||||
const forceLoad = true;
|
||||
const originalPropertyDescriptors = {};
|
||||
const undoPreIntercept = function(){
|
||||
if (state.preIntercepted){
|
||||
state.preIntercepted = false;
|
||||
forEach(windowToProcess, function({name, object}){
|
||||
const originalPropertyDescriptor = originalPropertyDescriptors[name].get(object);
|
||||
if (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();
|
||||
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)
|
||||
}
|
||||
originalPropertyDescriptor
|
||||
);
|
||||
});
|
||||
preIntercepted = true;
|
||||
}
|
||||
};
|
||||
const undoPreIntercept = function(){
|
||||
if (preIntercepted){
|
||||
preIntercepted = false;
|
||||
forEachFunction(function({name, object}){
|
||||
const originalPropertyDescriptor = originalPropertyDescriptors[name].get(object);
|
||||
if (originalPropertyDescriptor){
|
||||
Object.defineProperty(
|
||||
object,
|
||||
name,
|
||||
originalPropertyDescriptor
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
const doRealIntercept = function(){
|
||||
if (!intercepted){
|
||||
scope.intercept({subject: window}, apis);
|
||||
intercepted = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
if (!state.preIntercepted){
|
||||
forEach(windowToProcess, 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,
|
||||
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(){
|
||||
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;
|
||||
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 {
|
||||
// return original if the extension itself requested the function
|
||||
if (
|
||||
errorStack
|
||||
.split("\n", callingDepth + 2)[callingDepth + 1]
|
||||
.split("@", callingDepth + 1)[1]
|
||||
.startsWith(extensionID)
|
||||
){
|
||||
return {allow: true, original, window};
|
||||
}
|
||||
|
||||
function generateChecker({
|
||||
name, changedFunction, siteStatus, original,
|
||||
window: windowToProcess, prefs, notify, checkStack, ask
|
||||
}){
|
||||
return function checker(callingDepth = 2){
|
||||
const errorStack = (new Error()).stack;
|
||||
|
||||
try {
|
||||
// return original if the extension itself requested the function
|
||||
if (
|
||||
errorStack
|
||||
.split("\n", callingDepth + 2)[callingDepth + 1]
|
||||
.split("@", callingDepth + 1)[1]
|
||||
.startsWith(extensionID)
|
||||
){
|
||||
return {allow: true, original, window: windowToProcess};
|
||||
}
|
||||
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;
|
||||
function notifyCallback(messageId){
|
||||
notify({
|
||||
url: getURL(window),
|
||||
errorStack,
|
||||
messageId,
|
||||
timestamp: new Date(),
|
||||
functionName: name,
|
||||
}
|
||||
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,
|
||||
dataURL: getDataURL(This, prefs)
|
||||
canvas: this instanceof HTMLCanvasElement?
|
||||
this:
|
||||
(
|
||||
this &&
|
||||
(this.canvas instanceof HTMLCanvasElement)?
|
||||
this.canvas:
|
||||
false
|
||||
),
|
||||
errorStack
|
||||
});
|
||||
}
|
||||
const protectedAPIFeatures = prefs("protectedAPIFeatures");
|
||||
if (
|
||||
funcStatus.active &&
|
||||
(
|
||||
!protectedAPIFeatures.hasOwnProperty(name + " @ " + changedFunction.api) ||
|
||||
protectedAPIFeatures[name + " @ " + changedFunction.api]
|
||||
)
|
||||
){
|
||||
if (funcStatus.mode === "ask"){
|
||||
funcStatus.mode = ask({
|
||||
window: window,
|
||||
type: changedFunction.type,
|
||||
api: changedFunction.api,
|
||||
canvas: this instanceof HTMLCanvasElement?
|
||||
this:
|
||||
(
|
||||
this &&
|
||||
(this.canvas instanceof HTMLCanvasElement)?
|
||||
this.canvas:
|
||||
false
|
||||
),
|
||||
errorStack
|
||||
switch (funcStatus.mode){
|
||||
case "allow":
|
||||
return {allow: true, original, window: windowToProcess};
|
||||
case "fake":
|
||||
return {
|
||||
allow: "fake",
|
||||
prefs,
|
||||
notify: notifyCallback,
|
||||
window: windowToProcess,
|
||||
original
|
||||
};
|
||||
//case "block":
|
||||
default:
|
||||
return {allow: false, notify: notifyCallback};
|
||||
}
|
||||
}
|
||||
else {
|
||||
return {allow: true, original, window: windowToProcess};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function interceptFunctions(windowToProcess, siteStatus, {checkStack, ask, notify, prefs}){
|
||||
apiNames.forEach(function(name){
|
||||
const changedFunction = changedFunctions[name];
|
||||
const functionStatus = changedFunction.getStatus(undefined, siteStatus, prefs);
|
||||
logging.verbose("status for", name, ":", functionStatus);
|
||||
if (functionStatus.active){
|
||||
getAllFunctionObjects(windowToProcess, changedFunction).forEach(function(object){
|
||||
if (object){
|
||||
const original = object[name];
|
||||
const checker = generateChecker({
|
||||
name, changedFunction, siteStatus, original,
|
||||
window: windowToProcess, prefs, checkStack, ask, notify
|
||||
});
|
||||
}
|
||||
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};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const siteStatus = check({url: getURL(window)});
|
||||
logging.verbose("status for page", window, siteStatus);
|
||||
if (siteStatus.mode !== "allow"){
|
||||
apiNames.forEach(function(name){
|
||||
const changedFunction = changedFunctions[name];
|
||||
const functionStatus = changedFunction.getStatus(undefined, siteStatus, prefs);
|
||||
logging.verbose("status for", name, ":", functionStatus);
|
||||
if (functionStatus.active){
|
||||
(
|
||||
Array.isArray(changedFunction.object)?
|
||||
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){
|
||||
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;
|
||||
}
|
||||
const descriptor = Object.getOwnPropertyDescriptor(object, name);
|
||||
if (descriptor){
|
||||
if (descriptor.hasOwnProperty("value")){
|
||||
if (changedFunction.fakeGenerator){
|
||||
descriptor.value = exportFunction(
|
||||
changedFunction.fakeGenerator(checker, original, windowToProcess),
|
||||
windowToProcess
|
||||
);
|
||||
}
|
||||
else {
|
||||
descriptor.get = exportFunction(function(){
|
||||
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;
|
||||
}
|
||||
descriptor.value = null;
|
||||
}
|
||||
}
|
||||
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";
|
||||
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -14,11 +14,11 @@
|
|||
scope = require.register("./lists", {});
|
||||
}
|
||||
|
||||
var settings = require("./settings");
|
||||
const settings = require("./settings");
|
||||
|
||||
|
||||
function getDomainRegExpList(domainList){
|
||||
var list = domainList
|
||||
const list = domainList
|
||||
.split(",")
|
||||
.map(function(entry){
|
||||
return entry.replace(/^\s+|\s+$/g, "");
|
||||
|
@ -27,8 +27,8 @@
|
|||
return !!entry.length;
|
||||
})
|
||||
.map(function(entry){
|
||||
var regExp;
|
||||
var domain = !!entry.match(/^[A-Za-z0-9_.-]+$/);
|
||||
let regExp;
|
||||
const domain = !!entry.match(/^[A-Za-z0-9_.-]+$/);
|
||||
if (domain){
|
||||
regExp = new RegExp("(?:^|\\.)" + entry.replace(/([\\+*?[^\]$(){}=!|.])/g, "\\$1") + "\\.?$", "i");
|
||||
}
|
||||
|
@ -59,7 +59,7 @@
|
|||
return list;
|
||||
}
|
||||
|
||||
var lists = {
|
||||
const lists = {
|
||||
white: [],
|
||||
sessionWhite: [],
|
||||
"ignore": [],
|
||||
|
@ -81,9 +81,9 @@
|
|||
});
|
||||
|
||||
function updateStackList(value){
|
||||
var list;
|
||||
let list;
|
||||
try {
|
||||
var data = JSON.parse(value);
|
||||
let data = JSON.parse(value);
|
||||
if (!Array.isArray(data)){
|
||||
data = [data];
|
||||
}
|
||||
|
@ -91,7 +91,7 @@
|
|||
return typeof entry === "object" && typeof entry.url === "string";
|
||||
});
|
||||
}
|
||||
catch(e){
|
||||
catch(error){
|
||||
list = [];
|
||||
}
|
||||
list.match = function(stack){
|
||||
|
@ -109,13 +109,13 @@
|
|||
|
||||
scope.get = function getList(type){
|
||||
if (type === "white"){
|
||||
var combined = lists.white.slice().concat(lists.sessionWhite);
|
||||
const combined = lists.white.slice().concat(lists.sessionWhite);
|
||||
return addMatchToList(combined);
|
||||
}
|
||||
return lists[type];
|
||||
};
|
||||
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 updateList(type);
|
||||
});
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
/* 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/. */
|
||||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -17,21 +16,21 @@
|
|||
scope.setSettings = function(realSettings){
|
||||
if (!settings){
|
||||
settings = realSettings;
|
||||
settings.loaded.then(scope.clearQueue);
|
||||
return settings.loaded.then(scope.clearQueue);
|
||||
}
|
||||
else {
|
||||
warning("logging: Settings can only be set once.");
|
||||
}
|
||||
};
|
||||
|
||||
var prefix = "";
|
||||
let prefix = "";
|
||||
|
||||
function leftPad(str, char, pad){
|
||||
str = "" + str;
|
||||
return char.repeat(pad - str.length) + str;
|
||||
}
|
||||
|
||||
var colors = {
|
||||
const colors = {
|
||||
1: "color: red",
|
||||
25: "color: orange",
|
||||
50: "",
|
||||
|
@ -40,7 +39,7 @@
|
|||
999: "background-color: lightgray"
|
||||
};
|
||||
|
||||
var queue = [];
|
||||
let queue = [];
|
||||
function performLog(level, args, date){
|
||||
if (!date){
|
||||
date = new Date();
|
||||
|
@ -50,7 +49,7 @@
|
|||
}
|
||||
else {
|
||||
if (settings.logLevel >= level){
|
||||
var pre = "%c[CanvasBlocker] ";
|
||||
let pre = "%c[CanvasBlocker] ";
|
||||
if (prefix){
|
||||
pre += prefix + ": ";
|
||||
}
|
||||
|
@ -71,6 +70,7 @@
|
|||
args.unshift(colors[level] || "");
|
||||
args.unshift(pre);
|
||||
}
|
||||
// eslint-disable-next-line no-console
|
||||
console.log.apply(console, args);
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +94,7 @@
|
|||
scope.clearQueue = function(){
|
||||
if (queue.length){
|
||||
metaLog("clear logging queue");
|
||||
var tmp = queue;
|
||||
const tmp = queue;
|
||||
queue = [];
|
||||
tmp.forEach(function(item){
|
||||
performLog(item.level, item.args, item.date);
|
||||
|
|
160
lib/main.js
160
lib/main.js
|
@ -6,25 +6,81 @@
|
|||
|
||||
const settings = require("./settings");
|
||||
const logging = require("./logging");
|
||||
const {error, warning, message, notice, verbose, } = logging;
|
||||
logging.setPrefix("main script");
|
||||
const persistentRndStorage = require("./persistentRndStorage");
|
||||
const notification = require("./notification");
|
||||
|
||||
message("start of background script");
|
||||
message("waiting for settings to be loaded");
|
||||
const registerSettingsContentScript = (function(){
|
||||
let unregisterSettingsContentScript = function(){};
|
||||
let lastRegistering;
|
||||
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);
|
||||
});
|
||||
};
|
||||
}());
|
||||
|
||||
logging.message("start of background script");
|
||||
logging.message("waiting for settings to be loaded");
|
||||
settings.onloaded(function(){
|
||||
notice("everything loaded");
|
||||
logging.notice("everything loaded");
|
||||
|
||||
message("perform startup reset");
|
||||
logging.message("perform startup reset");
|
||||
settings.startupReset();
|
||||
|
||||
persistentRndStorage.init();
|
||||
|
||||
message("register non port message listener");
|
||||
logging.message("register non port message listener");
|
||||
browser.runtime.onMessage.addListener(function(data){
|
||||
notice("got data without port", data);
|
||||
var keys = Object.keys(data);
|
||||
logging.notice("got data without port", data);
|
||||
const keys = Object.keys(data);
|
||||
if (data["canvasBlocker-new-domain-rnd"]){
|
||||
persistentRndStorage.setDomainData(
|
||||
data["canvasBlocker-new-domain-rnd"].domain,
|
||||
|
@ -47,31 +103,34 @@
|
|||
return;
|
||||
}
|
||||
}
|
||||
notice("pass the message to the tabs");
|
||||
logging.notice("pass the message to the tabs");
|
||||
browser.tabs.query({}).then(function(tabs){
|
||||
tabs.forEach(function(tab){
|
||||
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){
|
||||
notice("got port", port);
|
||||
logging.notice("got port", port);
|
||||
if (!port.sender.tab){
|
||||
notice("got port without tab = Firefox bug:", port);
|
||||
logging.notice("got port without tab = Firefox bug:", port);
|
||||
return;
|
||||
}
|
||||
verbose("send back the tab id", port.sender.tab.id);
|
||||
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 tab id", port.sender.tab.id);
|
||||
logging.verbose("send back the tab cookie store id", port.sender.tab.cookieStoreId);
|
||||
logging.verbose("send back the persistent random seeds", persistentRndStorage.persistentRnd);
|
||||
port.postMessage({
|
||||
tabId: port.sender.tab.id,
|
||||
cookieStoreId: port.sender.tab.cookieStoreId,
|
||||
persistentRnd: persistentRndStorage.persistentRnd,
|
||||
persistentIncognitoRnd: persistentRndStorage.persistentIncognitoRnd
|
||||
});
|
||||
var url = new URL(port.sender.url);
|
||||
const url = new URL(port.sender.url);
|
||||
port.onMessage.addListener(function(data){
|
||||
if (data.hasOwnProperty("canvasBlocker-notify")){
|
||||
notification.show(port.sender.tab.id, url, data["canvasBlocker-notify"].api);
|
||||
|
@ -79,76 +138,25 @@
|
|||
if (data.hasOwnProperty("canvasBlocker-clear-page-action")){
|
||||
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){
|
||||
let unregister = function(){};
|
||||
let lastRegistering;
|
||||
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);
|
||||
registerSettingsContentScript();
|
||||
settings.on("any", registerSettingsContentScript);
|
||||
}
|
||||
else {
|
||||
logging.error("Old Firefox does not support browser.contentScript.register()");
|
||||
}
|
||||
});
|
||||
|
||||
message("Initialize data-URL workaround.");
|
||||
logging.message("Initialize data-URL workaround.");
|
||||
require("./dataUrls").init();
|
||||
|
||||
message("Initialize navigator HTTP header protection.");
|
||||
logging.message("Initialize navigator HTTP header protection.");
|
||||
require("./navigator").init();
|
||||
|
||||
browser.runtime.onInstalled.addListener(function(details){
|
||||
|
@ -165,7 +173,7 @@
|
|||
}
|
||||
switch (details.reason){
|
||||
case "install":
|
||||
message("CanvasBlocker installed");
|
||||
logging.message("CanvasBlocker installed");
|
||||
openOptions(details.reason);
|
||||
browser.tabs.create({
|
||||
url: browser.extension.getURL("options/presets.html?notice=" + details.reason)
|
||||
|
@ -174,12 +182,12 @@
|
|||
case "update":
|
||||
settings.onloaded(function(){
|
||||
if (!settings.dontShowOptionsOnUpdate){
|
||||
message("CanvasBlocker updated");
|
||||
logging.message("CanvasBlocker updated");
|
||||
openOptions(details.reason);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
message("end");
|
||||
logging.message("end");
|
||||
}());
|
||||
|
|
|
@ -96,8 +96,7 @@
|
|||
const parentTop = getGlobalOffsetTop(parent) - getGlobalScrollTop(parent);
|
||||
const parentHeight = parent.offsetHeight;
|
||||
const height = dialog.offsetHeight;
|
||||
const top = Math.max(
|
||||
0,
|
||||
const top = Math.max(0,
|
||||
Math.min(
|
||||
container.offsetHeight - height,
|
||||
parentTop + parentHeight / 2 - height / 2
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
|||
|
||||
scope.setFunctionProperties = function setFunctionProperties(functions, data){
|
||||
Object.keys(functions).forEach(function(key){
|
||||
var func = functions[key];
|
||||
const func = functions[key];
|
||||
["type", "api", "getStatus"].forEach(function(property){
|
||||
if (data[property] && !func[property]){
|
||||
func[property] = data[property];
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -12,25 +12,24 @@
|
|||
scope = require.register("./modifiedAudioAPI", {});
|
||||
}
|
||||
|
||||
const logging = require("./logging");
|
||||
const {sha256String: hashing} = require("./hash");
|
||||
const {checkerWrapper} = require("./modifiedAPIFunctions");
|
||||
|
||||
var randomSupply = null;
|
||||
let randomSupply = null;
|
||||
|
||||
const getAudioFakeRate = function(){
|
||||
const audioFakeRate = {
|
||||
"1": function(array){return 1;},
|
||||
"10": function(array){return 10;},
|
||||
"100": function(array){return 100;},
|
||||
"1000": function(array){return 1000;},
|
||||
"1": function(){return 1;},
|
||||
"10": function(){return 10;},
|
||||
"100": function(){return 100;},
|
||||
"1000": function(){return 1000;},
|
||||
"0.1%": function(array){return array.length / 1000;},
|
||||
"1%": function(array){return array.length / 100;},
|
||||
"10%": function(array){return array.length / 10;},
|
||||
"100%": function(array){return array.length;},
|
||||
};
|
||||
return function getAudioFakeRate(array, prefs){
|
||||
var func = audioFakeRate[prefs("audioFakeRate")];
|
||||
const func = audioFakeRate[prefs("audioFakeRate")];
|
||||
if (typeof func === "function"){
|
||||
return func(array);
|
||||
}
|
||||
|
@ -66,18 +65,18 @@
|
|||
}
|
||||
|
||||
function forEachIndex(array, prefs, callback){
|
||||
var length = array.length;
|
||||
var rate = getAudioFakeRate(array, prefs);
|
||||
var start = 0;
|
||||
const length = array.length;
|
||||
const rate = getAudioFakeRate(array, prefs);
|
||||
let start = 0;
|
||||
forEachFixedIndex(prefs, function(index){
|
||||
callback(index, start);
|
||||
start += 1;
|
||||
});
|
||||
if (start < rate){
|
||||
var delta = Math.floor(length / (rate - start));
|
||||
var indexRng = randomSupply.getIndexRng(1, length - delta * (rate - start - 1), window);
|
||||
var offset = indexRng(0);
|
||||
for (var i = start; i < rate; i += 1){
|
||||
const delta = Math.floor(length / (rate - start));
|
||||
const indexRng = randomSupply.getIndexRng(1, length - delta * (rate - start - 1), window);
|
||||
let offset = indexRng(0);
|
||||
for (let i = start; i < rate; i += 1){
|
||||
callback(offset, i);
|
||||
offset += delta;
|
||||
}
|
||||
|
@ -88,7 +87,7 @@
|
|||
const intCache = Object.create(null);
|
||||
|
||||
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]){
|
||||
return true;
|
||||
}
|
||||
|
@ -105,9 +104,9 @@
|
|||
cached = floatCache[hash];
|
||||
}
|
||||
if (!cached){
|
||||
var rate = getAudioFakeRate(array, prefs);
|
||||
var noiseLevel = getAudioNoiseLevel(prefs);
|
||||
var rng = randomSupply.getRng(rate, window);
|
||||
const rate = getAudioFakeRate(array, prefs);
|
||||
const noiseLevel = getAudioNoiseLevel(prefs);
|
||||
const rng = randomSupply.getRng(rate, window);
|
||||
forEachIndex(array, prefs, function(index, i){
|
||||
let value;
|
||||
if (array[index] !== 0){
|
||||
|
@ -137,8 +136,8 @@
|
|||
cached = intCache[hash];
|
||||
}
|
||||
if (!cached){
|
||||
var rate = getAudioFakeRate(array, prefs);
|
||||
var rng = randomSupply.getValueRng(rate, window);
|
||||
const rate = getAudioFakeRate(array, prefs);
|
||||
const rng = randomSupply.getValueRng(rate, window);
|
||||
forEachIndex(array, prefs, function(index, i){
|
||||
array[index] = rng(array[index], i);
|
||||
});
|
||||
|
@ -171,9 +170,9 @@
|
|||
fakeGenerator: function(checker){
|
||||
return function getFloatFrequencyData(array){
|
||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||
var {prefs, notify, window, original} = check;
|
||||
const {prefs, notify, window, original} = check;
|
||||
notify("fakedAudioReadout");
|
||||
var ret = original.apply(this, window.Array.from(args));
|
||||
const ret = original.apply(this, window.Array.from(args));
|
||||
fakeFloat32Array(array, window, prefs);
|
||||
return ret;
|
||||
});
|
||||
|
@ -185,9 +184,9 @@
|
|||
fakeGenerator: function(checker){
|
||||
return function getByteFrequencyData(array){
|
||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||
var {prefs, notify, window, original} = check;
|
||||
const {prefs, notify, window, original} = check;
|
||||
notify("fakedAudioReadout");
|
||||
var ret = original.apply(this, window.Array.from(args));
|
||||
const ret = original.apply(this, window.Array.from(args));
|
||||
fakeUint8Array(array, window, prefs);
|
||||
return ret;
|
||||
});
|
||||
|
@ -199,9 +198,9 @@
|
|||
fakeGenerator: function(checker){
|
||||
return function getFloatTimeDomainData(array){
|
||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||
var {prefs, notify, window, original} = check;
|
||||
const {prefs, notify, window, original} = check;
|
||||
notify("fakedAudioReadout");
|
||||
var ret = original.apply(this, window.Array.from(args));
|
||||
const ret = original.apply(this, window.Array.from(args));
|
||||
fakeFloat32Array(array, window, prefs);
|
||||
return ret;
|
||||
});
|
||||
|
@ -213,9 +212,9 @@
|
|||
fakeGenerator: function(checker){
|
||||
return function getByteTimeDomainData(array){
|
||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||
var {prefs, notify, window, original} = check;
|
||||
const {prefs, notify, window, original} = check;
|
||||
notify("fakedAudioReadout");
|
||||
var ret = original.apply(this, window.Array.from(args));
|
||||
const ret = original.apply(this, window.Array.from(args));
|
||||
fakeUint8Array(array, window, prefs);
|
||||
return ret;
|
||||
});
|
||||
|
@ -225,10 +224,11 @@
|
|||
getChannelData: {
|
||||
object: ["AudioBuffer"],
|
||||
fakeGenerator: function(checker){
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
return function getChannelData(channel){
|
||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||
var {prefs, notify, window, original} = check;
|
||||
var ret = original.apply(this, window.Array.from(args));
|
||||
const {prefs, notify, window, original} = check;
|
||||
const ret = original.apply(this, window.Array.from(args));
|
||||
if (!getChannelDataAlreadyFakedArrays.get(ret)){
|
||||
notify("fakedAudioReadout");
|
||||
fakeFloat32Array(ret, window, prefs);
|
||||
|
@ -242,16 +242,17 @@
|
|||
copyFromChannel: {
|
||||
object: ["AudioBuffer"],
|
||||
fakeGenerator: function(checker){
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
return function copyFromChannel(destination, channelNumber, startInChannel){
|
||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||
var {prefs, notify, window, original} = check;
|
||||
var channelData = this.getChannelData(channelNumber);
|
||||
const {prefs, notify, window, original} = check;
|
||||
const channelData = this.getChannelData(channelNumber);
|
||||
if (!getChannelDataAlreadyFakedArrays.get(channelData)){
|
||||
notify("fakedAudioReadout");
|
||||
fakeFloat32Array(channelData, window, prefs);
|
||||
getChannelDataAlreadyFakedArrays.set(channelData, true);
|
||||
}
|
||||
var ret = original.apply(this, window.Array.from(args));
|
||||
const ret = original.apply(this, window.Array.from(args));
|
||||
return ret;
|
||||
});
|
||||
};
|
||||
|
@ -260,11 +261,12 @@
|
|||
getFrequencyResponse: {
|
||||
object: ["BiquadFilterNode", "IIRFilterNode"],
|
||||
fakeGenerator: function(checker){
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
return function getFrequencyResponse(frequencyArray, magResponseOutput, phaseResponseOutput){
|
||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||
var {prefs, notify, window, original} = check;
|
||||
const {prefs, notify, window, original} = check;
|
||||
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(phaseResponseOutput, window, prefs);
|
||||
return ret;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
const {copyCanvasToWebgl} = require("./webgl");
|
||||
const {getWrapped, checkerWrapper} = require("./modifiedAPIFunctions");
|
||||
|
||||
var randomSupply = null;
|
||||
let randomSupply = null;
|
||||
|
||||
function getContext(window, canvas){
|
||||
return window.HTMLCanvasElement.prototype.getContext.call(canvas, "2d") ||
|
||||
|
@ -20,8 +20,8 @@
|
|||
window.HTMLCanvasElement.prototype.getContext.call(canvas, "experimental-webgl2");
|
||||
}
|
||||
function getImageData(window, context){
|
||||
var imageData;
|
||||
var source;
|
||||
let imageData;
|
||||
let source;
|
||||
if ((context.canvas.width || 0) * (context.canvas.height || 0) === 0){
|
||||
imageData = 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){
|
||||
try {
|
||||
let originalDataURL;
|
||||
if (prefs("useCanvasCache")){
|
||||
var originalDataURL = original.toDataURL();
|
||||
var cached = canvasCache[originalDataURL];
|
||||
originalDataURL = original.toDataURL();
|
||||
const cached = canvasCache[originalDataURL];
|
||||
if (cached){
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
// original may not be a canvas -> we must not leak an error
|
||||
var context = getContext(window, original);
|
||||
var {imageData, source} = getImageData(window, context);
|
||||
var desc = imageData.data;
|
||||
var l = desc.length;
|
||||
let context = getContext(window, original);
|
||||
const {imageData, source} = getImageData(window, context);
|
||||
const desc = imageData.data;
|
||||
const l = desc.length;
|
||||
|
||||
var ignoredColors = {};
|
||||
var statistic;
|
||||
let ignoredColors = {};
|
||||
let statistic;
|
||||
if (prefs("ignoreFrequentColors")){
|
||||
statistic = colorStatistics.compute(source);
|
||||
ignoredColors = statistic.getMaxColors(prefs("ignoreFrequentColors"));
|
||||
|
@ -82,10 +83,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
var rng = randomSupply.getPixelRng(l, window, ignoredColors);
|
||||
var fakeAlphaChannel = prefs("fakeAlphaChannel");
|
||||
for (var i = 0; i < l; i += 4){
|
||||
var [r, g, b, a] = rng(
|
||||
const rng = randomSupply.getPixelRng(l, window, ignoredColors);
|
||||
const fakeAlphaChannel = prefs("fakeAlphaChannel");
|
||||
for (let i = 0; i < l; i += 4){
|
||||
const [r, g, b, a] = rng(
|
||||
source[i + 0],
|
||||
source[i + 1],
|
||||
source[i + 2],
|
||||
|
@ -97,7 +98,7 @@
|
|||
desc[i + 2] = b;
|
||||
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.putImageData(imageData, 0, 0);
|
||||
if (prefs("useCanvasCache")){
|
||||
|
@ -106,25 +107,25 @@
|
|||
}
|
||||
return canvas;
|
||||
}
|
||||
catch (e){
|
||||
logging.warning("Error while faking:", e);
|
||||
catch (error){
|
||||
logging.warning("Error while faking:", error);
|
||||
return original;
|
||||
}
|
||||
}
|
||||
function randomMixImageData(window, imageData1, imageData2){
|
||||
var data1 = imageData1.data;
|
||||
var data2 = imageData2.data;
|
||||
var l = data1.length;
|
||||
const data1 = imageData1.data;
|
||||
const data2 = imageData2.data;
|
||||
const l = data1.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 signG = data1[i + 1] > data2[i + 1]? -1: 1;
|
||||
const signB = data1[i + 2] > data2[i + 2]? -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]),
|
||||
signG * (data2[i + 1] - data1[i + 1]),
|
||||
signB * (data2[i + 2] - data1[i + 2]),
|
||||
|
@ -142,9 +143,9 @@
|
|||
|
||||
function canvasSizeShouldBeFaked(canvas, prefs){
|
||||
if (canvas){
|
||||
var size = canvas.height * canvas.width;
|
||||
var maxSize = prefs("maxFakeSize") || Number.POSITIVE_INFINITY;
|
||||
var minSize = prefs("minFakeSize") || 0;
|
||||
const size = canvas.height * canvas.width;
|
||||
const maxSize = prefs("maxFakeSize") || Number.POSITIVE_INFINITY;
|
||||
const minSize = prefs("minFakeSize") || 0;
|
||||
return size > minSize && size <= maxSize;
|
||||
}
|
||||
else {
|
||||
|
@ -181,7 +182,98 @@
|
|||
scope.setRandomSupply = function(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
|
||||
scope.changedFunctions = {
|
||||
getContext: {
|
||||
|
@ -209,9 +301,10 @@
|
|||
},
|
||||
object: "HTMLCanvasElement",
|
||||
fakeGenerator: function(checker){
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
return function(context, contextAttributes){
|
||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||
var {prefs, notify, window, original} = check;
|
||||
const {window, original} = check;
|
||||
canvasContextType.set(this, context);
|
||||
return original.apply(this, window.Array.from(args));
|
||||
});
|
||||
|
@ -225,7 +318,7 @@
|
|||
status = Object.create(status);
|
||||
status.active = protectedPartChecker("readout");
|
||||
if (!status.active && protectedPartChecker("input")){
|
||||
var contextType = canvasContextType.get(obj);
|
||||
const contextType = canvasContextType.get(obj);
|
||||
status.active = contextType !== "2d";
|
||||
}
|
||||
return status;
|
||||
|
@ -234,9 +327,9 @@
|
|||
fakeGenerator: function(checker){
|
||||
return function toDataURL(){
|
||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||
var {prefs, notify, window, original} = check;
|
||||
const {prefs, notify, window, original} = check;
|
||||
if (canvasSizeShouldBeFaked(this, prefs)){
|
||||
var fakeCanvas = getFakeCanvas(window, this, prefs);
|
||||
const fakeCanvas = getFakeCanvas(window, this, prefs);
|
||||
if (fakeCanvas !== this){
|
||||
notify("fakedReadout");
|
||||
}
|
||||
|
@ -256,18 +349,19 @@
|
|||
status = Object.create(status);
|
||||
status.active = protectedPartChecker("readout");
|
||||
if (!status.active && protectedPartChecker("input")){
|
||||
var contextType = canvasContextType.get(obj);
|
||||
const contextType = canvasContextType.get(obj);
|
||||
status.active = contextType !== "2d";
|
||||
}
|
||||
return status;
|
||||
},
|
||||
object: "HTMLCanvasElement",
|
||||
fakeGenerator: function(checker){
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
return function toBlob(callback){
|
||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||
var {prefs, notify, window, original} = check;
|
||||
const {prefs, notify, window, original} = check;
|
||||
if (canvasSizeShouldBeFaked(this, prefs)){
|
||||
var fakeCanvas = getFakeCanvas(window, this, prefs);
|
||||
const fakeCanvas = getFakeCanvas(window, this, prefs);
|
||||
if (fakeCanvas !== this){
|
||||
notify("fakedReadout");
|
||||
}
|
||||
|
@ -288,18 +382,19 @@
|
|||
status = Object.create(status);
|
||||
status.active = protectedPartChecker("readout");
|
||||
if (!status.active && protectedPartChecker("input")){
|
||||
var contextType = canvasContextType.get(obj);
|
||||
const contextType = canvasContextType.get(obj);
|
||||
status.active = contextType !== "2d";
|
||||
}
|
||||
return status;
|
||||
},
|
||||
object: "HTMLCanvasElement",
|
||||
fakeGenerator: function(checker){
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
return function mozGetAsFile(callback){
|
||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||
var {prefs, notify, window, original} = check;
|
||||
const {prefs, notify, window, original} = check;
|
||||
if (canvasSizeShouldBeFaked(this, prefs)){
|
||||
var fakeCanvas = getFakeCanvas(window, this, prefs);
|
||||
const fakeCanvas = getFakeCanvas(window, this, prefs);
|
||||
if (fakeCanvas !== this){
|
||||
notify("fakedReadout");
|
||||
}
|
||||
|
@ -322,12 +417,13 @@
|
|||
},
|
||||
object: "CanvasRenderingContext2D",
|
||||
fakeGenerator: function(checker){
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
return function getImageData(sx, sy, sw, sh){
|
||||
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)){
|
||||
var fakeCanvas;
|
||||
var context = this;
|
||||
let fakeCanvas;
|
||||
let context = this;
|
||||
if (this && this.canvas) {
|
||||
fakeCanvas = getFakeCanvas(window, this.canvas, prefs);
|
||||
}
|
||||
|
@ -359,12 +455,12 @@
|
|||
fakeGenerator: function(checker){
|
||||
return function isPointInPath(x, y){
|
||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||
var {prefs, notify, window, original} = check;
|
||||
var rng = randomSupply.getValueRng(1, window);
|
||||
var originalValue = original.apply(this, window.Array.from(args));
|
||||
const {notify, window, original} = check;
|
||||
const rng = randomSupply.getValueRng(1, window);
|
||||
const originalValue = original.apply(this, window.Array.from(args));
|
||||
if ((typeof originalValue) === "boolean"){
|
||||
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]);
|
||||
}
|
||||
else {
|
||||
|
@ -386,9 +482,9 @@
|
|||
fakeGenerator: function(checker){
|
||||
return function isPointInStroke(x, y){
|
||||
return checkerWrapper(checker, this, arguments, function(args, check){
|
||||
var {prefs, notify, window, original} = check;
|
||||
var rng = randomSupply.getValueRng(1, window);
|
||||
var originalValue = original.apply(this, window.Array.from(args));
|
||||
const {notify, window, original} = check;
|
||||
const rng = randomSupply.getValueRng(1, window);
|
||||
const originalValue = original.apply(this, window.Array.from(args));
|
||||
if ((typeof originalValue) === "boolean"){
|
||||
notify("fakedReadout");
|
||||
if (x instanceof window.Path2D){
|
||||
|
@ -420,22 +516,23 @@
|
|||
},
|
||||
object: "CanvasRenderingContext2D",
|
||||
fakeGenerator: function(checker){
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
return function fillText(str, x, y){
|
||||
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)){
|
||||
notify("fakedInput");
|
||||
var oldImageData;
|
||||
let oldImageData;
|
||||
try {
|
||||
// "this" is not trustable - it may be not a context
|
||||
oldImageData = getImageData(window, this).imageData;
|
||||
}
|
||||
catch (e){
|
||||
catch (error){
|
||||
// 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(args));
|
||||
var newImageData = getImageData(window, this).imageData;
|
||||
const ret = original.apply(this, window.Array.from(args));
|
||||
const newImageData = getImageData(window, this).imageData;
|
||||
this.putImageData(randomMixImageData(window, oldImageData, newImageData), 0, 0);
|
||||
return ret;
|
||||
}
|
||||
|
@ -456,22 +553,23 @@
|
|||
},
|
||||
object: "CanvasRenderingContext2D",
|
||||
fakeGenerator: function(checker){
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
return function strokeText(str, x, y){
|
||||
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)){
|
||||
notify("fakedInput");
|
||||
var oldImageData;
|
||||
let oldImageData;
|
||||
try {
|
||||
// "this" is not trustable - it may be not a context
|
||||
oldImageData = getImageData(window, this).imageData;
|
||||
}
|
||||
catch (e){
|
||||
catch (error){
|
||||
// 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(args));
|
||||
var newImageData = getImageData(window, this).imageData;
|
||||
const ret = original.apply(this, window.Array.from(args));
|
||||
const newImageData = getImageData(window, this).imageData;
|
||||
this.putImageData(randomMixImageData(window, oldImageData, newImageData), 0, 0);
|
||||
return ret;
|
||||
}
|
||||
|
@ -492,13 +590,14 @@
|
|||
},
|
||||
object: ["WebGLRenderingContext", "WebGL2RenderingContext"],
|
||||
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){
|
||||
var {prefs, notify, window, original} = check;
|
||||
const {prefs, notify, window, original} = check;
|
||||
if (!this || canvasSizeShouldBeFaked(this.canvas, prefs)){
|
||||
notify("fakedReadout");
|
||||
var fakeCanvas = getFakeCanvas(window, this.canvas, prefs);
|
||||
var {context} = copyCanvasToWebgl(
|
||||
const fakeCanvas = getFakeCanvas(window, this.canvas, prefs);
|
||||
const {context} = copyCanvasToWebgl(
|
||||
window,
|
||||
fakeCanvas,
|
||||
this instanceof window.WebGLRenderingContext? "webgl": "webgl2"
|
||||
|
@ -522,111 +621,22 @@
|
|||
},
|
||||
object: ["WebGLRenderingContext", "WebGL2RenderingContext"],
|
||||
fakeGenerator: function(checker){
|
||||
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 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];
|
||||
Object.keys(parameterChangeDefinition).forEach(function(parameterName){
|
||||
const definition = parameterChangeDefinition[parameterName];
|
||||
definition.pname = parameterName;
|
||||
if (!definition.fake){
|
||||
definition.fake = definition.isArray?
|
||||
function fake(originalValue, window){
|
||||
let faked = false;
|
||||
let fakedValue = [];
|
||||
for (var i = 0; i < originalValue.length; i += 1){
|
||||
fakedValue[i] = types[this.type](originalValue[i], this, window);
|
||||
for (let i = 0; i < originalValue.length; i += 1){
|
||||
fakedValue[i] = parameterFakeTypes[this.type](originalValue[i], this, window);
|
||||
faked |= originalValue[i] === fakedValue[i];
|
||||
originalValue[i] = fakedValue[i];
|
||||
}
|
||||
this.fake = function(originalValue){
|
||||
if (faked){
|
||||
for (var i = 0; i < originalValue.length; i += 1){
|
||||
for (let i = 0; i < originalValue.length; i += 1){
|
||||
originalValue[i] = fakedValue[i];
|
||||
}
|
||||
}
|
||||
|
@ -641,7 +651,7 @@
|
|||
};
|
||||
}:
|
||||
function fake(originalValue, window){
|
||||
let value = types[this.type](originalValue, this, window);
|
||||
let value = parameterFakeTypes[this.type](originalValue, this, window);
|
||||
let faked = value === originalValue;
|
||||
this.fake = function(){
|
||||
return {value, faked};
|
||||
|
@ -652,10 +662,10 @@
|
|||
});
|
||||
return function getParameter(pname){
|
||||
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));
|
||||
if (changeDefinition[pname]){
|
||||
const definition = changeDefinition[pname];
|
||||
if (parameterChangeDefinition[pname]){
|
||||
const definition = parameterChangeDefinition[pname];
|
||||
const {value, faked} = definition.fake(originalValue, window, prefs);
|
||||
if (faked){
|
||||
notify("fakedReadout");
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
|||
const temp = eval(`({
|
||||
get ${property}(){
|
||||
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 returnValue = navigator.getNavigatorValue("${property}");
|
||||
if (originalValue !== returnValue){
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -177,7 +177,7 @@
|
|||
const temp = {
|
||||
get availLeft(){
|
||||
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));
|
||||
if (originalValue !== 0){
|
||||
notify("fakedScreenReadout");
|
||||
|
@ -196,7 +196,7 @@
|
|||
const temp = {
|
||||
get availTop(){
|
||||
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));
|
||||
if (originalValue !== 0){
|
||||
notify("fakedScreenReadout");
|
||||
|
@ -215,7 +215,7 @@
|
|||
const temp = {
|
||||
get outerWidth(){
|
||||
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 returnValue = window.innerWidth;
|
||||
if (originalValue !== returnValue){
|
||||
|
@ -235,7 +235,7 @@
|
|||
const temp = {
|
||||
get outerHeight(){
|
||||
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 returnValue = window.innerHeight;
|
||||
if (originalValue !== returnValue){
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@
|
|||
settings.protectedAPIFeatures["userAgent @ navigator"]
|
||||
)
|
||||
){
|
||||
for (var header of details.requestHeaders){
|
||||
for (let header of details.requestHeaders){
|
||||
if (header.name.toLowerCase() === "user-agent"){
|
||||
header.value = getValue("userAgent");
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -170,6 +170,9 @@
|
|||
tabs.forEach(function(tab){
|
||||
browser.pageAction.hide(tab.id);
|
||||
});
|
||||
return;
|
||||
}).catch(function(error){
|
||||
logging.warning("Unable to get browser tabs:", error);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -188,6 +191,9 @@
|
|||
text: ""
|
||||
});
|
||||
});
|
||||
return;
|
||||
}).catch(function(error){
|
||||
logging.warning("Unable to get browser tabs:", error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
|||
|
||||
scope.persistentRnd = Object.create(null);
|
||||
scope.persistentIncognitoRnd = Object.create(null);
|
||||
let clearTimeout;
|
||||
scope.init = function init(){
|
||||
logging.message("initializing persistent rng storage");
|
||||
|
||||
|
@ -26,8 +27,8 @@
|
|||
if (settings.storePersistentRnd){
|
||||
try {
|
||||
let storedData = JSON.parse(settings.persistentRndStorage);
|
||||
for (var domain in storedData){
|
||||
var value = storedData[domain];
|
||||
for (let domain in storedData){
|
||||
const value = storedData[domain];
|
||||
if (
|
||||
Array.isArray(value) &&
|
||||
value.length === 128 &&
|
||||
|
@ -39,7 +40,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (e){
|
||||
catch (error){
|
||||
// JSON is not valid -> ignore it
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +75,7 @@
|
|||
};
|
||||
|
||||
const getInterval = function(){
|
||||
var units = {
|
||||
const units = {
|
||||
seconds: 1000,
|
||||
minutes: 60 * 1000,
|
||||
hours: 60 * 60 * 1000,
|
||||
|
@ -95,18 +96,20 @@
|
|||
})){
|
||||
clearIncognito();
|
||||
}
|
||||
return;
|
||||
}).catch(function(error){
|
||||
logging.warning("Unable to get browser windows:", error);
|
||||
});
|
||||
});
|
||||
|
||||
let clearTimeout;
|
||||
|
||||
function registerTimeout(){
|
||||
var interval = getInterval();
|
||||
const interval = getInterval();
|
||||
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");
|
||||
if (timeout > 1073741824){
|
||||
// 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);
|
||||
}
|
||||
else {
|
||||
|
@ -119,6 +122,9 @@
|
|||
tabs.forEach(function(tab){
|
||||
browser.tabs.sendMessage(tab.id, data);
|
||||
});
|
||||
return;
|
||||
}).catch(function(error){
|
||||
logging.warning("Unable to get browser tabs:", error);
|
||||
});
|
||||
}
|
||||
function clearIncognito(){
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
|||
const rngTemplate = {
|
||||
getBitRng: function(length, window){
|
||||
const rng = this.getRng(Math.ceil(length / 32), window);
|
||||
let bitIndex = 32;
|
||||
let rnd = 0;
|
||||
let mask = 0xffffffff * 2;
|
||||
return function(value, i){
|
||||
|
@ -38,20 +37,21 @@
|
|||
getValueRng: function(length, window){
|
||||
const rng = this.getBitRng(length, window);
|
||||
return function(value, i){
|
||||
var rnd = rng(value, i);
|
||||
const rnd = rng(value, i);
|
||||
|
||||
// XOR the last bit to alter it... or not
|
||||
return value ^ (rnd & 0x01);
|
||||
};
|
||||
},
|
||||
getPixelRng: function(length, window, ignoredColors){
|
||||
var rng = this.getValueRng(length, window);
|
||||
return function(r, g, b, a, i){ // eslint-disable-line max-params
|
||||
var index = String.fromCharCode(r, g, b, a);
|
||||
const rng = this.getValueRng(length, window);
|
||||
// eslint-disable-next-line max-params
|
||||
return function(r, g, b, a, i){
|
||||
const index = String.fromCharCode(r, g, b, a);
|
||||
if (ignoredColors[index]){
|
||||
return [r, g, b, a];
|
||||
}
|
||||
var baseIndex = i * 4;
|
||||
const baseIndex = i * 4;
|
||||
return [
|
||||
rng(r, baseIndex + 0),
|
||||
rng(g, baseIndex + 1),
|
||||
|
@ -81,7 +81,7 @@
|
|||
return window.location.host;
|
||||
}
|
||||
|
||||
var persistentRnd = Object.create(null);
|
||||
let persistentRnd = Object.create(null);
|
||||
let cookieStoreId = false;
|
||||
settings.onloaded(function(){
|
||||
try {
|
||||
|
@ -90,8 +90,8 @@
|
|||
settings.persistentIncognitoRndStorage:
|
||||
settings.persistentRndStorage
|
||||
);
|
||||
for (var domain in storedData){
|
||||
var value = storedData[domain];
|
||||
for (let domain in storedData){
|
||||
const value = storedData[domain];
|
||||
if (
|
||||
Array.isArray(value) &&
|
||||
value.length === 128 &&
|
||||
|
@ -103,7 +103,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (e){
|
||||
catch (error){
|
||||
// JSON is not valid -> ignore it
|
||||
}
|
||||
});
|
||||
|
@ -111,7 +111,7 @@
|
|||
|
||||
extension.message.on(function(data){
|
||||
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){
|
||||
persistentRnd[domain] = new Uint8Array(rnd);
|
||||
}
|
||||
|
@ -130,11 +130,11 @@
|
|||
xhr.send();
|
||||
xhr = null;
|
||||
}
|
||||
catch (e){
|
||||
logging.verbose("Error in XHR:", e);
|
||||
catch (error){
|
||||
logging.verbose("Error in XHR:", error);
|
||||
}
|
||||
}
|
||||
var domain = cookieStoreId + getDomain(window);
|
||||
const domain = cookieStoreId + getDomain(window);
|
||||
if (!persistentRnd[domain]){
|
||||
// create the (sub-)domains random numbers if not existing
|
||||
persistentRnd[domain] = new Uint8Array(128);
|
||||
|
@ -165,26 +165,26 @@
|
|||
}
|
||||
};
|
||||
scope.persistent.getRng = function(length, window){
|
||||
var bitSet = new Uint32Array(getPersistentRnd(window).buffer);
|
||||
var bitSetLength = bitSet.length;
|
||||
const bitSet = new Uint32Array(getPersistentRnd(window).buffer);
|
||||
const bitSetLength = bitSet.length;
|
||||
return function(i){
|
||||
return bitSet[i % bitSetLength];
|
||||
};
|
||||
};
|
||||
scope.persistent.getBitRng = function(length, window){
|
||||
var bitSet = getPersistentRnd(window);
|
||||
const bitSet = getPersistentRnd(window);
|
||||
|
||||
return function(value, i){
|
||||
// use the last 7 bits from the value for the index of the
|
||||
// random number
|
||||
var index = value & 0x7F;
|
||||
const index = value & 0x7F;
|
||||
|
||||
// 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
|
||||
var bitIndex = ((i & 0x03) << 1) | (value >>> 7);
|
||||
const bitIndex = ((i & 0x03) << 1) | (value >>> 7);
|
||||
|
||||
// extract the bit
|
||||
var bit = (bitSet[index] >>> bitIndex) & 0x01;
|
||||
const bit = (bitSet[index] >>> bitIndex) & 0x01;
|
||||
|
||||
return bit;
|
||||
};
|
||||
|
@ -196,16 +196,17 @@
|
|||
return scope.nonPersistent.getRng(length, window);
|
||||
};
|
||||
scope.constant.getPixelRng = (function(){
|
||||
var colors = Object.create(null);
|
||||
const colors = Object.create(null);
|
||||
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
|
||||
var index = String.fromCharCode(r, g, b, a);
|
||||
// eslint-disable-next-line max-params, no-unused-vars
|
||||
return function(r, g, b, a, i){
|
||||
const index = String.fromCharCode(r, g, b, a);
|
||||
if (ignoredColors[index]){
|
||||
return [r, g, b, a];
|
||||
}
|
||||
var color = colors[index];
|
||||
let color = colors[index];
|
||||
if (!color){
|
||||
color = [
|
||||
rng(r, 0),
|
||||
|
@ -224,8 +225,8 @@
|
|||
scope.nonPersistent.name = "nonPersistent";
|
||||
scope.nonPersistent.getRng = function(length, window){
|
||||
const maxLength = 0x4000;
|
||||
var randomI = maxLength;
|
||||
var randomNumbers = new Uint32Array(Math.min(maxLength, length));
|
||||
let randomI = maxLength;
|
||||
let randomNumbers = new Uint32Array(Math.min(maxLength, length));
|
||||
return function(i){
|
||||
if (randomI >= randomNumbers.length){
|
||||
// refill the random number bucket if empty
|
||||
|
@ -235,7 +236,7 @@
|
|||
}
|
||||
window.crypto.getRandomValues(randomNumbers);
|
||||
}
|
||||
var rnd = randomNumbers[randomI];
|
||||
const rnd = randomNumbers[randomI];
|
||||
randomI += 1;
|
||||
|
||||
return rnd;
|
||||
|
|
|
@ -10,14 +10,14 @@ const require = function(){
|
|||
const scope = window.scope;
|
||||
|
||||
function getScopeName(module){
|
||||
var scopeName = module.replace(/^\..*\//, "").replace(/\..+/, "");
|
||||
const scopeName = module.replace(/^\..*\//, "").replace(/\..+/, "");
|
||||
// console.log(scopeName);
|
||||
return scopeName;
|
||||
}
|
||||
|
||||
function require(module){
|
||||
if (module.startsWith(".")){
|
||||
var scopeName = getScopeName(module);
|
||||
const scopeName = getScopeName(module);
|
||||
return scope[scopeName];
|
||||
}
|
||||
throw new ReferenceError("Unable to get non relative module " + module + "!");
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@
|
|||
if (resultSets.length){
|
||||
return Array.from(
|
||||
resultSets.reduce(function(previousSet, set){
|
||||
var andSet = new Set();
|
||||
const andSet = new Set();
|
||||
set.forEach(function(entry){
|
||||
if (previousSet.has(entry)){
|
||||
andSet.add(entry);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
|||
scope.expandContainer = null;
|
||||
|
||||
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);
|
||||
}).filter(function(urlSetting){
|
||||
return urlSetting.match(url);
|
||||
|
@ -32,8 +32,8 @@
|
|||
}
|
||||
};
|
||||
scope.setUrlValue = function(name, value, url){
|
||||
var urlContainerValue = scope.urlContainer.get();
|
||||
var matching = urlContainerValue.filter(function(urlSetting){
|
||||
const urlContainerValue = scope.urlContainer.get();
|
||||
let matching = urlContainerValue.filter(function(urlSetting){
|
||||
return urlSetting.match(url);
|
||||
});
|
||||
if (!matching.length){
|
||||
|
@ -46,8 +46,8 @@
|
|||
return scope.urlContainer.set(urlContainerValue);
|
||||
};
|
||||
scope.resetUrlValue = function(name, url){
|
||||
var urlContainerValue = scope.urlContainer.get();
|
||||
var matching = urlContainerValue.filter(function(urlSetting){
|
||||
let urlContainerValue = scope.urlContainer.get();
|
||||
const matching = urlContainerValue.filter(function(urlSetting){
|
||||
return urlSetting.match(url);
|
||||
});
|
||||
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){
|
||||
if (settingDefinition.isUrlContainer){
|
||||
scope.urlContainer = settingDefinition;
|
||||
|
@ -70,89 +156,11 @@
|
|||
}
|
||||
|
||||
if (settingDefinition.isHideContainer){
|
||||
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;
|
||||
processHideContainer(settingDefinition);
|
||||
}
|
||||
|
||||
if (settingDefinition.isExpandContainer){
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
processExpandContainer(settingDefinition);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -160,8 +168,8 @@
|
|||
if (scope.urlContainer){
|
||||
scope.urlContainer.on(function({newValue, oldValue}){
|
||||
newValue.forEach(function(urlSetting){
|
||||
var regExp;
|
||||
var domain = !!urlSetting.url.match(/^[A-Za-z0-9_.-]+$/);
|
||||
let regExp;
|
||||
const domain = !!urlSetting.url.match(/^[A-Za-z0-9_.-]+$/);
|
||||
if (domain){
|
||||
regExp = new RegExp(
|
||||
"(?:^|\\.)" + urlSetting.url.replace(/([\\+*?[^\]$(){}=!|.])/g, "\\$1") + "\\.?$",
|
||||
|
@ -200,9 +208,9 @@
|
|||
);
|
||||
});
|
||||
|
||||
var newUrls = newValue.map(function(entry){return entry.url;});
|
||||
var oldUrls = oldValue.map(function(entry){return entry.url;});
|
||||
var matching = {};
|
||||
const newUrls = newValue.map(function(entry){return entry.url;});
|
||||
const oldUrls = oldValue.map(function(entry){return entry.url;});
|
||||
const matching = {};
|
||||
newUrls.forEach(function(url, i){
|
||||
matching[url] = {new: i, old: oldUrls.indexOf(url)};
|
||||
});
|
||||
|
@ -212,12 +220,12 @@
|
|||
}
|
||||
});
|
||||
Object.keys(matching).forEach(function(url){
|
||||
var oldEntry = oldValue[matching[url].old] || {};
|
||||
var newEntry = newValue[matching[url].new] || {};
|
||||
const oldEntry = oldValue[matching[url].old] || {};
|
||||
const newEntry = newValue[matching[url].new] || {};
|
||||
scope.urlContainer.entries.forEach(function(settingDefinition){
|
||||
var name = settingDefinition.name;
|
||||
var oldValue = oldEntry[name];
|
||||
var newValue = newEntry[name];
|
||||
const name = settingDefinition.name;
|
||||
const oldValue = oldEntry[name];
|
||||
const newValue = newEntry[name];
|
||||
|
||||
if (oldValue !== newValue){
|
||||
((eventHandler[name] || {})[url] || []).forEach(function(callback){
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var settingDefinitions = [
|
||||
const settingDefinitions = [
|
||||
{
|
||||
name: "logLevel",
|
||||
defaultValue: 1,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
(function(require){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@
|
|||
if (!Array.isArray(newValue)){
|
||||
return "wrongType";
|
||||
}
|
||||
var entriesInvalid = newValue.reduce(function(v, entry){
|
||||
const entriesInvalid = newValue.reduce(function(v, entry){
|
||||
v = v || settingDefinition.entries.reduce(function(v, entryDefinition){
|
||||
return v || isDefinitionInvalid(entryDefinition, entry[entryDefinition.name]);
|
||||
}, false);
|
||||
|
@ -74,7 +74,7 @@
|
|||
else if (settingDefinition.urlSpecific){
|
||||
return function getValue(url){
|
||||
if (url){
|
||||
var match = settingContainers.getUrlValueContainer(settingDefinition.name, url);
|
||||
const match = settingContainers.getUrlValueContainer(settingDefinition.name, url);
|
||||
if (match){
|
||||
return match[settingDefinition.name];
|
||||
}
|
||||
|
@ -105,13 +105,13 @@
|
|||
function createSetter(settingDefinition){
|
||||
if (settingDefinition.dynamic){
|
||||
return function setValue(newValue){
|
||||
settingDefinition.setter(scope);
|
||||
settingDefinition.setter(scope, newValue);
|
||||
};
|
||||
}
|
||||
else {
|
||||
const name = settingDefinition.name;
|
||||
const isValid = function isValid(newValue){
|
||||
var invalid = settingDefinition.invalid(newValue);
|
||||
const invalid = settingDefinition.invalid(newValue);
|
||||
if (invalid){
|
||||
if (invalid === "fixed"){
|
||||
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);
|
||||
settings[name] = newValue;
|
||||
if (!settingDefinition.transient){
|
||||
var storeObject = {};
|
||||
const storeObject = {};
|
||||
storeObject[name] = newValue;
|
||||
var promise = browser.storage.local.set(storeObject);
|
||||
const promise = browser.storage.local.set(storeObject);
|
||||
promise.then(function(){
|
||||
logging.verbose("New value stored for %s:", name, newValue);
|
||||
}, function(err){
|
||||
logging.error("Unable to store new value for %s:", name, newValue, err);
|
||||
return;
|
||||
}).catch(function(error){
|
||||
logging.error("Unable to store new value for %s:", name, newValue, error);
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
@ -227,7 +228,7 @@
|
|||
};
|
||||
|
||||
settingDefinitions.forEach(function(settingDefinition){
|
||||
var name = settingDefinition.name;
|
||||
const name = settingDefinition.name;
|
||||
definitionsByName[name] = settingDefinition;
|
||||
if (typeof settingDefinition.defaultValue === "function"){
|
||||
settingDefinition.defaultValue = settingDefinition.defaultValue();
|
||||
|
@ -282,7 +283,7 @@
|
|||
});
|
||||
|
||||
scope.getDefinition = function(name){
|
||||
var foundDefinition = definitionsByName[name];
|
||||
const foundDefinition = definitionsByName[name];
|
||||
if (foundDefinition){
|
||||
return Object.create(foundDefinition);
|
||||
}
|
||||
|
@ -300,7 +301,7 @@
|
|||
};
|
||||
|
||||
scope.set = function(name, ...args){
|
||||
var foundDefinition = definitionsByName[name];
|
||||
const foundDefinition = definitionsByName[name];
|
||||
if (foundDefinition){
|
||||
return foundDefinition.set(...args);
|
||||
}
|
||||
|
@ -309,7 +310,7 @@
|
|||
}
|
||||
};
|
||||
scope.get = function(name, ...args){
|
||||
var foundDefinition = definitionsByName[name];
|
||||
const foundDefinition = definitionsByName[name];
|
||||
if (foundDefinition){
|
||||
return foundDefinition.get(...args);
|
||||
}
|
||||
|
@ -328,9 +329,9 @@
|
|||
|
||||
const resetSymbol = Symbol("reset");
|
||||
function changeValue(name, newValue){
|
||||
var settingDefinition = scope.getDefinition(name);
|
||||
const settingDefinition = scope.getDefinition(name);
|
||||
if (settingDefinition){
|
||||
var oldValue = settings[name];
|
||||
const oldValue = settings[name];
|
||||
if (newValue === resetSymbol){
|
||||
newValue = getDefaultValue(settingDefinition);
|
||||
}
|
||||
|
@ -355,7 +356,7 @@
|
|||
browser.storage.onChanged.addListener(function(changes, area){
|
||||
if (area === "local"){
|
||||
logging.notice("settings changed", changes);
|
||||
var delayedChange = [];
|
||||
const delayedChange = [];
|
||||
Object.entries(changes).forEach(function(entry){
|
||||
const [name, change] = entry;
|
||||
if (settingContainers.urlContainer && name === settingContainers.urlContainer.name){
|
||||
|
@ -407,7 +408,7 @@
|
|||
{settings, logging, changeValue, urlContainer: settingContainers.urlContainer}
|
||||
);
|
||||
}
|
||||
var delayedChange = [];
|
||||
const delayedChange = [];
|
||||
Object.entries(storage).forEach(function(entry){
|
||||
const [name, value] = entry;
|
||||
if (settingContainers.urlContainer && name === settingContainers.urlContainer.name){
|
||||
|
@ -451,8 +452,8 @@
|
|||
xhr.send();
|
||||
xhr = null;
|
||||
}
|
||||
catch (e){
|
||||
logging.verbose("Error in XHR:", e);
|
||||
catch (error){
|
||||
logging.verbose("Error in XHR:", error);
|
||||
}
|
||||
logging.message("settings still default?", settings.isStillDefault);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -17,13 +17,14 @@
|
|||
|
||||
scope.validVersions = [undefined, 0.1, 0.2, 0.3, 0.4, 0.5];
|
||||
scope.transitions = {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
"": function(oldStorage){
|
||||
return {
|
||||
storageVersion: 0.5
|
||||
};
|
||||
},
|
||||
0.1: function(oldStorage){
|
||||
var newStorage = {
|
||||
const newStorage = {
|
||||
storageVersion: 0.2
|
||||
};
|
||||
if (oldStorage.hasOwnProperty("askOnlyOnce")){
|
||||
|
@ -32,7 +33,7 @@
|
|||
return newStorage;
|
||||
},
|
||||
0.2: function(oldStorage){
|
||||
var newStorage = {
|
||||
const newStorage = {
|
||||
storageVersion: 0.3,
|
||||
urlSettings: (
|
||||
oldStorage.urlSettings &&
|
||||
|
@ -40,13 +41,13 @@
|
|||
)? oldStorage.urlSettings: []
|
||||
};
|
||||
|
||||
var urlSettings = {};
|
||||
const urlSettings = {};
|
||||
|
||||
(oldStorage.blackList || "").split(",")
|
||||
.map(function(url){return url.trim();})
|
||||
.filter(function(url){return !!url;})
|
||||
.forEach(function(url){
|
||||
var entry = urlSettings[url];
|
||||
let entry = urlSettings[url];
|
||||
if (!entry){
|
||||
entry = {url, blockMode: "block"};
|
||||
urlSettings[url] = entry;
|
||||
|
@ -57,7 +58,7 @@
|
|||
.map(function(url){return url.trim();})
|
||||
.filter(function(url){return !!url;})
|
||||
.forEach(function(url){
|
||||
var entry = urlSettings[url];
|
||||
let entry = urlSettings[url];
|
||||
if (!entry){
|
||||
entry = {url, blockMode: "allow"};
|
||||
urlSettings[url] = entry;
|
||||
|
@ -68,7 +69,7 @@
|
|||
.map(function(url){return url.trim();})
|
||||
.filter(function(url){return !!url;})
|
||||
.forEach(function(url){
|
||||
var entry = urlSettings[url];
|
||||
let entry = urlSettings[url];
|
||||
if (!entry){
|
||||
entry = {url, showNotifications: false};
|
||||
urlSettings[url] = entry;
|
||||
|
@ -87,7 +88,7 @@
|
|||
return newStorage;
|
||||
},
|
||||
0.3: function(oldStorage){
|
||||
var newStorage = {
|
||||
const newStorage = {
|
||||
storageVersion: 0.4
|
||||
};
|
||||
if (oldStorage.hasOwnProperty("apiWhiteList")){
|
||||
|
@ -100,7 +101,7 @@
|
|||
return newStorage;
|
||||
},
|
||||
0.4: function(oldStorage){
|
||||
var newStorage = {
|
||||
const newStorage = {
|
||||
storageVersion: 0.5
|
||||
};
|
||||
|
||||
|
@ -134,7 +135,7 @@
|
|||
return newStorage;
|
||||
},
|
||||
0.5: function(oldStorage){
|
||||
var newStorage = {
|
||||
const newStorage = {
|
||||
storageVersion: 0.6
|
||||
};
|
||||
|
||||
|
@ -159,7 +160,7 @@
|
|||
},
|
||||
};
|
||||
|
||||
scope.check = function(storage, {settings, logging, changeValue, urlContainer}){
|
||||
scope.check = function(storage, {settings, logging}){
|
||||
|
||||
if (!storage.storageVersion){
|
||||
logging.message("No storage version found. Initializing storage.");
|
||||
|
@ -168,13 +169,13 @@
|
|||
browser.storage.local.set(storage);
|
||||
}
|
||||
else if (storage.storageVersion !== settings.storageVersion){
|
||||
var toChange = {};
|
||||
const toChange = {};
|
||||
while (storage.storageVersion !== settings.storageVersion){
|
||||
logging.message("Old storage found (",
|
||||
storage.storageVersion, "expected", settings.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){
|
||||
const [name, value] = entry;
|
||||
toChange[name] = value;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
scope.init = function(page){
|
||||
const basePath = browser.extension.getURL("themes");
|
||||
|
||||
var baseLink = document.createElement("link");
|
||||
const baseLink = document.createElement("link");
|
||||
baseLink.href = `${basePath}/base/layout.css`;
|
||||
baseLink.rel = "stylesheet";
|
||||
baseLink.type = "text/css";
|
||||
|
@ -25,7 +25,7 @@
|
|||
const links = ["layout", page].filter(function(file){
|
||||
return file;
|
||||
}).map(function(file){
|
||||
var link = document.createElement("link");
|
||||
const link = document.createElement("link");
|
||||
link.cbFile = file;
|
||||
link.rel = "alternative";
|
||||
link.type = "text/css";
|
||||
|
|
79
lib/webgl.js
79
lib/webgl.js
|
@ -4,9 +4,9 @@
|
|||
(function(){
|
||||
"use strict";
|
||||
|
||||
var logging = require("./logging");
|
||||
const logging = require("./logging");
|
||||
|
||||
var scope;
|
||||
let scope;
|
||||
if ((typeof exports) !== "undefined"){
|
||||
scope = exports;
|
||||
}
|
||||
|
@ -15,9 +15,8 @@
|
|||
}
|
||||
|
||||
scope.copyCanvasToWebgl = function copyCanvasToWebgl(window, canvas, webGLVersion = "webgl"){
|
||||
var webGlCanvas = canvas.cloneNode(true);
|
||||
var success;
|
||||
var context =
|
||||
const webGlCanvas = canvas.cloneNode(true);
|
||||
const context =
|
||||
window.HTMLCanvasElement.prototype.getContext.call(webGlCanvas, webGLVersion) ||
|
||||
window.HTMLCanvasElement.prototype.getContext.call(webGlCanvas, "experimental-" + webGLVersion);
|
||||
if (!context){
|
||||
|
@ -27,38 +26,35 @@
|
|||
}
|
||||
|
||||
context.viewport(0, 0, webGlCanvas.width, webGlCanvas.height);
|
||||
|
||||
var program = context.createProgram();
|
||||
|
||||
var shader = context.createShader(context.VERTEX_SHADER);
|
||||
var vertex = "attribute vec4 a_position;\nattribute vec2 a_texCoord;\nvarying vec2 v_texCoord;\n" +
|
||||
|
||||
const program = context.createProgram();
|
||||
|
||||
const vertexShader = context.createShader(context.VERTEX_SHADER);
|
||||
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}";
|
||||
context.shaderSource(shader, vertex);
|
||||
context.compileShader(shader);
|
||||
success = context.getShaderParameter(shader, context.COMPILE_STATUS);
|
||||
if (!success){
|
||||
context.deleteShader(shader);
|
||||
context.shaderSource(vertexShader, vertex);
|
||||
context.compileShader(vertexShader);
|
||||
if (!context.getShaderParameter(vertexShader, context.COMPILE_STATUS)){
|
||||
context.deleteShader(vertexShader);
|
||||
logging.warning("webgl: failed to compile vertex shader.");
|
||||
return {canvas: false, context: false};
|
||||
}
|
||||
context.attachShader(program, shader);
|
||||
context.attachShader(program, vertexShader);
|
||||
|
||||
shader = context.createShader(context.FRAGMENT_SHADER);
|
||||
var fragmenter = "precision mediump float;\nuniform sampler2D u_image;\nvarying vec2 v_texCoord;\n" +
|
||||
const fragmentShader = context.createShader(context.FRAGMENT_SHADER);
|
||||
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}";
|
||||
context.shaderSource(shader, fragmenter);
|
||||
context.compileShader(shader);
|
||||
success = context.getShaderParameter(shader, context.COMPILE_STATUS);
|
||||
if (!success){
|
||||
context.deleteShader(shader);
|
||||
context.shaderSource(fragmentShader, fragmenter);
|
||||
context.compileShader(fragmentShader);
|
||||
if (!context.getShaderParameter(fragmentShader, context.COMPILE_STATUS)){
|
||||
context.deleteShader(fragmentShader);
|
||||
logging.warning("webgl: failed to compile fragmenter shader.");
|
||||
return {canvas: false, context: false};
|
||||
}
|
||||
context.attachShader(program, shader);
|
||||
context.attachShader(program, fragmentShader);
|
||||
|
||||
context.linkProgram(program);
|
||||
success = context.getProgramParameter(program, context.LINK_STATUS);
|
||||
if (!success){
|
||||
if (!context.getProgramParameter(program, context.LINK_STATUS)){
|
||||
context.deleteProgram(program);
|
||||
logging.warning("webgl: failed to link program.");
|
||||
return {canvas: false, context: false};
|
||||
|
@ -66,8 +62,7 @@
|
|||
|
||||
context.useProgram(program);
|
||||
|
||||
var positionAttributeLocation = context.getAttribLocation(program, "a_position");
|
||||
var positionBuffer = context.createBuffer();
|
||||
const positionBuffer = context.createBuffer();
|
||||
context.bindBuffer(context.ARRAY_BUFFER, positionBuffer);
|
||||
context.bufferData(context.ARRAY_BUFFER, new Float32Array([
|
||||
-1, -1,
|
||||
|
@ -76,21 +71,21 @@
|
|||
1, 1,
|
||||
-1, 1,
|
||||
1, -1
|
||||
|
||||
]), context.STATIC_DRAW);
|
||||
|
||||
const positionAttributeLocation = context.getAttribLocation(program, "a_position");
|
||||
context.enableVertexAttribArray(positionAttributeLocation);
|
||||
var size = 2; // 2 components per iteration
|
||||
var type = context.FLOAT; // the data is 32bit floats
|
||||
var normalize = false; // don't normalize the data
|
||||
var 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 size = 2; // 2 components per iteration
|
||||
const type = context.FLOAT; // the data is 32bit floats
|
||||
const normalize = false; // don't normalize the data
|
||||
const stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position
|
||||
const offset = 0; // start at the beginning of the buffer
|
||||
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.
|
||||
var texCoordBuffer = context.createBuffer();
|
||||
const texCoordBuffer = context.createBuffer();
|
||||
context.bindBuffer(context.ARRAY_BUFFER, texCoordBuffer);
|
||||
context.bufferData(context.ARRAY_BUFFER, new Float32Array([
|
||||
0, 1,
|
||||
|
@ -102,19 +97,15 @@
|
|||
]), context.STATIC_DRAW);
|
||||
context.enableVertexAttribArray(texCoordLocation);
|
||||
context.vertexAttribPointer(texCoordLocation, 2, context.FLOAT, false, 0, 0);
|
||||
|
||||
var texture = context.createTexture();
|
||||
context.bindTexture(context.TEXTURE_2D, texture);
|
||||
|
||||
context.bindTexture(context.TEXTURE_2D, context.createTexture());
|
||||
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_MIN_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);
|
||||
|
||||
var primitiveType = context.TRIANGLES;
|
||||
var triangleOffset = 0;
|
||||
var count = 6;
|
||||
context.drawArrays(primitiveType, triangleOffset, count);
|
||||
|
||||
context.drawArrays(context.TRIANGLES /*primitiveType*/, 0 /*triangleOffset*/, 6 /*count*/);
|
||||
|
||||
return {webGlCanvas, context};
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue