diff --git a/test/detectionTest.html b/test/detectionTest.html
index 7a22d0f..994ab75 100644
--- a/test/detectionTest.html
+++ b/test/detectionTest.html
@@ -1,8 +1,7 @@
-
- Detection Test
+ Detection test
+Detection test
+Checks if the addon can be detected by websites.
-
+
\ No newline at end of file
diff --git a/test/detectionTest.js b/test/detectionTest.js
new file mode 100644
index 0000000..dd8113b
--- /dev/null
+++ b/test/detectionTest.js
@@ -0,0 +1,195 @@
+
+var addTest = (function(){
+ var stati = [
+ {className: "notRun", text: "not run"},
+ {className: "loud", text: "CB detected"},
+ {className: "stealthy", text: "CB not detected"},
+ {className: "failed", text: "test failed"}
+ ];
+ var ul = document.getElementById("tests");
+ return function addTest(name, func){
+ var logs = [];
+ function log(){
+ logs.push(Array.prototype.slice.call(arguments).join(" "));
+ }
+ var status = 0;
+ try {
+ status = func(log)? 1: 2;
+ }
+ catch (e){
+ console.log(e);
+ status = 3;
+ }
+ var li = document.createElement("li");
+ li.className = stati[status].className;
+ var nameNode = document.createElement("span");
+ nameNode.className = "name";
+ nameNode.textContent = name;
+ nameNode.title = func.toString();
+ li.appendChild(nameNode);
+ li.appendChild(document.createTextNode(": "));
+ var statusNode = document.createElement("span");
+ statusNode.className = "status";
+ statusNode.textContent = stati[status].text;
+ statusNode.title = logs.join("\n");
+ li.appendChild(statusNode);
+ ul.appendChild(li);
+ }
+}());
+
+addTest("function length", function(log){
+ if (CanvasRenderingContext2D.prototype.getImageData.length !== 4){
+ log("expected 4 parameters for getImageData - got", CanvasRenderingContext2D.prototype.getImageData.length);
+ return true;
+ }
+ else {
+ return false;
+ }
+});
+addTest("function code", function(log){
+ if (!CanvasRenderingContext2D.prototype.getImageData.toString().match(/^\s*function getImageData\s*\(\)\s*\{\s*\[native code\]\s*\}\s*$/)){
+ log("unexpected function code:", CanvasRenderingContext2D.prototype.getImageData.toString());
+ return true;
+ }
+ else {
+ return false;
+ }
+});
+addTest("function name", function(){return CanvasRenderingContext2D.prototype.getImageData.name !== "getImageData"});
+addTest("error provocation 1", function(log){
+ var canvas = document.createElement('canvas');
+ var ctx = canvas.getContext("2d");
+ var canvasBlocker = false;
+ try{
+ ctx.getImageData(0, 0, 0, 0);
+ }
+ catch (err){
+ try {
+ log(err.name);
+ log(err.toString());
+ }
+ catch (e){
+ canvasBlocker = true;
+ }
+ }
+ return canvasBlocker;
+});
+addTest("error provocation 2", function(log){
+ var canvas = document.createElement('canvas');
+ canvas.width = 0;
+ var ctx = canvas.getContext("2d");
+ var canvasBlocker = false;
+ try{
+ ctx.getImageData(0, 0, 1, 1);
+ log("no error provoked");
+ }
+ catch (err){
+ try {
+ log(err.name);
+ log(err.toString());
+ }
+ catch (e){
+ canvasBlocker = true;
+ }
+ }
+ return canvasBlocker;
+});
+addTest("error provocation 3", function(log){
+ var canvasBlocker = false;
+ try{
+ CanvasRenderingContext2D.prototype.getImageData.apply(undefined, [0, 0, 1, 1]);
+ }
+ catch (err){
+ try {
+ log(err.name);
+ log(err.toString());
+ }
+ catch (e){
+ canvasBlocker = true;
+ }
+ }
+ return canvasBlocker;
+});
+function testKnownPixelValue(size, log){
+ var canvas = document.createElement("canvas");
+ canvas.height = size;
+ canvas.width = size;
+ var context = canvas.getContext("2d");
+ context.fillStyle = "rgba(0, 127, 255, 1)";
+ var pixelValues = [0, 127, 255, 255];
+ context.fillRect(0, 0, canvas.width, canvas.height);
+ var p = context.getImageData(0, 0, canvas.width, canvas.height).data;
+ for (var i = 0; i < p.length; i += 1){
+ if (p[i] !== pixelValues[i%4]){
+ log("wrong value", p[i], "at", i, "expected", pixelValues[i%4]);
+ return true;
+ }
+ }
+ return false;
+}
+addTest("known pixel value test 1", function(log){
+ return testKnownPixelValue(1, log);
+});
+addTest("known pixel value test 10", function(log){
+ return testKnownPixelValue(10, log);
+});
+addTest("double readout test", function(log){
+ var canvas = document.createElement("canvas");
+ var context = canvas.getContext("2d");
+ var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
+ for (var i = 0; i < imageData.data.length; i += 1){
+ if (i % 4 !== 3){
+ imageData.data[i] = Math.floor(256 * Math.random());
+ }
+ else {
+ imageData.data[i] = 255;
+ }
+ }
+ context.putImageData(imageData, 0, 0);
+
+ var imageData1 = context.getImageData(0, 0, canvas.width, canvas.height);
+ var imageData2 = context.getImageData(0, 0, canvas.width, canvas.height);
+ for (var i = 0; i < imageData2.data.length; i += 1){
+ if (imageData1.data[i] !== imageData2.data[i]){
+ log("mismatch at", i, ":",
+ imageData1.data[i], "(", imageData1.data[i].toString(2), ")",
+ "!=",
+ imageData2.data[i], "(", imageData2.data[i].toString(2), ")",
+ "| original:", imageData.data[i], "(", imageData.data[i].toString(2), ")"
+ );
+ return true;
+ }
+ }
+ return false;
+});
+addTest("readout - in - out test", function(log){
+ var canvas = document.createElement("canvas");
+ var context = canvas.getContext("2d");
+ var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
+ for (var i = 0; i < imageData.data.length; i += 1){
+ if (i % 4 !== 3){
+ imageData.data[i] = Math.floor(256 * Math.random());
+ }
+ else {
+ imageData.data[i] = 255;
+ }
+ }
+ context.putImageData(imageData, 0, 0);
+
+ var imageData1 = context.getImageData(0, 0, canvas.width, canvas.height);
+ var canvas2 = document.createElement("canvas");
+ var context2 = canvas2.getContext("2d");
+ context2.putImageData(imageData1, 0, 0);
+ var imageData2 = context2.getImageData(0, 0, canvas.width, canvas.height);
+ for (var i = 0; i < imageData2.data.length; i += 1){
+ if (imageData1.data[i] !== imageData2.data[i]){
+ log("mismatch at", i, ":",
+ imageData1.data[i], "(", imageData1.data[i].toString(2), ")",
+ "!=",
+ imageData2.data[i], "(", imageData2.data[i].toString(2), ")"
+ );
+ return true;
+ }
+ }
+ return false;
+});
\ No newline at end of file
diff --git a/test/firstPossibleCall.js b/test/firstPossibleCall.js
new file mode 100644
index 0000000..3d1f0e4
--- /dev/null
+++ b/test/firstPossibleCall.js
@@ -0,0 +1 @@
+console.log("first possible call");
\ No newline at end of file
diff --git a/test/index.html b/test/index.html
new file mode 100644
index 0000000..6c42639
--- /dev/null
+++ b/test/index.html
@@ -0,0 +1,15 @@
+
+
+
+ Test pages
+
+
+Test pages for CanvasBlocker
+
+
+
\ No newline at end of file
diff --git a/test/performanceTest.html b/test/performanceTest.html
index 4047820..ef866e8 100644
--- a/test/performanceTest.html
+++ b/test/performanceTest.html
@@ -1,137 +1,12 @@
-
Performance test
+Performance test
+Tests the canvas readout performance.
-
+
\ No newline at end of file
diff --git a/test/performanceTest.js b/test/performanceTest.js
new file mode 100644
index 0000000..6a74eb2
--- /dev/null
+++ b/test/performanceTest.js
@@ -0,0 +1,123 @@
+
+var createLog = function(){
+ var div = document.getElementById("log");
+
+ return function createLog(){
+ var logDiv = document.createElement("div");
+ logDiv.className = "log";
+ div.appendChild(logDiv);
+ return function createLine(str){
+ var logLine = document.createElement("div");
+ logLine.className = "logLine";
+ logDiv.appendChild(logLine);
+ logLine.textContent = str;
+ return function updateLine(str){
+ logLine.textContent = str;
+ };
+ };
+ };
+}();
+
+var performTest = function(){
+ return function performTest(name, func, innerRunLength, outerRunLength){
+ var log = createLog();
+ log("test " + name);
+ var line = log("starting");
+ var time = 0;
+ var time2 = 0;
+ var min = Number.POSITIVE_INFINITY;
+ var max = 0;
+ var outerI = 0;
+ function run(){
+ for (var i = 0; i < innerRunLength; i += 1){
+ func.prepare();
+ var start = performance.now();
+ func.test();
+ var end = performance.now();
+ var duration = end - start;
+ min = Math.min(min, duration);
+ max = Math.max(max, duration);
+ time2 += duration * duration;
+ time += duration;
+ }
+ outerI += 1;
+ var totalRunI = outerI * innerRunLength;
+ line(
+ "finished run " + totalRunI + " from " + (innerRunLength * outerRunLength) +
+ " -> average: " + (time / totalRunI).toFixed(2) + "ms" +
+ "(min: " + min.toFixed(2) + "ms, max: " + max.toFixed(2) + "ms)"
+ );
+ if (outerI < outerRunLength){
+ window.setTimeout(run, 10);
+ }
+ else {
+ log("finished");
+ }
+ }
+ window.setTimeout(run, 10);
+ };
+}();
+
+function draw(canvas){
+ canvas.setAttribute("width", 220);
+ canvas.setAttribute("height", 30);
+
+ var fp_text = "BrowserLeaks,com 10";
+
+ var ctx = canvas.getContext('2d');
+ ctx.textBaseline = "top";
+ ctx.font = "14px 'Arial'";
+ ctx.textBaseline = "alphabetic";
+ ctx.fillStyle = "#f60";
+ ctx.fillRect(125, 1, 62, 20);
+ ctx.fillStyle = "#069";
+ ctx.fillText(fp_text, 2, 15);
+ ctx.fillStyle = "rgba(102, 204, 0, 07)";
+ ctx.fillText(fp_text, 4, 17);
+
+ return ctx;
+}
+
+var fingerprintTest = function(){
+ var canvas;
+ return {
+ prepare: function(){
+ // create window canvas
+ canvas = document.createElement('canvas');
+ // draw image in window canvas
+ draw(canvas);
+ },
+ test: function fingerprintTest(){
+ return canvas.toDataURL();
+ }
+ };
+}();
+
+var randomImageTest = function(){
+ var canvas;
+
+ return {
+ prepare: function(){
+ canvas = document.createElement("canvas");
+ canvas.width = 1000;
+ canvas.height = 100;
+ var imageData = new ImageData(canvas.width, canvas.height);
+ var data = imageData.data;
+
+ for (var i = 0; i < data.length; i += 4){
+ data[i + 0] = Math.floor(256 * Math.random());
+ data[i + 1] = Math.floor(256 * Math.random());
+ data[i + 2] = Math.floor(256 * Math.random());
+ data[i + 3] = 255;
+ }
+
+ canvas.getContext("2d").putImageData(imageData, 0, 0);
+ },
+ test: function randomImageTest(){
+ return canvas.toDataURL();
+ }
+ };
+}();
+
+performTest("fingerprinting", fingerprintTest, 10, 100);
+performTest("big random image", randomImageTest, 10, 10);
\ No newline at end of file
diff --git a/test/test-main.js b/test/test-main.js
deleted file mode 100644
index 147f98a..0000000
--- a/test/test-main.js
+++ /dev/null
@@ -1,12 +0,0 @@
-var main = require("./main");
-
-exports["test main"] = function(assert) {
- assert.pass("Unit test running!");
-};
-
-exports["test main async"] = function(assert, done) {
- assert.pass("async Unit test running!");
- done();
-};
-
-require("sdk/test").run(exports);
diff --git a/test/test.html b/test/test.html
index 15fa015..0f51f0b 100644
--- a/test/test.html
+++ b/test/test.html
@@ -1,5 +1,5 @@
-
+
Test
@@ -18,76 +18,5 @@
refresh
-
+
\ No newline at end of file
diff --git a/test/test.js b/test/test.js
new file mode 100644
index 0000000..12302df
--- /dev/null
+++ b/test/test.js
@@ -0,0 +1,71 @@
+
+(function(){
+ function show(container, url){
+ container.querySelector(".display").src = url;
+ var buffer = new TextEncoder("utf-8").encode(url);
+ crypto.subtle.digest("SHA-256", buffer).then(function(hash){
+ var chunks = [];
+ (new Uint32Array(hash)).forEach(function(num){
+ chunks.push(num.toString(16));
+ });
+ container.querySelector(".hash").textContent = chunks.map(function(chunk){
+ return "0".repeat(8 - chunk.length) + chunk;
+ }).join("");
+ });
+ }
+
+ if (location.search !== "?notInitial"){
+ show(document.getElementById("top"), topTest());
+ show(document.getElementById("iframe"), iframeTest());
+ }
+ document.querySelector("#top button").addEventListener("click", function(){show(document.getElementById("top"), topTest());});
+ document.querySelector("#iframe button").addEventListener("click", function(){show(document.getElementById("iframe"), iframeTest());});
+}());
+
+function draw(canvas){
+ canvas.setAttribute("width", 220);
+ canvas.setAttribute("height", 30);
+
+ var fp_text = "BrowserLeaks,com 10";
+
+ var ctx = canvas.getContext('2d');
+ ctx.textBaseline = "top";
+ ctx.font = "14px 'Arial'";
+ ctx.textBaseline = "alphabetic";
+ ctx.fillStyle = "#f60";
+ ctx.fillRect(125, 1, 62, 20);
+ ctx.fillStyle = "#069";
+ ctx.fillText(fp_text, 2, 15);
+ ctx.fillStyle = "rgba(102, 204, 0, 07)";
+ ctx.fillText(fp_text, 4, 17);
+
+ return ctx;
+}
+
+function topTest(){
+ // create window canvas
+ var canvas = document.createElement('canvas');
+ // draw image in window canvas
+ draw(canvas);
+ return canvas.toDataURL();
+}
+
+function iframeTest(){
+
+ // create window canvas
+ var canvas = document.createElement('canvas');
+
+ // draw image in window canvas
+ draw(canvas);
+
+ // create iframe canvas and ctx
+ var iframe_canvas = document.querySelector("#iframe iframe").contentDocument.createElement('canvas');
+ iframe_canvas.setAttribute("width", 220);
+ iframe_canvas.setAttribute("height", 30);
+ var iframe_ctx = iframe_canvas.getContext('2d');
+
+ // copy image from window canvas to iframe ctx
+ iframe_ctx.drawImage(canvas, 0, 0);
+
+ return iframe_canvas.toDataURL();
+}
\ No newline at end of file
diff --git a/test/webGL-Test.html b/test/webGL-Test.html
index a693f62..58e363f 100644
--- a/test/webGL-Test.html
+++ b/test/webGL-Test.html
@@ -1,22 +1,11 @@
- Test
+ webGL test
-
-
-
+webGL test
+Checks if the addon also supports webGL.
+
+
\ No newline at end of file
diff --git a/test/webGL-Test.js b/test/webGL-Test.js
new file mode 100644
index 0000000..25424f3
--- /dev/null
+++ b/test/webGL-Test.js
@@ -0,0 +1,18 @@
+(function(){
+ var canvas = document.createElement('canvas');
+ canvas.width = 11;
+ canvas.height = 13;
+ var gl = canvas.getContext('webgl');
+
+ // paint it completely black
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var pixels = new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4);
+ gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ var values = {};
+ for (var i = 0; i < pixels.length; i += 1){
+ values[pixels[i]] = (values[pixels[i]] || 0) + 1;
+ }
+ document.getElementById("output").textContent = JSON.stringify(values);
+}());
\ No newline at end of file