Compare commits

...

50 Commits
1.9 ... master

Author SHA1 Message Date
kkapsner 4f366ed86c
New translations 2024-04-17 00:35:54 +02:00
kkapsner 00e60074c3 Don't throw `target.apply is not a function`
For #705
2024-04-17 00:34:19 +02:00
kkapsner 3eedc7b7dc Only check for prototype loops when there is a prototype
For #705
2024-04-17 00:07:16 +02:00
kkapsner bebcec2139 Version 1.11 2024-04-16 14:53:11 +02:00
kkapsner 5181a55071 change "Site specific" to "Site-specific" 2024-04-10 16:06:56 +02:00
kkapsner a8e192fa9b change "non persistent" to "nonpersistent"
For #696
2024-04-09 14:04:51 +02:00
kkapsner 0f3141ee12
New translations
For #696
2024-04-09 14:03:06 +02:00
kkapsner e9ce4668fe
New translations 2024-04-09 14:01:35 +02:00
kkapsner acce01bfeb Mark default value in drop downs settings
For #696
2024-04-08 00:15:55 +02:00
kkapsner d159769997 Added :changed tag
For #696
2024-04-08 00:12:46 +02:00
kkapsner 56401048d1 Added tag search 2024-04-08 00:09:37 +02:00
kkapsner 54c625cd26 Fix function tampering detection via prototype
For #619 and #685
2024-04-08 00:05:50 +02:00
kkapsner 7bb3f00b45 Update releaseNotes.txt 2024-04-08 00:04:53 +02:00
kkapsner b8c6115603 Not using proxy for toString broke google
For #698, #699, #700, #701
2024-04-07 23:59:49 +02:00
kkapsner dacc578e12 Alpha versions must not break with patches 2024-04-07 02:36:20 +02:00
kkapsner 825fa42141 Fix isPointInPath and isPointInStroke
Fixes #696
2024-04-07 01:53:01 +02:00
kkapsner 40a8012ab0 Version 1.10.1 2024-04-04 23:30:20 +02:00
kkapsner ec95cbe11b Bump min version to 100
to avoid warnings in the upload process
2024-03-30 17:27:30 +01:00
kkapsner 36b54f3ab5 Update navigator test to include storage.quota 2024-03-30 13:58:09 +01:00
kkapsner 87790c9731 Remove facebook.com from the convenience preset
Fixes #563
2024-03-30 13:54:47 +01:00
kkapsner 200f6b31f3 Do not use proxy for Function.prototype.toString
Fixes #685
2024-03-29 16:37:07 +01:00
kkapsner 1d8bf95926 Added protection for navigator.storage.estimate()
Fixes #681
2024-03-28 16:53:01 +01:00
kkapsner c6cf48c489 Display version
Fixes #687
2024-03-28 14:43:53 +01:00
kkapsner 9a3745b366 Whitelist also data URL blocking
Fixes #665
2024-03-28 14:40:08 +01:00
kkapsner a18e3ba37d Disable cache when reloading in the browser action 2024-03-28 14:26:20 +01:00
kkapsner 645d0ac550 dictionary update 2024-03-28 14:23:31 +01:00
kkapsner 809c1270c5
New translations 2024-03-28 14:21:13 +01:00
kkapsner a99a0615d0 Update dev dependencies 2024-03-28 14:20:01 +01:00
kkapsner bc13a5e2a2 Fix typos 2024-03-28 14:18:37 +01:00
kkapsner 8176ac83dc
New translations
* New Spanish translations
* New German translations
* New Portuguese translations
* New Russian translations
* New Portuguese (Brazilian) translations
2024-03-28 14:07:25 +01:00
kkapsner 4a2079bf47 Add alpha version to updates.json during build 2024-02-17 00:07:11 +01:00
kkapsner 7229133c8d Update build tool for manifest version v3 2024-02-17 00:02:10 +01:00
kkapsner 8bdedfcb3d Update package-lock.json 2024-02-16 23:48:34 +01:00
kkapsner ae40caed09 Update package-lock.json 2023-07-19 01:22:11 +02:00
kkapsner 053ae6725e remove crowdin.yml from build 2023-05-30 19:04:40 +02:00
kkapsner 2a6c564ed8 Remove usage of deprecated browser.extension.getURL 2023-05-30 19:04:02 +02:00
kkapsner 8a84dd09f3
New translations
Lithuanian
2023-05-30 13:50:52 +02:00
kkapsner df039b0f3c Do not use UTC for alpha version 2023-05-30 13:48:25 +02:00
kkapsner fc5cce23ea Increase bottom padding of options page 2023-05-30 13:42:30 +02:00
kkapsner e9f5f710e6 Replace window.open with browser.tabs.create
Fixes #661
2023-05-30 00:20:54 +02:00
kkapsner 5df98e0cf5 Settings export page did not show whole content in Firefox for Android 2023-05-30 00:11:43 +02:00
kkapsner 6ea89b6318 Improve isMobile
Fixes #658
2023-05-29 21:41:42 +02:00
kkapsner 02dfa8bd1b browser.windows.onRemoved not available on Fenix
Fix #654
2023-05-29 21:39:02 +02:00
kkapsner 8dcfac442f Added eBay and facebook.com to the convenience preset
Fixes #563
2023-05-29 14:48:56 +02:00
kkapsner 27d8d61da6 Update release notes
For #656
2023-05-29 14:44:36 +02:00
kkapsner fb1311a842 Added showPresetsOnInstallation
Fixes #656
2023-05-29 14:05:03 +02:00
kkapsner 114b109340 Enable multiple alpha versions per day 2023-04-19 14:48:47 +02:00
kkapsner 4ce2f98b10 Fix alpha version 2023-04-19 14:48:23 +02:00
kkapsner 2c5b00a55d Always protect about:blank
Fixes #652
2023-04-19 14:34:37 +02:00
kkapsner d6916b013e Version 1.10 2023-04-19 14:24:41 +02:00
48 changed files with 5132 additions and 1479 deletions

View File

