From a9c7d9770807103d1a656229f76dbc7769db0ecf Mon Sep 17 00:00:00 2001 From: kkapsner Date: Fri, 5 May 2017 09:18:11 +0200 Subject: [PATCH] Prevented error when wrong object is passed to the faked functions. Solves the fourth problem in #114. --- lib/intercept.js | 2 +- lib/modifiedAPI.js | 102 ++++++++++++++++++++++++++------------------- releaseNotes.txt | 1 + 3 files changed, 60 insertions(+), 45 deletions(-) diff --git a/lib/intercept.js b/lib/intercept.js index dc3b929..fc91109 100644 --- a/lib/intercept.js +++ b/lib/intercept.js @@ -73,7 +73,7 @@ setRandomSupplyByType(prefs("rng")); var fake = changedFunction.fakeGenerator(prefs, function(messageId){ notify({url, errorStack: error.stack, messageId}); - }, original); + }, window, original); switch (fake){ case true: return original; diff --git a/lib/modifiedAPI.js b/lib/modifiedAPI.js index 1527e52..e08e538 100644 --- a/lib/modifiedAPI.js +++ b/lib/modifiedAPI.js @@ -44,19 +44,25 @@ } function getFakeCanvas(window, original){ - var context = getContext(window, original); - var {imageData, source} = getImageData(window, context); - var desc = imageData.data; - var l = desc.length; - var rng = randomSupply.getRng(l, window); - - for (var i = 0; i < l; i += 1){ - desc[i] = rng(source[i], i); + try { + // original may not be a canvas -> we must not leak an error + var context = getContext(window, original); + var {imageData, source} = getImageData(window, context); + var desc = imageData.data; + var l = desc.length; + var rng = randomSupply.getRng(l, window); + + for (var i = 0; i < l; i += 1){ + desc[i] = rng(source[i], i); + } + var canvas = original.cloneNode(true); + context = window.HTMLCanvasElement.prototype.getContext.call(canvas, "2d"); + context.putImageData(imageData, 0, 0); + return canvas; + } + catch (e){ + return original; } - var canvas = original.cloneNode(true); - context = window.HTMLCanvasElement.prototype.getContext.call(canvas, "2d"); - context.putImageData(imageData, 0, 0); - return canvas; } function randomMixImageData(window, imageData1, imageData2){ var data1 = imageData1.data; @@ -77,9 +83,6 @@ return imageData2; } - function getWindow(canvas){ - return canvas.ownerDocument.defaultView; - } function hasType(status, type){ return status.type.indexOf(type) !== -1; } @@ -114,11 +117,10 @@ } }, object: "HTMLCanvasElement", - fakeGenerator: function(prefs, notify){ + fakeGenerator: function(prefs, notify, window, original){ return function(context, contextAttributes){ - var window = getWindow(this); canvasContextType.set(this, context); - return window.HTMLCanvasElement.prototype.getContext.apply(this, arguments); + return original.apply(this, window.Array.from(arguments)); }; } }, @@ -136,11 +138,10 @@ return status; }, object: "HTMLCanvasElement", - fakeGenerator: function(prefs, notify){ + fakeGenerator: function(prefs, notify, window, original){ return function toDataURL(){ notify("fakedReadout"); - var window = getWindow(this); - return window.HTMLCanvasElement.prototype.toDataURL.apply(getFakeCanvas(window, this), arguments); + return original.apply(getFakeCanvas(window, this), window.Array.from(arguments)); }; } }, @@ -158,11 +159,10 @@ return status; }, object: "HTMLCanvasElement", - fakeGenerator: function(prefs, notify){ + fakeGenerator: function(prefs, notify, window, original){ return function toBlob(callback){ notify("fakedReadout"); - var window = getWindow(this); - return window.HTMLCanvasElement.prototype.toBlob.apply(getFakeCanvas(window, this), arguments); + return original.apply(getFakeCanvas(window, this), window.Array.from(arguments)); }; }, exportOptions: {allowCallbacks: true} @@ -181,11 +181,10 @@ return status; }, object: "HTMLCanvasElement", - fakeGenerator: function(prefs, notify){ + fakeGenerator: function(prefs, notify, window, original){ return function mozGetAsFile(callback){ notify("fakedReadout"); - var window = getWindow(this); - return window.HTMLCanvasElement.prototype.mozGetAsFile.apply(getFakeCanvas(window, this), arguments); + return original.apply(getFakeCanvas(window, this), window.Array.from(arguments)); }; } }, @@ -203,19 +202,25 @@ return status; }, object: "CanvasRenderingContext2D", - fakeGenerator: function(prefs, notify, original){ + fakeGenerator: function(prefs, notify, window, original){ var maxSize = prefs("maxFakeSize") || Number.POSITIVE_INFINITY; return function getImageData(sx, sy, sw, sh){ - var window = getWindow(this.canvas); if (sw * sh > maxSize){ return original.apply(this, window.Array.from(arguments)); } else { notify("fakedReadout"); - var context = window.HTMLCanvasElement.prototype.getContext.call( - getFakeCanvas(window, this.canvas), - "2d" - ); + var fakeCanvas; + var context = this; + if (this && this.canvas) { + fakeCanvas = getFakeCanvas(window, this.canvas); + } + if (fakeCanvas && fakeCanvas !== this.canvas){ + context = window.HTMLCanvasElement.prototype.getContext.call( + getFakeCanvas(window, this.canvas), + "2d" + ); + } return original.apply(context, window.Array.from(arguments)); } }; @@ -229,12 +234,17 @@ return status; }, object: "CanvasRenderingContext2D", - fakeGenerator: function(prefs, notify){ + fakeGenerator: function(prefs, notify, window, original){ return function fillText(str, x, y){ notify("fakedInput"); - var window = getWindow(this.canvas); - var oldImageData = getImageData(window, this).imageData; - var ret = window.CanvasRenderingContext2D.prototype.fillText.apply(this, arguments); + var oldImageData; + try { + // "this" is not trustable - it may be not a context + oldImageData = getImageData(window, this).imageData; + } + catch (e){} + // if "this" is not a correct context the next line will throw an error + var ret = original.apply(this, window.Array.from(arguments)); var newImageData = getImageData(window, this).imageData; this.putImageData(randomMixImageData(window, oldImageData, newImageData), 0, 0); return ret; @@ -249,12 +259,17 @@ return status; }, object: "CanvasRenderingContext2D", - fakeGenerator: function(prefs, notify){ + fakeGenerator: function(prefs, notify, window, original){ return function strokeText(str, x, y){ notify("fakedInput"); - var window = getWindow(this.canvas); - var oldImageData = getImageData(window, this).imageData; - var ret = window.CanvasRenderingContext2D.prototype.strokeText.apply(this, arguments); + var oldImageData; + try { + // "this" is not trustable - it may be not a context + oldImageData = getImageData(window, this).imageData; + } + catch (e){} + // if "this" is not a correct context the next line will throw an error + var ret = original.apply(this, window.Array.from(arguments)); var newImageData = getImageData(window, this).imageData; this.putImageData(randomMixImageData(window, oldImageData, newImageData), 0, 0); return ret; @@ -269,13 +284,12 @@ return status; }, object: ["WebGLRenderingContext", "WebGL2RenderingContext"], - fakeGenerator: function(prefs, notify){ + fakeGenerator: function(prefs, notify, window, original){ 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 window = getWindow(this.canvas); - var ret = window.WebGLRenderingContext.prototype.readPixels.apply(this, arguments); + var ret = original.apply(this, window.Array.from(arguments)); var l = xPixels.length; var rng = randomSupply.getRng(l, window); diff --git a/releaseNotes.txt b/releaseNotes.txt index 0ebc023..5c97914 100644 --- a/releaseNotes.txt +++ b/releaseNotes.txt @@ -8,6 +8,7 @@ Version 0.3.8: fixes: - prevented error when canvas has size zero - frame script was not loaded in the first tab that was restored from the last session + - prevented error when wrong object is passed to the faked functions Version 0.3.7: new features: