summaryrefslogtreecommitdiff
path: root/data/extensions/jsr@javascriptrestrictor/wrappingS-H-C.js
diff options
context:
space:
mode:
Diffstat (limited to 'data/extensions/jsr@javascriptrestrictor/wrappingS-H-C.js')
-rw-r--r--data/extensions/jsr@javascriptrestrictor/wrappingS-H-C.js337
1 files changed, 0 insertions, 337 deletions
diff --git a/data/extensions/jsr@javascriptrestrictor/wrappingS-H-C.js b/data/extensions/jsr@javascriptrestrictor/wrappingS-H-C.js
deleted file mode 100644
index f641d4b..0000000
--- a/data/extensions/jsr@javascriptrestrictor/wrappingS-H-C.js
+++ /dev/null
@@ -1,337 +0,0 @@
-/** \file
- * \brief This file contains wrappers for Canvas-related calls
- *
- * \see https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API
- * \see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
- * \see https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas
- *
- * \author Copyright (C) 2019 Libor Polcak
- * \author Copyright (C) 2021 Matus Svancar
- * \author Copyright (C) 2023 Martin Zmitko
- *
- * \license SPDX-License-Identifier: GPL-3.0-or-later
- * \license SPDX-License-Identifier: MPL-2.0
- */
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-//
-// Alternatively, the contents of this file may be used under the terms
-// of the Mozilla Public License, v. 2.0, as described below:
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this file,
-// You can obtain one at http://mozilla.org/MPL/2.0/.
-//
-// \copyright Copyright (c) 2020 The Brave Authors.
-
-/** \file
- * \ingroup wrappers
- * This file contains wrappers for calls related to the Canvas API, about which you can read more at MDN:
- * * [Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API)
- * * [CanvasRenderingContext2D](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D)
- * * [OffscreenCanvas](https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas)
- *
- * The goal is to prevent fingerprinting by modifying the values that can be read from the canvas.
- * So the visual content of wrapped canvases as displayed on the screen is the same as intended.
- *
- * The modified content can be either an empty image or a fake image that is modified according to
- * session and domain keys to be different than the original albeit very similar (i.e. the approach
- * inspired by the algorithms created by [Brave Software](https://brave.com) available [here](https://github.com/brave/brave-core/blob/master/chromium_src/third_party/blink/renderer/core/execution_context/execution_context.cc).
- *
- * Note that both approaches are detectable by a fingerprinter that checks if a predetermined image
- * inserted to the canvas is the same as the read one, see [here](https://arkenfox.github.io/TZP/tests/canvasnoise.html) for an example,
- * Nevertheless, the aim of the wrappers is to limit the finerprintability.
- *
- * Also note that a determined fingerprinter can reveal the modifications and consequently uncover
- * the original image. This can be avoided with the approach that completely clears the data stored
- * in the canvas. Use the modifications based on session and domain keys if you want to provide an
- * image that is similar to the original or if you want to produce a fake image that is not
- * obviously spoofed to a naked eye. Otherwise, use the clearing approach.
- */
-
-/*
- * Create private namespace
- */
-(function() {
-
- const DEF_CANVAS_COPY = `
- let canvasCopy = ctx => {
- let {width, height} = ctx.canvas;
- let fake = document.createElement("canvas");
- fake.setAttribute("width", width);
- fake.setAttribute("height", height);
- let stx = fake.getContext("2d");
- let imageData = window.CanvasRenderingContext2D.prototype.getImageData.call(ctx, 0, 0, width, height);
- stx.putImageData(imageData, 0, 0);
- return fake;
- };
- `;
-
- /** @var String helping_code.
- * Selects if the canvas should be cleared (1) or a fake image should be created based on session
- * and domain keys (0).
- */
- var helping_code = `var approach = args[0];`;
- var wrappers = [{
- parent_object: "HTMLCanvasElement.prototype",
- parent_object_property: "toDataURL",
- wrapped_objects: [{
- original_name: "HTMLCanvasElement.prototype.toDataURL",
- wrapped_name: "origToDataURL",
- }],
- helping_code: helping_code,
- wrapping_code_function_name: "wrapping",
- wrapping_code_function_params: "parent",
- wrapping_code_function_call_window: true,
- original_function: "parent.HTMLCanvasElement.prototype.toDataURL",
- replace_original_function: true,
- wrapping_function_args: "...args",
- /** \fn fake HTMLCanvasElement.prototype.toDataURL
- * \brief Returns fake canvas content, see CanvasRenderingContext2D.prototype for more details.
- *
- * Internally creates a fake canvas of the same height and width as the original and calls
- * CanvasRenderingContext2D.getImageData() that determines the result. If canvas uses WebGLRenderingContext
- * the content is copied to new canvas using CanvasRenderingContext2D and function toDataURL is called on it.
- */
- wrapping_function_body: `
- var ctx = this.getContext("2d");
- if(ctx){
- ${DEF_CANVAS_COPY}
- return origToDataURL.call(canvasCopy(ctx), ...args);
- }
- else {
- var ctx = this.getContext("webgl2", {preserveDrawingBuffer: true}) ||
- this.getContext("experimental-webgl2", {preserveDrawingBuffer: true}) ||
- this.getContext("webgl", {preserveDrawingBuffer: true}) ||
- this.getContext("experimental-webgl", {preserveDrawingBuffer: true}) ||
- this.getContext("moz-webgl", {preserveDrawingBuffer: true});
- if(ctx){
- var fake = document.createElement("canvas");
- fake.setAttribute("width", this.width);
- fake.setAttribute("height", this.height);
- var stx = fake.getContext("2d");
- stx.drawImage(ctx.canvas, 0, 0);
- return HTMLCanvasElement.prototype.toDataURL.call(fake);
- }
- }
- `,
- },
- {
- parent_object: "CanvasRenderingContext2D.prototype",
- parent_object_property: "getImageData",
- wrapped_objects: [{
- original_name: "CanvasRenderingContext2D.prototype.getImageData",
- wrapped_name: "origGetImageData",
- }],
- helping_code: helping_code + farbleCanvasDataBrave.toString() + `
- var farble = function(context, fake) {
- if(approach === 1){
- fake.fillStyle = "white";
- fake.fillRect(0, 0, context.canvas.width, context.canvas.height);
- return;
- }
- else if(approach === 0){
- const width = context.canvas.width;
- const height = context.canvas.height;
- const imageData = origGetImageData.call(context, 0, 0, width, height);
- const len = imageData.data.length;
- if (wasm.ready && wasm.grow(len)) {
- try {
- farblePixelsWASM();
- } catch (e) {
- console.error("WebAssembly optimized farbling failed, falling back to JavaScript implementation", e);
- farblePixelsJS();
- }
- } else {
- farblePixelsJS();
- }
- // Do not modify the original canvas, always modify the fake canvas.
- // Always farble the whole image so that the farbled data do not depend
- // on the page-specified extraction data rectangle.
- fake.putImageData(imageData, 0, 0);
-
- function farblePixelsWASM() {
- wasm.set(imageData.data);
- const crc = wasm.crc16(len);
- const mash = new Mash();
- mash.addData(' ');
- mash.addData(domainHash);
- mash.addData("CanvasFarbling");
- mash.addData(crc);
- wasm.farbleBytes(len, mash.n | 0, true);
- imageData.data.set(wasm.get(len));
- }
-
- function farblePixelsJS() {
- const BYTES_PER_ROW = width * 4;
- farbleCanvasDataBrave(function*() {
- let data = imageData.data;
- let offset = 0;
- while (offset < len) {
- yield data.subarray(offset, offset + BYTES_PER_ROW);
- offset += BYTES_PER_ROW;
- }
- }, width);
- }
- }
- };`,
- wrapping_code_function_name: "wrapping",
- wrapping_code_function_params: "parent",
- wrapping_code_function_call_window: true,
- original_function: "parent.CanvasRenderingContext2D.prototype.getImageData",
- replace_original_function: true,
- wrapping_function_args: "...args",
- /** \fn fake CanvasRenderingContext2D.prototype.getImageData
- * \brief Returns a fake image data of the same height and width as stored in the original canvas.
- *
- * Internally calls the farbling that select the output which can be either an empty image or
- * a fake image that is modified according to session and domain keys to be different than the
- * original albeit very similar.
- */
- wrapping_function_body: `
- var fake = document.createElement("canvas");
- fake.setAttribute("width", this.canvas.width);
- fake.setAttribute("height", this.canvas.height);
- var stx = fake.getContext("2d");
- farble(this,stx);
- return origGetImageData.call(stx, ...args);
- `,
- },
- {
- parent_object: "HTMLCanvasElement.prototype",
- parent_object_property: "toBlob",
- wrapped_objects: [{
- original_name: "HTMLCanvasElement.prototype.toBlob",
- wrapped_name: "origToBlob",
- }],
- helping_code: ``,
- wrapping_code_function_name: "wrapping",
- wrapping_code_function_params: "parent",
- wrapping_code_function_call_window: true,
- original_function: "parent.HTMLCanvasElement.prototype.toBlob",
- replace_original_function: true,
- wrapping_function_args: "...args",
- /** \fn fake HTMLCanvasElement.prototype.toBlob
- * \brief Returns fake canvas content, see CanvasRenderingContext2D.prototype for more details.
- *
- * Internally creates a fake canvas of the same height and width as the original and calls
- * CanvasRenderingContext2D.getImageData() that detemines the result.
- */
- wrapping_function_body: `
- ${DEF_CANVAS_COPY}
- return origToBlob.call(canvasCopy(this.getContext("2d")), ...args);
- `,
- },
- {
- parent_object: "OffscreenCanvas.prototype",
- parent_object_property: "convertToBlob",
- wrapped_objects: [{
- original_name: "OffscreenCanvas.prototype.convertToBlob",
- wrapped_name: "origConvertToBlob",
- }],
- helping_code: ``,
- wrapping_code_function_name: "wrapping",
- wrapping_code_function_params: "parent",
- wrapping_code_function_call_window: true,
- original_function: "parent.OffscreenCanvas.prototype.convertToBlob",
- replace_original_function: true,
- wrapping_function_args: "...args",
- /** \fn fake OffscreenCanvas.prototype.convertToBlob
- * \brief Returns fake canvas content, see CanvasRenderingContext2D.prototype for more details.
- *
- * Internally creates a fake canvas of the same height and width as the original and calls
- * CanvasRenderingContext2D.getImageData() that detemines the result.
- */
- wrapping_function_body: `
- ${DEF_CANVAS_COPY}
- return origConvertToBlob.call(canvasCopy(this.getContext("2d")), ...args);
- `,
- },
- {
- parent_object: "CanvasRenderingContext2D.prototype",
- parent_object_property: "isPointInPath",
- wrapped_objects: [{
- original_name: "CanvasRenderingContext2D.prototype.isPointInPath",
- wrapped_name: "origIsPointInPath",
- }],
- helping_code: helping_code + `
- function farbleIsPointInPath(ctx, ...args){
- if(approach === 0){
- var ret = origIsPointInPath.call(ctx, ...args);
- return (ret && ((prng()*20) > 1));
- }
- else if(approach === 1){
- return false;
- }
- };
- `,
- wrapping_code_function_name: "wrapping",
- wrapping_code_function_params: "parent",
- wrapping_code_function_call_window: true,
- original_function: "parent.CanvasRenderingContext2D.prototype.isPointInPath",
- replace_original_function: true,
- wrapping_function_args: "...args",
- /** \fn fake CanvasRenderingContext2D.prototype.isPointInPath
- * \brief Returns modified result
- *
- * Either returns false or original function return value which is changed to false with 1/20 probability
- *
- * \bug Changing value with probability has some issues:
- * * multiple calls with the same pixel can return different values
- * * inconsistencies among adjacent pixels
- */
- wrapping_function_body: `
- return farbleIsPointInPath(this, ...args);
- `,
- },
- {
- parent_object: "CanvasRenderingContext2D.prototype",
- parent_object_property: "isPointInStroke",
- wrapped_objects: [{
- original_name: "CanvasRenderingContext2D.prototype.isPointInStroke",
- wrapped_name: "origIsPointInStroke",
- }],
- helping_code: helping_code + `
- function farbleIsPointInStroke(ctx, ...args){
- if(approach === 0){
- var ret = origIsPointInStroke.call(ctx, ...args);
- return (ret && ((prng()*20) > 1));
- }
- else if(approach === 1){
- return false;
- }
- };
- `,
- wrapping_code_function_name: "wrapping",
- wrapping_code_function_params: "parent",
- wrapping_code_function_call_window: true,
- original_function: "parent.CanvasRenderingContext2D.prototype.isPointInStroke",
- replace_original_function: true,
- wrapping_function_args: "...args",
- /** \fn fake CanvasRenderingContext2D.prototype.isPointInStroke
- * \brief Returns modified result
- *
- * Either returns false or original function return value which is changed to false with 1/20 probability
- *
- * \bug Changing value with probability has some issues:
- * * multiple calls with the same pixel can return different values
- * * inconsistencies among adjacent pixels
- */
- wrapping_function_body: `
- return farbleIsPointInStroke(this, ...args);
- `,
- },
- ]
- add_wrappers(wrappers);
-})();