@ -14,11 +14,53 @@ const args = yargs
const fs = require("fs");
function getAlphaVersion(manifest){
const versionsPath = path.join(__dirname, "..", "versions");
function getXPIFileName(id, version){
"use strict";
return `${id}-${version}.xpi`;
}
async function addAlphaVersionToUpdatesJSON(version){
"use strict";
const updatesPath = path.join(versionsPath, "updates.json");
const data = JSON.parse(await fs.promises.readFile(updatesPath));
const versions = data.addons["CanvasBlocker-Beta@kkapsner.de"].updates;
if (versions.some(function(entry){
return entry.version === version;
})){
return;
}
versions.push({
version,
update_link: `https://canvasblocker.kkapsner.de/versions/${getXPIFileName("canvasblocker_beta", version)}`
});
await fs.promises.writeFile(updatesPath, JSON.stringify(data, undefined, "\t"));
}
async function getAlphaVersion(manifest){
"use strict";
function f(n){
if (n < 10) return "0" + n.toString(10);
return n.toString(10);
}
const now = new Date();
const date = now.toISOString().substring(0, 10).replace(/-/g, "");
return manifest.version.replace(/^([\d.]+).*$/, "$1Alpha" + date);
const date = `${now.getFullYear()}${f(now.getMonth() + 1)}${f(now.getDate())}`;
const versionParts = manifest.version.split(".");
while (versionParts.length > 2){
versionParts.pop();
}
const baseVersion = `${versionParts.join(".")}.${date}`;
if (!fs.existsSync(path.join(versionsPath, getXPIFileName("canvasblocker_beta", baseVersion)))){
return baseVersion;
}
let dayTry = 1;
while (fs.existsSync(path.join(versionsPath, getXPIFileName("canvasblocker_beta", `${baseVersion}.${dayTry}`)))){
dayTry += 1;
}
return `${baseVersion}.${dayTry}`;
}
function getRCVersion(manifest){
"use strict";
@ -37,15 +79,22 @@ async function run(){
const manifest = require(manifestPath);
if (args.type === "alpha" || args.type === "rc"){
manifest.name = "CanvasBlocker-Beta";
manifest.browser_specific_settings.gecko.id = "CanvasBlocker-Beta@kkapsner.de";
["gecko", "gecko_android"].forEach(function(browserType){
if (!manifest.browser_specific_settings[browserType]) return;
manifest.browser_specific_settings[browserType].id = "CanvasBlocker-Beta@kkapsner.de";
});
}
else {
manifest.name = "CanvasBlocker";
manifest.browser_specific_settings.gecko.id = "CanvasBlocker@kkapsner.de";
delete manifest.browser_specific_settings.gecko.update_url;
["gecko", "gecko_android"].forEach(function(browserType){
if (!manifest.browser_specific_settings[browserType]) return;
manifest.browser_specific_settings[browserType].id = "CanvasBlocker@kkapsner.de";
delete manifest.browser_specific_settings[browserType].update_url;
});
}
if (args.type === "alpha"){
manifest.version = getAlphaVersion(manifest);
manifest.version = await getAlphaVersion(manifest);
addAlphaVersionToUpdatesJSON(manifest.version);
}
else if (args.type === "rc"){
manifest.version = getRCVersion(manifest);
@ -64,6 +113,8 @@ async function run(){
"--ignore-files",
"versions",
"--ignore-files",
"crowdin.yml",
"--ignore-files",
"package*"
];
const child = child_process.spawn("web-ext", childArgs, {stdio: "inherit"});

View File

@ -7,6 +7,7 @@
"Blockiermodus",
"canvasblocker",
"Captcha",
"checkmark",
"collapser",
"Coord",
"darkgreen",

2
.vscode/tasks.json vendored
View File

@ -154,6 +154,8 @@
"--ignore-files",
"versions",
"--ignore-files",
"crowdin.yml",
"--ignore-files",
"package*"
],
"presentation": {

View File

@ -103,6 +103,10 @@
"message": "Otevřít v samostatném panelu",
"description": ""
},
"labelForDefaultOption": {
"message": " (default)",
"description": ""
},
"group_general": {
"message": "Obecné",
"description": ""
@ -1556,7 +1560,7 @@
"description": ""
},
"sanitation_resolution.switchToNonPersistentRng": {
"message": "switch to \"non persistent\" rng",
"message": "switch to \"nonpersistent\" rng",
"description": ""
},
"sanitation_error.fakeEverythingInCanvas": {

View File

@ -4,7 +4,7 @@
"description": ""
},
"addon_description": {
"message": "Verändert einige JS-APIs um Fingerprinting zu verhindern.",
"message": "Verändert einige JS-APIs, um Fingerprinting zu verhindern.",
"description": ""
},
"browserAction_title_default": {
@ -72,7 +72,7 @@
"description": ""
},
"options_title": {
"message": "CanvasBlocker Einstellungen",
"message": "CanvasBlocker-Einstellungen",
"description": ""
},
"optionsIntroduction": {
@ -103,6 +103,10 @@
"message": "In separatem Tab öffnen",
"description": ""
},
"labelForDefaultOption": {
"message": " (Standard)",
"description": ""
},
"group_general": {
"message": "Allgemein",
"description": ""
@ -112,7 +116,7 @@
"description": ""
},
"group_misc": {
"message": "Vermischtes",
"message": "Sonstiges",
"description": ""
},
"section_asking": {
@ -132,7 +136,7 @@
"description": ""
},
"section_misc": {
"message": "Vermischtes",
"message": "Sonstiges",
"description": ""
},
"section_settings": {
@ -504,7 +508,7 @@
"description": ""
},
"rng_description": {
"message": "nichts (komplett weiß): es wird immer ein weißes Bild zurückgegeben. Hierbei sollte die Option \"Alpha-Kanal auch vortäuschen\" aktiviert werden. ACHTUNG: Nicht im Modus \"Bei Ausgabe vortäuschen\" verwenden.\n\nnicht persistent: die Zufallszahlen werden bei jeder Vortäuschaktion neu bestimmt. Beachten Sie, dass für viele APIs ein Zwischenspeicher verwendet wird, um eine Detektion zu verhindern.\n\nkonstant: Variante von nicht persistent. Wenn die Daten eines Canvas verändert werden, haben gleichfarbige Pixel danach auch die gleiche Farbe.\n\npersistent: für jede Domain werden die Zufallszahlen nur einmal bestimmt.",
"message": "nichts (komplett weiß): es wird immer ein weißes Bild zurückgegeben. Hierbei sollte die Option \"Alpha-Kanal auch vortäuschen\" aktiviert werden. ACHTUNG: Nicht im Modus \"Bei Ausgabe vortäuschen\" verwenden.\n\nnichtpersistent: die Zufallszahlen werden bei jeder Vortäuschaktion neu bestimmt. Beachten Sie, dass für viele APIs ein Zwischenspeicher verwendet wird, um eine Detektion zu verhindern.\n\nkonstant: Variante von nichtpersistent. Wenn die Daten eines Canvas verändert werden, haben gleichfarbige Pixel danach auch die gleiche Farbe.\n\npersistent: für jede Domain werden die Zufallszahlen nur einmal bestimmt.",
"description": ""
},
"rng_options.persistent": {
@ -516,7 +520,7 @@
"description": ""
},
"rng_options.nonPersistent": {
"message": "nicht persistent",
"message": "nichtpersistent",
"description": ""
},
"rng_options.white": {
@ -1556,7 +1560,7 @@
"description": ""
},
"sanitation_resolution.switchToNonPersistentRng": {
"message": "wechsle zu \"nicht persistent\"",
"message": "wechsle zu \"nichtpersistent\"",
"description": ""
},
"sanitation_error.fakeEverythingInCanvas": {

View File

@ -109,6 +109,11 @@
"description": ""
},
"labelForDefaultOption": {
"message": " (default)",
"description": ""
},
"group_general": {
"message": "General",
"description": ""
@ -374,7 +379,7 @@
"description": ""
},
"askOnlyOnce_description": {
"message": "When CanvasBlocker's block mode is set to 'ask permission' or 'ask permission for readout API', a confirm message will appear every time a page tries to access the API or readout API. This setting tries to display the confirm message only once for each page regardless of how many times the page tries to access the API. Nevertheless, multiple confirm messages may still be displayed on some pages.\n\nNo: asking every time\n\nIndividual: each API-type (context, input, readout) has to be confirmed separately\n\ncombined: all API-types get confirmed together",
"message": "When CanvasBlocker's block mode is set to 'ask permission' or 'ask permission for readout API', a confirm message will appear every time a page tries to access the API or readout API. This setting tries to display the confirm message only once for each page regardless of how many times the page tries to access the API. Nevertheless, multiple confirm messages may still be displayed on some pages.\n\nNo: asking every time\n\nIndividual: each API type (context, input, readout) has to be confirmed separately\n\nCombined: all API types get confirmed together",
"description": ""
},
"askOnlyOnce_options.no": {
@ -495,7 +500,7 @@
},
"urlSettings_title": {
"message": "Site specific values",
"message": "Site-specific values",
"description": ""
},
"urlSettings_description": {
@ -527,7 +532,7 @@
},
"rng_description": {
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnon persistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of non persistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnonpersistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of nonpersistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"description": ""
},
"rng_options.persistent": {
@ -539,7 +544,7 @@
"description": ""
},
"rng_options.nonPersistent": {
"message": "non persistent",
"message": "nonpersistent",
"description": ""
},
"rng_options.white": {
@ -1621,7 +1626,7 @@
"description": ""
},
"sanitation_resolution.switchToNonPersistentRng": {
"message": "switch to \"non persistent\" rng",
"message": "switch to \"nonpersistent\" rng",
"description": ""
},
"sanitation_error.fakeEverythingInCanvas": {

View File

@ -80,7 +80,7 @@
"description": ""
},
"installNotice": {
"message": "Se ha instalado CanvasBlocker. Si quieres poder acceder a está página más adelante, añádela a los marcadores.",
"message": "Se ha instalado CanvasBlocker. Si quiere poder acceder a está página más adelante, añádala a los marcadores.",
"description": ""
},
"updateNotice": {
@ -103,12 +103,16 @@
"message": "Abrir en una pestaña separada",
"description": ""
},
"labelForDefaultOption": {
"message": " (default)",
"description": ""
},
"group_general": {
"message": "General",
"description": ""
},
"group_APIs": {
"message": "APIs",
"message": "API",
"description": ""
},
"group_misc": {
@ -224,39 +228,39 @@
"description": ""
},
"askForInvisiblePermission": {
"message": "¿Quieres permitir los <canvas> invisibles?",
"message": "¿Quiere permitir los <canvas> invisibles?",
"description": ""
},
"askForInvisibleInputPermission": {
"message": "¿Quieres permitir la entrada para los <canvas> invisibles?",
"message": "¿Quiere permitir la entrada para los <canvas> invisibles?",
"description": ""
},
"askForInvisibleReadoutPermission": {
"message": "¿Quieres permitir la lectura para los <canvas> invisibles?",
"message": "¿Quiere permitir la lectura para los <canvas> invisibles?",
"description": ""
},
"askForPermission": {
"message": "¿Quieres permitir los <canvas>?",
"message": "¿Quiere permitir los <canvas>?",
"description": ""
},
"askForInputPermission": {
"message": "¿Quieres permitir la entrada para los <canvas>?",
"message": "¿Quiere permitir la entrada para los <canvas>?",
"description": ""
},
"askForReadoutPermission": {
"message": "¿Quieres permitir la lectura para los <canvas>?",
"message": "¿Quiere permitir la lectura para los <canvas>?",
"description": ""
},
"askForVisiblePermission": {
"message": "¿Quieres permitir los <canvas> con borde rojo?",
"message": "¿Quiere permitir los <canvas> con borde rojo?",
"description": ""
},
"askForVisibleInputPermission": {
"message": "¿Quieres permitir la entrada para los <canvas> con borde rojo?",
"message": "¿Quiere permitir la entrada para los <canvas> con borde rojo?",
"description": ""
},
"askForVisibleReadoutPermission": {
"message": "¿Quieres permitir la lectura de para los <canvas> con borde rojo?",
"message": "¿Quiere permitir la lectura de para los <canvas> con borde rojo?",
"description": ""
},
"askForAudioPermission": {
@ -272,39 +276,39 @@
"description": ""
},
"askForHistoryPermission": {
"message": "¿Quieres permitir la API history?",
"message": "¿Quiere permitir la API de history?",
"description": ""
},
"askForHistoryInputPermission": {
"message": "¿Quieres permitir la entrada para la API history?",
"message": "¿Quiere permitir la entrada para la API de history?",
"description": ""
},
"askForHistoryReadoutPermission": {
"message": "¿Quieres permitir la lectura para la API history?",
"message": "¿Quiere permitir la lectura para la API de history?",
"description": ""
},
"askForWindowPermission": {
"message": "¿Quieres permitir la API window?",
"message": "¿Quiere permitir la API de window?",
"description": ""
},
"askForWindowInputPermission": {
"message": "¿Quieres permitir la entrada para la API window?",
"message": "¿Quiere permitir la entrada para la API de window?",
"description": ""
},
"askForWindowReadoutPermission": {
"message": "¿Quieres permitir la lectura para la API window?",
"message": "¿Quiere permitir la lectura para la API de window?",
"description": ""
},
"askForDOMRectPermission": {
"message": "¿Quieres permitir la API DOMRect?",
"message": "¿Quiere permitir la API de DOMRect?",
"description": ""
},
"askForDOMRectInputPermission": {
"message": "¿Quieres permitir la entrada para la API DOMRect?",
"message": "¿Quiere permitir la entrada para la API de DOMRect?",
"description": ""
},
"askForDOMRectReadoutPermission": {
"message": "¿Quieres permitir la lectura para la API DOMRect?",
"message": "¿Quiere permitir la lectura para la API de DOMRect?",
"description": ""
},
"askForSVGPermission": {
@ -324,35 +328,35 @@
"description": ""
},
"askForTextMetricsInputPermission": {
"message": "¿Quieres permitir la entrada de la API TextMetrics?",
"message": "¿Quiere permitir la entrada de la API de TextMetrics?",
"description": ""
},
"askForTextMetricsReadoutPermission": {
"message": "¿Quieres permitir la lectura de la API TextMetrics?",
"message": "¿Quiere permitir la lectura de la API de TextMetrics?",
"description": ""
},
"askForNavigatorPermission": {
"message": "¿Quieres permitir la API navigator?",
"message": "¿Quiere permitir la API de navigator?",
"description": ""
},
"askForNavigatorInputPermission": {
"message": "¿Quieres permitir la entrada para la API navigator?",
"message": "¿Quiere permitir la entrada para la API de navigator?",
"description": ""
},
"askForNavigatorReadoutPermission": {
"message": "¿Quieres permitir la lectura para la API navigator?",
"message": "¿Quiere permitir la lectura para la API de navigator?",
"description": ""
},
"askForScreenPermission": {
"message": "¿Quieres permitir la API screen?",
"message": "¿Quiere permitir la API de pantalla?",
"description": ""
},
"askForScreenInputPermission": {
"message": "¿Quieres permitir la entrada de la API screen?",
"message": "¿Quiere permitir la entrada de la API de pantalla?",
"description": ""
},
"askForScreenReadoutPermission": {
"message": "¿Quieres permitir la lectura de la API screen?",
"message": "¿Quiere permitir la lectura de la API de pantalla?",
"description": ""
},
"askOnlyOnce_title": {
@ -416,7 +420,7 @@
"description": ""
},
"blockMode_urlSpecific": {
"message": "Para establecer modos de bloqueo individuales para sitios específicos, haz clic en la flecha negra para abrir el menú, añade el dominio o URL haciendo clic en «+» y selecciona el modo de bloqueo deseado.",
"message": "Para establecer modos de bloqueo individuales para sitios específicos, haga clic en la flecha negra para abrir el menú, añada el dominio o URL haciendo clic en «+» y seleccione el modo de bloqueo deseado.",
"description": ""
},
"blockMode_options.allowEverything": {
@ -456,7 +460,7 @@
"description": ""
},
"protectedCanvasPart_urlSpecific": {
"message": "Para proteger partes concretas de sitios web específicos, haz clic en la flecha negra para abrir el menú, añade el dominio o URL haciendo clic en «+» y selecciona la parte deseada.",
"message": "Para proteger partes concretas de sitios web específicos, haga clic en la flecha negra para abrir el menú, añada el dominio o URL haciendo clic en «+» y seleccione la parte deseada.",
"description": ""
},
"protectedCanvasPart_options.nothing": {
@ -496,7 +500,7 @@
"description": ""
},
"maxFakeSize_description": {
"message": "Los «canvas» con un área mayor que este número no se falsean (ingresa un cero para deshabilitarlo). Es un parámetro de rendimiento que puede prevenir bloqueos del navegador y debe ajustarse a la potencia de cálculo del dispositivo.\nPRECAUCIÓN: esto reduce la seguridad del complemento, por lo que es muy recomendable no darle un valor menor que 1000000.",
"message": "Los «canvas» con un área mayor que este número no se falsean (introduzca un cero para deshabilitarlo). Es un parámetro de rendimiento que puede prevenir bloqueos del navegador y debe ajustarse a la potencia de cálculo del dispositivo.\nPRECAUCIÓN: esto reduce la seguridad del complemento, por lo que es muy recomendable no darle un valor menor que 1000000.",
"description": ""
},
"maxFakeSize_title": {
@ -504,7 +508,7 @@
"description": ""
},
"rng_description": {
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnon persistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of non persistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnonpersistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of nonpersistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"description": ""
},
"rng_options.persistent": {
@ -604,11 +608,11 @@
"description": ""
},
"sharePersistentRndBetweenDomains_description": {
"message": "PRECAUCIÓN: este configuración hace al navegador 100 % rastreable, y por tanto, una amenaza para tu privacidad.",
"message": "PRECAUCIÓN: este ajuste hace al navegador 100% rastreable y es, por tanto, una amenaza para su privacidad.",
"description": ""
},
"sharePersistentRndBetweenDomains_confirmMessage": {
"message": "¿Seguro que quieres compartir la aleatoriedad persistente entre dominios?\nPRECAUCIÓN: esto hace al navegador 100 % rastreable, y por tanto, una amenaza para tu privacidad.",
"message": "¿Seguro que quiere compartir la aleatoriedad persistente entre dominios?\nPRECAUCIÓN: esto hace al nevegador 100% rastreable y es, por tanto, una amenaza para su privacidad.",
"description": ""
},
"ignoreFrequentColors_title": {
@ -872,7 +876,7 @@
"description": ""
},
"showNotifications_urlSpecific": {
"message": "Para deshabilitar las notificaciones para sitios web específicos, haz clic en la flecha negra para abrir el menú, añade el dominio o URL haciendo clic en «+» y desmarca la casilla.",
"message": "Para desactivar las notificaciones para sitios web específicos, haga clic en la flecha negra para abrir el menú, añada el dominio o URL haciendo clic en «+» y desmarque la casilla.",
"description": ""
},
"showNotifications_title": {
@ -1024,7 +1028,7 @@
"description": ""
},
"protectAudio_urlSpecific": {
"message": "Para excluir sitios web específicos de esta protección, haz clic en la flecha negra para abrir el menú, añade el dominio o URL haciendo clic en «+» y desmarca la casilla.",
"message": "Para excluir sitios web específicos de esta protección, haga clic en la flecha negra para abrir el menú, añada el dominio o URL haciendo clic en «+» y desmarque la casilla.",
"description": ""
},
"audioFakeRate_title": {
@ -1052,15 +1056,15 @@
"description": ""
},
"audioFakeRate_options.0.1%": {
"message": "0.1% de los valores",
"message": "0,1% de los valores",
"description": ""
},
"audioFakeRate_options.1%": {
"message": "1% de los valores",
"message": "1% de los valores",
"description": ""
},
"audioFakeRate_options.10%": {
"message": "10% de los valores",
"message": "10% de los valores",
"description": ""
},
"audioFakeRate_options.100%": {
@ -1132,7 +1136,7 @@
"description": ""
},
"historyLengthThreshold_urlSpecific": {
"message": "Para cambiar este valor para sitios web específicos, haz clic en la flecha negra para abrir el menú, añadir el dominio o URL haciendo clic en «+» y establecer un valor diferente.",
"message": "Para cambiar este valor para sítios web específicos, haga clic en la flecha negra para abrir el menú, añada el dominio o URL haciendo clic en «+» y ponga un valor distinto.",
"description": ""
},
"protectWindow_title": {
@ -1312,7 +1316,7 @@
"description": ""
},
"theme_options.default": {
"message": "por defecto",
"message": "predeterminado",
"description": ""
},
"theme_options.light": {

View File

@ -103,6 +103,10 @@
"message": "Ouvrir dans un onglet séparé",
"description": ""
},
"labelForDefaultOption": {
"message": " (default)",
"description": ""
},
"group_general": {
"message": "Général",
"description": ""
@ -504,7 +508,7 @@
"description": ""
},
"rng_description": {
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnon persistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of non persistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnonpersistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of nonpersistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"description": ""
},
"rng_options.persistent": {

View File

@ -103,6 +103,10 @@
"message": "अलग टैब में खोलें",
"description": ""
},
"labelForDefaultOption": {
"message": " (default)",
"description": ""
},
"group_general": {
"message": "जनरल",
"description": ""
@ -360,7 +364,7 @@
"description": ""
},
"askOnlyOnce_description": {
"message": "When CanvasBlocker's block mode is set to 'ask permission' or 'ask permission for readout API', a confirm message will appear every time a page tries to access the API or readout API. This setting tries to display the confirm message only once for each page regardless of how many times the page tries to access the API. Nevertheless, multiple confirm messages may still be displayed on some pages.\n\nNo: asking every time\n\nIndividual: each API-type (context, input, readout) has to be confirmed separately\n\ncombined: all API-types get confirmed together",
"message": "When CanvasBlocker's block mode is set to 'ask permission' or 'ask permission for readout API', a confirm message will appear every time a page tries to access the API or readout API. This setting tries to display the confirm message only once for each page regardless of how many times the page tries to access the API. Nevertheless, multiple confirm messages may still be displayed on some pages.\n\nNo: asking every time\n\nIndividual: each API type (context, input, readout) has to be confirmed separately\n\nCombined: all API types get confirmed together",
"description": ""
},
"askOnlyOnce_options.no": {
@ -476,7 +480,7 @@
"description": ""
},
"urlSettings_title": {
"message": "Site specific values",
"message": "Site-specific values",
"description": ""
},
"urlSettings_description": {
@ -504,7 +508,7 @@
"description": ""
},
"rng_description": {
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnon persistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of non persistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnonpersistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of nonpersistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"description": ""
},
"rng_options.persistent": {
@ -516,7 +520,7 @@
"description": ""
},
"rng_options.nonPersistent": {
"message": "non persistent",
"message": "nonpersistent",
"description": ""
},
"rng_options.white": {
@ -1556,7 +1560,7 @@
"description": ""
},
"sanitation_resolution.switchToNonPersistentRng": {
"message": "switch to \"non persistent\" rng",
"message": "switch to \"nonpersistent\" rng",
"description": ""
},
"sanitation_error.fakeEverythingInCanvas": {

View File

@ -103,6 +103,10 @@
"message": "Apri in una nuova scheda",
"description": ""
},
"labelForDefaultOption": {
"message": " (default)",
"description": ""
},
"group_general": {
"message": "Generale",
"description": ""

1670
_locales/ja/messages.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -103,6 +103,10 @@
"message": "별도의 탭에서 열기",
"description": ""
},
"labelForDefaultOption": {
"message": " (default)",
"description": ""
},
"group_general": {
"message": "일반 설정",
"description": ""
@ -360,7 +364,7 @@
"description": ""
},
"askOnlyOnce_description": {
"message": "When CanvasBlocker's block mode is set to 'ask permission' or 'ask permission for readout API', a confirm message will appear every time a page tries to access the API or readout API. This setting tries to display the confirm message only once for each page regardless of how many times the page tries to access the API. Nevertheless, multiple confirm messages may still be displayed on some pages.\n\nNo: asking every time\n\nIndividual: each API-type (context, input, readout) has to be confirmed separately\n\ncombined: all API-types get confirmed together",
"message": "When CanvasBlocker's block mode is set to 'ask permission' or 'ask permission for readout API', a confirm message will appear every time a page tries to access the API or readout API. This setting tries to display the confirm message only once for each page regardless of how many times the page tries to access the API. Nevertheless, multiple confirm messages may still be displayed on some pages.\n\nNo: asking every time\n\nIndividual: each API type (context, input, readout) has to be confirmed separately\n\nCombined: all API types get confirmed together",
"description": ""
},
"askOnlyOnce_options.no": {
@ -476,7 +480,7 @@
"description": ""
},
"urlSettings_title": {
"message": "Site specific values",
"message": "Site-specific values",
"description": ""
},
"urlSettings_description": {
@ -504,7 +508,7 @@
"description": ""
},
"rng_description": {
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnon persistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of non persistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnonpersistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of nonpersistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"description": ""
},
"rng_options.persistent": {
@ -516,7 +520,7 @@
"description": ""
},
"rng_options.nonPersistent": {
"message": "non persistent",
"message": "nonpersistent",
"description": ""
},
"rng_options.white": {
@ -1556,7 +1560,7 @@
"description": ""
},
"sanitation_resolution.switchToNonPersistentRng": {
"message": "switch to \"non persistent\" rng",
"message": "switch to \"nonpersistent\" rng",
"description": ""
},
"sanitation_error.fakeEverythingInCanvas": {

1670
_locales/lt/messages.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -103,6 +103,10 @@
"message": "Åpne i egen fane",
"description": ""
},
"labelForDefaultOption": {
"message": " (default)",
"description": ""
},
"group_general": {
"message": "Generelt",
"description": ""
@ -476,7 +480,7 @@
"description": ""
},
"urlSettings_title": {
"message": "Site specific values",
"message": "Site-specific values",
"description": ""
},
"urlSettings_description": {
@ -504,7 +508,7 @@
"description": ""
},
"rng_description": {
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnon persistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of non persistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnonpersistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of nonpersistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"description": ""
},
"rng_options.persistent": {
@ -516,7 +520,7 @@
"description": ""
},
"rng_options.nonPersistent": {
"message": "non persistent",
"message": "nonpersistent",
"description": ""
},
"rng_options.white": {
@ -1556,7 +1560,7 @@
"description": ""
},
"sanitation_resolution.switchToNonPersistentRng": {
"message": "switch to \"non persistent\" rng",
"message": "switch to \"nonpersistent\" rng",
"description": ""
},
"sanitation_error.fakeEverythingInCanvas": {

View File

@ -96,13 +96,17 @@
"description": ""
},
"settingsNotice.dom.webAudio.enabled": {
"message": "You have dom.webAudio.enabled disabled. This makes you more trackable as very few people do this.",
"message": "Masz wyłączone dom.webAudio.enabled. Z tego powodu twoja aktywność jest łatwiejsza do namierzenia, bo nie wiele osób ma tę opcję włączoną.",
"description": ""
},
"openInTab": {
"message": "Otwórz w nowej karcie",
"description": ""
},
"labelForDefaultOption": {
"message": " (default)",
"description": ""
},
"group_general": {
"message": "Ogólne",
"description": ""
@ -504,7 +508,7 @@
"description": ""
},
"rng_description": {
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnon persistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of non persistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnonpersistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of nonpersistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"description": ""
},
"rng_options.persistent": {
@ -1556,7 +1560,7 @@
"description": ""
},
"sanitation_resolution.switchToNonPersistentRng": {
"message": "switch to \"non persistent\" rng",
"message": "switch to \"nonpersistent\" rng",
"description": ""
},
"sanitation_error.fakeEverythingInCanvas": {

View File

@ -24,11 +24,11 @@
"description": ""
},
"browserAction_status_on": {
"message": "CanvasBlocker on",
"message": "CanvasBlocker ligado",
"description": ""
},
"browserAction_status_off": {
"message": "CanvasBlocker off",
"message": "CanvasBlocker desligado",
"description": ""
},
"more": {
@ -76,15 +76,15 @@
"description": ""
},
"optionsIntroduction": {
"message": "Nesta página você pode ajustar as configurações do CanvasBlocker.",
"message": "Nesta página pode ajustar as configurações do CanvasBlocker.",
"description": ""
},
"installNotice": {
"message": "CanvasBlocker foi instalado. Se quiser aceder esta página futuramente, por favor, adicione-a aos marcadores.",
"message": "CanvasBlocker foi instalado. Se quiser aceder esta página no futuro, por favor, adicione-a aos marcadores.",
"description": ""
},
"updateNotice": {
"message": "CanvasBlocker foi atualizado. Se quiser ser aceder esta página futuramente e ainda não a adicionou aos marcadores, por favor adicione-a.",
"message": "CanvasBlocker foi atualizado. Se quiser aceder a esta página no futuro e ainda não a adicionou aos marcadores, por favor adicione-a.",
"description": ""
},
"dontShowOptionsOnUpdate": {
@ -96,11 +96,15 @@
"description": ""
},
"settingsNotice.dom.webAudio.enabled": {
"message": "You have dom.webAudio.enabled disabled. This makes you more trackable as very few people do this.",
"message": "Tem o dom.webAudio.enabled desligado. Isto torna-o mais rastreável já que poucas pessoas o fazem.",
"description": ""
},
"openInTab": {
"message": "Abrir num noutro separador",
"message": "Abrir noutro separador",
"description": ""
},
"labelForDefaultOption": {
"message": " (padrão)",
"description": ""
},
"group_general": {
@ -192,23 +196,23 @@
"description": ""
},
"disruptSessionOnUpdate_title": {
"message": "Disrupt session on update",
"message": "Interromper sessão ao atualizar",
"description": ""
},
"disruptSessionOnUpdate_description": {
"message": "If set to true the extension will update as soon as the update is available. This might break some tabs that are currently open.",
"message": "Se definido para verdadeiro, a extensão irá atualizar mal a atualização estiver disponível. Isto pode quebrar algumas janelas que estão abertas de momento.",
"description": ""
},
"reloadExtension_title": {
"message": "Reload extension",
"message": "Recarregar extensão",
"description": ""
},
"reloadExtension_description": {
"message": "Perform a pending update.",
"message": "Executar uma atualização pendente.",
"description": ""
},
"reloadExtension_label": {
"message": "Reload",
"message": "Recarregar",
"description": ""
},
"hideSetting": {
@ -308,15 +312,15 @@
"description": ""
},
"askForSVGPermission": {
"message": "Do you want to allow the SVG API?",
"message": "Quer permitir o SVG API?",
"description": ""
},
"askForSVGInputPermission": {
"message": "Do you want to allow SVG API input?",
"message": "Quer permitir a entrada da API de SVG?",
"description": ""
},
"askForSVGReadoutPermission": {
"message": "Do you want to allow SVG API readout?",
"message": "Quer permitir a leitura da API de SVG?",
"description": ""
},
"askForTextMetricsPermission": {
@ -504,7 +508,7 @@
"description": ""
},
"rng_description": {
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnon persistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of non persistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"message": "nenhum (completamente branco): uma imagem completamente branca é devolvida. A opção “Falsifique o canal alfa” deve ser ativada com isso. CUIDADO: Não use isso com o modo \"falsificar na entrada\".\n\nnão persistente: os números aleatórios serão determinados no momento para cada ação de falsificação. Lembre-se de que muitas proteções de API possuem caches para evitar detecção.\n\nconstante: variação de não persistente. Mas ao alterar os dados do ecrã, os pixels da mesma cor também compartilham a mesma cor posteriormente.\n\npersistente: o número aleatório será determinado apenas uma vez para cada domínio.",
"description": ""
},
"rng_options.persistent": {
@ -640,7 +644,7 @@
"description": ""
},
"webGLVendor_description": {
"message": "Value to be reported in the webGL function \"getParameter\" for the \"vendor\". Special values:\nLeave empty to use the original value\n\n{undefined}: returns undefined (#508)\n\n{false}: returns the boolean value false (#508)\n\n{empty}: returns an empty string (#508)\n\n{disabled}: returns null (#508)\n\n{random vendor}: returns a random vendor from the built-in list (#493)\n\n{random renderer}: returns a random renderer from the built-in list (#493)\n\n<xxx|yyy|zzz>: picks one of the given options xxx, yyy or zzz at random (arbitrary number of options) (#493)",
"message": "Valor a ser informado na função webGL \"getParameter\" para o \"fornecedor\". Valores especiais:\nDeixe em branco para usar o valor original\n\n{undefined}: devolve indefinido (#508)\n\n{false}: devolve o valor booleano falso (#508)\n\n{empty}: devolve uma string vazia (#508)\n\n{disabled}: devolve nulo (#508)\n\n{random vendor}: devolve um fornecedor aleatório da lista interna (#493)\n\n{random renderer}: devolve um renderizador aleatório da lista interna (#493)\n\n<xxx|yyy|zzz>: escolhe uma das opções fornecidas xxx, yyy ou zzz aleatoriamente (número arbitrário de opções) (#493)",
"description": ""
},
"webGLRenderer_title": {
@ -648,7 +652,7 @@
"description": ""
},
"webGLRenderer_description": {
"message": "Value to be reported in the webGL function \"getParameter\" for the \"renderer\". Special values:\nLeave empty to use the original value\n\n{undefined}: returns undefined (#508)\n\n{false}: returns the boolean value false (#508)\n\n{empty}: returns an empty string (#508)\n\n{disabled}: returns null (#508)\n\n{random vendor}: returns a random vendor from the built-in list (#493)\n\n{random renderer}: returns a random renderer from the built-in list (#493)\n\n<xxx|yyy|zzz>: picks one of the given options xxx, yyy or zzz at random (arbitrary number of options) (#493)",
"message": "Valor a ser informado na função webGL \"getParameter\" para o \"renderer\". Valores especiais:\nDeixe em branco para usar o valor original\n\n{undefined}: devolve indefinido (#508)\n\n{false}: devolve o valor booleano falso (#508)\n\n{empty}: devolve uma string vazia (#508)\n\n{disabled}: devolve nulo (#508)\n\n{random vendor}: devolve um fornecedor aleatório da lista interna (#493)\n\n{random renderer}: devolve um renderizador aleatório da lista interna (#493)\n\n<xxx|yyy|zzz>: escolhe uma das opções fornecidas xxx, yyy ou zzz aleatoriamente (número arbitrário de opções) (#493)",
"description": ""
},
"webGLUnmaskedVendor_title": {
@ -656,7 +660,7 @@
"description": ""
},
"webGLUnmaskedVendor_description": {
"message": "Value to be reported in the webGL function \"getParameter\" for the \"unmasked vendor\". Special values:\nLeave empty to use the original value\n\n{undefined}: returns undefined (#508)\n\n{false}: returns the boolean value false (#508)\n\n{empty}: returns an empty string (#508)\n\n{disabled}: returns null (#508)\n\n{random vendor}: returns a random vendor from the built-in list (#493)\n\n{random renderer}: returns a random renderer from the built-in list (#493)\n\n<xxx|yyy|zzz>: picks one of the given options xxx, yyy or zzz at random (arbitrary number of options) (#493)",
"message": "Valor a ser informado na função webGL \"getParameter\" para o \"fornecedor desmascarado\". Valores especiais:\nDeixe em branco para usar o valor original\n\n{undefined}: devolve indefinido (#508)\n\n{false}: devolve o valor booleano falso (#508)\n\n{empty}: devolve uma string vazia (#508)\n\n{disabled}: devolve nulo (#508)\n\n{random vendor}: devolve um fornecedor aleatório da lista interna (#493)\n\n{random renderer}: devolve um renderizador aleatório da lista interna (#493)\n\n<xxx|yyy|zzz>: escolhe uma das opções fornecidas xxx, yyy ou zzz aleatoriamente (número arbitrário de opções) (#493)",
"description": ""
},
"webGLUnmaskedRenderer_title": {
@ -664,7 +668,7 @@
"description": ""
},
"webGLUnmaskedRenderer_description": {
"message": "Value to be reported in the webGL function \"getParameter\" for the \"unmasked renderer\". Special values:\nLeave empty to use the original value\n\n{undefined}: returns undefined (#508)\n\n{false}: returns the boolean value false (#508)\n\n{empty}: returns an empty string (#508)\n\n{disabled}: returns null (#508)\n\n{random vendor}: returns a random vendor from the built-in list (#493)\n\n{random renderer}: returns a random renderer from the built-in list (#493)\n\n<xxx|yyy|zzz>: picks one of the given options xxx, yyy or zzz at random (arbitrary number of options) (#493)",
"message": "Valor a ser informado na função webGL \"getParameter\" para o \"renderizador desmascarado\". Valores especiais:\nDeixe em branco para usar o valor original\n\n{undefined}: devolve indefinido (#508)\n\n{false}: devolve o valor booleano falso (#508)\n\n{empty}: devolve uma string vazia (#508)\n\n{disabled}: devolve nulo (#508)\n\n{random vendor}: devolve um fornecedor aleatório da lista interna (#493)\n\n{random renderer}: devolve um renderizador aleatório da lista interna (#493)\n\n<xxx|yyy|zzz>: escolhe uma das opções fornecidas xxx, yyy ou zzz aleatoriamente (número arbitrário de opções) (#493)",
"description": ""
},
"useCanvasCache_title": {
@ -736,7 +740,7 @@
"description": ""
},
"fakedSVGReadout": {
"message": "Faked SVG readout on {url}",
"message": "Leitura falsa de SVG em {url}",
"description": ""
},
"fakedTextMetricsReadout": {
@ -836,7 +840,7 @@
"description": ""
},
"selectWhitelistType": {
"message": "What is the type of the whitelisting?",
"message": "Qual é o tipo de lista branca?",
"description": ""
},
"whitelistOnlyAPI": {
@ -1184,15 +1188,15 @@
"description": ""
},
"protectSVG_title": {
"message": "Protect SVG API",
"message": "Proteger a API de SVG",
"description": ""
},
"protectSVG_description": {
"message": "This protects against fingerprinting using SVGs.",
"message": "Isso protege contra o fingerprinting usando SVGs.",
"description": ""
},
"protectSVG_urlSpecific": {
"message": "To exclude specific websites from this protection, click on the black arrow to open the menu, add the domain or URL by clicking on \"+\" and remove its checkmark.",
"message": "Para excluir sites específicos desta proteção, clique na seta preta para abrir o menu, adicione o domínio ou URL clicando em \"+\" e remova sua caixa de seleção.",
"description": ""
},
"protectTextMetrics_title": {
@ -1600,7 +1604,7 @@
"description": ""
},
"whitelist_inspection_description": {
"message": "Shows which API protections are active for a given site. If you remove a checkmark for an API this API will be not protected for the selected site.",
"message": "Mostra que proteções de API estão ativas para um determinado site. Se remover uma marca de seleção para uma API, esta API não será protegida para o site selecionado.",
"description": ""
},
"whitelist_all_apis": {

View File

@ -4,7 +4,7 @@
"description": ""
},
"addon_description": {
"message": "Altera algumas APIs JS para impedir fingerprinting.",
"message": "Altera algumas APIs JS para impedir impressões digitais.",
"description": ""
},
"browserAction_title_default": {
@ -88,21 +88,25 @@
"description": ""
},
"dontShowOptionsOnUpdate": {
"message": "Não mostrar novamente após a atualização.",
"message": "Não mostrar novamente após atualizações.",
"description": ""
},
"resistFingerprintingNotice": {
"message": "Você tem privacy.resistFingerprinting ativo. Isso muda ligeiramente o comportamento do CanvasBlocker. Veja mais informações {link:aqui:https://github.com/kkapsner/CanvasBlocker/issues/158} e {link:aqui:https://github.com/ghacksuserjs/ghacks-user.js/issues/767}.",
"message": "Você tem privacy.resistFingerprinting ativado. Isso muda ligeiramente o comportamento do CanvasBlocker. Veja mais informações {link:aqui:https://github.com/kkapsner/CanvasBlocker/issues/158} e {link:aqui:https://github.com/ghacksuserjs/ghacks-user.js/issues/767}.",
"description": ""
},
"settingsNotice.dom.webAudio.enabled": {
"message": "Sua configuração dom.webAudio.enabled está desativada. Isso lhe torna mais rastreável já que muito poucas pessoas fazem isso.",
"message": "Você tem dom.webAudio.enabled desativado. Isso lhe torna mais rastreável já que muito poucas pessoas fazem isso.",
"description": ""
},
"openInTab": {
"message": "Abrir numa aba separada",
"description": ""
},
"labelForDefaultOption": {
"message": " (default)",
"description": ""
},
"group_general": {
"message": "Geral",
"description": ""
@ -156,7 +160,7 @@
"description": ""
},
"section_DOMRect-api": {
"message": "DOMRect API",
"message": "API DOMRect",
"description": ""
},
"section_SVG-api": {
@ -164,7 +168,7 @@
"description": ""
},
"section_TextMetrics-api": {
"message": "TextMetrics API",
"message": "API TextMetrics",
"description": ""
},
"section_Navigator-api": {
@ -176,7 +180,7 @@
"description": ""
},
"displayAdvancedSettings_title": {
"message": "Modo Expert",
"message": "Modo especialista",
"description": ""
},
"displayAdvancedSettings_description": {
@ -192,11 +196,11 @@
"description": ""
},
"disruptSessionOnUpdate_title": {
"message": "Interromper sessão na atualização",
"message": "Interromper sessão ao atualizar",
"description": ""
},
"disruptSessionOnUpdate_description": {
"message": "Se for definido como verdadeiro, a extensão atualizará o mais cedo o possível quando uma atualização estiver disponível. Isso pode quebrar algumas abas que podem estar abertas.",
"message": "Se definido como verdadeiro, a extensão será atualizada assim que a atualização estiver disponível. Isso pode quebrar algumas abas que podem estar abertas.",
"description": ""
},
"reloadExtension_title": {
@ -212,7 +216,7 @@
"description": ""
},
"hideSetting": {
"message": "Clique aqui para ocultar a configuração.",
"message": "Clique aqui para ocultar esta configuração.",
"description": ""
},
"displayHiddenSettings_title": {
@ -232,7 +236,7 @@
"description": ""
},
"askForInvisibleReadoutPermission": {
"message": "Você quer permitir leitura <canvas> invisível?",
"message": "Você quer permitir leitura invisível de <canvas>?",
"description": ""
},
"askForPermission": {
@ -244,7 +248,7 @@
"description": ""
},
"askForReadoutPermission": {
"message": "Deseja permitir a leitura do <canvas>?",
"message": "Deseja permitir a leitura de <canvas>?",
"description": ""
},
"askForVisiblePermission": {
@ -252,11 +256,11 @@
"description": ""
},
"askForVisibleInputPermission": {
"message": "Deseja permitir entrada nas <canvas> com borda vermelha?",
"message": "Deseja permitir a entrada do <canvas> com borda vermelha?",
"description": ""
},
"askForVisibleReadoutPermission": {
"message": "Deseja permitir a leitura das <canvas> com borda vermelha?",
"message": "Deseja permitir a leitura do <canvas> com borda vermelha?",
"description": ""
},
"askForAudioPermission": {
@ -276,63 +280,63 @@
"description": ""
},
"askForHistoryInputPermission": {
"message": "Deseja permitir a entrada do histórico da API?",
"message": "Deseja permitir a entrada da API de histórico?",
"description": ""
},
"askForHistoryReadoutPermission": {
"message": "Deseja permitir leitura do histórico da API?",
"message": "Deseja permitir a leitura da API de histórico?",
"description": ""
},
"askForWindowPermission": {
"message": "Você deseja permitir a API da janela?",
"message": "Deseja permitir a API de janela?",
"description": ""
},
"askForWindowInputPermission": {
"message": "Você deseja permitir a entrada da API da janela?",
"message": "Deseja permitir a entrada da API de janela?",
"description": ""
},
"askForWindowReadoutPermission": {
"message": "Deseja permitir a leitura da API da janela?",
"message": "Deseja permitir a leitura da API de janela?",
"description": ""
},
"askForDOMRectPermission": {
"message": "Você deseja permitir a API DOMRect?",
"message": "Deseja permitir a API DOMRect?",
"description": ""
},
"askForDOMRectInputPermission": {
"message": "Você deseja permitir a entrada da API DOMRect?",
"message": "Deseja permitir a entrada da API DOMRect?",
"description": ""
},
"askForDOMRectReadoutPermission": {
"message": "Deseja permitir leitura da API DOMRect?",
"message": "Deseja permitir a leitura da API DOMRect?",
"description": ""
},
"askForSVGPermission": {
"message": "Deseja permitir a API de SVG?",
"message": "Deseja permitir a API SVG?",
"description": ""
},
"askForSVGInputPermission": {
"message": "Deseja permitir a entrada da API de SVG?",
"message": "Deseja permitir a entrada da API SVG?",
"description": ""
},
"askForSVGReadoutPermission": {
"message": "Deseja permitir a leitura da API de SVG?",
"message": "Deseja permitir a leitura da API SVG?",
"description": ""
},
"askForTextMetricsPermission": {
"message": "Deseja permitir a API de Métricas de Texto?",
"message": "Deseja permitir a API TextMetrics?",
"description": ""
},
"askForTextMetricsInputPermission": {
"message": "Deseja permitir a entrada da API de Métricas de Texto?",
"message": "Deseja permitir a entrada da API TextMetrics?",
"description": ""
},
"askForTextMetricsReadoutPermission": {
"message": "Deseja permitir leitura da API de Métricas de Texto?",
"message": "Deseja permitir leitura da API TextMetrics?",
"description": ""
},
"askForNavigatorPermission": {
"message": "Deseja permitir a API de navegador?",
"message": "Deseja permitir a API do navegador?",
"description": ""
},
"askForNavigatorInputPermission": {
@ -340,7 +344,7 @@
"description": ""
},
"askForNavigatorReadoutPermission": {
"message": "Deseja permitir leitura da API do navegador?",
"message": "Deseja permitir a leitura da API do navegador?",
"description": ""
},
"askForScreenPermission": {
@ -352,7 +356,7 @@
"description": ""
},
"askForScreenReadoutPermission": {
"message": "Deseja permitir leitura da API de tela?",
"message": "Deseja permitir a leitura da API de tela?",
"description": ""
},
"askOnlyOnce_title": {

View File

@ -103,6 +103,10 @@
"message": "Открыть в отдельной вкладке",
"description": ""
},
"labelForDefaultOption": {
"message": " (default)",
"description": ""
},
"group_general": {
"message": "Основные",
"description": ""
@ -308,15 +312,15 @@
"description": ""
},
"askForSVGPermission": {
"message": "Do you want to allow the SVG API?",
"message": "Разрешить SVG API?",
"description": ""
},
"askForSVGInputPermission": {
"message": "Do you want to allow SVG API input?",
"message": "Вы хотите разрешить SVG API input(ввод)?",
"description": ""
},
"askForSVGReadoutPermission": {
"message": "Do you want to allow SVG API readout?",
"message": "Разрешить SVG API readout(считывание)?",
"description": ""
},
"askForTextMetricsPermission": {
@ -504,7 +508,7 @@
"description": ""
},
"rng_description": {
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnon persistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of non persistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"message": "нет (белый цвет): возвращается полностью белое изображение. Должна быть включена опция \"подделывать альфа-канал\". ВНИМАНИЕ: Не используйте вместе с режимом \"подделка ввода(input)\".\n\nнепостоянный: для каждой подделки случайные числа будут генерироваться заново. Имейте ввиду, что большинство функций защиты API хранят кэш для предотвращения обнаружения.\n\nконстантный: вариация непостоянного. Только при изменении данных в <canvas> сохраняется цвет изменённых пикселей и доступен в дальнейшем.\n\nпостоянный: для каждого домена случайное число генерируется единожды.",
"description": ""
},
"rng_options.persistent": {
@ -736,7 +740,7 @@
"description": ""
},
"fakedSVGReadout": {
"message": "Faked SVG readout on {url}",
"message": "Подделан SVG readout(чтение) на {url}",
"description": ""
},
"fakedTextMetricsReadout": {
@ -1168,7 +1172,7 @@
"description": ""
},
"protectDOMRect_description": {
"message": "Это защищает от снятия отпечатков \"getClientRects()\" и нескольких подобных методов.",
"message": "Защищает от снятия отпечатка \"getClientRects()\" и нескольких подобных методов.",
"description": ""
},
"protectDOMRect_urlSpecific": {
@ -1184,15 +1188,15 @@
"description": ""
},
"protectSVG_title": {
"message": "Protect SVG API",
"message": "Защищать SVG API",
"description": ""
},
"protectSVG_description": {
"message": "This protects against fingerprinting using SVGs.",
"message": "Защищает от снятия отпечатка через SVG.",
"description": ""
},
"protectSVG_urlSpecific": {
"message": "To exclude specific websites from this protection, click on the black arrow to open the menu, add the domain or URL by clicking on \"+\" and remove its checkmark.",
"message": "Чтобы отключить защиту для конкретных сайтов, нажмите на чёрную стрелку открытия меню, добавьте домен или URL нажатием на \"+\" и снимите с него флажок.",
"description": ""
},
"protectTextMetrics_title": {
@ -1200,7 +1204,7 @@
"description": ""
},
"protectTextMetrics_description": {
"message": "Это защищает от считывания отпечатка \"measureText()\", который может быть использован для перекрестной проверки значений DOMRect.",
"message": "Защищает от снятия отпечатка \"measureText()\", который может быть использован для перекрестной проверки значений DOMRect.",
"description": ""
},
"protectTextMetrics_urlSpecific": {
@ -1268,7 +1272,7 @@
"description": ""
},
"protectScreen_description": {
"message": "Это защищает от попыток снятия цифровых отпечатков, включая размер экрана.",
"message": "Защищает от попыток снятия отпечатка на основе таких характеристик, как размер экрана.",
"description": ""
},
"protectScreen_urlSpecific": {

View File

@ -103,6 +103,10 @@
"message": "在新标签页中打开",
"description": ""
},
"labelForDefaultOption": {
"message": " (default)",
"description": ""
},
"group_general": {
"message": "一般",
"description": ""
@ -504,7 +508,7 @@
"description": ""
},
"rng_description": {
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnon persistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of non persistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnonpersistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of nonpersistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"description": ""
},
"rng_options.persistent": {

View File

@ -103,6 +103,10 @@
"message": "在新的隱身標籤頁中打開",
"description": ""
},
"labelForDefaultOption": {
"message": " (default)",
"description": ""
},
"group_general": {
"message": "一般設定",
"description": ""
@ -360,7 +364,7 @@
"description": ""
},
"askOnlyOnce_description": {
"message": "When CanvasBlocker's block mode is set to 'ask permission' or 'ask permission for readout API', a confirm message will appear every time a page tries to access the API or readout API. This setting tries to display the confirm message only once for each page regardless of how many times the page tries to access the API. Nevertheless, multiple confirm messages may still be displayed on some pages.\n\nNo: asking every time\n\nIndividual: each API-type (context, input, readout) has to be confirmed separately\n\ncombined: all API-types get confirmed together",
"message": "When CanvasBlocker's block mode is set to 'ask permission' or 'ask permission for readout API', a confirm message will appear every time a page tries to access the API or readout API. This setting tries to display the confirm message only once for each page regardless of how many times the page tries to access the API. Nevertheless, multiple confirm messages may still be displayed on some pages.\n\nNo: asking every time\n\nIndividual: each API type (context, input, readout) has to be confirmed separately\n\nCombined: all API types get confirmed together",
"description": ""
},
"askOnlyOnce_options.no": {
@ -504,7 +508,7 @@
"description": ""
},
"rng_description": {
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnon persistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of non persistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"message": "none (completely white): a completely white image is returned. The option \"Fake the alpha channel\" should be activated with this. CAUTION: Do not use this with the \"fake at input\" mode.\n\nnonpersistent: the random numbers will be determined freshly for each faking action. Keep in mind that many API protections have caches in place to prevent detection.\n\nconstant: variation of nonpersistent. But when altering canvas data same colored pixels also share the same color afterwards.\n\npersistent: the random number will only be determined once for every domain.",
"description": ""
},
"rng_options.persistent": {
@ -1556,7 +1560,7 @@
"description": ""
},
"sanitation_resolution.switchToNonPersistentRng": {
"message": "switch to \"non persistent\" rng",
"message": "switch to \"nonpersistent\" rng",
"description": ""
},
"sanitation_error.fakeEverythingInCanvas": {

View File

@ -12,6 +12,7 @@
<div id="reload" class="hidden"></div>
</div>
<div id="actions" class="stackedInputs"></div>
<div id="version" class="versionDisplay"></div>
<script src="../lib/require.js"></script>
<script src="../lib/logging.js"></script>
<script src="../lib/extension.js"></script>

View File

@ -25,7 +25,7 @@
const currentURL = new URL(currentTab.url);
const reloadButton = document.getElementById("reload");
reloadButton.addEventListener("click", async function(){
await browser.tabs.reload(currentTab.id);
await browser.tabs.reload(currentTab.id, {bypassCache: true});
window.close();
});
const addonStatus = document.getElementById("addonStatus");
@ -36,6 +36,9 @@
if (settings.get("blockMode").startsWith("allow")){
settings.set("blockMode", "fake", currentURL.host);
}
if (settings.get("blockDataURLs")){
settingContainers.resetUrlValue("blockDataURLs", currentURL);
}
const entries = lists.get("white").filter(e => e.match(currentURL)).map(e => e.value);
await Promise.all([
lists.removeFrom("white", entries),
@ -44,6 +47,9 @@
}
else {
settings.set("blockMode", "allowEverything", currentURL.hostname);
if (settings.get("blockDataURLs")){
settings.set("blockDataURLs", false, currentURL.hostname);
}
}
update();
});
@ -69,7 +75,7 @@
browser.runtime.openOptionsPage();
}
else {
window.open(extension.getURL("options/options.html"), "_blank");
browser.tabs.create({url: extension.getURL("options/options.html")});
}
window.close();
}
@ -78,7 +84,7 @@
label: "faq",
icon: extension.getURL("icons/browserAction-faq.svg"),
action: function(){
window.open("https://canvasblocker.kkapsner.de/faq/", "_blank");
browser.tabs.create({url: "https://canvasblocker.kkapsner.de/faq/"});
window.close();
}
},
@ -87,7 +93,7 @@
advanced: true,
icon: extension.getURL("icons/browserAction-test.svg"),
action: function(){
window.open("https://canvasblocker.kkapsner.de/test", "_blank");
browser.tabs.create({url: "https://canvasblocker.kkapsner.de/test"});
window.close();
}
},
@ -95,7 +101,7 @@
label: "review",
icon: extension.getURL("icons/browserAction-review.svg"),
action: function(){
window.open("https://addons.mozilla.org/firefox/addon/canvasblocker/reviews/", "_blank");
browser.tabs.create({url: "https://addons.mozilla.org/firefox/addon/canvasblocker/reviews/"});
window.close();
}
},
@ -103,7 +109,7 @@
label: "reportIssue",
icon: extension.getURL("icons/browserAction-reportIssue.svg"),
action: function(){
window.open("https://github.com/kkapsner/CanvasBlocker/issues", "_blank");
browser.tabs.create({url: "https://github.com/kkapsner/CanvasBlocker/issues"});
window.close();
}
},
@ -149,13 +155,17 @@
search.addEventListener("keypress", function(event){
if ([10, 13].indexOf(event.keyCode) !== -1){
window.open(extension.getURL(
browser.tabs.create({url: extension.getURL(
"options/options.html" +
"?search=" +
encodeURIComponent(this.value)
));
)});
window.close();
}
});
});
window.addEventListener("load", async function(){
extension.displayVersion("version", 250);
});
}());

