mirror of
https://github.com/kkapsner/CanvasBlocker
synced 2024-12-22 12:50:36 +01:00
Changed to getter approach
- no "visible vs. invisible" possible
This commit is contained in:
parent
b2f6aee8f9
commit
147a2893c4
Binary file not shown.
329
data/inject.js
329
data/inject.js
@ -2,215 +2,94 @@
|
||||
(function(){
|
||||
"use strict";
|
||||
|
||||
var originalGetContext = unsafeWindow.HTMLCanvasElement.prototype.getContext;
|
||||
var originalToDataURL = unsafeWindow.HTMLCanvasElement.prototype.toDataURL;
|
||||
var originalGetImageData = unsafeWindow.CanvasRenderingContext2D.prototype.getImageData;
|
||||
var askFunctionName = Math.random().toString(16);
|
||||
var blockMode = {
|
||||
getContext: {
|
||||
status: "block",
|
||||
askStatus: {
|
||||
askOnce: false,
|
||||
alreadyAsked: false,
|
||||
answer: null
|
||||
}
|
||||
},
|
||||
readAPI: {
|
||||
status: "allow"
|
||||
}
|
||||
};
|
||||
|
||||
function transformFunctionToUnsafeWindow(func, name){
|
||||
var funcString = func.toString();
|
||||
var parameter = funcString.match(/^function\s*\(([^\)]*)\)\s*\{/)[1];
|
||||
funcString = funcString
|
||||
.replace(/^function\s*\(([^\)]*)\)\s*\{|\}\s*$/g, "")
|
||||
.replace(/(^|\n|\r)\t{3}/g, "$1")
|
||||
.replace(/askFunctionName/g, JSON.stringify(askFunctionName))
|
||||
.replace(/askForPermission/g, _("askForPermission"))
|
||||
.replace(/askForInvisiblePermission/g, _("askForInvisiblePermission"));
|
||||
var unsafeFunction = new unsafeWindow.Function(parameter, funcString);
|
||||
unsafeFunction.toString =
|
||||
unsafeFunction.toLocaleString =
|
||||
unsafeFunction.toSource = new unsafeWindow.Function(
|
||||
"return \"function " + name + "() {\\n [native code]\\n}\";"
|
||||
);
|
||||
return unsafeFunction;
|
||||
}
|
||||
function setAPIFunctions(getContext, toDataURL, getImageData){
|
||||
delete unsafeWindow.HTMLCanvasElement.prototype[askFunctionName];
|
||||
if (getContext){
|
||||
if (getContext === true){
|
||||
getContext = originalGetContext;
|
||||
}
|
||||
else {
|
||||
var secretObject = new unsafeWindow.Object();
|
||||
Object.defineProperties(
|
||||
secretObject,
|
||||
{
|
||||
getContext: {value: originalGetContext},
|
||||
confirm: {value: unsafeWindow.confirm}
|
||||
}
|
||||
);
|
||||
Object.defineProperty(
|
||||
unsafeWindow.HTMLCanvasElement.prototype,
|
||||
askFunctionName,
|
||||
{
|
||||
value: secretObject,
|
||||
configurable: true,
|
||||
enumerable: false
|
||||
}
|
||||
);
|
||||
getContext = transformFunctionToUnsafeWindow(getContext, "getContext");
|
||||
}
|
||||
}
|
||||
unsafeWindow.HTMLCanvasElement.prototype.getContext = getContext;
|
||||
|
||||
if (toDataURL){
|
||||
if (toDataURL === true){
|
||||
toDataURL = originalToDataURL;
|
||||
}
|
||||
else {
|
||||
toDataURL = transformFunctionToUnsafeWindow(toDataURL, "toDataURL");
|
||||
}
|
||||
}
|
||||
unsafeWindow.HTMLCanvasElement.prototype.toDataURL = toDataURL;
|
||||
|
||||
if (getImageData){
|
||||
if (getImageData === true){
|
||||
getImageData = originalGetImageData;
|
||||
}
|
||||
else {
|
||||
getImageData = transformFunctionToUnsafeWindow(getImageData, "getImageData");
|
||||
}
|
||||
}
|
||||
unsafeWindow.CanvasRenderingContext2D.prototype.getImageData = getImageData;
|
||||
}
|
||||
|
||||
function checkPDF(blocking){
|
||||
if (document.contentType.match(/\/pdf$/i)){
|
||||
self.port.emit("isPDF", blocking);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function block(force){
|
||||
if (force || !checkPDF("block")){
|
||||
setAPIFunctions(null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
function askVisible(force, askOnlyOnce){
|
||||
if (force || !checkPDF("askVisible")){
|
||||
setAPIFunctions(
|
||||
askOnlyOnce?
|
||||
function(){
|
||||
if (this.parentNode){
|
||||
var oldBorder = this.style.border;
|
||||
this.style.border = "2px dashed red";
|
||||
var confirmText = "askForPermission";
|
||||
// try {throw new Error();}
|
||||
// catch (e){
|
||||
// console.log(e.stack.split(/\s*(?:-?>|@)\s*/));
|
||||
// }
|
||||
var allow = this[askFunctionName].confirm.call(window, confirmText);
|
||||
this.style.border = oldBorder;
|
||||
if (allow){
|
||||
HTMLCanvasElement.prototype.getContext = this[askFunctionName].getContext;
|
||||
delete HTMLCanvasElement.prototype[askFunctionName];
|
||||
return this.getContext.apply(this, arguments);
|
||||
var undef;
|
||||
var originalGetContext = unsafeWindow.HTMLCanvasElement.prototype.getContext;
|
||||
Object.defineProperty(
|
||||
unsafeWindow.HTMLCanvasElement.prototype,
|
||||
"getContext",
|
||||
{
|
||||
enumerable: true,
|
||||
configureable: false,
|
||||
get: exportFunction(function(){
|
||||
switch (blockMode.getContext.status){
|
||||
case "allow":
|
||||
// console.log("allow");
|
||||
return originalGetContext;
|
||||
case "ask":
|
||||
// console.log("ask");
|
||||
var status = blockMode.getContext.askStatus;
|
||||
var allow;
|
||||
if (status.askOnce && status.alreadyAsked){
|
||||
// console.log("already asked");
|
||||
allow = status.answer;
|
||||
}
|
||||
else {
|
||||
HTMLCanvasElement.prototype.getContext = null;
|
||||
delete HTMLCanvasElement.prototype[askFunctionName];
|
||||
return null;
|
||||
// console.log("asking");
|
||||
allow = window.confirm(_("askForPermission"));
|
||||
status.alreadyAsked = true;
|
||||
status.answer = allow;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}:
|
||||
function(){
|
||||
if (this.parentNode){
|
||||
var oldBorder = this.style.border;
|
||||
this.style.border = "2px dashed red";
|
||||
var confirmText = "askForPermission";
|
||||
// try {throw new Error();}
|
||||
// catch (e){
|
||||
// console.log(e.stack.split(/\s*(?:-?>|@)\s*/));
|
||||
// }
|
||||
var allow = this[askFunctionName].confirm.call(window, confirmText);
|
||||
this.style.border = oldBorder;
|
||||
if (allow){
|
||||
this.getContext = this[askFunctionName].getContext;
|
||||
return this.getContext.apply(this, arguments);
|
||||
}
|
||||
else {
|
||||
this.getContext = null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
true,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
function askInvisible(force, askOnlyOnce){
|
||||
if (force || !checkPDF("askInvisible")){
|
||||
setAPIFunctions(
|
||||
askOnlyOnce?
|
||||
function(){
|
||||
var oldBorder = this.style.border;
|
||||
this.style.border = "2px dashed red";
|
||||
var confirmText =
|
||||
this.parentNode?
|
||||
"askForPermission":
|
||||
"askForInvisiblePermission";
|
||||
var allow = this[askFunctionName].confirm.call(window, confirmText);
|
||||
this.style.border = oldBorder;
|
||||
if (allow){
|
||||
HTMLCanvasElement.prototype.getContext = this[askFunctionName].getContext;
|
||||
delete HTMLCanvasElement.prototype[askFunctionName];
|
||||
return this.getContext.apply(this, arguments);
|
||||
}
|
||||
else {
|
||||
HTMLCanvasElement.prototype.getContext = null;
|
||||
delete HTMLCanvasElement.prototype[askFunctionName];
|
||||
return null;
|
||||
}
|
||||
}:
|
||||
function(){
|
||||
var oldBorder = this.style.border;
|
||||
this.style.border = "2px dashed red";
|
||||
var confirmText =
|
||||
this.parentNode?
|
||||
"askForPermission":
|
||||
"askForInvisiblePermission";
|
||||
var allow = this[askFunctionName].confirm.call(window, confirmText);
|
||||
this.style.border = oldBorder;
|
||||
if (allow){
|
||||
this.getContext = this[askFunctionName].getContext;
|
||||
return this.getContext.apply(this, arguments);
|
||||
}
|
||||
else {
|
||||
this.getContext = null;
|
||||
return null;
|
||||
}
|
||||
},
|
||||
true,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
function blockReadout(force){
|
||||
if (force || !checkPDF("blockReadout")){
|
||||
setAPIFunctions(
|
||||
true,
|
||||
function(){
|
||||
return "data:image/png;base64";
|
||||
},
|
||||
function(sx, sy, sw, sh){
|
||||
var imageData = this.createImageData(sw, sh);
|
||||
return imageData;
|
||||
return allow? originalGetContext: undef;
|
||||
case "block":
|
||||
default:
|
||||
// console.log("block");
|
||||
return undef;
|
||||
}
|
||||
);
|
||||
}, unsafeWindow)
|
||||
}
|
||||
}
|
||||
function unblock(){
|
||||
setAPIFunctions(true, true, true);
|
||||
}
|
||||
);
|
||||
|
||||
var originalToDataURL = unsafeWindow.HTMLCanvasElement.prototype.toDataURL;
|
||||
Object.defineProperty(
|
||||
unsafeWindow.HTMLCanvasElement.prototype,
|
||||
"toDataURL",
|
||||
{
|
||||
enumerable: true,
|
||||
configureable: false,
|
||||
get: exportFunction(function(){
|
||||
switch (blockMode.readAPI.status){
|
||||
case "allow":
|
||||
return originalToDataURL;
|
||||
case "block":
|
||||
default:
|
||||
return undef;
|
||||
}
|
||||
}, unsafeWindow)
|
||||
}
|
||||
);
|
||||
|
||||
var originalGetImageData = unsafeWindow.CanvasRenderingContext2D.prototype.getImageData;
|
||||
Object.defineProperty(
|
||||
unsafeWindow.CanvasRenderingContext2D.prototype,
|
||||
"getImageData",
|
||||
{
|
||||
enumerable: true,
|
||||
configureable: false,
|
||||
get: exportFunction(function(){
|
||||
switch (blockMode.readAPI.status){
|
||||
case "allow":
|
||||
return originalGetImageData;
|
||||
case "block":
|
||||
default:
|
||||
return undef;
|
||||
}
|
||||
}, unsafeWindow)
|
||||
}
|
||||
);
|
||||
|
||||
var _ = function(name){
|
||||
return _[name] || name;
|
||||
@ -218,12 +97,40 @@
|
||||
self.port.on("setTranslation", function(name, translation){
|
||||
_[name] = translation;
|
||||
});
|
||||
|
||||
block();
|
||||
self.port.on("block", block);
|
||||
self.port.on("askVisible", askVisible);
|
||||
self.port.on("askInvisible", askInvisible);
|
||||
self.port.on("blockReadout", blockReadout);
|
||||
self.port.on("unblock", unblock);
|
||||
//self.port.on("detach", unblock); // produces memory leak due to the reference to unsafeWindow
|
||||
|
||||
function checkPDF(blocking){
|
||||
if (document.contentType.match(/\/pdf$/i)){
|
||||
self.port.emit("isPDF", blocking);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
self.port.on("block", function(force){
|
||||
if (force || !checkPDF("block")){
|
||||
blockMode.getContext.status = "block";
|
||||
blockMode.readAPI.status = "allow";
|
||||
}
|
||||
});
|
||||
self.port.on("ask", function(force, askOnce){
|
||||
if (force || !checkPDF("askVisible")){
|
||||
blockMode.getContext.status = "ask";
|
||||
blockMode.getContext.askStatus.askOnce = askOnce;
|
||||
blockMode.readAPI.status = "allow";
|
||||
}
|
||||
});
|
||||
self.port.on("blockReadout", function(force){
|
||||
if (force || !checkPDF("blockReadout")){
|
||||
blockMode.getContext.status = "allow";
|
||||
blockMode.readAPI.status = "block";
|
||||
}
|
||||
});
|
||||
self.port.on("unblock", function(){
|
||||
blockMode.getContext.status = "allow";
|
||||
blockMode.readAPI.status = "allow";
|
||||
});
|
||||
self.port.on("detach", function(force){
|
||||
blockMode.getContext.status = "allow";
|
||||
blockMode.readAPI.status = "allow";
|
||||
});
|
||||
}());
|
||||
|
152
lib/main.js
152
lib/main.js
@ -42,12 +42,18 @@
|
||||
|
||||
var self = require("sdk/self");
|
||||
var pageMod = require("sdk/page-mod");
|
||||
var array = require("sdk/util/array");
|
||||
var preferences = require("sdk/simple-prefs");
|
||||
var prefs = preferences.prefs;
|
||||
var {URL} = require("sdk/url");
|
||||
var _ = require("sdk/l10n").get;
|
||||
|
||||
// preferences
|
||||
Object.keys(prefs).forEach(function(pref){
|
||||
preferences.on(pref, function(){
|
||||
workers.forEach(checkWorker);
|
||||
});
|
||||
});
|
||||
var whiteList;
|
||||
function updateWhiteList(){
|
||||
whiteList = getDomainRegExpList(prefs.whiteList);
|
||||
@ -55,7 +61,6 @@
|
||||
updateWhiteList();
|
||||
preferences.on("whiteList", function(){
|
||||
updateWhiteList();
|
||||
// workers.forEach(checkWorker);
|
||||
});
|
||||
|
||||
var blackList;
|
||||
@ -65,100 +70,84 @@
|
||||
updateBlackList();
|
||||
preferences.on("blackList", function(){
|
||||
updateBlackList();
|
||||
// workers.forEach(checkWorker);
|
||||
});
|
||||
|
||||
|
||||
// preferences.on("blockMode", function(){
|
||||
// workers.forEach(checkWorker);
|
||||
// });
|
||||
// preferences.on("allowPDFCanvas", function(){
|
||||
// workers.forEach(checkWorker);
|
||||
// });
|
||||
|
||||
// var workers = [];
|
||||
// function detachWorker(worker, workerArray) {
|
||||
// var index = workerArray.indexOf(worker);
|
||||
// if (index !== -1){
|
||||
// workerArray.splice(index, 1);
|
||||
// }
|
||||
// }
|
||||
function checkWorker(worker){
|
||||
var url = new URL(worker.url);
|
||||
var mode = "block";
|
||||
switch (prefs.blockMode){
|
||||
case "blockEverything":
|
||||
mode = "block";
|
||||
break;
|
||||
case "allowOnlyWhiteList":
|
||||
if (whiteList.match(url)){
|
||||
mode = "unblock";
|
||||
}
|
||||
else {
|
||||
try {
|
||||
var url = new URL(worker.url);
|
||||
var mode = "block";
|
||||
switch (prefs.blockMode){
|
||||
case "blockEverything":
|
||||
mode = "block";
|
||||
}
|
||||
break;
|
||||
case "askVisible":
|
||||
if (whiteList.match(url)){
|
||||
break;
|
||||
case "allowOnlyWhiteList":
|
||||
if (whiteList.match(url)){
|
||||
mode = "unblock";
|
||||
}
|
||||
else {
|
||||
mode = "block";
|
||||
}
|
||||
break;
|
||||
case "ask":
|
||||
if (whiteList.match(url)){
|
||||
mode = "unblock";
|
||||
}
|
||||
else if (blackList.match(url)){
|
||||
mode = "block";
|
||||
}
|
||||
else {
|
||||
mode = "ask";
|
||||
}
|
||||
break;
|
||||
case "blockReadout":
|
||||
if (whiteList.match(url)){
|
||||
mode = "unblock";
|
||||
}
|
||||
else if (blackList.match(url)){
|
||||
mode = "block";
|
||||
}
|
||||
else {
|
||||
mode = "blockReadout";
|
||||
}
|
||||
break;
|
||||
case "blockOnlyBlackList":
|
||||
if (blackList.match(url)){
|
||||
mode = "block";
|
||||
}
|
||||
else {
|
||||
mode = "unblock";
|
||||
}
|
||||
break;
|
||||
case "allowEverything":
|
||||
mode = "unblock";
|
||||
}
|
||||
else if (blackList.match(url)){
|
||||
mode = "block";
|
||||
}
|
||||
else {
|
||||
mode = "askVisible";
|
||||
}
|
||||
break;
|
||||
case "askInvisible":
|
||||
if (whiteList.match(url)){
|
||||
mode = "unblock";
|
||||
}
|
||||
else if (blackList.match(url)){
|
||||
mode = "block";
|
||||
}
|
||||
else {
|
||||
mode = "askInvisible";
|
||||
}
|
||||
break;
|
||||
case "blockReadout":
|
||||
if (whiteList.match(url)){
|
||||
mode = "unblock";
|
||||
}
|
||||
else if (blackList.match(url)){
|
||||
mode = "block";
|
||||
}
|
||||
else {
|
||||
mode = "blockReadout";
|
||||
}
|
||||
break;
|
||||
case "blockOnlyBlackList":
|
||||
if (blackList.match(url)){
|
||||
mode = "block";
|
||||
}
|
||||
else {
|
||||
mode = "unblock";
|
||||
}
|
||||
break;
|
||||
case "allowEverything":
|
||||
mode = "unblock";
|
||||
break;
|
||||
default:
|
||||
console.log("Unknown blocking mode. Default to block everything.");
|
||||
break;
|
||||
default:
|
||||
console.log("Unknown blocking mode. Default to block everything.");
|
||||
}
|
||||
worker.port.emit(mode, false, prefs.askOnlyOnce);
|
||||
}
|
||||
catch (e){
|
||||
console.log("Error updating " + worker.url + ": " + e.message);
|
||||
}
|
||||
worker.port.emit(mode, false, prefs.askOnlyOnce);
|
||||
}
|
||||
|
||||
|
||||
var workers = [];
|
||||
pageMod.PageMod({
|
||||
include: "*",
|
||||
contentScriptWhen: "start",
|
||||
contentScriptFile: self.data.url("inject.js"),
|
||||
onAttach: function(worker){
|
||||
|
||||
// workers.push(worker);
|
||||
// worker.on("detach", function(){
|
||||
// detachWorker(this, workers);
|
||||
// });
|
||||
array.add(workers, worker);
|
||||
worker.on("pageshow", function(){
|
||||
array.add(workers, this);
|
||||
});
|
||||
worker.on("pagehide", function(){
|
||||
array.remove(workers, this);
|
||||
});
|
||||
worker.on("detach", function(){
|
||||
array.remove(workers, this);
|
||||
});
|
||||
worker.port.on("isPDF", function(blocking){
|
||||
if (prefs.allowPDFCanvas){
|
||||
this.emit("unblock");
|
||||
@ -168,7 +157,6 @@
|
||||
}
|
||||
});
|
||||
worker.port.emit("setTranslation", "askForPermission", _("askForPermission"));
|
||||
worker.port.emit("setTranslation", "askForInvisiblePermission", _("askForInvisiblePermission"));
|
||||
checkWorker(worker);
|
||||
},
|
||||
});
|
||||
|
@ -9,8 +9,7 @@ blockMode_description=
|
||||
|
||||
blockMode_options.block everything= alles blockieren
|
||||
blockMode_options.allow only white list= nur Einträge der Whitelist erlauben
|
||||
blockMode_options.ask for permission for visible <canvas>= bei sichtbaren <canvas> um Erlaubnis fragen
|
||||
blockMode_options.ask for permision for invisible <canvas>= bei unsichtbaren <canvas> um Erlaubnis fragen
|
||||
blockMode_options.ask for permission= um Erlaubnis fragen
|
||||
blockMode_options.block readout API= Auslese-API blockieren
|
||||
blockMode_options.block only black list= nur Einträge der Blacklist blockieren
|
||||
blockMode_options.allow everything= alles erlauben
|
||||
@ -21,5 +20,4 @@ askOnlyOnce_description= Wenn eine Seite öfters versucht, die <canvas>-API abzu
|
||||
allowPDFCanvas_title= <canvas> in PDFs erlauben
|
||||
allowPDFCanvas_description= Die native pdf.js verwendet <canvas> um den Inhalt von PDFs anzuzeigen. Wenn dies nicht markiert ist, werden viele Nachfragedialoge erscheinen oder die PDF Ansicht nicht funktionieren.
|
||||
|
||||
askForPermission= Wollen Sie das rot umrandete <canvas> erlauben?
|
||||
askForInvisiblePermission= Wollen Sie ein verstecktes <canvas> erlauben?
|
||||
askForPermission= Wollen Sie <canvas> erlauben?
|
@ -9,8 +9,7 @@ blockMode_description=
|
||||
|
||||
blockMode_options.block everything= block everything
|
||||
blockMode_options.allow only white list= allow only white list
|
||||
blockMode_options.ask for permission for visible <canvas>= ask for permission for visible <canvas>
|
||||
blockMode_options.ask for permision for invisible <canvas>= ask for permision for invisible <canvas>
|
||||
blockMode_options.ask for permission= ask for permission
|
||||
blockMode_options.block readout API= block readout API
|
||||
blockMode_options.block only black list= block only black list
|
||||
blockMode_options.allow everything= allow everything
|
||||
@ -21,5 +20,4 @@ askOnlyOnce_description= If a page tries to access the <canvas>-API several time
|
||||
allowPDFCanvas_title= Allow canvas in PDFs
|
||||
allowPDFCanvas_description= The native pdf.js uses <canvas> to display the PDF content. If this is unchecked there will lots of annoying ask dialogs or the PDF display will not work.
|
||||
|
||||
askForPermission= Do you want to allow the red bordered <canvas>?
|
||||
askForInvisiblePermission= Do you want to allow an invisibe <canvas>?
|
||||
askForPermission= Do you want to allow <canvas>?
|
12
package.json
12
package.json
@ -20,7 +20,7 @@
|
||||
"name": "blockMode",
|
||||
"title": "block mode",
|
||||
"type": "menulist",
|
||||
"value": "askVisible",
|
||||
"value": "ask",
|
||||
"options": [
|
||||
{
|
||||
"value": "blockEverything",
|
||||
@ -31,12 +31,8 @@
|
||||
"label": "allow only white list"
|
||||
},
|
||||
{
|
||||
"value": "askVisible",
|
||||
"label": "ask for permission for visible <canvas>"
|
||||
},
|
||||
{
|
||||
"value": "askInvisible",
|
||||
"label": "ask for permision for invisible <canvas>"
|
||||
"value": "ask",
|
||||
"label": "ask for permission"
|
||||
},
|
||||
{
|
||||
"value": "blockReadout",
|
||||
@ -56,7 +52,7 @@
|
||||
"name": "askOnlyOnce",
|
||||
"title": "Ask only once",
|
||||
"type": "bool",
|
||||
"value": false
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"name": "allowPDFCanvas",
|
||||
|
Loading…
x
Reference in New Issue
Block a user