From 51445b36e02588bc6d0f75f26e4a5dfec1fb0963 Mon Sep 17 00:00:00 2001 From: kkapsner Date: Tue, 30 Apr 2019 23:42:21 +0200 Subject: [PATCH 1/2] Added whitelist scope question --- _locales/de/messages.json | 12 +++++++ _locales/en/messages.json | 12 +++++++ lib/frame.js | 8 ++++- pageAction/domainNotification.js | 9 ++--- pageAction/pageAction.js | 58 +++++++++++++++++++++++++++++--- 5 files changed, 89 insertions(+), 10 deletions(-) diff --git a/_locales/de/messages.json b/_locales/de/messages.json index ec3b7a5..eeb234d 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -667,6 +667,18 @@ "message": "Geben Sie die URL \"RegExp\" ein, die für diese Sitzung erlaubt werden soll:", "description": "" }, + "selectWhitelistScope": { + "message": "Was soll erlaubt werden?", + "description": "" + }, + "whitelistOnlyAPI": { + "message": "Erlaube nur die \"{api}\" API.", + "description": "" + }, + "whitelistAllAPIs": { + "message": "Erlaube alle APIs.", + "description": "" + }, "settings": { "message": "Einstellungen", "description": "" diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 4ec10e9..d1238a5 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -701,6 +701,18 @@ "message": "Input URL \"RegExp\" to add to the session whitelist:", "description": "" }, + "selectWhitelistScope": { + "message": "What is the scope of the whitelisting?", + "description": "" + }, + "whitelistOnlyAPI": { + "message": "Whitelist only the API \"{api}\".", + "description": "" + }, + "whitelistAllAPIs": { + "message": "Whitelist all APIs.", + "description": "" + }, "settings": { "message": "settings", "description": "" diff --git a/lib/frame.js b/lib/frame.js index c8a1c1f..1282d25 100644 --- a/lib/frame.js +++ b/lib/frame.js @@ -76,7 +76,13 @@ if (settings.storeNotificationData){ notifications.push(data); } - notificationCounter[data.messageId] = (notificationCounter[data.messageId] || 0) + 1; + if (!notificationCounter[data.messageId]){ + notificationCounter[data.messageId] = { + count: 0, + api: data.api + }; + } + notificationCounter[data.messageId].count += 1; if (!sentAPIs[data.api]){ sentAPIs[data.api] = true; port.postMessage({"canvasBlocker-notify": data}); diff --git a/pageAction/domainNotification.js b/pageAction/domainNotification.js index 198deae..9a434da 100644 --- a/pageAction/domainNotification.js +++ b/pageAction/domainNotification.js @@ -26,7 +26,7 @@ }; }(); - const DomainNotification = function DomainNotification(domain, messageId, count = 0){ + const DomainNotification = function DomainNotification(domain, messageId, count = 0, api = ""){ if (domain instanceof URL){ this.urls().add(domain.href); domain = domain.hostname; @@ -34,6 +34,7 @@ this.domain = domain; this.messageId = messageId; this.count = count; + this.api = api; this.extraNotifications = 0; addToContainer(this); this.update(); @@ -148,7 +149,7 @@ DomainNotification.prototype.actionsNode = function actionsNode(){ const node = document.createElement("div"); node.className = "actions"; - createActionButtons(node, actions, {domain: this.domain, urls: this.urls()}); + createActionButtons(node, actions, {domain: this.domain, urls: this.urls(), api: this.api}); this.actionsNode = function(){ return node; }; @@ -165,11 +166,11 @@ }; const domains = new Map(); - const domainNotification = function(url, messageId, count = 0){ + const domainNotification = function(url, messageId, count = 0, api = ""){ const domain = url.hostname; var domainNotification = domains.get(domain + messageId); if (!domainNotification){ - domainNotification = new DomainNotification(url, messageId, count); + domainNotification = new DomainNotification(url, messageId, count, api); domains.set(domain + messageId, domainNotification); } else { diff --git a/pageAction/pageAction.js b/pageAction/pageAction.js index 0a9f7ae..659e363 100644 --- a/pageAction/pageAction.js +++ b/pageAction/pageAction.js @@ -120,15 +120,60 @@ { name: "whitelist", isIcon: true, - callback: function({domain, urls}){ + callback: function({domain, urls, api}){ + const whitelistingSettings = { + all: {name: "blockMode", value: "allow"}, + canvas: {name: "protectedCanvasPart", value: "nothing"}, + audio: {name: "protectAudio", value: false}, + domRect: {name: "protectDOMRect", value: false}, + history: {name: "historyLengthThreshold", value: 10000}, + navigator: {name: "protectNavigator", value: false}, + windows: {name: "protectWindow", value: false} + + }; domainOrUrlPicker( domain, urls, extension.getTranslation("selectWhitelist"), extension.getTranslation("inputWhitelistURL") ).then(function(choice){ + const allAPIs = { + choice, + setting: "blockMode", + settingValue: "allow" + }; + const onlyAPI = { + choice, + setting: whitelistingSettings[api], + settingValue: false + }; + if ( + api && + whitelistingSettings[api] + ){ + return modalChoice( + extension.getTranslation("selectWhitelistScope"), + [ + { + text: extension.getTranslation("whitelistOnlyAPI") + .replace(/\{api\}/g, api), + value: api + }, + { + text: extension.getTranslation("whitelistAllAPIs"), + value: "all" + } + ] + ).then(function(selection){ + return {choice, setting: whitelistingSettings[selection]}; + }); + } + else { + return {choice, setting: whitelistingSettings.all}; + } + }).then(function({choice, setting}){ if (choice){ - settings.set("blockMode", "allow", choice).then(function(){ + settings.set(setting.name, setting.value, choice).then(function(){ window.close(); }); } @@ -184,14 +229,15 @@ }); var tab = tabs[0]; - browser.runtime.onMessage.addListener(function(data){ + extension.message.on(function(data){ if (data["canvasBlocker-notificationCounter"]){ const url = new URL(data.url); Object.keys(data["canvasBlocker-notificationCounter"]).forEach(function(key){ const notification = domainNotification( url, key, - data["canvasBlocker-notificationCounter"][key] + data["canvasBlocker-notificationCounter"][key].count, + data["canvasBlocker-notificationCounter"][key].api ); }); } @@ -218,7 +264,9 @@ notification.url = new URL(notification.url); domainNotification( notification.url, - notification.messageId + notification.messageId, + 0, + notification.api ).addNotification(new Notification(notification)); } i += delta; From b27cf7087b8cb5f8b7cf7769e68876755103434c Mon Sep 17 00:00:00 2001 From: kkapsner Date: Sat, 4 May 2019 01:12:45 +0200 Subject: [PATCH 2/2] Added whitelist inspection Fixes #331 --- _locales/de/messages.json | 28 +++++- _locales/en/messages.json | 29 +++++- icons/pageAction-inspectWhitelist.svg | 78 +++++++++++++++ lib/settingDefinitions.js | 3 +- options/options.js | 4 + options/settingsDisplay.js | 2 +- options/whitelist.html | 18 ++++ options/whitelist.js | 132 ++++++++++++++++++++++++++ pageAction/pageAction.js | 30 +++--- releaseNotes.txt | 3 + 10 files changed, 310 insertions(+), 17 deletions(-) create mode 100644 icons/pageAction-inspectWhitelist.svg create mode 100644 options/whitelist.html create mode 100644 options/whitelist.js diff --git a/_locales/de/messages.json b/_locales/de/messages.json index e7bef6a..1bb3553 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -672,11 +672,11 @@ "description": "" }, "whitelistOnlyAPI": { - "message": "Erlaube nur die \"{api}\" API.", + "message": "Erlaube nur die {api}", "description": "" }, "whitelistAllAPIs": { - "message": "Erlaube alle APIs.", + "message": "Erlaube alle APIs", "description": "" }, "settings": { @@ -811,6 +811,10 @@ "message": "temporär erlauben", "description": "" }, + "inspectWhitelist": { + "message": "Erlaubnisse ansehen", + "description": "" + }, "sessionWhiteList_title": { "message": "Sitzungs-Whitelist", "description": "" @@ -959,6 +963,10 @@ "message": "Maximale Länge der Browser-History, die der Webseite mitgeteilt wird.", "description": "" }, + "historyLengthThreshold_urlSpecific": { + "message": "Um diesen Wert für bestimmte Seiten zu ändern, klicken Sie auf den schwarzen Pfeil um das Menü zu öffnen, fügen Sie die gewünschte Domain oder URL mit einem Klick auf \"+\" hinzu und geben Sie dort einen anderen Wert ein.", + "description": "" + }, "protectWindow_title": { "message": "Window-API beschützen", "description": "" @@ -1003,6 +1011,10 @@ "message": "Dies ermöglicht Änderungen an der Navigator-API. Diesen Schutz zu aktivieren ändert standardmäßig noch nichts. Öffnen Sie die Navigatoreinstellungen um die gewünschten Änderungen durchzuführen.", "description": "" }, + "protectNavigator_urlSpecific": { + "message": "Um bestimmte Seiten von diesem Schutz auszuschließen, klicken Sie auf den schwarzen Pfeil um das Menü zu öffnen, fügen Sie die gewünschte Domain oder URL mit einem Klick auf \"+\" hinzu und entfernen Sie das zugehörige Häkchen.", + "description": "" + }, "openNavigatorSettings_title": { "message": "Navigatoreinstellungen", "description": "" @@ -1159,6 +1171,10 @@ "message": "Laden", "description": "" }, + "inspectWhitelist_label": { + "message": "Erlaubnisse ansehen", + "description": "" + }, "resetSettings_title": { "message": "Einstellungen zurücksetzen", "description": "" @@ -1306,5 +1322,13 @@ "sanitation_error.doNotSharePersistentRndBetweenDomains": { "message": "Teilen Sie die persistenten Zufallszahlen nicht zwischen Domains, da dies den Browser 100% eindeutig identifizierbar macht.", "description": "" + }, + "whitelist_inspection_title": { + "message": "CanvasBlocker Erlaubnisse ansehen", + "description": "" + }, + "whitelist_all_apis": { + "message": "Alle APIs", + "description": "" } } \ No newline at end of file diff --git a/_locales/en/messages.json b/_locales/en/messages.json index a84eef4..84136aa 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -706,11 +706,11 @@ "description": "" }, "whitelistOnlyAPI": { - "message": "Whitelist only the API \"{api}\".", + "message": "Whitelist only the {api}", "description": "" }, "whitelistAllAPIs": { - "message": "Whitelist all APIs.", + "message": "Whitelist all APIs", "description": "" }, "settings": { @@ -845,6 +845,10 @@ "message": "whitelist temporarily", "description": "" }, + "inspectWhitelist": { + "message": "inspect whitelist", + "description": "" + }, "sessionWhiteList_title": { "message": "Session whitelist", @@ -999,6 +1003,10 @@ "message": "Maximal length of the history that is reported to the website.", "description": "" }, + "historyLengthThreshold_urlSpecific": { + "message": "To change this value for specific websites, click on the black arrow to open the menu, add the domain or URL by clicking on \"+\" and set a different value.", + "description": "" + }, "protectWindow_title": { "message": "Protect window API", @@ -1047,6 +1055,10 @@ "message": "This page allows for changes in the navigator API. Enabling this protection does not change anything by default. Open the navigator settings to specify the changes you want to have there.", "description": "" }, + "protectNavigator_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.", + "description": "" + }, "openNavigatorSettings_title": { "message": "Navigator settings", @@ -1212,6 +1224,10 @@ "message": "Load", "description": "" }, + "inspectWhitelist_label": { + "message": "Inspect whitelist", + "description": "" + }, "resetSettings_title": { "message": "Reset settings", @@ -1362,5 +1378,14 @@ "sanitation_error.doNotSharePersistentRndBetweenDomains": { "message": "Do not share persistent randomness between domains because this makes the browser 100% trackable.", "description": "" + }, + + "whitelist_inspection_title": { + "message": "CanvasBlocker whitelist inspection", + "description": "" + }, + "whitelist_all_apis": { + "message": "All APIs", + "description": "" } } diff --git a/icons/pageAction-inspectWhitelist.svg b/icons/pageAction-inspectWhitelist.svg new file mode 100644 index 0000000..a39f293 --- /dev/null +++ b/icons/pageAction-inspectWhitelist.svg @@ -0,0 +1,78 @@ + + + + + + + + + + image/svg+xml + + + + + + + www. + + + + diff --git a/lib/settingDefinitions.js b/lib/settingDefinitions.js index 40a7587..a0c3f44 100644 --- a/lib/settingDefinitions.js +++ b/lib/settingDefinitions.js @@ -310,7 +310,8 @@ }, { name: "protectNavigator", - defaultValue: false + defaultValue: false, + urlSpecific: true }, { name: "navigatorDetails", diff --git a/options/options.js b/options/options.js index 1bfb461..70e23b5 100644 --- a/options/options.js +++ b/options/options.js @@ -56,6 +56,10 @@ link.click(); document.body.removeChild(link); }, + inspectWhitelist: function(){ + logging.verbose("open whitelist inspection"); + window.open("whitelist.html", "_blank"); + }, loadSettings: function(){ logging.verbose("load settings"); new Promise(function(resolve, reject){ diff --git a/options/settingsDisplay.js b/options/settingsDisplay.js index 3711183..93d4b15 100644 --- a/options/settingsDisplay.js +++ b/options/settingsDisplay.js @@ -538,7 +538,7 @@ }, { "name": "exportSettings", - "actions": ["inspectSettings", "saveSettings", "loadSettings"] + "actions": ["inspectSettings", "inspectWhitelist", "saveSettings", "loadSettings"] }, { "name": "resetSettings" diff --git a/options/whitelist.html b/options/whitelist.html new file mode 100644 index 0000000..4061e01 --- /dev/null +++ b/options/whitelist.html @@ -0,0 +1,18 @@ + + + + CanvasBlocker whitelist inspection + + + + + + + + + + + + + + \ No newline at end of file diff --git a/options/whitelist.js b/options/whitelist.js new file mode 100644 index 0000000..4f540d6 --- /dev/null +++ b/options/whitelist.js @@ -0,0 +1,132 @@ +/* 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"; + + const extension = require("../lib/extension"); + const settings = require("../lib/settings"); + const settingContainers = require("../lib/settingContainers"); + require("../lib/theme").init(); + const searchParameters = new URLSearchParams(window.location.search); + + + var title = document.createElement("h1"); + title.className = "title"; + title.textContent = extension.getTranslation("whitelist_inspection_title"); + document.body.appendChild(title); + + document.querySelector("head title").textContent = title.textContent; + + settings.onloaded(function(){ + const sets = settingContainers.urlContainer.get(); + + const setSelect = document.createElement("select"); + sets.forEach(function(set){ + setSelect.appendChild(new Option(set.url)); + }); + document.body.appendChild(setSelect); + + if (searchParameters.has("urls")){ + const urls = JSON.parse(searchParameters.get("urls")).map(function(url){ + return new URL(url); + }); + if ( + !sets.some(function(set, index){ + if (urls.some(function(url){ + return set.match && set.match(url); + })){ + setSelect.selectedIndex = index; + return true; + } + }) && + searchParameters.has("domain") + ){ + setSelect.appendChild(new Option(searchParameters.get("domain"))); + setSelect.selectedIndex = setSelect.options.length - 1; + } + } + + const whitelistSettings = [ + { + title: extension.getTranslation("whitelist_all_apis"), + name: "blockMode", + whitelistValue: "allow", + protectedValue: "fake" + }, + { + title: extension.getTranslation("section_canvas-api"), + name: "protectedCanvasPart", + whitelistValue: "nothing", + protectedValue: "readout" + }, + { + title: extension.getTranslation("section_audio-api"), + name: "protectAudio", + whitelistValue: false, + protectedValue: true + }, + { + title: extension.getTranslation("section_history-api"), + name: "historyLengthThreshold", + whitelistValue: 10000, + protectedValue: 2 + }, + { + title: extension.getTranslation("section_window-api"), + name: "protectWindow", + whitelistValue: false, + protectedValue: true + }, + { + title: extension.getTranslation("section_DOMRect-api"), + name: "protectDOMRect", + whitelistValue: false, + protectedValue: true + }, + { + title: extension.getTranslation("section_navigator-api"), + name: "protectNavigator", + whitelistValue: false, + protectedValue: true + }, + ]; + + const table = document.createElement("table"); + whitelistSettings.forEach(function(setting){ + const row = document.createElement("tr"); + setting.row = row; + const name = document.createElement("td"); + name.textContent = setting.title || extension.getTranslation(setting.name + "_title"); + row.appendChild(name); + setting.input = document.createElement("input"); + setting.input.type = "checkbox"; + setting.input.addEventListener("change", function(){ + settings.set( + setting.name, + this.checked? setting.protectedValue: setting.whitelistValue, + setSelect.value + ); + }); + const input = document.createElement("td"); + input.appendChild(setting.input); + row.appendChild(input); + table.appendChild(row); + }); + document.body.appendChild(table); + + function update(){ + whitelistSettings.forEach(function(setting){ + setting.row.style.display = settings.get(setting.name) === setting.whitelistValue? + "none": + ""; + + const currentValue = settings.get(setting.name, setSelect.value); + setting.input.checked = currentValue !== setting.whitelistValue; + }); + } + update(); + setSelect.addEventListener("change", update); + settings.on("any", update); + }); +}()); \ No newline at end of file diff --git a/pageAction/pageAction.js b/pageAction/pageAction.js index 3399c64..09edacf 100644 --- a/pageAction/pageAction.js +++ b/pageAction/pageAction.js @@ -128,16 +128,6 @@ extension.getTranslation("selectWhitelist"), extension.getTranslation("inputWhitelistURL") ).then(function(choice){ - const allAPIs = { - choice, - setting: "blockMode", - settingValue: "allow" - }; - const onlyAPI = { - choice, - setting: whitelistingSettings[api], - settingValue: false - }; if ( api && whitelistingSettings[api] @@ -147,7 +137,10 @@ [ { text: extension.getTranslation("whitelistOnlyAPI") - .replace(/\{api\}/g, api), + .replace( + /\{api\}/g, + extension.getTranslation("section_" + api + "-api") + ), value: api }, { @@ -194,6 +187,21 @@ } }); } + }, + { + name: "inspectWhitelist", + isIcon: true, + callback: function({domain, urls}){ + window.open( + browser.extension.getURL( + "options/whitelist.html?domain=" + + encodeURIComponent(domain) + + "&urls=" + + encodeURIComponent(JSON.stringify(Array.from(urls.values()))) + ), + "_blank" + ); + } } ].forEach(function(domainAction){ domainNotification.addAction(domainAction); diff --git a/releaseNotes.txt b/releaseNotes.txt index 7867948..3bc66c3 100644 --- a/releaseNotes.txt +++ b/releaseNotes.txt @@ -2,6 +2,7 @@ Version 0.5.9: changes: - code cleanup - made history length threshold url specific + - made navigator protection url specific - uniform themes new features: @@ -12,6 +13,8 @@ Version 0.5.9: - added option to protect no part of the canvas API - apply themes to all extension pages (options, page action, browser action, setting sanitation, setting inspection, navigator settings) - theme for automatic detection of dark mode (only works with Firefox >= 67) + - within the page action the used API can be whitelisted alone + - added overview page for whitelist fixes: - search could show hidden settings