View File

@ -52,7 +52,7 @@
logging.message("check url %s for block mode %s", url, blockMode);
switch (url.protocol){
case "about:":
if (url.href === "about:blank"){
if (url.pathname === "blank"){
logging.message("use regular mode on about:blank");
break;
}

View File

@ -73,7 +73,7 @@
};
scope.getURL = function getURL(str){
return (browser.runtime.getURL? browser.runtime.getURL: browser.extension.getURL)(str);
return browser.runtime.getURL(str);
};
scope.extensionID = browserAvailable? scope.getURL(""): "extensionID";
@ -141,43 +141,109 @@
};
const proxies = new Map();
const changedToStrings = new WeakMap();
scope.createProxyFunction = function createProxyFunction(window, original, replacement){
if (!changedToStrings.get(window)){
changedToStrings.set(window, true);
const functionPrototype = scope.getWrapped(window).Function.prototype;
const toString = functionPrototype.toString;
scope.changeProperty(window, "toString", {
object: functionPrototype,
name: "toString",
type: "value",
changed: scope.createProxyFunction(
window,
toString,
function(){
return proxies.get(this) || toString.call(this);
}
)
});
const changedWindowsForProxies = new WeakMap();
function setupWindowForProxies(window){
if (changedWindowsForProxies.get(window)){
return;
}
const handler = scope.getWrapped(window).Object.create(null);
handler.apply = scope.exportFunctionWithName(function(target, thisArgs, args){
const wrappedWindow = scope.getWrapped(window);
const functionPrototype = wrappedWindow.Function.prototype;
const originalToString = functionPrototype.toString;
changedWindowsForProxies.set(window, originalToString);
const alteredToString = scope.createProxyFunction(
window,
originalToString,
function toString(){
if (proxies.has(this)){
return proxies.get(this).string;
}
return originalToString.call(scope.getWrapped(this));
}
);
scope.changeProperty(window, "toString", {
object: functionPrototype,
name: "toString",
type: "value",
changed: alteredToString
});
const wrappedReflect = wrappedWindow.Reflect;
const originalReflectSetPrototypeOf = wrappedReflect.setPrototypeOf;
const alteredReflectSetPrototypeOf = scope.exportFunctionWithName(
function setPrototypeOf(target, prototype){
target = scope.getWrapped(target);
if (proxies.has(target)){
target = proxies.get(target).wrappedOriginal;
}
if (proxies.has(prototype)){
prototype = proxies.get(prototype).wrappedOriginal;
}
if (prototype){
const grandPrototype = wrappedReflect.getPrototypeOf(prototype);
if (proxies.has(grandPrototype)){
const testPrototype = wrappedWindow.Object.create(proxies.get(grandPrototype).wrappedOriginal);
const value = originalReflectSetPrototypeOf.call(wrappedReflect, target, testPrototype);
if (!value){
return false;
}
}
}
const value = originalReflectSetPrototypeOf.call(wrappedReflect, target, scope.getWrapped(prototype));
return value;
}, window, "setPrototypeOf"
);
scope.changeProperty(window, "toString", {
object: wrappedWindow.Reflect,
name: "setPrototypeOf",
type: "value",
changed: alteredReflectSetPrototypeOf
});
}
scope.createProxyFunction = function createProxyFunction(window, original, replacement){
setupWindowForProxies(window);
const wrappedObject = scope.getWrapped(window).Object;
const handler = wrappedObject.create(null);
handler.apply = scope.exportFunctionWithName(function(target, thisArg, args){
try {
return args.length?
replacement.call(thisArgs, ...args):
replacement.call(thisArgs);
replacement.call(thisArg, ...args):
replacement.call(thisArg);
}
catch (error){
try {
return original.apply(thisArgs, args);
return original.apply(thisArg, args);
}
catch (error){
return target.apply(thisArgs, args);
return scope.getWrapped(target).apply(thisArg, args);
}
}
}, window, "");
handler.setPrototypeOf = scope.exportFunctionWithName(function(target, prototype){
target = scope.getWrapped(target);
if (proxies.has(target)){
target = proxies.get(target).wrappedOriginal;
}
if (proxies.has(prototype)){
prototype = proxies.get(prototype).wrappedOriginal;
}
if (prototype){
const grandPrototype = wrappedObject.getPrototypeOf(prototype);
if (proxies.has(grandPrototype)){
const testPrototype = wrappedObject.create(proxies.get(grandPrototype).wrappedOriginal);
wrappedObject.setPrototypeOf(target, testPrototype);
}
}
return wrappedObject.setPrototypeOf(target, scope.getWrapped(prototype));
}, window, "");
const proxy = new window.Proxy(original, handler);
proxies.set(proxy, original.toString());
const proxyData = {
original: original,
wrappedOriginal: scope.getWrapped(original),
string: changedWindowsForProxies.get(window).call(original),
};
proxies.set(proxy, proxyData);
proxies.set(scope.getWrapped(proxy), proxyData);
return scope.getWrapped(proxy);
};
@ -235,5 +301,30 @@
}
};
scope.displayVersion = async function displayVersion(node, displayRefresh = false){
if ("string" === typeof node){
node = document.getElementById(node);
}
if (!node){
throw "display node not found";
}
fetch(scope.getURL("manifest.json")).then(function(response){
return response.json();
}).then(function(manifest){
node.textContent = "Version " + manifest.version;
return manifest.version;
}).catch(function(error){
node.textContent = "Unable to get version: " + error;
});
if (displayRefresh){
// Workaround to hide the scroll bars
window.setTimeout(function(){
node.style.display = "none";
node.style.display = "";
}, displayRefresh);
}
};
Object.seal(scope);
}());

