diff --git a/lib/modifiedCanvasAPI.js b/lib/modifiedCanvasAPI.js index 278b827..252f8fc 100644 --- a/lib/modifiedCanvasAPI.js +++ b/lib/modifiedCanvasAPI.js @@ -185,8 +185,65 @@ webgl.setRandomSupply(supply); }; - const canvasContextType = new WeakMap(); + function createGetStatus(protectedPart){ + if (protectedPart === "readout+"){ + return function(obj, status, prefs){ + const protectedPartChecker = getProtectedPartChecker(prefs, status.url); + status = Object.create(status); + status.active = protectedPartChecker("readout"); + if (!status.active && protectedPartChecker("input")){ + const contextType = canvasContextType.get(obj); + status.active = contextType !== "2d"; + } + return status; + }; + } + return function getStatus(obj, status, prefs){ + const protectedPartChecker = getProtectedPartChecker(prefs, status.url); + status = Object.create(status); + status.active = protectedPartChecker(protectedPart); + return status; + }; + } + + function useFakeCanvasCallback(args, check){ + const {prefs, notify, window, original} = check; + if (canvasSizeShouldBeFaked(this, prefs)){ + const fakeCanvas = getFakeCanvas(window, this, prefs); + if (fakeCanvas !== this){ + notify("fakedReadout"); + } + return original.apply(fakeCanvas, window.Array.from(args)); + } + else { + return original.apply(this, window.Array.from(args)); + } + } + + function mixOnInputCallback(args, check){ + const {prefs, notify, window, original} = check; + if (!this || canvasSizeShouldBeFaked(this.canvas, prefs)){ + notify("fakedInput"); + let oldImageData; + try { + // "this" is not trustable - it may be not a context + oldImageData = getImageData(window, this).imageData; + } + catch (error){ + // nothing to do here + } + // if "this" is not a correct context the next line will throw an error + const ret = original.apply(this, window.Array.from(args)); + const newImageData = getImageData(window, this).imageData; + this.putImageData(randomMixImageData(window, oldImageData, newImageData), 0, 0); + return ret; + } + else { + return original.apply(this, window.Array.from(args)); + } + } + // changed functions and their fakes scope.changedFunctions = { getContext: { @@ -225,106 +282,38 @@ }, toDataURL: { type: "readout", - getStatus: function(obj, status, prefs){ - const protectedPartChecker = getProtectedPartChecker(prefs, status.url); - status = Object.create(status); - status.active = protectedPartChecker("readout"); - if (!status.active && protectedPartChecker("input")){ - const contextType = canvasContextType.get(obj); - status.active = contextType !== "2d"; - } - return status; - }, + getStatus: createGetStatus("readout+"), object: "HTMLCanvasElement", fakeGenerator: function(checker){ return function toDataURL(){ - return checkerWrapper(checker, this, arguments, function(args, check){ - const {prefs, notify, window, original} = check; - if (canvasSizeShouldBeFaked(this, prefs)){ - const fakeCanvas = getFakeCanvas(window, this, prefs); - if (fakeCanvas !== this){ - notify("fakedReadout"); - } - return original.apply(fakeCanvas, window.Array.from(args)); - } - else { - return original.apply(this, window.Array.from(args)); - } - }); + return checkerWrapper(checker, this, arguments, useFakeCanvasCallback); }; } }, toBlob: { type: "readout", - getStatus: function(obj, status, prefs){ - const protectedPartChecker = getProtectedPartChecker(prefs, status.url); - status = Object.create(status); - status.active = protectedPartChecker("readout"); - if (!status.active && protectedPartChecker("input")){ - const contextType = canvasContextType.get(obj); - status.active = contextType !== "2d"; - } - return status; - }, + getStatus: createGetStatus("readout+"), object: "HTMLCanvasElement", fakeGenerator: function(checker){ return function toBlob(callback){ - return checkerWrapper(checker, this, arguments, function(args, check){ - const {prefs, notify, window, original} = check; - if (canvasSizeShouldBeFaked(this, prefs)){ - const fakeCanvas = getFakeCanvas(window, this, prefs); - if (fakeCanvas !== this){ - notify("fakedReadout"); - } - return original.apply(fakeCanvas, window.Array.from(args)); - } - else { - return original.apply(this, window.Array.from(args)); - } - }); + return checkerWrapper(checker, this, arguments, useFakeCanvasCallback); }; }, exportOptions: {allowCallbacks: true} }, mozGetAsFile: { type: "readout", - getStatus: function(obj, status, prefs){ - const protectedPartChecker = getProtectedPartChecker(prefs, status.url); - status = Object.create(status); - status.active = protectedPartChecker("readout"); - if (!status.active && protectedPartChecker("input")){ - const contextType = canvasContextType.get(obj); - status.active = contextType !== "2d"; - } - return status; - }, + getStatus: createGetStatus("readout+"), object: "HTMLCanvasElement", fakeGenerator: function(checker){ return function mozGetAsFile(callback){ - return checkerWrapper(checker, this, arguments, function(args, check){ - const {prefs, notify, window, original} = check; - if (canvasSizeShouldBeFaked(this, prefs)){ - const fakeCanvas = getFakeCanvas(window, this, prefs); - if (fakeCanvas !== this){ - notify("fakedReadout"); - } - return original.apply(fakeCanvas, window.Array.from(args)); - } - else { - return original.apply(this, window.Array.from(args)); - } - }); + return checkerWrapper(checker, this, arguments, useFakeCanvasCallback); }; } }, getImageData: { type: "readout", - getStatus: function(obj, status, prefs){ - const protectedPartChecker = getProtectedPartChecker(prefs, status.url); - status = Object.create(status); - status.active = protectedPartChecker("readout"); - return status; - }, + getStatus: createGetStatus("readout"), object: "CanvasRenderingContext2D", fakeGenerator: function(checker){ return function getImageData(sx, sy, sw, sh){ @@ -354,12 +343,7 @@ }, isPointInPath: { type: "readout", - getStatus: function(obj, status, prefs){ - const protectedPartChecker = getProtectedPartChecker(prefs, status.url); - status = Object.create(status); - status.active = protectedPartChecker("readout"); - return status; - }, + getStatus: createGetStatus("readout"), object: "CanvasRenderingContext2D", fakeGenerator: function(checker){ return function isPointInPath(x, y){ @@ -381,12 +365,7 @@ }, isPointInStroke: { type: "readout", - getStatus: function(obj, status, prefs){ - const protectedPartChecker = getProtectedPartChecker(prefs, status.url); - status = Object.create(status); - status.active = protectedPartChecker("readout"); - return status; - }, + getStatus: createGetStatus("readout"), object: "CanvasRenderingContext2D", fakeGenerator: function(checker){ return function isPointInStroke(x, y){ @@ -417,84 +396,27 @@ }, fillText: { type: "input", - getStatus: function(obj, status, prefs){ - const protectedPartChecker = getProtectedPartChecker(prefs, status.url); - status = Object.create(status); - status.active = protectedPartChecker("input"); - return status; - }, + getStatus: createGetStatus("input"), object: "CanvasRenderingContext2D", fakeGenerator: function(checker){ return function fillText(str, x, y){ - return checkerWrapper(checker, this, arguments, function(args, check){ - const {prefs, notify, window, original} = check; - if (!this || canvasSizeShouldBeFaked(this.canvas, prefs)){ - notify("fakedInput"); - let oldImageData; - try { - // "this" is not trustable - it may be not a context - oldImageData = getImageData(window, this).imageData; - } - catch (error){ - // nothing to do here - } - // if "this" is not a correct context the next line will throw an error - const ret = original.apply(this, window.Array.from(args)); - const newImageData = getImageData(window, this).imageData; - this.putImageData(randomMixImageData(window, oldImageData, newImageData), 0, 0); - return ret; - } - else { - return original.apply(this, window.Array.from(args)); - } - }); + return checkerWrapper(checker, this, arguments, mixOnInputCallback); }; } }, strokeText: { type: "input", - getStatus: function(obj, status, prefs){ - const protectedPartChecker = getProtectedPartChecker(prefs, status.url); - status = Object.create(status); - status.active = protectedPartChecker("input"); - return status; - }, + getStatus: createGetStatus("input"), object: "CanvasRenderingContext2D", fakeGenerator: function(checker){ return function strokeText(str, x, y){ - return checkerWrapper(checker, this, arguments, function(args, check){ - const {prefs, notify, window, original} = check; - if (!this || canvasSizeShouldBeFaked(this.canvas, prefs)){ - notify("fakedInput"); - let oldImageData; - try { - // "this" is not trustable - it may be not a context - oldImageData = getImageData(window, this).imageData; - } - catch (error){ - // nothing to do here - } - // if "this" is not a correct context the next line will throw an error - const ret = original.apply(this, window.Array.from(args)); - const newImageData = getImageData(window, this).imageData; - this.putImageData(randomMixImageData(window, oldImageData, newImageData), 0, 0); - return ret; - } - else { - return original.apply(this, window.Array.from(args)); - } - }); + return checkerWrapper(checker, this, arguments, mixOnInputCallback); }; } }, readPixels: { type: "readout", - getStatus: function(obj, status, prefs){ - const protectedPartChecker = getProtectedPartChecker(prefs, status.url); - status = Object.create(status); - status.active = protectedPartChecker(["readout", "input"]); - return status; - }, + getStatus: createGetStatus(["readout", "input"]), object: ["WebGLRenderingContext", "WebGL2RenderingContext"], fakeGenerator: function(checker){ // eslint-disable-next-line max-params @@ -520,12 +442,7 @@ }, getParameter: { type: "readout", - getStatus: function(obj, status, prefs){ - const protectedPartChecker = getProtectedPartChecker(prefs, status.url); - status = Object.create(status); - status.active = protectedPartChecker(["readout", "input"]); - return status; - }, + getStatus: createGetStatus(["readout", "input"]), object: ["WebGLRenderingContext", "WebGL2RenderingContext"], fakeGenerator: function(checker){ webgl.initializeParameterDefinitions();