diff --git a/.vscode/settings.json b/.vscode/settings.json index 496dab5..716f858 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,6 +5,7 @@ "Blockiermodus", "Captcha", "Coord", + "Fenix", "Funktionalitätstest", "Funktionalitätstests", "Hyrp", diff --git a/lib/modifiedDOMRectAPI.js b/lib/modifiedDOMRectAPI.js index 9a70378..4c413eb 100644 --- a/lib/modifiedDOMRectAPI.js +++ b/lib/modifiedDOMRectAPI.js @@ -50,51 +50,79 @@ } const cache = {}; - const valueCache = [{}, {}, {}, {}, {}]; + const valueCache = [{}, {}, {}, {}, {}, {}, {}]; scope.cache = { valueCache, X: 0, Y: 1, WIDTH: 2, HEIGHT: 3, - OTHER: 4 + OTHER: 4, + Z: 5, + W: 6, }; + function getFakeValue(value, i, {window, prefs, rng}){ + const valueHash = getValueHash(value); + const cache = valueCache[i]; + let cachedValue = cache[valueHash]; + if (typeof cachedValue === "number"){ + return cachedValue; + } + if ((value * prefs("domRectIntegerFactor", window.location)) % 1 === 0){ + cache[valueHash] = value; + return value; + } + else { + const fakedValue = value + 0.01 * (rng(i) / 0xffffffff - 0.5); + const fakedHash = getValueHash(fakedValue); + cache[valueHash] = fakedValue; + cache[fakedHash] = fakedValue; + return fakedValue; + } + } + scope.getFakeValue = getFakeValue; function getFakeDomRect(window, domRect, prefs, notify){ const hash = getHash(domRect); let cached = cache[hash]; if (!cached){ notify("fakedDOMRectReadout"); const rng = randomSupply.getRng(4, window); - const getFakeValue = function getFakeValue(value, i){ - const valueHash = getValueHash(value); - const cache = valueCache[i]; - let cachedValue = cache[valueHash]; - if (typeof cachedValue === "number"){ - return cachedValue; - } - if ((value * prefs("domRectIntegerFactor", window.location)) % 1 === 0){ - cache[valueHash] = value; - return value; - } - else { - const fakedValue = value + 0.01 * (rng(i) / 0xffffffff - 0.5); - const fakedHash = getValueHash(fakedValue); - cache[valueHash] = fakedValue; - cache[fakedHash] = fakedValue; - return fakedValue; - } - }; - cached = new domRect.constructor( - getFakeValue(domRect.x, 0), - getFakeValue(domRect.y, 1), - getFakeValue(domRect.width, 2), - getFakeValue(domRect.height, 3) + const env = {window, prefs, rng}; + cached = new (domRect instanceof window.SVGRect? window.DOMRectReadOnly: domRect.constructor)( + getFakeValue(domRect.x, 0, env), + getFakeValue(domRect.y, 1, env), + getFakeValue(domRect.width, 2, env), + getFakeValue(domRect.height, 3, env) ); cache[hash] = cached; cache[getHash(cached)] = cached; } return cached; } + function getFakeDOMPoint(window, domPoint, prefs){ + const env = {window, prefs, rng: randomSupply.getRng(7, window)}; + return new domPoint.constructor( + getFakeValue(domPoint.x, 0, env), + getFakeValue(domPoint.y, 1, env), + getFakeValue(domPoint.z, 5, env), + getFakeValue(domPoint.w, 6, env) + ); + } + function getFakeSVGPoint(window, svgPoint, prefs){ + const env = {window, prefs, rng: randomSupply.getRng(2, window)}; + svgPoint.x = getFakeValue(svgPoint.x, 0, env); + svgPoint.y = getFakeValue(svgPoint.y, 1, env); + return svgPoint; + } + function getFakeDOMQuad(window, domQuad, prefs, notify){ + notify("fakedDOMRectReadout"); + return new domQuad.constructor( + getFakeDOMPoint(window, domQuad.p1, prefs), + getFakeDOMPoint(window, domQuad.p2, prefs), + getFakeDOMPoint(window, domQuad.p3, prefs), + getFakeDOMPoint(window, domQuad.p4, prefs) + ); + } function registerCallback(args, check){ const {prefs, notify, window, original} = check; @@ -105,6 +133,18 @@ return originalValue; } + function fakePointCallback(args, check){ + const {prefs, notify, window, original} = check; + const ret = args.length? original.call(this, ...args): original.call(this); + notify("fakedDOMRectReadout"); + if (ret instanceof window.SVGPoint){ + return getFakeSVGPoint(window, ret, prefs); + } + else { + return getFakeDOMPoint(window, ret, prefs); + } + } + scope.changedFunctions = { getClientRects: { object: ["Range", "Element"], @@ -130,14 +170,31 @@ } }, - getBounds: { - object: ["DOMQuad"], + getBoxQuads: { + object: ["Document", "Element", "Text", "CSSPseudoElement"], fakeGenerator: function(checker){ - return function getBounds(){ - return checkerWrapper(checker, this, arguments, registerCallback); + return function getBoxQuads(){ + return checkerWrapper(checker, this, arguments, function(args, check){ + const {prefs, notify, window, original} = check; + const ret = args.length? original.call(this, ...args): original.call(this); + for (let i = 0; i < ret.length; i += 1){ + ret[i] = getFakeDOMQuad(window, ret[i], prefs, notify); + } + return ret; + }); }; } }, + // It seems only getBoxQuads creates a DOMQuad and this method is behind a flag. + // So the only way to create one is manually by the constructor and then no fingerprinting is possible. + // getBounds: { + // object: ["DOMQuad"], + // fakeGenerator: function(checker){ + // return function getBounds(){ + // return checkerWrapper(checker, this, arguments, registerCallback); + // }; + // } + // }, getBBox: { object: ["SVGGraphicsElement"], fakeGenerator: function(checker){ @@ -146,6 +203,23 @@ }; } }, + + getStartPositionOfChar: { + object: ["SVGTextContentElement"], + fakeGenerator: function(checker){ + return function getStartOfChar(){ + return checkerWrapper(checker, this, arguments, fakePointCallback); + }; + } + }, + getEndPositionOfChar: { + object: ["SVGTextContentElement"], + fakeGenerator: function(checker){ + return function getEndOfChar(){ + return checkerWrapper(checker, this, arguments, fakePointCallback); + }; + } + }, getExtentOfChar: { object: ["SVGTextContentElement"], fakeGenerator: function(checker){ @@ -154,6 +228,14 @@ }; } }, + getPointAtLength: { + object: ["SVGGeometryElement", "SVGPathElement"], + fakeGenerator: function(checker){ + return function getPointAtLength(){ + return checkerWrapper(checker, this, arguments, fakePointCallback); + }; + } + }, }; function generateChangedDOMRectPropertyGetter(property, readonly = false){ @@ -164,6 +246,7 @@ ]: [ function(window){return window.DOMRect && window.DOMRect.prototype;}, + function(window){return window.SVGRect && window.SVGRect.prototype;}, function(window){return window.DOMRectReadOnly && window.DOMRectReadOnly.prototype;} ], name: property, diff --git a/lib/settingDefinitions.js b/lib/settingDefinitions.js index 879c985..398b488 100644 --- a/lib/settingDefinitions.js +++ b/lib/settingDefinitions.js @@ -114,9 +114,13 @@ {name: "DOMRect-API", level: 1}, "getClientRects @ domRect", "getBoundingClientRect @ domRect", + "getBoxQuads @ domRect", "getBounds @ domRect", "getBBox @ domRect", + "getStartPositionOfChar @ domRect", + "getEndPositionOfChar @ domRect", "getExtentOfChar @ domRect", + "getPointAtLength @ domRect", "intersectionRect @ domRect", "boundingClientRect @ domRect", "rootBounds @ domRect", diff --git a/releaseNotes.txt b/releaseNotes.txt index 39ba1b6..30bbc5d 100644 --- a/releaseNotes.txt +++ b/releaseNotes.txt @@ -1,6 +1,6 @@ Version 1.4: changes: - - + - updated DOMRect protection new features: - diff --git a/versions/updates.json b/versions/updates.json index 0b4bc8f..b4b5902 100644 --- a/versions/updates.json +++ b/versions/updates.json @@ -145,6 +145,10 @@ { "version": "1.4Alpha20200607", "update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.4Alpha20200607-an+fx.xpi" + }, + { + "version": "1.4Alpha20201102", + "update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.4Alpha20201102-an+fx.xpi" } ] }