mirror of
https://github.com/gorhill/uBlock.git
synced 2024-09-18 17:02:27 +02:00
this addresses #184
This commit is contained in:
parent
70533b93fe
commit
65775a5e27
@ -380,7 +380,7 @@ var reloadAll = function(update) {
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var buttonApplyHandler = function() {
|
var buttonApplyHandler = function() {
|
||||||
reloadAll();
|
reloadAll(false);
|
||||||
uDom('#buttonApply').toggleClass('enabled', false);
|
uDom('#buttonApply').toggleClass('enabled', false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.abpFilters = (function(){
|
µBlock.netFilteringEngine = (function(){
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
@ -137,6 +137,19 @@ var histogram = function(label, categories) {
|
|||||||
console.log('\tTotal buckets count: %d', total);
|
console.log('\tTotal buckets count: %d', total);
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// Could be replaced with encodeURIComponent/decodeURIComponent,
|
||||||
|
// which seems faster on Firefox.
|
||||||
|
var encode = JSON.stringify;
|
||||||
|
var decode = JSON.parse;
|
||||||
|
|
||||||
|
var cachedParseInt = parseInt;
|
||||||
|
|
||||||
|
var atoi = function(s) {
|
||||||
|
return cachedParseInt(s, 10);
|
||||||
|
};
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Filters family tree:
|
Filters family tree:
|
||||||
@ -187,10 +200,22 @@ FilterPlain.prototype.match = function(url, tokenBeg) {
|
|||||||
return url.substr(tokenBeg - this.tokenBeg, this.s.length) === this.s;
|
return url.substr(tokenBeg - this.tokenBeg, this.s.length) === this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlain.prototype.fid = 'a';
|
||||||
|
|
||||||
FilterPlain.prototype.toString = function() {
|
FilterPlain.prototype.toString = function() {
|
||||||
return this.s;
|
return this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlain.prototype.toSelfie = function() {
|
||||||
|
return this.s + '\t' +
|
||||||
|
this.tokenBeg;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterPlain.fromSelfie = function(s) {
|
||||||
|
var pos = s.indexOf('\t');
|
||||||
|
return new FilterPlain(s.slice(0, pos), atoi(s.slice(pos + 1)));
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterPlainHostname = function(s, tokenBeg, hostname) {
|
var FilterPlainHostname = function(s, tokenBeg, hostname) {
|
||||||
@ -204,10 +229,23 @@ FilterPlainHostname.prototype.match = function(url, tokenBeg) {
|
|||||||
url.substr(tokenBeg - this.tokenBeg, this.s.length) === this.s;
|
url.substr(tokenBeg - this.tokenBeg, this.s.length) === this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainHostname.prototype.fid = 'ah';
|
||||||
|
|
||||||
FilterPlainHostname.prototype.toString = function() {
|
FilterPlainHostname.prototype.toString = function() {
|
||||||
return this.s + '$domain=' + this.hostname;
|
return this.s + '$domain=' + this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainHostname.prototype.toSelfie = function() {
|
||||||
|
return this.s + '\t' +
|
||||||
|
this.tokenBeg + '\t' +
|
||||||
|
this.hostname;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterPlainHostname.fromSelfie = function(s) {
|
||||||
|
var args = s.split('\t');
|
||||||
|
return new FilterPlainHostname(args[0], atoi(args[1]), args[2]);
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterPlainPrefix0 = function(s) {
|
var FilterPlainPrefix0 = function(s) {
|
||||||
@ -218,10 +256,20 @@ FilterPlainPrefix0.prototype.match = function(url, tokenBeg) {
|
|||||||
return url.substr(tokenBeg, this.s.length) === this.s;
|
return url.substr(tokenBeg, this.s.length) === this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainPrefix0.prototype.fid = '0a';
|
||||||
|
|
||||||
FilterPlainPrefix0.prototype.toString = function() {
|
FilterPlainPrefix0.prototype.toString = function() {
|
||||||
return this.s;
|
return this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainPrefix0.prototype.toSelfie = function() {
|
||||||
|
return this.s;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterPlainPrefix0.fromSelfie = function(s) {
|
||||||
|
return new FilterPlainPrefix0(s);
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterPlainPrefix0Hostname = function(s, hostname) {
|
var FilterPlainPrefix0Hostname = function(s, hostname) {
|
||||||
@ -234,10 +282,22 @@ FilterPlainPrefix0Hostname.prototype.match = function(url, tokenBeg) {
|
|||||||
url.substr(tokenBeg, this.s.length) === this.s;
|
url.substr(tokenBeg, this.s.length) === this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainPrefix0Hostname.prototype.fid = '0ah';
|
||||||
|
|
||||||
FilterPlainPrefix0Hostname.prototype.toString = function() {
|
FilterPlainPrefix0Hostname.prototype.toString = function() {
|
||||||
return this.s + '$domain=' + this.hostname;
|
return this.s + '$domain=' + this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainPrefix0Hostname.prototype.toSelfie = function() {
|
||||||
|
return this.s + '\t' +
|
||||||
|
this.hostname;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterPlainPrefix0Hostname.fromSelfie = function(s) {
|
||||||
|
var pos = s.indexOf('\t');
|
||||||
|
return new FilterPlainPrefix0Hostname(s.slice(0, pos), s.slice(pos + 1));
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterPlainPrefix1 = function(s) {
|
var FilterPlainPrefix1 = function(s) {
|
||||||
@ -248,10 +308,20 @@ FilterPlainPrefix1.prototype.match = function(url, tokenBeg) {
|
|||||||
return url.substr(tokenBeg - 1, this.s.length) === this.s;
|
return url.substr(tokenBeg - 1, this.s.length) === this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainPrefix1.prototype.fid = '1a';
|
||||||
|
|
||||||
FilterPlainPrefix1.prototype.toString = function() {
|
FilterPlainPrefix1.prototype.toString = function() {
|
||||||
return this.s;
|
return this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainPrefix1.prototype.toSelfie = function() {
|
||||||
|
return this.s;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterPlainPrefix1.fromSelfie = function(s) {
|
||||||
|
return new FilterPlainPrefix1(s);
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterPlainPrefix1Hostname = function(s, hostname) {
|
var FilterPlainPrefix1Hostname = function(s, hostname) {
|
||||||
@ -264,10 +334,22 @@ FilterPlainPrefix1Hostname.prototype.match = function(url, tokenBeg) {
|
|||||||
url.substr(tokenBeg - 1, this.s.length) === this.s;
|
url.substr(tokenBeg - 1, this.s.length) === this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainPrefix1Hostname.prototype.fid = '1ah';
|
||||||
|
|
||||||
FilterPlainPrefix1Hostname.prototype.toString = function() {
|
FilterPlainPrefix1Hostname.prototype.toString = function() {
|
||||||
return this.s + '$domain=' + this.hostname;
|
return this.s + '$domain=' + this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainPrefix1Hostname.prototype.toSelfie = function() {
|
||||||
|
return this.s + '\t' +
|
||||||
|
this.hostname;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterPlainPrefix1Hostname.fromSelfie = function(s) {
|
||||||
|
var pos = s.indexOf('\t');
|
||||||
|
return new FilterPlainPrefix1Hostname(s.slice(0, pos), s.slice(pos + 1));
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterPlainLeftAnchored = function(s) {
|
var FilterPlainLeftAnchored = function(s) {
|
||||||
@ -278,10 +360,20 @@ FilterPlainLeftAnchored.prototype.match = function(url) {
|
|||||||
return url.slice(0, this.s.length) === this.s;
|
return url.slice(0, this.s.length) === this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainLeftAnchored.prototype.fid = '|a';
|
||||||
|
|
||||||
FilterPlainLeftAnchored.prototype.toString = function() {
|
FilterPlainLeftAnchored.prototype.toString = function() {
|
||||||
return '|' + this.s;
|
return '|' + this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainLeftAnchored.prototype.toSelfie = function() {
|
||||||
|
return this.s;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterPlainLeftAnchored.fromSelfie = function(s) {
|
||||||
|
return new FilterPlainLeftAnchored(s);
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterPlainLeftAnchoredHostname = function(s, hostname) {
|
var FilterPlainLeftAnchoredHostname = function(s, hostname) {
|
||||||
@ -294,10 +386,22 @@ FilterPlainLeftAnchoredHostname.prototype.match = function(url) {
|
|||||||
url.slice(0, this.s.length) === this.s;
|
url.slice(0, this.s.length) === this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainLeftAnchoredHostname.prototype.fid = '|ah';
|
||||||
|
|
||||||
FilterPlainLeftAnchoredHostname.prototype.toString = function() {
|
FilterPlainLeftAnchoredHostname.prototype.toString = function() {
|
||||||
return '|' + this.s + '$domain=' + this.hostname;
|
return '|' + this.s + '$domain=' + this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainLeftAnchoredHostname.prototype.toSelfie = function() {
|
||||||
|
return this.s + '\t' +
|
||||||
|
this.hostname;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterPlainLeftAnchoredHostname.fromSelfie = function(s) {
|
||||||
|
var pos = s.indexOf('\t');
|
||||||
|
return new FilterPlainLeftAnchoredHostname(s.slice(0, pos), s.slice(pos + 1));
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterPlainRightAnchored = function(s) {
|
var FilterPlainRightAnchored = function(s) {
|
||||||
@ -308,10 +412,20 @@ FilterPlainRightAnchored.prototype.match = function(url) {
|
|||||||
return url.slice(-this.s.length) === this.s;
|
return url.slice(-this.s.length) === this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainRightAnchored.prototype.fid = 'a|';
|
||||||
|
|
||||||
FilterPlainRightAnchored.prototype.toString = function() {
|
FilterPlainRightAnchored.prototype.toString = function() {
|
||||||
return this.s + '|';
|
return this.s + '|';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainRightAnchored.prototype.toSelfie = function() {
|
||||||
|
return this.s;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterPlainRightAnchored.fromSelfie = function(s) {
|
||||||
|
return new FilterPlainRightAnchored(s);
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterPlainRightAnchoredHostname = function(s, hostname) {
|
var FilterPlainRightAnchoredHostname = function(s, hostname) {
|
||||||
@ -324,10 +438,22 @@ FilterPlainRightAnchoredHostname.prototype.match = function(url) {
|
|||||||
url.slice(-this.s.length) === this.s;
|
url.slice(-this.s.length) === this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainRightAnchoredHostname.prototype.fid = 'a|h';
|
||||||
|
|
||||||
FilterPlainRightAnchoredHostname.prototype.toString = function() {
|
FilterPlainRightAnchoredHostname.prototype.toString = function() {
|
||||||
return this.s + '|$domain=' + this.hostname;
|
return this.s + '|$domain=' + this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainRightAnchoredHostname.prototype.toSelfie = function() {
|
||||||
|
return this.s + '\t' +
|
||||||
|
this.hostname;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterPlainRightAnchoredHostname.fromSelfie = function(s) {
|
||||||
|
var pos = s.indexOf('\t');
|
||||||
|
return new FilterPlainRightAnchoredHostname(s.slice(0, pos), s.slice(pos + 1));
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// With a single wildcard, regex is not optimal.
|
// With a single wildcard, regex is not optimal.
|
||||||
@ -335,11 +461,10 @@ FilterPlainRightAnchoredHostname.prototype.toString = function() {
|
|||||||
// http://jsperf.com/regexp-vs-indexof-abp-miss/3
|
// http://jsperf.com/regexp-vs-indexof-abp-miss/3
|
||||||
// http://jsperf.com/regexp-vs-indexof-abp-hit/3
|
// http://jsperf.com/regexp-vs-indexof-abp-hit/3
|
||||||
|
|
||||||
var FilterSingleWildcard = function(s, tokenBeg) {
|
var FilterSingleWildcard = function(lSegment, rSegment, tokenBeg) {
|
||||||
this.tokenBeg = tokenBeg;
|
this.tokenBeg = tokenBeg;
|
||||||
var wcOffset = s.indexOf('*');
|
this.lSegment = lSegment;
|
||||||
this.lSegment = s.slice(0, wcOffset);
|
this.rSegment = rSegment;
|
||||||
this.rSegment = s.slice(wcOffset + 1);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterSingleWildcard.prototype.match = function(url, tokenBeg) {
|
FilterSingleWildcard.prototype.match = function(url, tokenBeg) {
|
||||||
@ -348,17 +473,29 @@ FilterSingleWildcard.prototype.match = function(url, tokenBeg) {
|
|||||||
url.indexOf(this.rSegment, tokenBeg + this.lSegment.length) > 0;
|
url.indexOf(this.rSegment, tokenBeg + this.lSegment.length) > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcard.prototype.fid = '*';
|
||||||
|
|
||||||
FilterSingleWildcard.prototype.toString = function() {
|
FilterSingleWildcard.prototype.toString = function() {
|
||||||
return this.lSegment + '*' + this.rSegment;
|
return this.lSegment + '*' + this.rSegment;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcard.prototype.toSelfie = function() {
|
||||||
|
return this.lSegment + '\t' +
|
||||||
|
this.rSegment + '\t' +
|
||||||
|
this.tokenBeg;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcard.fromSelfie = function(s) {
|
||||||
|
var args = s.split('\t');
|
||||||
|
return new FilterSingleWildcard(args[0], args[1], atoi(args[2]));
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterSingleWildcardHostname = function(s, tokenBeg, hostname) {
|
var FilterSingleWildcardHostname = function(lSegment, rSegment, tokenBeg, hostname) {
|
||||||
this.tokenBeg = tokenBeg;
|
this.tokenBeg = tokenBeg;
|
||||||
var wcOffset = s.indexOf('*');
|
this.lSegment = lSegment;
|
||||||
this.lSegment = s.slice(0, wcOffset);
|
this.rSegment = rSegment;
|
||||||
this.rSegment = s.slice(wcOffset + 1);
|
|
||||||
this.hostname = hostname;
|
this.hostname = hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -369,16 +506,29 @@ FilterSingleWildcardHostname.prototype.match = function(url, tokenBeg) {
|
|||||||
url.indexOf(this.rSegment, tokenBeg + this.lSegment.length) > 0;
|
url.indexOf(this.rSegment, tokenBeg + this.lSegment.length) > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardHostname.prototype.fid = '*h';
|
||||||
|
|
||||||
FilterSingleWildcardHostname.prototype.toString = function() {
|
FilterSingleWildcardHostname.prototype.toString = function() {
|
||||||
return this.lSegment + '*' + this.rSegment + '$domain=' + this.hostname;
|
return this.lSegment + '*' + this.rSegment + '$domain=' + this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardHostname.prototype.toSelfie = function() {
|
||||||
|
return this.lSegment + '\t' +
|
||||||
|
this.rSegment + '\t' +
|
||||||
|
this.tokenBeg + '\t' +
|
||||||
|
this.hostname;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardHostname.fromSelfie = function(s) {
|
||||||
|
var args = s.split('\t');
|
||||||
|
return new FilterSingleWildcardHostname(args[0], args[1], atoi(args[2]), args[3]);
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterSingleWildcardPrefix0 = function(s) {
|
var FilterSingleWildcardPrefix0 = function(lSegment, rSegment) {
|
||||||
var wcOffset = s.indexOf('*');
|
this.lSegment = lSegment;
|
||||||
this.lSegment = s.slice(0, wcOffset);
|
this.rSegment = rSegment;
|
||||||
this.rSegment = s.slice(wcOffset + 1);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterSingleWildcardPrefix0.prototype.match = function(url, tokenBeg) {
|
FilterSingleWildcardPrefix0.prototype.match = function(url, tokenBeg) {
|
||||||
@ -386,16 +536,27 @@ FilterSingleWildcardPrefix0.prototype.match = function(url, tokenBeg) {
|
|||||||
url.indexOf(this.rSegment, tokenBeg + this.lSegment.length) > 0;
|
url.indexOf(this.rSegment, tokenBeg + this.lSegment.length) > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardPrefix0.prototype.fid = '0*';
|
||||||
|
|
||||||
FilterSingleWildcardPrefix0.prototype.toString = function() {
|
FilterSingleWildcardPrefix0.prototype.toString = function() {
|
||||||
return this.lSegment + '*' + this.rSegment;
|
return this.lSegment + '*' + this.rSegment;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardPrefix0.prototype.toSelfie = function() {
|
||||||
|
return this.lSegment + '\t' +
|
||||||
|
this.rSegment;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardPrefix0.fromSelfie = function(s) {
|
||||||
|
var pos = s.indexOf('\t');
|
||||||
|
return new FilterSingleWildcardPrefix0(s.slice(0, pos), s.slice(pos + 1));
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterSingleWildcardPrefix0Hostname = function(s, hostname) {
|
var FilterSingleWildcardPrefix0Hostname = function(lSegment, rSegment, hostname) {
|
||||||
var wcOffset = s.indexOf('*');
|
this.lSegment = lSegment;
|
||||||
this.lSegment = s.slice(0, wcOffset);
|
this.rSegment = rSegment;
|
||||||
this.rSegment = s.slice(wcOffset + 1);
|
|
||||||
this.hostname = hostname;
|
this.hostname = hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -405,21 +566,28 @@ FilterSingleWildcardPrefix0Hostname.prototype.match = function(url, tokenBeg) {
|
|||||||
url.indexOf(this.rSegment, tokenBeg + this.lSegment.length) > 0;
|
url.indexOf(this.rSegment, tokenBeg + this.lSegment.length) > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardPrefix0Hostname.prototype.fid = '0*h';
|
||||||
|
|
||||||
FilterSingleWildcardPrefix0Hostname.prototype.toString = function() {
|
FilterSingleWildcardPrefix0Hostname.prototype.toString = function() {
|
||||||
return this.lSegment + '*' + this.rSegment + '$domain=' + this.hostname;
|
return this.lSegment + '*' + this.rSegment + '$domain=' + this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardPrefix0Hostname.prototype.toSelfie = function() {
|
||||||
|
return this.lSegment + '\t' +
|
||||||
|
this.rSegment + '\t' +
|
||||||
|
this.hostname;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardPrefix0Hostname.fromSelfie = function(s) {
|
||||||
|
var args = s.split('\t');
|
||||||
|
return new FilterSingleWildcardPrefix0Hostname(args[0], args[1], args[2]);
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// With a single wildcard, regex is not optimal.
|
var FilterSingleWildcardLeftAnchored = function(lSegment, rSegment) {
|
||||||
// See:
|
this.lSegment = lSegment;
|
||||||
// http://jsperf.com/regexp-vs-indexof-abp-miss/3
|
this.rSegment = rSegment;
|
||||||
// http://jsperf.com/regexp-vs-indexof-abp-hit/3
|
|
||||||
|
|
||||||
var FilterSingleWildcardLeftAnchored = function(s) {
|
|
||||||
var wcOffset = s.indexOf('*');
|
|
||||||
this.lSegment = s.slice(0, wcOffset);
|
|
||||||
this.rSegment = s.slice(wcOffset + 1);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterSingleWildcardLeftAnchored.prototype.match = function(url) {
|
FilterSingleWildcardLeftAnchored.prototype.match = function(url) {
|
||||||
@ -427,16 +595,27 @@ FilterSingleWildcardLeftAnchored.prototype.match = function(url) {
|
|||||||
url.indexOf(this.rSegment, this.lSegment.length) > 0;
|
url.indexOf(this.rSegment, this.lSegment.length) > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardLeftAnchored.prototype.fid = '|*';
|
||||||
|
|
||||||
FilterSingleWildcardLeftAnchored.prototype.toString = function() {
|
FilterSingleWildcardLeftAnchored.prototype.toString = function() {
|
||||||
return '|' + this.lSegment + '*' + this.rSegment;
|
return '|' + this.lSegment + '*' + this.rSegment;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardLeftAnchored.prototype.toSelfie = function() {
|
||||||
|
return this.lSegment + '\t' +
|
||||||
|
this.rSegment;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardLeftAnchored.fromSelfie = function(s) {
|
||||||
|
var pos = s.indexOf('\t');
|
||||||
|
return new FilterSingleWildcardLeftAnchored(s.slice(0, pos), s.slice(pos + 1));
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterSingleWildcardLeftAnchoredHostname = function(s, hostname) {
|
var FilterSingleWildcardLeftAnchoredHostname = function(lSegment, rSegment, hostname) {
|
||||||
var wcOffset = s.indexOf('*');
|
this.lSegment = lSegment;
|
||||||
this.lSegment = s.slice(0, wcOffset);
|
this.rSegment = rSegment;
|
||||||
this.rSegment = s.slice(wcOffset + 1);
|
|
||||||
this.hostname = hostname;
|
this.hostname = hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -446,21 +625,28 @@ FilterSingleWildcardLeftAnchoredHostname.prototype.match = function(url) {
|
|||||||
url.indexOf(this.rSegment, this.lSegment.length) > 0;
|
url.indexOf(this.rSegment, this.lSegment.length) > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardLeftAnchoredHostname.prototype.fid = '|*h';
|
||||||
|
|
||||||
FilterSingleWildcardLeftAnchoredHostname.prototype.toString = function() {
|
FilterSingleWildcardLeftAnchoredHostname.prototype.toString = function() {
|
||||||
return '|' + this.lSegment + '*' + this.rSegment + '$domain=' + this.hostname;
|
return '|' + this.lSegment + '*' + this.rSegment + '$domain=' + this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardLeftAnchoredHostname.prototype.toSelfie = function() {
|
||||||
|
return this.lSegment + '\t' +
|
||||||
|
this.rSegment + '\t' +
|
||||||
|
this.hostname;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardLeftAnchoredHostname.fromSelfie = function(s) {
|
||||||
|
var args = s.split('\t');
|
||||||
|
return new FilterSingleWildcardLeftAnchoredHostname(args[0], args[1], args[2]);
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// With a single wildcard, regex is not optimal.
|
var FilterSingleWildcardRightAnchored = function(lSegment, rSegment) {
|
||||||
// See:
|
this.lSegment = lSegment;
|
||||||
// http://jsperf.com/regexp-vs-indexof-abp-miss/3
|
this.rSegment = rSegment;
|
||||||
// http://jsperf.com/regexp-vs-indexof-abp-hit/3
|
|
||||||
|
|
||||||
var FilterSingleWildcardRightAnchored = function(s) {
|
|
||||||
var wcOffset = s.indexOf('*');
|
|
||||||
this.lSegment = s.slice(0, wcOffset);
|
|
||||||
this.rSegment = s.slice(wcOffset + 1);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterSingleWildcardRightAnchored.prototype.match = function(url) {
|
FilterSingleWildcardRightAnchored.prototype.match = function(url) {
|
||||||
@ -468,16 +654,27 @@ FilterSingleWildcardRightAnchored.prototype.match = function(url) {
|
|||||||
url.lastIndexOf(this.lSegment, url.length - this.rSegment.length - this.lSegment.length) >= 0;
|
url.lastIndexOf(this.lSegment, url.length - this.rSegment.length - this.lSegment.length) >= 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardRightAnchored.prototype.fid = '*|';
|
||||||
|
|
||||||
FilterSingleWildcardRightAnchored.prototype.toString = function() {
|
FilterSingleWildcardRightAnchored.prototype.toString = function() {
|
||||||
return this.lSegment + '*' + this.rSegment + '|';
|
return this.lSegment + '*' + this.rSegment + '|';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardRightAnchored.prototype.toSelfie = function() {
|
||||||
|
return this.lSegment + '\t' +
|
||||||
|
this.rSegment;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardRightAnchored.fromSelfie = function(s) {
|
||||||
|
var pos = s.indexOf('\t');
|
||||||
|
return new FilterSingleWildcardRightAnchored(s.slice(0, pos), s.slice(pos + 1));
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterSingleWildcardRightAnchoredHostname = function(s, hostname) {
|
var FilterSingleWildcardRightAnchoredHostname = function(lSegment, rSegment, hostname) {
|
||||||
var wcOffset = s.indexOf('*');
|
this.lSegment = lSegment;
|
||||||
this.lSegment = s.slice(0, wcOffset);
|
this.rSegment = rSegment;
|
||||||
this.rSegment = s.slice(wcOffset + 1);
|
|
||||||
this.hostname = hostname;
|
this.hostname = hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -487,10 +684,23 @@ FilterSingleWildcardRightAnchoredHostname.prototype.match = function(url) {
|
|||||||
url.lastIndexOf(this.lSegment, url.length - this.rSegment.length - this.lSegment.length) >= 0;
|
url.lastIndexOf(this.lSegment, url.length - this.rSegment.length - this.lSegment.length) >= 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardRightAnchoredHostname.prototype.fid = '*|h';
|
||||||
|
|
||||||
FilterSingleWildcardRightAnchoredHostname.prototype.toString = function() {
|
FilterSingleWildcardRightAnchoredHostname.prototype.toString = function() {
|
||||||
return this.lSegment + '*' + this.rSegment + '|$domain=' + this.hostname;
|
return this.lSegment + '*' + this.rSegment + '|$domain=' + this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardRightAnchoredHostname.prototype.toSelfie = function() {
|
||||||
|
return this.lSegment + '\t' +
|
||||||
|
this.rSegment + '\t' +
|
||||||
|
this.hostname;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardRightAnchoredHostname.fromSelfie = function(s) {
|
||||||
|
var args = s.split('\t');
|
||||||
|
return new FilterSingleWildcardRightAnchoredHostname(args[0], args[1], args[2]);
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// With many wildcards, a regex is best.
|
// With many wildcards, a regex is best.
|
||||||
@ -509,10 +719,22 @@ FilterManyWildcards.prototype.match = function(url, tokenBeg) {
|
|||||||
return this.re.test(url.slice(tokenBeg - this.tokenBeg));
|
return this.re.test(url.slice(tokenBeg - this.tokenBeg));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterManyWildcards.prototype.fid = '*+';
|
||||||
|
|
||||||
FilterManyWildcards.prototype.toString = function() {
|
FilterManyWildcards.prototype.toString = function() {
|
||||||
return this.s;
|
return this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterManyWildcards.prototype.toSelfie = function() {
|
||||||
|
return this.s + '\t' +
|
||||||
|
this.tokenBeg;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterManyWildcards.fromSelfie = function(s) {
|
||||||
|
var pos = s.indexOf('\t');
|
||||||
|
return new FilterManyWildcards(s.slice(0, pos), atoi(s.slice(pos + 1)));
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterManyWildcardsHostname = function(s, tokenBeg, hostname) {
|
var FilterManyWildcardsHostname = function(s, tokenBeg, hostname) {
|
||||||
@ -527,29 +749,90 @@ FilterManyWildcardsHostname.prototype.match = function(url, tokenBeg) {
|
|||||||
this.re.test(url.slice(tokenBeg - this.tokenBeg));
|
this.re.test(url.slice(tokenBeg - this.tokenBeg));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterManyWildcardsHostname.prototype.fid = '*+h';
|
||||||
|
|
||||||
FilterManyWildcardsHostname.prototype.toString = function() {
|
FilterManyWildcardsHostname.prototype.toString = function() {
|
||||||
return this.s + '$domain=' + this.hostname;
|
return this.s + '$domain=' + this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterManyWildcardsHostname.prototype.toSelfie = function() {
|
||||||
|
return this.s + '\t' +
|
||||||
|
this.tokenBeg + '\t' +
|
||||||
|
this.hostname;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterManyWildcardsHostname.fromSelfie = function(s) {
|
||||||
|
var args = s.split('\t');
|
||||||
|
return new FilterManyWildcardsHostname(args[0], atoi(args[1]), args[2]);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var FilterBucket = function(a, b) {
|
||||||
|
this.f = null;
|
||||||
|
this.filters = [];
|
||||||
|
if ( a !== undefined ) {
|
||||||
|
this.filters[0] = a;
|
||||||
|
if ( b !== undefined ) {
|
||||||
|
this.filters[1] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterBucket.prototype.add = function(a) {
|
||||||
|
this.filters.push(a);
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterBucket.prototype.match = function(url, tokenBeg) {
|
||||||
|
var filters = this.filters;
|
||||||
|
var i = filters.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
if ( filters[i].match(url, tokenBeg) !== false ) {
|
||||||
|
this.f = filters[i];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterBucket.prototype.fid = '[]';
|
||||||
|
|
||||||
|
FilterBucket.prototype.toString = function() {
|
||||||
|
if ( this.f !== null ) {
|
||||||
|
return this.f.toString();
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterBucket.prototype.toSelfie = function() {
|
||||||
|
return this.filters.length.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterBucket.fromSelfie = function() {
|
||||||
|
return new FilterBucket();
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var makeFilter = function(details, tokenBeg) {
|
var makeFilter = function(details, tokenBeg) {
|
||||||
var s = details.f;
|
var s = details.f;
|
||||||
var wcOffset = s.indexOf('*');
|
var wcOffset = s.indexOf('*');
|
||||||
if ( wcOffset > 0 ) {
|
if ( wcOffset !== -1 ) {
|
||||||
if ( (/\*[^*]\*/).test(s) ) {
|
if ( s.indexOf('*', wcOffset + 1) !== -1 ) {
|
||||||
return details.anchor === 0 ? new FilterManyWildcards(s, tokenBeg) : null;
|
return details.anchor === 0 ? new FilterManyWildcards(s, tokenBeg) : null;
|
||||||
}
|
}
|
||||||
|
var lSegment = s.slice(0, wcOffset);
|
||||||
|
var rSegment = s.slice(wcOffset + 1);
|
||||||
if ( details.anchor < 0 ) {
|
if ( details.anchor < 0 ) {
|
||||||
return new FilterSingleWildcardLeftAnchored(s);
|
return new FilterSingleWildcardLeftAnchored(lSegment, rSegment);
|
||||||
}
|
}
|
||||||
if ( details.anchor > 0 ) {
|
if ( details.anchor > 0 ) {
|
||||||
return new FilterSingleWildcardRightAnchored(s);
|
return new FilterSingleWildcardRightAnchored(lSegment, rSegment);
|
||||||
}
|
}
|
||||||
if ( tokenBeg === 0 ) {
|
if ( tokenBeg === 0 ) {
|
||||||
return new FilterSingleWildcardPrefix0(s);
|
return new FilterSingleWildcardPrefix0(lSegment, rSegment);
|
||||||
}
|
}
|
||||||
return new FilterSingleWildcard(s, tokenBeg);
|
return new FilterSingleWildcard(lSegment, rSegment, tokenBeg);
|
||||||
}
|
}
|
||||||
if ( details.anchor < 0 ) {
|
if ( details.anchor < 0 ) {
|
||||||
return new FilterPlainLeftAnchored(s);
|
return new FilterPlainLeftAnchored(s);
|
||||||
@ -571,20 +854,22 @@ var makeFilter = function(details, tokenBeg) {
|
|||||||
var makeHostnameFilter = function(details, tokenBeg, hostname) {
|
var makeHostnameFilter = function(details, tokenBeg, hostname) {
|
||||||
var s = details.f;
|
var s = details.f;
|
||||||
var wcOffset = s.indexOf('*');
|
var wcOffset = s.indexOf('*');
|
||||||
if ( wcOffset > 0 ) {
|
if ( wcOffset !== -1 ) {
|
||||||
if ( (/\*[^*]\*/).test(s) ) {
|
if ( s.indexOf('*', wcOffset + 1) !== -1 ) {
|
||||||
return details.anchor === 0 ? new FilterManyWildcardsHostname(s, tokenBeg, hostname) : null;
|
return details.anchor === 0 ? new FilterManyWildcardsHostname(s, tokenBeg, hostname) : null;
|
||||||
}
|
}
|
||||||
|
var lSegment = s.slice(0, wcOffset);
|
||||||
|
var rSegment = s.slice(wcOffset + 1);
|
||||||
if ( details.anchor < 0 ) {
|
if ( details.anchor < 0 ) {
|
||||||
return new FilterSingleWildcardLeftAnchoredHostname(s, hostname);
|
return new FilterSingleWildcardLeftAnchoredHostname(lSegment, rSegment, hostname);
|
||||||
}
|
}
|
||||||
if ( details.anchor > 0 ) {
|
if ( details.anchor > 0 ) {
|
||||||
return new FilterSingleWildcardRightAnchoredHostname(s, hostname);
|
return new FilterSingleWildcardRightAnchoredHostname(lSegment, rSegment, hostname);
|
||||||
}
|
}
|
||||||
if ( tokenBeg === 0 ) {
|
if ( tokenBeg === 0 ) {
|
||||||
return new FilterSingleWildcardPrefix0Hostname(s, hostname);
|
return new FilterSingleWildcardPrefix0Hostname(lSegment, rSegment, hostname);
|
||||||
}
|
}
|
||||||
return new FilterSingleWildcardHostname(s, tokenBeg, hostname);
|
return new FilterSingleWildcardHostname(lSegment, rSegment, tokenBeg, hostname);
|
||||||
}
|
}
|
||||||
if ( details.anchor < 0 ) {
|
if ( details.anchor < 0 ) {
|
||||||
return new FilterPlainLeftAnchoredHostname(s, hostname);
|
return new FilterPlainLeftAnchoredHostname(s, hostname);
|
||||||
@ -613,6 +898,7 @@ var badTokens = {
|
|||||||
'com': true,
|
'com': true,
|
||||||
'http': true,
|
'http': true,
|
||||||
'https': true,
|
'https': true,
|
||||||
|
'icon': true,
|
||||||
'images': true,
|
'images': true,
|
||||||
'img': true,
|
'img': true,
|
||||||
'js': true,
|
'js': true,
|
||||||
@ -661,6 +947,7 @@ var trimChar = function(s, c) {
|
|||||||
return s;
|
return s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterParser = function() {
|
var FilterParser = function() {
|
||||||
@ -783,6 +1070,19 @@ FilterParser.prototype.parse = function(s) {
|
|||||||
s = s.slice(2);
|
s = s.slice(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// options
|
||||||
|
var pos = s.indexOf('$');
|
||||||
|
if ( pos > 0 ) {
|
||||||
|
this.fopts = s.slice(pos + 1);
|
||||||
|
s = s.slice(0, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// regex? (not supported)
|
||||||
|
if ( s.charAt(0) === '/' && s.slice(-1) === '/' ) {
|
||||||
|
this.unsupported = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
// hostname anchoring
|
// hostname anchoring
|
||||||
if ( s.slice(0, 2) === '||' ) {
|
if ( s.slice(0, 2) === '||' ) {
|
||||||
this.hostname = true;
|
this.hostname = true;
|
||||||
@ -795,13 +1095,6 @@ FilterParser.prototype.parse = function(s) {
|
|||||||
s = s.slice(1);
|
s = s.slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// options
|
|
||||||
var pos = s.indexOf('$');
|
|
||||||
if ( pos > 0 ) {
|
|
||||||
this.fopts = s.slice(pos + 1);
|
|
||||||
s = s.slice(0, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// right-anchored
|
// right-anchored
|
||||||
if ( s.slice(-1) === '|' ) {
|
if ( s.slice(-1) === '|' ) {
|
||||||
this.anchor = 1;
|
this.anchor = 1;
|
||||||
@ -859,37 +1152,6 @@ FilterParser.prototype.parse = function(s) {
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var FilterBucket = function(a, b) {
|
|
||||||
this.filters = [a, b];
|
|
||||||
this.f = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
FilterBucket.prototype.add = function(a) {
|
|
||||||
this.filters.push(a);
|
|
||||||
};
|
|
||||||
|
|
||||||
FilterBucket.prototype.match = function(url, tokenBeg) {
|
|
||||||
var filters = this.filters;
|
|
||||||
var i = filters.length;
|
|
||||||
while ( i-- ) {
|
|
||||||
if ( filters[i].match(url, tokenBeg) !== false ) {
|
|
||||||
this.f = filters[i];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
FilterBucket.prototype.toString = function() {
|
|
||||||
if ( this.f !== null ) {
|
|
||||||
return this.f.toString();
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
var FilterContainer = function() {
|
var FilterContainer = function() {
|
||||||
this.reAnyToken = /[%0-9a-z]+/g;
|
this.reAnyToken = /[%0-9a-z]+/g;
|
||||||
this.buckets = new Array(8);
|
this.buckets = new Array(8);
|
||||||
@ -908,6 +1170,7 @@ FilterContainer.prototype.reset = function() {
|
|||||||
this.frozen = false;
|
this.frozen = false;
|
||||||
this.processedFilterCount = 0;
|
this.processedFilterCount = 0;
|
||||||
this.acceptedCount = 0;
|
this.acceptedCount = 0;
|
||||||
|
this.rejectedCount = 0;
|
||||||
this.allowFilterCount = 0;
|
this.allowFilterCount = 0;
|
||||||
this.blockFilterCount = 0;
|
this.blockFilterCount = 0;
|
||||||
this.duplicateCount = 0;
|
this.duplicateCount = 0;
|
||||||
@ -931,6 +1194,136 @@ FilterContainer.prototype.freeze = function() {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
FilterContainer.prototype.toSelfie = function() {
|
||||||
|
var categoryToSelfie = function(dict) {
|
||||||
|
var selfie = [];
|
||||||
|
var bucket, ff, n, i, f;
|
||||||
|
for ( var k in dict ) {
|
||||||
|
if ( dict.hasOwnProperty(k) === false ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// We need to encode the key because there could be a `\n` or '\t'
|
||||||
|
// character in it, which would trip the code at parse time.
|
||||||
|
selfie.push('k2\t' + encode(k));
|
||||||
|
bucket = dict[k];
|
||||||
|
selfie.push(bucket.fid + '\t' + bucket.toSelfie());
|
||||||
|
if ( bucket.fid !== '[]' ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ff = bucket.filters;
|
||||||
|
n = ff.length;
|
||||||
|
for ( i = 0; i < n; i++ ) {
|
||||||
|
f = ff[i];
|
||||||
|
selfie.push(f.fid + '\t' + f.toSelfie());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return selfie.join('\n');
|
||||||
|
};
|
||||||
|
|
||||||
|
var categoriesToSelfie = function(dict) {
|
||||||
|
var selfie = [];
|
||||||
|
for ( var k in dict ) {
|
||||||
|
if ( dict.hasOwnProperty(k) === false ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// We need to encode the key because there could be a `\n` or '\t'
|
||||||
|
// character in it, which would trip the code at parse time.
|
||||||
|
selfie.push('k1\t' + encode(k));
|
||||||
|
selfie.push(categoryToSelfie(dict[k]));
|
||||||
|
}
|
||||||
|
return selfie.join('\n');
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
processedFilterCount: this.processedFilterCount,
|
||||||
|
acceptedCount: this.acceptedCount,
|
||||||
|
rejectedCount: this.rejectedCount,
|
||||||
|
allowFilterCount: this.allowFilterCount,
|
||||||
|
blockFilterCount: this.blockFilterCount,
|
||||||
|
duplicateCount: this.duplicateCount,
|
||||||
|
categories: categoriesToSelfie(this.categories),
|
||||||
|
blockedAnyPartyHostnames: this.blockedAnyPartyHostnames.toSelfie(),
|
||||||
|
blocked3rdPartyHostnames: this.blocked3rdPartyHostnames.toSelfie()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
FilterContainer.prototype.fromSelfie = function(selfie) {
|
||||||
|
this.frozen = true;
|
||||||
|
this.processedFilterCount = selfie.processedFilterCount;
|
||||||
|
this.acceptedCount = selfie.acceptedCount;
|
||||||
|
this.rejectedCount = selfie.rejectedCount;
|
||||||
|
this.allowFilterCount = selfie.allowFilterCount;
|
||||||
|
this.blockFilterCount = selfie.blockFilterCount;
|
||||||
|
this.duplicateCount = selfie.duplicateCount;
|
||||||
|
this.blockedAnyPartyHostnames.fromSelfie(selfie.blockedAnyPartyHostnames);
|
||||||
|
this.blocked3rdPartyHostnames.fromSelfie(selfie.blocked3rdPartyHostnames);
|
||||||
|
|
||||||
|
var factories = {
|
||||||
|
'[]': FilterBucket,
|
||||||
|
'a': FilterPlain,
|
||||||
|
'ah': FilterPlainHostname,
|
||||||
|
'0a': FilterPlainPrefix0,
|
||||||
|
'0ah': FilterPlainPrefix0Hostname,
|
||||||
|
'1a': FilterPlainPrefix1,
|
||||||
|
'1ah': FilterPlainPrefix1Hostname,
|
||||||
|
'|a': FilterPlainLeftAnchored,
|
||||||
|
'|ah': FilterPlainLeftAnchoredHostname,
|
||||||
|
'a|': FilterPlainRightAnchored,
|
||||||
|
'a|h': FilterPlainRightAnchoredHostname,
|
||||||
|
'*': FilterSingleWildcard,
|
||||||
|
'*h': FilterSingleWildcardHostname,
|
||||||
|
'0*': FilterSingleWildcardPrefix0,
|
||||||
|
'0*h': FilterSingleWildcardPrefix0Hostname,
|
||||||
|
'|*': FilterSingleWildcardLeftAnchored,
|
||||||
|
'|*h': FilterSingleWildcardLeftAnchoredHostname,
|
||||||
|
'*|': FilterSingleWildcardRightAnchored,
|
||||||
|
'*|h': FilterSingleWildcardRightAnchoredHostname,
|
||||||
|
'*+': FilterManyWildcards,
|
||||||
|
'*+h': FilterManyWildcardsHostname
|
||||||
|
};
|
||||||
|
|
||||||
|
var catKey, tokenKey;
|
||||||
|
var dict = this.categories, subdict;
|
||||||
|
var bucket = null;
|
||||||
|
var rawText = selfie.categories;
|
||||||
|
var rawEnd = rawText.length;
|
||||||
|
var lineBeg = 0, lineEnd;
|
||||||
|
var line, pos, what, factory;
|
||||||
|
while ( lineBeg < rawEnd ) {
|
||||||
|
lineEnd = rawText.indexOf('\n', lineBeg);
|
||||||
|
if ( lineEnd < 0 ) {
|
||||||
|
lineEnd = rawEnd;
|
||||||
|
}
|
||||||
|
line = rawText.slice(lineBeg, lineEnd);
|
||||||
|
lineBeg = lineEnd + 1;
|
||||||
|
pos = line.indexOf('\t');
|
||||||
|
what = line.slice(0, pos);
|
||||||
|
if ( what === 'k1' ) {
|
||||||
|
catKey = decode(line.slice(pos + 1));
|
||||||
|
subdict = dict[catKey] = {};
|
||||||
|
bucket = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( what === 'k2' ) {
|
||||||
|
tokenKey = decode(line.slice(pos + 1));
|
||||||
|
bucket = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
factory = factories[what];
|
||||||
|
if ( bucket === null ) {
|
||||||
|
bucket = subdict[tokenKey] = factory.fromSelfie(line.slice(pos + 1));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// When token key is reused, it can't be anything
|
||||||
|
// else than FilterBucket
|
||||||
|
bucket.add(factory.fromSelfie(line.slice(pos + 1)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.toDomainBits = function(domain) {
|
FilterContainer.prototype.toDomainBits = function(domain) {
|
||||||
if ( domain === undefined ) {
|
if ( domain === undefined ) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -989,6 +1382,13 @@ FilterContainer.prototype.add = function(s) {
|
|||||||
|
|
||||||
var parsed = this.filterParser.parse(s);
|
var parsed = this.filterParser.parse(s);
|
||||||
|
|
||||||
|
// Ignore rules with other conditions for now
|
||||||
|
if ( parsed.unsupported ) {
|
||||||
|
this.rejectedCount += 1;
|
||||||
|
// console.log('µBlock> abp-filter.js/FilterContainer.add(): unsupported filter "%s"', s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Ignore element-hiding filters
|
// Ignore element-hiding filters
|
||||||
if ( parsed.elemHiding ) {
|
if ( parsed.elemHiding ) {
|
||||||
return false;
|
return false;
|
||||||
@ -1002,12 +1402,6 @@ FilterContainer.prototype.add = function(s) {
|
|||||||
|
|
||||||
this.processedFilterCount += 1;
|
this.processedFilterCount += 1;
|
||||||
|
|
||||||
// Ignore rules with other conditions for now
|
|
||||||
if ( parsed.unsupported ) {
|
|
||||||
// console.log('µBlock> abp-filter.js/FilterContainer.add(): unsupported filter "%s"', s);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore optionless hostname rules, these will be taken care of by µBlock.
|
// Ignore optionless hostname rules, these will be taken care of by µBlock.
|
||||||
if ( parsed.hostname && parsed.fopts === '' && parsed.action === BlockAction && reHostnameRule.test(parsed.f) ) {
|
if ( parsed.hostname && parsed.fopts === '' && parsed.action === BlockAction && reHostnameRule.test(parsed.f) ) {
|
||||||
return false;
|
return false;
|
||||||
@ -1145,7 +1539,7 @@ FilterContainer.prototype.addToCategory = function(category, tokenKey, filter) {
|
|||||||
categoryBucket[tokenKey] = filter;
|
categoryBucket[tokenKey] = filter;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( filterEntry instanceof FilterBucket ) {
|
if ( filterEntry.fid === '[]' ) {
|
||||||
filterEntry.add(filter);
|
filterEntry.add(filter);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,20 @@
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.abpHideFilters = (function(){
|
µBlock.cosmeticFilteringEngine = (function(){
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var µb = µBlock;
|
var µb = µBlock;
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// Could be replaced with encodeURIComponent/decodeURIComponent,
|
||||||
|
// which seems faster on Firefox.
|
||||||
|
var encode = JSON.stringify;
|
||||||
|
var decode = JSON.parse;
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/*
|
/*
|
||||||
var histogram = function(label, buckets) {
|
var histogram = function(label, buckets) {
|
||||||
@ -86,6 +93,16 @@ FilterPlain.prototype.retrieve = function(s, out) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlain.prototype.fid = '#';
|
||||||
|
|
||||||
|
FilterPlain.prototype.toSelfie = function() {
|
||||||
|
return this.s;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterPlain.fromSelfie = function(s) {
|
||||||
|
return new FilterPlain(s);
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// Id- and class-based filters with extra selector stuff following.
|
// Id- and class-based filters with extra selector stuff following.
|
||||||
@ -104,6 +121,50 @@ FilterPlainMore.prototype.retrieve = function(s, out) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainMore.prototype.fid = '#+';
|
||||||
|
|
||||||
|
FilterPlainMore.prototype.toSelfie = function() {
|
||||||
|
return this.s;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterPlainMore.fromSelfie = function(s) {
|
||||||
|
return new FilterPlainMore(s);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var FilterBucket = function(a, b) {
|
||||||
|
this.f = null;
|
||||||
|
this.filters = [];
|
||||||
|
if ( a !== undefined ) {
|
||||||
|
this.filters[0] = a;
|
||||||
|
if ( b !== undefined ) {
|
||||||
|
this.filters[1] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterBucket.prototype.add = function(a) {
|
||||||
|
this.filters.push(a);
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterBucket.prototype.retrieve = function(s, out) {
|
||||||
|
var i = this.filters.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
this.filters[i].retrieve(s, out);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterBucket.prototype.fid = '[]';
|
||||||
|
|
||||||
|
FilterBucket.prototype.toSelfie = function() {
|
||||||
|
return this.filters.length.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterBucket.fromSelfie = function() {
|
||||||
|
return new FilterBucket();
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// Any selector specific to a hostname
|
// Any selector specific to a hostname
|
||||||
@ -127,6 +188,17 @@ FilterHostname.prototype.retrieve = function(hostname, out) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterHostname.prototype.fid = 'h';
|
||||||
|
|
||||||
|
FilterHostname.prototype.toSelfie = function() {
|
||||||
|
return encode(this.s) + '\t' + this.hostname;
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterHostname.fromSelfie = function(s) {
|
||||||
|
var pos = s.indexOf('\t');
|
||||||
|
return new FilterHostname(decode(s.slice(0, pos)), s.slice(pos + 1));
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// Any selector specific to an entity
|
// Any selector specific to an entity
|
||||||
@ -144,28 +216,15 @@ FilterEntity.prototype.retrieve = function(entity, out) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
FilterEntity.prototype.fid = 'e';
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// TODO: evaluate the gain (if any) from avoiding the use of an array for when
|
FilterEntity.prototype.toSelfie = function() {
|
||||||
// there are only two filters (or three, etc.). I suppose there is a specific
|
return encode(this.s) + '\t' + this.entity;
|
||||||
// number of filters below which using an array is more of an overhead than
|
|
||||||
// using a couple of property members.
|
|
||||||
// i.e. FilterBucket2, FilterBucket3, FilterBucketN.
|
|
||||||
|
|
||||||
var FilterBucket = function(a, b) {
|
|
||||||
this.filters = [a, b];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterBucket.prototype.add = function(a) {
|
FilterEntity.fromSelfie = function(s) {
|
||||||
this.filters.push(a);
|
var pos = s.indexOf('\t');
|
||||||
};
|
return new FilterEntity(decode(s.slice(0, pos)), s.slice(pos + 1));
|
||||||
|
|
||||||
FilterBucket.prototype.retrieve = function(s, out) {
|
|
||||||
var i = this.filters.length;
|
|
||||||
while ( i-- ) {
|
|
||||||
this.filters[i].retrieve(s, out);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -419,6 +478,7 @@ FilterContainer.prototype.reset = function() {
|
|||||||
this.hostnameDonthide = {};
|
this.hostnameDonthide = {};
|
||||||
this.entityHide = {};
|
this.entityHide = {};
|
||||||
this.entityDonthide = {};
|
this.entityDonthide = {};
|
||||||
|
|
||||||
// permanent
|
// permanent
|
||||||
// [class], [id]
|
// [class], [id]
|
||||||
this.lowGenericFilters = {};
|
this.lowGenericFilters = {};
|
||||||
@ -436,11 +496,12 @@ FilterContainer.prototype.reset = function() {
|
|||||||
this.highMediumGenericDonthideCount = 0;
|
this.highMediumGenericDonthideCount = 0;
|
||||||
|
|
||||||
// everything else
|
// everything else
|
||||||
this.highHighGenericHide = [];
|
this.highHighGenericHide = '';
|
||||||
this.highHighGenericDonthide = [];
|
this.highHighGenericDonthide = '';
|
||||||
this.highHighGenericHideCount = 0;
|
this.highHighGenericHideCount = 0;
|
||||||
this.highHighGenericDonthideCount = 0;
|
this.highHighGenericDonthideCount = 0;
|
||||||
|
|
||||||
|
// hostname, entity-based filters
|
||||||
this.hostnameFilters = {};
|
this.hostnameFilters = {};
|
||||||
this.entityFilters = {};
|
this.entityFilters = {};
|
||||||
};
|
};
|
||||||
@ -705,6 +766,120 @@ FilterContainer.prototype.freeze = function() {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
FilterContainer.prototype.toSelfie = function() {
|
||||||
|
var selfieFromDict = function(dict) {
|
||||||
|
var selfie = [];
|
||||||
|
var bucket, ff, n, i, f;
|
||||||
|
for ( var k in dict ) {
|
||||||
|
if ( dict.hasOwnProperty(k) === false ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// We need to encode the key because there could be a `\n`
|
||||||
|
// character in it, which would trip the code at parse time.
|
||||||
|
selfie.push('k\t' + encode(k));
|
||||||
|
bucket = dict[k];
|
||||||
|
selfie.push(bucket.fid + '\t' + bucket.toSelfie());
|
||||||
|
if ( bucket.fid !== '[]' ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ff = bucket.filters;
|
||||||
|
n = ff.length;
|
||||||
|
for ( i = 0; i < n; i++ ) {
|
||||||
|
f = ff[i];
|
||||||
|
selfie.push(f.fid + '\t' + f.toSelfie());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return selfie.join('\n');
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
acceptedCount: this.acceptedCount,
|
||||||
|
duplicateCount: this.duplicateCount,
|
||||||
|
hostnameSpecificFilters: selfieFromDict(this.hostnameFilters),
|
||||||
|
entitySpecificFilters: selfieFromDict(this.entityFilters),
|
||||||
|
lowGenericFilters: selfieFromDict(this.lowGenericFilters),
|
||||||
|
highLowGenericHide: this.highLowGenericHide,
|
||||||
|
highLowGenericDonthide: this.highLowGenericDonthide,
|
||||||
|
highLowGenericHideCount: this.highLowGenericHideCount,
|
||||||
|
highLowGenericDonthideCount: this.highLowGenericDonthideCount,
|
||||||
|
highMediumGenericHide: this.highMediumGenericHide,
|
||||||
|
highMediumGenericDonthide: this.highMediumGenericDonthide,
|
||||||
|
highMediumGenericHideCount: this.highMediumGenericHideCount,
|
||||||
|
highMediumGenericDonthideCount: this.highMediumGenericDonthideCount,
|
||||||
|
highHighGenericHide: this.highHighGenericHide,
|
||||||
|
highHighGenericDonthide: this.highHighGenericDonthide,
|
||||||
|
highHighGenericHideCount: this.highHighGenericHideCount,
|
||||||
|
highHighGenericDonthideCount: this.highHighGenericDonthideCount
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
FilterContainer.prototype.fromSelfie = function(selfie) {
|
||||||
|
var factories = {
|
||||||
|
'[]': FilterBucket,
|
||||||
|
'#': FilterPlain,
|
||||||
|
'#+': FilterPlainMore,
|
||||||
|
'h': FilterHostname,
|
||||||
|
'e': FilterEntity
|
||||||
|
};
|
||||||
|
|
||||||
|
var dictFromSelfie = function(selfie) {
|
||||||
|
var dict = {};
|
||||||
|
var dictKey;
|
||||||
|
var bucket = null;
|
||||||
|
var rawText = selfie;
|
||||||
|
var rawEnd = rawText.length;
|
||||||
|
var lineBeg = 0, lineEnd;
|
||||||
|
var line, pos, what, factory;
|
||||||
|
while ( lineBeg < rawEnd ) {
|
||||||
|
lineEnd = rawText.indexOf('\n', lineBeg);
|
||||||
|
if ( lineEnd < 0 ) {
|
||||||
|
lineEnd = rawEnd;
|
||||||
|
}
|
||||||
|
line = rawText.slice(lineBeg, lineEnd);
|
||||||
|
lineBeg = lineEnd + 1;
|
||||||
|
pos = line.indexOf('\t');
|
||||||
|
what = line.slice(0, pos);
|
||||||
|
if ( what === 'k' ) {
|
||||||
|
dictKey = decode(line.slice(pos + 1));
|
||||||
|
bucket = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
factory = factories[what];
|
||||||
|
if ( bucket === null ) {
|
||||||
|
bucket = dict[dictKey] = factory.fromSelfie(line.slice(pos + 1));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// When token key is reused, it can't be anything
|
||||||
|
// else than FilterBucket
|
||||||
|
bucket.add(factory.fromSelfie(line.slice(pos + 1)));
|
||||||
|
}
|
||||||
|
return dict;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.frozen = true;
|
||||||
|
this.acceptedCount = selfie.acceptedCount;
|
||||||
|
this.duplicateCount = selfie.duplicateCount;
|
||||||
|
this.hostnameFilters = dictFromSelfie(selfie.hostnameSpecificFilters);
|
||||||
|
this.entityFilters = dictFromSelfie(selfie.entitySpecificFilters);
|
||||||
|
this.lowGenericFilters = dictFromSelfie(selfie.lowGenericFilters);
|
||||||
|
this.highLowGenericHide = selfie.highLowGenericHide;
|
||||||
|
this.highLowGenericDonthide = selfie.highLowGenericDonthide;
|
||||||
|
this.highLowGenericHideCount = selfie.highLowGenericHideCount;
|
||||||
|
this.highLowGenericDonthideCount = selfie.highLowGenericDonthideCount;
|
||||||
|
this.highMediumGenericHide = selfie.highMediumGenericHide;
|
||||||
|
this.highMediumGenericDonthide = selfie.highMediumGenericDonthide;
|
||||||
|
this.highMediumGenericHideCount = selfie.highMediumGenericHideCount;
|
||||||
|
this.highMediumGenericDonthideCount = selfie.highMediumGenericDonthideCount;
|
||||||
|
this.highHighGenericHide = selfie.highHighGenericHide;
|
||||||
|
this.highHighGenericDonthide = selfie.highHighGenericDonthide;
|
||||||
|
this.highHighGenericHideCount = selfie.highHighGenericHideCount;
|
||||||
|
this.highHighGenericDonthideCount = selfie.highHighGenericDonthideCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.addToSelectorCache = function(details) {
|
FilterContainer.prototype.addToSelectorCache = function(details) {
|
||||||
var hostname = details.hostname;
|
var hostname = details.hostname;
|
||||||
if ( typeof hostname !== 'string' || hostname === '' ) {
|
if ( typeof hostname !== 'string' || hostname === '' ) {
|
||||||
|
15
js/assets.js
15
js/assets.js
@ -43,16 +43,23 @@ File system structure:
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var oneSecond = 1000;
|
||||||
|
var oneMinute = 60 * oneSecond;
|
||||||
|
var oneHour = 60 * oneMinute;
|
||||||
|
var oneDay = 24 * oneHour;
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
var repositoryRoot = µBlock.projectServerRoot;
|
var repositoryRoot = µBlock.projectServerRoot;
|
||||||
var nullFunc = function() {};
|
var nullFunc = function() {};
|
||||||
var reIsExternalPath = /^https?:\/\/[a-z0-9]/;
|
var reIsExternalPath = /^https?:\/\/[a-z0-9]/;
|
||||||
var reIsUserPath = /^assets\/user\//;
|
var reIsUserPath = /^assets\/user\//;
|
||||||
var lastRepoMetaTimestamp = 0;
|
var lastRepoMetaTimestamp = 0;
|
||||||
var refreshRepoMetaPeriod = 6 * 60 * 60 * 1000;
|
var refreshRepoMetaPeriod = 5 * oneHour;
|
||||||
|
|
||||||
var exports = {
|
var exports = {
|
||||||
autoUpdate: true,
|
autoUpdate: true,
|
||||||
autoUpdateDelay: 2 * 24 * 60 * 60 * 1000
|
autoUpdateDelay: 4 * oneDay
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -349,7 +356,7 @@ exports.setHomeURL = function(path, homeURL) {
|
|||||||
entry = metadata.entries[path] = new AssetEntry();
|
entry = metadata.entries[path] = new AssetEntry();
|
||||||
}
|
}
|
||||||
entry.homeURL = homeURL;
|
entry.homeURL = homeURL;
|
||||||
}
|
};
|
||||||
getRepoMetadata(onRepoMetadataReady);
|
getRepoMetadata(onRepoMetadataReady);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -548,9 +555,9 @@ var readRepoCopyAsset = function(path, callback) {
|
|||||||
var onCacheMetaReady = function(entries) {
|
var onCacheMetaReady = function(entries) {
|
||||||
// Fetch from remote if:
|
// Fetch from remote if:
|
||||||
// - Auto-update enabled AND (not in cache OR in cache but obsolete)
|
// - Auto-update enabled AND (not in cache OR in cache but obsolete)
|
||||||
|
var timestamp = entries[path];
|
||||||
var homeURL = assetEntry.homeURL;
|
var homeURL = assetEntry.homeURL;
|
||||||
if ( exports.autoUpdate && typeof homeURL === 'string' && homeURL !== '' ) {
|
if ( exports.autoUpdate && typeof homeURL === 'string' && homeURL !== '' ) {
|
||||||
var timestamp = entries[path];
|
|
||||||
var obsolete = Date.now() - exports.autoUpdateDelay;
|
var obsolete = Date.now() - exports.autoUpdateDelay;
|
||||||
if ( typeof timestamp !== 'number' || timestamp <= obsolete ) {
|
if ( typeof timestamp !== 'number' || timestamp <= obsolete ) {
|
||||||
//console.log('µBlock> readRepoCopyAsset("%s") / onCacheMetaReady(): not cached or obsolete', path);
|
//console.log('µBlock> readRepoCopyAsset("%s") / onCacheMetaReady(): not cached or obsolete', path);
|
||||||
|
@ -63,6 +63,7 @@ return {
|
|||||||
updateAssetsEvery: 75 * oneHour + 23 * oneMinute + 53 * oneSecond + 605,
|
updateAssetsEvery: 75 * oneHour + 23 * oneMinute + 53 * oneSecond + 605,
|
||||||
projectServerRoot: 'https://raw.githubusercontent.com/gorhill/uBlock/master/',
|
projectServerRoot: 'https://raw.githubusercontent.com/gorhill/uBlock/master/',
|
||||||
userFiltersPath: 'assets/user/filters.txt',
|
userFiltersPath: 'assets/user/filters.txt',
|
||||||
|
pslPath: 'assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat',
|
||||||
|
|
||||||
// permanent lists
|
// permanent lists
|
||||||
permanentLists: {
|
permanentLists: {
|
||||||
@ -86,11 +87,21 @@ return {
|
|||||||
remoteBlacklists: {
|
remoteBlacklists: {
|
||||||
},
|
},
|
||||||
|
|
||||||
|
firstUpdateAfter: 5 * oneMinute,
|
||||||
|
nextUpdateAfter: 7 * oneHour,
|
||||||
|
|
||||||
|
selfieMagic: 'ccolmudazpvm',
|
||||||
|
selfieAfter: 7 * oneMinute,
|
||||||
|
|
||||||
pageStores: {},
|
pageStores: {},
|
||||||
|
|
||||||
storageQuota: chrome.storage.local.QUOTA_BYTES,
|
storageQuota: chrome.storage.local.QUOTA_BYTES,
|
||||||
storageUsed: 0,
|
storageUsed: 0,
|
||||||
|
|
||||||
|
noopFunc: function(){},
|
||||||
|
|
||||||
|
apiErrorCount: 0,
|
||||||
|
|
||||||
// so that I don't have to care for last comma
|
// so that I don't have to care for last comma
|
||||||
dummy: 0
|
dummy: 0
|
||||||
};
|
};
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
Home: https://github.com/gorhill/uBlock
|
Home: https://github.com/gorhill/uBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* jshint bitwise: false */
|
||||||
|
/* global µBlock */
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.LiquidDict = (function() {
|
µBlock.LiquidDict = (function() {
|
||||||
@ -94,12 +97,20 @@ LiquidDict.prototype.makeKey = function(word) {
|
|||||||
if ( len > 255 ) {
|
if ( len > 255 ) {
|
||||||
len = 255;
|
len = 255;
|
||||||
}
|
}
|
||||||
var i = len >> 2;
|
var i8 = len >>> 3;
|
||||||
|
var i4 = len >>> 2;
|
||||||
|
var i2 = len >>> 1;
|
||||||
|
|
||||||
|
// Be sure the msb is not set, this will guarantee a valid unicode
|
||||||
|
// character (because 0xD800-0xDFFF).
|
||||||
return String.fromCharCode(
|
return String.fromCharCode(
|
||||||
(word.charCodeAt( 0) & 0x03) << 14 |
|
(word.charCodeAt( i8) & 0x01) << 14 |
|
||||||
(word.charCodeAt( i) & 0x03) << 12 |
|
(word.charCodeAt( i4 ) & 0x01) << 13 |
|
||||||
(word.charCodeAt( i+i) & 0x03) << 10 |
|
(word.charCodeAt( i4+i8) & 0x01) << 12 |
|
||||||
(word.charCodeAt(i+i+i) & 0x03) << 8 |
|
(word.charCodeAt(i2 ) & 0x01) << 11 |
|
||||||
|
(word.charCodeAt(i2 +i8) & 0x01) << 10 |
|
||||||
|
(word.charCodeAt(i2+i4 ) & 0x01) << 9 |
|
||||||
|
(word.charCodeAt(i2+i4+i8) & 0x01) << 8 ,
|
||||||
len
|
len
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -187,6 +198,26 @@ LiquidDict.prototype.reset = function() {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
LiquidDict.prototype.toSelfie = function() {
|
||||||
|
return {
|
||||||
|
count: this.count,
|
||||||
|
bucketCount: this.bucketCount,
|
||||||
|
frozenBucketCount: this.frozenBucketCount,
|
||||||
|
dict: this.dict
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
LiquidDict.prototype.fromSelfie = function(selfie) {
|
||||||
|
this.count = selfie.count;
|
||||||
|
this.bucketCount = selfie.bucketCount;
|
||||||
|
this.frozenBucketCount = selfie.frozenBucketCount;
|
||||||
|
this.dict = selfie.dict;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
return LiquidDict;
|
return LiquidDict;
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -121,7 +121,7 @@ var onMessage = function(request, sender, callback) {
|
|||||||
switch ( request.what ) {
|
switch ( request.what ) {
|
||||||
case 'retrieveDomainCosmeticSelectors':
|
case 'retrieveDomainCosmeticSelectors':
|
||||||
if ( pageStore && pageStore.getNetFilteringSwitch() ) {
|
if ( pageStore && pageStore.getNetFilteringSwitch() ) {
|
||||||
response = µb.abpHideFilters.retrieveDomainSelectors(request);
|
response = µb.cosmeticFilteringEngine.retrieveDomainSelectors(request);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -162,12 +162,12 @@ var onMessage = function(request, sender, callback) {
|
|||||||
switch ( request.what ) {
|
switch ( request.what ) {
|
||||||
case 'retrieveGenericCosmeticSelectors':
|
case 'retrieveGenericCosmeticSelectors':
|
||||||
if ( pageStore && pageStore.getNetFilteringSwitch() ) {
|
if ( pageStore && pageStore.getNetFilteringSwitch() ) {
|
||||||
response = µb.abpHideFilters.retrieveGenericSelectors(request);
|
response = µb.cosmeticFilteringEngine.retrieveGenericSelectors(request);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'injectedSelectors':
|
case 'injectedSelectors':
|
||||||
µb.abpHideFilters.addToSelectorCache(request);
|
µb.cosmeticFilteringEngine.addToSelectorCache(request);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'blockedRequests':
|
case 'blockedRequests':
|
||||||
@ -250,8 +250,8 @@ var getLists = function(callback) {
|
|||||||
available: null,
|
available: null,
|
||||||
current: µb.remoteBlacklists,
|
current: µb.remoteBlacklists,
|
||||||
cosmetic: µb.userSettings.parseAllABPHideFilters,
|
cosmetic: µb.userSettings.parseAllABPHideFilters,
|
||||||
netFilterCount: µb.abpFilters.getFilterCount(),
|
netFilterCount: µb.netFilteringEngine.getFilterCount(),
|
||||||
cosmeticFilterCount: µb.abpHideFilters.getFilterCount(),
|
cosmeticFilterCount: µb.cosmeticFilteringEngine.getFilterCount(),
|
||||||
autoUpdate: µb.userSettings.autoUpdate,
|
autoUpdate: µb.userSettings.autoUpdate,
|
||||||
userFiltersPath: µb.userFiltersPath,
|
userFiltersPath: µb.userFiltersPath,
|
||||||
cache: null
|
cache: null
|
||||||
|
@ -40,12 +40,15 @@ var quickProfiler = (function() {
|
|||||||
prompt = s || '';
|
prompt = s || '';
|
||||||
tstart = timer.now();
|
tstart = timer.now();
|
||||||
};
|
};
|
||||||
var stop = function() {
|
var stop = function(period) {
|
||||||
|
if ( period === undefined ) {
|
||||||
|
period = 10000;
|
||||||
|
}
|
||||||
var now = timer.now();
|
var now = timer.now();
|
||||||
count += 1;
|
count += 1;
|
||||||
time += (now - tstart);
|
time += (now - tstart);
|
||||||
if ( (now - lastlog) > 10000 ) {
|
if ( (now - lastlog) >= period ) {
|
||||||
console.log('µBlock > %s: %s ms (%d samples)', prompt, avg().toFixed(3), count);
|
console.log('µBlock> %s: %s ms (%d samples)', prompt, avg().toFixed(3), count);
|
||||||
lastlog = now;
|
lastlog = now;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
60
js/start.js
60
js/start.js
@ -31,36 +31,76 @@
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var µb = µBlock;
|
var µb = µBlock;
|
||||||
var bufferTime = 0 * 60 * 1000;
|
|
||||||
var exports = {};
|
|
||||||
|
|
||||||
var jobCallback = function() {
|
var jobCallback = function() {
|
||||||
|
// Simpler to fire restart here, and safe given how far this will happen
|
||||||
|
// in the future.
|
||||||
|
restart();
|
||||||
|
|
||||||
|
// If auto-update is disabled, check again in a while.
|
||||||
if ( µb.userSettings.autoUpdate !== true ) {
|
if ( µb.userSettings.autoUpdate !== true ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO: need smarter update, currently blindly reloading all.
|
|
||||||
µb.loadUpdatableAssets(true);
|
var onMetadataReady = function(metadata) {
|
||||||
|
// Check PSL
|
||||||
|
var mdEntry = metadata[µb.pslPath];
|
||||||
|
if ( mdEntry.repoObsolete ) {
|
||||||
|
// console.log('µBlock.updater> updating all updatable assets');
|
||||||
|
µb.loadUpdatableAssets({ update: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Check used filter lists
|
||||||
|
var lists = µb.remoteBlacklists;
|
||||||
|
for ( var path in lists ) {
|
||||||
|
if ( lists.hasOwnProperty(path) === false ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( lists[path].off ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( metadata.hasOwnProperty(path) === false ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mdEntry = metadata[path];
|
||||||
|
if ( mdEntry.cacheObsolete || mdEntry.repoObsolete ) {
|
||||||
|
// console.log('µBlock.updater> updating only filter lists');
|
||||||
|
µb.loadUpdatableAssets({ update: true, psl: false });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log('µBlock.updater> all is up to date');
|
||||||
|
};
|
||||||
|
|
||||||
|
µb.assets.metadata(onMetadataReady);
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://www.youtube.com/watch?v=cIrGQD84F1g
|
// https://www.youtube.com/watch?v=cIrGQD84F1g
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
exports.restart = function() {
|
var restart = function(after) {
|
||||||
|
if ( after === undefined ) {
|
||||||
|
after = µb.nextUpdateAfter;
|
||||||
|
}
|
||||||
|
|
||||||
µb.asyncJobs.add(
|
µb.asyncJobs.add(
|
||||||
'autoUpdateAssets',
|
'autoUpdateAssets',
|
||||||
null,
|
null,
|
||||||
jobCallback,
|
jobCallback,
|
||||||
µb.updateAssetsEvery - bufferTime,
|
after,
|
||||||
true
|
false
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.restart();
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
return exports;
|
return {
|
||||||
|
restart: restart
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
220
js/storage.js
220
js/storage.js
@ -139,12 +139,18 @@
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.appendUserFilters = function(content) {
|
µBlock.appendUserFilters = function(content) {
|
||||||
|
var µb = this;
|
||||||
|
|
||||||
|
var onFiltersReady = function() {
|
||||||
|
};
|
||||||
|
|
||||||
var onSaved = function(details) {
|
var onSaved = function(details) {
|
||||||
if ( details.error ) {
|
if ( details.error ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
µBlock.loadUbiquitousBlacklists();
|
µb.loadFilterLists(onFiltersReady);
|
||||||
};
|
};
|
||||||
|
|
||||||
var onLoaded = function(details) {
|
var onLoaded = function(details) {
|
||||||
if ( details.error ) {
|
if ( details.error ) {
|
||||||
return;
|
return;
|
||||||
@ -152,8 +158,9 @@
|
|||||||
if ( details.content.indexOf(content.trim()) !== -1 ) {
|
if ( details.content.indexOf(content.trim()) !== -1 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
µBlock.saveUserFilters(details.content + '\n' + content, onSaved);
|
µb.saveUserFilters(details.content + '\n' + content, onSaved);
|
||||||
};
|
};
|
||||||
|
|
||||||
if ( content.length > 0 ) {
|
if ( content.length > 0 ) {
|
||||||
this.loadUserFilters(onLoaded);
|
this.loadUserFilters(onLoaded);
|
||||||
}
|
}
|
||||||
@ -256,15 +263,21 @@
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.loadUbiquitousBlacklists = function() {
|
µBlock.loadFilterLists = function(callback) {
|
||||||
var µb = this;
|
var µb = this;
|
||||||
var blacklistLoadCount;
|
var blacklistLoadCount;
|
||||||
|
|
||||||
|
if ( typeof callback !== 'function' ) {
|
||||||
|
callback = this.noopFunc;
|
||||||
|
}
|
||||||
|
|
||||||
var loadBlacklistsEnd = function() {
|
var loadBlacklistsEnd = function() {
|
||||||
µb.abpFilters.freeze();
|
µb.netFilteringEngine.freeze();
|
||||||
µb.abpHideFilters.freeze();
|
µb.cosmeticFilteringEngine.freeze();
|
||||||
µb.messaging.announce({ what: 'loadUbiquitousBlacklistCompleted' });
|
|
||||||
chrome.storage.local.set({ 'remoteBlacklists': µb.remoteBlacklists });
|
chrome.storage.local.set({ 'remoteBlacklists': µb.remoteBlacklists });
|
||||||
|
µb.messaging.announce({ what: 'loadUbiquitousBlacklistCompleted' });
|
||||||
|
µb.toSelfieAsync();
|
||||||
|
callback();
|
||||||
};
|
};
|
||||||
|
|
||||||
var mergeBlacklist = function(details) {
|
var mergeBlacklist = function(details) {
|
||||||
@ -277,10 +290,9 @@
|
|||||||
|
|
||||||
var loadBlacklistsStart = function(lists) {
|
var loadBlacklistsStart = function(lists) {
|
||||||
µb.remoteBlacklists = lists;
|
µb.remoteBlacklists = lists;
|
||||||
|
µb.netFilteringEngine.reset();
|
||||||
// rhill 2013-12-10: set all existing entries to `false`.
|
µb.cosmeticFilteringEngine.reset();
|
||||||
µb.abpFilters.reset();
|
µb.destroySelfie();
|
||||||
µb.abpHideFilters.reset();
|
|
||||||
var locations = Object.keys(lists);
|
var locations = Object.keys(lists);
|
||||||
blacklistLoadCount = locations.length;
|
blacklistLoadCount = locations.length;
|
||||||
if ( blacklistLoadCount === 0 ) {
|
if ( blacklistLoadCount === 0 ) {
|
||||||
@ -322,11 +334,11 @@
|
|||||||
// Useful references:
|
// Useful references:
|
||||||
// https://adblockplus.org/en/filter-cheatsheet
|
// https://adblockplus.org/en/filter-cheatsheet
|
||||||
// https://adblockplus.org/en/filters
|
// https://adblockplus.org/en/filters
|
||||||
var abpFilters = this.abpFilters;
|
var netFilteringEngine = this.netFilteringEngine;
|
||||||
var abpHideFilters = this.abpHideFilters;
|
var cosmeticFilteringEngine = this.cosmeticFilteringEngine;
|
||||||
var parseCosmeticFilters = this.userSettings.parseAllABPHideFilters;
|
var parseCosmeticFilters = this.userSettings.parseAllABPHideFilters;
|
||||||
var duplicateCount = abpFilters.duplicateCount + abpHideFilters.duplicateCount;
|
var duplicateCount = netFilteringEngine.duplicateCount + cosmeticFilteringEngine.duplicateCount;
|
||||||
var acceptedCount = abpFilters.acceptedCount + abpHideFilters.acceptedCount;
|
var acceptedCount = netFilteringEngine.acceptedCount + cosmeticFilteringEngine.acceptedCount;
|
||||||
var reLocalhost = /(^|\s)(localhost\.localdomain|localhost|local|broadcasthost|0\.0\.0\.0|127\.0\.0\.1|::1|fe80::1%lo0)(?=\s|$)/g;
|
var reLocalhost = /(^|\s)(localhost\.localdomain|localhost|local|broadcasthost|0\.0\.0\.0|127\.0\.0\.1|::1|fe80::1%lo0)(?=\s|$)/g;
|
||||||
var reAdblockFilter = /^[^a-z0-9:]|[^a-z0-9]$|[^a-z0-9_:.-]/;
|
var reAdblockFilter = /^[^a-z0-9:]|[^a-z0-9]$|[^a-z0-9_:.-]/;
|
||||||
var reAdblockHostFilter = /^\|\|([a-z0-9.-]+[a-z0-9])\^?$/;
|
var reAdblockHostFilter = /^\|\|([a-z0-9.-]+[a-z0-9])\^?$/;
|
||||||
@ -360,7 +372,7 @@
|
|||||||
// 2014-05-18: ABP element hide filters are allowed to contain space
|
// 2014-05-18: ABP element hide filters are allowed to contain space
|
||||||
// characters
|
// characters
|
||||||
if ( parseCosmeticFilters ) {
|
if ( parseCosmeticFilters ) {
|
||||||
if ( abpHideFilters.add(line) ) {
|
if ( cosmeticFilteringEngine.add(line) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -396,7 +408,7 @@
|
|||||||
|
|
||||||
// Likely an ABP net filter?
|
// Likely an ABP net filter?
|
||||||
if ( reAdblockFilter.test(line) ) {
|
if ( reAdblockFilter.test(line) ) {
|
||||||
if ( abpFilters.add(line) ) {
|
if ( netFilteringEngine.add(line) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// rhill 2014-01-22: Transpose possible Adblock Plus-filter syntax
|
// rhill 2014-01-22: Transpose possible Adblock Plus-filter syntax
|
||||||
@ -412,13 +424,13 @@
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
abpFilters.addAnyPartyHostname(line);
|
netFilteringEngine.addAnyPartyHostname(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For convenience, store the number of entries for this
|
// For convenience, store the number of entries for this
|
||||||
// blacklist, user might be happy to know this information.
|
// blacklist, user might be happy to know this information.
|
||||||
duplicateCount = abpFilters.duplicateCount + abpHideFilters.duplicateCount - duplicateCount;
|
duplicateCount = netFilteringEngine.duplicateCount + cosmeticFilteringEngine.duplicateCount - duplicateCount;
|
||||||
acceptedCount = abpFilters.acceptedCount + abpHideFilters.acceptedCount - acceptedCount;
|
acceptedCount = netFilteringEngine.acceptedCount + cosmeticFilteringEngine.acceptedCount - acceptedCount;
|
||||||
|
|
||||||
this.remoteBlacklists[details.path].entryCount = acceptedCount + duplicateCount;
|
this.remoteBlacklists[details.path].entryCount = acceptedCount + duplicateCount;
|
||||||
this.remoteBlacklists[details.path].entryUsedCount = acceptedCount;
|
this.remoteBlacklists[details.path].entryUsedCount = acceptedCount;
|
||||||
@ -449,66 +461,192 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now force reload
|
// Now force reload
|
||||||
this.loadUpdatableAssets(update);
|
this.loadUpdatableAssets({ update: update, psl: update });
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.loadPublicSuffixList = function(callback) {
|
µBlock.loadPublicSuffixList = function(callback) {
|
||||||
|
if ( typeof callback !== 'function' ) {
|
||||||
|
callback = this.noopFunc;
|
||||||
|
}
|
||||||
var applyPublicSuffixList = function(details) {
|
var applyPublicSuffixList = function(details) {
|
||||||
// TODO: Not getting proper suffix list is a bit serious, I think
|
// TODO: Not getting proper suffix list is a bit serious, I think
|
||||||
// the extension should be force-restarted if it occurs..
|
// the extension should be force-restarted if it occurs..
|
||||||
if ( !details.error ) {
|
if ( !details.error ) {
|
||||||
publicSuffixList.parse(details.content, punycode.toASCII);
|
publicSuffixList.parse(details.content, punycode.toASCII);
|
||||||
}
|
}
|
||||||
if ( typeof callback === 'function' ) {
|
callback();
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
this.assets.get(
|
this.assets.get(this.pslPath, applyPublicSuffixList);
|
||||||
'assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat',
|
|
||||||
applyPublicSuffixList
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// Load updatable assets
|
// Load updatable assets
|
||||||
|
|
||||||
µBlock.loadUpdatableAssets = function(update) {
|
µBlock.loadUpdatableAssets = function(details) {
|
||||||
|
var µb = this;
|
||||||
|
|
||||||
|
details = details || {};
|
||||||
|
var update = details.update !== false;
|
||||||
|
|
||||||
this.assets.autoUpdate = update || this.userSettings.autoUpdate;
|
this.assets.autoUpdate = update || this.userSettings.autoUpdate;
|
||||||
this.assets.autoUpdateDelay = this.updateAssetsEvery;
|
this.assets.autoUpdateDelay = this.updateAssetsEvery;
|
||||||
this.loadPublicSuffixList();
|
|
||||||
this.loadUbiquitousBlacklists();
|
|
||||||
|
|
||||||
// It could be a manual update, so we reset the auto-updater
|
var onFiltersReady = function() {
|
||||||
if ( update ) {
|
if ( update ) {
|
||||||
this.updater.restart();
|
µb.updater.restart();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var onPSLReady = function() {
|
||||||
|
µb.loadFilterLists(onFiltersReady);
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( details.psl !== false ) {
|
||||||
|
this.loadPublicSuffixList(onPSLReady);
|
||||||
|
} else {
|
||||||
|
this.loadFilterLists(onFiltersReady);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
µBlock.toSelfie = function() {
|
||||||
|
var selfie = {
|
||||||
|
magic: this.selfieMagic,
|
||||||
|
publicSuffixList: publicSuffixList.toSelfie(),
|
||||||
|
filterLists: this.remoteBlacklists,
|
||||||
|
netFilteringEngine: this.netFilteringEngine.toSelfie(),
|
||||||
|
cosmeticFilteringEngine: this.cosmeticFilteringEngine.toSelfie(),
|
||||||
|
};
|
||||||
|
chrome.storage.local.set({ selfie: selfie });
|
||||||
|
// console.log('µBlock.toSelfie> made a selfie!');
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is to be sure the selfie is generated in a sane manner: the selfie will
|
||||||
|
// be generated if the user doesn't change his filter lists selection for
|
||||||
|
// some set time.
|
||||||
|
µBlock.toSelfieAsync = function(after) {
|
||||||
|
if ( typeof after !== 'number' ) {
|
||||||
|
after = this.selfieAfter;
|
||||||
|
}
|
||||||
|
this.asyncJobs.add(
|
||||||
|
'toSelfie',
|
||||||
|
null,
|
||||||
|
this.toSelfie.bind(this),
|
||||||
|
after,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
µBlock.fromSelfie = function(callback) {
|
||||||
|
var µb = this;
|
||||||
|
|
||||||
|
if ( typeof callback !== 'function' ) {
|
||||||
|
callback = this.noopFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
var onSelfieReady = function(store) {
|
||||||
|
var selfie = store.selfie;
|
||||||
|
if ( typeof selfie !== 'object' || selfie.magic !== µb.selfieMagic ) {
|
||||||
|
callback(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( publicSuffixList.fromSelfie(selfie.publicSuffixList) !== true ) {
|
||||||
|
callback(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// console.log('µBlock.fromSelfie> selfie looks good');
|
||||||
|
µb.remoteBlacklists = selfie.filterLists;
|
||||||
|
µb.netFilteringEngine.fromSelfie(selfie.netFilteringEngine);
|
||||||
|
µb.cosmeticFilteringEngine.fromSelfie(selfie.cosmeticFilteringEngine);
|
||||||
|
callback(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
chrome.storage.local.get('selfie', onSelfieReady);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
µBlock.destroySelfie = function() {
|
||||||
|
chrome.storage.local.remove('selfie');
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
// Load all
|
// Load all
|
||||||
|
|
||||||
µBlock.load = function() {
|
µBlock.load = function() {
|
||||||
var µb = this;
|
var µb = this;
|
||||||
|
|
||||||
// User whitelist directives and filters need the Public Suffix List to be
|
// Final initialization steps after all needed assets are in memory
|
||||||
// available -- because the way they are stored internally.
|
var onAllDone = function(wasAutoUpdated) {
|
||||||
|
// Initialize internal state with maybe already existing tabs
|
||||||
|
var bindToTabs = function(tabs) {
|
||||||
|
var scriptStart = function(tabId) {
|
||||||
|
var scriptEnd = function() {
|
||||||
|
chrome.tabs.executeScript(tabId, {
|
||||||
|
file: 'js/contentscript-end.js',
|
||||||
|
allFrames: true,
|
||||||
|
runAt: 'document_idle'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
chrome.tabs.executeScript(tabId, {
|
||||||
|
file: 'js/contentscript-start.js',
|
||||||
|
allFrames: true,
|
||||||
|
runAt: 'document_idle'
|
||||||
|
}, scriptEnd);
|
||||||
|
};
|
||||||
|
var i = tabs.length, tab;
|
||||||
|
while ( i-- ) {
|
||||||
|
tab = tabs[i];
|
||||||
|
µb.bindTabToPageStats(tab.id, tab.url);
|
||||||
|
// https://github.com/gorhill/uBlock/issues/129
|
||||||
|
scriptStart(tab.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
chrome.tabs.query({ url: 'http://*/*' }, bindToTabs);
|
||||||
|
chrome.tabs.query({ url: 'https://*/*' }, bindToTabs);
|
||||||
|
|
||||||
|
// https://github.com/gorhill/uBlock/issues/184
|
||||||
|
// If we restored a selfie, check for updates not too far
|
||||||
|
// in the future.
|
||||||
|
µb.updater.restart(wasAutoUpdated ? µb.nextUpdateAfter : µb.firstUpdateAfter);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Filters are in memory
|
||||||
|
var onFiltersReady = function() {
|
||||||
|
onAllDone(µb.userSettings.autoUpdate);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load order because dependencies:
|
||||||
|
// User settings -> PSL -> [filter lists, user whitelist]
|
||||||
var onPSLReady = function() {
|
var onPSLReady = function() {
|
||||||
µb.loadWhitelist();
|
µb.loadWhitelist();
|
||||||
µb.loadUbiquitousBlacklists();
|
µb.loadFilterLists(onFiltersReady);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Public Suffix List loader needs the user settings need to be available
|
// If no selfie available, take the long way, i.e. load and parse
|
||||||
// because we need to know whether to auto-update the list or not.
|
// raw data.
|
||||||
var onUserSettingsReady = function() {
|
var onSelfieReady = function(success) {
|
||||||
µb.assets.autoUpdate = µb.userSettings.autoUpdate || true;
|
if ( success === true ) {
|
||||||
|
onAllDone(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
µb.assets.autoUpdate = µb.userSettings.autoUpdate;
|
||||||
µb.loadPublicSuffixList(onPSLReady);
|
µb.loadPublicSuffixList(onPSLReady);
|
||||||
};
|
};
|
||||||
this.loadUserSettings(onUserSettingsReady);
|
|
||||||
|
|
||||||
|
// User settings are in memory
|
||||||
|
var onUserSettingsReady = function() {
|
||||||
|
µb.fromSelfie(onSelfieReady);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.loadUserSettings(onUserSettingsReady);
|
||||||
this.loadLocalSettings();
|
this.loadLocalSettings();
|
||||||
this.getBytesInUse();
|
this.getBytesInUse();
|
||||||
};
|
};
|
||||||
|
35
js/tab.js
35
js/tab.js
@ -59,41 +59,6 @@
|
|||||||
chrome.tabs.onRemoved.addListener(onTabRemoved);
|
chrome.tabs.onRemoved.addListener(onTabRemoved);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// Initialize internal state with maybe already existing tabs
|
|
||||||
// This needs to be executed once, hence it has its own scope, which will
|
|
||||||
// allow the code to be flushed once completed.
|
|
||||||
|
|
||||||
(function(){
|
|
||||||
var µb = µBlock;
|
|
||||||
var bindToTabs = function(tabs) {
|
|
||||||
var scriptStart = function(tabId) {
|
|
||||||
var scriptEnd = function() {
|
|
||||||
chrome.tabs.executeScript(tabId, {
|
|
||||||
file: 'js/contentscript-end.js',
|
|
||||||
allFrames: true,
|
|
||||||
runAt: 'document_idle'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
chrome.tabs.executeScript(tabId, {
|
|
||||||
file: 'js/contentscript-start.js',
|
|
||||||
allFrames: true,
|
|
||||||
runAt: 'document_idle'
|
|
||||||
}, scriptEnd);
|
|
||||||
};
|
|
||||||
var i = tabs.length, tab;
|
|
||||||
while ( i-- ) {
|
|
||||||
tab = tabs[i];
|
|
||||||
µb.bindTabToPageStats(tab.id, tab.url);
|
|
||||||
// https://github.com/gorhill/uBlock/issues/129
|
|
||||||
scriptStart(tab.id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
chrome.tabs.query({ url: 'http://*/*' }, bindToTabs);
|
|
||||||
chrome.tabs.query({ url: 'https://*/*' }, bindToTabs);
|
|
||||||
})();
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ var onBeforeRequest = function(details) {
|
|||||||
|
|
||||||
var reason = false;
|
var reason = false;
|
||||||
if ( pageStore.getNetFilteringSwitch() ) {
|
if ( pageStore.getNetFilteringSwitch() ) {
|
||||||
reason = µb.abpFilters.matchString(requestContext, requestURL, requestType, requestHostname);
|
reason = µb.netFilteringEngine.matchString(requestContext, requestURL, requestType, requestHostname);
|
||||||
}
|
}
|
||||||
// Record what happened.
|
// Record what happened.
|
||||||
pageStore.recordRequest(requestType, requestURL, reason);
|
pageStore.recordRequest(requestType, requestURL, reason);
|
||||||
@ -168,7 +168,7 @@ var onBeforeSendHeaders = function(details) {
|
|||||||
// in multiple tabs.
|
// in multiple tabs.
|
||||||
var reason = false;
|
var reason = false;
|
||||||
if ( pageStore.getNetFilteringSwitch() ) {
|
if ( pageStore.getNetFilteringSwitch() ) {
|
||||||
reason = µb.abpFilters.matchStringExactType(
|
reason = µb.netFilteringEngine.matchStringExactType(
|
||||||
pageDetails,
|
pageDetails,
|
||||||
requestURL,
|
requestURL,
|
||||||
'popup',
|
'popup',
|
||||||
|
32
lib/publicsuffixlist.min.js
vendored
32
lib/publicsuffixlist.min.js
vendored
@ -1,17 +1,17 @@
|
|||||||
/*! Home: https://github.com/gorhill/publicsuffixlist.js */
|
/*! Home: https://github.com/gorhill/publicsuffixlist.js */
|
||||||
;(function(f){var b={};var h={};var a=480;
|
/* Minified using http://refresh-sf.com/yui/ */
|
||||||
var g=/[^a-z0-9.-]/;function i(k){if(!k||k.charAt(0)==="."){return""}k=k.toLowerCase();var l=c(k);if(l===k){return""
|
;(function(i){var d={};var k={};var g="iscjsfsaolnm";var b=480;
|
||||||
}var m=k.lastIndexOf(".",k.lastIndexOf(".",k.length-l.length)-1);if(m<=0){return k}return k.slice(m+1)
|
var j=/[^a-z0-9.-]/;function l(n){if(!n||n.charAt(0)==="."){return""}n=n.toLowerCase();var o=e(n);if(o===n){return""}var p=n.lastIndexOf(".",n.lastIndexOf(".",n.length-o.length)-1);
|
||||||
}function c(k){if(!k){return""}var l;while(true){l=k.indexOf(".");if(l<0){return k}if(j(b,k)){return k.slice(l+1)
|
if(p<=0){return n}return n.slice(p+1)}function e(n){if(!n){return""}var o;while(true){o=n.indexOf(".");if(o<0){return n}if(m(d,n)){return n.slice(o+1)
|
||||||
}if(j(h,k)){return k}if(j(h,"*"+k.slice(l))){return k}k=k.slice(l+1)}}function j(t,r){var q=r.lastIndexOf(".");
|
}if(m(k,n)){return n}if(m(k,"*"+n.slice(o))){return n}n=n.slice(o+1)}}function m(v,t){var s=t.lastIndexOf(".");var o,x;if(s<0){o=t;
|
||||||
var m,v;if(q<0){m=r;v=r}else{m=r.slice(q+1);v=r.slice(0,q)}var s=t[m];if(!s){return false}if(typeof s==="string"){return s.indexOf(" "+v+" ")>=0
|
x=t}else{o=t.slice(s+1);x=t.slice(0,s)}var u=v[o];if(!u){return false}if(typeof u==="string"){return u.indexOf(" "+x+" ")>=0
|
||||||
}var n=v.length;var w=s[n];if(!w){return false}var k=0;var u=Math.floor(w.length/n+0.5);var p,o;while(k<u){p=k+u>>1;
|
}var p=x.length;var y=u[p];if(!y){return false}var n=0;var w=Math.floor(y.length/p+0.5);var r,q;while(n<w){r=n+w>>1;q=y.substr(p*r,p);
|
||||||
o=w.substr(n*p,n);if(v<o){u=p}else{if(v>o){k=p+1}else{return true}}}return false}function d(r,p){b={};
|
if(x<q){w=r}else{if(x>q){n=r+1}else{return true}}}return false}function f(u,s){d={};k={};u=u.toLowerCase();var r=0,o;var p=u.length;
|
||||||
h={};r=r.toLowerCase();var o=0,l;var m=r.length;var s,q,n,k;while(o<m){l=r.indexOf("\n",o);if(l<0){l=m
|
var v,t,q,n;while(r<p){o=u.indexOf("\n",r);if(o<0){o=u.indexOf("\r",r);if(o<0){o=p}}v=u.slice(r,o).trim();r=o+1;if(v.length===0){continue
|
||||||
}s=r.slice(o,l);o=l+1;if(s.length===0){continue}n=s.indexOf("//");if(n>=0){s=s.slice(0,n)}s=s.trim();
|
}q=v.indexOf("//");if(q>=0){v=v.slice(0,q)}v=v.trim();if(!v){continue}if(j.test(v)){v=s(v)}if(v.charAt(0)==="!"){t=d;v=v.slice(1)
|
||||||
if(!s){continue}if(g.test(s)){s=p(s)}if(s.charAt(0)==="!"){q=b;s=s.slice(1)}else{q=h}n=s.lastIndexOf(".");
|
}else{t=k}q=v.lastIndexOf(".");if(q<0){n=v}else{n=v.slice(q+1);v=v.slice(0,q)}if(!t.hasOwnProperty(n)){t[n]=[]}if(v){t[n].push(v)
|
||||||
if(n<0){k=s}else{k=s.slice(n+1);s=s.slice(0,n)}if(!q[k]){q[k]=[]}if(s){q[k].push(s)}}e(b);e(h)}function e(m){var o,q,p,k;
|
}}h(d);h(k)}function h(o){var q,s,r,n;for(var p in o){if(!o.hasOwnProperty(p)){continue}q=o[p].join(" ");if(!q){o[p]="";continue
|
||||||
for(var n in m){if(!m.hasOwnProperty(n)){continue}o=m[n].join(" ");if(!o){m[n]="";continue}if(o.length<a){m[n]=" "+o+" ";
|
}if(q.length<b){o[p]=" "+q+" ";continue}r=o[p].length;q=[];while(r--){s=o[p][r];n=s.length;if(!q[n]){q[n]=[]}q[n].push(s)
|
||||||
continue}p=m[n].length;o=[];while(p--){q=m[n][p];k=q.length;if(!o[k]){o[k]=[]}o[k].push(q)}k=o.length;
|
}n=q.length;while(n--){if(q[n]){q[n]=q[n].sort().join("")}}o[p]=q}return o}function c(){return{magic:g,rules:k,exceptions:d}
|
||||||
while(k--){if(o[k]){o[k]=o[k].sort().join("")}}m[n]=o}return m}f.publicSuffixList={version:"1.0",parse:d,getDomain:i,getPublicSuffix:c}
|
}function a(n){if(typeof n!=="object"||typeof n.magic!=="string"||n.magic!==g){return false}k=n.rules;d=n.exceptions;return true
|
||||||
})(this);
|
}i=i||window;i.publicSuffixList={version:"1.0",parse:f,getDomain:l,getPublicSuffix:e,toSelfie:c,fromSelfie:a}})(this);
|
Loading…
Reference in New Issue
Block a user