diff --git a/.documentation/addon description/de/description.txt b/.documentation/addon description/de/description.txt index bbb31d4..defdc10 100644 --- a/.documentation/addon description/de/description.txt +++ b/.documentation/addon description/de/description.txt @@ -37,6 +37,7 @@ Beschützte "Fingerprinting"-APIs:
  • history
  • window (standardmäßig deaktiviert)
  • DOMRect
  • +
  • navigator (standardmäßig deaktiviert)
  • 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 0866ceb..ae0e5ad 100644 --- a/.documentation/addon description/en/description.txt +++ b/.documentation/addon description/en/description.txt @@ -38,6 +38,7 @@ Protected "fingerprinting" APIs:
  • history
  • window (disabled by default)
  • DOMRect
  • +
  • navigator (disabled by default)
  • Please report issues and feature requests at https://github.com/kkapsner/CanvasBlocker/issues diff --git a/.documentation/addon description/es/description.txt b/.documentation/addon description/es/description.txt index 8e26cdd..7b9dd32 100644 --- a/.documentation/addon description/es/description.txt +++ b/.documentation/addon description/es/description.txt @@ -35,6 +35,7 @@ API para «huellas digitales» protegidas:
  • history
  • window (deshabilitada por defecto)
  • DOMRect
  • +
  • navigator (deshabilitada por defecto)
  • Puede informar sobre problemas y solicitar funciones en https://github.com/kkapsner/CanvasBlocker/issues diff --git a/.documentation/addon description/ru/description.txt b/.documentation/addon description/ru/description.txt index 6612a33..65e1d46 100644 --- a/.documentation/addon description/ru/description.txt +++ b/.documentation/addon description/ru/description.txt @@ -21,6 +21,7 @@
  • history
  • window (disabled by default)
  • DOMRect
  • +
  • navigator (disabled by default)
  • Сообщите о проблемах и пожеланиях на странице https://github.com/kkapsner/CanvasBlocker/issues. \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 03d8c81..3155ceb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,9 +5,11 @@ "Blockiermodus", "Captcha", "Ignorierliste", + "KHTML", "Maleficient", "Nachfrageverweigerungsmodus", "Oakenpants", + "Palemoon", "PDFs", "Rect", "Rects", @@ -23,7 +25,9 @@ "fragmenter", "ignorelist", "micrococo", + "monero", "onloaded", + "oscpu", "prefs", "promisify", "ruleset", diff --git a/README.md b/README.md index 5f53071..cdb9ba1 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ Protected "fingerprinting" APIs: * history * window (disabled by default) * DOMRect + * navigator (disabled by default) Special thanks to: * spodermenpls for finding all the typos diff --git a/_locales/de/messages.json b/_locales/de/messages.json index e860ac1..13529ae 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -119,6 +119,10 @@ "message": "DOMRect-API", "description": "" }, + "section_Navigator-api": { + "message": "Navigator-API", + "description": "" + }, "displayAdvancedSettings_title": { "message": "Expertenmodus", "description": "" @@ -231,6 +235,18 @@ "message": "Wollen Sie das Auslesen über die DOMRect-API erlauben?", "description": "" }, + "askForNavigatorPermission": { + "message": "Wollen Sie die Navigator-API erlauben?", + "description": "" + }, + "askForNavigatorInputPermission": { + "message": "Wollen Sie das Schreiben über die Navigator-API erlauben?", + "description": "" + }, + "askForNavigatorReadoutPermission": { + "message": "Wollen Sie das Auslesen über die Navigator-API erlauben?", + "description": "" + }, "askOnlyOnce_title": { "message": "Nur einmal nachfragen", "description": "" @@ -567,6 +583,10 @@ "message": "DOMRect-Auslese vorgetäuscht auf {url}", "description": "" }, + "fakedNavigatorReadout": { + "message": "Navigator-Auslese vorgetäuscht auf {url}", + "description": "" + }, "fakedInput": { "message": "Bei Ausgabe vorgetäuscht auf {url}", "description": "" @@ -959,6 +979,50 @@ "message": "Ein Bruchteil eines Pixels kann durch CSS kontrolliert werden. Eigenschaften eines DOMRect, die multipliziert mit diesem Faktor eine ganze Zahl ergeben, dürfen nicht verändert werden um eine Detektion zu verhindern.", "description": "" }, + "protectNavigator_title": { + "message": "Navigator-API beschützen", + "description": "" + }, + "protectNavigator_description": { + "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": "" + }, + "openNavigatorSettings_title": { + "message": "Navigatoreinstellungen", + "description": "" + }, + "openNavigatorSettings_description": { + "message": "", + "description": "" + }, + "openNavigatorSettings_label": { + "message": "Öffnen", + "description": "" + }, + "navigatorSettings_title": { + "message": "CanvasBlocker Navigatoreinstellungen", + "description": "" + }, + "navigatorSettings_description": { + "message": "Auf dieser Seite können Sie die Navigatoreinstellungen festlegen. Wenn Sie eine Voreinstellung verwenden möchten, sollten Sie immer sowohl eine Betriebssystem- als auch eine Browservoreinstellung verwenden. Danach können Sie Ihre individuellen Änderungen vornehmen.", + "description": "" + }, + "navigatorSettings_presetSection.os": { + "message": "Betriebssystemvoreinstellungen", + "description": "" + }, + "navigatorSettings_presetSection.browser": { + "message": "Browservoreinstellungen", + "description": "" + }, + "navigatorSettings_values": { + "message": "Navigatorwerte", + "description": "" + }, + "navigatorSettings_reset": { + "message": "Zurücksetzen", + "description": "" + }, "theme_title": { "message": "Theme", "description": "" diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 72a6ce0..bc7ee52 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -125,6 +125,10 @@ "message": "DOMRect API", "description": "" }, + "section_Navigator-api":{ + "message": "Navigator API", + "description": "" + }, "displayAdvancedSettings_title": { "message": "Expert mode", @@ -242,6 +246,18 @@ "message": "Do you want to allow DOMRect API readout?", "description": "" }, + "askForNavigatorPermission": { + "message": "Do you want to allow the navigator API?", + "description": "" + }, + "askForNavigatorInputPermission": { + "message": "Do you want to allow navigator API input?", + "description": "" + }, + "askForNavigatorReadoutPermission": { + "message": "Do you want to allow navigator API readout?", + "description": "" + }, "askOnlyOnce_title": { "message": "Ask only once", "description": "" @@ -599,6 +615,10 @@ "message": "Faked DOMRect readout on {url}", "description": "" }, + "fakedNavigatorReadout": { + "message": "Faked navigator readout on {url}", + "description": "" + }, "fakedInput": { "message": "Faked at input on {url}", "description": "" @@ -1003,6 +1023,53 @@ "description": "" }, + "protectNavigator_title": { + "message": "Protect navigator API", + "description": "" + }, + "protectNavigator_description": { + "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": "" + }, + + "openNavigatorSettings_title": { + "message": "Navigator settings", + "description": "" + }, + "openNavigatorSettings_description": { + "message": "", + "description": "" + }, + "openNavigatorSettings_label": { + "message": "Open", + "description": "" + }, + + "navigatorSettings_title": { + "message": "CanvasBlocker navigator settings", + "description": "" + }, + "navigatorSettings_description": { + "message": "In this page you can set the navigator settings. If using a preset you should always use a operating system and browser preset. After selecting these you can still make modifications.", + "description": "" + }, + "navigatorSettings_presetSection.os": { + "message": "Operating system presets", + "description": "" + }, + "navigatorSettings_presetSection.browser": { + "message": "Browser presets", + "description": "" + }, + "navigatorSettings_values": { + "message": "Navigator values", + "description": "" + }, + "navigatorSettings_reset": { + "message": "Reset", + "description": "" + }, + "theme_title": { "message": "Theme", "description": "" diff --git a/lib/main.js b/lib/main.js index b69f08c..2c96935 100644 --- a/lib/main.js +++ b/lib/main.js @@ -140,6 +140,9 @@ message("Initialize data-URL workaround."); require("./dataUrls").init(); + message("Initialize navigator HTTP header protection."); + require("./navigator").init(); + browser.runtime.onInstalled.addListener(function(details){ function openOptions(reason){ if ( diff --git a/lib/modifiedAPI.js b/lib/modifiedAPI.js index c376de7..873c643 100644 --- a/lib/modifiedAPI.js +++ b/lib/modifiedAPI.js @@ -540,4 +540,5 @@ appendModified(require("./modifiedHistoryAPI")); appendModified(require("./modifiedWindowAPI")); appendModified(modifiedDOMRectAPI); + appendModified(require("./modifiedNavigatorAPI")); }()); \ No newline at end of file diff --git a/lib/modifiedNavigatorAPI.js b/lib/modifiedNavigatorAPI.js new file mode 100644 index 0000000..99597b5 --- /dev/null +++ b/lib/modifiedNavigatorAPI.js @@ -0,0 +1,52 @@ +/* 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 { + scope = require.register("./modifiedNavigatorAPI", {}); + } + + const {checkerWrapper} = require("./modifiedAPIFunctions"); + const navigator = require("./navigator"); + + scope.changedGetters = navigator.allProperties.map(function(property){ + return { + objectGetters: [function(window){return window.Navigator && window.Navigator.prototype;}], + name: property, + getterGenerator: function(checker){ + const temp = { + get [property](){ + return checkerWrapper(checker, this, arguments, function(args, check){ + const {prefs, notify, window, original} = check; + const originalValue = original.apply(this, window.Array.from(args)); + const returnValue = navigator.getNavigatorValue(property); + if (originalValue !== returnValue){ + notify("fakedNavigatorReadout"); + } + return returnValue; + }); + } + }; + return Object.getOwnPropertyDescriptor(temp, property).get; + } + }; + }); + + function getStatus(obj, status, prefs){ + status = Object.create(status); + status.active = prefs("protectNavigator", status.url); + return status; + } + + scope.changedGetters.forEach(function(changedGetter){ + changedGetter.type = "readout"; + changedGetter.getStatus = getStatus; + changedGetter.api = "navigator"; + }); +}()); \ No newline at end of file diff --git a/lib/navigator.js b/lib/navigator.js new file mode 100644 index 0000000..f7f8cd7 --- /dev/null +++ b/lib/navigator.js @@ -0,0 +1,116 @@ +/* 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 { + scope = require.register("./navigator", {}); + } + + const settings = require("./settings"); + const logging = require("./logging"); + + scope.allProperties = [ + "appCodeName", "appName", + "appVersion", "buildID", "oscpu", "platform", + "product", + "productSub", "userAgent", "vendor", "vendorSub"]; + const original = {}; + scope.allProperties.forEach(function(property){ + original[property] = window.navigator[property]; + }); + original["real Firefox version"] = window.navigator.userAgent.replace(/^.+Firefox\//, ""); + + let changedValues = {}; + + settings.onloaded(function(){ + changedValues = settings.navigatorDetails; + }); + settings.on("navigatorDetails", function({newValue}){ + changedValues = newValue; + }); + + + function getValue(name, stack = []){ + if (stack.indexOf(name) !== -1){ + return "[ERROR: loop in property definition]"; + } + stack.push(name); + + switch (name){ + case "original value": + return original[stack[stack.length - 2]]; + case "random": + return String.fromCharCode(Math.floor(65 + 85 * Math.random())); + default: + if (changedValues.hasOwnProperty(name)){ + return parseString(changedValues[name], stack.slice()); + } + else { + return original[name]; + } + } + } + function parseString(string, stack){ + return string.replace(/{([a-z[\]_. -]*)}/ig, function(m, name){ + return getValue(name, stack.slice()); + }); + } + + scope.getNavigatorValue = function getNavigatorValue(name){ + return getValue(name); + }; + + function changeHTTPHeader(details){ + if ( + settings.protectNavigator && + ( + !settings.protectedAPIFeatures.hasOwnProperty("userAgent") || + settings.protectedAPIFeatures.userAgent + ) + ){ + for (var header of details.requestHeaders){ + if (header.name.toLowerCase() === "user-agent"){ + header.value = getValue("userAgent"); + } + } + } + return details; + } + + scope.registerHeaderChange = function(){ + logging.message("Register HTTP header modification for navigator protection."); + if (!browser.webRequest.onBeforeSendHeaders.hasListener(changeHTTPHeader)){ + browser.webRequest.onBeforeSendHeaders.addListener( + changeHTTPHeader, + { + urls: [""], + }, + ["blocking", "requestHeaders"]); + } + }; + scope.unregisterHeaderChange = function(){ + logging.message("Removing header modification for navigator protection."); + browser.webRequest.onBeforeSendHeaders.removeListener(changeHTTPHeader); + }; + scope.init = function (){ + settings.onloaded(function(){ + if (!settings.protectNavigator){ + scope.unregisterHeaderChange(); + } + }); + settings.on("protectNavigator", function({newValue}){ + if (newValue){ + scope.registerHeaderChange(); + } + else { + scope.unregisterHeaderChange(); + } + }); + }; +}()); \ No newline at end of file diff --git a/lib/settingDefinitions.js b/lib/settingDefinitions.js index 570a449..95b36fe 100644 --- a/lib/settingDefinitions.js +++ b/lib/settingDefinitions.js @@ -117,6 +117,18 @@ "intersectionRect", "boundingClientRect", "rootBounds", + {name: "Navigator-API", level: 1}, + "appCodeName", + "appName", + "appVersion", + "buildID", + "oscpu", + "platform", + "product", + "productSub", + "userAgent", + "vendor", + "vendorSub" ], defaultKeyValue: true }, @@ -222,6 +234,7 @@ "history", "window", "domRect", + "navigator", ], defaultKeyValue: false }, @@ -293,6 +306,14 @@ name: "blockDataURLs", defaultValue: true }, + { + name: "protectNavigator", + defaultValue: false + }, + { + name: "navigatorDetails", + defaultValue: {}, + }, { name: "displayAdvancedSettings", defaultValue: false diff --git a/manifest.json b/manifest.json index 2b043a6..5d0830d 100644 --- a/manifest.json +++ b/manifest.json @@ -19,6 +19,7 @@ "lib/persistentRndStorage.js", "lib/dataUrls.js", "lib/notification.js", + "lib/navigator.js", "lib/main.js" ] }, @@ -43,6 +44,8 @@ "lib/modifiedHistoryAPI.js", "lib/modifiedWindowAPI.js", "lib/modifiedDOMRectAPI.js", + "lib/navigator.js", + "lib/modifiedNavigatorAPI.js", "lib/modifiedAPI.js", "lib/randomSupplies.js", "lib/intercept.js", diff --git a/options/navigator.css b/options/navigator.css new file mode 100644 index 0000000..99870c8 --- /dev/null +++ b/options/navigator.css @@ -0,0 +1,36 @@ +.presetSection ul { + list-style-type: none; + padding: 0; + margin: 0; +} + +.presetSection ul li { + display: inline-block; +} + +.button { + display: inline-block; + border: none; + background-color: white; + border: 1px solid lightgray; + margin: 2px; + width: 7em; + box-sizing: border-box; + padding: 0.5em; + outline: none; + cursor: pointer; +} +.active .button { + border-color: red; +} +.button:focus { + outline: none; + border-style: dotted; +} +.button::-moz-focus-inner { + border: 0; +} + +.values tbody + tbody tr:first-child td { + padding-top: 1em; +} \ No newline at end of file diff --git a/options/navigator.html b/options/navigator.html new file mode 100644 index 0000000..5536fa9 --- /dev/null +++ b/options/navigator.html @@ -0,0 +1,17 @@ + + + + CanvasBlocker navigator settings + + + + + + + + + + + + + \ No newline at end of file diff --git a/options/navigator.js b/options/navigator.js new file mode 100644 index 0000000..1e1f3da --- /dev/null +++ b/options/navigator.js @@ -0,0 +1,237 @@ +/* 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 settings = require("./settings"); + const navigator = require("./navigator"); + + const title = document.createElement("h1"); + title.className = "title"; + title.textContent = browser.i18n.getMessage("navigatorSettings_title"); + document.body.appendChild(title); + + document.querySelector("head title").textContent = title.textContent; + + const description = document.createElement("div"); + description.className = "description"; + description.textContent = browser.i18n.getMessage("navigatorSettings_description"); + document.body.appendChild(description); + + function presetSection(title, presets){ + const container = document.createElement("div"); + container.className = "presetSection"; + + const titleNode = document.createElement("h2"); + titleNode.className = "title"; + titleNode.textContent = browser.i18n.getMessage("navigatorSettings_presetSection." + title); + container.appendChild(titleNode); + + const presetsList = document.createElement("ul"); + presetsList.className = "presets"; + container.appendChild(presetsList); + + Object.keys(presets).forEach(function(presetName){ + const li = document.createElement("li"); + li.className = "preset " + presetName; + presetsList.appendChild(li); + + const button = document.createElement("button"); + button.className = "button"; + button.textContent = presetName; + li.appendChild(button); + + const presetProperties = presets[presetName]; + function checkActive(currentProperties){ + if (Object.keys(presetProperties).every(function(property){ + return currentProperties[property] === presetProperties[property]; + })){ + li.classList.add("active"); + } + else { + li.classList.remove("active"); + } + } + settings.on("navigatorDetails", function({newValue}){ + checkActive(newValue); + }); + settings.onloaded(function(){ + checkActive(settings.navigatorDetails); + }); + + button.addEventListener("click", function(){ + const data = settings.navigatorDetails; + Object.keys(presetProperties).forEach(function(property){ + if (presetProperties[property] === undefined){ + delete data[property]; + } + else { + data[property] = presetProperties[property]; + } + }); + settings.navigatorDetails = data; + }); + }); + + return container; + } + + + const osPresets = { + Windows: { + windowManager: "Windows", + platform: "Win32", + platformDetails: "Windows NT 10.0; Win64; x64", + oscpu: "{platformDetails}" + }, + Linux: { + windowManager: "X11", + platform: "Linux x86_64", + platformDetails: "X11; Linux x86_64", + oscpu: "{platform}" + }, + "Mac OS X": { + windowManager: "Macintosh", + platform: "MacIntel", + platformDetails: "Macintosh; {oscpu}", + oscpu: "Intel Mac OS X 10.14.3" + } + }; + + const browserPresets = { + Edge: { + chromeVersion: "71.0.3578.98", + edgeVersion: "17.17134", + firefoxVersion: undefined, + operaVersion: undefined, + safariVersion: undefined, + + appVersion: "5.0 ({platformDetails}) AppleWebKit/537.36 (KHTML, like Gecko) " + + "Chrome/{chromeVersion} Safari/537.36 Edge/{edgeVersion}", + productSub: "20030107", + userAgent: "Mozilla/{appVersion}", + vendor: undefined, + }, + Opera: { + chromeVersion: "71.0.3578.98", + edgeVersion: undefined, + firefoxVersion: undefined, + operaVersion: "58.0.3135.65", + safariVersion: undefined, + + appVersion: "5.0 ({platformDetails}) AppleWebKit/537.36 (KHTML, like Gecko) " + + "Chrome/{chromeVersion} Safari/537.36 OPR/{operaVersion}", + productSub: "20030107", + userAgent: "Mozilla/{appVersion}", + vendor: "Google Inc.", + }, + Chrome: { + chromeVersion: "71.0.3578.98", + edgeVersion: undefined, + firefoxVersion: undefined, + operaVersion: undefined, + safariVersion: undefined, + + appVersion: "5.0 ({platformDetails}) AppleWebKit/537.36 (KHTML, like Gecko) " + + "Chrome/{chromeVersion} Safari/537.36", + productSub: "20030107", + userAgent: "Mozilla/{appVersion}", + vendor: "Google Inc.", + }, + Safari: { + chromeVersion: undefined, + edgeVersion: undefined, + firefoxVersion: undefined, + operaVersion: undefined, + safariVersion: "12.0.3", + + appVersion: "5.0 ({platformDetails}) AppleWebKit/605.1.15 (KHTML, like Gecko) " + + "Version/{safariVersion} Safari/605.1.15", + productSub: "20030107", + userAgent: "Mozilla/{appVersion}", + vendor: "Apple Computer, Inc.", + }, + Firefox: { + chromeVersion: undefined, + edgeVersion: undefined, + firefoxVersion: "{real Firefox version}", + operaVersion: undefined, + safariVersion: undefined, + + appVersion: "5.0 ({windowManager})", + buildID: "20181001000000", + productSub: "20100101", + userAgent: "Mozilla/5.0 ({platformDetails}; rv:{firefoxVersion}) Gecko/20100101 Firefox/{firefoxVersion}", + vendor: undefined, + } + }; + + document.body.appendChild(presetSection("os", osPresets)); + document.body.appendChild(presetSection("browser", browserPresets)); + + const valueTitle = document.createElement("h2"); + valueTitle.textContent = browser.i18n.getMessage("navigatorSettings_values"); + document.body.appendChild(valueTitle); + + const valueSection = document.createElement("table"); + valueSection.className = "values"; + document.body.appendChild(valueSection); + + function updateValueSection(currentProperties){ + function createPropertyRow(section, property){ + const row = document.createElement("tr"); + + const name = document.createElement("td"); + name.textContent = property; + row.appendChild(name); + + const value = document.createElement("td"); + row.appendChild(value); + + const input = document.createElement("input"); + value.appendChild(input); + input.value = currentProperties.hasOwnProperty(property)? currentProperties[property]: "{original value}"; + input.addEventListener("change", function(){ + currentProperties[property] = this.value; + settings.navigatorDetails = currentProperties; + }); + + const computedValue = document.createElement("td"); + computedValue.textContent = navigator.getNavigatorValue(property); + row.appendChild(computedValue); + + section.appendChild(row); + } + + valueSection.innerHTML = ""; + let section = document.createElement("tbody"); + section.className = "helperValues"; + valueSection.appendChild(section); + + Object.keys(currentProperties).filter(function(property){ + return navigator.allProperties.indexOf(property) === -1; + }).sort().forEach(createPropertyRow.bind(undefined, section)); + + section = document.createElement("tbody"); + section.className = "realValues"; + valueSection.appendChild(section); + + navigator.allProperties.forEach(createPropertyRow.bind(undefined, section)); + } + + settings.on("navigatorDetails", function({newValue}){ + updateValueSection(newValue); + }); + settings.onloaded(function(){ + updateValueSection(settings.navigatorDetails); + }); + + const resetButton = document.createElement("button"); + resetButton.className = "button"; + resetButton.textContent = browser.i18n.getMessage("navigatorSettings_reset"); + resetButton.addEventListener("click", function(){ + settings.navigatorDetails = {}; + }); + document.body.appendChild(resetButton); +}()); \ No newline at end of file diff --git a/options/options.js b/options/options.js index 65021ac..d2560bb 100644 --- a/options/options.js +++ b/options/options.js @@ -15,6 +15,10 @@ const searchParameters = new URLSearchParams(window.location.search); var callbacks = { + openNavigatorSettings: function(){ + logging.verbose("open navigator settings"); + window.open("navigator.html", "_blank"); + }, showReleaseNotes: function(){ logging.verbose("open release notes"); window.open("../releaseNotes.txt", "_blank"); diff --git a/options/settingsDisplay.js b/options/settingsDisplay.js index 84c8b53..5fa594a 100644 --- a/options/settingsDisplay.js +++ b/options/settingsDisplay.js @@ -486,6 +486,28 @@ "displayAdvancedSettings": [true] } }, + "Navigator-API", + { + "name": "protectNavigator" + }, + { + "name": "protectedAPIFeatures", + "displayedSection": "Navigator-API", + "displayDependencies": [ + { + "protectNavigator": [true], + "displayAdvancedSettings": [true] + } + ] + }, + { + "name": "openNavigatorSettings", + "displayDependencies": [ + { + "protectNavigator": [true] + } + ] + }, "misc", { "name": "theme" diff --git a/releaseNotes.txt b/releaseNotes.txt index 360b970..c1e569d 100644 --- a/releaseNotes.txt +++ b/releaseNotes.txt @@ -3,7 +3,7 @@ Version 0.5.9: - new features: - - + - added protection for navigator properties fixes: - diff --git a/test/index.html b/test/index.html index 597f575..6e25370 100644 --- a/test/index.html +++ b/test/index.html @@ -17,6 +17,7 @@
  • Detection test
  • Performance test
  • Support for webGL
  • +
  • Navigator test
  • Settings loading
  • \ No newline at end of file diff --git a/test/navigatorTest.js b/test/navigatorTest.js new file mode 100644 index 0000000..35d430f --- /dev/null +++ b/test/navigatorTest.js @@ -0,0 +1,34 @@ + +var createLog = function(){ + "use strict"; + + var div = document.getElementById("log"); + + return function createLog(){ + var logDiv = document.createElement("div"); + logDiv.className = "log"; + div.appendChild(logDiv); + return function createLine(str){ + var logLine = document.createElement("div"); + logLine.className = "logLine"; + logDiv.appendChild(logLine); + logLine.textContent = str; + return function updateLine(str){ + logLine.textContent = str; + }; + }; + }; +}(); + +var log = createLog(); + +log("user agent equal between server and client: " + (serverUserAgent === navigator.userAgent)); + +Object.keys(navigator.__proto__).sort().forEach(function(property){ + "use strict"; + + var value = navigator[property]; + if ((typeof value) === "string"){ + log(property + ": " + value); + } +}); diff --git a/test/navigatorTest.php b/test/navigatorTest.php new file mode 100644 index 0000000..6d4d96d --- /dev/null +++ b/test/navigatorTest.php @@ -0,0 +1,23 @@ + + + + Navigator test + + + + + +

    Navigator test

    +Tests the navigator properties. +
    +
    +
    + server site user agent: +
    +
    +
    + + + \ No newline at end of file