diff --git a/canvasblocker.xpi b/canvasblocker.xpi index fa0d17c..837eb5f 100644 Binary files a/canvasblocker.xpi and b/canvasblocker.xpi differ diff --git a/data/inject.js b/data/inject.js index 64740cc..297ebb7 100644 --- a/data/inject.js +++ b/data/inject.js @@ -1,4 +1,4 @@ -/* global self, window, console, unsafeWindow */ +/* global self, window, console, unsafeWindow, exportFunction */ (function(){ "use strict"; @@ -12,7 +12,12 @@ } }, readAPI: { - status: "allow" + status: "allow", + askStatus: { + askOnce: false, + alreadyAsked: false, + answer: null + } } }; @@ -62,108 +67,86 @@ return bytes; }()); - 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 exportFunction( - function(){ - var type = arguments[0] || "image/png"; - return "data:" + type + ";base64," + btoa(randomImage); - }, - unsafeWindow - ); + // Readout API blocking + var fakeFunctions = { + toDataURL: { + object: unsafeWindow.HTMLCanvasElement, + func: function(){ + var type = arguments[0] || "image/png"; + return "data:" + type + ";base64," + btoa(randomImage); + } + }, + toBlob: { + object: unsafeWindow.HTMLCanvasElement, + func: function(callback){ + var type = arguments[0] || "image/png"; + var blob = new window.Blob(randomImage, {type: type}); + callback(blob); + }, + exportOptions: {allowCallbacks: true} + }, + mozGetAsFile: { + object: unsafeWindow.HTMLCanvasElement, + func: undef + }, + getImageData: { + object: unsafeWindow.CanvasRenderingContext2D, + func: function(sx, sy, sw, sh){ + var imageData = new window.ImageData(sw, sh); + var l = sw * sh * 4; + for (var i = 0; i < l; i += 1){ + imageData.data[i] = Math.floor( + Math.random() * 256 + ); } - }, unsafeWindow) + return imageData; + } } - ); + }; - var originalToBlob = unsafeWindow.HTMLCanvasElement.prototype.toBlob; - Object.defineProperty( - unsafeWindow.HTMLCanvasElement.prototype, - "toBlob", - { - enumerable: true, - configureable: false, - get: exportFunction(function(){ - switch (blockMode.readAPI.status){ - case "allow": - return originalToBlob; - case "block": - default: - return exportFunction( - function(callback){ - var type = arguments[0] || "image/png"; - var blob = new window.Blob(randomImage, {type: type}); - callback(blob); - }, - unsafeWindow, - {allowCallbacks: true} - ); - } - }, unsafeWindow) - } - ); + Object.keys(fakeFunctions).forEach(function(name){ + var fakeFunction = fakeFunctions[name]; + var original = fakeFunction.object.prototype[name]; + Object.defineProperty( + fakeFunction.object.prototype, + name, + { + enumerable: true, + configureable: false, + get: exportFunction(function(){ + var status = blockMode.readAPI.status; + if (status === "ask"){ + var askStatus = blockMode.readAPI.askStatus; + var allow; + if (askStatus.askOnce && askStatus.alreadyAsked){ + // console.log("already asked"); + allow = askStatus.answer; + } + else { + // console.log("asking"); + allow = window.confirm(_("askForReadoutPermission")); + askStatus.alreadyAsked = true; + askStatus.answer = allow; + } + status = allow? "allow": "block"; + } + switch (status){ + case "allow": + return original; + case "block": + default: + return exportFunction( + fakeFunction.func, + unsafeWindow, + fakeFunction.exportOptions + ); + } + }, unsafeWindow) + } + ); + }); - var originalMozGetAsFile = unsafeWindow.HTMLCanvasElement.prototype.mozGetAsFile; - Object.defineProperty( - unsafeWindow.HTMLCanvasElement.prototype, - "mozGetAsFile", - { - enumerable: true, - configureable: false, - get: exportFunction(function(){ - switch (blockMode.readAPI.status){ - case "allow": - return originalMozGetAsFile; - case "block": - default: - 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 exportFunction( - function(sx, sy, sw, sh){ - var imageData = new window.ImageData(sw, sh); - var l = sw * sh * 4; - for (var i = 0; i < l; i += 1){ - imageData.data[i] = Math.floor( - Math.random() * 256 - ); - } - return imageData; - }, - unsafeWindow - ); - } - }, unsafeWindow) - } - ); - + // Translation var _ = function(name){ return _[name] || name; }; @@ -171,6 +154,8 @@ _[name] = translation; }); + // Communication with main.js + function checkPDF(blocking){ if (document.contentType.match(/\/pdf$/i)){ self.port.emit("isPDF", blocking); @@ -198,6 +183,13 @@ blockMode.readAPI.status = "block"; } }); + self.port.on("askReadout", function(force, askOnce){ + if (force || !checkPDF("askReadout")){ + blockMode.getContext.status = "allow"; + blockMode.readAPI.status = "ask"; + blockMode.readAPI.askStatus.askOnce = askOnce; + } + }); self.port.on("unblock", function(){ blockMode.getContext.status = "allow"; blockMode.readAPI.status = "allow"; diff --git a/lib/main.js b/lib/main.js index 3305609..712d2b3 100644 --- a/lib/main.js +++ b/lib/main.js @@ -109,6 +109,17 @@ mode = "blockReadout"; } break; + case "askReadout": + if (whiteList.match(url)){ + mode = "unblock"; + } + else if (blackList.match(url)){ + mode = "block"; + } + else { + mode = "askReadout"; + } + break; case "blockOnlyBlackList": if (blackList.match(url)){ mode = "block"; @@ -161,6 +172,7 @@ } }); worker.port.emit("setTranslation", "askForPermission", _("askForPermission")); + worker.port.emit("setTranslation", "askForReadoutPermission", _("askForReadoutPermission")); checkWorker(worker); }, }); diff --git a/locale/de-DE.properties b/locale/de-DE.properties index 6d0ff55..1bb896f 100644 --- a/locale/de-DE.properties +++ b/locale/de-DE.properties @@ -11,6 +11,7 @@ blockMode_options.block everything= alles blockieren blockMode_options.allow only white list= nur Einträge der Whitelist erlauben blockMode_options.ask for permission= um Erlaubnis fragen blockMode_options.block readout API= Auslese-API blockieren +blockMode_options.ask for readout API permission= bei Auslese-API um Erlaubnis fragen blockMode_options.block only black list= nur Einträge der Blacklist blockieren blockMode_options.allow everything= alles erlauben @@ -20,4 +21,5 @@ askOnlyOnce_description= Wenn eine Seite öfters versucht, die -API abzu allowPDFCanvas_title= in PDFs erlauben allowPDFCanvas_description= Die native pdf.js verwendet um den Inhalt von PDFs anzuzeigen. Wenn dies nicht markiert ist, werden viele Nachfragedialoge erscheinen oder die PDF Ansicht nicht funktionieren. -askForPermission= Wollen Sie erlauben? \ No newline at end of file +askForPermission= Wollen Sie erlauben? +askForReadoutPermission= Wollen Sie das Auslesen von erlauben? \ No newline at end of file diff --git a/locale/en-US.properties b/locale/en-US.properties index 8ba708e..3f6910a 100644 --- a/locale/en-US.properties +++ b/locale/en-US.properties @@ -11,6 +11,7 @@ blockMode_options.block everything= block everything blockMode_options.allow only white list= allow only white list blockMode_options.ask for permission= ask for permission blockMode_options.block readout API= block readout API +blockMode_options.ask for readout API permission= ask for readout API permission blockMode_options.block only black list= block only black list blockMode_options.allow everything= allow everything @@ -20,4 +21,5 @@ askOnlyOnce_description= If a page tries to access the -API several time allowPDFCanvas_title= Allow canvas in PDFs allowPDFCanvas_description= The native pdf.js uses 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 ? \ No newline at end of file +askForPermission= Do you want to allow ? +askForReadoutPermission= Do you want to allow readout? \ No newline at end of file diff --git a/package.json b/package.json index 8961171..5f4895a 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "name": "blockMode", "title": "block mode", "type": "menulist", - "value": "blockReadout", + "value": "askReadout", "options": [ { "value": "blockEverything", @@ -38,6 +38,10 @@ "value": "blockReadout", "label": "block readout API" }, + { + "value": "askReadout", + "label": "ask for readout API permission" + }, { "value": "blockOnlyBlackList", "label": "block only black list"