mirror of
https://github.com/kkapsner/CanvasBlocker
synced 2024-12-22 12:50:36 +01:00
Added askOnlyOnce and blockReadout and major code changes
This commit is contained in:
parent
4c2596f880
commit
b2f6aee8f9
Binary file not shown.
197
data/inject.js
197
data/inject.js
@ -1,8 +1,78 @@
|
||||
/* global self, window, console, unsafeWindow */
|
||||
(function(){
|
||||
"use strict";
|
||||
|
||||
var getContext = unsafeWindow.HTMLCanvasElement.prototype.getContext;
|
||||
var originalGetContext = unsafeWindow.HTMLCanvasElement.prototype.getContext;
|
||||
var originalToDataURL = unsafeWindow.HTMLCanvasElement.prototype.toDataURL;
|
||||
var originalGetImageData = unsafeWindow.CanvasRenderingContext2D.prototype.getImageData;
|
||||
var askFunctionName = Math.random().toString(16);
|
||||
|
||||
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)){
|
||||
@ -14,24 +84,14 @@
|
||||
|
||||
function block(force){
|
||||
if (force || !checkPDF("block")){
|
||||
// consoe.log("block");
|
||||
delete unsafeWindow.HTMLCanvasElement.prototype[askFunctionName];
|
||||
unsafeWindow.HTMLCanvasElement.prototype.getContext = null;
|
||||
setAPIFunctions(null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
function askVisible(force){
|
||||
function askVisible(force, askOnlyOnce){
|
||||
if (force || !checkPDF("askVisible")){
|
||||
|
||||
Object.defineProperty(
|
||||
unsafeWindow.HTMLCanvasElement.prototype,
|
||||
askFunctionName,
|
||||
{
|
||||
value: getContext,
|
||||
enumerable: false
|
||||
}
|
||||
);
|
||||
unsafeWindow.HTMLCanvasElement.prototype.getContext = new unsafeWindow.Function(
|
||||
setAPIFunctions(
|
||||
askOnlyOnce?
|
||||
function(){
|
||||
if (this.parentNode){
|
||||
var oldBorder = this.style.border;
|
||||
@ -41,11 +101,37 @@
|
||||
// catch (e){
|
||||
// console.log(e.stack.split(/\s*(?:-?>|@)\s*/));
|
||||
// }
|
||||
var allow = confirm(confirmText);
|
||||
var allow = this[askFunctionName].confirm.call(window, confirmText);
|
||||
this.style.border = oldBorder;
|
||||
if (allow){
|
||||
this.getContext = this["askFunctionName"];
|
||||
return this["askFunctionName"].apply(this, arguments);
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
@ -55,25 +141,16 @@
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}.toString()
|
||||
.replace(/^function\s*\(\)\s*\{|\}\s*$/g, "")
|
||||
.replace(/askFunctionName/g, askFunctionName)
|
||||
.replace(/askForPermission/g, _("askForPermission"))
|
||||
},
|
||||
true,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
function askInvisible(force){
|
||||
function askInvisible(force, askOnlyOnce){
|
||||
if (force || !checkPDF("askInvisible")){
|
||||
|
||||
Object.defineProperty(
|
||||
unsafeWindow.HTMLCanvasElement.prototype,
|
||||
askFunctionName,
|
||||
{
|
||||
value: getContext,
|
||||
enumerable: false
|
||||
}
|
||||
);
|
||||
unsafeWindow.HTMLCanvasElement.prototype.getContext = new unsafeWindow.Function(
|
||||
setAPIFunctions(
|
||||
askOnlyOnce?
|
||||
function(){
|
||||
var oldBorder = this.style.border;
|
||||
this.style.border = "2px dashed red";
|
||||
@ -81,32 +158,63 @@
|
||||
this.parentNode?
|
||||
"askForPermission":
|
||||
"askForInvisiblePermission";
|
||||
var allow = confirm(confirmText);
|
||||
var allow = this[askFunctionName].confirm.call(window, confirmText);
|
||||
this.style.border = oldBorder;
|
||||
if (allow){
|
||||
this.getContext = this["askFunctionName"];
|
||||
return this["askFunctionName"].apply(this, arguments);
|
||||
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;
|
||||
}
|
||||
}.toString()
|
||||
.replace(/^function\s*\(\)\s*\{|\}\s*$/g, "")
|
||||
.replace(/askFunctionName/g, askFunctionName)
|
||||
.replace(/askForPermission/g, _("askForPermission"))
|
||||
.replace(/askForInvisiblePermission/g, _("askForInvisiblePermission"))
|
||||
},
|
||||
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;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
function unblock(){
|
||||
// console.log("unblock");
|
||||
unsafeWindow.HTMLCanvasElement.prototype.getContext = getContext;
|
||||
setAPIFunctions(true, true, true);
|
||||
}
|
||||
|
||||
var _ = function(name){
|
||||
return _[name] || name;
|
||||
}
|
||||
};
|
||||
self.port.on("setTranslation", function(name, translation){
|
||||
_[name] = translation;
|
||||
});
|
||||
@ -115,6 +223,7 @@
|
||||
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
|
||||
}());
|
||||
|
41
lib/main.js
41
lib/main.js
@ -85,54 +85,67 @@
|
||||
// }
|
||||
function checkWorker(worker){
|
||||
var url = new URL(worker.url);
|
||||
var mode = "block";
|
||||
switch (prefs.blockMode){
|
||||
case "blockEverything":
|
||||
worker.port.emit("block");
|
||||
mode = "block";
|
||||
break;
|
||||
case "allowOnlyWhiteList":
|
||||
if (whiteList.match(url)){
|
||||
worker.port.emit("unblock");
|
||||
mode = "unblock";
|
||||
}
|
||||
else {
|
||||
worker.port.emit("block");
|
||||
mode = "block";
|
||||
}
|
||||
break;
|
||||
case "askVisible":
|
||||
if (whiteList.match(url)){
|
||||
worker.port.emit("unblock");
|
||||
mode = "unblock";
|
||||
}
|
||||
else if (blackList.match(url)){
|
||||
worker.port.emit("block");
|
||||
mode = "block";
|
||||
}
|
||||
else {
|
||||
worker.port.emit("askVisible");
|
||||
mode = "askVisible";
|
||||
}
|
||||
break;
|
||||
case "askInvisible":
|
||||
if (whiteList.match(url)){
|
||||
worker.port.emit("unblock");
|
||||
mode = "unblock";
|
||||
}
|
||||
else if (blackList.match(url)){
|
||||
worker.port.emit("block");
|
||||
mode = "block";
|
||||
}
|
||||
else {
|
||||
worker.port.emit("askInvisible");
|
||||
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)){
|
||||
worker.port.emit("block");
|
||||
mode = "block";
|
||||
}
|
||||
else {
|
||||
worker.port.emit("unblock");
|
||||
mode = "unblock";
|
||||
}
|
||||
break;
|
||||
case "allowEverything":
|
||||
worker.port.emit("unblock");
|
||||
mode = "unblock";
|
||||
break;
|
||||
default:
|
||||
console.log("Unknown blocking mode.");
|
||||
console.log("Unknown blocking mode. Default to block everything.");
|
||||
}
|
||||
worker.port.emit(mode, false, prefs.askOnlyOnce);
|
||||
}
|
||||
|
||||
|
||||
@ -151,7 +164,7 @@
|
||||
this.emit("unblock");
|
||||
}
|
||||
else {
|
||||
this.emit(blocking, true);
|
||||
this.emit(blocking, true, prefs.askOnlyOnce);
|
||||
}
|
||||
});
|
||||
worker.port.emit("setTranslation", "askForPermission", _("askForPermission"));
|
||||
|
@ -11,9 +11,13 @@ 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.block readout API= Auslese-API blockieren
|
||||
blockMode_options.block only black list= nur Einträge der Blacklist blockieren
|
||||
blockMode_options.allow everything= alles erlauben
|
||||
|
||||
askOnlyOnce_title= Nur einmal nachfragen
|
||||
askOnlyOnce_description= Wenn eine Seite öfters versucht, die <canvas>-API abzurufen, erscheint jedes mal eine Nachfrage. Mit diesem Schalter wird pro Seitenbesuch nur einmal nachgefragt. Bei manchen Seiten kann es trotzdem zu mehrmaligem Nachfragen kommen.
|
||||
|
||||
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.
|
||||
|
||||
|
@ -11,9 +11,13 @@ 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.block readout API= block readout API
|
||||
blockMode_options.block only black list= block only black list
|
||||
blockMode_options.allow everything= allow everything
|
||||
|
||||
askOnlyOnce_title= Ask only once
|
||||
askOnlyOnce_description= If a page tries to access the <canvas>-API several times a confirm message will appear every time. This switch tries to make only one confirmation. Never the less on some pages there will be more.
|
||||
|
||||
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.
|
||||
|
||||
|
12
package.json
12
package.json
@ -38,6 +38,10 @@
|
||||
"value": "askInvisible",
|
||||
"label": "ask for permision for invisible <canvas>"
|
||||
},
|
||||
{
|
||||
"value": "blockReadout",
|
||||
"label": "block readout API"
|
||||
},
|
||||
{
|
||||
"value": "blockOnlyBlackList",
|
||||
"label": "block only black list"
|
||||
@ -48,6 +52,12 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "askOnlyOnce",
|
||||
"title": "Ask only once",
|
||||
"type": "bool",
|
||||
"value": false
|
||||
},
|
||||
{
|
||||
"name": "allowPDFCanvas",
|
||||
"title": "Allow canvas in PDFs",
|
||||
@ -57,6 +67,6 @@
|
||||
],
|
||||
"author": "Korbinian Kapsner",
|
||||
"license": "MPL 2.0",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.4",
|
||||
"permissions": {"private-browsing": true}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user