mirror of
https://github.com/gorhill/uMatrix.git
synced 2024-09-30 09:06:56 +13:00
work toward resolving #853
This commit is contained in:
parent
07eb60abc6
commit
537f8ef79a
3 changed files with 147 additions and 217 deletions
263
src/js/matrix.js
263
src/js/matrix.js
|
@ -31,7 +31,7 @@
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var µm = µMatrix;
|
var µm = µMatrix;
|
||||||
var magicId = 'tckuvvpyvswo';
|
var magicId = 'axyorpwxtmnf';
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
@ -58,24 +58,24 @@ Matrix.GrayIndirect = Matrix.Gray | Matrix.Indirect;
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var typeBitOffsets = {
|
var typeBitOffsets = new Map([
|
||||||
'*': 0,
|
[ '*', 0 ],
|
||||||
'doc': 2,
|
[ 'doc', 2 ],
|
||||||
'cookie': 4,
|
[ 'cookie', 4 ],
|
||||||
'css': 6,
|
[ 'css', 6 ],
|
||||||
'image': 8,
|
[ 'image', 8 ],
|
||||||
'media': 10,
|
[ 'media', 10 ],
|
||||||
'script': 12,
|
[ 'script', 12 ],
|
||||||
'xhr': 14,
|
[ 'xhr', 14 ],
|
||||||
'frame': 16,
|
[ 'frame', 16 ],
|
||||||
'other': 18
|
[ 'other', 18 ]
|
||||||
};
|
]);
|
||||||
|
|
||||||
var stateToNameMap = {
|
var stateToNameMap = new Map([
|
||||||
'1': 'block',
|
[ 1, 'block' ],
|
||||||
'2': 'allow',
|
[ 2, 'allow' ],
|
||||||
'3': 'inherit'
|
[ 3, 'inherit' ]
|
||||||
};
|
]);
|
||||||
|
|
||||||
var nameToStateMap = {
|
var nameToStateMap = {
|
||||||
'block': 1,
|
'block': 1,
|
||||||
|
@ -84,63 +84,36 @@ var nameToStateMap = {
|
||||||
'inherit': 3
|
'inherit': 3
|
||||||
};
|
};
|
||||||
|
|
||||||
var switchBitOffsets = {
|
var switchBitOffsets = new Map([
|
||||||
'matrix-off': 0,
|
[ 'matrix-off', 0 ],
|
||||||
'https-strict': 2,
|
[ 'https-strict', 2 ],
|
||||||
'ua-spoof': 4,
|
[ 'ua-spoof', 4 ],
|
||||||
'referrer-spoof': 6
|
[ 'referrer-spoof', 6 ]
|
||||||
};
|
]);
|
||||||
|
|
||||||
var switchStateToNameMap = {
|
var switchStateToNameMap = new Map([
|
||||||
'1': 'true',
|
[ 1, 'true' ],
|
||||||
'2': 'false'
|
[ 2, 'false' ]
|
||||||
};
|
]);
|
||||||
|
|
||||||
var nameToSwitchStateMap = {
|
var nameToSwitchStateMap = {
|
||||||
'true': 1,
|
'true': 1,
|
||||||
'false': 2,
|
'false': 2
|
||||||
'on': 2, // backward compatibility
|
|
||||||
'off': 1 // backward compatibility
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var columnHeaders = (function() {
|
Matrix.columnHeaderIndices = (function() {
|
||||||
var out = {};
|
var out = new Map(),
|
||||||
var i = 0;
|
i = 0;
|
||||||
for ( var type in typeBitOffsets ) {
|
for ( var type of typeBitOffsets.keys() ) {
|
||||||
if ( typeBitOffsets.hasOwnProperty(type) === false ) {
|
out.set(type, i++);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
out[type] = i++;
|
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
Matrix.getColumnHeaders = function() {
|
Matrix.switchNames = new Set(switchBitOffsets.keys());
|
||||||
return columnHeaders;
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
var switchNames = (function() {
|
|
||||||
var out = {};
|
|
||||||
for ( var switchName in switchBitOffsets ) {
|
|
||||||
if ( switchBitOffsets.hasOwnProperty(switchName) === false ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
out[switchName] = true;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
})();
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
Matrix.getSwitchNames = function() {
|
|
||||||
return switchNames;
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
@ -208,8 +181,8 @@ var extractFirstPartyDesDomain = function(srcHostname, desHostname) {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
Matrix.prototype.reset = function() {
|
Matrix.prototype.reset = function() {
|
||||||
this.switches = {};
|
this.switches = new Map();
|
||||||
this.rules = {};
|
this.rules = new Map();
|
||||||
this.rootValue = Matrix.RedIndirect;
|
this.rootValue = Matrix.RedIndirect;
|
||||||
this.modifiedTime = 0;
|
this.modifiedTime = 0;
|
||||||
};
|
};
|
||||||
|
@ -220,38 +193,26 @@ Matrix.prototype.reset = function() {
|
||||||
// a live matrix.
|
// a live matrix.
|
||||||
|
|
||||||
Matrix.prototype.assign = function(other) {
|
Matrix.prototype.assign = function(other) {
|
||||||
var k;
|
var k, entry;
|
||||||
// Remove rules not in other
|
// Remove rules not in other
|
||||||
for ( k in this.rules ) {
|
for ( k of this.rules.keys() ) {
|
||||||
if ( this.rules.hasOwnProperty(k) === false ) {
|
if ( other.rules.has(k) === false ) {
|
||||||
continue;
|
this.rules.delete(k);
|
||||||
}
|
|
||||||
if ( other.rules.hasOwnProperty(k) === false ) {
|
|
||||||
delete this.rules[k];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove switches not in other
|
// Remove switches not in other
|
||||||
for ( k in this.switches ) {
|
for ( k of this.switches.keys() ) {
|
||||||
if ( this.switches.hasOwnProperty(k) === false ) {
|
if ( other.switches.has(k) === false ) {
|
||||||
continue;
|
this.switches.delete(k);
|
||||||
}
|
|
||||||
if ( other.switches.hasOwnProperty(k) === false ) {
|
|
||||||
delete this.switches[k];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Add/change rules in other
|
// Add/change rules in other
|
||||||
for ( k in other.rules ) {
|
for ( entry of other.rules ) {
|
||||||
if ( other.rules.hasOwnProperty(k) === false ) {
|
this.rules.set(entry[0], entry[1]);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
this.rules[k] = other.rules[k];
|
|
||||||
}
|
}
|
||||||
// Add/change switches in other
|
// Add/change switches in other
|
||||||
for ( k in other.switches ) {
|
for ( entry of other.switches ) {
|
||||||
if ( other.switches.hasOwnProperty(k) === false ) {
|
this.switches.set(entry[0], entry[1]);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
this.switches[k] = other.switches[k];
|
|
||||||
}
|
}
|
||||||
this.modifiedTime = other.modifiedTime;
|
this.modifiedTime = other.modifiedTime;
|
||||||
return this;
|
return this;
|
||||||
|
@ -264,20 +225,20 @@ Matrix.prototype.assign = function(other) {
|
||||||
// If value is undefined, the switch is removed
|
// If value is undefined, the switch is removed
|
||||||
|
|
||||||
Matrix.prototype.setSwitch = function(switchName, srcHostname, newVal) {
|
Matrix.prototype.setSwitch = function(switchName, srcHostname, newVal) {
|
||||||
var bitOffset = switchBitOffsets[switchName];
|
var bitOffset = switchBitOffsets.get(switchName);
|
||||||
if ( bitOffset === undefined ) {
|
if ( bitOffset === undefined ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ( newVal === this.evaluateSwitch(switchName, srcHostname) ) {
|
if ( newVal === this.evaluateSwitch(switchName, srcHostname) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var bits = this.switches[srcHostname] || 0;
|
var bits = this.switches.get(srcHostname) || 0;
|
||||||
bits &= ~(3 << bitOffset);
|
bits &= ~(3 << bitOffset);
|
||||||
bits |= newVal << bitOffset;
|
bits |= newVal << bitOffset;
|
||||||
if ( bits === 0 ) {
|
if ( bits === 0 ) {
|
||||||
delete this.switches[srcHostname];
|
this.switches.delete(srcHostname);
|
||||||
} else {
|
} else {
|
||||||
this.switches[srcHostname] = bits;
|
this.switches.set(srcHostname, bits);
|
||||||
}
|
}
|
||||||
this.modifiedTime = Date.now();
|
this.modifiedTime = Date.now();
|
||||||
return true;
|
return true;
|
||||||
|
@ -286,9 +247,9 @@ Matrix.prototype.setSwitch = function(switchName, srcHostname, newVal) {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
Matrix.prototype.setCell = function(srcHostname, desHostname, type, state) {
|
Matrix.prototype.setCell = function(srcHostname, desHostname, type, state) {
|
||||||
var bitOffset = typeBitOffsets[type];
|
var bitOffset = typeBitOffsets.get(type),
|
||||||
var k = srcHostname + ' ' + desHostname;
|
k = srcHostname + ' ' + desHostname,
|
||||||
var oldBitmap = this.rules[k];
|
oldBitmap = this.rules.get(k);
|
||||||
if ( oldBitmap === undefined ) {
|
if ( oldBitmap === undefined ) {
|
||||||
oldBitmap = 0;
|
oldBitmap = 0;
|
||||||
}
|
}
|
||||||
|
@ -297,9 +258,9 @@ Matrix.prototype.setCell = function(srcHostname, desHostname, type, state) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ( newBitmap === 0 ) {
|
if ( newBitmap === 0 ) {
|
||||||
delete this.rules[k];
|
this.rules.delete(k);
|
||||||
} else {
|
} else {
|
||||||
this.rules[k] = newBitmap;
|
this.rules.set(k, newBitmap);
|
||||||
}
|
}
|
||||||
this.modifiedTime = Date.now();
|
this.modifiedTime = Date.now();
|
||||||
return true;
|
return true;
|
||||||
|
@ -357,21 +318,21 @@ Matrix.prototype.graylistCell = function(srcHostname, desHostname, type) {
|
||||||
|
|
||||||
Matrix.prototype.evaluateCell = function(srcHostname, desHostname, type) {
|
Matrix.prototype.evaluateCell = function(srcHostname, desHostname, type) {
|
||||||
var key = srcHostname + ' ' + desHostname;
|
var key = srcHostname + ' ' + desHostname;
|
||||||
var bitmap = this.rules[key];
|
var bitmap = this.rules.get(key);
|
||||||
if ( bitmap === undefined ) {
|
if ( bitmap === undefined ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return bitmap >> typeBitOffsets[type] & 3;
|
return bitmap >> typeBitOffsets.get(type) & 3;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type) {
|
Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type) {
|
||||||
var bitOffset = typeBitOffsets[type];
|
var bitOffset = typeBitOffsets.get(type);
|
||||||
var s = srcHostname;
|
var s = srcHostname;
|
||||||
var v;
|
var v;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
v = this.rules[s + ' ' + desHostname];
|
v = this.rules.get(s + ' ' + desHostname);
|
||||||
if ( v !== undefined ) {
|
if ( v !== undefined ) {
|
||||||
v = v >> bitOffset & 3;
|
v = v >> bitOffset & 3;
|
||||||
if ( v !== 0 ) {
|
if ( v !== 0 ) {
|
||||||
|
@ -380,9 +341,7 @@ Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type) {
|
||||||
}
|
}
|
||||||
// TODO: external rules? (for presets)
|
// TODO: external rules? (for presets)
|
||||||
s = toBroaderHostname(s);
|
s = toBroaderHostname(s);
|
||||||
if ( s === '' ) {
|
if ( s === '' ) { break; }
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// srcHostname is '*' at this point
|
// srcHostname is '*' at this point
|
||||||
|
|
||||||
|
@ -396,6 +355,7 @@ Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type) {
|
||||||
if ( type === 'doc' && desHostname === '*' ) {
|
if ( type === 'doc' && desHostname === '*' ) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -495,10 +455,7 @@ Matrix.prototype.evaluateCellZXY = function(srcHostname, desHostname, type) {
|
||||||
|
|
||||||
Matrix.prototype.evaluateRowZXY = function(srcHostname, desHostname) {
|
Matrix.prototype.evaluateRowZXY = function(srcHostname, desHostname) {
|
||||||
var out = [];
|
var out = [];
|
||||||
for ( var type in typeBitOffsets ) {
|
for ( var type of typeBitOffsets.keys() ) {
|
||||||
if ( typeBitOffsets.hasOwnProperty(type) === false ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
out.push(this.evaluateCellZXY(srcHostname, desHostname, type));
|
out.push(this.evaluateCellZXY(srcHostname, desHostname, type));
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
|
@ -525,7 +482,7 @@ Matrix.prototype.desHostnameFromRule = function(rule) {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
Matrix.prototype.setSwitchZ = function(switchName, srcHostname, newState) {
|
Matrix.prototype.setSwitchZ = function(switchName, srcHostname, newState) {
|
||||||
var bitOffset = switchBitOffsets[switchName];
|
var bitOffset = switchBitOffsets.get(switchName);
|
||||||
if ( bitOffset === undefined ) {
|
if ( bitOffset === undefined ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -536,19 +493,19 @@ Matrix.prototype.setSwitchZ = function(switchName, srcHostname, newState) {
|
||||||
if ( newState === undefined ) {
|
if ( newState === undefined ) {
|
||||||
newState = !state;
|
newState = !state;
|
||||||
}
|
}
|
||||||
var bits = this.switches[srcHostname] || 0;
|
var bits = this.switches.get(srcHostname) || 0;
|
||||||
bits &= ~(3 << bitOffset);
|
bits &= ~(3 << bitOffset);
|
||||||
if ( bits === 0 ) {
|
if ( bits === 0 ) {
|
||||||
delete this.switches[srcHostname];
|
this.switches.delete(srcHostname);
|
||||||
} else {
|
} else {
|
||||||
this.switches[srcHostname] = bits;
|
this.switches.set(srcHostname, bits);
|
||||||
}
|
}
|
||||||
this.modifiedTime = Date.now();
|
this.modifiedTime = Date.now();
|
||||||
state = this.evaluateSwitchZ(switchName, srcHostname);
|
state = this.evaluateSwitchZ(switchName, srcHostname);
|
||||||
if ( state === newState ) {
|
if ( state === newState ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
this.switches[srcHostname] = bits | ((newState ? 1 : 2) << bitOffset);
|
this.switches.set(srcHostname, bits | ((newState ? 1 : 2) << bitOffset));
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -559,11 +516,11 @@ Matrix.prototype.setSwitchZ = function(switchName, srcHostname, newState) {
|
||||||
// 2 = forced default state (to override a broader non-default state)
|
// 2 = forced default state (to override a broader non-default state)
|
||||||
|
|
||||||
Matrix.prototype.evaluateSwitch = function(switchName, srcHostname) {
|
Matrix.prototype.evaluateSwitch = function(switchName, srcHostname) {
|
||||||
var bits = this.switches[srcHostname] || 0;
|
var bits = this.switches.get(srcHostname) || 0;
|
||||||
if ( bits === 0 ) {
|
if ( bits === 0 ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
var bitOffset = switchBitOffsets[switchName];
|
var bitOffset = switchBitOffsets.get(switchName);
|
||||||
if ( bitOffset === undefined ) {
|
if ( bitOffset === undefined ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -573,14 +530,14 @@ Matrix.prototype.evaluateSwitch = function(switchName, srcHostname) {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
Matrix.prototype.evaluateSwitchZ = function(switchName, srcHostname) {
|
Matrix.prototype.evaluateSwitchZ = function(switchName, srcHostname) {
|
||||||
var bitOffset = switchBitOffsets[switchName];
|
var bitOffset = switchBitOffsets.get(switchName);
|
||||||
if ( bitOffset === undefined ) {
|
if ( bitOffset === undefined ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var bits;
|
var bits;
|
||||||
var s = srcHostname;
|
var s = srcHostname;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
bits = this.switches[s] || 0;
|
bits = this.switches.get(s) || 0;
|
||||||
if ( bits !== 0 ) {
|
if ( bits !== 0 ) {
|
||||||
bits = bits >> bitOffset & 3;
|
bits = bits >> bitOffset & 3;
|
||||||
if ( bits !== 0 ) {
|
if ( bits !== 0 ) {
|
||||||
|
@ -602,11 +559,7 @@ Matrix.prototype.evaluateSwitchZ = function(switchName, srcHostname) {
|
||||||
|
|
||||||
Matrix.prototype.extractAllSourceHostnames = function() {
|
Matrix.prototype.extractAllSourceHostnames = function() {
|
||||||
var srcHostnames = {};
|
var srcHostnames = {};
|
||||||
var rules = this.rules;
|
for ( var rule of this.rules.keys() ) {
|
||||||
for ( var rule in rules ) {
|
|
||||||
if ( rules.hasOwnProperty(rule) === false ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
srcHostnames[rule.slice(0, rule.indexOf(' '))] = true;
|
srcHostnames[rule.slice(0, rule.indexOf(' '))] = true;
|
||||||
}
|
}
|
||||||
return srcHostnames;
|
return srcHostnames;
|
||||||
|
@ -619,11 +572,7 @@ Matrix.prototype.extractAllSourceHostnames = function() {
|
||||||
|
|
||||||
Matrix.prototype.extractAllDestinationHostnames = function() {
|
Matrix.prototype.extractAllDestinationHostnames = function() {
|
||||||
var desHostnames = {};
|
var desHostnames = {};
|
||||||
var rules = this.rules;
|
for ( var rule of this.rules.keys() ) {
|
||||||
for ( var rule in rules ) {
|
|
||||||
if ( rules.hasOwnProperty(rule) === false ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
desHostnames[this.desHostnameFromRule(rule)] = true;
|
desHostnames[this.desHostnameFromRule(rule)] = true;
|
||||||
}
|
}
|
||||||
return desHostnames;
|
return desHostnames;
|
||||||
|
@ -635,41 +584,25 @@ Matrix.prototype.toString = function() {
|
||||||
var out = [];
|
var out = [];
|
||||||
var rule, type, switchName, val;
|
var rule, type, switchName, val;
|
||||||
var srcHostname, desHostname;
|
var srcHostname, desHostname;
|
||||||
for ( rule in this.rules ) {
|
for ( rule of this.rules.keys() ) {
|
||||||
if ( this.rules.hasOwnProperty(rule) === false ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
srcHostname = this.srcHostnameFromRule(rule);
|
srcHostname = this.srcHostnameFromRule(rule);
|
||||||
desHostname = this.desHostnameFromRule(rule);
|
desHostname = this.desHostnameFromRule(rule);
|
||||||
for ( type in typeBitOffsets ) {
|
for ( type of typeBitOffsets.keys() ) {
|
||||||
if ( typeBitOffsets.hasOwnProperty(type) === false ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
val = this.evaluateCell(srcHostname, desHostname, type);
|
val = this.evaluateCell(srcHostname, desHostname, type);
|
||||||
if ( val === 0 ) {
|
if ( val === 0 ) { continue; }
|
||||||
continue;
|
|
||||||
}
|
|
||||||
out.push(
|
out.push(
|
||||||
punycode.toUnicode(srcHostname) + ' ' +
|
punycode.toUnicode(srcHostname) + ' ' +
|
||||||
punycode.toUnicode(desHostname) + ' ' +
|
punycode.toUnicode(desHostname) + ' ' +
|
||||||
type + ' ' +
|
type + ' ' +
|
||||||
stateToNameMap[val]
|
stateToNameMap.get(val)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for ( srcHostname in this.switches ) {
|
for ( srcHostname of this.switches.keys() ) {
|
||||||
if ( this.switches.hasOwnProperty(srcHostname) === false ) {
|
for ( switchName of switchBitOffsets.keys() ) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for ( switchName in switchBitOffsets ) {
|
|
||||||
if ( switchBitOffsets.hasOwnProperty(switchName) === false ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
val = this.evaluateSwitch(switchName, srcHostname);
|
val = this.evaluateSwitch(switchName, srcHostname);
|
||||||
if ( val === 0 ) {
|
if ( val === 0 ) { continue; }
|
||||||
continue;
|
out.push(switchName + ': ' + srcHostname + ' ' + switchStateToNameMap.get(val));
|
||||||
}
|
|
||||||
out.push(switchName + ': ' + srcHostname + ' ' + switchStateToNameMap[val]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out.sort().join('\n');
|
return out.sort().join('\n');
|
||||||
|
@ -744,7 +677,7 @@ Matrix.prototype.fromString = function(text, append) {
|
||||||
if ( pos !== -1 ) {
|
if ( pos !== -1 ) {
|
||||||
switchName = fieldVal.slice(0, pos);
|
switchName = fieldVal.slice(0, pos);
|
||||||
}
|
}
|
||||||
if ( switchBitOffsets.hasOwnProperty(switchName) ) {
|
if ( switchBitOffsets.has(switchName) ) {
|
||||||
srcHostname = punycode.toASCII(fields[1]);
|
srcHostname = punycode.toASCII(fields[1]);
|
||||||
|
|
||||||
// No state field: reject
|
// No state field: reject
|
||||||
|
@ -801,7 +734,7 @@ Matrix.prototype.fromString = function(text, append) {
|
||||||
type = 'media';
|
type = 'media';
|
||||||
}
|
}
|
||||||
// Unknown type: reject
|
// Unknown type: reject
|
||||||
if ( typeBitOffsets.hasOwnProperty(type) === false ) {
|
if ( typeBitOffsets.has(type) === false ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -835,17 +768,19 @@ Matrix.prototype.fromString = function(text, append) {
|
||||||
Matrix.prototype.toSelfie = function() {
|
Matrix.prototype.toSelfie = function() {
|
||||||
return {
|
return {
|
||||||
magicId: magicId,
|
magicId: magicId,
|
||||||
switches: this.switches,
|
switches: Array.from(this.switches),
|
||||||
rules: this.rules
|
rules: Array.from(this.rules)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
Matrix.prototype.fromSelfie = function(selfie) {
|
Matrix.prototype.fromSelfie = function(selfie) {
|
||||||
this.switches = selfie.switches;
|
if ( selfie.magicId !== magicId ) { return false; }
|
||||||
this.rules = selfie.rules;
|
this.switches = new Map(selfie.switches);
|
||||||
|
this.rules = new Map(selfie.rules);
|
||||||
this.modifiedTime = Date.now();
|
this.modifiedTime = Date.now();
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -855,10 +790,7 @@ Matrix.prototype.diff = function(other, srcHostname, desHostnames) {
|
||||||
var desHostname, type;
|
var desHostname, type;
|
||||||
var switchName, i, thisVal, otherVal;
|
var switchName, i, thisVal, otherVal;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
for ( switchName in switchBitOffsets ) {
|
for ( switchName of switchBitOffsets.keys() ) {
|
||||||
if ( switchBitOffsets.hasOwnProperty(switchName) === false ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
thisVal = this.evaluateSwitch(switchName, srcHostname);
|
thisVal = this.evaluateSwitch(switchName, srcHostname);
|
||||||
otherVal = other.evaluateSwitch(switchName, srcHostname);
|
otherVal = other.evaluateSwitch(switchName, srcHostname);
|
||||||
if ( thisVal !== otherVal ) {
|
if ( thisVal !== otherVal ) {
|
||||||
|
@ -871,15 +803,10 @@ Matrix.prototype.diff = function(other, srcHostname, desHostnames) {
|
||||||
i = desHostnames.length;
|
i = desHostnames.length;
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
desHostname = desHostnames[i];
|
desHostname = desHostnames[i];
|
||||||
for ( type in typeBitOffsets ) {
|
for ( type of typeBitOffsets.keys() ) {
|
||||||
if ( typeBitOffsets.hasOwnProperty(type) === false ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
thisVal = this.evaluateCell(srcHostname, desHostname, type);
|
thisVal = this.evaluateCell(srcHostname, desHostname, type);
|
||||||
otherVal = other.evaluateCell(srcHostname, desHostname, type);
|
otherVal = other.evaluateCell(srcHostname, desHostname, type);
|
||||||
if ( thisVal === otherVal ) {
|
if ( thisVal === otherVal ) { continue; }
|
||||||
continue;
|
|
||||||
}
|
|
||||||
out.push({
|
out.push({
|
||||||
'what': 'rule',
|
'what': 'rule',
|
||||||
'src': srcHostname,
|
'src': srcHostname,
|
||||||
|
@ -909,7 +836,7 @@ Matrix.prototype.applyDiff = function(diff, from) {
|
||||||
changed = this.setCell(action.src, action.des, action.type, val) || changed;
|
changed = this.setCell(action.src, action.des, action.type, val) || changed;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( switchBitOffsets.hasOwnProperty(action.what) ) {
|
if ( switchBitOffsets.has(action.what) ) {
|
||||||
val = from.evaluateSwitch(action.what, action.src);
|
val = from.evaluateSwitch(action.what, action.src);
|
||||||
changed = this.setSwitch(action.what, action.src, val) || changed;
|
changed = this.setSwitch(action.what, action.src, val) || changed;
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -130,9 +130,8 @@ var RowSnapshot = function(srcHostname, desHostname, desDomain) {
|
||||||
};
|
};
|
||||||
|
|
||||||
RowSnapshot.counts = (function() {
|
RowSnapshot.counts = (function() {
|
||||||
var i = Object.keys(µm.Matrix.getColumnHeaders()).length;
|
var aa = [];
|
||||||
var aa = new Array(i);
|
for ( var i = 0, n = µm.Matrix.columnHeaderIndices.size; i < n; i++ ) {
|
||||||
while ( i-- ) {
|
|
||||||
aa[i] = 0;
|
aa[i] = 0;
|
||||||
}
|
}
|
||||||
return aa;
|
return aa;
|
||||||
|
@ -142,12 +141,14 @@ RowSnapshot.counts = (function() {
|
||||||
|
|
||||||
var matrixSnapshot = function(pageStore, details) {
|
var matrixSnapshot = function(pageStore, details) {
|
||||||
var µmuser = µm.userSettings;
|
var µmuser = µm.userSettings;
|
||||||
|
var headerIndices = µm.Matrix.columnHeaderIndices;
|
||||||
|
|
||||||
var r = {
|
var r = {
|
||||||
appVersion: vAPI.app.version,
|
appVersion: vAPI.app.version,
|
||||||
blockedCount: pageStore.requestStats.blocked.all,
|
blockedCount: pageStore.requestStats.blocked.all,
|
||||||
diff: [],
|
diff: [],
|
||||||
domain: pageStore.pageDomain,
|
domain: pageStore.pageDomain,
|
||||||
headers: µm.Matrix.getColumnHeaders(),
|
headerIndices: Array.from(headerIndices),
|
||||||
hostname: pageStore.pageHostname,
|
hostname: pageStore.pageHostname,
|
||||||
mtxContentModified: pageStore.mtxContentModifiedTime !== details.mtxContentModifiedTime,
|
mtxContentModified: pageStore.mtxContentModifiedTime !== details.mtxContentModifiedTime,
|
||||||
mtxCountModified: pageStore.mtxCountModifiedTime !== details.mtxCountModifiedTime,
|
mtxCountModified: pageStore.mtxCountModifiedTime !== details.mtxCountModifiedTime,
|
||||||
|
@ -171,8 +172,6 @@ var matrixSnapshot = function(pageStore, details) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var headers = r.headers;
|
|
||||||
|
|
||||||
if ( typeof details.scope === 'string' ) {
|
if ( typeof details.scope === 'string' ) {
|
||||||
r.scope = details.scope;
|
r.scope = details.scope;
|
||||||
} else if ( µmuser.popupScopeLevel === 'site' ) {
|
} else if ( µmuser.popupScopeLevel === 'site' ) {
|
||||||
|
@ -181,11 +180,7 @@ var matrixSnapshot = function(pageStore, details) {
|
||||||
r.scope = r.domain;
|
r.scope = r.domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
var switchNames = µm.Matrix.getSwitchNames();
|
for ( var switchName of µm.Matrix.switchNames ) {
|
||||||
for ( var switchName in switchNames ) {
|
|
||||||
if ( switchNames.hasOwnProperty(switchName) === false ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
r.tSwitches[switchName] = µm.tMatrix.evaluateSwitchZ(switchName, r.scope);
|
r.tSwitches[switchName] = µm.tMatrix.evaluateSwitchZ(switchName, r.scope);
|
||||||
r.pSwitches[switchName] = µm.pMatrix.evaluateSwitchZ(switchName, r.scope);
|
r.pSwitches[switchName] = µm.pMatrix.evaluateSwitchZ(switchName, r.scope);
|
||||||
}
|
}
|
||||||
|
@ -199,7 +194,7 @@ var matrixSnapshot = function(pageStore, details) {
|
||||||
var reqKey, reqType, reqHostname, reqDomain;
|
var reqKey, reqType, reqHostname, reqDomain;
|
||||||
var desHostname;
|
var desHostname;
|
||||||
var row, typeIndex;
|
var row, typeIndex;
|
||||||
var anyIndex = headers['*'];
|
var anyIndex = headerIndices.get('*');
|
||||||
|
|
||||||
var pageRequests = pageStore.requests;
|
var pageRequests = pageStore.requests;
|
||||||
var reqKeys = pageRequests.getRequestKeys();
|
var reqKeys = pageRequests.getRequestKeys();
|
||||||
|
@ -236,7 +231,7 @@ var matrixSnapshot = function(pageStore, details) {
|
||||||
desHostname = desHostname.slice(pos + 1);
|
desHostname = desHostname.slice(pos + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
typeIndex = headers[reqType];
|
typeIndex = headerIndices.get(reqType);
|
||||||
|
|
||||||
row = r.rows[reqHostname];
|
row = r.rows[reqHostname];
|
||||||
row.counts[typeIndex] += 1;
|
row.counts[typeIndex] += 1;
|
||||||
|
|
|
@ -224,8 +224,7 @@ function getGroupStats() {
|
||||||
// hierarchy is white or blacklisted
|
// hierarchy is white or blacklisted
|
||||||
var pageDomain = matrixSnapshot.domain;
|
var pageDomain = matrixSnapshot.domain;
|
||||||
var rows = matrixSnapshot.rows;
|
var rows = matrixSnapshot.rows;
|
||||||
var columnOffsets = matrixSnapshot.headers;
|
var anyTypeOffset = matrixSnapshot.headerIndices.get('*');
|
||||||
var anyTypeOffset = columnOffsets['*'];
|
|
||||||
var hostname, domain;
|
var hostname, domain;
|
||||||
var row, color, count, groupIndex;
|
var row, color, count, groupIndex;
|
||||||
var domainToGroupMap = {};
|
var domainToGroupMap = {};
|
||||||
|
@ -349,11 +348,11 @@ function getGroupStats() {
|
||||||
// helpers
|
// helpers
|
||||||
|
|
||||||
function getTemporaryColor(hostname, type) {
|
function getTemporaryColor(hostname, type) {
|
||||||
return matrixSnapshot.rows[hostname].temporary[matrixSnapshot.headers[type]];
|
return matrixSnapshot.rows[hostname].temporary[matrixSnapshot.headerIndices.get(type)];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPermanentColor(hostname, type) {
|
function getPermanentColor(hostname, type) {
|
||||||
return matrixSnapshot.rows[hostname].permanent[matrixSnapshot.headers[type]];
|
return matrixSnapshot.rows[hostname].permanent[matrixSnapshot.headerIndices.get(type)];
|
||||||
}
|
}
|
||||||
|
|
||||||
function addCellClass(cell, hostname, type) {
|
function addCellClass(cell, hostname, type) {
|
||||||
|
@ -429,7 +428,7 @@ function updateMatrixCounts() {
|
||||||
var matCells = uDom('.matrix .matRow.rw > .matCell'),
|
var matCells = uDom('.matrix .matRow.rw > .matCell'),
|
||||||
i = matCells.length,
|
i = matCells.length,
|
||||||
matRow, matCell, count, counts,
|
matRow, matCell, count, counts,
|
||||||
headers = matrixSnapshot.headers,
|
headerIndices = matrixSnapshot.headerIndices,
|
||||||
rows = matrixSnapshot.rows,
|
rows = matrixSnapshot.rows,
|
||||||
expandos;
|
expandos;
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
|
@ -440,7 +439,7 @@ function updateMatrixCounts() {
|
||||||
}
|
}
|
||||||
matRow = matCell.parentNode;
|
matRow = matCell.parentNode;
|
||||||
counts = matRow.classList.contains('meta') ? 'totals' : 'counts';
|
counts = matRow.classList.contains('meta') ? 'totals' : 'counts';
|
||||||
count = rows[expandos.hostname][counts][headers[expandos.reqType]];
|
count = rows[expandos.hostname][counts][headerIndices.get(expandos.reqType)];
|
||||||
if ( count === expandos.count ) { continue; }
|
if ( count === expandos.count ) { continue; }
|
||||||
expandos.count = count;
|
expandos.count = count;
|
||||||
matCell.textContent = count ? count : '\u00A0';
|
matCell.textContent = count ? count : '\u00A0';
|
||||||
|
@ -705,15 +704,15 @@ function renderMatrixCellType(cell, hostname, type, count) {
|
||||||
|
|
||||||
function renderMatrixCellTypes(cells, hostname, countName) {
|
function renderMatrixCellTypes(cells, hostname, countName) {
|
||||||
var counts = matrixSnapshot.rows[hostname][countName];
|
var counts = matrixSnapshot.rows[hostname][countName];
|
||||||
var countIndices = matrixSnapshot.headers;
|
var headerIndices = matrixSnapshot.headerIndices;
|
||||||
renderMatrixCellType(cells.at(1), hostname, 'cookie', counts[countIndices.cookie]);
|
renderMatrixCellType(cells.at(1), hostname, 'cookie', counts[headerIndices.get('cookie')]);
|
||||||
renderMatrixCellType(cells.at(2), hostname, 'css', counts[countIndices.css]);
|
renderMatrixCellType(cells.at(2), hostname, 'css', counts[headerIndices.get('css')]);
|
||||||
renderMatrixCellType(cells.at(3), hostname, 'image', counts[countIndices.image]);
|
renderMatrixCellType(cells.at(3), hostname, 'image', counts[headerIndices.get('image')]);
|
||||||
renderMatrixCellType(cells.at(4), hostname, 'media', counts[countIndices.media]);
|
renderMatrixCellType(cells.at(4), hostname, 'media', counts[headerIndices.get('media')]);
|
||||||
renderMatrixCellType(cells.at(5), hostname, 'script', counts[countIndices.script]);
|
renderMatrixCellType(cells.at(5), hostname, 'script', counts[headerIndices.get('script')]);
|
||||||
renderMatrixCellType(cells.at(6), hostname, 'xhr', counts[countIndices.xhr]);
|
renderMatrixCellType(cells.at(6), hostname, 'xhr', counts[headerIndices.get('xhr')]);
|
||||||
renderMatrixCellType(cells.at(7), hostname, 'frame', counts[countIndices.frame]);
|
renderMatrixCellType(cells.at(7), hostname, 'frame', counts[headerIndices.get('frame')]);
|
||||||
renderMatrixCellType(cells.at(8), hostname, 'other', counts[countIndices.other]);
|
renderMatrixCellType(cells.at(8), hostname, 'other', counts[headerIndices.get('other')]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -760,36 +759,37 @@ function renderMatrixMetaCellType(cell, count) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeMatrixMetaRow(totals) {
|
function makeMatrixMetaRow(totals) {
|
||||||
var typeOffsets = matrixSnapshot.headers;
|
var headerIndices = matrixSnapshot.headerIndices,
|
||||||
var matrixRow = createMatrixRow().at(0).addClass('ro');
|
matrixRow = createMatrixRow().at(0).addClass('ro'),
|
||||||
var cells = matrixRow.descendants('.matCell');
|
cells = matrixRow.descendants('.matCell'),
|
||||||
var contents = cells.at(0).addClass('t81').contents();
|
contents = cells.at(0).addClass('t81').contents(),
|
||||||
var expandos = expandosFromNode(cells.nodeAt(0));
|
expandos = expandosFromNode(cells.nodeAt(0));
|
||||||
expandos.hostname = '';
|
expandos.hostname = '';
|
||||||
expandos.reqType = '*';
|
expandos.reqType = '*';
|
||||||
contents.nodeAt(0).textContent = ' ';
|
contents.nodeAt(0).textContent = ' ';
|
||||||
contents.nodeAt(1).textContent = blacklistedHostnamesLabel.replace(
|
contents.nodeAt(1).textContent = blacklistedHostnamesLabel.replace(
|
||||||
'{{count}}',
|
'{{count}}',
|
||||||
totals[typeOffsets['*']].toLocaleString()
|
totals[headerIndices.get('*')].toLocaleString()
|
||||||
);
|
);
|
||||||
renderMatrixMetaCellType(cells.at(1), totals[typeOffsets.cookie]);
|
renderMatrixMetaCellType(cells.at(1), totals[headerIndices.get('cookie')]);
|
||||||
renderMatrixMetaCellType(cells.at(2), totals[typeOffsets.css]);
|
renderMatrixMetaCellType(cells.at(2), totals[headerIndices.get('css')]);
|
||||||
renderMatrixMetaCellType(cells.at(3), totals[typeOffsets.image]);
|
renderMatrixMetaCellType(cells.at(3), totals[headerIndices.get('image')]);
|
||||||
renderMatrixMetaCellType(cells.at(4), totals[typeOffsets.media]);
|
renderMatrixMetaCellType(cells.at(4), totals[headerIndices.get('media')]);
|
||||||
renderMatrixMetaCellType(cells.at(5), totals[typeOffsets.script]);
|
renderMatrixMetaCellType(cells.at(5), totals[headerIndices.get('script')]);
|
||||||
renderMatrixMetaCellType(cells.at(6), totals[typeOffsets.xhr]);
|
renderMatrixMetaCellType(cells.at(6), totals[headerIndices.get('xhr')]);
|
||||||
renderMatrixMetaCellType(cells.at(7), totals[typeOffsets.frame]);
|
renderMatrixMetaCellType(cells.at(7), totals[headerIndices.get('frame')]);
|
||||||
renderMatrixMetaCellType(cells.at(8), totals[typeOffsets.other]);
|
renderMatrixMetaCellType(cells.at(8), totals[headerIndices.get('other')]);
|
||||||
return matrixRow;
|
return matrixRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
function computeMatrixGroupMetaStats(group) {
|
function computeMatrixGroupMetaStats(group) {
|
||||||
var headers = matrixSnapshot.headers;
|
var headerIndices = matrixSnapshot.headerIndices,
|
||||||
var n = Object.keys(headers).length;
|
anyTypeIndex = headerIndices.get('*'),
|
||||||
var totals = new Array(n);
|
n = headerIndices.size,
|
||||||
var i = n;
|
totals = new Array(n),
|
||||||
|
i = n;
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
totals[i] = 0;
|
totals[i] = 0;
|
||||||
}
|
}
|
||||||
|
@ -802,7 +802,7 @@ function computeMatrixGroupMetaStats(group) {
|
||||||
if ( group.hasOwnProperty(row.domain) === false ) {
|
if ( group.hasOwnProperty(row.domain) === false ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( row.counts[headers['*']] === 0 ) {
|
if ( row.counts[anyTypeIndex] === 0 ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
totals[0] += 1;
|
totals[0] += 1;
|
||||||
|
@ -1367,6 +1367,13 @@ var onMatrixSnapshotReady = function(response) {
|
||||||
var matrixSnapshotPoller = (function() {
|
var matrixSnapshotPoller = (function() {
|
||||||
var timer = null;
|
var timer = null;
|
||||||
|
|
||||||
|
var preprocessMatrixSnapshot = function(snapshot) {
|
||||||
|
if ( Array.isArray(snapshot.headerIndices) ) {
|
||||||
|
snapshot.headerIndices = new Map(snapshot.headerIndices);
|
||||||
|
}
|
||||||
|
return snapshot;
|
||||||
|
};
|
||||||
|
|
||||||
var processPollResult = function(response) {
|
var processPollResult = function(response) {
|
||||||
if ( typeof response !== 'object' ) {
|
if ( typeof response !== 'object' ) {
|
||||||
return;
|
return;
|
||||||
|
@ -1379,7 +1386,8 @@ var matrixSnapshotPoller = (function() {
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
matrixSnapshot = response;
|
matrixSnapshot = preprocessMatrixSnapshot(response);
|
||||||
|
|
||||||
if ( response.mtxContentModified ) {
|
if ( response.mtxContentModified ) {
|
||||||
makeMenu();
|
makeMenu();
|
||||||
return;
|
return;
|
||||||
|
@ -1454,7 +1462,7 @@ var matrixSnapshotPoller = (function() {
|
||||||
|
|
||||||
var snapshotFetched = function(response) {
|
var snapshotFetched = function(response) {
|
||||||
if ( typeof response === 'object' ) {
|
if ( typeof response === 'object' ) {
|
||||||
matrixSnapshot = response;
|
matrixSnapshot = preprocessMatrixSnapshot(response);
|
||||||
}
|
}
|
||||||
onMatrixSnapshotReady(response);
|
onMatrixSnapshotReady(response);
|
||||||
pollAsync();
|
pollAsync();
|
||||||
|
|
Loading…
Reference in a new issue