mirror of
https://github.com/kkapsner/CanvasBlocker
synced 2024-12-31 17:11:54 +01:00
First working webExtesion.
This commit is contained in:
parent
4ea073132d
commit
cba5680406
70
lib/frame.js
70
lib/frame.js
@ -4,7 +4,6 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
const {process, frames} = require("sdk/remote/child");
|
|
||||||
const {intercept} = require("./intercept.js");
|
const {intercept} = require("./intercept.js");
|
||||||
const {ask} = require("./askForPermission.js");
|
const {ask} = require("./askForPermission.js");
|
||||||
const {check: originalCheck, checkStack: originalCheckStack} = require("./check.js");
|
const {check: originalCheck, checkStack: originalCheckStack} = require("./check.js");
|
||||||
@ -38,7 +37,7 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
function notify(data){
|
function notify(data){
|
||||||
process.port.emit("canvasBlocker-notify", data);
|
browser.runtime.sendMessage({"canvasBlocker-notify": data});
|
||||||
}
|
}
|
||||||
|
|
||||||
const preferences = require("sdk/simple-prefs");
|
const preferences = require("sdk/simple-prefs");
|
||||||
@ -46,22 +45,59 @@
|
|||||||
return preferences.prefs[name];
|
return preferences.prefs[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
frames.forEvery(function(frame){
|
|
||||||
frame.addEventListener("DOMWindowCreated", function(ev){
|
var interceptedWindows = new WeakMap();
|
||||||
function notify(data){
|
function interceptWindow(window){
|
||||||
frame.port.emit("canvasBlocker-notify", data);
|
if (interceptedWindows.get(window)){
|
||||||
}
|
return false;
|
||||||
if (enabled){
|
}
|
||||||
var subject = ev.target.defaultView;
|
intercept(
|
||||||
intercept(
|
{subject: window},
|
||||||
{subject},
|
{check, checkStack, ask: askWrapper, notify, prefs}
|
||||||
{check, checkStack, ask: askWrapper, notify, prefs}
|
);
|
||||||
);
|
|
||||||
}
|
[window.HTMLIFrameElement, window.HTMLFrameElement].forEach(function(constructor){
|
||||||
|
var oldContentWindowGetter = constructor.prototype.__lookupGetter__("contentWindow");
|
||||||
|
Object.defineProperty(
|
||||||
|
constructor.prototype.wrappedJSObject,
|
||||||
|
"contentWindow",
|
||||||
|
{
|
||||||
|
enumerable: true,
|
||||||
|
configureable: true,
|
||||||
|
get: exportFunction(function(){
|
||||||
|
var window = oldContentWindowGetter.call(this);
|
||||||
|
interceptWindow(window);
|
||||||
|
return window;
|
||||||
|
}, window)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
var oldContentDocumentGetter = constructor.prototype.__lookupGetter__("contentDocument");
|
||||||
|
Object.defineProperty(
|
||||||
|
constructor.prototype.wrappedJSObject,
|
||||||
|
"contentDocument",
|
||||||
|
{
|
||||||
|
enumerable: true,
|
||||||
|
configureable: true,
|
||||||
|
get: exportFunction(function(){
|
||||||
|
var document = oldContentDocumentGetter.call(this);
|
||||||
|
interceptWindow(document.defaultView);
|
||||||
|
return document;
|
||||||
|
}, window)
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
interceptedWindows.set(window, true);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (enabled){
|
||||||
|
interceptWindow(window);
|
||||||
|
}
|
||||||
|
|
||||||
process.port.on("canvasBlocker-unload", function unload(){
|
browser.runtime.onMessage.addListener(function(data){
|
||||||
enabled = false;
|
if (data["canvasBlocker-unload"]){
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}());
|
}());
|
@ -60,7 +60,7 @@
|
|||||||
{
|
{
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configureable: false,
|
configureable: false,
|
||||||
get: exportFunction(function()
|
get: exportFunction(function(){
|
||||||
var url = getURL(window);
|
var url = getURL(window);
|
||||||
if (!url){
|
if (!url){
|
||||||
return undef;
|
return undef;
|
||||||
|
204
lib/lists.js
204
lib/lists.js
@ -3,110 +3,124 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
(function(){
|
||||||
var preferences = require("sdk/simple-prefs");
|
|
||||||
var prefService = require("sdk/preferences/service");
|
|
||||||
var prefs = preferences.prefs;
|
|
||||||
|
|
||||||
|
|
||||||
function getDomainRegExpList(domainList){
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var list = domainList
|
|
||||||
.split(",")
|
var scope;
|
||||||
.map(function(entry){
|
if ((typeof exports) !== "undefined"){
|
||||||
return entry.replace(/^\s+|\s+$/g, "");
|
scope = exports;
|
||||||
})
|
}
|
||||||
.filter(function(entry){
|
else {
|
||||||
return !!entry.length;
|
window.scope.lists = {};
|
||||||
})
|
scope = window.scope.lists;
|
||||||
.map(function(entry){
|
}
|
||||||
var regExp;
|
|
||||||
var domain = !!entry.match(/^[\w.]+$/);
|
var preferences = require("sdk/simple-prefs");
|
||||||
if (domain){
|
var prefs = preferences.prefs;
|
||||||
regExp = new RegExp("(?:^|\\.)" + entry.replace(/([\\\+\*\?\[\^\]\$\(\)\{\}\=\!\|\.])/g, "\\$1") + "\\.?$", "i");
|
|
||||||
}
|
|
||||||
else {
|
function getDomainRegExpList(domainList){
|
||||||
regExp = new RegExp(entry, "i");
|
"use strict";
|
||||||
}
|
|
||||||
return {
|
var list = domainList
|
||||||
match: function(url){
|
.split(",")
|
||||||
if (domain){
|
.map(function(entry){
|
||||||
return (url.hostname || "").match(regExp);
|
return entry.replace(/^\s+|\s+$/g, "");
|
||||||
}
|
})
|
||||||
else {
|
.filter(function(entry){
|
||||||
return url.href.match(regExp);
|
return !!entry.length;
|
||||||
}
|
})
|
||||||
|
.map(function(entry){
|
||||||
|
var regExp;
|
||||||
|
var domain = !!entry.match(/^[\w.]+$/);
|
||||||
|
if (domain){
|
||||||
|
regExp = new RegExp("(?:^|\\.)" + entry.replace(/([\\\+\*\?\[\^\]\$\(\)\{\}\=\!\|\.])/g, "\\$1") + "\\.?$", "i");
|
||||||
}
|
}
|
||||||
};
|
else {
|
||||||
});
|
regExp = new RegExp(entry, "i");
|
||||||
|
}
|
||||||
list.match = function(url){
|
return {
|
||||||
return this.some(function(entry){
|
match: function(url){
|
||||||
return entry.match(url);
|
if (domain){
|
||||||
|
return (url.hostname || "").match(regExp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return url.href.match(regExp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
list.match = function(url){
|
||||||
|
return this.some(function(entry){
|
||||||
|
return entry.match(url);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
var lists = {
|
||||||
|
white: [],
|
||||||
|
"ignore": [],
|
||||||
|
black: []
|
||||||
|
};
|
||||||
|
|
||||||
|
function updateList(type){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
return list;
|
lists[type] = getDomainRegExpList(prefs[type + "List"]);
|
||||||
}
|
}
|
||||||
|
Object.keys(lists).forEach(function(type){
|
||||||
var lists = {
|
"use strict";
|
||||||
white: [],
|
|
||||||
"ignore": [],
|
preferences.on(type + "List", function(){
|
||||||
black: []
|
updateList(type);
|
||||||
};
|
});
|
||||||
|
|
||||||
function updateList(type){
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
lists[type] = getDomainRegExpList(prefs[type + "List"]);
|
|
||||||
}
|
|
||||||
Object.keys(lists).forEach(function(type){
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
preferences.on(type + "List", function(){
|
|
||||||
updateList(type);
|
updateList(type);
|
||||||
});
|
});
|
||||||
updateList(type);
|
|
||||||
});
|
|
||||||
|
|
||||||
function updateStackList(){
|
function updateStackList(){
|
||||||
var list;
|
var list;
|
||||||
try {
|
try {
|
||||||
var data = JSON.parse(prefs.stackList);
|
var data = JSON.parse(prefs.stackList);
|
||||||
if (!Array.isArray(data)){
|
if (!Array.isArray(data)){
|
||||||
data = [data];
|
data = [data];
|
||||||
|
}
|
||||||
|
list = data.filter(function(entry){
|
||||||
|
return typeof entry === "object" && typeof entry.url === "string";
|
||||||
|
});
|
||||||
}
|
}
|
||||||
list = data.filter(function(entry){
|
catch(e){
|
||||||
return typeof entry === "object" && typeof entry.url === "string";
|
list = [];
|
||||||
});
|
}
|
||||||
|
list.match = function(stack){
|
||||||
|
return this.some(function(stackRule){
|
||||||
|
return stack.match(stackRule);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
lists.stack = list;
|
||||||
}
|
}
|
||||||
catch(e){
|
lists.stack = [];
|
||||||
list = [];
|
preferences.on("stackList", function(){
|
||||||
}
|
updateStackList();
|
||||||
list.match = function(stack){
|
});
|
||||||
return this.some(function(stackRule){
|
|
||||||
return stack.match(stackRule);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
lists.stack = list;
|
|
||||||
}
|
|
||||||
lists.stack = [];
|
|
||||||
preferences.on("stackList", function(){
|
|
||||||
updateStackList();
|
updateStackList();
|
||||||
});
|
|
||||||
updateStackList();
|
|
||||||
|
|
||||||
exports.get = function getList(type){
|
scope.get = function getList(type){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
return lists[type];
|
return lists[type];
|
||||||
};
|
};
|
||||||
exports.appendTo = function appendToList(type, entry){
|
scope.appendTo = function appendToList(type, entry){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
prefs[type + "List"] += (prefs[type + "List"]? ",": "") + entry;
|
prefs[type + "List"] += (prefs[type + "List"]? ",": "") + entry;
|
||||||
prefService.set("extensions.CanvasBlocker@kkapsner.de." + type + "List", prefs[type + "List"]);
|
var obj = {};
|
||||||
updateList(type);
|
obj[type + "List"] = prefs[type + "List"];
|
||||||
};
|
browser.storage.local.set(obj);
|
||||||
exports.update = updateList;
|
updateList(type);
|
||||||
|
};
|
||||||
|
scope.update = updateList;
|
||||||
|
}());
|
10
lib/main.js
10
lib/main.js
@ -4,6 +4,16 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
console.log("start main script");
|
||||||
|
browser.runtime.onMessage.addListener(function(data){
|
||||||
|
console.log("got data", data);
|
||||||
|
});
|
||||||
|
browser.runtime.onConnect.addListener(function(port){
|
||||||
|
console.log("got port");
|
||||||
|
});
|
||||||
|
console.log("end main script");
|
||||||
|
return null;
|
||||||
require("./stylePreferencePane");
|
require("./stylePreferencePane");
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,7 +5,16 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
let Cu = require("chrome").Cu;
|
var scope;
|
||||||
|
if ((typeof exports) !== "undefined"){
|
||||||
|
scope = exports;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
window.scope.modifiedAPI = {};
|
||||||
|
scope = window.scope.modifiedAPI;
|
||||||
|
}
|
||||||
|
|
||||||
|
// let Cu = require("chrome").Cu;
|
||||||
|
|
||||||
var randomSupply = null;
|
var randomSupply = null;
|
||||||
|
|
||||||
@ -87,12 +96,12 @@
|
|||||||
return status.type.indexOf(type) !== -1;
|
return status.type.indexOf(type) !== -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.setRandomSupply = function(supply){
|
scope.setRandomSupply = function(supply){
|
||||||
randomSupply = supply;
|
randomSupply = supply;
|
||||||
};
|
};
|
||||||
var canvasContextType = new WeakMap();
|
var canvasContextType = new WeakMap();
|
||||||
// changed functions and their fakes
|
// changed functions and their fakes
|
||||||
exports.changedFunctions = {
|
scope.changedFunctions = {
|
||||||
getContext: {
|
getContext: {
|
||||||
type: "context",
|
type: "context",
|
||||||
getStatus: function(obj, status){
|
getStatus: function(obj, status){
|
||||||
@ -288,7 +297,7 @@
|
|||||||
return function readPixels(x, y, width, height, format, type, pixels){
|
return function readPixels(x, y, width, height, format, type, pixels){
|
||||||
// not able to use the getFakeCanvas function because the context type is wrong...
|
// not able to use the getFakeCanvas function because the context type is wrong...
|
||||||
notify("fakedReadout");
|
notify("fakedReadout");
|
||||||
var xPixels = Cu.waiveXrays(pixels);
|
var xPixels = pixels//Cu.waiveXrays(pixels);
|
||||||
var ret = original.apply(this, window.Array.from(arguments));
|
var ret = original.apply(this, window.Array.from(arguments));
|
||||||
var l = xPixels.length;
|
var l = xPixels.length;
|
||||||
var rng = randomSupply.getRng(l, window);
|
var rng = randomSupply.getRng(l, window);
|
||||||
|
@ -5,6 +5,15 @@
|
|||||||
(function(){
|
(function(){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var scope;
|
||||||
|
if ((typeof exports) !== "undefined"){
|
||||||
|
scope = exports;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
window.scope.randomSupplies = {};
|
||||||
|
scope = window.scope.randomSupplies;
|
||||||
|
}
|
||||||
|
|
||||||
function getDomain(window){
|
function getDomain(window){
|
||||||
if (!window.location.href || window.location.href === "about:blank"){
|
if (!window.location.href || window.location.href === "about:blank"){
|
||||||
if (window !== window.parent){
|
if (window !== window.parent){
|
||||||
@ -19,12 +28,14 @@
|
|||||||
const getPersistentRnd = (function(){
|
const getPersistentRnd = (function(){
|
||||||
var persistentRnd = Object.create(null);
|
var persistentRnd = Object.create(null);
|
||||||
|
|
||||||
const {process} = require("sdk/remote/child");
|
browser.runtime.onMessage.addListener(function(data){
|
||||||
process.port.on("canvasBlocker-set-domain-rnd", function(process, {domain, rnd}){
|
if (data["canvasBlocker-set-domain-rnd"]){
|
||||||
persistentRnd[domain] = new Uint8Array(rnd);
|
var {domain, rnd} = data["canvasBlocker-set-domain-rnd"];
|
||||||
});
|
persistentRnd[domain] = new Uint8Array(rnd);
|
||||||
process.port.on("canvasBlocker-clear-domain-rnd", function(){
|
}
|
||||||
persistentRnd = Object.create(null);
|
if (data["canvasBlocker-clear-domain-rnd"]){
|
||||||
|
persistentRnd = Object.create(null);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return function getPersistentRnd(window){
|
return function getPersistentRnd(window){
|
||||||
@ -33,12 +44,12 @@
|
|||||||
// create the (sub-)domains random numbers if not existing
|
// create the (sub-)domains random numbers if not existing
|
||||||
persistentRnd[domain] = new Uint8Array(128);
|
persistentRnd[domain] = new Uint8Array(128);
|
||||||
window.crypto.getRandomValues(persistentRnd[domain]);
|
window.crypto.getRandomValues(persistentRnd[domain]);
|
||||||
process.port.emit("canvasBlocker-new-domain-rnd", {domain, rnd: Array.from(persistentRnd[domain])});
|
browser.runtime.sendMessage({"canvasBlocker-new-domain-rnd": {domain, rnd: Array.from(persistentRnd[domain])}});
|
||||||
}
|
}
|
||||||
return persistentRnd[domain];
|
return persistentRnd[domain];
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
exports.persistent = {
|
scope.persistent = {
|
||||||
getRng: function(length, window){
|
getRng: function(length, window){
|
||||||
var bitSet = getPersistentRnd(window);
|
var bitSet = getPersistentRnd(window);
|
||||||
|
|
||||||
@ -60,7 +71,7 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.nonPersistent = {
|
scope.nonPersistent = {
|
||||||
getRng: function(length, window){
|
getRng: function(length, window){
|
||||||
// Initialize the random number batch creation
|
// Initialize the random number batch creation
|
||||||
var randomI = 65536;
|
var randomI = 65536;
|
||||||
|
56
manifest.json
Normal file
56
manifest.json
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"name": "CanvasBlocker",
|
||||||
|
"title": "__MSG_addon_title__",
|
||||||
|
"id": "CanvasBlocker@kkapsner.de",
|
||||||
|
"keywords": "privacy, canvas, fingerprinting",
|
||||||
|
"description": "__MSG_addon_description__",
|
||||||
|
"homepage": "https://github.com/kkapsner/CanvasBlocker/",
|
||||||
|
"version": "0.4.0-Development",
|
||||||
|
"background": {
|
||||||
|
"scripts": ["lib/main.js"]
|
||||||
|
},
|
||||||
|
"content_scripts": [{
|
||||||
|
"matches": ["<all_urls>"],
|
||||||
|
"all_frames": true,
|
||||||
|
"run_at": "document_start",
|
||||||
|
"js": [
|
||||||
|
"lib/defaultSettings.js",
|
||||||
|
"lib/require.js",
|
||||||
|
|
||||||
|
"lib/modifiedAPI.js",
|
||||||
|
"lib/randomSupplies.js",
|
||||||
|
"lib/intercept.js",
|
||||||
|
|
||||||
|
"lib/callingStack.js",
|
||||||
|
"lib/askForPermission.js",
|
||||||
|
|
||||||
|
"lib/lists.js",
|
||||||
|
"lib/check.js",
|
||||||
|
|
||||||
|
"lib/frame.js"
|
||||||
|
]
|
||||||
|
}],
|
||||||
|
"options_ui": {
|
||||||
|
"browser_style": true,
|
||||||
|
"page": "options/options.html"
|
||||||
|
},
|
||||||
|
"author": "Korbinian Kapsner",
|
||||||
|
"license": "MPL 2.0",
|
||||||
|
"permissions": [
|
||||||
|
"<all_urls>",
|
||||||
|
"storage",
|
||||||
|
"tabs",
|
||||||
|
"activeTab",
|
||||||
|
"declarativeContentScript",
|
||||||
|
"events"
|
||||||
|
],
|
||||||
|
|
||||||
|
"applications": {
|
||||||
|
"gecko": {
|
||||||
|
"id": "CanvasBlocker@kkapsner.de",
|
||||||
|
"strict_min_version": "50.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default_locale": "en",
|
||||||
|
"manifest_version": 2
|
||||||
|
}
|
183
package.json
183
package.json
@ -1,183 +0,0 @@
|
|||||||
{
|
|
||||||
"locales": {
|
|
||||||
"de": {
|
|
||||||
"title": "CanvasBlocker",
|
|
||||||
"description": "Ändert die JS-API zum Ändern von <canvas> um Canvas-Fingerprinting zu verhindern."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"name": "canvasblocker",
|
|
||||||
"title": "CanvasBlocker",
|
|
||||||
"id": "CanvasBlocker@kkapsner.de",
|
|
||||||
"keywords": "privacy, canvas, fingerprinting",
|
|
||||||
"description": "Changes the JS-API for modifying <canvas> to prevent Canvas-Fingerprinting.",
|
|
||||||
"homepage": "https://github.com/kkapsner/CanvasBlocker/",
|
|
||||||
"preferences": [
|
|
||||||
{
|
|
||||||
"name": "whiteList",
|
|
||||||
"title": "White list",
|
|
||||||
"type": "string",
|
|
||||||
"value": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "blackList",
|
|
||||||
"title": "Black list",
|
|
||||||
"type": "string",
|
|
||||||
"value": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "blockMode",
|
|
||||||
"title": "block mode",
|
|
||||||
"type": "menulist",
|
|
||||||
"value": "fakeReadout",
|
|
||||||
"options": [
|
|
||||||
{
|
|
||||||
"value": "blockReadout",
|
|
||||||
"label": "block readout API"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": "fakeReadout",
|
|
||||||
"label": "fake readout API"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": "fakeInput",
|
|
||||||
"label": "fake input API"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": "askReadout",
|
|
||||||
"label": "ask for readout API permission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": "",
|
|
||||||
"label": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": "blockEverything",
|
|
||||||
"label": "block everything"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": "block",
|
|
||||||
"label": "allow only white list"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": "ask",
|
|
||||||
"label": "ask for permission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": "allow",
|
|
||||||
"label": "block only black list"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": "allowEverything",
|
|
||||||
"label": "allow everything"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "maxFakeSize",
|
|
||||||
"title": "Maximal fake size",
|
|
||||||
"type": "integer",
|
|
||||||
"value": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "rng",
|
|
||||||
"title": "Random number generator",
|
|
||||||
"type": "menulist",
|
|
||||||
"value": "nonPersistent",
|
|
||||||
"options": [
|
|
||||||
{
|
|
||||||
"value": "nonPersistent",
|
|
||||||
"label": "non persistent"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": "persistent",
|
|
||||||
"label": "persistent"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "persistentRndStorage",
|
|
||||||
"title": "Persistent storage",
|
|
||||||
"type": "string",
|
|
||||||
"value": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "storePersistentRnd",
|
|
||||||
"title": "Store persistent data",
|
|
||||||
"type": "bool",
|
|
||||||
"value": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "clearPersistentRnd",
|
|
||||||
"title": "Clear persistent random storage",
|
|
||||||
"type": "control",
|
|
||||||
"label": "Clear"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "askOnlyOnce",
|
|
||||||
"title": "Ask only once",
|
|
||||||
"type": "bool",
|
|
||||||
"value": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "showNotifications",
|
|
||||||
"title": "Show notifications",
|
|
||||||
"type": "bool",
|
|
||||||
"value": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "notificationDisplayTime",
|
|
||||||
"title": "notification display time",
|
|
||||||
"type": "integer",
|
|
||||||
"value": 30
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ignoreList",
|
|
||||||
"title": "Ignore list",
|
|
||||||
"type": "string",
|
|
||||||
"value": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "showCallingFile",
|
|
||||||
"title": "Display calling file",
|
|
||||||
"type": "bool",
|
|
||||||
"value": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "showCompleteCallingStack",
|
|
||||||
"title": "Display complete calling stack",
|
|
||||||
"type": "bool",
|
|
||||||
"value": false
|
|
||||||
},{
|
|
||||||
"name": "enableStackList",
|
|
||||||
"title": "Use file specific scoped white list",
|
|
||||||
"type": "bool",
|
|
||||||
"value": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "stackList",
|
|
||||||
"title": "File specific white list",
|
|
||||||
"type": "string",
|
|
||||||
"value": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "showReleaseNotes",
|
|
||||||
"title": "Release notes",
|
|
||||||
"type": "control",
|
|
||||||
"label": "Show"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"main": "lib/main.js",
|
|
||||||
"author": "Korbinian Kapsner",
|
|
||||||
"license": "MPL 2.0",
|
|
||||||
"version": "0.4.0-Development",
|
|
||||||
|
|
||||||
"engines": {
|
|
||||||
"firefox": ">=50.0",
|
|
||||||
"fennec": ">=50.0"
|
|
||||||
},
|
|
||||||
"permissions": {
|
|
||||||
"private-browsing": true,
|
|
||||||
"multiprocess": true
|
|
||||||
},
|
|
||||||
"hasEmbeddedWebExtension": true
|
|
||||||
}
|
|
@ -1,6 +1,9 @@
|
|||||||
Version 0.4.0:
|
Version 0.4.0:
|
||||||
|
todos:
|
||||||
|
- import settings in content script (have to wait for the new API to register content scripts)
|
||||||
|
- check if webGL is still working
|
||||||
changes:
|
changes:
|
||||||
-
|
- switched to webExtension
|
||||||
|
|
||||||
new features:
|
new features:
|
||||||
-
|
-
|
||||||
|
Loading…
x
Reference in New Issue
Block a user