1
0
mirror of https://github.com/kkapsner/CanvasBlocker synced 2024-12-22 12:50:36 +01:00

First working webExtesion.

This commit is contained in:
kkapsner 2017-06-25 22:33:12 +02:00
parent 4ea073132d
commit cba5680406
9 changed files with 266 additions and 310 deletions

View File

@ -4,7 +4,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
(function(){
"use strict";
const {process, frames} = require("sdk/remote/child");
const {intercept} = require("./intercept.js");
const {ask} = require("./askForPermission.js");
const {check: originalCheck, checkStack: originalCheckStack} = require("./check.js");
@ -38,7 +37,7 @@
});
}
function notify(data){
process.port.emit("canvasBlocker-notify", data);
browser.runtime.sendMessage({"canvasBlocker-notify": data});
}
const preferences = require("sdk/simple-prefs");
@ -46,22 +45,59 @@
return preferences.prefs[name];
}
frames.forEvery(function(frame){
frame.addEventListener("DOMWindowCreated", function(ev){
function notify(data){
frame.port.emit("canvasBlocker-notify", data);
}
if (enabled){
var subject = ev.target.defaultView;
intercept(
{subject},
{check, checkStack, ask: askWrapper, notify, prefs}
);
}
var interceptedWindows = new WeakMap();
function interceptWindow(window){
if (interceptedWindows.get(window)){
return false;
}
intercept(
{subject: window},
{check, checkStack, ask: askWrapper, notify, prefs}
);
[window.HTMLIFrameElement, window.HTMLFrameElement].forEach(function(constructor){
var oldContentWindowGetter = constructor.prototype.__lookupGetter__("contentWindow");
Object.defineProperty(
constructor.prototype.wrappedJSObject,
"contentWindow",
{
enumerable: true,
configureable: true,
get: exportFunction(function(){
var window = oldContentWindowGetter.call(this);
interceptWindow(window);
return window;
}, window)
}
);
var oldContentDocumentGetter = constructor.prototype.__lookupGetter__("contentDocument");
Object.defineProperty(
constructor.prototype.wrappedJSObject,
"contentDocument",
{
enumerable: true,
configureable: true,
get: exportFunction(function(){
var document = oldContentDocumentGetter.call(this);
interceptWindow(document.defaultView);
return document;
}, window)
}
);
});
});
interceptedWindows.set(window, true);
return true;
};
if (enabled){
interceptWindow(window);
}
process.port.on("canvasBlocker-unload", function unload(){
enabled = false;
browser.runtime.onMessage.addListener(function(data){
if (data["canvasBlocker-unload"]){
enabled = false;
}
});
}());

View File

@ -60,7 +60,7 @@
{
enumerable: true,
configureable: false,
get: exportFunction(function()
get: exportFunction(function(){
var url = getURL(window);
if (!url){
return undef;

View File

@ -3,110 +3,124 @@
* 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/. */
var preferences = require("sdk/simple-prefs");
var prefService = require("sdk/preferences/service");
var prefs = preferences.prefs;
function getDomainRegExpList(domainList){
(function(){
"use strict";
var list = domainList
.split(",")
.map(function(entry){
return entry.replace(/^\s+|\s+$/g, "");
})
.filter(function(entry){
return !!entry.length;
})
.map(function(entry){
var regExp;
var domain = !!entry.match(/^[\w.]+$/);
if (domain){
regExp = new RegExp("(?:^|\\.)" + entry.replace(/([\\\+\*\?\[\^\]\$\(\)\{\}\=\!\|\.])/g, "\\$1") + "\\.?$", "i");
}
else {
regExp = new RegExp(entry, "i");
}
return {
match: function(url){
if (domain){
return (url.hostname || "").match(regExp);
}
else {
return url.href.match(regExp);
}
var scope;
if ((typeof exports) !== "undefined"){
scope = exports;
}
else {
window.scope.lists = {};
scope = window.scope.lists;
}
var preferences = require("sdk/simple-prefs");
var prefs = preferences.prefs;
function getDomainRegExpList(domainList){
"use strict";
var list = domainList
.split(",")
.map(function(entry){
return entry.replace(/^\s+|\s+$/g, "");
})
.filter(function(entry){
return !!entry.length;
})
.map(function(entry){
var regExp;
var domain = !!entry.match(/^[\w.]+$/);
if (domain){
regExp = new RegExp("(?:^|\\.)" + entry.replace(/([\\\+\*\?\[\^\]\$\(\)\{\}\=\!\|\.])/g, "\\$1") + "\\.?$", "i");
}
};
});
list.match = function(url){
return this.some(function(entry){
return entry.match(url);
else {
regExp = new RegExp(entry, "i");
}
return {
match: function(url){
if (domain){
return (url.hostname || "").match(regExp);
}
else {
return url.href.match(regExp);
}
}
};
});
};
list.match = function(url){
return this.some(function(entry){
return entry.match(url);
});
};
return list;
}
var lists = {
white: [],
"ignore": [],
black: []
};
function updateList(type){
"use strict";
return list;
}
var lists = {
white: [],
"ignore": [],
black: []
};
function updateList(type){
"use strict";
lists[type] = getDomainRegExpList(prefs[type + "List"]);
}
Object.keys(lists).forEach(function(type){
"use strict";
preferences.on(type + "List", function(){
lists[type] = getDomainRegExpList(prefs[type + "List"]);
}
Object.keys(lists).forEach(function(type){
"use strict";
preferences.on(type + "List", function(){
updateList(type);
});
updateList(type);
});
updateList(type);
});
function updateStackList(){
var list;
try {
var data = JSON.parse(prefs.stackList);
if (!Array.isArray(data)){
data = [data];
function updateStackList(){
var list;
try {
var data = JSON.parse(prefs.stackList);
if (!Array.isArray(data)){
data = [data];
}
list = data.filter(function(entry){
return typeof entry === "object" && typeof entry.url === "string";
});
}
list = data.filter(function(entry){
return typeof entry === "object" && typeof entry.url === "string";
});
catch(e){
list = [];
}
list.match = function(stack){
return this.some(function(stackRule){
return stack.match(stackRule);
});
};
lists.stack = list;
}
catch(e){
list = [];
}
list.match = function(stack){
return this.some(function(stackRule){
return stack.match(stackRule);
});
};
lists.stack = list;
}
lists.stack = [];
preferences.on("stackList", function(){
lists.stack = [];
preferences.on("stackList", function(){
updateStackList();
});
updateStackList();
});
updateStackList();
exports.get = function getList(type){
"use strict";
return lists[type];
};
exports.appendTo = function appendToList(type, entry){
"use strict";
prefs[type + "List"] += (prefs[type + "List"]? ",": "") + entry;
prefService.set("extensions.CanvasBlocker@kkapsner.de." + type + "List", prefs[type + "List"]);
updateList(type);
};
exports.update = updateList;
scope.get = function getList(type){
"use strict";
return lists[type];
};
scope.appendTo = function appendToList(type, entry){
"use strict";
prefs[type + "List"] += (prefs[type + "List"]? ",": "") + entry;
var obj = {};
obj[type + "List"] = prefs[type + "List"];
browser.storage.local.set(obj);
updateList(type);
};
scope.update = updateList;
}());

View File

@ -4,6 +4,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
(function(){
"use strict";
console.log("start main script");
browser.runtime.onMessage.addListener(function(data){
console.log("got data", data);
});
browser.runtime.onConnect.addListener(function(port){
console.log("got port");
});
console.log("end main script");
return null;
require("./stylePreferencePane");

View File

@ -5,7 +5,16 @@
(function(){
"use strict";
let Cu = require("chrome").Cu;
var scope;
if ((typeof exports) !== "undefined"){
scope = exports;
}
else {
window.scope.modifiedAPI = {};
scope = window.scope.modifiedAPI;
}
// let Cu = require("chrome").Cu;
var randomSupply = null;
@ -87,12 +96,12 @@
return status.type.indexOf(type) !== -1;
}
exports.setRandomSupply = function(supply){
scope.setRandomSupply = function(supply){
randomSupply = supply;
};
var canvasContextType = new WeakMap();
// changed functions and their fakes
exports.changedFunctions = {
scope.changedFunctions = {
getContext: {
type: "context",
getStatus: function(obj, status){
@ -288,7 +297,7 @@
return function readPixels(x, y, width, height, format, type, pixels){
// not able to use the getFakeCanvas function because the context type is wrong...
notify("fakedReadout");
var xPixels = Cu.waiveXrays(pixels);
var xPixels = pixels//Cu.waiveXrays(pixels);
var ret = original.apply(this, window.Array.from(arguments));
var l = xPixels.length;
var rng = randomSupply.getRng(l, window);

View File

@ -5,6 +5,15 @@
(function(){
"use strict";
var scope;
if ((typeof exports) !== "undefined"){
scope = exports;
}
else {
window.scope.randomSupplies = {};
scope = window.scope.randomSupplies;
}
function getDomain(window){
if (!window.location.href || window.location.href === "about:blank"){
if (window !== window.parent){
@ -19,12 +28,14 @@
const getPersistentRnd = (function(){
var persistentRnd = Object.create(null);
const {process} = require("sdk/remote/child");
process.port.on("canvasBlocker-set-domain-rnd", function(process, {domain, rnd}){
persistentRnd[domain] = new Uint8Array(rnd);
});
process.port.on("canvasBlocker-clear-domain-rnd", function(){
persistentRnd = Object.create(null);
browser.runtime.onMessage.addListener(function(data){
if (data["canvasBlocker-set-domain-rnd"]){
var {domain, rnd} = data["canvasBlocker-set-domain-rnd"];
persistentRnd[domain] = new Uint8Array(rnd);
}
if (data["canvasBlocker-clear-domain-rnd"]){
persistentRnd = Object.create(null);
}
});
return function getPersistentRnd(window){
@ -33,12 +44,12 @@
// create the (sub-)domains random numbers if not existing
persistentRnd[domain] = new Uint8Array(128);
window.crypto.getRandomValues(persistentRnd[domain]);
process.port.emit("canvasBlocker-new-domain-rnd", {domain, rnd: Array.from(persistentRnd[domain])});
browser.runtime.sendMessage({"canvasBlocker-new-domain-rnd": {domain, rnd: Array.from(persistentRnd[domain])}});
}
return persistentRnd[domain];
}
}());
exports.persistent = {
scope.persistent = {
getRng: function(length, window){
var bitSet = getPersistentRnd(window);
@ -60,7 +71,7 @@
}
};
exports.nonPersistent = {
scope.nonPersistent = {
getRng: function(length, window){
// Initialize the random number batch creation
var randomI = 65536;

56
manifest.json Normal file
View File

@ -0,0 +1,56 @@
{
"name": "CanvasBlocker",
"title": "__MSG_addon_title__",
"id": "CanvasBlocker@kkapsner.de",
"keywords": "privacy, canvas, fingerprinting",
"description": "__MSG_addon_description__",
"homepage": "https://github.com/kkapsner/CanvasBlocker/",
"version": "0.4.0-Development",
"background": {
"scripts": ["lib/main.js"]
},
"content_scripts": [{
"matches": ["<all_urls>"],
"all_frames": true,
"run_at": "document_start",
"js": [
"lib/defaultSettings.js",
"lib/require.js",
"lib/modifiedAPI.js",
"lib/randomSupplies.js",
"lib/intercept.js",
"lib/callingStack.js",
"lib/askForPermission.js",
"lib/lists.js",
"lib/check.js",
"lib/frame.js"
]
}],
"options_ui": {
"browser_style": true,
"page": "options/options.html"
},
"author": "Korbinian Kapsner",
"license": "MPL 2.0",
"permissions": [
"<all_urls>",
"storage",
"tabs",
"activeTab",
"declarativeContentScript",
"events"
],
"applications": {
"gecko": {
"id": "CanvasBlocker@kkapsner.de",
"strict_min_version": "50.0"
}
},
"default_locale": "en",
"manifest_version": 2
}

View File

@ -1,183 +0,0 @@
{
"locales": {
"de": {
"title": "CanvasBlocker",
"description": "Ändert die JS-API zum Ändern von <canvas> um Canvas-Fingerprinting zu verhindern."
}
},
"name": "canvasblocker",
"title": "CanvasBlocker",
"id": "CanvasBlocker@kkapsner.de",
"keywords": "privacy, canvas, fingerprinting",
"description": "Changes the JS-API for modifying <canvas> to prevent Canvas-Fingerprinting.",
"homepage": "https://github.com/kkapsner/CanvasBlocker/",
"preferences": [
{
"name": "whiteList",
"title": "White list",
"type": "string",
"value": ""
},
{
"name": "blackList",
"title": "Black list",
"type": "string",
"value": ""
},
{
"name": "blockMode",
"title": "block mode",
"type": "menulist",
"value": "fakeReadout",
"options": [
{
"value": "blockReadout",
"label": "block readout API"
},
{
"value": "fakeReadout",
"label": "fake readout API"
},
{
"value": "fakeInput",
"label": "fake input API"
},
{
"value": "askReadout",
"label": "ask for readout API permission"
},
{
"value": "",
"label": ""
},
{
"value": "blockEverything",
"label": "block everything"
},
{
"value": "block",
"label": "allow only white list"
},
{
"value": "ask",
"label": "ask for permission"
},
{
"value": "allow",
"label": "block only black list"
},
{
"value": "allowEverything",
"label": "allow everything"
}
]
},
{
"name": "maxFakeSize",
"title": "Maximal fake size",
"type": "integer",
"value": 0
},
{
"name": "rng",
"title": "Random number generator",
"type": "menulist",
"value": "nonPersistent",
"options": [
{
"value": "nonPersistent",
"label": "non persistent"
},
{
"value": "persistent",
"label": "persistent"
}
]
},
{
"name": "persistentRndStorage",
"title": "Persistent storage",
"type": "string",
"value": ""
},
{
"name": "storePersistentRnd",
"title": "Store persistent data",
"type": "bool",
"value": false
},
{
"name": "clearPersistentRnd",
"title": "Clear persistent random storage",
"type": "control",
"label": "Clear"
},
{
"name": "askOnlyOnce",
"title": "Ask only once",
"type": "bool",
"value": true
},
{
"name": "showNotifications",
"title": "Show notifications",
"type": "bool",
"value": true
},
{
"name": "notificationDisplayTime",
"title": "notification display time",
"type": "integer",
"value": 30
},
{
"name": "ignoreList",
"title": "Ignore list",
"type": "string",
"value": ""
},
{
"name": "showCallingFile",
"title": "Display calling file",
"type": "bool",
"value": false
},
{
"name": "showCompleteCallingStack",
"title": "Display complete calling stack",
"type": "bool",
"value": false
},{
"name": "enableStackList",
"title": "Use file specific scoped white list",
"type": "bool",
"value": false
},
{
"name": "stackList",
"title": "File specific white list",
"type": "string",
"value": ""
},
{
"name": "showReleaseNotes",
"title": "Release notes",
"type": "control",
"label": "Show"
}
],
"main": "lib/main.js",
"author": "Korbinian Kapsner",
"license": "MPL 2.0",
"version": "0.4.0-Development",
"engines": {
"firefox": ">=50.0",
"fennec": ">=50.0"
},
"permissions": {
"private-browsing": true,
"multiprocess": true
},
"hasEmbeddedWebExtension": true
}

View File

@ -1,6 +1,9 @@
Version 0.4.0:
todos:
- import settings in content script (have to wait for the new API to register content scripts)
- check if webGL is still working
changes:
-
- switched to webExtension
new features:
-