Added setting "ignoreFrequentColors"

This commit is contained in:
kkapsner 2017-08-07 21:03:34 +02:00
parent 9da251b14d
commit 1733be23f2
8 changed files with 131 additions and 7 deletions

View File

@ -184,6 +184,15 @@
"description": ""
},
"ignoreFrequentColors_title": {
"message": "Ignoriere die häufigsten Farben",
"description": ""
},
"ignoreFrequentColors_description": {
"message": "Anzahl der Farben, die pro Canvas nicht vorgetäuscht werden sollen. Dies ist ein Parameter, der die Detektion des Addons erschweren soll.\nACHTUNG: Dies kann die Geschwindigkeit des Addons beeinträchtigen, da für jedes Bild die Farbstatistik berechnet werden muss. Außerdem kann es die Sicherheit des Addons verringern, wenn der Wert zu hoch gestellt wird. Deswegen wird stark empfohlen, diesen Wert nicht über 3 zu setzen.",
"description": ""
},
"disableNotifications": {
"message": "Benachrichtigungen deaktivieren",
"description": ""

View File

@ -183,6 +183,15 @@
"message": "Clear",
"description": ""
},
"ignoreFrequentColors_title": {
"message": "Ignore the most frequent colors",
"description": ""
},
"ignoreFrequentColors_description": {
"message": "Number of colors that should not be faked per canvas. This is a parameter to prevent detection.\nCAUTION: This can reduce the performance of the addon because the color statistic has to be calculated for every image. Additional this can lower the safety of the addon, therefore it is highly recommended not to set this value above 3.",
"description": ""
},
"disableNotifications": {
"message": "disable notifications",

80
lib/colorStatistics.js Normal file
View File

@ -0,0 +1,80 @@
/* jslint moz: true */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
(function(){
"use strict";
var scope;
if ((typeof exports) !== "undefined"){
scope = exports;
}
else {
window.scope.colorStatistics = {};
scope = window.scope.colorStatistics;
}
class Statistic{
constructor(){
this.colors = Object.create(null);
this.numberOfColors = 0;
this.minBoundary = {count: Number.NEGATIVE_INFINITY};
this.maxBoundary = {count: Number.POSITIVE_INFINITY, previousColor: this.minBoundary};
this.minBoundary.nextColor = this.maxBoundary;
}
addColor(r, g, b, a){
var index = String.fromCharCode(r, g, b, a);
var color = this.colors[index];
if (!color){
color = {index, color: [r, g, b, a], count: 0, previousColor: this.minBoundary, nextColor: this.minBoundary.nextColor};
this.numberOfColors += 1;
this.minBoundary.nextColor = color;
color.nextColor.previousColor = color;
this.colors[index] = color;
}
color.count += 1;
if (color.count > color.nextColor.count){
// swap colors to remain in right order
// a -> b -> c -> d becomes a -> c -> b -> d
var a = color.previousColor;
var b = color;
var c = color.nextColor;
var d = color.nextColor.nextColor;
a.nextColor = c;
c.previousColor = a;
c.nextColor = b;
b.previousColor = c;
b.nextColor = d;
d.previousColor = b;
}
}
getMaxColors(n){
var n = Math.min(n, this.numberOfColors);
var colors = Object.create(null);
var current = this.maxBoundary;
for (;n && current;n -= 1){
current = current.previousColor;
colors[current.index] = current;
}
return colors;
}
}
scope.compute = function computeColorStatistics(rawData){
var statistic = new Statistic();
for (var i = 0, l = rawData.length; i < l; i += 4){
statistic.addColor(
rawData[i + 0],
rawData[i + 1],
rawData[i + 2],
rawData[i + 3]
);
}
return statistic;
}
}());

View File

@ -8,6 +8,7 @@ var settings = {
minFakeSize: 1,
maxFakeSize: 0,
rng: "constant",
ignoreFrequentColors: 0,
persistentRndStorage: "",
storePersistentRnd: false,
askOnlyOnce: true,

View File

@ -14,6 +14,8 @@
scope = window.scope.modifiedAPI;
}
const colorStatistics = require("./colorStatistics");
// let Cu = require("chrome").Cu;
var randomSupply = null;
@ -52,7 +54,7 @@
};
}
function getFakeCanvas(window, original){
function getFakeCanvas(window, original, prefs){
try {
// original may not be a canvas -> we must not leak an error
var context = getContext(window, original);
@ -61,6 +63,11 @@
var l = desc.length;
var ignoredColors = {};
if (prefs("ignoreFrequentColors")){
var statistic = colorStatistics.compute(source);
ignoredColors = statistic.getMaxColors(prefs("ignoreFrequentColors"));
}
var rng = randomSupply.getPixelRng(l, window, ignoredColors);
for (var i = 0; i < l; i += 4){
@ -175,7 +182,7 @@
return function toDataURL(){
if (canvasSizeShouldBeFaked(this, prefs)){
notify.call(this, "fakedReadout");
return original.apply(getFakeCanvas(window, this), window.Array.from(arguments));
return original.apply(getFakeCanvas(window, this, prefs), window.Array.from(arguments));
}
else {
return original.apply(this, window.Array.from(arguments));
@ -201,7 +208,7 @@
return function toBlob(callback){
if (canvasSizeShouldBeFaked(this, prefs)){
notify.call(this, "fakedReadout");
return original.apply(getFakeCanvas(window, this), window.Array.from(arguments));
return original.apply(getFakeCanvas(window, this, prefs), window.Array.from(arguments));
}
else {
return original.apply(this, window.Array.from(arguments));
@ -228,7 +235,7 @@
return function mozGetAsFile(callback){
if (canvasSizeShouldBeFaked(this, prefs)){
notify.call(this, "fakedReadout");
return original.apply(getFakeCanvas(window, this), window.Array.from(arguments));
return original.apply(getFakeCanvas(window, this, prefs), window.Array.from(arguments));
}
else {
return original.apply(this, window.Array.from(arguments));
@ -257,11 +264,11 @@
var fakeCanvas;
var context = this;
if (this && this.canvas) {
fakeCanvas = getFakeCanvas(window, this.canvas);
fakeCanvas = getFakeCanvas(window, this.canvas, prefs);
}
if (fakeCanvas && fakeCanvas !== this.canvas){
context = window.HTMLCanvasElement.prototype.getContext.call(
getFakeCanvas(window, this.canvas),
fakeCanvas,
"2d"
);
}
@ -349,7 +356,12 @@
var xPixels = pixels;
var ret = original.apply(this, window.Array.from(arguments));
var l = xPixels.length;
var rng = randomSupply.getPixelRng(l, window, {});
var ignoredColors = {};
if (prefs("ignoreFrequentColors")){
var statistic = colorStatistics.compute(pixels);
ignoredColors = statistic.getMaxColors(prefs("ignoreFrequentColors"));
}
var rng = randomSupply.getPixelRng(l, window, ignoredColors);
for (var i = 0; i < l; i += 4){
var [r, g, b, a] = rng(

View File

@ -25,6 +25,7 @@
"lib/logging.js",
"lib/colorStatistics.js",
"lib/modifiedAPI.js",
"lib/randomSupplies.js",
"lib/intercept.js",

View File

@ -130,6 +130,15 @@ document.body.appendChild(table);
"rng": ["persistent"]
}
},
{
"name": "ignoreFrequentColors",
"title": "Ignore most frequent colors",
"type": "integer",
"value": 0,
"displayDependencies": {
"blockMode": ["fakeReadout"]
}
},
{
"name": "askOnlyOnce",
"title": "Ask only once",

View File

@ -6,6 +6,7 @@ Version 0.4.0:
- switched to webExtension
- notifications are now done via page action
- minimal and maximal fake size are now respected in all fakeable functions
- fake readout now fakes one pixel at once and no longer one single channel
new features:
- information of all fake events in one tab are visible
@ -13,6 +14,8 @@ Version 0.4.0:
- new preferences:
* minimal fake size
* setting to enable the inspection of the content of the faked canvas
* new random number generator "constant"
* setting to not fake the most frequent colors in a canvas
fixes:
- ask mode did not work for input types