mirror of
https://github.com/kkapsner/CanvasBlocker
synced 2024-07-05 00:29:17 +02:00
230 lines
6.4 KiB
JavaScript
230 lines
6.4 KiB
JavaScript
/* global self, window, console, unsafeWindow */
|
|
(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);
|
|
|
|
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);
|
|
}
|
|
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;
|
|
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;
|
|
}
|
|
);
|
|
}
|
|
}
|
|
function unblock(){
|
|
setAPIFunctions(true, true, true);
|
|
}
|
|
|
|
var _ = function(name){
|
|
return _[name] || name;
|
|
};
|
|
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
|
|
}());
|