View File

@ -170,8 +170,12 @@
case "install":
logging.message("CanvasBlocker installed");
openOptions(details.reason);
browser.tabs.create({
url: extension.getURL("options/presets.html?notice=" + details.reason)
settings.onloaded(function(){
if (settings.showPresetsOnInstallation){
browser.tabs.create({
url: extension.getURL("options/presets.html?notice=" + details.reason)
});
}
});
break;
case "update":

View File

@ -16,6 +16,10 @@
const settingDefinitions = require("./settingDefinitions");
scope.isMobile = async function isMobile(){
const platformInfo = await browser.runtime.getPlatformInfo();
if (platformInfo && platformInfo.os === "android"){
return true;
}
// todo: proper mobile check (e.g. over browser.runtime.getBrowserInfo()) and no feature check
return !browser.pageAction ||
!browser.pageAction.show ||

View File

@ -427,7 +427,7 @@
return getIsPointValue({
func: (x, y) => original.call(this, x, y, args[2]),
x, y,
index: x + this.width * y,
index: x + this.canvas.width * y,
originalValue, window, prefs
});
}
@ -462,7 +462,7 @@
return getIsPointValue({
func,
x, y,
index: x + this.width * y,
index: x + this.canvas.width * y,
originalValue, window, prefs
});
}

View File

@ -12,7 +12,7 @@
scope = require.register("./modifiedNavigatorAPI", {});
}
const {checkerWrapper, setGetterProperties, getStatusByFlag} = require("./modifiedAPIFunctions");
const {checkerWrapper, setProperties, getStatusByFlag} = require("./modifiedAPIFunctions");
const extension = require("./extension");
const navigator = require("./navigator");
@ -55,7 +55,40 @@
};
});
setGetterProperties(scope.changedGetters, {
scope.changedFunctions = {
estimate: {
objectGetters: [function(window){return window.StorageManager && window.StorageManager.prototype;}],
fakeGenerator: function(checker){
const quota = 10 * 1024 * 1024 * 1024;
return function estimate(){
return checkerWrapper(checker, this, arguments, function(args, check){
const {notify, original, window} = check;
const This = this;
return new window.Promise(async function(resolve, reject){
try {
const originalValue = await original.call(This, ...args);
if (originalValue.quota !== quota){
originalValue.usage = Math.min(
quota,
Math.max(0, quota - (originalValue.quota - originalValue.usage))
);
originalValue.quota = quota;
notify("fakedNavigatorReadout");
}
resolve(originalValue);
}
catch (error){
reject(error);
}
});
});
};
}
}
};
setProperties(scope.changedFunctions, scope.changedGetters, {
type: "readout",
getStatus: getStatusByFlag("protectNavigator"),
api: "navigator"

View File

@ -89,15 +89,6 @@
};
}();
browser.windows.onRemoved.addListener(async function(){
const windows = await browser.windows.getAll();
if (windows.every(function(window){
return !window.incognito;
})){
clearIncognito();
}
});
function registerTimeout(){
const interval = getInterval();
if (interval > 0){
@ -173,4 +164,18 @@
scope.setDomainData = setDomainData;
scope.clearDomainData = clearDomainData;
scope.clearContainerData = clearContainerData;
try {
browser.windows.onRemoved.addListener(async function(){
const windows = await browser.windows.getAll();
if (windows.every(function(window){
return !window.incognito;
})){
clearIncognito();
}
});
}
catch (error){
logging.error("Unable to register windows.onRemoved listener", error);
}
}());

View File

@ -19,17 +19,26 @@
texts.push({text: text.toLowerCase(), content});
};
scope.search = function(search){
const resultSets = search.toLowerCase().split(/\s+/).filter(function(term){
const resultSets = search.split(/\s+/).filter(function(term){
return term.trim();
}).map(function(term){
return new RegExp(term);
}).map(function(term){
const matching = new Set();
texts.forEach(function(text){
if (term.test(text.text)){
matching.add(text.content);
}
});
if (term.match(/^:[a-z]+$/i)){
const tag = term.substring(1);
texts.forEach(function(text){
if (text.content.querySelector(`.${tag}`)){
matching.add(text.content);
}
});
}
else {
term = new RegExp(term.toLowerCase());
texts.forEach(function(text){
if (term.test(text.text)){
matching.add(text.content);
}
});
}
return matching;
});
if (resultSets.length){

View File

@ -146,6 +146,7 @@
"appName @ navigator",
"appVersion @ navigator",
"buildID @ navigator",
"estimate @ navigator",
"oscpu @ navigator",
"platform @ navigator",
"product @ navigator",
@ -414,6 +415,10 @@
defaultValue: "auto",
options: ["auto", "default", "light", "dark", "colorful"/*, "none"*/]
},
{
name: "showPresetsOnInstallation",
defaultValue: true
},
{
name: "dontShowOptionsOnUpdate",
defaultValue: false

View File

@ -2,7 +2,7 @@
{
"name": "CanvasBlocker",
"description": "__MSG_addon_description__",
"version": "1.9",
"version": "1.11",
"icons": {
"48": "icons/icon.svg",
"96": "icons/icon.svg"
@ -102,7 +102,7 @@
"gecko": {
"id": "CanvasBlocker@kkapsner.de",
"update_url": "https://canvasblocker.kkapsner.de/versions/updates.json",
"strict_min_version": "68.0"
"strict_min_version": "100.0"
}
},
"default_locale": "en",

View File

@ -6,7 +6,7 @@ html, body {
#settings {
width: 100%;
box-sizing: border-box;
height: 95%;
height: 100%;
}
#settings.invalid {
background-color: var(--input-error-background-color);

View File

@ -1,5 +1,5 @@
body.standalone {
padding: 0.5em;
padding: 0.5em 0.5em 2.5em;
}
@media (max-width: 400px){

View File

@ -25,11 +25,11 @@
},
openNavigatorSettings: function(){
logging.verbose("open navigator settings");
window.open("navigator.html", "_blank");
browser.tabs.create({url: "navigator.html"});
},
showReleaseNotes: function(){
logging.verbose("open release notes");
window.open("../releaseNotes.txt", "_blank");
browser.tabs.create({url: extension.getURL("../releaseNotes.txt")});
},
clearPersistentRnd: function(){
logging.message("clear persistent rnd storage");
@ -53,15 +53,15 @@
},
inspectSettings: function(){
logging.verbose("open settings inspection");
window.open("export.html", "_blank");
browser.tabs.create({url: "export.html"});
},
openSettingSanitation: function(){
logging.verbose("open settings sanitation");
window.open("sanitize.html", "_blank");
browser.tabs.create({url: "sanitize.html"});
},
openSettingPresets: function(){
logging.verbose("open setting presets");
window.open("presets.html", "_blank");
browser.tabs.create({url: "presets.html"});
},
saveSettings: function(){
logging.verbose("save settings");
@ -92,7 +92,7 @@
},
inspectWhitelist: function(){
logging.verbose("open whitelist inspection");
window.open("whitelist.html", "_blank");
browser.tabs.create({url: "whitelist.html"});
},
loadSettings: async function(){
logging.verbose("load settings");

View File

@ -51,10 +51,12 @@
const option = document.createElement("option");
if (typeof value === typeof setting.defaultValue){
option.value = value;
option.text = extension.getTranslation(setting.name + "_options." + value) || value;
if (setting.defaultValue === value){
option.selected = true;
option.selectedText = option.text;
option.notSelectedText = option.text + extension.getTranslation("labelForDefaultOption");
}
option.text = extension.getTranslation(setting.name + "_options." + value) || value;
}
else {
option.disabled = true;
@ -62,10 +64,29 @@
}
select.appendChild(option);
});
select.update = function(){
Array.from(select.options).forEach(function(option){
if (option.notSelectedText){
option.text = option.notSelectedText;
}
});
const selectedOption = select.options[select.selectedIndex];
if (selectedOption.selectedText){
selectedOption.text = selectedOption.selectedText;
}
};
return select;
}
const inputTypes = {
all: {
updateCallback: function(input, value, defaultValue){
if (input.update){
input.update();
}
input.classList[value === defaultValue? "remove": "add"]("changed");
}
},
number: {
input: function(value){
const input = document.createElement("input");
@ -73,8 +94,9 @@
input.value = value;
return input;
},
updateCallback: function(input, value){
updateCallback: function(input, value, defaultValue){
input.value = value;
inputTypes.all.updateCallback(input, value, defaultValue);
return input.value;
},
getValue: function(input){
@ -95,8 +117,9 @@
input.value = value;
return input;
},
updateCallback: function(input, value){
updateCallback: function(input, value, defaultValue){
input.value = value;
inputTypes.all.updateCallback(input, value, defaultValue);
return input.value;
},
getValue: function(input){
@ -111,8 +134,9 @@
input.style.display = "inline-block";
return input;
},
updateCallback: function(input, value){
updateCallback: function(input, value, defaultValue){
input.checked = value;
inputTypes.all.updateCallback(input, value, defaultValue);
return input.checked;
},
getValue: function(input){
@ -169,7 +193,7 @@
container && container.hasOwnProperty(key)?
container[key]:
setting.defaultKeyValue,
url
setting.defaultKeyValue
);
});
keyInput.addEventListener("change", function(){
@ -189,7 +213,7 @@
container && container.hasOwnProperty(key)?
container[key]:
setting.defaultKeyValue,
url
setting.defaultKeyValue
);
logging.message("setting", setting.name, "(", key, ") was not changed");
}
@ -232,7 +256,7 @@
urlCell.textContent = entry.url;
row.appendChild(urlCell);
let input = createInput(setting, entry.url);
type.updateCallback(input, setting.get(entry.url));
type.updateCallback(input, setting.get(entry.url), setting.defaultValue);
if (!entry.hasOwnProperty(setting.name)){
input.classList.add("notSpecifiedForUrl");
}
@ -319,14 +343,17 @@
}
}
if (type){
setting.on(function(){type.updateCallback(input, setting.get(url));}, url);
setting.on(function(){
type.updateCallback(input, setting.get(url), setting.defaultValue);
}, url);
input.addEventListener("change", function(){
const value = type.getValue(input);
if (setting.set(value, url)){
type.updateCallback(input, value, setting.defaultValue);
logging.message("changed setting", setting.name, ":", value);
}
else {
type.updateCallback(input, setting.get(url));
type.updateCallback(input, setting.get(url), setting.defaultValue);
logging.message("setting", setting.name, "was not changed");
}
});

View File

@ -3,7 +3,8 @@
"maxFakeSize": 1000000,
"protectDOMRect": {
"mail.google.com": false,
"onedrive.live.com": false
"onedrive.live.com": false,
"^https://[^/]*ebay\\.([a-z]+|com\\.(au|hk|my|sg)|co\\.uk)(/|$)": false
},
"protectWindow": {
"paypal.com": false,

2267
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -7,12 +7,12 @@
"test": "test"
},
"devDependencies": {
"eslint": "^8.11.0",
"eslint": "^8.57.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-html": "^6.1.1",
"eslint-plugin-promise": "^4.2.1",
"web-ext": "^7.6.1",
"yargs": "^15.4.1"
"eslint-plugin-html": "^8.0.0",
"eslint-plugin-promise": "^6.1.1",
"web-ext": "^7.11.0",
"yargs": "^17.7.2"
},
"scripts": {},
"repository": {

View File

@ -11,6 +11,7 @@
<ul id="prints">
<li>...</li>
</ul>
<div id="version" class="versionDisplay"></div>
<script src="../lib/require.js"></script>
<script src="../lib/logging.js"></script>
<script src="../lib/extension.js"></script>

View File

@ -9,6 +9,10 @@
const {parseErrorStack} = require("../lib/callingStack");
const logging = require("../lib/logging");
logging.setPrefix("page action script");
window.addEventListener("load", async function(){
extension.displayVersion("version", 250);
});
const domainNotification = require("./domainNotification");
const Notification = require("./Notification");
@ -30,7 +34,7 @@
browser.runtime.openOptionsPage();
}
else {
window.open(extension.getURL("options/options.html"), "_blank");
browser.tabs.create({url: extension.getURL("options/options.html")});
}
}
},
@ -152,15 +156,12 @@
name: "inspectWhitelist",
isIcon: true,
callback: function({domain, urls}){
window.open(
extension.getURL(
"options/whitelist.html?domain=" +
encodeURIComponent(domain) +
"&urls=" +
encodeURIComponent(JSON.stringify(Array.from(urls.values())))
),
"_blank"
);
browser.tabs.create({url: extension.getURL(
"options/whitelist.html?domain=" +
encodeURIComponent(domain) +
"&urls=" +
encodeURIComponent(JSON.stringify(Array.from(urls.values())))
)});
}
}
];

View File

@ -1,3 +1,57 @@
Version 1.11:
changes:
-
new features:
-
fixes:
-
known issues:
- if a data URL is blocked the page action button does not appear
- canvas and navigator APIs in workers are not protected
Version 1.10.1:
new features:
- added tag search
- added :changed tag
- mark default value in drop downs settings
fixes:
- lag and functionality loss on google sites
- fix function tampering detection via prototype
- isPointInPath and isPointInStroke return undefined with persistent rng
known issues:
- if a data URL is blocked the page action button does not appear
- canvas and navigator APIs in workers are not protected
Version 1.10:
changes:
- added eBay to the convenience preset
- do not use proxy for Function.prototype.toString (causes weird problems sometimes)
new features:
- added setting showPresetsOnInstallation to be able to not show the presets page upon installation
- display version in page and browser action
- added protection for navigator.storage.estimate()
fixes:
- always protect about:blank
- persistent rng not working in Firefox for Android
- mobile default settings were not used in Firefox for Android
- settings export page did not show whole content in Firefox for Android
- new tabs opened from within the extension did not open properly in Firefox for Android
- settings reset confirmation dialog was not properly visible in Firefox for Android
- reload after changing the whitelist state in the browser action has to be done without cache
- data URL blocking was not affected by when changing the whitelist state in the browser action
- prevent unnecessary scroll bars in popups
known issues:
- if a data URL is blocked the page action button does not appear
- canvas and navigator APIs in workers are not protected
Version 1.9:
changes:
- update setting descriptions

View File

@ -181,6 +181,16 @@ addTest("toString modified", function(log){
configurable: true
},
log
) | checkPropertyDescriptor(
Function.prototype,
"toString",
{
value: function toString(){},
writable: true,
enumerable: false,
configurable: true
},
log
);
});
addTest("function name", function(log){

View File

@ -86,9 +86,28 @@ const iframeAPI = function(){
}
},
{
name: "window.open",
name: "removed iframe",
prepare: async function openWindow(){
const newWindow = window.open("/");
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
const iframeWindow = iframe.contentWindow;
document.body.removeChild(iframe);
console.log("window of iframe directly after removing", iframeWindow);
return new Promise(function(resolve){
window.setTimeout(function(){
console.log("window of iframe in timeout", iframeWindow);
resolve(iframeWindow);
}, 1000);
});
}
},
];
["/", "about:blank", "about:blank#"].forEach(function(url){
methods.push({
name: "window.open " + url,
prepare: async function openWindow(){
const newWindow = window.open(url);
if (newWindow){
return {
window: newWindow,
@ -106,11 +125,12 @@ const iframeAPI = function(){
});
}
}
}
];
});
});
function getPerformer(callback){
return async function perform(method){
console.log("run iframe method", method.name);
const api = await method.prepare();
callback(api.window, method.name);
api.cleanup();

View File

@ -60,15 +60,28 @@ function processNavigatorObject(navigator, keys, name){
});
}
iframeAPI.forEachMethod(function(windowToUse, name){
iframeAPI.forEachMethod(async function(windowToUse, name){
"use strict";
const navigator = windowToUse.navigator;
processNavigatorObject(navigator, Object.keys(navigator.__proto__), name);
const values = {};
const keys = Object.keys(navigator.__proto__);
keys.forEach(function(property){
const value = navigator[property];
if ((typeof value) === "string"){
values[property] = value;
}
});
const storage = await navigator.storage.estimate();
values.storage_quota = storage.quota.toString(10);
keys.push("storage_quota");
console.log(name, values);
processNavigatorObject(values, keys, name);
});
function processWorkerNavigatorObject(data, name){
"use strict";
console.log(name, data);
processNavigatorObject(data.values, Object.keys(data.values), name);
if (data.nestedValues){
processWorkerNavigatorObject(data.nestedValues, "nested " + name);

View File

@ -1,4 +1,4 @@
(function(){
(async function(){
"use strict";
const values = {};
@ -10,6 +10,8 @@
values[property] = value;
}
});
const storage = await navigator.storage.estimate();
values.storage_quota = storage.quota.toString(10);
const ports = [];
const sources = [];

View File

@ -106,4 +106,12 @@ input[type=checkbox]:checked::before {
box-sizing: border-box;
cursor: initial;
background-color: var(--input-background-color);
}
.versionDisplay {
text-align: right;
font-size: 0.6em;
opacity: 0.5;
margin: 0.3em 0.5em 0.2em;
clear: both;
}

View File

@ -249,6 +249,94 @@
{
"version": "1.9Alpha20230408",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.9Alpha20230408.xpi"
},
{
"version": "1.10Alpha20230419",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10Alpha20230419.xpi"
},
{
"version": "1.10Alpha20230529",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10Alpha20230529.xpi"
},
{
"version": "1.10Alpha20230530",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10Alpha20230530.xpi"
},
{
"version": "1.10Alpha20230531",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10Alpha20230531.xpi"
},
{
"version": "1.10Alpha20240216",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10Alpha20240216.xpi"
},
{
"version": "1.10.20240217",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10.20240217.xpi"
},
{
"version": "1.10.20240217.1",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10.20240217.1.xpi"
},
{
"version": "1.10.20240217.2",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10.20240217.2.xpi"
},
{
"version": "1.10.20240217.3",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10.20240217.3.xpi"
},
{
"version": "1.10.20240217.4",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10.20240217.4.xpi"
},
{
"version": "1.10.20240217.5",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10.20240217.5.xpi"
},
{
"version": "1.10.20240218",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10.20240218.xpi"
},
{
"version": "1.10.20240218.1",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10.20240218.1.xpi"
},
{
"version": "1.10.20240218.2",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10.20240218.2.xpi"
},
{
"version": "1.10.20240218.3",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10.20240218.3.xpi"
},
{
"version": "1.10.20240328",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10.20240328.xpi"
},
{
"version": "1.10.20240330",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10.20240330.xpi"
},
{
"version": "1.10.1.20240405",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10.1.20240405.xpi"
},
{
"version": "1.10.20240407",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10.20240407.xpi"
},
{
"version": "1.10.20240407.1",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10.20240407.1.xpi"
},
{
"version": "1.10.20240408",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.10.20240408.xpi"
},
{
"version": "1.11.20240417",
"update_link": "https://canvasblocker.kkapsner.de/versions/canvasblocker_beta-1.11.20240417.xpi"
}
]
}