mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-10 09:07:54 +01:00
refactor static network filtering, add support for csp injection
This commit is contained in:
parent
8570b63bef
commit
0232382695
18 changed files with 1844 additions and 1771 deletions
|
@ -35,7 +35,13 @@ var chrome = self.chrome;
|
||||||
var manifest = chrome.runtime.getManifest();
|
var manifest = chrome.runtime.getManifest();
|
||||||
|
|
||||||
vAPI.chrome = true;
|
vAPI.chrome = true;
|
||||||
vAPI.cantWebsocket = true;
|
vAPI.chromiumVersion = (function(){
|
||||||
|
var matches = /\bChrom(?:e|ium)\/(\d+)\b/.exec(navigator.userAgent);
|
||||||
|
return matches !== null ? parseInt(matches[1], 10) : NaN;
|
||||||
|
})();
|
||||||
|
vAPI.cantWebsocket =
|
||||||
|
chrome.webRequest.ResourceType instanceof Object === false ||
|
||||||
|
chrome.webRequest.ResourceType.WEBSOCKET !== 'websocket';
|
||||||
|
|
||||||
var noopFunc = function(){};
|
var noopFunc = function(){};
|
||||||
|
|
||||||
|
|
|
@ -157,7 +157,7 @@ body.colorBlind #netInspector tr.nooped {
|
||||||
body.colorBlind #netInspector tr.allowed {
|
body.colorBlind #netInspector tr.allowed {
|
||||||
background-color: rgba(255, 194, 57, 0.1)
|
background-color: rgba(255, 194, 57, 0.1)
|
||||||
}
|
}
|
||||||
#netInspector tr.cb, #netInspector tr.rr {
|
#netInspector tr.cosmetic, #netInspector tr.redirect {
|
||||||
background-color: rgba(255, 255, 0, 0.1);
|
background-color: rgba(255, 255, 0, 0.1);
|
||||||
}
|
}
|
||||||
#netInspector tr.maindoc {
|
#netInspector tr.maindoc {
|
||||||
|
|
|
@ -439,40 +439,40 @@ body.advancedUser #firewallContainer > div > span:first-of-type ~ span {
|
||||||
background-color: rgb(192, 160, 0);
|
background-color: rgb(192, 160, 0);
|
||||||
}
|
}
|
||||||
/* Rule cells */
|
/* Rule cells */
|
||||||
body.advancedUser #firewallContainer > div > span.aRule {
|
body.advancedUser #firewallContainer > div > span.allowRule {
|
||||||
background-color: rgba(0, 160, 0, 0.3);
|
background-color: rgba(0, 160, 0, 0.3);
|
||||||
}
|
}
|
||||||
body.advancedUser #firewallContainer.colorBlind > div > span.aRule {
|
body.advancedUser #firewallContainer.colorBlind > div > span.allowRule {
|
||||||
background-color: rgba(255, 194, 57, 0.4);
|
background-color: rgba(255, 194, 57, 0.4);
|
||||||
}
|
}
|
||||||
body.advancedUser #firewallContainer > div > span.bRule {
|
body.advancedUser #firewallContainer > div > span.blockRule {
|
||||||
background-color: rgba(192, 0, 0, 0.3);
|
background-color: rgba(192, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
body.advancedUser #firewallContainer.colorBlind > div > span.bRule {
|
body.advancedUser #firewallContainer.colorBlind > div > span.blockRule {
|
||||||
background-color: rgba(0, 19, 110, 0.4);
|
background-color: rgba(0, 19, 110, 0.4);
|
||||||
}
|
}
|
||||||
body.advancedUser #firewallContainer > div > span.nRule {
|
body.advancedUser #firewallContainer > div > span.noopRule {
|
||||||
background-color: rgba(108, 108, 108, 0.3);
|
background-color: rgba(108, 108, 108, 0.3);
|
||||||
}
|
}
|
||||||
body.advancedUser #firewallContainer.colorBlind > div > span.nRule {
|
body.advancedUser #firewallContainer.colorBlind > div > span.noopRule {
|
||||||
background-color: rgba(96, 96, 96, 0.4);
|
background-color: rgba(96, 96, 96, 0.4);
|
||||||
}
|
}
|
||||||
body.advancedUser #firewallContainer > div > span.ownRule {
|
body.advancedUser #firewallContainer > div > span.ownRule {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
body.advancedUser #firewallContainer > div > span.aRule.ownRule {
|
body.advancedUser #firewallContainer > div > span.allowRule.ownRule {
|
||||||
background-color: rgba(0, 160, 0, 1);
|
background-color: rgba(0, 160, 0, 1);
|
||||||
}
|
}
|
||||||
body.advancedUser #firewallContainer.colorBlind > div > span.aRule.ownRule {
|
body.advancedUser #firewallContainer.colorBlind > div > span.allowRule.ownRule {
|
||||||
background-color: rgba(255, 194, 57, 1);
|
background-color: rgba(255, 194, 57, 1);
|
||||||
}
|
}
|
||||||
body.advancedUser #firewallContainer > div > span.bRule.ownRule {
|
body.advancedUser #firewallContainer > div > span.blockRule.ownRule {
|
||||||
background-color: rgba(192, 0, 0, 1);
|
background-color: rgba(192, 0, 0, 1);
|
||||||
}
|
}
|
||||||
body.advancedUser #firewallContainer.colorBlind > div > span.bRule.ownRule {
|
body.advancedUser #firewallContainer.colorBlind > div > span.blockRule.ownRule {
|
||||||
background-color: rgba(0, 19, 110, 1);
|
background-color: rgba(0, 19, 110, 1);
|
||||||
}
|
}
|
||||||
body.advancedUser #firewallContainer > div > span.nRule.ownRule {
|
body.advancedUser #firewallContainer > div > span.noopRule.ownRule {
|
||||||
background-color: rgba(108, 108, 108, 1);
|
background-color: rgba(108, 108, 108, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,8 +121,8 @@ var µBlock = (function() { // jshint ignore:line
|
||||||
|
|
||||||
// read-only
|
// read-only
|
||||||
systemSettings: {
|
systemSettings: {
|
||||||
compiledMagic: 'fxtcjjhbhyiw',
|
compiledMagic: 'lcmfjiajoqwe',
|
||||||
selfieMagic: 'fxtcjjhbhyiw'
|
selfieMagic: 'lcmfjiajoqwe'
|
||||||
},
|
},
|
||||||
|
|
||||||
restoreBackupSettings: {
|
restoreBackupSettings: {
|
||||||
|
@ -170,4 +170,3 @@ var µBlock = (function() { // jshint ignore:line
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -719,6 +719,8 @@ FilterContainer.prototype.freeze = function() {
|
||||||
this.highHighComplexGenericHideCount !== 0;
|
this.highHighComplexGenericHideCount !== 0;
|
||||||
|
|
||||||
this.parser.reset();
|
this.parser.reset();
|
||||||
|
this.compileSelector.reset();
|
||||||
|
this.compileProceduralSelector.reset();
|
||||||
this.frozen = true;
|
this.frozen = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -746,7 +748,7 @@ FilterContainer.prototype.compileSelector = (function() {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
return function(raw) {
|
var entryPoint = function(raw) {
|
||||||
if ( isValidCSSSelector(raw) && raw.indexOf('[-abp-properties=') === -1 ) {
|
if ( isValidCSSSelector(raw) && raw.indexOf('[-abp-properties=') === -1 ) {
|
||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
|
@ -812,6 +814,11 @@ FilterContainer.prototype.compileSelector = (function() {
|
||||||
|
|
||||||
µb.logger.writeOne('', 'error', 'Cosmetic filtering – invalid filter: ' + raw);
|
µb.logger.writeOne('', 'error', 'Cosmetic filtering – invalid filter: ' + raw);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
entryPoint.reset = function() {
|
||||||
|
};
|
||||||
|
|
||||||
|
return entryPoint;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -927,7 +934,7 @@ FilterContainer.prototype.compileProceduralSelector = (function() {
|
||||||
return { selector: firstOperand, tasks: tasks };
|
return { selector: firstOperand, tasks: tasks };
|
||||||
};
|
};
|
||||||
|
|
||||||
return function(raw) {
|
var entryPoint = function(raw) {
|
||||||
if ( raw === lastProceduralSelector ) {
|
if ( raw === lastProceduralSelector ) {
|
||||||
return lastProceduralSelectorCompiled;
|
return lastProceduralSelectorCompiled;
|
||||||
}
|
}
|
||||||
|
@ -940,6 +947,13 @@ FilterContainer.prototype.compileProceduralSelector = (function() {
|
||||||
lastProceduralSelectorCompiled = compiled;
|
lastProceduralSelectorCompiled = compiled;
|
||||||
return compiled;
|
return compiled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
entryPoint.reset = function() {
|
||||||
|
lastProceduralSelector = '';
|
||||||
|
lastProceduralSelectorCompiled = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
return entryPoint;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -1038,12 +1052,12 @@ FilterContainer.prototype.compileGenericHideSelector = function(parsed, out) {
|
||||||
// is valid, the regex took care of this. Most generic selector falls
|
// is valid, the regex took care of this. Most generic selector falls
|
||||||
// into that category.
|
// into that category.
|
||||||
if ( key === selector ) {
|
if ( key === selector ) {
|
||||||
out.push('c\vlg\v' + key);
|
out.push(4, 'lg\v' + key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Composite CSS rule.
|
// Composite CSS rule.
|
||||||
if ( this.compileSelector(selector) ) {
|
if ( this.compileSelector(selector) ) {
|
||||||
out.push('c\vlg+\v' + key + '\v' + selector);
|
out.push(4, 'lg+\v' + key + '\v' + selector);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1054,21 +1068,21 @@ FilterContainer.prototype.compileGenericHideSelector = function(parsed, out) {
|
||||||
|
|
||||||
// ["title"] and ["alt"] will go in high-low generic bin.
|
// ["title"] and ["alt"] will go in high-low generic bin.
|
||||||
if ( this.reHighLow.test(selector) ) {
|
if ( this.reHighLow.test(selector) ) {
|
||||||
out.push('c\vhlg0\v' + selector);
|
out.push(4, 'hlg0\v' + selector);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// [href^="..."] will go in high-medium generic bin.
|
// [href^="..."] will go in high-medium generic bin.
|
||||||
matches = this.reHighMedium.exec(selector);
|
matches = this.reHighMedium.exec(selector);
|
||||||
if ( matches && matches.length === 2 ) {
|
if ( matches && matches.length === 2 ) {
|
||||||
out.push('c\vhmg0\v' + matches[1] + '\v' + selector);
|
out.push(4, 'hmg0\v' + matches[1] + '\v' + selector);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// script:contains(...)
|
// script:contains(...)
|
||||||
// script:inject(...)
|
// script:inject(...)
|
||||||
if ( this.reScriptSelector.test(selector) ) {
|
if ( this.reScriptSelector.test(selector) ) {
|
||||||
out.push('c\vjs\v0\v\v' + selector);
|
out.push(4, 'js\v0\v\v' + selector);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1077,16 +1091,16 @@ FilterContainer.prototype.compileGenericHideSelector = function(parsed, out) {
|
||||||
// as a low generic cosmetic filter.
|
// as a low generic cosmetic filter.
|
||||||
matches = this.rePlainSelectorEx.exec(selector);
|
matches = this.rePlainSelectorEx.exec(selector);
|
||||||
if ( matches && matches.length === 2 ) {
|
if ( matches && matches.length === 2 ) {
|
||||||
out.push('c\vlg+\v' + matches[1] + '\v' + selector);
|
out.push(4, 'lg+\v' + matches[1] + '\v' + selector);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// All else: high-high generics.
|
// All else: high-high generics.
|
||||||
// Distinguish simple vs complex selectors.
|
// Distinguish simple vs complex selectors.
|
||||||
if ( selector.indexOf(' ') === -1 ) {
|
if ( selector.indexOf(' ') === -1 ) {
|
||||||
out.push('c\vhhsg0\v' + selector);
|
out.push(4, 'hhsg0\v' + selector);
|
||||||
} else {
|
} else {
|
||||||
out.push('c\vhhcg0\v' + selector);
|
out.push(4, 'hhcg0\v' + selector);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1098,7 +1112,7 @@ FilterContainer.prototype.compileGenericUnhideSelector = function(parsed, out) {
|
||||||
// script:contains(...)
|
// script:contains(...)
|
||||||
// script:inject(...)
|
// script:inject(...)
|
||||||
if ( this.reScriptSelector.test(selector) ) {
|
if ( this.reScriptSelector.test(selector) ) {
|
||||||
out.push('c\vjs\v1\v\v' + selector);
|
out.push(4, 'js\v1\v\v' + selector);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1109,7 +1123,7 @@ FilterContainer.prototype.compileGenericUnhideSelector = function(parsed, out) {
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/497
|
// https://github.com/chrisaljoudi/uBlock/issues/497
|
||||||
// All generic exception filters are put in the same bucket: they are
|
// All generic exception filters are put in the same bucket: they are
|
||||||
// expected to be very rare.
|
// expected to be very rare.
|
||||||
out.push('c\vg1\v' + compiled);
|
out.push(4, 'g1\v' + compiled);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -1138,7 +1152,7 @@ FilterContainer.prototype.compileHostnameSelector = function(hostname, parsed, o
|
||||||
if ( unhide ) {
|
if ( unhide ) {
|
||||||
hash = '!' + hash;
|
hash = '!' + hash;
|
||||||
}
|
}
|
||||||
out.push('c\vjs\v' + hash + '\v' + hostname + '\v' + selector);
|
out.push(4, 'js\v' + hash + '\v' + hostname + '\v' + selector);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1156,12 +1170,16 @@ FilterContainer.prototype.compileHostnameSelector = function(hostname, parsed, o
|
||||||
hash = '!' + hash;
|
hash = '!' + hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
out.push('c\vh\v' + hash + '\v' + hostname + '\v' + compiled);
|
out.push(4, 'h\v' + hash + '\v' + hostname + '\v' + compiled);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.fromCompiledContent = function(lineIter, skipGenericCosmetic, skipCosmetic) {
|
FilterContainer.prototype.fromCompiledContent = function(
|
||||||
|
lineIter,
|
||||||
|
skipGenericCosmetic,
|
||||||
|
skipCosmetic
|
||||||
|
) {
|
||||||
if ( skipCosmetic ) {
|
if ( skipCosmetic ) {
|
||||||
this.skipCompiledContent(lineIter);
|
this.skipCompiledContent(lineIter);
|
||||||
return;
|
return;
|
||||||
|
@ -1171,15 +1189,19 @@ FilterContainer.prototype.fromCompiledContent = function(lineIter, skipGenericCo
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var line, field0, field1, field2, field3, filter, bucket,
|
var lineBits, line, field0, field1, field2, field3, filter, bucket,
|
||||||
|
aCharCode = 'a'.charCodeAt(0),
|
||||||
fieldIter = new µb.FieldIterator('\v');
|
fieldIter = new µb.FieldIterator('\v');
|
||||||
|
|
||||||
while ( lineIter.eot() === false ) {
|
while ( lineIter.eot() === false ) {
|
||||||
line = lineIter.next();
|
lineBits = lineIter.charCodeAt(0) - aCharCode;
|
||||||
if ( line.charCodeAt(0) !== 0x63 /* 'c' */ ) {
|
if ( (lineBits & 0x04) === 0 ) {
|
||||||
lineIter.rewind();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
line = lineIter.next(1);
|
||||||
|
if ( (lineBits & 0x02) !== 0 ) {
|
||||||
|
line = decodeURIComponent(line);
|
||||||
|
}
|
||||||
|
|
||||||
this.acceptedCount += 1;
|
this.acceptedCount += 1;
|
||||||
if ( this.duplicateBuster.has(line) ) {
|
if ( this.duplicateBuster.has(line) ) {
|
||||||
|
@ -1188,8 +1210,7 @@ FilterContainer.prototype.fromCompiledContent = function(lineIter, skipGenericCo
|
||||||
}
|
}
|
||||||
this.duplicateBuster.add(line);
|
this.duplicateBuster.add(line);
|
||||||
|
|
||||||
fieldIter.first(line);
|
field0 = fieldIter.first(line);
|
||||||
field0 = fieldIter.next();
|
|
||||||
field1 = fieldIter.next();
|
field1 = fieldIter.next();
|
||||||
|
|
||||||
// h [\v] hash [\v] example.com [\v] .promoted-tweet
|
// h [\v] hash [\v] example.com [\v] .promoted-tweet
|
||||||
|
@ -1298,15 +1319,19 @@ FilterContainer.prototype.fromCompiledContent = function(lineIter, skipGenericCo
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.skipGenericCompiledContent = function(lineIter) {
|
FilterContainer.prototype.skipGenericCompiledContent = function(lineIter) {
|
||||||
var line, field0, field1, field2, field3, filter, bucket,
|
var lineBits, line, field0, field1, field2, field3, filter, bucket,
|
||||||
|
aCharCode = 'a'.charCodeAt(0),
|
||||||
fieldIter = new µb.FieldIterator('\v');
|
fieldIter = new µb.FieldIterator('\v');
|
||||||
|
|
||||||
while ( lineIter.eot() === false ) {
|
while ( lineIter.eot() === false ) {
|
||||||
line = lineIter.next();
|
lineBits = lineIter.charCodeAt(0) - aCharCode;
|
||||||
if ( line.charCodeAt(0) !== 0x63 /* 'c' */ ) {
|
if ( (lineBits & 0x04) === 0 ) {
|
||||||
lineIter.rewind();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
line = lineIter.next(1);
|
||||||
|
if ( (lineBits & 0x02) !== 0 ) {
|
||||||
|
line = decodeURIComponent(line);
|
||||||
|
}
|
||||||
|
|
||||||
this.acceptedCount += 1;
|
this.acceptedCount += 1;
|
||||||
if ( this.duplicateBuster.has(line) ) {
|
if ( this.duplicateBuster.has(line) ) {
|
||||||
|
@ -1361,15 +1386,19 @@ FilterContainer.prototype.skipGenericCompiledContent = function(lineIter) {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.skipCompiledContent = function(lineIter) {
|
FilterContainer.prototype.skipCompiledContent = function(lineIter) {
|
||||||
var line, field0, field1, field2, field3,
|
var lineBits, line, field0, field1, field2, field3,
|
||||||
|
aCharCode = 'a'.charCodeAt(0),
|
||||||
fieldIter = new µb.FieldIterator('\v');
|
fieldIter = new µb.FieldIterator('\v');
|
||||||
|
|
||||||
while ( lineIter.eot() === false ) {
|
while ( lineIter.eot() === false ) {
|
||||||
line = lineIter.next();
|
lineBits = lineIter.charCodeAt(0) - aCharCode;
|
||||||
if ( line.charCodeAt(0) !== 0x63 /* 'c' */ ) {
|
if ( (lineBits & 0x04) === 0 ) {
|
||||||
lineIter.rewind();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
line = lineIter.next(1);
|
||||||
|
if ( (lineBits & 0x02) !== 0 ) {
|
||||||
|
line = decodeURIComponent(line);
|
||||||
|
}
|
||||||
|
|
||||||
this.acceptedCount += 1;
|
this.acceptedCount += 1;
|
||||||
if ( this.duplicateBuster.has(line) ) {
|
if ( this.duplicateBuster.has(line) ) {
|
||||||
|
|
|
@ -337,7 +337,7 @@ Matrix.prototype.evaluateCellZY = function(srcHostname, desHostname, type) {
|
||||||
var d = desHostname;
|
var d = desHostname;
|
||||||
if ( d === '' ) {
|
if ( d === '' ) {
|
||||||
this.r = 0;
|
this.r = 0;
|
||||||
return this;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare broadening handlers -- depends on whether we are dealing with
|
// Prepare broadening handlers -- depends on whether we are dealing with
|
||||||
|
@ -350,7 +350,9 @@ Matrix.prototype.evaluateCellZY = function(srcHostname, desHostname, type) {
|
||||||
// Specific-destination, any party, any type
|
// Specific-destination, any party, any type
|
||||||
while ( d !== '*' ) {
|
while ( d !== '*' ) {
|
||||||
this.y = d;
|
this.y = d;
|
||||||
if ( this.evaluateCellZ(srcHostname, d, '*', broadenSource) !== 0 ) { return this; }
|
if ( this.evaluateCellZ(srcHostname, d, '*', broadenSource) !== 0 ) {
|
||||||
|
return this.r;
|
||||||
|
}
|
||||||
d = broadenDestination(d);
|
d = broadenDestination(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,27 +365,39 @@ Matrix.prototype.evaluateCellZY = function(srcHostname, desHostname, type) {
|
||||||
if ( thirdParty ) {
|
if ( thirdParty ) {
|
||||||
// 3rd-party, specific type
|
// 3rd-party, specific type
|
||||||
if ( type === 'script' ) {
|
if ( type === 'script' ) {
|
||||||
if ( this.evaluateCellZ(srcHostname, '*', '3p-script', broadenSource) !== 0 ) { return this; }
|
if ( this.evaluateCellZ(srcHostname, '*', '3p-script', broadenSource) !== 0 ) {
|
||||||
|
return this.r;
|
||||||
|
}
|
||||||
} else if ( type === 'sub_frame' ) {
|
} else if ( type === 'sub_frame' ) {
|
||||||
if ( this.evaluateCellZ(srcHostname, '*', '3p-frame', broadenSource) !== 0 ) { return this; }
|
if ( this.evaluateCellZ(srcHostname, '*', '3p-frame', broadenSource) !== 0 ) {
|
||||||
|
return this.r;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 3rd-party, any type
|
// 3rd-party, any type
|
||||||
if ( this.evaluateCellZ(srcHostname, '*', '3p', broadenSource) !== 0 ) { return this; }
|
if ( this.evaluateCellZ(srcHostname, '*', '3p', broadenSource) !== 0 ) {
|
||||||
|
return this.r;
|
||||||
|
}
|
||||||
} else if ( type === 'script' ) {
|
} else if ( type === 'script' ) {
|
||||||
// 1st party, specific type
|
// 1st party, specific type
|
||||||
if ( this.evaluateCellZ(srcHostname, '*', '1p-script', broadenSource) !== 0 ) { return this; }
|
if ( this.evaluateCellZ(srcHostname, '*', '1p-script', broadenSource) !== 0 ) {
|
||||||
|
return this.r;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any destination, any party, specific type
|
// Any destination, any party, specific type
|
||||||
if ( supportedDynamicTypes.hasOwnProperty(type) ) {
|
if ( supportedDynamicTypes.hasOwnProperty(type) ) {
|
||||||
if ( this.evaluateCellZ(srcHostname, '*', type, broadenSource) !== 0 ) { return this; }
|
if ( this.evaluateCellZ(srcHostname, '*', type, broadenSource) !== 0 ) {
|
||||||
|
return this.r;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any destination, any party, any type
|
// Any destination, any party, any type
|
||||||
if ( this.evaluateCellZ(srcHostname, '*', '*', broadenSource) !== 0 ) { return this; }
|
if ( this.evaluateCellZ(srcHostname, '*', '*', broadenSource) !== 0 ) {
|
||||||
|
return this.r;
|
||||||
|
}
|
||||||
|
|
||||||
this.type = '';
|
this.type = '';
|
||||||
return this;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// http://youtu.be/gSGk1bQ9rcU?t=25m6s
|
// http://youtu.be/gSGk1bQ9rcU?t=25m6s
|
||||||
|
@ -391,7 +405,7 @@ Matrix.prototype.evaluateCellZY = function(srcHostname, desHostname, type) {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
Matrix.prototype.mustAllowCellZY = function(srcHostname, desHostname, type) {
|
Matrix.prototype.mustAllowCellZY = function(srcHostname, desHostname, type) {
|
||||||
return this.evaluateCellZY(srcHostname, desHostname, type).r === 2;
|
return this.evaluateCellZY(srcHostname, desHostname, type) === 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -414,23 +428,44 @@ Matrix.prototype.mustAbort = function() {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
Matrix.prototype.toFilterString = function() {
|
Matrix.prototype.lookupRuleData = function(src, des, type) {
|
||||||
if ( this.r === 0 || this.type === '' ) {
|
var r = this.evaluateCellZY(src, des, type);
|
||||||
return '';
|
if ( r === 0 ) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
var body = this.z + ' ' + this.y + ' ' + this.type;
|
return {
|
||||||
if ( this.r === 1 ) {
|
src: this.z,
|
||||||
return 'db:' + body + ' block';
|
des: this.y,
|
||||||
}
|
type: this.type,
|
||||||
if ( this.r === 2 ) {
|
action: r === 1 ? 'block' : (r === 2 ? 'allow' : 'noop')
|
||||||
return 'da:' + body + ' allow';
|
};
|
||||||
}
|
|
||||||
/* this.r === 3 */
|
|
||||||
return 'dn:' + body + ' noop';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Matrix.prototype.toLogData = function() {
|
||||||
|
if ( this.r === 0 || this.type === '' ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var logData = {
|
||||||
|
source: 'dynamicHost',
|
||||||
|
result: this.r,
|
||||||
|
raw: this.z + ' ' +
|
||||||
|
this.y + ' ' +
|
||||||
|
this.type + ' ' +
|
||||||
|
this.intToActionMap.get(this.r)
|
||||||
|
};
|
||||||
|
return logData;
|
||||||
|
};
|
||||||
|
|
||||||
|
Matrix.prototype.intToActionMap = new Map([
|
||||||
|
[ 1, ' block' ],
|
||||||
|
[ 2, ' allow' ],
|
||||||
|
[ 3, ' noop' ]
|
||||||
|
]);
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
Matrix.prototype.srcHostnameFromRule = function(rule) {
|
Matrix.prototype.srcHostnameFromRule = function(rule) {
|
||||||
return rule.slice(0, rule.indexOf(' '));
|
return rule.slice(0, rule.indexOf(' '));
|
||||||
};
|
};
|
||||||
|
|
|
@ -249,10 +249,12 @@ HnSwitches.prototype.evaluateZ = function(switchName, hostname) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
HnSwitches.prototype.toResultString = function() {
|
HnSwitches.prototype.toLogData = function() {
|
||||||
return this.r !== 1 ?
|
return {
|
||||||
'' :
|
source: 'switch',
|
||||||
'ub:' + this.n + ': ' + this.z + ' true';
|
result: this.r,
|
||||||
|
raw: this.n + ': ' + this.z + ' true'
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
uBlock Origin - a browser extension to block requests.
|
uBlock Origin - a browser extension to block requests.
|
||||||
Copyright (C) 2015-2016 Raymond Hill
|
Copyright (C) 2015-2017 Raymond Hill
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -92,9 +92,11 @@ var uglyRequestTypes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
var staticFilterTypes = {
|
var staticFilterTypes = {
|
||||||
|
'beacon': 'other',
|
||||||
'doc': 'document',
|
'doc': 'document',
|
||||||
'css': 'stylesheet',
|
'css': 'stylesheet',
|
||||||
'frame': 'subdocument',
|
'frame': 'subdocument',
|
||||||
|
'ping': 'other',
|
||||||
'xhr': 'xmlhttprequest'
|
'xhr': 'xmlhttprequest'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -146,212 +148,6 @@ var renderedURLTemplate = document.querySelector('#renderedURLTemplate > span');
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// Pretty much same logic as found in:
|
|
||||||
// µBlock.staticNetFilteringEngine.filterStringFromCompiled
|
|
||||||
// µBlock.staticNetFilteringEngine.filterRegexFromCompiled
|
|
||||||
|
|
||||||
var filterDecompiler = (function() {
|
|
||||||
var typeValToTypeName = {
|
|
||||||
1: 'stylesheet',
|
|
||||||
2: 'image',
|
|
||||||
3: 'object',
|
|
||||||
4: 'script',
|
|
||||||
5: 'xmlhttprequest',
|
|
||||||
6: 'subdocument',
|
|
||||||
7: 'font',
|
|
||||||
8: 'media',
|
|
||||||
9: 'websocket',
|
|
||||||
10: 'other',
|
|
||||||
11: 'popunder',
|
|
||||||
12: 'document',
|
|
||||||
13: 'generichide',
|
|
||||||
14: 'inline-script',
|
|
||||||
15: 'popup'
|
|
||||||
};
|
|
||||||
|
|
||||||
var toString = function(compiled) {
|
|
||||||
var opts = [];
|
|
||||||
var vfields = compiled.split('\v');
|
|
||||||
var filter = '';
|
|
||||||
var bits = parseInt(vfields[0], 16) | 0;
|
|
||||||
|
|
||||||
if ( bits & 0x01 ) {
|
|
||||||
filter += '@@';
|
|
||||||
}
|
|
||||||
|
|
||||||
var fid = vfields[1] === '.' ? '.' : vfields[2];
|
|
||||||
var tfields = fid !== '.' ? vfields[3].split('\t') : [];
|
|
||||||
var tfield0 = tfields[0];
|
|
||||||
|
|
||||||
// Filter options
|
|
||||||
// Importance
|
|
||||||
if ( bits & 0x02 ) {
|
|
||||||
opts.push('important');
|
|
||||||
}
|
|
||||||
// Party
|
|
||||||
if ( bits & 0x08 ) {
|
|
||||||
opts.push('third-party');
|
|
||||||
} else if ( bits & 0x04 ) {
|
|
||||||
opts.push('first-party');
|
|
||||||
}
|
|
||||||
// Type
|
|
||||||
var typeVal = bits >>> 4 & 0x0F;
|
|
||||||
if ( typeVal ) {
|
|
||||||
opts.push(typeValToTypeName[typeVal]);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ( fid ) {
|
|
||||||
case '.':
|
|
||||||
filter += '||' + vfields[2] + '^';
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
case 'ah':
|
|
||||||
case '0a':
|
|
||||||
case '0ah':
|
|
||||||
case '1a':
|
|
||||||
case '1ah':
|
|
||||||
case '_':
|
|
||||||
case '_h':
|
|
||||||
filter += tfield0;
|
|
||||||
// If the filter resemble a regex, add a trailing `*` as is
|
|
||||||
// customary to prevent ambiguity in logger.
|
|
||||||
if ( tfield0.charAt(0) === '/' && tfield0.slice(-1) === '/' ) {
|
|
||||||
filter += '*';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '|a':
|
|
||||||
case '|ah':
|
|
||||||
filter += '|' + tfield0;
|
|
||||||
break;
|
|
||||||
case 'a|':
|
|
||||||
case 'a|h':
|
|
||||||
filter += tfield0 + '|';
|
|
||||||
break;
|
|
||||||
case '||a':
|
|
||||||
case '||ah':
|
|
||||||
filter += '||' + tfield0;
|
|
||||||
break;
|
|
||||||
case '||_':
|
|
||||||
case '||_h':
|
|
||||||
filter += '||' + tfield0;
|
|
||||||
if ( tfields[1] === '1' ) { // left-anchored?
|
|
||||||
filter += '|';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '//':
|
|
||||||
case '//h':
|
|
||||||
filter += '/' + tfield0 + '/';
|
|
||||||
break;
|
|
||||||
// https://github.com/gorhill/uBlock/issues/465
|
|
||||||
// Unexpected: return the raw compiled representation instead of a
|
|
||||||
// blank string.
|
|
||||||
default:
|
|
||||||
return compiled.replace(/\s+/g, ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Domain option?
|
|
||||||
switch ( fid ) {
|
|
||||||
case '0ah':
|
|
||||||
case '1ah':
|
|
||||||
case '|ah':
|
|
||||||
case 'a|h':
|
|
||||||
case '||ah':
|
|
||||||
case '//h':
|
|
||||||
opts.push('domain=' + tfields[1]);
|
|
||||||
break;
|
|
||||||
case 'ah':
|
|
||||||
case '_h':
|
|
||||||
case '||_h':
|
|
||||||
opts.push('domain=' + tfields[2]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( opts.length !== 0 ) {
|
|
||||||
filter += '$' + opts.join(',');
|
|
||||||
}
|
|
||||||
|
|
||||||
return filter;
|
|
||||||
};
|
|
||||||
|
|
||||||
var reEscapeHostname = /[.[\]]/g;
|
|
||||||
var reEscape = /[.+?${}()|[\]\\]/g;
|
|
||||||
var reWildcards = /\*+/g;
|
|
||||||
var reSeparator = /\^/g;
|
|
||||||
|
|
||||||
var toRegex = function(compiled) {
|
|
||||||
var vfields = compiled.split('\v');
|
|
||||||
var fid = vfields[1] === '.' ? '.' : vfields[2];
|
|
||||||
var tfields = fid !== '.' ? vfields[3].split('\t') : [];
|
|
||||||
var reStr;
|
|
||||||
|
|
||||||
switch ( fid ) {
|
|
||||||
case '.':
|
|
||||||
reStr = vfields[2].replace(reEscapeHostname, '\\$&') +
|
|
||||||
'(?:[^%.0-9a-z_-]|$)';
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
case 'ah':
|
|
||||||
case '0a':
|
|
||||||
case '0ah':
|
|
||||||
case '1a':
|
|
||||||
case '1ah':
|
|
||||||
case '|a':
|
|
||||||
case '|ah':
|
|
||||||
case 'a|':
|
|
||||||
case 'a|h':
|
|
||||||
case '_':
|
|
||||||
case '_h':
|
|
||||||
reStr = tfields[0]
|
|
||||||
.replace(reEscape, '\\$&')
|
|
||||||
.replace(reWildcards, '.*?')
|
|
||||||
.replace(reSeparator, '(?:[^%.0-9a-z_-]|$)');
|
|
||||||
break;
|
|
||||||
case '||a':
|
|
||||||
case '||ah':
|
|
||||||
case '||_':
|
|
||||||
case '||_h':
|
|
||||||
reStr = '';
|
|
||||||
if ( tfields[0].charCodeAt(0) === 0x2A ) {
|
|
||||||
reStr = '[0-9a-z.-]*?';
|
|
||||||
tfields[0] = tfields[0].slice(1);
|
|
||||||
}
|
|
||||||
reStr += tfields[0]
|
|
||||||
.replace(reEscape, '\\$&')
|
|
||||||
.replace(reWildcards, '.*?')
|
|
||||||
.replace(reSeparator, '(?:[^%.0-9a-z_-]|$)');
|
|
||||||
break;
|
|
||||||
case '//':
|
|
||||||
case '//h':
|
|
||||||
reStr = tfields[0];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anchored?
|
|
||||||
var s = fid.slice(0, 2);
|
|
||||||
if ( s === '|a' ) {
|
|
||||||
reStr = '^' + reStr;
|
|
||||||
} else if ( s === 'a|' ) {
|
|
||||||
reStr += '$';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( reStr === undefined) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new RegExp(reStr, 'gi');
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
toString: toString,
|
|
||||||
toRegex: toRegex
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
var createCellAt = function(tr, index) {
|
var createCellAt = function(tr, index) {
|
||||||
var td = tr.cells[index];
|
var td = tr.cells[index];
|
||||||
var mustAppend = !td;
|
var mustAppend = !td;
|
||||||
|
@ -442,7 +238,7 @@ var createGap = function(tabId, url) {
|
||||||
|
|
||||||
var renderNetLogEntry = function(tr, entry) {
|
var renderNetLogEntry = function(tr, entry) {
|
||||||
var trcl = tr.classList;
|
var trcl = tr.classList;
|
||||||
var filter = entry.d0;
|
var filter = entry.d0 || undefined;
|
||||||
var type = entry.d1;
|
var type = entry.d1;
|
||||||
var url = entry.d2;
|
var url = entry.d2;
|
||||||
var td;
|
var td;
|
||||||
|
@ -463,52 +259,50 @@ var renderNetLogEntry = function(tr, entry) {
|
||||||
tr.setAttribute('data-hn-frame', entry.d4);
|
tr.setAttribute('data-hn-frame', entry.d4);
|
||||||
}
|
}
|
||||||
|
|
||||||
var filterCat = filter.slice(0, 3);
|
var filteringType;
|
||||||
if ( filterCat.charAt(2) === ':' ) {
|
if ( filter !== undefined && typeof filter.source === 'string' ) {
|
||||||
trcl.add(filterCat.slice(0, 2));
|
filteringType = filter.source;
|
||||||
|
trcl.add(filteringType);
|
||||||
}
|
}
|
||||||
|
|
||||||
var filteringType = filterCat.charAt(0);
|
|
||||||
td = tr.cells[2];
|
td = tr.cells[2];
|
||||||
if ( filter !== '' ) {
|
if ( filter !== undefined ) {
|
||||||
filter = filter.slice(3);
|
if ( filteringType === 'static' ) {
|
||||||
if ( filteringType === 's' ) {
|
td.textContent = filter.raw;
|
||||||
td.textContent = filterDecompiler.toString(filter);
|
|
||||||
trcl.add('canLookup');
|
trcl.add('canLookup');
|
||||||
tr.setAttribute('data-filter', filter);
|
tr.setAttribute('data-filter', filter.compiled);
|
||||||
} else if ( filteringType === 'c' ) {
|
} else if ( filteringType === 'cosmetic' ) {
|
||||||
td.textContent = filter;
|
td.textContent = filter.raw;
|
||||||
trcl.add('canLookup');
|
trcl.add('canLookup');
|
||||||
} else {
|
} else {
|
||||||
td.textContent = filter;
|
td.textContent = filter.raw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
td = tr.cells[3];
|
td = tr.cells[3];
|
||||||
var filteringOp = filterCat.charAt(1);
|
if ( filter !== undefined ) {
|
||||||
if ( filteringOp === 'b' ) {
|
if ( filter.result === 1 ) {
|
||||||
trcl.add('blocked');
|
trcl.add('blocked');
|
||||||
td.textContent = '--';
|
td.textContent = '--';
|
||||||
} else if ( filteringOp === 'a' ) {
|
} else if ( filter.result === 2 ) {
|
||||||
trcl.add('allowed');
|
trcl.add('allowed');
|
||||||
td.textContent = '++';
|
td.textContent = '++';
|
||||||
} else if ( filteringOp === 'n' ) {
|
} else if ( filter.result === 3 ) {
|
||||||
trcl.add('nooped');
|
trcl.add('nooped');
|
||||||
td.textContent = '**';
|
td.textContent = '**';
|
||||||
} else if ( filteringOp === 'r' ) {
|
} else if ( filter.source === 'redirect' ) {
|
||||||
trcl.add('redirected');
|
trcl.add('redirect');
|
||||||
td.textContent = '<<';
|
td.textContent = '<<';
|
||||||
} else {
|
}
|
||||||
td.textContent = '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.cells[4].textContent = (prettyRequestTypes[type] || type);
|
tr.cells[4].textContent = (prettyRequestTypes[type] || type);
|
||||||
|
|
||||||
var re = null;
|
var re = null;
|
||||||
if ( filteringType === 's' ) {
|
if ( filteringType === 'static' ) {
|
||||||
re = filterDecompiler.toRegex(filter);
|
re = new RegExp(filter.regex, 'gi');
|
||||||
} else if ( filteringType === 'l' ) {
|
} else if ( filteringType === 'dynamicUrl' ) {
|
||||||
re = regexFromURLFilteringResult(filter);
|
re = regexFromURLFilteringResult(filter.rule.join(' '));
|
||||||
}
|
}
|
||||||
tr.cells[5].appendChild(nodeFromURL(url, re));
|
tr.cells[5].appendChild(nodeFromURL(url, re));
|
||||||
};
|
};
|
||||||
|
|
|
@ -258,28 +258,28 @@ var getHostnameDict = function(hostnameToCountMap) {
|
||||||
var getFirewallRules = function(srcHostname, desHostnames) {
|
var getFirewallRules = function(srcHostname, desHostnames) {
|
||||||
var r = {};
|
var r = {};
|
||||||
var df = µb.sessionFirewall;
|
var df = µb.sessionFirewall;
|
||||||
r['/ * *'] = df.evaluateCellZY('*', '*', '*').toFilterString();
|
r['/ * *'] = df.lookupRuleData('*', '*', '*');
|
||||||
r['/ * image'] = df.evaluateCellZY('*', '*', 'image').toFilterString();
|
r['/ * image'] = df.lookupRuleData('*', '*', 'image');
|
||||||
r['/ * 3p'] = df.evaluateCellZY('*', '*', '3p').toFilterString();
|
r['/ * 3p'] = df.lookupRuleData('*', '*', '3p');
|
||||||
r['/ * inline-script'] = df.evaluateCellZY('*', '*', 'inline-script').toFilterString();
|
r['/ * inline-script'] = df.lookupRuleData('*', '*', 'inline-script');
|
||||||
r['/ * 1p-script'] = df.evaluateCellZY('*', '*', '1p-script').toFilterString();
|
r['/ * 1p-script'] = df.lookupRuleData('*', '*', '1p-script');
|
||||||
r['/ * 3p-script'] = df.evaluateCellZY('*', '*', '3p-script').toFilterString();
|
r['/ * 3p-script'] = df.lookupRuleData('*', '*', '3p-script');
|
||||||
r['/ * 3p-frame'] = df.evaluateCellZY('*', '*', '3p-frame').toFilterString();
|
r['/ * 3p-frame'] = df.lookupRuleData('*', '*', '3p-frame');
|
||||||
if ( typeof srcHostname !== 'string' ) {
|
if ( typeof srcHostname !== 'string' ) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
r['. * *'] = df.evaluateCellZY(srcHostname, '*', '*').toFilterString();
|
r['. * *'] = df.lookupRuleData(srcHostname, '*', '*');
|
||||||
r['. * image'] = df.evaluateCellZY(srcHostname, '*', 'image').toFilterString();
|
r['. * image'] = df.lookupRuleData(srcHostname, '*', 'image');
|
||||||
r['. * 3p'] = df.evaluateCellZY(srcHostname, '*', '3p').toFilterString();
|
r['. * 3p'] = df.lookupRuleData(srcHostname, '*', '3p');
|
||||||
r['. * inline-script'] = df.evaluateCellZY(srcHostname, '*', 'inline-script').toFilterString();
|
r['. * inline-script'] = df.lookupRuleData(srcHostname, '*', 'inline-script');
|
||||||
r['. * 1p-script'] = df.evaluateCellZY(srcHostname, '*', '1p-script').toFilterString();
|
r['. * 1p-script'] = df.lookupRuleData(srcHostname, '*', '1p-script');
|
||||||
r['. * 3p-script'] = df.evaluateCellZY(srcHostname, '*', '3p-script').toFilterString();
|
r['. * 3p-script'] = df.lookupRuleData(srcHostname, '*', '3p-script');
|
||||||
r['. * 3p-frame'] = df.evaluateCellZY(srcHostname, '*', '3p-frame').toFilterString();
|
r['. * 3p-frame'] = df.lookupRuleData(srcHostname, '*', '3p-frame');
|
||||||
|
|
||||||
for ( var desHostname in desHostnames ) {
|
for ( var desHostname in desHostnames ) {
|
||||||
r['/ ' + desHostname + ' *'] = df.evaluateCellZY('*', desHostname, '*').toFilterString();
|
r['/ ' + desHostname + ' *'] = df.lookupRuleData('*', desHostname, '*');
|
||||||
r['. ' + desHostname + ' *'] = df.evaluateCellZY(srcHostname, desHostname, '*').toFilterString();
|
r['. ' + desHostname + ' *'] = df.lookupRuleData(srcHostname, desHostname, '*');
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
|
@ -1239,7 +1239,7 @@ var logCosmeticFilters = function(tabId, details) {
|
||||||
µb.logger.writeOne(
|
µb.logger.writeOne(
|
||||||
tabId,
|
tabId,
|
||||||
'cosmetic',
|
'cosmetic',
|
||||||
'cb:##' + selectors[i],
|
{ source: 'cosmetic', raw: '##' + selectors[i] },
|
||||||
'dom',
|
'dom',
|
||||||
details.frameURL,
|
details.frameURL,
|
||||||
null,
|
null,
|
||||||
|
|
|
@ -48,16 +48,17 @@ var netFilteringResultCacheEntryJunkyardMax = 200;
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var NetFilteringResultCacheEntry = function(result, type) {
|
var NetFilteringResultCacheEntry = function(result, type, logData) {
|
||||||
this.init(result, type);
|
this.init(result, type, logData);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
NetFilteringResultCacheEntry.prototype.init = function(result, type) {
|
NetFilteringResultCacheEntry.prototype.init = function(result, type, logData) {
|
||||||
this.result = result;
|
this.result = result;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.time = Date.now();
|
this.time = Date.now();
|
||||||
|
this.logData = logData;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -65,6 +66,7 @@ NetFilteringResultCacheEntry.prototype.init = function(result, type) {
|
||||||
|
|
||||||
NetFilteringResultCacheEntry.prototype.dispose = function() {
|
NetFilteringResultCacheEntry.prototype.dispose = function() {
|
||||||
this.result = this.type = '';
|
this.result = this.type = '';
|
||||||
|
this.logData = undefined;
|
||||||
if ( netFilteringResultCacheEntryJunkyard.length < netFilteringResultCacheEntryJunkyardMax ) {
|
if ( netFilteringResultCacheEntryJunkyard.length < netFilteringResultCacheEntryJunkyardMax ) {
|
||||||
netFilteringResultCacheEntryJunkyard.push(this);
|
netFilteringResultCacheEntryJunkyard.push(this);
|
||||||
}
|
}
|
||||||
|
@ -72,11 +74,11 @@ NetFilteringResultCacheEntry.prototype.dispose = function() {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
NetFilteringResultCacheEntry.factory = function(result, type) {
|
NetFilteringResultCacheEntry.factory = function(result, type, logData) {
|
||||||
if ( netFilteringResultCacheEntryJunkyard.length ) {
|
if ( netFilteringResultCacheEntryJunkyard.length ) {
|
||||||
return netFilteringResultCacheEntryJunkyard.pop().init(result, type);
|
return netFilteringResultCacheEntryJunkyard.pop().init(result, type, logData);
|
||||||
}
|
}
|
||||||
return new NetFilteringResultCacheEntry(result, type);
|
return new NetFilteringResultCacheEntry(result, type, logData);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -127,7 +129,7 @@ NetFilteringResultCache.prototype.dispose = function() {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
NetFilteringResultCache.prototype.add = function(context, result) {
|
NetFilteringResultCache.prototype.add = function(context, result, logData) {
|
||||||
var url = context.requestURL,
|
var url = context.requestURL,
|
||||||
type = context.requestType,
|
type = context.requestType,
|
||||||
key = type + ' ' + url,
|
key = type + ' ' + url,
|
||||||
|
@ -136,9 +138,10 @@ NetFilteringResultCache.prototype.add = function(context, result) {
|
||||||
entry.result = result;
|
entry.result = result;
|
||||||
entry.type = type;
|
entry.type = type;
|
||||||
entry.time = Date.now();
|
entry.time = Date.now();
|
||||||
|
entry.logData = logData;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.urls[key] = NetFilteringResultCacheEntry.factory(result, type);
|
this.urls[key] = NetFilteringResultCacheEntry.factory(result, type, logData);
|
||||||
if ( this.count === 0 ) {
|
if ( this.count === 0 ) {
|
||||||
this.pruneAsync();
|
this.pruneAsync();
|
||||||
}
|
}
|
||||||
|
@ -305,6 +308,7 @@ PageStore.prototype.init = function(tabId) {
|
||||||
this.hostnameToCountMap = new Map();
|
this.hostnameToCountMap = new Map();
|
||||||
this.contentLastModified = 0;
|
this.contentLastModified = 0;
|
||||||
this.frames = Object.create(null);
|
this.frames = Object.create(null);
|
||||||
|
this.logData = undefined;
|
||||||
this.perLoadBlockedRequestCount = 0;
|
this.perLoadBlockedRequestCount = 0;
|
||||||
this.perLoadAllowedRequestCount = 0;
|
this.perLoadAllowedRequestCount = 0;
|
||||||
this.hiddenElementCount = ''; // Empty string means "unknown"
|
this.hiddenElementCount = ''; // Empty string means "unknown"
|
||||||
|
@ -320,7 +324,7 @@ PageStore.prototype.init = function(tabId) {
|
||||||
µb.logger.writeOne(
|
µb.logger.writeOne(
|
||||||
tabId,
|
tabId,
|
||||||
'cosmetic',
|
'cosmetic',
|
||||||
µb.hnSwitches.toResultString(),
|
µb.hnSwitches.toLogData(),
|
||||||
'dom',
|
'dom',
|
||||||
tabContext.rawURL,
|
tabContext.rawURL,
|
||||||
this.tabHostname,
|
this.tabHostname,
|
||||||
|
@ -336,12 +340,12 @@ PageStore.prototype.init = function(tabId) {
|
||||||
tabContext.normalURL,
|
tabContext.normalURL,
|
||||||
'generichide'
|
'generichide'
|
||||||
);
|
);
|
||||||
this.noGenericCosmeticFiltering = result === false;
|
this.noGenericCosmeticFiltering = result === 2;
|
||||||
if ( result !== undefined && µb.logger.isEnabled() ) {
|
if ( result !== 0 && µb.logger.isEnabled() ) {
|
||||||
µb.logger.writeOne(
|
µb.logger.writeOne(
|
||||||
tabId,
|
tabId,
|
||||||
'net',
|
'net',
|
||||||
µb.staticNetFilteringEngine.toResultString(true),
|
µb.staticNetFilteringEngine.toLogData(),
|
||||||
'generichide',
|
'generichide',
|
||||||
tabContext.rawURL,
|
tabContext.rawURL,
|
||||||
this.tabHostname,
|
this.tabHostname,
|
||||||
|
@ -525,7 +529,7 @@ PageStore.prototype.journalAddRequest = function(hostname, result) {
|
||||||
if ( hostname === '' ) { return; }
|
if ( hostname === '' ) { return; }
|
||||||
this.journal.push(
|
this.journal.push(
|
||||||
hostname,
|
hostname,
|
||||||
result.charCodeAt(1) === 0x62 /* 'b' */ ? 0x00000001 : 0x00010000
|
result === 1 ? 0x00000001 : 0x00010000
|
||||||
);
|
);
|
||||||
if ( this.journalTimer === null ) {
|
if ( this.journalTimer === null ) {
|
||||||
this.journalTimer = vAPI.setTimeout(this.journalProcess.bind(this, true), 1000);
|
this.journalTimer = vAPI.setTimeout(this.journalProcess.bind(this, true), 1000);
|
||||||
|
@ -604,6 +608,8 @@ PageStore.prototype.journalProcess = function(fromTimer) {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
PageStore.prototype.filterRequest = function(context) {
|
PageStore.prototype.filterRequest = function(context) {
|
||||||
|
this.logData = undefined;
|
||||||
|
|
||||||
var requestType = context.requestType;
|
var requestType = context.requestType;
|
||||||
|
|
||||||
// We want to short-term cache filtering results of collapsible types,
|
// We want to short-term cache filtering results of collapsible types,
|
||||||
|
@ -614,35 +620,39 @@ PageStore.prototype.filterRequest = function(context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( this.getNetFilteringSwitch() === false ) {
|
if ( this.getNetFilteringSwitch() === false ) {
|
||||||
this.netFilteringCache.add(context, '');
|
this.netFilteringCache.add(context, 0);
|
||||||
return '';
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var entry = this.netFilteringCache.lookup(context);
|
var entry = this.netFilteringCache.lookup(context);
|
||||||
if ( entry !== undefined ) {
|
if ( entry !== undefined ) {
|
||||||
|
this.logData = entry.logData;
|
||||||
return entry.result;
|
return entry.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamic URL filtering.
|
// Dynamic URL filtering.
|
||||||
µb.sessionURLFiltering.evaluateZ(context.rootHostname, context.requestURL, requestType);
|
var result = µb.sessionURLFiltering.evaluateZ(context.rootHostname, context.requestURL, requestType);
|
||||||
var result = µb.sessionURLFiltering.toFilterString();
|
if ( result !== 0 && µb.logger.isEnabled() ) {
|
||||||
|
this.logData = µb.sessionURLFiltering.toLogData();
|
||||||
|
}
|
||||||
|
|
||||||
// Dynamic hostname/type filtering.
|
// Dynamic hostname/type filtering.
|
||||||
if ( result === '' && µb.userSettings.advancedUserEnabled ) {
|
if ( result === 0 && µb.userSettings.advancedUserEnabled ) {
|
||||||
µb.sessionFirewall.evaluateCellZY( context.rootHostname, context.requestHostname, requestType);
|
result = µb.sessionFirewall.evaluateCellZY( context.rootHostname, context.requestHostname, requestType);
|
||||||
if ( µb.sessionFirewall.mustBlockOrAllow() ) {
|
if ( result !== 0 && µb.logger.isEnabled() ) {
|
||||||
result = µb.sessionFirewall.toFilterString();
|
this.logData = µb.sessionFirewall.toLogData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static filtering: lowest filtering precedence.
|
// Static filtering: lowest filtering precedence.
|
||||||
if ( result === '' || result.charCodeAt(1) === 110 /* 'n' */ ) {
|
if ( result === 0 || result === 3 ) {
|
||||||
if ( µb.staticNetFilteringEngine.matchString(context) !== undefined ) {
|
result = µb.staticNetFilteringEngine.matchString(context);
|
||||||
result = µb.staticNetFilteringEngine.toResultString(µb.logger.isEnabled());
|
if ( result !== 0 && µb.logger.isEnabled() ) {
|
||||||
|
this.logData = µb.staticNetFilteringEngine.toLogData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.netFilteringCache.add(context, result);
|
this.netFilteringCache.add(context, result, this.logData);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
@ -652,14 +662,16 @@ PageStore.prototype.filterRequest = function(context) {
|
||||||
// The caller is responsible to check whether filtering is enabled or not.
|
// The caller is responsible to check whether filtering is enabled or not.
|
||||||
|
|
||||||
PageStore.prototype.filterLargeMediaElement = function(size) {
|
PageStore.prototype.filterLargeMediaElement = function(size) {
|
||||||
|
this.logData = undefined;
|
||||||
|
|
||||||
if ( Date.now() < this.allowLargeMediaElementsUntil ) {
|
if ( Date.now() < this.allowLargeMediaElementsUntil ) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
if ( µb.hnSwitches.evaluateZ('no-large-media', this.tabHostname) !== true ) {
|
if ( µb.hnSwitches.evaluateZ('no-large-media', this.tabHostname) !== true ) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
if ( (size >>> 10) < µb.userSettings.largeMediaSize ) {
|
if ( (size >>> 10) < µb.userSettings.largeMediaSize ) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.largeMediaCount += 1;
|
this.largeMediaCount += 1;
|
||||||
|
@ -670,48 +682,66 @@ PageStore.prototype.filterLargeMediaElement = function(size) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return µb.hnSwitches.toResultString();
|
if ( µb.logger.isEnabled() ) {
|
||||||
|
this.logData = µb.hnSwitches.toLogData();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
PageStore.prototype.filterRequestNoCache = function(context) {
|
PageStore.prototype.filterRequestNoCache = function(context) {
|
||||||
|
this.logData = undefined;
|
||||||
|
|
||||||
if ( this.getNetFilteringSwitch() === false ) {
|
if ( this.getNetFilteringSwitch() === false ) {
|
||||||
return '';
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var requestType = context.requestType,
|
var requestType = context.requestType;
|
||||||
result = '';
|
|
||||||
|
|
||||||
if ( requestType === 'csp_report' ) {
|
if ( requestType === 'csp_report' ) {
|
||||||
if ( this.internalRedirectionCount !== 0 ) {
|
if ( this.internalRedirectionCount !== 0 ) {
|
||||||
result = 'gb:no-spurious-csp-report';
|
if ( µb.logger.isEnabled() ) {
|
||||||
|
this.logData = { result: 1, source: 'global', raw: 'no-spurious-csp-report' };
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
} else if ( requestType === 'font' ) {
|
|
||||||
if ( µb.hnSwitches.evaluateZ('no-remote-fonts', context.rootHostname) !== false ) {
|
|
||||||
result = µb.hnSwitches.toResultString();
|
|
||||||
}
|
|
||||||
this.remoteFontCount += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( requestType === 'font' ) {
|
||||||
|
this.remoteFontCount += 1;
|
||||||
|
if ( µb.hnSwitches.evaluateZ('no-remote-fonts', context.rootHostname) !== false ) {
|
||||||
|
if ( µb.logger.isEnabled() ) {
|
||||||
|
this.logData = µb.hnSwitches.toLogData();
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = 0;
|
||||||
|
|
||||||
// Dynamic URL filtering.
|
// Dynamic URL filtering.
|
||||||
if ( result === '' ) {
|
if ( result === 0 ) {
|
||||||
µb.sessionURLFiltering.evaluateZ(context.rootHostname, context.requestURL, requestType);
|
result = µb.sessionURLFiltering.evaluateZ(context.rootHostname, context.requestURL, requestType);
|
||||||
result = µb.sessionURLFiltering.toFilterString();
|
if ( result !== 0 && µb.logger.isEnabled() ) {
|
||||||
|
this.logData = µb.sessionURLFiltering.toLogData();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamic hostname/type filtering.
|
// Dynamic hostname/type filtering.
|
||||||
if ( result === '' && µb.userSettings.advancedUserEnabled ) {
|
if ( result === 0 && µb.userSettings.advancedUserEnabled ) {
|
||||||
µb.sessionFirewall.evaluateCellZY(context.rootHostname, context.requestHostname, requestType);
|
result = µb.sessionFirewall.evaluateCellZY(context.rootHostname, context.requestHostname, requestType);
|
||||||
if ( µb.sessionFirewall.mustBlockOrAllow() ) {
|
if ( result !== 0 && µb.logger.isEnabled() ) {
|
||||||
result = µb.sessionFirewall.toFilterString();
|
this.logData = µb.sessionFirewall.toLogData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static filtering has lowest precedence.
|
// Static filtering has lowest precedence.
|
||||||
if ( result === '' || result.charCodeAt(1) === 110 /* 'n' */ ) {
|
if ( result === 0 || result === 3 ) {
|
||||||
if ( µb.staticNetFilteringEngine.matchString(context) !== undefined ) {
|
result = µb.staticNetFilteringEngine.matchString(context);
|
||||||
result = µb.staticNetFilteringEngine.toResultString(µb.logger.isEnabled());
|
if ( result !== 0 && µb.logger.isEnabled() ) {
|
||||||
|
this.logData = µb.staticNetFilteringEngine.toLogData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,6 @@ var messaging = vAPI.messaging;
|
||||||
var popupData = {};
|
var popupData = {};
|
||||||
var dfPaneBuilt = false;
|
var dfPaneBuilt = false;
|
||||||
var reIP = /^\d+(?:\.\d+){1,3}$/;
|
var reIP = /^\d+(?:\.\d+){1,3}$/;
|
||||||
var reSrcHostnameFromRule = /^d[abn]:([^ ]+) ([^ ]+) ([^ ]+)/;
|
|
||||||
var scopeToSrcHostnameMap = {
|
var scopeToSrcHostnameMap = {
|
||||||
'/': '*',
|
'/': '*',
|
||||||
'.': ''
|
'.': ''
|
||||||
|
@ -148,16 +147,12 @@ var hashFromPopupData = function(reset) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasher = [];
|
var hasher = [],
|
||||||
var rules = popupData.firewallRules;
|
rules = popupData.firewallRules;
|
||||||
var rule;
|
|
||||||
for ( var key in rules ) {
|
for ( var key in rules ) {
|
||||||
if ( rules.hasOwnProperty(key) === false ) {
|
var rule = rules[key];
|
||||||
continue;
|
if ( rule !== null ) {
|
||||||
}
|
hasher.push(rule.src + ' ' + rule.des + ' ' + rule.type + ' ' + rule.action);
|
||||||
rule = rules[key];
|
|
||||||
if ( rule !== '' ) {
|
|
||||||
hasher.push(rule);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hasher.sort();
|
hasher.sort();
|
||||||
|
@ -243,18 +238,16 @@ var updateFirewallCell = function(scope, des, type, rule) {
|
||||||
}
|
}
|
||||||
|
|
||||||
cells.removeClass();
|
cells.removeClass();
|
||||||
var action = rule.charAt(1);
|
if ( rule !== null ) {
|
||||||
if ( action !== '' ) {
|
cells.toggleClass(rule.action + 'Rule', true);
|
||||||
cells.toggleClass(action + 'Rule', true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use dark shade visual cue if the rule is specific to the cell.
|
// Use dark shade visual cue if the rule is specific to the cell.
|
||||||
var ownRule = false;
|
var ownRule = false;
|
||||||
var matches = reSrcHostnameFromRule.exec(rule);
|
if ( rule !== null ) {
|
||||||
if ( matches !== null ) {
|
ownRule = (rule.des !== '*' || rule.type === type) &&
|
||||||
ownRule = (matches[2] !== '*' || matches[3] === type) &&
|
(rule.des === des) &&
|
||||||
(matches[2] === des) &&
|
(rule.src === scopeToSrcHostnameMap[scope]);
|
||||||
(matches[1] === scopeToSrcHostnameMap[scope]);
|
|
||||||
}
|
}
|
||||||
cells.toggleClass('ownRule', ownRule);
|
cells.toggleClass('ownRule', ownRule);
|
||||||
|
|
||||||
|
|
|
@ -35,14 +35,14 @@ var reEscape = function(s) {
|
||||||
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
};
|
};
|
||||||
|
|
||||||
var reSpecialChars = /[\*\^\t\v\n]/;
|
var reSpecialNetworkChars = /[a-d]/;
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var fromNetFilter = function(details) {
|
var fromNetFilter = function(details) {
|
||||||
var lists = [];
|
var lists = [];
|
||||||
var compiledFilter = details.compiledFilter;
|
var compiledFilter = details.compiledFilter;
|
||||||
var entry, content, pos, c;
|
var entry, content, pos, notFound;
|
||||||
for ( var assetKey in listEntries ) {
|
for ( var assetKey in listEntries ) {
|
||||||
entry = listEntries[assetKey];
|
entry = listEntries[assetKey];
|
||||||
if ( entry === undefined ) {
|
if ( entry === undefined ) {
|
||||||
|
@ -52,23 +52,23 @@ var fromNetFilter = function(details) {
|
||||||
pos = 0;
|
pos = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
pos = content.indexOf(compiledFilter, pos);
|
pos = content.indexOf(compiledFilter, pos);
|
||||||
if ( pos === -1 ) {
|
if ( pos === -1 ) { break; }
|
||||||
break;
|
|
||||||
}
|
|
||||||
// We need an exact match.
|
// We need an exact match.
|
||||||
// https://github.com/gorhill/uBlock/issues/1392
|
// https://github.com/gorhill/uBlock/issues/1392
|
||||||
// https://github.com/gorhill/uBlock/issues/835
|
// https://github.com/gorhill/uBlock/issues/835
|
||||||
if ( pos === 0 || reSpecialChars.test(content.charAt(pos - 1)) ) {
|
pos -= 1;
|
||||||
c = content.charAt(pos + compiledFilter.length);
|
notFound =
|
||||||
if ( c === '' || reSpecialChars.test(c) ) {
|
reSpecialNetworkChars.test(content.charAt(pos)) === false ||
|
||||||
lists.push({
|
pos !== 0 && content.charCodeAt(pos - 1) !== 0x0A /* '\n' */;
|
||||||
title: entry.title,
|
pos += 1 + compiledFilter.length;
|
||||||
supportURL: entry.supportURL
|
if ( notFound ) { continue; }
|
||||||
});
|
if ( pos === content.length || content.charCodeAt(pos) === 0x0A ) {
|
||||||
break;
|
lists.push({
|
||||||
}
|
title: entry.title,
|
||||||
|
supportURL: entry.supportURL
|
||||||
|
});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
pos += compiledFilter.length;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,18 +119,18 @@ var fromCosmeticFilter = function(details) {
|
||||||
var matches = rePlainSelector.exec(filter);
|
var matches = rePlainSelector.exec(filter);
|
||||||
if ( matches ) {
|
if ( matches ) {
|
||||||
if ( matches[0] === filter ) { // simple CSS selector
|
if ( matches[0] === filter ) { // simple CSS selector
|
||||||
reStr.push('c', 'lg', reEscape(filter));
|
reStr.push('[e-h]lg', reEscape(filter));
|
||||||
} else { // complex CSS selector
|
} else { // complex CSS selector
|
||||||
reStr.push('c', reEscape('lg+'), reEscape(matches[0]), reEscape(filter));
|
reStr.push('[e-h]lg\\+', reEscape(matches[0]), reEscape(filter));
|
||||||
}
|
}
|
||||||
} else if ( reHighLow.test(filter) ) { // [alt] or [title]
|
} else if ( reHighLow.test(filter) ) { // [alt] or [title]
|
||||||
reStr.push('c', 'hlg0', reEscape(filter));
|
reStr.push('[e-h]hlg0', reEscape(filter));
|
||||||
} else if ( reHighMedium.test(filter) ) { // [href^="..."]
|
} else if ( reHighMedium.test(filter) ) { // [href^="..."]
|
||||||
reStr.push('c', 'hmg0', '[^"]{8}', '[a-z]*' + reEscape(filter));
|
reStr.push('[e-h]hmg0', '[^"]{8}', '[a-z]*' + reEscape(filter));
|
||||||
} else if ( filter.indexOf(' ') === -1 ) { // high-high-simple selector
|
} else if ( filter.indexOf(' ') === -1 ) { // high-high-simple selector
|
||||||
reStr.push('c', 'hhsg0', reEscape(filter));
|
reStr.push('[e-h]hhsg0', reEscape(filter));
|
||||||
} else { // high-high-complex selector
|
} else { // high-high-complex selector
|
||||||
reStr.push('c', 'hhcg0', reEscape(filter));
|
reStr.push('[e-h]hhcg0', reEscape(filter));
|
||||||
}
|
}
|
||||||
candidates[details.rawFilter] = new RegExp(reStr.join('\\v') + '(?:\\n|$)');
|
candidates[details.rawFilter] = new RegExp(reStr.join('\\v') + '(?:\\n|$)');
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ var fromCosmeticFilter = function(details) {
|
||||||
if ( hostname !== '' ) {
|
if ( hostname !== '' ) {
|
||||||
for ( ;; ) {
|
for ( ;; ) {
|
||||||
candidates[hostname + '##' + filter] = new RegExp(
|
candidates[hostname + '##' + filter] = new RegExp(
|
||||||
['c', 'h', '[^\\v]+', reEscape(hostname), filterEx].join('\\v') +
|
['[e-h]h', '[^\\v]+', reEscape(hostname), filterEx].join('\\v') +
|
||||||
'(?:\\n|$)'
|
'(?:\\n|$)'
|
||||||
);
|
);
|
||||||
pos = hostname.indexOf('.');
|
pos = hostname.indexOf('.');
|
||||||
|
@ -168,7 +168,7 @@ var fromCosmeticFilter = function(details) {
|
||||||
if ( pos !== -1 ) {
|
if ( pos !== -1 ) {
|
||||||
var entity = domain.slice(0, pos) + '.*';
|
var entity = domain.slice(0, pos) + '.*';
|
||||||
candidates[entity + '##' + filter] = new RegExp(
|
candidates[entity + '##' + filter] = new RegExp(
|
||||||
['c', 'h', '[^\\v]+', reEscape(entity), filterEx].join('\\v') +
|
['[e-h]h', '[^\\v]+', reEscape(entity), filterEx].join('\\v') +
|
||||||
'(?:\\n|$)'
|
'(?:\\n|$)'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -680,6 +680,9 @@
|
||||||
µb.assets.get(assetKey, onRawListLoaded);
|
µb.assets.get(assetKey, onRawListLoaded);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if ( /[^\x00-\x7F]/.test(details.content) ) {
|
||||||
|
console.log(assetKey, 'has Unicode characters');
|
||||||
|
}
|
||||||
details.assetKey = assetKey;
|
details.assetKey = assetKey;
|
||||||
callback(details);
|
callback(details);
|
||||||
};
|
};
|
||||||
|
@ -727,7 +730,7 @@
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.compileFilters = function(rawText) {
|
µBlock.compileFilters = function(rawText) {
|
||||||
var compiledFilters = [];
|
var compiledFilters = new this.CompiledOutput();
|
||||||
|
|
||||||
// Useful references:
|
// Useful references:
|
||||||
// https://adblockplus.org/en/filter-cheatsheet
|
// https://adblockplus.org/en/filter-cheatsheet
|
||||||
|
@ -793,7 +796,7 @@
|
||||||
staticNetFilteringEngine.compile(line, compiledFilters);
|
staticNetFilteringEngine.compile(line, compiledFilters);
|
||||||
}
|
}
|
||||||
|
|
||||||
return compiledFilters.join('\n');
|
return compiledFilters.toString();
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
120
src/js/tab.js
120
src/js/tab.js
|
@ -525,7 +525,8 @@ vAPI.tabs.onClosed = function(tabId) {
|
||||||
vAPI.tabs.onPopupUpdated = (function() {
|
vAPI.tabs.onPopupUpdated = (function() {
|
||||||
// The same context object will be reused everytime. This also allows to
|
// The same context object will be reused everytime. This also allows to
|
||||||
// remember whether a popup or popunder was matched.
|
// remember whether a popup or popunder was matched.
|
||||||
var context = {};
|
var context = {},
|
||||||
|
logData;
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/commit/1d448b85b2931412508aa01bf899e0b6f0033626#commitcomment-14944764
|
// https://github.com/gorhill/uBlock/commit/1d448b85b2931412508aa01bf899e0b6f0033626#commitcomment-14944764
|
||||||
// See if two URLs are different, disregarding scheme -- because the scheme
|
// See if two URLs are different, disregarding scheme -- because the scheme
|
||||||
|
@ -549,8 +550,9 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
var popupMatch = function(openerURL, targetURL, clickedURL, popupType) {
|
var popupMatch = function(openerURL, targetURL, clickedURL, popupType) {
|
||||||
var openerHostname = µb.URI.hostnameFromURI(openerURL);
|
var openerHostname = µb.URI.hostnameFromURI(openerURL),
|
||||||
var openerDomain = µb.URI.domainFromHostname(openerHostname);
|
openerDomain = µb.URI.domainFromHostname(openerHostname),
|
||||||
|
result;
|
||||||
|
|
||||||
context.pageHostname = openerHostname;
|
context.pageHostname = openerHostname;
|
||||||
context.pageDomain = openerDomain;
|
context.pageDomain = openerDomain;
|
||||||
|
@ -579,90 +581,90 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||||
// URL.
|
// URL.
|
||||||
if ( openerHostname !== '' && targetURL !== 'about:blank' ) {
|
if ( openerHostname !== '' && targetURL !== 'about:blank' ) {
|
||||||
// Check per-site switch first
|
// Check per-site switch first
|
||||||
if ( µb.hnSwitches.evaluateZ('no-popups', openerHostname) ) {
|
if ( µb.hnSwitches.evaluateZ('no-popups', openerHostname) === true ) {
|
||||||
if ( typeof clickedURL === 'string' && areDifferentURLs(targetURL, clickedURL) ) {
|
if (
|
||||||
return 'ub:no-popups: ' + µb.hnSwitches.z + ' true';
|
typeof clickedURL === 'string' &&
|
||||||
|
areDifferentURLs(targetURL, clickedURL)
|
||||||
|
) {
|
||||||
|
logData = {
|
||||||
|
source: 'switch',
|
||||||
|
raw: 'no-popups: ' + µb.hnSwitches.z + ' true'
|
||||||
|
};
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/581
|
// https://github.com/gorhill/uBlock/issues/581
|
||||||
// Take into account popup-specific rules in dynamic URL filtering, OR
|
// Take into account popup-specific rules in dynamic URL filtering, OR
|
||||||
// generic allow rules.
|
// generic allow rules.
|
||||||
µb.sessionURLFiltering.evaluateZ(openerHostname, targetURL, popupType);
|
result = µb.sessionURLFiltering.evaluateZ(openerHostname, targetURL, popupType);
|
||||||
if (
|
if (
|
||||||
µb.sessionURLFiltering.r === 1 && µb.sessionURLFiltering.type === popupType ||
|
result === 1 && µb.sessionURLFiltering.type === popupType ||
|
||||||
µb.sessionURLFiltering.r === 2
|
result === 2
|
||||||
) {
|
) {
|
||||||
return µb.sessionURLFiltering.toFilterString();
|
logData = µb.sessionURLFiltering.toLogData();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/581
|
// https://github.com/gorhill/uBlock/issues/581
|
||||||
// Take into account `allow` rules in dynamic filtering: `block` rules
|
// Take into account `allow` rules in dynamic filtering: `block` rules
|
||||||
// are ignored, as block rules are not meant to block specific types
|
// are ignored, as block rules are not meant to block specific types
|
||||||
// like `popup` (just like with static filters).
|
// like `popup` (just like with static filters).
|
||||||
µb.sessionFirewall.evaluateCellZY(openerHostname, context.requestHostname, popupType);
|
result = µb.sessionFirewall.evaluateCellZY(openerHostname, context.requestHostname, popupType);
|
||||||
if ( µb.sessionFirewall.r === 2 ) {
|
if ( result === 2 ) {
|
||||||
return µb.sessionFirewall.toFilterString();
|
logData = µb.sessionFirewall.toLogData();
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/323
|
// https://github.com/chrisaljoudi/uBlock/issues/323
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/1142
|
// https://github.com/chrisaljoudi/uBlock/issues/1142
|
||||||
// Don't block if uBlock is turned off in popup's context
|
// Don't block if uBlock is turned off in popup's context
|
||||||
var snfe = µb.staticNetFilteringEngine;
|
if ( µb.getNetFilteringSwitch(targetURL) ) {
|
||||||
if (
|
result = µb.staticNetFilteringEngine.matchStringExactType(
|
||||||
µb.getNetFilteringSwitch(targetURL) &&
|
context,
|
||||||
snfe.matchStringExactType(context, targetURL, popupType) !== undefined
|
targetURL,
|
||||||
) {
|
popupType
|
||||||
return snfe.toResultString(µb.logger.isEnabled());
|
);
|
||||||
|
if ( result !== 0 ) {
|
||||||
|
logData = µb.staticNetFilteringEngine.toLogData();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
var mapPopunderResult = function(popunderURL, popunderHostname, result) {
|
var mapPopunderResult = function(popunderURL, popunderHostname, result) {
|
||||||
if ( result.startsWith('sb:') === false ) {
|
if (
|
||||||
return '';
|
logData === undefined ||
|
||||||
}
|
logData.source !== 'static' ||
|
||||||
var snfe = µb.staticNetFilteringEngine;
|
logData.token === '*'
|
||||||
var token = snfe.tokenRegister;
|
) {
|
||||||
if ( token === '*' ) {
|
return 0;
|
||||||
return '';
|
|
||||||
}
|
|
||||||
if ( token === '.' ) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = snfe.toResultString(true);
|
|
||||||
var re = snfe.filterRegexFromCompiled(result.slice(3));
|
|
||||||
if ( re === null ) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
var matches = re.exec(popunderURL);
|
|
||||||
if ( matches === null ) {
|
|
||||||
return '';
|
|
||||||
}
|
}
|
||||||
|
if ( logData.token === '.' ) { return result; }
|
||||||
|
var re = new RegExp(logData.regex),
|
||||||
|
matches = re.exec(popunderURL);
|
||||||
|
if ( matches === null ) { return ''; }
|
||||||
var beg = matches.index,
|
var beg = matches.index,
|
||||||
end = beg + matches[0].length,
|
end = beg + matches[0].length,
|
||||||
pos = popunderURL.indexOf(popunderHostname);
|
pos = popunderURL.indexOf(popunderHostname);
|
||||||
if ( pos === -1 ) {
|
if ( pos === -1 ) { return ''; }
|
||||||
return '';
|
|
||||||
}
|
|
||||||
// https://github.com/gorhill/uBlock/issues/1471
|
// https://github.com/gorhill/uBlock/issues/1471
|
||||||
// We test whether the opener hostname as at least one character
|
// We test whether the opener hostname as at least one character
|
||||||
// within matched portion of URL.
|
// within matched portion of URL.
|
||||||
// https://github.com/gorhill/uBlock/issues/1903
|
// https://github.com/gorhill/uBlock/issues/1903
|
||||||
// Ignore filters which cause a match before the start of the
|
// Ignore filters which cause a match before the start of the
|
||||||
// hostname in the URL.
|
// hostname in the URL.
|
||||||
return beg >= pos &&
|
return beg >= pos && beg < pos + popunderHostname.length && end > pos
|
||||||
beg < pos + popunderHostname.length &&
|
? result
|
||||||
end > pos ?
|
: 0;
|
||||||
result :
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var popunderMatch = function(openerURL, targetURL) {
|
var popunderMatch = function(openerURL, targetURL) {
|
||||||
var result = popupMatch(targetURL, openerURL, null, 'popunder');
|
var result = popupMatch(targetURL, openerURL, null, 'popunder');
|
||||||
if ( µb.isBlockResult(result) ) {
|
if ( result === 1 ) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
// https://github.com/gorhill/uBlock/issues/1010#issuecomment-186824878
|
// https://github.com/gorhill/uBlock/issues/1010#issuecomment-186824878
|
||||||
|
@ -671,24 +673,24 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||||
// a broad one, we will consider the opener tab to be a popunder tab.
|
// a broad one, we will consider the opener tab to be a popunder tab.
|
||||||
// For now, a "broad" filter is one which does not touch any part of
|
// For now, a "broad" filter is one which does not touch any part of
|
||||||
// the hostname part of the opener URL.
|
// the hostname part of the opener URL.
|
||||||
var popunderURL = openerURL;
|
var popunderURL = openerURL,
|
||||||
var popunderHostname = µb.URI.hostnameFromURI(popunderURL);
|
popunderHostname = µb.URI.hostnameFromURI(popunderURL);
|
||||||
if ( popunderHostname === '' ) {
|
if ( popunderHostname === '' ) {
|
||||||
return '';
|
return 0;
|
||||||
}
|
}
|
||||||
result = mapPopunderResult(
|
result = mapPopunderResult(
|
||||||
popunderURL,
|
popunderURL,
|
||||||
popunderHostname,
|
popunderHostname,
|
||||||
popupMatch(targetURL, popunderURL, null, 'popup')
|
popupMatch(targetURL, popunderURL, null, 'popup')
|
||||||
);
|
);
|
||||||
if ( result !== '' ) {
|
if ( result !== 0 ) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
// https://github.com/gorhill/uBlock/issues/1598
|
// https://github.com/gorhill/uBlock/issues/1598
|
||||||
// Try to find a match against origin part of the opener URL.
|
// Try to find a match against origin part of the opener URL.
|
||||||
popunderURL = µb.URI.originFromURI(popunderURL);
|
popunderURL = µb.URI.originFromURI(popunderURL);
|
||||||
if ( popunderURL === '' ) {
|
if ( popunderURL === '' ) {
|
||||||
return '';
|
return 0;
|
||||||
}
|
}
|
||||||
return mapPopunderResult(
|
return mapPopunderResult(
|
||||||
popunderURL,
|
popunderURL,
|
||||||
|
@ -731,13 +733,13 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Popup test.
|
// Popup test.
|
||||||
var popupType = 'popup';
|
var popupType = 'popup',
|
||||||
var result = popupMatch(openerURL, targetURL, µb.mouseURL, 'popup');
|
result = popupMatch(openerURL, targetURL, µb.mouseURL, 'popup');
|
||||||
|
|
||||||
// Popunder test.
|
// Popunder test.
|
||||||
if ( result === '' ) {
|
if ( result === 0 ) {
|
||||||
result = popunderMatch(openerURL, targetURL);
|
result = popunderMatch(openerURL, targetURL);
|
||||||
if ( µb.isBlockResult(result) ) {
|
if ( result === 1 ) {
|
||||||
popupType = 'popunder';
|
popupType = 'popunder';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -747,7 +749,7 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||||
µb.logger.writeOne(
|
µb.logger.writeOne(
|
||||||
popupType === 'popup' ? openerTabId : targetTabId,
|
popupType === 'popup' ? openerTabId : targetTabId,
|
||||||
'net',
|
'net',
|
||||||
result,
|
logData,
|
||||||
popupType,
|
popupType,
|
||||||
popupType === 'popup' ? targetURL : openerURL,
|
popupType === 'popup' ? targetURL : openerURL,
|
||||||
µb.URI.hostnameFromURI(context.rootURL),
|
µb.URI.hostnameFromURI(context.rootURL),
|
||||||
|
@ -756,7 +758,7 @@ vAPI.tabs.onPopupUpdated = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not blocked
|
// Not blocked
|
||||||
if ( µb.isAllowResult(result) ) {
|
if ( result !== 1 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,9 @@ var onBeforeRequest = function(details) {
|
||||||
var isFrame = requestType === 'sub_frame';
|
var isFrame = requestType === 'sub_frame';
|
||||||
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/114
|
// https://github.com/chrisaljoudi/uBlock/issues/114
|
||||||
var requestContext = pageStore.createContextFromFrameId(isFrame ? details.parentFrameId : details.frameId);
|
var requestContext = pageStore.createContextFromFrameId(
|
||||||
|
isFrame ? details.parentFrameId : details.frameId
|
||||||
|
);
|
||||||
|
|
||||||
// Setup context and evaluate
|
// Setup context and evaluate
|
||||||
var requestURL = details.url;
|
var requestURL = details.url;
|
||||||
|
@ -132,7 +134,7 @@ var onBeforeRequest = function(details) {
|
||||||
µb.logger.writeOne(
|
µb.logger.writeOne(
|
||||||
tabId,
|
tabId,
|
||||||
'net',
|
'net',
|
||||||
result,
|
pageStore.logData,
|
||||||
requestType,
|
requestType,
|
||||||
requestURL,
|
requestURL,
|
||||||
requestContext.rootHostname,
|
requestContext.rootHostname,
|
||||||
|
@ -141,7 +143,7 @@ var onBeforeRequest = function(details) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not blocked
|
// Not blocked
|
||||||
if ( µb.isAllowResult(result) ) {
|
if ( result !== 1 ) {
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/114
|
// https://github.com/chrisaljoudi/uBlock/issues/114
|
||||||
if ( details.parentFrameId !== -1 && isFrame ) {
|
if ( details.parentFrameId !== -1 && isFrame ) {
|
||||||
pageStore.setFrame(details.frameId, requestURL);
|
pageStore.setFrame(details.frameId, requestURL);
|
||||||
|
@ -162,7 +164,7 @@ var onBeforeRequest = function(details) {
|
||||||
µb.logger.writeOne(
|
µb.logger.writeOne(
|
||||||
tabId,
|
tabId,
|
||||||
'redirect',
|
'redirect',
|
||||||
'rr:' + µb.redirectEngine.resourceNameRegister,
|
{ source: 'redirect', raw: µb.redirectEngine.resourceNameRegister },
|
||||||
requestType,
|
requestType,
|
||||||
requestURL,
|
requestURL,
|
||||||
requestContext.rootHostname,
|
requestContext.rootHostname,
|
||||||
|
@ -193,8 +195,7 @@ var onBeforeRootFrameRequest = function(details) {
|
||||||
// behind-the-scene
|
// behind-the-scene
|
||||||
var µburi = µb.URI,
|
var µburi = µb.URI,
|
||||||
requestHostname = µburi.hostnameFromURI(requestURL),
|
requestHostname = µburi.hostnameFromURI(requestURL),
|
||||||
requestDomain = µburi.domainFromHostname(requestHostname) || requestHostname,
|
requestDomain = µburi.domainFromHostname(requestHostname) || requestHostname;
|
||||||
result = '';
|
|
||||||
var context = {
|
var context = {
|
||||||
rootHostname: requestHostname,
|
rootHostname: requestHostname,
|
||||||
rootDomain: requestDomain,
|
rootDomain: requestDomain,
|
||||||
|
@ -204,22 +205,31 @@ var onBeforeRootFrameRequest = function(details) {
|
||||||
requestHostname: requestHostname,
|
requestHostname: requestHostname,
|
||||||
requestType: 'main_frame'
|
requestType: 'main_frame'
|
||||||
};
|
};
|
||||||
|
var result = 0,
|
||||||
|
logData,
|
||||||
|
logEnabled = µb.logger.isEnabled();
|
||||||
|
|
||||||
// If the site is whitelisted, disregard strict blocking
|
// If the site is whitelisted, disregard strict blocking
|
||||||
if ( µb.getNetFilteringSwitch(requestURL) === false ) {
|
if ( µb.getNetFilteringSwitch(requestURL) === false ) {
|
||||||
result = 'ua:whitelisted';
|
result = 2;
|
||||||
|
if ( logEnabled === true ) {
|
||||||
|
logData = { engine: 'u', result: 2, raw: 'whitelisted' };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Permanently unrestricted?
|
// Permanently unrestricted?
|
||||||
if ( result === '' && µb.hnSwitches.evaluateZ('no-strict-blocking', requestHostname) ) {
|
if ( result === 0 && µb.hnSwitches.evaluateZ('no-strict-blocking', requestHostname) ) {
|
||||||
result = 'ua:no-strict-blocking: ' + µb.hnSwitches.z + ' true';
|
result = 2;
|
||||||
|
if ( logEnabled === true ) {
|
||||||
|
logData = { engine: 'u', result: 2, raw: 'no-strict-blocking: ' + µb.hnSwitches.z + ' true' };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporarily whitelisted?
|
// Temporarily whitelisted?
|
||||||
if ( result === '' ) {
|
if ( result === 0 ) {
|
||||||
result = isTemporarilyWhitelisted(result, requestHostname);
|
result = isTemporarilyWhitelisted(result, requestHostname);
|
||||||
if ( result.charAt(1) === 'a' ) {
|
if ( result === 2 && logEnabled === true ) {
|
||||||
result = 'ua:no-strict-blocking true (temporary)';
|
logData = { engine: 'u', result: 2, raw: 'no-strict-blocking true (temporary)' };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,26 +237,31 @@ var onBeforeRootFrameRequest = function(details) {
|
||||||
var snfe = µb.staticNetFilteringEngine;
|
var snfe = µb.staticNetFilteringEngine;
|
||||||
|
|
||||||
// Check for specific block
|
// Check for specific block
|
||||||
if (
|
if ( result === 0 ) {
|
||||||
result === '' &&
|
result = snfe.matchStringExactType(context, requestURL, 'main_frame');
|
||||||
snfe.matchStringExactType(context, requestURL, 'main_frame') !== undefined
|
if ( result !== 0 && logEnabled === true ) {
|
||||||
) {
|
logData = snfe.toLogData();
|
||||||
result = snfe.toResultString(true);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for generic block
|
// Check for generic block
|
||||||
if (
|
if ( result === 0 ) {
|
||||||
result === '' &&
|
result = snfe.matchStringExactType(context, requestURL, 'no_type');
|
||||||
snfe.matchStringExactType(context, requestURL, 'no_type') !== undefined
|
if ( result !== 0 ) {
|
||||||
) {
|
if ( result === 1 || logEnabled === true ) {
|
||||||
result = snfe.toResultString(true);
|
logData = snfe.toLogData();
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/1128
|
}
|
||||||
// Do not block if the match begins after the hostname, except when
|
// https://github.com/chrisaljoudi/uBlock/issues/1128
|
||||||
// the filter is specifically of type `other`.
|
// Do not block if the match begins after the hostname, except when
|
||||||
// https://github.com/gorhill/uBlock/issues/490
|
// the filter is specifically of type `other`.
|
||||||
// Removing this for the time being, will need a new, dedicated type.
|
// https://github.com/gorhill/uBlock/issues/490
|
||||||
if ( result.charAt(1) === 'b' ) {
|
// Removing this for the time being, will need a new, dedicated type.
|
||||||
result = toBlockDocResult(requestURL, requestHostname, result);
|
if (
|
||||||
|
result === 1 &&
|
||||||
|
toBlockDocResult(requestURL, requestHostname, logData) === false
|
||||||
|
) {
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,11 +272,11 @@ var onBeforeRootFrameRequest = function(details) {
|
||||||
pageStore.journalAddRequest(requestHostname, result);
|
pageStore.journalAddRequest(requestHostname, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( µb.logger.isEnabled() ) {
|
if ( logEnabled ) {
|
||||||
µb.logger.writeOne(
|
µb.logger.writeOne(
|
||||||
tabId,
|
tabId,
|
||||||
'net',
|
'net',
|
||||||
result,
|
logData,
|
||||||
'main_frame',
|
'main_frame',
|
||||||
requestURL,
|
requestURL,
|
||||||
requestHostname,
|
requestHostname,
|
||||||
|
@ -270,19 +285,19 @@ var onBeforeRootFrameRequest = function(details) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not blocked
|
// Not blocked
|
||||||
if ( µb.isAllowResult(result) ) {
|
if ( result !== 1 ) { return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var compiled = result.slice(3);
|
// No log data means no strict blocking (because we need to report why
|
||||||
|
// the blocking occurs.
|
||||||
|
if ( logData === undefined ) { return; }
|
||||||
|
|
||||||
// Blocked
|
// Blocked
|
||||||
var query = btoa(JSON.stringify({
|
var query = btoa(JSON.stringify({
|
||||||
url: requestURL,
|
url: requestURL,
|
||||||
hn: requestHostname,
|
hn: requestHostname,
|
||||||
dn: requestDomain,
|
dn: requestDomain,
|
||||||
fc: compiled,
|
fc: logData.compiled,
|
||||||
fs: snfe.filterStringFromCompiled(compiled)
|
fs: logData.raw
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vAPI.tabs.replace(tabId, vAPI.getURL('document-blocked.html?details=') + query);
|
vAPI.tabs.replace(tabId, vAPI.getURL('document-blocked.html?details=') + query);
|
||||||
|
@ -292,26 +307,23 @@ var onBeforeRootFrameRequest = function(details) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var toBlockDocResult = function(url, hostname, result) {
|
var toBlockDocResult = function(url, hostname, logData) {
|
||||||
// Make a regex out of the result
|
if ( typeof logData.regex !== 'string' ) { return; }
|
||||||
var re = µBlock.staticNetFilteringEngine
|
var re = new RegExp(logData.regex),
|
||||||
.filterRegexFromCompiled(result.slice(3), 'gi');
|
match = re.exec(url.toLowerCase());
|
||||||
if ( re === null ) {
|
if ( match === null ) { return ''; }
|
||||||
return '';
|
|
||||||
}
|
|
||||||
var matches = re.exec(url);
|
|
||||||
if ( matches === null ) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/1128
|
// https://github.com/chrisaljoudi/uBlock/issues/1128
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/1212
|
// https://github.com/chrisaljoudi/uBlock/issues/1212
|
||||||
// Relax the rule: verify that the match is completely before the path part
|
// Relax the rule: verify that the match is completely before the path part
|
||||||
if ( re.lastIndex <= url.indexOf(hostname) + hostname.length + 1 ) {
|
if (
|
||||||
return result;
|
(match.index + match.length) <=
|
||||||
|
(url.indexOf(hostname) + hostname.length + 1)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -410,18 +422,20 @@ var onHeadersReceived = function(details) {
|
||||||
// Turns out scripts must also be considered as potential embedded
|
// Turns out scripts must also be considered as potential embedded
|
||||||
// contexts (as workers) and as such we may need to inject content
|
// contexts (as workers) and as such we may need to inject content
|
||||||
// security policy directives.
|
// security policy directives.
|
||||||
if ( requestType === 'script' || requestType === 'main_frame' || requestType === 'sub_frame' ) {
|
if ( requestType === 'main_frame' || requestType === 'sub_frame' ) {
|
||||||
return processCSP(pageStore, details);
|
return injectCSP(pageStore, details);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var processCSP = function(pageStore, details) {
|
var injectCSP = function(pageStore, details) {
|
||||||
var µb = µBlock,
|
var µb = µBlock,
|
||||||
tabId = details.tabId,
|
tabId = details.tabId,
|
||||||
requestURL = details.url,
|
requestURL = details.url,
|
||||||
loggerEnabled = µb.logger.isEnabled();
|
loggerEnabled = µb.logger.isEnabled(),
|
||||||
|
logger = µb.logger,
|
||||||
|
cspSubsets = [];
|
||||||
|
|
||||||
var context = pageStore.createContextFromPage();
|
var context = pageStore.createContextFromPage();
|
||||||
context.requestHostname = µb.URI.hostnameFromURI(requestURL);
|
context.requestHostname = µb.URI.hostnameFromURI(requestURL);
|
||||||
|
@ -429,79 +443,125 @@ var processCSP = function(pageStore, details) {
|
||||||
context.pageHostname = context.pageDomain = context.requestHostname;
|
context.pageHostname = context.pageDomain = context.requestHostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
var inlineScriptResult, blockInlineScript,
|
// Start collecting policies >>>>>>>>
|
||||||
workerResult, blockWorker;
|
|
||||||
if ( details.type !== 'script' ) {
|
// ======== built-in policies
|
||||||
context.requestType = 'inline-script';
|
|
||||||
context.requestURL = requestURL;
|
context.requestType = 'inline-script';
|
||||||
inlineScriptResult = pageStore.filterRequestNoCache(context);
|
context.requestURL = requestURL;
|
||||||
blockInlineScript = µb.isBlockResult(inlineScriptResult);
|
if ( pageStore.filterRequestNoCache(context) === 1 ) {
|
||||||
// https://github.com/gorhill/uBlock/issues/2360
|
cspSubsets[0] = "script-src 'unsafe-eval' * blob: data:";
|
||||||
// https://github.com/gorhill/uBlock/issues/2440
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=669086
|
||||||
context.requestType = 'script';
|
// TODO: remove when most users are beyond Chromium v56
|
||||||
context.requestURL = 'blob:';
|
if ( vAPI.chromiumVersion < 57 ) {
|
||||||
µb.staticNetFilteringEngine.matchString(context);
|
cspSubsets[0] += '; frame-src *';
|
||||||
workerResult = µb.staticNetFilteringEngine.toResultString(loggerEnabled);
|
}
|
||||||
blockWorker = µb.isBlockResult(workerResult);
|
|
||||||
}
|
}
|
||||||
|
if ( loggerEnabled === true ) {
|
||||||
µb.staticNetFilteringEngine.matchStringExactType(context, requestURL, 'websocket');
|
logger.writeOne(
|
||||||
var websocketResult = µb.staticNetFilteringEngine.toResultString(loggerEnabled),
|
tabId,
|
||||||
blockWebsocket = µb.isBlockResult(websocketResult);
|
'net',
|
||||||
|
pageStore.logData,
|
||||||
var headersChanged;
|
'inline-script',
|
||||||
if ( blockInlineScript || blockWebsocket || blockWorker ) {
|
requestURL,
|
||||||
headersChanged = foilWithCSP(
|
context.rootHostname,
|
||||||
details.responseHeaders,
|
context.pageHostname
|
||||||
blockInlineScript,
|
|
||||||
blockWebsocket,
|
|
||||||
blockWorker
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( loggerEnabled && details.type !== 'script' ) {
|
// ======== filter-based policies
|
||||||
if ( blockInlineScript !== undefined ) {
|
|
||||||
µb.logger.writeOne(
|
// Static filtering.
|
||||||
tabId,
|
|
||||||
'net',
|
var logData = [];
|
||||||
inlineScriptResult,
|
|
||||||
'inline-script',
|
µb.staticNetFilteringEngine.matchAndFetchData(
|
||||||
requestURL,
|
'csp',
|
||||||
context.rootHostname,
|
requestURL,
|
||||||
context.pageHostname
|
cspSubsets,
|
||||||
);
|
loggerEnabled === true ? logData : undefined
|
||||||
}
|
);
|
||||||
if ( websocketResult ) {
|
|
||||||
µb.logger.writeOne(
|
// <<<<<<<< All policies have been collected
|
||||||
tabId,
|
|
||||||
'net',
|
|
||||||
websocketResult,
|
|
||||||
'websocket',
|
|
||||||
requestURL,
|
|
||||||
context.rootHostname,
|
|
||||||
context.pageHostname
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ( workerResult ) {
|
|
||||||
µb.logger.writeOne(
|
|
||||||
tabId,
|
|
||||||
'net',
|
|
||||||
workerResult,
|
|
||||||
'worker',
|
|
||||||
requestURL,
|
|
||||||
context.rootHostname,
|
|
||||||
context.pageHostname
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
context.dispose();
|
context.dispose();
|
||||||
|
|
||||||
if ( headersChanged !== true ) { return; }
|
// URL filtering `allow` rules override static filtering.
|
||||||
|
if (
|
||||||
|
cspSubsets.length !== 0 &&
|
||||||
|
µb.sessionURLFiltering.evaluateZ(context.rootHostname, requestURL, 'csp') === 2
|
||||||
|
) {
|
||||||
|
if ( loggerEnabled === true ) {
|
||||||
|
logger.writeOne(
|
||||||
|
tabId,
|
||||||
|
'net',
|
||||||
|
µb.sessionURLFiltering.toLogData(),
|
||||||
|
'csp',
|
||||||
|
requestURL,
|
||||||
|
context.rootHostname,
|
||||||
|
context.pageHostname
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dynamic filtering rules override static filtering.
|
||||||
|
if (
|
||||||
|
cspSubsets.length !== 0 &&
|
||||||
|
µb.userSettings.advancedUserEnabled &&
|
||||||
|
µb.sessionFirewall.evaluateCellZY(context.rootHostname, context.rootHostname, '*') === 2
|
||||||
|
) {
|
||||||
|
if ( loggerEnabled === true ) {
|
||||||
|
logger.writeOne(
|
||||||
|
tabId,
|
||||||
|
'net',
|
||||||
|
µb.sessionFirewall.toLogData(),
|
||||||
|
'csp',
|
||||||
|
requestURL,
|
||||||
|
context.rootHostname,
|
||||||
|
context.pageHostname
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static CSP policies will be applied.
|
||||||
|
var i = logData.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
logger.writeOne(
|
||||||
|
tabId,
|
||||||
|
'net',
|
||||||
|
logData[i],
|
||||||
|
'csp',
|
||||||
|
requestURL,
|
||||||
|
context.rootHostname,
|
||||||
|
context.pageHostname
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( cspSubsets.length === 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
µb.updateBadgeAsync(tabId);
|
µb.updateBadgeAsync(tabId);
|
||||||
|
|
||||||
return { 'responseHeaders': details.responseHeaders };
|
var csp, headers = details.responseHeaders;
|
||||||
|
i = headerIndexFromName('content-security-policy', headers);
|
||||||
|
if ( i !== -1 ) {
|
||||||
|
csp = headers[i].value.trim();
|
||||||
|
headers.splice(i, 1);
|
||||||
|
}
|
||||||
|
cspSubsets = cspSubsets.join(', ');
|
||||||
|
// Use comma to add a new subset to potentially existing one(s). This new
|
||||||
|
// subset has its own reporting options and won't cause spurious CSP
|
||||||
|
// reports to outside world.
|
||||||
|
// Ref.: https://www.w3.org/TR/CSP2/#implementation-considerations
|
||||||
|
headers.push({
|
||||||
|
name: 'Content-Security-Policy',
|
||||||
|
value: csp === undefined ? cspSubsets : csp + ', ' + cspSubsets
|
||||||
|
});
|
||||||
|
|
||||||
|
return { 'responseHeaders': headers };
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -518,13 +578,13 @@ var foilLargeMediaElement = function(pageStore, details) {
|
||||||
var tabId = details.tabId,
|
var tabId = details.tabId,
|
||||||
size = parseInt(details.responseHeaders[i].value, 10) || 0,
|
size = parseInt(details.responseHeaders[i].value, 10) || 0,
|
||||||
result = pageStore.filterLargeMediaElement(size);
|
result = pageStore.filterLargeMediaElement(size);
|
||||||
if ( result === undefined ) { return; }
|
if ( result === 0 ) { return; }
|
||||||
|
|
||||||
if ( µb.logger.isEnabled() ) {
|
if ( µb.logger.isEnabled() ) {
|
||||||
µb.logger.writeOne(
|
µb.logger.writeOne(
|
||||||
tabId,
|
tabId,
|
||||||
'net',
|
'net',
|
||||||
result,
|
pageStore.logData,
|
||||||
details.type,
|
details.type,
|
||||||
details.url,
|
details.url,
|
||||||
pageStore.tabHostname,
|
pageStore.tabHostname,
|
||||||
|
@ -537,57 +597,6 @@ var foilLargeMediaElement = function(pageStore, details) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var foilWithCSP = function(headers, noInlineScript, noWebsocket, noBlobWorker) {
|
|
||||||
var i = headerIndexFromName('content-security-policy', headers),
|
|
||||||
cspSubset = [];
|
|
||||||
|
|
||||||
if ( noInlineScript ) {
|
|
||||||
cspSubset.push("script-src 'unsafe-eval' *");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( noWebsocket ) {
|
|
||||||
cspSubset.push('connect-src http: https:');
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://www.w3.org/TR/CSP2/#directive-child-src
|
|
||||||
// https://www.w3.org/TR/CSP3/#directive-worker-src
|
|
||||||
if ( noBlobWorker ) {
|
|
||||||
cspSubset.push('child-src http: https:');
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=513860
|
|
||||||
// Bad Chromium bug: web pages can work around CSP directives by
|
|
||||||
// creating data:- or blob:-based URI. So if we must restrict using CSP,
|
|
||||||
// we have no choice but to also prevent the creation of nested browsing
|
|
||||||
// contexts based on data:- or blob:-based URIs.
|
|
||||||
if ( vAPI.chrome && (noInlineScript || noWebsocket) ) {
|
|
||||||
// https://w3c.github.io/webappsec-csp/#directive-frame-src
|
|
||||||
cspSubset.push('frame-src http: https:');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( cspSubset.length === 0 ) { return; }
|
|
||||||
|
|
||||||
var csp;
|
|
||||||
if ( i !== -1 ) {
|
|
||||||
csp = headers[i].value.trim();
|
|
||||||
headers.splice(i, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use comma to add a new subset to potentially existing one(s). This new
|
|
||||||
// subset has its own reporting options and won't cause spurious CSP
|
|
||||||
// reports to outside world.
|
|
||||||
// Ref.: https://www.w3.org/TR/CSP2/#implementation-considerations
|
|
||||||
cspSubset = cspSubset.join('; ');
|
|
||||||
headers.push({
|
|
||||||
name: 'Content-Security-Policy',
|
|
||||||
value: csp === undefined ? cspSubset : csp + ', ' + cspSubset
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// Caller must ensure headerName is normalized to lower case.
|
// Caller must ensure headerName is normalized to lower case.
|
||||||
|
|
||||||
var headerIndexFromName = function(headerName, headers) {
|
var headerIndexFromName = function(headerName, headers) {
|
||||||
|
@ -620,8 +629,7 @@ vAPI.net.onHeadersReceived = {
|
||||||
'main_frame',
|
'main_frame',
|
||||||
'sub_frame',
|
'sub_frame',
|
||||||
'image',
|
'image',
|
||||||
'media',
|
'media'
|
||||||
'script'
|
|
||||||
],
|
],
|
||||||
extra: [ 'blocking', 'responseHeaders' ],
|
extra: [ 'blocking', 'responseHeaders' ],
|
||||||
callback: onHeadersReceived
|
callback: onHeadersReceived
|
||||||
|
@ -629,8 +637,6 @@ vAPI.net.onHeadersReceived = {
|
||||||
|
|
||||||
vAPI.net.registerListeners();
|
vAPI.net.registerListeners();
|
||||||
|
|
||||||
//console.log('traffic.js > Beginning to intercept net requests at %s', (new Date()).toISOString());
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var isTemporarilyWhitelisted = function(result, hostname) {
|
var isTemporarilyWhitelisted = function(result, hostname) {
|
||||||
|
@ -640,17 +646,15 @@ var isTemporarilyWhitelisted = function(result, hostname) {
|
||||||
obsolete = documentWhitelists[hostname];
|
obsolete = documentWhitelists[hostname];
|
||||||
if ( obsolete !== undefined ) {
|
if ( obsolete !== undefined ) {
|
||||||
if ( obsolete > Date.now() ) {
|
if ( obsolete > Date.now() ) {
|
||||||
if ( result === '' ) {
|
if ( result === 0 ) {
|
||||||
return 'ua:*' + ' ' + hostname + ' doc allow';
|
return 2;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
delete documentWhitelists[hostname];
|
delete documentWhitelists[hostname];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pos = hostname.indexOf('.');
|
pos = hostname.indexOf('.');
|
||||||
if ( pos === -1 ) {
|
if ( pos === -1 ) { break; }
|
||||||
break;
|
|
||||||
}
|
|
||||||
hostname = hostname.slice(pos + 1);
|
hostname = hostname.slice(pos + 1);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -210,7 +210,7 @@ URLNetFiltering.prototype.removeRule = function(srcHostname, url, type) {
|
||||||
URLNetFiltering.prototype.evaluateZ = function(context, target, type) {
|
URLNetFiltering.prototype.evaluateZ = function(context, target, type) {
|
||||||
this.r = 0;
|
this.r = 0;
|
||||||
if ( this.rules.size === 0 ) {
|
if ( this.rules.size === 0 ) {
|
||||||
return this;
|
return 0;
|
||||||
}
|
}
|
||||||
var entries, pos, i, entry;
|
var entries, pos, i, entry;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -222,7 +222,7 @@ URLNetFiltering.prototype.evaluateZ = function(context, target, type) {
|
||||||
this.url = entry.url;
|
this.url = entry.url;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.r = entry.action;
|
this.r = entry.action;
|
||||||
return this;
|
return this.r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( (entries = this.rules.get(context + ' *')) ) {
|
if ( (entries = this.rules.get(context + ' *')) ) {
|
||||||
|
@ -232,14 +232,20 @@ URLNetFiltering.prototype.evaluateZ = function(context, target, type) {
|
||||||
this.url = entry.url;
|
this.url = entry.url;
|
||||||
this.type = '*';
|
this.type = '*';
|
||||||
this.r = entry.action;
|
this.r = entry.action;
|
||||||
return this;
|
return this.r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( context === '*' ) { break; }
|
if ( context === '*' ) { break; }
|
||||||
pos = context.indexOf('.');
|
pos = context.indexOf('.');
|
||||||
context = pos !== -1 ? context.slice(pos + 1) : '*';
|
context = pos !== -1 ? context.slice(pos + 1) : '*';
|
||||||
}
|
}
|
||||||
return this;
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
URLNetFiltering.prototype.mustAllowCellZ = function(context, target, type) {
|
||||||
|
return this.evaluateZ(context, target, type).r === 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -250,21 +256,30 @@ URLNetFiltering.prototype.mustBlockOrAllow = function() {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
URLNetFiltering.prototype.toFilterString = function() {
|
URLNetFiltering.prototype.toLogData = function() {
|
||||||
if ( this.r === 0 ) {
|
if ( this.r === 0 ) { return; }
|
||||||
return '';
|
return {
|
||||||
}
|
source: 'dynamicUrl',
|
||||||
var body = this.context + ' ' + this.url + ' ' + this.type;
|
result: this.r,
|
||||||
if ( this.r === 1 ) {
|
rule: [
|
||||||
return 'lb:' + body + ' block';
|
this.context,
|
||||||
}
|
this.url,
|
||||||
if ( this.r === 2 ) {
|
this.type,
|
||||||
return 'la:' + body + ' allow';
|
this.intToActionMap.get(this.r)
|
||||||
}
|
],
|
||||||
/* this.r === 3 */
|
raw: this.context + ' ' +
|
||||||
return 'ln:' + body + ' noop';
|
this.url + ' ' +
|
||||||
|
this.type + ' ' +
|
||||||
|
this.intToActionMap.get(this.r)
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
URLNetFiltering.prototype.intToActionMap = new Map([
|
||||||
|
[ 1, ' block' ],
|
||||||
|
[ 2, ' allow' ],
|
||||||
|
[ 3, ' noop' ]
|
||||||
|
]);
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
URLNetFiltering.prototype.copyRules = function(other, context, urls, type) {
|
URLNetFiltering.prototype.copyRules = function(other, context, urls, type) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
uBlock Origin - a browser extension to block requests.
|
uBlock Origin - a browser extension to block requests.
|
||||||
Copyright (C) 2014-2016 Raymond Hill
|
Copyright (C) 2014-2017 Raymond Hill
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -150,7 +150,10 @@
|
||||||
this.offset = offset || 0;
|
this.offset = offset || 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
µBlock.LineIterator.prototype.next = function() {
|
µBlock.LineIterator.prototype.next = function(offset) {
|
||||||
|
if ( offset !== undefined ) {
|
||||||
|
this.offset += offset;
|
||||||
|
}
|
||||||
var lineEnd = this.text.indexOf('\n', this.offset);
|
var lineEnd = this.text.indexOf('\n', this.offset);
|
||||||
if ( lineEnd === -1 ) {
|
if ( lineEnd === -1 ) {
|
||||||
lineEnd = this.text.indexOf('\r', this.offset);
|
lineEnd = this.text.indexOf('\r', this.offset);
|
||||||
|
@ -163,18 +166,8 @@
|
||||||
return line;
|
return line;
|
||||||
};
|
};
|
||||||
|
|
||||||
µBlock.LineIterator.prototype.rewind = function() {
|
µBlock.LineIterator.prototype.charCodeAt = function(offset) {
|
||||||
if ( this.offset <= 1 ) {
|
return this.text.charCodeAt(this.offset + offset);
|
||||||
this.offset = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var lineEnd = this.text.lastIndexOf('\n', this.offset - 2);
|
|
||||||
if ( lineEnd !== -1 ) {
|
|
||||||
this.offset = lineEnd + 1;
|
|
||||||
} else {
|
|
||||||
lineEnd = this.text.lastIndexOf('\r', this.offset - 2);
|
|
||||||
this.offset = lineEnd !== -1 ? lineEnd + 1 : 0;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
µBlock.LineIterator.prototype.eot = function() {
|
µBlock.LineIterator.prototype.eot = function() {
|
||||||
|
@ -209,6 +202,59 @@
|
||||||
return field;
|
return field;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
µBlock.FieldIterator.prototype.remainder = function() {
|
||||||
|
return this.text.slice(this.offset);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
µBlock.CompiledOutput = function() {
|
||||||
|
this.bufferLen = 8192;
|
||||||
|
this.buffer = new Uint8Array(this.bufferLen);
|
||||||
|
this.offset = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
µBlock.CompiledOutput.prototype.push = function(lineBits, line) {
|
||||||
|
var lineLen = line.length,
|
||||||
|
offset = this.offset,
|
||||||
|
need = offset + 2 + lineLen; // lineBits, line, \n
|
||||||
|
if ( need > this.bufferLen ) {
|
||||||
|
this.grow(need);
|
||||||
|
}
|
||||||
|
var buffer = this.buffer;
|
||||||
|
if ( offset !== 0 ) {
|
||||||
|
buffer[offset++] = 0x0A /* '\n' */;
|
||||||
|
}
|
||||||
|
buffer[offset++] = 0x61 /* 'a' */ + lineBits;
|
||||||
|
for ( var i = 0, c; i < lineLen; i++ ) {
|
||||||
|
c = line.charCodeAt(i);
|
||||||
|
if ( c > 0x7F ) {
|
||||||
|
return this.push(lineBits | 0x02, encodeURIComponent(line));
|
||||||
|
}
|
||||||
|
buffer[offset++] = c;
|
||||||
|
}
|
||||||
|
this.offset = offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
µBlock.CompiledOutput.prototype.grow = function(need) {
|
||||||
|
var newBufferLen = Math.min(
|
||||||
|
2097152,
|
||||||
|
1 << Math.ceil(Math.log(need) / Math.log(2))
|
||||||
|
);
|
||||||
|
while ( newBufferLen < need ) {
|
||||||
|
newBufferLen += 1048576;
|
||||||
|
}
|
||||||
|
var newBuffer = new Uint8Array(newBufferLen);
|
||||||
|
newBuffer.set(this.buffer);
|
||||||
|
this.buffer = newBuffer;
|
||||||
|
this.bufferLen = newBufferLen;
|
||||||
|
};
|
||||||
|
|
||||||
|
µBlock.CompiledOutput.prototype.toString = function() {
|
||||||
|
var decoder = new TextDecoder();
|
||||||
|
return decoder.decode(new Uint8Array(this.buffer.buffer, 0, this.offset));
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.mapToArray = typeof Array.from === 'function'
|
µBlock.mapToArray = typeof Array.from === 'function'
|
||||||
|
|
Loading…
Reference in a new issue