diff --git a/.documentation/addon description/de/description.txt b/.documentation/addon description/de/description.txt
index 948a3a4..61aa60d 100644
--- a/.documentation/addon description/de/description.txt
+++ b/.documentation/addon description/de/description.txt
@@ -18,6 +18,7 @@ Geschützte "Fingerprinting"-APIs:
canvas 2d
webGL
audio
+ history
Falls Sie Fehler finden oder Verbesserungsvorschläge haben, teilen Sie mir das bitte auf https://github.com/kkapsner/CanvasBlocker/issues mit.
\ No newline at end of file
diff --git a/.documentation/addon description/en/description.txt b/.documentation/addon description/en/description.txt
index 891655c..2dcb180 100644
--- a/.documentation/addon description/en/description.txt
+++ b/.documentation/addon description/en/description.txt
@@ -18,6 +18,7 @@ Protected "fingerprinting" APIs:
canvas 2d
webGL
audio
+ history
Please report issues and feature requests at https://github.com/kkapsner/CanvasBlocker/issues
diff --git a/_locales/de/messages.json b/_locales/de/messages.json
index b027b8a..1e00553 100644
--- a/_locales/de/messages.json
+++ b/_locales/de/messages.json
@@ -93,6 +93,10 @@
"message": "Audio API",
"description": ""
},
+ "section_history-api":{
+ "message": "History API",
+ "description": ""
+ },
"displayAdvancedSettings_title": {
"message": "Expertenmodus",
@@ -177,6 +181,18 @@
"message": "Wollen Sie das Auslesen über die Audio-API erlauben?",
"description": ""
},
+ "askForHistoryPermission": {
+ "message": "Wollen Sie die History-API erlauben?",
+ "description": ""
+ },
+ "askForHistoryInputPermission": {
+ "message": "Wollen Sie das Schreiben in über die History-API erlauben?",
+ "description": ""
+ },
+ "askForHistoryReadoutPermission": {
+ "message": "Wollen Sie das Auslesen über die History-API erlauben?",
+ "description": ""
+ },
"askOnlyOnce_title": {
"message": "Nur einmal nachfragen",
"description": ""
@@ -500,6 +516,10 @@
"message": "Audioauslese vorgetäuscht auf {url}",
"description": ""
},
+ "fakedHistoryReadout": {
+ "message": "History-Auslese vorgetäuscht auf {url}",
+ "description": ""
+ },
"fakedInput": {
"message": "Bei Ausgabe vorgetäuscht auf {url}",
"description": ""
@@ -804,6 +824,15 @@
"description": ""
},
+ "historyLengthThreshold_title": {
+ "message": "History-Längenschwellwert",
+ "description": ""
+ },
+ "historyLengthThreshold_description": {
+ "message": "Maximale Länge der Browser-History, die der Web-Seite mitgeteilt wird.",
+ "description": ""
+ },
+
"theme_title": {
"message": "Theme",
"description": ""
diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index b1e6411..9272887 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -93,6 +93,10 @@
"message": "Audio API",
"description": ""
},
+ "section_history-api":{
+ "message": "History API",
+ "description": ""
+ },
"displayAdvancedSettings_title": {
"message": "Expert mode",
@@ -177,6 +181,18 @@
"message": "Do you want to allow audio readout?",
"description": ""
},
+ "askForHistoryPermission": {
+ "message": "Do you want to allow the history API?",
+ "description": ""
+ },
+ "askForHistoryInputPermission": {
+ "message": "Do you want to allow history-API input?",
+ "description": ""
+ },
+ "askForHistoryReadoutPermission": {
+ "message": "Do you want to allow history readout?",
+ "description": ""
+ },
"askOnlyOnce_title": {
"message": "Ask only once",
"description": ""
@@ -500,6 +516,10 @@
"message": "Faked audio readout on {url}",
"description": ""
},
+ "fakedHistoryReadout": {
+ "message": "Faked history readout on {url}",
+ "description": ""
+ },
"fakedInput": {
"message": "Faked at input on {url}",
"description": ""
@@ -803,6 +823,15 @@
"description": ""
},
+ "historyLengthThreshold_title": {
+ "message": "History length threshold",
+ "description": ""
+ },
+ "historyLengthThreshold_description": {
+ "message": "Maximal length of the history that is reported to the web site.",
+ "description": ""
+ },
+
"theme_title": {
"message": "Theme",
"description": ""
diff --git a/lib/askForPermission.js b/lib/askForPermission.js
index 1769134..bc2c7b0 100644
--- a/lib/askForPermission.js
+++ b/lib/askForPermission.js
@@ -86,7 +86,8 @@
visible: _("askForVisiblePermission"),
invisible: _("askForInvisiblePermission"),
nocanvas: _("askForPermission"),
- audio: _("askForAudioPermission")
+ audio: _("askForAudioPermission"),
+ history: _("askForHistoryPermission"),
},
askStatus: {
alreadyAsked: {},
@@ -98,7 +99,8 @@
visible: _("askForVisibleInputPermission"),
invisible: _("askForInvisibleInputPermission"),
nocanvas: _("askForInputPermission"),
- audio: _("askForAudioInputPermission")
+ audio: _("askForAudioInputPermission"),
+ history: _("askForHistoryInputPermission"),
},
askStatus: {
alreadyAsked: {},
@@ -110,7 +112,8 @@
visible: _("askForVisibleReadoutPermission"),
invisible: _("askForInvisibleReadoutPermission"),
nocanvas: _("askForReadoutPermission"),
- audio: _("askForAudioReadoutPermission")
+ audio: _("askForAudioReadoutPermission"),
+ history: _("askForHistoryReadoutPermission"),
},
askStatus: {
alreadyAsked: {},
diff --git a/lib/modifiedAPI.js b/lib/modifiedAPI.js
index 5db6834..7149c1d 100644
--- a/lib/modifiedAPI.js
+++ b/lib/modifiedAPI.js
@@ -486,4 +486,5 @@
});
}
appendModified(modifiedAudioAPI);
+ appendModified(require("./modifiedHistoryAPI"));
}());
\ No newline at end of file
diff --git a/lib/modifiedHistoryAPI.js b/lib/modifiedHistoryAPI.js
new file mode 100644
index 0000000..b9b8fee
--- /dev/null
+++ b/lib/modifiedHistoryAPI.js
@@ -0,0 +1,56 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+(function(){
+ "use strict";
+
+ var scope;
+ if ((typeof exports) !== "undefined"){
+ scope = exports;
+ }
+ else {
+ window.scope.modifiedHistoryAPI = {};
+ scope = window.scope.modifiedHistoryAPI;
+ }
+
+ const {hasType, checkerWrapper} = require("./modifiedAPIFunctions");
+
+ scope.changedGetters = [
+ {
+ objectGetters: [function(window){return window.History.prototype;}],
+ name: "length",
+ getterGenerator: function(checker){
+ const temp = {
+ get length(){
+ return checkerWrapper(checker, this, arguments, function(args, check){
+ const {prefs, notify, window, original} = check;
+ const originalLength = original.apply(this, window.Array.from(args));
+ const threshold = prefs("historyLengthThreshold", window.location);
+ if (originalLength > threshold){
+ notify("fakedHistoryReadout");
+ return threshold;
+ }
+ else {
+ return originalLength;
+ }
+ });
+ }
+ };
+ return Object.getOwnPropertyDescriptor(temp, "length").get;
+ }
+ }
+ ];
+
+
+ function getStatus(obj, status){
+ status = Object.create(status);
+ status.active = hasType(status, "readout");
+ return status;
+ }
+
+ scope.changedGetters.forEach(function(changedGetter){
+ changedGetter.type = "readout";
+ changedGetter.getStatus = getStatus;
+ changedGetter.api = "history";
+ });
+}());
\ No newline at end of file
diff --git a/lib/settingDefinitions.js b/lib/settingDefinitions.js
index b59ca2b..212fa1e 100644
--- a/lib/settingDefinitions.js
+++ b/lib/settingDefinitions.js
@@ -89,7 +89,9 @@
{name: "Audio-API", level: 1},
"getFloatFrequencyData", "getByteFrequencyData", "getFloatTimeDomainData", "getByteTimeDomainData",
"getChannelData", "copyFromChannel",
- "getFrequencyResponse"
+ "getFrequencyResponse",
+ {name: "History-API", level: 1},
+ "length",
],
defaultKeyValue: false
},
@@ -188,6 +190,7 @@
keys: [
"canvas",
"audio",
+ "history",
],
defaultKeyValue: false
},
@@ -236,6 +239,10 @@
return Math.floor(Math.random() * 30).toString(10);
}
},
+ {
+ name: "historyLengthThreshold",
+ defaultValue: 2
+ },
{
name: "blockDataURLs",
defaultValue: true
diff --git a/manifest.json b/manifest.json
index 431ba68..1d8bfb1 100644
--- a/manifest.json
+++ b/manifest.json
@@ -37,6 +37,7 @@
"lib/hash.js",
"lib/modifiedAPIFunctions.js",
"lib/modifiedAudioAPI.js",
+ "lib/modifiedHistoryAPI.js",
"lib/modifiedAPI.js",
"lib/randomSupplies.js",
"lib/intercept.js",
diff --git a/options/settingsDisplay.js b/options/settingsDisplay.js
index 9572f4b..4f03593 100644
--- a/options/settingsDisplay.js
+++ b/options/settingsDisplay.js
@@ -390,6 +390,13 @@
}
]
},
+ "History-API",
+ {
+ "name": "historyLengthThreshold",
+ "displayDependencies": {
+ "displayAdvancedSettings": [true]
+ }
+ },
"misc",
{
"name": "theme"
diff --git a/releaseNotes.txt b/releaseNotes.txt
index f4c693d..76a1cea 100644
--- a/releaseNotes.txt
+++ b/releaseNotes.txt
@@ -11,6 +11,7 @@ Version 0.5.3:
- added theme for browser action popup
- added badge
- added option to ignore APIs
+ - added protection for history length
fixes:
- CSP did not work properly for worker-src
diff --git a/test/detectionTest.js b/test/detectionTest.js
index 8a784c7..6efc75a 100644
--- a/test/detectionTest.js
+++ b/test/detectionTest.js
@@ -96,22 +96,28 @@ addTest("function length", function(log){
addTest("function code", function(log){
"use strict";
var codeDetected = false;
- if (
- !CanvasRenderingContext2D.prototype.getImageData.toString().match(
- /^\s*function getImageData\s*\(\)\s*\{\s*\[native code\]\s*\}\s*$/
- )
- ){
- log("unexpected function code:", CanvasRenderingContext2D.prototype.getImageData.toString());
- codeDetected = true;
- }
- if (
- !HTMLCanvasElement.prototype.toDataURL.toString().match(
- /^\s*function toDataURL\s*\(\)\s*\{\s*\[native code\]\s*\}\s*$/
- )
- ){
- log("unexpected function code:", HTMLCanvasElement.prototype.toDataURL.toString());
- codeDetected = true;
+ function checkFunctionCode(func, expectedName){
+ log("checking", expectedName);
+ if (!func.toString().match(
+ new RegExp("^\\s*function " + expectedName + "\\s*\\(\\)\\s*\\{\\s*\\[native code\\]\\s*\\}\\s*$")
+ )){
+ log("unexpected function code:", func.toString());
+ return true;
+ }
+ return false;
}
+ codeDetected = checkFunctionCode(
+ CanvasRenderingContext2D.prototype.getImageData,
+ "getImageData"
+ ) || codeDetected;
+ codeDetected = checkFunctionCode(
+ HTMLCanvasElement.prototype.toDataURL,
+ "toDataURL"
+ ) || codeDetected;
+ codeDetected = checkFunctionCode(
+ history.__lookupGetter__("length"),
+ "get length"
+ ) || codeDetected;
return codeDetected;
});
addTest("toString modified", function(log){