mirror of
https://github.com/gorhill/uBlock.git
synced 2024-10-06 09:37:12 +02:00
parent
ae15aca35f
commit
c7bab5502e
@ -2,7 +2,7 @@
|
|||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
|
|
||||||
"name": "µBlock",
|
"name": "µBlock",
|
||||||
"version": "0.8.8.4",
|
"version": "0.8.8.5",
|
||||||
|
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"description": "__MSG_extShortDesc__",
|
"description": "__MSG_extShortDesc__",
|
||||||
|
@ -43,7 +43,7 @@ var re3rdPartyExternalAsset = /^https?:\/\/[a-z0-9]+/;
|
|||||||
|
|
||||||
var onMessage = function(msg) {
|
var onMessage = function(msg) {
|
||||||
switch ( msg.what ) {
|
switch ( msg.what ) {
|
||||||
case 'loadUbiquitousBlacklistCompleted':
|
case 'allFilterListsReloaded':
|
||||||
renderBlacklists();
|
renderBlacklists();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
157
src/js/assets.js
157
src/js/assets.js
@ -57,6 +57,7 @@ var thirdpartiesRepositoryRoot = 'https://raw.githubusercontent.com/gorhill/uAss
|
|||||||
var nullFunc = function() {};
|
var nullFunc = function() {};
|
||||||
var reIsExternalPath = /^[a-z]+:\/\//;
|
var reIsExternalPath = /^[a-z]+:\/\//;
|
||||||
var reIsUserPath = /^assets\/user\//;
|
var reIsUserPath = /^assets\/user\//;
|
||||||
|
var reIsCachePath = /^cache:\/\//;
|
||||||
var lastRepoMetaTimestamp = 0;
|
var lastRepoMetaTimestamp = 0;
|
||||||
var lastRepoMetaIsRemote = false;
|
var lastRepoMetaIsRemote = false;
|
||||||
var refreshRepoMetaPeriod = 5 * oneHour;
|
var refreshRepoMetaPeriod = 5 * oneHour;
|
||||||
@ -197,17 +198,26 @@ var cachedAssetsManager = (function() {
|
|||||||
var cachedContentPath = cachedAssetPathPrefix + path;
|
var cachedContentPath = cachedAssetPathPrefix + path;
|
||||||
var bin = {};
|
var bin = {};
|
||||||
bin[cachedContentPath] = content;
|
bin[cachedContentPath] = content;
|
||||||
|
var removedItems = [];
|
||||||
var onSaved = function() {
|
var onSaved = function() {
|
||||||
var lastError = vAPI.lastError();
|
var lastError = vAPI.lastError();
|
||||||
if ( lastError ) {
|
if ( lastError ) {
|
||||||
details.error = 'Error: ' + lastError.message;
|
details.error = 'Error: ' + lastError.message;
|
||||||
console.error('µBlock> cachedAssetsManager.save():', details.error);
|
console.error('µBlock> cachedAssetsManager.save():', details.error);
|
||||||
cbError(details);
|
cbError(details);
|
||||||
} else {
|
return;
|
||||||
cbSuccess(details);
|
|
||||||
}
|
}
|
||||||
|
// Saving over an existing item must be seen as removing an
|
||||||
|
// existing item and adding a new one.
|
||||||
|
if ( typeof exports.onRemovedListener === 'function' ) {
|
||||||
|
exports.onRemovedListener(removedItems);
|
||||||
|
}
|
||||||
|
cbSuccess(details);
|
||||||
};
|
};
|
||||||
var onEntries = function(entries) {
|
var onEntries = function(entries) {
|
||||||
|
if ( entries.hasOwnProperty(path) ) {
|
||||||
|
removedItems.push(path);
|
||||||
|
}
|
||||||
entries[path] = Date.now();
|
entries[path] = Date.now();
|
||||||
bin.cached_asset_entries = entries;
|
bin.cached_asset_entries = entries;
|
||||||
vAPI.storage.set(bin, onSaved);
|
vAPI.storage.set(bin, onSaved);
|
||||||
@ -218,6 +228,7 @@ var cachedAssetsManager = (function() {
|
|||||||
exports.remove = function(pattern, before) {
|
exports.remove = function(pattern, before) {
|
||||||
var onEntries = function(entries) {
|
var onEntries = function(entries) {
|
||||||
var keystoRemove = [];
|
var keystoRemove = [];
|
||||||
|
var removedItems = [];
|
||||||
var paths = Object.keys(entries);
|
var paths = Object.keys(entries);
|
||||||
var i = paths.length;
|
var i = paths.length;
|
||||||
var path;
|
var path;
|
||||||
@ -232,12 +243,16 @@ var cachedAssetsManager = (function() {
|
|||||||
if ( typeof before === 'number' && entries[path] >= before ) {
|
if ( typeof before === 'number' && entries[path] >= before ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
removedItems.push(path);
|
||||||
keystoRemove.push(cachedAssetPathPrefix + path);
|
keystoRemove.push(cachedAssetPathPrefix + path);
|
||||||
delete entries[path];
|
delete entries[path];
|
||||||
}
|
}
|
||||||
if ( keystoRemove.length ) {
|
if ( keystoRemove.length ) {
|
||||||
vAPI.storage.remove(keystoRemove);
|
vAPI.storage.remove(keystoRemove);
|
||||||
vAPI.storage.set({ 'cached_asset_entries': entries });
|
vAPI.storage.set({ 'cached_asset_entries': entries });
|
||||||
|
if ( typeof exports.onRemovedListener === 'function' ) {
|
||||||
|
exports.onRemovedListener(removedItems);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
getEntries(onEntries);
|
getEntries(onEntries);
|
||||||
@ -245,8 +260,10 @@ var cachedAssetsManager = (function() {
|
|||||||
|
|
||||||
exports.removeAll = function(callback) {
|
exports.removeAll = function(callback) {
|
||||||
var onEntries = function() {
|
var onEntries = function() {
|
||||||
|
// Careful! do not remove 'assets/user/'
|
||||||
exports.remove(/^https?:\/\/[a-z0-9]+/);
|
exports.remove(/^https?:\/\/[a-z0-9]+/);
|
||||||
exports.remove(/^assets\/(ublock|thirdparties)\//);
|
exports.remove(/^assets\/(ublock|thirdparties)\//);
|
||||||
|
exports.remove(/^cache:\/\//);
|
||||||
exports.remove('assets/checksums.txt');
|
exports.remove('assets/checksums.txt');
|
||||||
if ( typeof callback === 'function' ) {
|
if ( typeof callback === 'function' ) {
|
||||||
callback(null);
|
callback(null);
|
||||||
@ -255,6 +272,8 @@ var cachedAssetsManager = (function() {
|
|||||||
getEntries(onEntries);
|
getEntries(onEntries);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.onRemovedListener = null;
|
||||||
|
|
||||||
return exports;
|
return exports;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
@ -263,15 +282,18 @@ var cachedAssetsManager = (function() {
|
|||||||
var getTextFileFromURL = function(url, onLoad, onError) {
|
var getTextFileFromURL = function(url, onLoad, onError) {
|
||||||
// https://github.com/gorhill/uMatrix/issues/15
|
// https://github.com/gorhill/uMatrix/issues/15
|
||||||
var onResponseReceived = function() {
|
var onResponseReceived = function() {
|
||||||
if ( this.status !== 0 && ( this.status < 200 || this.status >= 300 ) ) {
|
this.onload = this.onerror = this.ontimeout = null;
|
||||||
|
// xhr for local files gives status 0, but actually succeeds
|
||||||
|
var status = this.status || 200;
|
||||||
|
if ( status < 200 || status >= 300 ) {
|
||||||
return onError.call(this);
|
return onError.call(this);
|
||||||
}
|
}
|
||||||
// xhr for local files gives status 0, but actually succeeds
|
// consider an empty result to be an error
|
||||||
if ( this.status === 0 && stringIsNotEmpty(this.responseText) === false ) {
|
if ( stringIsNotEmpty(this.responseText) === false ) {
|
||||||
return onError.call(this);
|
return onError.call(this);
|
||||||
}
|
}
|
||||||
// we never download anything else than plain text: discard if response
|
// we never download anything else than plain text: discard if response
|
||||||
// appears to be a HTML document: could happen when server returns
|
// appears to be a HTML document: could happen when server serves
|
||||||
// some kind of error page I suppose
|
// some kind of error page I suppose
|
||||||
var text = this.responseText.trim();
|
var text = this.responseText.trim();
|
||||||
if ( text.charAt(0) === '<' && text.slice(-1) === '>' ) {
|
if ( text.charAt(0) === '<' && text.slice(-1) === '>' ) {
|
||||||
@ -279,15 +301,23 @@ var getTextFileFromURL = function(url, onLoad, onError) {
|
|||||||
}
|
}
|
||||||
return onLoad.call(this);
|
return onLoad.call(this);
|
||||||
};
|
};
|
||||||
|
var onErrorReceived = function() {
|
||||||
|
this.onload = this.onerror = this.ontimeout = null;
|
||||||
|
onError.call(this);
|
||||||
|
};
|
||||||
// console.log('µBlock> getTextFileFromURL("%s"):', url);
|
// console.log('µBlock> getTextFileFromURL("%s"):', url);
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.open('get', url, true);
|
try {
|
||||||
xhr.timeout = 30000;
|
xhr.open('get', url, true);
|
||||||
xhr.onload = onResponseReceived;
|
xhr.timeout = 30000;
|
||||||
xhr.onerror = onError;
|
xhr.onload = onResponseReceived;
|
||||||
xhr.ontimeout = onError;
|
xhr.onerror = onErrorReceived;
|
||||||
xhr.responseType = 'text';
|
xhr.ontimeout = onErrorReceived;
|
||||||
xhr.send();
|
xhr.responseType = 'text';
|
||||||
|
xhr.send();
|
||||||
|
} catch (e) {
|
||||||
|
onErrorReceived.call(xhr);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -454,13 +484,11 @@ var readLocalFile = function(path, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var onInstallFileLoaded = function() {
|
var onInstallFileLoaded = function() {
|
||||||
this.onload = this.onerror = null;
|
|
||||||
//console.log('µBlock> readLocalFile("%s") / onInstallFileLoaded()', path);
|
//console.log('µBlock> readLocalFile("%s") / onInstallFileLoaded()', path);
|
||||||
reportBack(this.responseText);
|
reportBack(this.responseText);
|
||||||
};
|
};
|
||||||
|
|
||||||
var onInstallFileError = function() {
|
var onInstallFileError = function() {
|
||||||
this.onload = this.onerror = null;
|
|
||||||
console.error('µBlock> readLocalFile("%s") / onInstallFileError()', path);
|
console.error('µBlock> readLocalFile("%s") / onInstallFileError()', path);
|
||||||
reportBack('', 'Error');
|
reportBack('', 'Error');
|
||||||
};
|
};
|
||||||
@ -512,7 +540,6 @@ var readRepoFile = function(path, callback) {
|
|||||||
var repositoryURL = projectRepositoryRoot + path;
|
var repositoryURL = projectRepositoryRoot + path;
|
||||||
|
|
||||||
var onRepoFileLoaded = function() {
|
var onRepoFileLoaded = function() {
|
||||||
this.onload = this.onerror = null;
|
|
||||||
//console.log('µBlock> readRepoFile("%s") / onRepoFileLoaded()', path);
|
//console.log('µBlock> readRepoFile("%s") / onRepoFileLoaded()', path);
|
||||||
// https://github.com/gorhill/httpswitchboard/issues/263
|
// https://github.com/gorhill/httpswitchboard/issues/263
|
||||||
if ( this.status === 200 ) {
|
if ( this.status === 200 ) {
|
||||||
@ -523,7 +550,6 @@ var readRepoFile = function(path, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var onRepoFileError = function() {
|
var onRepoFileError = function() {
|
||||||
this.onload = this.onerror = null;
|
|
||||||
console.error(errorCantConnectTo.replace('{{url}}', repositoryURL));
|
console.error(errorCantConnectTo.replace('{{url}}', repositoryURL));
|
||||||
reportBack('', 'Error');
|
reportBack('', 'Error');
|
||||||
};
|
};
|
||||||
@ -568,13 +594,11 @@ var readRepoCopyAsset = function(path, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var onInstallFileLoaded = function() {
|
var onInstallFileLoaded = function() {
|
||||||
this.onload = this.onerror = null;
|
|
||||||
//console.log('µBlock> readRepoCopyAsset("%s") / onInstallFileLoaded()', path);
|
//console.log('µBlock> readRepoCopyAsset("%s") / onInstallFileLoaded()', path);
|
||||||
reportBack(this.responseText);
|
reportBack(this.responseText);
|
||||||
};
|
};
|
||||||
|
|
||||||
var onInstallFileError = function() {
|
var onInstallFileError = function() {
|
||||||
this.onload = this.onerror = null;
|
|
||||||
console.error('µBlock> readRepoCopyAsset("%s") / onInstallFileError():', path, this.statusText);
|
console.error('µBlock> readRepoCopyAsset("%s") / onInstallFileError():', path, this.statusText);
|
||||||
reportBack('', 'Error');
|
reportBack('', 'Error');
|
||||||
};
|
};
|
||||||
@ -593,7 +617,6 @@ var readRepoCopyAsset = function(path, callback) {
|
|||||||
var repositoryURLSkipCache = repositoryURL + '?ublock=' + Date.now();
|
var repositoryURLSkipCache = repositoryURL + '?ublock=' + Date.now();
|
||||||
|
|
||||||
var onRepoFileLoaded = function() {
|
var onRepoFileLoaded = function() {
|
||||||
this.onload = this.onerror = null;
|
|
||||||
if ( stringIsNotEmpty(this.responseText) === false ) {
|
if ( stringIsNotEmpty(this.responseText) === false ) {
|
||||||
console.error('µBlock> readRepoCopyAsset("%s") / onRepoFileLoaded("%s"): error', path, repositoryURL);
|
console.error('µBlock> readRepoCopyAsset("%s") / onRepoFileLoaded("%s"): error', path, repositoryURL);
|
||||||
cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError);
|
cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError);
|
||||||
@ -605,13 +628,11 @@ var readRepoCopyAsset = function(path, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var onRepoFileError = function() {
|
var onRepoFileError = function() {
|
||||||
this.onload = this.onerror = null;
|
|
||||||
console.error(errorCantConnectTo.replace('{{url}}', repositoryURL));
|
console.error(errorCantConnectTo.replace('{{url}}', repositoryURL));
|
||||||
cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError);
|
cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError);
|
||||||
};
|
};
|
||||||
|
|
||||||
var onHomeFileLoaded = function() {
|
var onHomeFileLoaded = function() {
|
||||||
this.onload = this.onerror = null;
|
|
||||||
if ( stringIsNotEmpty(this.responseText) === false ) {
|
if ( stringIsNotEmpty(this.responseText) === false ) {
|
||||||
console.error('µBlock> readRepoCopyAsset("%s") / onHomeFileLoaded("%s"): no response', path, homeURL);
|
console.error('µBlock> readRepoCopyAsset("%s") / onHomeFileLoaded("%s"): no response', path, homeURL);
|
||||||
// Fetch from repo only if obsolescence was due to repo checksum
|
// Fetch from repo only if obsolescence was due to repo checksum
|
||||||
@ -628,7 +649,6 @@ var readRepoCopyAsset = function(path, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var onHomeFileError = function() {
|
var onHomeFileError = function() {
|
||||||
this.onload = this.onerror = null;
|
|
||||||
console.error(errorCantConnectTo.replace('{{url}}', homeURL));
|
console.error(errorCantConnectTo.replace('{{url}}', homeURL));
|
||||||
// Fetch from repo only if obsolescence was due to repo checksum
|
// Fetch from repo only if obsolescence was due to repo checksum
|
||||||
if ( assetEntry.localChecksum !== assetEntry.repoChecksum ) {
|
if ( assetEntry.localChecksum !== assetEntry.repoChecksum ) {
|
||||||
@ -715,13 +735,11 @@ var readRepoOnlyAsset = function(path, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var onInstallFileLoaded = function() {
|
var onInstallFileLoaded = function() {
|
||||||
this.onload = this.onerror = null;
|
|
||||||
//console.log('µBlock> readRepoOnlyAsset("%s") / onInstallFileLoaded()', path);
|
//console.log('µBlock> readRepoOnlyAsset("%s") / onInstallFileLoaded()', path);
|
||||||
reportBack(this.responseText);
|
reportBack(this.responseText);
|
||||||
};
|
};
|
||||||
|
|
||||||
var onInstallFileError = function() {
|
var onInstallFileError = function() {
|
||||||
this.onload = this.onerror = null;
|
|
||||||
console.error('µBlock> readRepoOnlyAsset("%s") / onInstallFileError()', path);
|
console.error('µBlock> readRepoOnlyAsset("%s") / onInstallFileError()', path);
|
||||||
reportBack('', 'Error');
|
reportBack('', 'Error');
|
||||||
};
|
};
|
||||||
@ -739,7 +757,6 @@ var readRepoOnlyAsset = function(path, callback) {
|
|||||||
var repositoryURL = projectRepositoryRoot + path + '?ublock=' + Date.now();
|
var repositoryURL = projectRepositoryRoot + path + '?ublock=' + Date.now();
|
||||||
|
|
||||||
var onRepoFileLoaded = function() {
|
var onRepoFileLoaded = function() {
|
||||||
this.onload = this.onerror = null;
|
|
||||||
if ( typeof this.responseText !== 'string' ) {
|
if ( typeof this.responseText !== 'string' ) {
|
||||||
console.error('µBlock> readRepoOnlyAsset("%s") / onRepoFileLoaded("%s"): no response', path, repositoryURL);
|
console.error('µBlock> readRepoOnlyAsset("%s") / onRepoFileLoaded("%s"): no response', path, repositoryURL);
|
||||||
cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError);
|
cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError);
|
||||||
@ -757,7 +774,6 @@ var readRepoOnlyAsset = function(path, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var onRepoFileError = function() {
|
var onRepoFileError = function() {
|
||||||
this.onload = this.onerror = null;
|
|
||||||
console.error(errorCantConnectTo.replace('{{url}}', repositoryURL));
|
console.error(errorCantConnectTo.replace('{{url}}', repositoryURL));
|
||||||
cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError);
|
cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError);
|
||||||
};
|
};
|
||||||
@ -827,7 +843,6 @@ var readExternalAsset = function(path, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var onExternalFileLoaded = function() {
|
var onExternalFileLoaded = function() {
|
||||||
this.onload = this.onerror = null;
|
|
||||||
// https://github.com/gorhill/uBlock/issues/708
|
// https://github.com/gorhill/uBlock/issues/708
|
||||||
// A successful download should never return an empty file: turn this
|
// A successful download should never return an empty file: turn this
|
||||||
// into an error condition.
|
// into an error condition.
|
||||||
@ -841,7 +856,6 @@ var readExternalAsset = function(path, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var onExternalFileError = function() {
|
var onExternalFileError = function() {
|
||||||
this.onload = this.onerror = null;
|
|
||||||
console.error(errorCantConnectTo.replace('{{url}}', path));
|
console.error(errorCantConnectTo.replace('{{url}}', path));
|
||||||
cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError);
|
cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError);
|
||||||
};
|
};
|
||||||
@ -874,12 +888,33 @@ var readExternalAsset = function(path, callback) {
|
|||||||
|
|
||||||
var readUserAsset = function(path, callback) {
|
var readUserAsset = function(path, callback) {
|
||||||
var onCachedContentLoaded = function(details) {
|
var onCachedContentLoaded = function(details) {
|
||||||
//console.log('µBlock> readUserAsset("%s") / onCachedContentLoaded()', path);
|
//console.log('µBlock.assets/readUserAsset("%s")/onCachedContentLoaded()', path);
|
||||||
callback({ 'path': path, 'content': details.content });
|
callback({ 'path': path, 'content': details.content });
|
||||||
};
|
};
|
||||||
|
|
||||||
var onCachedContentError = function() {
|
var onCachedContentError = function() {
|
||||||
//console.log('µBlock> readUserAsset("%s") / onCachedContentError()', path);
|
//console.log('µBlock.assets/readUserAsset("%s")/onCachedContentError()', path);
|
||||||
|
callback({ 'path': path, 'content': '' });
|
||||||
|
};
|
||||||
|
|
||||||
|
cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// Asset available only from the cache.
|
||||||
|
// Cache data:
|
||||||
|
// Path --> starts with 'cache://'
|
||||||
|
// Cache --> whatever
|
||||||
|
|
||||||
|
var readCacheAsset = function(path, callback) {
|
||||||
|
var onCachedContentLoaded = function(details) {
|
||||||
|
//console.log('µBlock.assets/readCacheAsset("%s")/onCachedContentLoaded()', path);
|
||||||
|
callback({ 'path': path, 'content': details.content });
|
||||||
|
};
|
||||||
|
|
||||||
|
var onCachedContentError = function() {
|
||||||
|
//console.log('µBlock.assets/readCacheAsset("%s")/onCachedContentError()', path);
|
||||||
callback({ 'path': path, 'content': '' });
|
callback({ 'path': path, 'content': '' });
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -930,6 +965,11 @@ exports.get = function(path, callback) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( reIsCachePath.test(path) ) {
|
||||||
|
readCacheAsset(path, callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( reIsExternalPath.test(path) ) {
|
if ( reIsExternalPath.test(path) ) {
|
||||||
readExternalAsset(path, callback);
|
readExternalAsset(path, callback);
|
||||||
return;
|
return;
|
||||||
@ -1042,14 +1082,20 @@ exports.purge = function(pattern, before) {
|
|||||||
cachedAssetsManager.remove(pattern, before);
|
cachedAssetsManager.remove(pattern, before);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
exports.purgeAll = function(callback) {
|
exports.purgeAll = function(callback) {
|
||||||
cachedAssetsManager.removeAll(callback);
|
cachedAssetsManager.removeAll(callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
exports.onAssetCacheRemoved = {
|
||||||
|
addEventListener: function(callback) {
|
||||||
|
cachedAssetsManager.onRemovedListener = callback || null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
return exports;
|
return exports;
|
||||||
|
|
||||||
})();
|
})();
|
||||||
@ -1076,8 +1122,9 @@ var updated = {};
|
|||||||
var updatedCount = 0;
|
var updatedCount = 0;
|
||||||
var metadata = null;
|
var metadata = null;
|
||||||
|
|
||||||
var onStart = null;
|
var onStartListener = null;
|
||||||
var onCompleted = null;
|
var onCompletedListener = null;
|
||||||
|
var onAssetUpdatedListener = null;
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|
||||||
@ -1086,15 +1133,15 @@ var exports = {};
|
|||||||
var onAssetUpdated = function(details) {
|
var onAssetUpdated = function(details) {
|
||||||
var path = details.path;
|
var path = details.path;
|
||||||
if ( details.error ) {
|
if ( details.error ) {
|
||||||
//console.debug('assets.js > µBlock.assetUpdater/onAssetUpdated: "%s" failed', path);
|
//console.debug('µBlock.assetUpdater/onAssetUpdated: "%s" failed', path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//console.debug('assets.js > µBlock.assetUpdater/onAssetUpdated: "%s"', path);
|
//console.debug('µBlock.assetUpdater/onAssetUpdated: "%s"', path);
|
||||||
updated[path] = true;
|
updated[path] = true;
|
||||||
updatedCount += 1;
|
updatedCount += 1;
|
||||||
|
if ( typeof onAssetUpdatedListener === 'function' ) {
|
||||||
// New data available: selfie is now invalid
|
onAssetUpdatedListener(details);
|
||||||
µb.destroySelfie();
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -1117,7 +1164,7 @@ var updateOne = function() {
|
|||||||
if ( !metaEntry.cacheObsolete && !metaEntry.repoObsolete ) {
|
if ( !metaEntry.cacheObsolete && !metaEntry.repoObsolete ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//console.debug('assets.js > µBlock.assetUpdater/updateOne: assets.get("%s")', path);
|
//console.debug('µBlock.assetUpdater/updateOne: assets.get("%s")', path);
|
||||||
µb.assets.get(path, onAssetUpdated);
|
µb.assets.get(path, onAssetUpdated);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1144,10 +1191,10 @@ var updateDaemon = function() {
|
|||||||
// Start an update cycle?
|
// Start an update cycle?
|
||||||
if ( updateCycleTime !== 0 ) {
|
if ( updateCycleTime !== 0 ) {
|
||||||
if ( Date.now() >= updateCycleTime ) {
|
if ( Date.now() >= updateCycleTime ) {
|
||||||
//console.debug('assets.js > µBlock.assetUpdater/updateDaemon: update cycle started');
|
//console.debug('µBlock.assetUpdater/updateDaemon: update cycle started');
|
||||||
reset();
|
reset();
|
||||||
if ( onStart !== null ) {
|
if ( typeof onStartListener === 'function' ) {
|
||||||
onStart();
|
onStartListener();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -1166,9 +1213,9 @@ var updateDaemon = function() {
|
|||||||
|
|
||||||
// If anything was updated, notify listener
|
// If anything was updated, notify listener
|
||||||
if ( updatedCount !== 0 ) {
|
if ( updatedCount !== 0 ) {
|
||||||
if ( onCompleted !== null ) {
|
if ( typeof onCompletedListener === 'function' ) {
|
||||||
//console.debug('assets.js > µBlock.assetUpdater/updateDaemon: update cycle completed');
|
//console.debug('µBlock.assetUpdater/updateDaemon: update cycle completed');
|
||||||
onCompleted({
|
onCompletedListener({
|
||||||
updated: JSON.parse(JSON.stringify(updated)), // give callee its own safe copy
|
updated: JSON.parse(JSON.stringify(updated)), // give callee its own safe copy
|
||||||
updatedCount: updatedCount
|
updatedCount: updatedCount
|
||||||
});
|
});
|
||||||
@ -1178,7 +1225,7 @@ var updateDaemon = function() {
|
|||||||
// Schedule next update cycle
|
// Schedule next update cycle
|
||||||
if ( updateCycleTime === 0 ) {
|
if ( updateCycleTime === 0 ) {
|
||||||
reset();
|
reset();
|
||||||
//console.debug('assets.js > µBlock.assetUpdater/updateDaemon: update cycle re-scheduled');
|
//console.debug('µBlock.assetUpdater/updateDaemon: update cycle re-scheduled');
|
||||||
updateCycleTime = Date.now() + updateCycleNextPeriod;
|
updateCycleTime = Date.now() + updateCycleNextPeriod;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1200,8 +1247,8 @@ var reset = function() {
|
|||||||
|
|
||||||
exports.onStart = {
|
exports.onStart = {
|
||||||
addEventListener: function(callback) {
|
addEventListener: function(callback) {
|
||||||
onStart = callback || null;
|
onStartListener = callback || null;
|
||||||
if ( onStart !== null ) {
|
if ( typeof onStartListener === 'function' ) {
|
||||||
updateCycleTime = Date.now() + updateCycleFirstPeriod;
|
updateCycleTime = Date.now() + updateCycleFirstPeriod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1209,9 +1256,17 @@ exports.onStart = {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
exports.onAssetUpdated = {
|
||||||
|
addEventListener: function(callback) {
|
||||||
|
onAssetUpdatedListener = callback || null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
exports.onCompleted = {
|
exports.onCompleted = {
|
||||||
addEventListener: function(callback) {
|
addEventListener: function(callback) {
|
||||||
onCompleted = callback || null;
|
onCompletedListener = callback || null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,6 +83,12 @@ return {
|
|||||||
allowedRequestCount: 0
|
allowedRequestCount: 0
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// read-only
|
||||||
|
systemSettings: {
|
||||||
|
compiledMagic: 'dgycowxrdjuf',
|
||||||
|
selfieMagic: 'dmakcrbecglp'
|
||||||
|
},
|
||||||
|
|
||||||
// EasyList, EasyPrivacy and many others have an 4-day update period,
|
// EasyList, EasyPrivacy and many others have an 4-day update period,
|
||||||
// as per list headers.
|
// as per list headers.
|
||||||
updateAssetsEvery: 97 * oneHour,
|
updateAssetsEvery: 97 * oneHour,
|
||||||
@ -111,7 +117,6 @@ return {
|
|||||||
remoteBlacklists: {
|
remoteBlacklists: {
|
||||||
},
|
},
|
||||||
|
|
||||||
selfieMagic: 'bizhviclttie',
|
|
||||||
selfieAfter: 23 * oneMinute,
|
selfieAfter: 23 * oneMinute,
|
||||||
|
|
||||||
pageStores: {},
|
pageStores: {},
|
||||||
|
@ -334,7 +334,6 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
|||||||
hash = href.slice(pos + 3, pos + 11);
|
hash = href.slice(pos + 3, pos + 11);
|
||||||
selectors = generics[hash];
|
selectors = generics[hash];
|
||||||
if ( selectors === undefined ) { continue; }
|
if ( selectors === undefined ) { continue; }
|
||||||
selectors = selectors.split(',\n');
|
|
||||||
iSelector = selectors.length;
|
iSelector = selectors.length;
|
||||||
while ( iSelector-- ) {
|
while ( iSelector-- ) {
|
||||||
selector = selectors[iSelector];
|
selector = selectors[iSelector];
|
||||||
|
@ -71,8 +71,6 @@ var cosmeticFilters = function(details) {
|
|||||||
var hide = details.cosmeticHide;
|
var hide = details.cosmeticHide;
|
||||||
var i;
|
var i;
|
||||||
if ( donthide.length !== 0 ) {
|
if ( donthide.length !== 0 ) {
|
||||||
donthide = donthide.length !== 1 ? donthide.join(',\n') : donthide[0];
|
|
||||||
donthide = donthide.split(',\n');
|
|
||||||
i = donthide.length;
|
i = donthide.length;
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
donthideCosmeticFilters[donthide[i]] = true;
|
donthideCosmeticFilters[donthide[i]] = true;
|
||||||
@ -80,8 +78,6 @@ var cosmeticFilters = function(details) {
|
|||||||
}
|
}
|
||||||
// https://github.com/gorhill/uBlock/issues/143
|
// https://github.com/gorhill/uBlock/issues/143
|
||||||
if ( hide.length !== 0 ) {
|
if ( hide.length !== 0 ) {
|
||||||
hide = hide.length !== 1 ? hide.join(',\n') : hide[0];
|
|
||||||
hide = hide.split(',\n');
|
|
||||||
i = hide.length;
|
i = hide.length;
|
||||||
var selector;
|
var selector;
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
|
@ -481,7 +481,7 @@ var makeHash = function(unhide, token, mask) {
|
|||||||
if ( unhide !== 0 ) {
|
if ( unhide !== 0 ) {
|
||||||
hval |= 0x20000;
|
hval |= 0x20000;
|
||||||
}
|
}
|
||||||
return String.fromCharCode(hval >>> 9, hval & 0x1FF);
|
return hval.toString(36);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -503,8 +503,8 @@ var makeHash = function(unhide, token, mask) {
|
|||||||
// Specific filers can be enforced before the main document is loaded.
|
// Specific filers can be enforced before the main document is loaded.
|
||||||
|
|
||||||
var FilterContainer = function() {
|
var FilterContainer = function() {
|
||||||
this.domainHashMask = (1 << 10) - 1;
|
this.domainHashMask = (1 << 10) - 1; // 10 bits
|
||||||
this.genericHashMask = (1 << 15) - 1;
|
this.genericHashMask = (1 << 15) - 1; // 15 bits
|
||||||
this.type0NoDomainHash = 'type0NoDomain';
|
this.type0NoDomainHash = 'type0NoDomain';
|
||||||
this.type1NoDomainHash = 'type1NoDomain';
|
this.type1NoDomainHash = 'type1NoDomain';
|
||||||
this.parser = new FilterParser();
|
this.parser = new FilterParser();
|
||||||
@ -521,23 +521,15 @@ var FilterContainer = function() {
|
|||||||
|
|
||||||
FilterContainer.prototype.reset = function() {
|
FilterContainer.prototype.reset = function() {
|
||||||
this.parser.reset();
|
this.parser.reset();
|
||||||
|
this.µburi = µb.URI;
|
||||||
this.frozen = false;
|
this.frozen = false;
|
||||||
this.acceptedCount = 0;
|
this.acceptedCount = 0;
|
||||||
this.duplicateCount = 0;
|
this.duplicateCount = 0;
|
||||||
|
this.duplicateBuster = {};
|
||||||
|
|
||||||
this.selectorCache = {};
|
this.selectorCache = {};
|
||||||
this.selectorCacheCount = 0;
|
this.selectorCacheCount = 0;
|
||||||
|
|
||||||
// temporary (at parse time)
|
|
||||||
this.lowGenericHide = {};
|
|
||||||
this.lowGenericDonthide = {};
|
|
||||||
this.highGenericHide = {};
|
|
||||||
this.highGenericDonthide = {};
|
|
||||||
this.hostnameHide = {};
|
|
||||||
this.hostnameDonthide = {};
|
|
||||||
this.entityHide = {};
|
|
||||||
this.entityDonthide = {};
|
|
||||||
|
|
||||||
// permanent
|
// permanent
|
||||||
// [class], [id]
|
// [class], [id]
|
||||||
this.lowGenericFilters = {};
|
this.lowGenericFilters = {};
|
||||||
@ -555,9 +547,11 @@ FilterContainer.prototype.reset = function() {
|
|||||||
this.highMediumGenericDonthideCount = 0;
|
this.highMediumGenericDonthideCount = 0;
|
||||||
|
|
||||||
// everything else
|
// everything else
|
||||||
|
this.highHighGenericHideArray = [];
|
||||||
this.highHighGenericHide = '';
|
this.highHighGenericHide = '';
|
||||||
this.highHighGenericDonthide = '';
|
|
||||||
this.highHighGenericHideCount = 0;
|
this.highHighGenericHideCount = 0;
|
||||||
|
this.highHighGenericDonthideArray = [];
|
||||||
|
this.highHighGenericDonthide = '';
|
||||||
this.highHighGenericDonthideCount = 0;
|
this.highHighGenericDonthideCount = 0;
|
||||||
|
|
||||||
// hostname, entity-based filters
|
// hostname, entity-based filters
|
||||||
@ -567,7 +561,7 @@ FilterContainer.prototype.reset = function() {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.add = function(s) {
|
FilterContainer.prototype.compile = function(s, out) {
|
||||||
var parsed = this.parser.parse(s);
|
var parsed = this.parser.parse(s);
|
||||||
if ( parsed.invalid ) {
|
if ( parsed.invalid ) {
|
||||||
return false;
|
return false;
|
||||||
@ -576,271 +570,284 @@ FilterContainer.prototype.add = function(s) {
|
|||||||
var hostnames = parsed.hostnames;
|
var hostnames = parsed.hostnames;
|
||||||
var i = hostnames.length;
|
var i = hostnames.length;
|
||||||
if ( i === 0 ) {
|
if ( i === 0 ) {
|
||||||
this.addGenericSelector(parsed);
|
this.compileGenericSelector(parsed, out);
|
||||||
return true;
|
} else {
|
||||||
}
|
// https://github.com/gorhill/uBlock/issues/151
|
||||||
// https://github.com/gorhill/uBlock/issues/151
|
// Negated hostname means the filter applies to all non-negated hostnames
|
||||||
// Negated hostname means the filter applies to all non-negated hostnames
|
// of same filter OR globally if there is no non-negated hostnames.
|
||||||
// of same filter OR globally if there is no non-negated hostnames.
|
var applyGlobally = true;
|
||||||
var applyGlobally = true;
|
var hostname;
|
||||||
var hostname;
|
while ( i-- ) {
|
||||||
while ( i-- ) {
|
hostname = hostnames[i];
|
||||||
hostname = hostnames[i];
|
if ( hostname.charAt(0) !== '~' ) {
|
||||||
if ( hostname.charAt(0) !== '~' ) {
|
applyGlobally = false;
|
||||||
applyGlobally = false;
|
}
|
||||||
|
if ( hostname.slice(-2) === '.*' ) {
|
||||||
|
this.compileEntitySelector(hostname, parsed, out);
|
||||||
|
} else {
|
||||||
|
this.compileHostnameSelector(hostname, parsed, out);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ( hostname.slice(-2) === '.*' ) {
|
if ( applyGlobally ) {
|
||||||
this.addEntitySelector(hostname, parsed);
|
this.compileGenericSelector(parsed, out);
|
||||||
} else {
|
|
||||||
this.addHostnameSelector(hostname, parsed);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( applyGlobally ) {
|
|
||||||
this.addGenericSelector(parsed);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.addGenericSelector = function(parsed) {
|
FilterContainer.prototype.compileGenericSelector = function(parsed, out) {
|
||||||
var entries;
|
var selector = parsed.suffix;
|
||||||
var selectorType = parsed.suffix.charAt(0);
|
var type = selector.charAt(0);
|
||||||
if ( selectorType === '#' || selectorType === '.' ) {
|
var matches;
|
||||||
entries = parsed.unhide === 0 ?
|
|
||||||
this.lowGenericHide :
|
if ( type === '#' || type === '.' ) {
|
||||||
this.lowGenericDonthide;
|
matches = this.rePlainSelector.exec(selector);
|
||||||
} else {
|
if ( matches === null ) {
|
||||||
entries = parsed.unhide === 0 ?
|
return;
|
||||||
this.highGenericHide :
|
}
|
||||||
this.highGenericDonthide;
|
out.push(
|
||||||
|
'c\v' +
|
||||||
|
(matches[1] === selector ? 'lg\v' : 'lg+\v') +
|
||||||
|
makeHash(parsed.unhide, matches[1], this.genericHashMask) + '\v' +
|
||||||
|
selector
|
||||||
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if ( entries[parsed.suffix] === undefined ) {
|
|
||||||
entries[parsed.suffix] = true;
|
// ["title"] and ["alt"] will go in high-low generic bin.
|
||||||
} else {
|
if ( this.reHighLow.test(selector) ) {
|
||||||
//console.log('cosmetic-filtering.js > FilterContainer.addGenericSelector(): duplicate filter "%s"', parsed.suffix);
|
out.push(
|
||||||
this.duplicateCount += 1;
|
'c\v' +
|
||||||
|
(parsed.unhide === 0 ? 'hlg0\v' : 'hlg1\v') +
|
||||||
|
selector
|
||||||
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
this.acceptedCount += 1;
|
|
||||||
|
// [href^="..."] will go in high-medium generic bin.
|
||||||
|
matches = this.reHighMedium.exec(selector);
|
||||||
|
if ( matches && matches.length === 2 ) {
|
||||||
|
out.push(
|
||||||
|
'c\v' +
|
||||||
|
(parsed.unhide === 0 ? 'hmg0\v' : 'hmg1\v') +
|
||||||
|
matches[1] + '\v' +
|
||||||
|
selector
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All else
|
||||||
|
out.push(
|
||||||
|
'c\v' +
|
||||||
|
(parsed.unhide === 0 ? 'hhg0\v' : 'hhg1\v') +
|
||||||
|
selector
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterContainer.prototype.rePlainSelector = /^([#.][\w-]+)/;
|
||||||
|
FilterContainer.prototype.reHighLow = /^[a-z]*\[(?:alt|title)="[^"]+"\]$/;
|
||||||
|
FilterContainer.prototype.reHighMedium = /^\[href\^="https?:\/\/([^"]{8})[^"]*"\]$/;
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.addHostnameSelector = function(hostname, parsed) {
|
FilterContainer.prototype.compileHostnameSelector = function(hostname, parsed, out) {
|
||||||
// https://github.com/gorhill/uBlock/issues/145
|
// https://github.com/gorhill/uBlock/issues/145
|
||||||
var unhide = parsed.unhide;
|
var unhide = parsed.unhide;
|
||||||
if ( hostname.charAt(0) === '~' ) {
|
if ( hostname.charAt(0) === '~' ) {
|
||||||
hostname = hostname.slice(1);
|
hostname = hostname.slice(1);
|
||||||
unhide ^= 1;
|
unhide ^= 1;
|
||||||
}
|
}
|
||||||
var entries = unhide === 0 ?
|
// https://github.com/gorhill/uBlock/issues/188
|
||||||
this.hostnameHide :
|
// If not a real domain as per PSL, assign a synthetic one
|
||||||
this.hostnameDonthide;
|
var hash;
|
||||||
var entry = entries[hostname];
|
var domain = this.µburi.domainFromHostname(hostname);
|
||||||
if ( entry === undefined ) {
|
if ( domain === '' ) {
|
||||||
entry = entries[hostname] = {};
|
hash = unhide === 0 ? this.type0NoDomainHash : this.type1NoDomainHash;
|
||||||
entry[parsed.suffix] = true;
|
|
||||||
} else if ( entry[parsed.suffix] === undefined ) {
|
|
||||||
entry[parsed.suffix] = true;
|
|
||||||
} else {
|
} else {
|
||||||
//console.log('cosmetic-filtering.js > FilterContainer.addHostnameSelector(): duplicate filter "%s"', parsed.suffix);
|
hash = makeHash(unhide, domain, this.domainHashMask);
|
||||||
this.duplicateCount += 1;
|
|
||||||
}
|
}
|
||||||
this.acceptedCount += 1;
|
out.push(
|
||||||
|
'c\v' +
|
||||||
|
'h\v' +
|
||||||
|
hash + '\v' +
|
||||||
|
hostname + '\v' +
|
||||||
|
parsed.suffix
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.addEntitySelector = function(hostname, parsed) {
|
FilterContainer.prototype.compileEntitySelector = function(hostname, parsed, out) {
|
||||||
var entries = parsed.unhide === 0 ?
|
|
||||||
this.entityHide :
|
|
||||||
this.entityDonthide;
|
|
||||||
var entity = hostname.slice(0, -2);
|
var entity = hostname.slice(0, -2);
|
||||||
var entry = entries[entity];
|
out.push(
|
||||||
if ( entry === undefined ) {
|
'c\v' +
|
||||||
entry = entries[entity] = {};
|
'e\v' +
|
||||||
entry[parsed.suffix] = true;
|
entity + '\v' +
|
||||||
} else if ( entry[parsed.suffix] === undefined ) {
|
parsed.suffix
|
||||||
entry[parsed.suffix] = true;
|
);
|
||||||
} else {
|
|
||||||
//console.log('cosmetic-filtering.js > FilterContainer.addEntitySelector(): duplicate filter "%s"', parsed.suffix);
|
|
||||||
this.duplicateCount += 1;
|
|
||||||
}
|
|
||||||
this.acceptedCount += 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.freezeLowGenerics = function(what, type) {
|
FilterContainer.prototype.fromCompiledContent = function(text, lineBeg, skip) {
|
||||||
var selectors = this[what];
|
if ( skip ) {
|
||||||
var matches, selectorPrefix, f, hash, bucket;
|
return this.skipCompiledContent(text, lineBeg);
|
||||||
for ( var selector in selectors ) {
|
|
||||||
if ( selectors.hasOwnProperty(selector) === false ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
matches = this.rePlainSelector.exec(selector);
|
|
||||||
if ( !matches ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
selectorPrefix = matches[1];
|
|
||||||
f = selectorPrefix === selector ?
|
|
||||||
new FilterPlain(selector) :
|
|
||||||
new FilterPlainMore(selector);
|
|
||||||
hash = makeHash(type, selectorPrefix, this.genericHashMask);
|
|
||||||
bucket = this.lowGenericFilters[hash];
|
|
||||||
if ( bucket === undefined ) {
|
|
||||||
this.lowGenericFilters[hash] = f;
|
|
||||||
} else if ( bucket instanceof FilterBucket ) {
|
|
||||||
bucket.add(f);
|
|
||||||
} else {
|
|
||||||
this.lowGenericFilters[hash] = new FilterBucket(bucket, f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this[what] = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
FilterContainer.prototype.rePlainSelector = /^([#.][\w-]+)/;
|
var lineEnd;
|
||||||
|
var textEnd = text.length;
|
||||||
|
var line, fields, filter, bucket;
|
||||||
|
|
||||||
/******************************************************************************/
|
while ( lineBeg < textEnd ) {
|
||||||
|
if ( text.charAt(lineBeg) !== 'c' ) {
|
||||||
|
return lineBeg;
|
||||||
|
}
|
||||||
|
lineEnd = text.indexOf('\n', lineBeg);
|
||||||
|
if ( lineEnd === -1 ) {
|
||||||
|
lineEnd = textEnd;
|
||||||
|
}
|
||||||
|
line = text.slice(lineBeg + 2, lineEnd);
|
||||||
|
lineBeg = lineEnd + 1;
|
||||||
|
|
||||||
FilterContainer.prototype.freezeHostnameSpecifics = function(what, type) {
|
|
||||||
var µburi = µb.URI;
|
this.acceptedCount += 1;
|
||||||
var entries = this[what];
|
if ( this.duplicateBuster.hasOwnProperty(line) ) {
|
||||||
var filters = this.hostnameFilters;
|
this.duplicateCount += 1;
|
||||||
var f, domain, hash, bucket;
|
|
||||||
for ( var hostname in entries ) {
|
|
||||||
if ( entries.hasOwnProperty(hostname) === false ) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
f = new FilterHostname(Object.keys(entries[hostname]).join(',\n'), hostname);
|
this.duplicateBuster[line] = true;
|
||||||
// https://github.com/gorhill/uBlock/issues/188
|
|
||||||
// If not a real domain as per PSL, assign a synthetic one
|
|
||||||
domain = µburi.domainFromHostname(hostname);
|
|
||||||
if ( domain === '' ) {
|
|
||||||
hash = type === 0 ? this.type0NoDomainHash : this.type1NoDomainHash;
|
|
||||||
} else {
|
|
||||||
hash = makeHash(type, domain, this.domainHashMask);
|
|
||||||
}
|
|
||||||
bucket = filters[hash];
|
|
||||||
if ( bucket === undefined ) {
|
|
||||||
filters[hash] = f;
|
|
||||||
} else if ( bucket instanceof FilterBucket ) {
|
|
||||||
bucket.add(f);
|
|
||||||
} else {
|
|
||||||
filters[hash] = new FilterBucket(bucket, f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this[what] = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
fields = line.split('\v');
|
||||||
|
|
||||||
FilterContainer.prototype.freezeEntitySpecifics = function(what, type) {
|
// h ir twitter.com .promoted-tweet
|
||||||
var entries = this[what];
|
if ( fields[0] === 'h' ) {
|
||||||
var filters = this.entityFilters;
|
filter = new FilterHostname(fields[3], fields[2]);
|
||||||
var f, hash, bucket;
|
bucket = this.hostnameFilters[fields[1]];
|
||||||
for ( var entity in entries ) {
|
if ( bucket === undefined ) {
|
||||||
if ( entries.hasOwnProperty(entity) === false ) {
|
this.hostnameFilters[fields[1]] = filter;
|
||||||
continue;
|
} else if ( bucket instanceof FilterBucket ) {
|
||||||
}
|
bucket.add(filter);
|
||||||
f = new FilterEntity(Object.keys(entries[entity]).join(',\n'), entity);
|
|
||||||
hash = makeHash(type, entity, this.domainHashMask);
|
|
||||||
bucket = filters[hash];
|
|
||||||
if ( bucket === undefined ) {
|
|
||||||
filters[hash] = f;
|
|
||||||
} else if ( bucket instanceof FilterBucket ) {
|
|
||||||
bucket.add(f);
|
|
||||||
} else {
|
|
||||||
filters[hash] = new FilterBucket(bucket, f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this[what] = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
FilterContainer.prototype.freezeHighGenerics = function(what) {
|
|
||||||
var selectors = this['highGeneric' + what];
|
|
||||||
|
|
||||||
// ["title"] and ["alt"] will go in high-low generic bin.
|
|
||||||
var highLowGenericProp = 'highLowGeneric' + what;
|
|
||||||
var highLowGeneric = this[highLowGenericProp];
|
|
||||||
var highLowGenericCount = 0;
|
|
||||||
|
|
||||||
// [href^="..."] will go in high-medium generic bin.
|
|
||||||
var highMediumGenericProp = 'highMediumGeneric' + what;
|
|
||||||
var highMediumGeneric = this[highMediumGenericProp];
|
|
||||||
var highMediumGenericCount = 0;
|
|
||||||
|
|
||||||
// The rest will be put in the high-high generic bin.
|
|
||||||
// https://github.com/gorhill/uBlock/issues/236
|
|
||||||
// Insert whatever we already have
|
|
||||||
var highHighGeneric = [];
|
|
||||||
var highHighGenericProp = 'highHighGeneric' + what;
|
|
||||||
if ( this[highHighGenericProp] !== '' ) {
|
|
||||||
highHighGeneric.push(this[highHighGenericProp]);
|
|
||||||
}
|
|
||||||
var highHighGenericCount = 0;
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/456
|
|
||||||
// Include tag name, it's part of the filter
|
|
||||||
var reHighLow = /^[a-z]*\[(?:alt|title)="[^"]+"\]$/;
|
|
||||||
var reHighMedium = /^\[href\^="https?:\/\/([^"]{8})[^"]*"\]$/;
|
|
||||||
var matches, hash;
|
|
||||||
|
|
||||||
for ( var selector in selectors ) {
|
|
||||||
if ( selectors.hasOwnProperty(selector) === false ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// ["title"] and ["alt"] will go in high-low generic bin.
|
|
||||||
matches = reHighLow.exec(selector);
|
|
||||||
if ( matches && matches.length === 1 ) {
|
|
||||||
highLowGeneric[matches[0]] = true;
|
|
||||||
highLowGenericCount += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// [href^="..."] will go in high-medium generic bin.
|
|
||||||
matches = reHighMedium.exec(selector);
|
|
||||||
if ( matches && matches.length === 2 ) {
|
|
||||||
hash = matches[1];
|
|
||||||
if ( highMediumGeneric[hash] === undefined ) {
|
|
||||||
highMediumGeneric[hash] = matches[0];
|
|
||||||
} else {
|
} else {
|
||||||
highMediumGeneric[hash] += ',\n' + matches[0];
|
this.hostnameFilters[fields[1]] = new FilterBucket(bucket, filter);
|
||||||
}
|
}
|
||||||
highMediumGenericCount += 1;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// All else
|
|
||||||
highHighGeneric.push(selector);
|
// lg 105 .largeAd
|
||||||
highHighGenericCount += 1;
|
// lg+ 2jx .Mpopup + #Mad > #MadZone
|
||||||
|
if ( fields[0] === 'lg' || fields[0] === 'lg+' ) {
|
||||||
|
filter = fields[0] === 'lg' ?
|
||||||
|
new FilterPlain(fields[2]) :
|
||||||
|
new FilterPlainMore(fields[2]);
|
||||||
|
bucket = this.lowGenericFilters[fields[1]];
|
||||||
|
if ( bucket === undefined ) {
|
||||||
|
this.lowGenericFilters[fields[1]] = filter;
|
||||||
|
} else if ( bucket instanceof FilterBucket ) {
|
||||||
|
bucket.add(filter);
|
||||||
|
} else {
|
||||||
|
this.lowGenericFilters[fields[1]] = new FilterBucket(bucket, filter);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// entity selector
|
||||||
|
if ( fields[0] === 'e' ) {
|
||||||
|
bucket = this.entityFilters[fields[1]];
|
||||||
|
if ( bucket === undefined ) {
|
||||||
|
this.entityFilters[fields[1]] = [fields[2]];
|
||||||
|
} else {
|
||||||
|
bucket.push(fields[2]);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fields[0] === 'hlg0' ) {
|
||||||
|
this.highLowGenericHide[fields[1]] = true;
|
||||||
|
this.highLowGenericHideCount += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fields[0] === 'hlg1' ) {
|
||||||
|
this.highLowGenericDonthide[fields[1]] = true;
|
||||||
|
this.highLowGenericDonthideCount += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fields[0] === 'hmg0' ) {
|
||||||
|
if ( Array.isArray(this.highMediumGenericHide[fields[1]]) ) {
|
||||||
|
this.highMediumGenericHide[fields[1]].push(fields[2]);
|
||||||
|
} else {
|
||||||
|
this.highMediumGenericHide[fields[1]] = [fields[2]];
|
||||||
|
}
|
||||||
|
this.highMediumGenericHideCount += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fields[0] === 'hmg1' ) {
|
||||||
|
if ( Array.isArray(this.highMediumGenericDonthide[fields[1]]) ) {
|
||||||
|
this.highMediumGenericDonthide[fields[1]].push(fields[2]);
|
||||||
|
} else {
|
||||||
|
this.highMediumGenericDonthide[fields[1]] = [fields[2]];
|
||||||
|
}
|
||||||
|
this.highMediumGenericDonthideCount += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fields[0] === 'hhg0' ) {
|
||||||
|
this.highHighGenericHideArray.push(fields[1]);
|
||||||
|
this.highHighGenericHideCount += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fields[0] === 'hhg1' ) {
|
||||||
|
this.highHighGenericDonthideArray.push(fields[1]);
|
||||||
|
this.highHighGenericDonthideCount += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return textEnd;
|
||||||
|
};
|
||||||
|
|
||||||
this[highLowGenericProp + 'Count'] += highLowGenericCount;
|
/******************************************************************************/
|
||||||
this[highMediumGenericProp + 'Count'] += highMediumGenericCount;
|
|
||||||
this[highHighGenericProp] = highHighGeneric.join(',\n');
|
|
||||||
this[highHighGenericProp + 'Count'] += highHighGenericCount;
|
|
||||||
|
|
||||||
// Empty cumulated selectors
|
FilterContainer.prototype.skipCompiledContent = function(text, lineBeg) {
|
||||||
this['highGeneric' + what] = {};
|
var lineEnd;
|
||||||
|
var textEnd = text.length;
|
||||||
|
|
||||||
|
while ( lineBeg < textEnd ) {
|
||||||
|
if ( text.charAt(lineBeg) !== 'c' ) {
|
||||||
|
return lineBeg;
|
||||||
|
}
|
||||||
|
lineEnd = text.indexOf('\n', lineBeg);
|
||||||
|
if ( lineEnd === -1 ) {
|
||||||
|
lineEnd = textEnd;
|
||||||
|
}
|
||||||
|
lineBeg = lineEnd + 1;
|
||||||
|
}
|
||||||
|
return textEnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.freeze = function() {
|
FilterContainer.prototype.freeze = function() {
|
||||||
this.freezeLowGenerics('lowGenericHide', 0);
|
this.duplicateBuster = {};
|
||||||
this.freezeLowGenerics('lowGenericDonthide', 1);
|
|
||||||
this.freezeHighGenerics('Hide');
|
if ( this.highHighGenericHide !== '' ) {
|
||||||
this.freezeHighGenerics('Donthide');
|
this.highHighGenericHideArray.unshift(this.highHighGenericHide);
|
||||||
this.freezeHostnameSpecifics('hostnameHide', 0);
|
}
|
||||||
this.freezeHostnameSpecifics('hostnameDonthide', 1);
|
this.highHighGenericHide = this.highHighGenericHideArray.join(',\n');
|
||||||
this.freezeEntitySpecifics('entityHide', 0);
|
this.highHighGenericHideArray = [];
|
||||||
this.freezeEntitySpecifics('entityDonthide', 1);
|
if ( this.highHighGenericDonthide !== '' ) {
|
||||||
|
this.highHighGenericDonthideArray.unshift(this.highHighGenericDonthide);
|
||||||
|
}
|
||||||
|
this.highHighGenericDonthide = this.highHighGenericDonthideArray.join(',\n');
|
||||||
|
this.highHighGenericDonthideArray = [];
|
||||||
|
|
||||||
this.parser.reset();
|
this.parser.reset();
|
||||||
this.frozen = true;
|
this.frozen = true;
|
||||||
|
|
||||||
//histogram('lowGenericFilters', this.lowGenericFilters);
|
|
||||||
//histogram('hostnameFilters', this.hostnameFilters);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -875,7 +882,7 @@ FilterContainer.prototype.toSelfie = function() {
|
|||||||
acceptedCount: this.acceptedCount,
|
acceptedCount: this.acceptedCount,
|
||||||
duplicateCount: this.duplicateCount,
|
duplicateCount: this.duplicateCount,
|
||||||
hostnameSpecificFilters: selfieFromDict(this.hostnameFilters),
|
hostnameSpecificFilters: selfieFromDict(this.hostnameFilters),
|
||||||
entitySpecificFilters: selfieFromDict(this.entityFilters),
|
entitySpecificFilters: this.entityFilters,
|
||||||
lowGenericFilters: selfieFromDict(this.lowGenericFilters),
|
lowGenericFilters: selfieFromDict(this.lowGenericFilters),
|
||||||
highLowGenericHide: this.highLowGenericHide,
|
highLowGenericHide: this.highLowGenericHide,
|
||||||
highLowGenericDonthide: this.highLowGenericDonthide,
|
highLowGenericDonthide: this.highLowGenericDonthide,
|
||||||
@ -940,7 +947,7 @@ FilterContainer.prototype.fromSelfie = function(selfie) {
|
|||||||
this.acceptedCount = selfie.acceptedCount;
|
this.acceptedCount = selfie.acceptedCount;
|
||||||
this.duplicateCount = selfie.duplicateCount;
|
this.duplicateCount = selfie.duplicateCount;
|
||||||
this.hostnameFilters = dictFromSelfie(selfie.hostnameSpecificFilters);
|
this.hostnameFilters = dictFromSelfie(selfie.hostnameSpecificFilters);
|
||||||
this.entityFilters = dictFromSelfie(selfie.entitySpecificFilters);
|
this.entityFilters = selfie.entitySpecificFilters;
|
||||||
this.lowGenericFilters = dictFromSelfie(selfie.lowGenericFilters);
|
this.lowGenericFilters = dictFromSelfie(selfie.lowGenericFilters);
|
||||||
this.highLowGenericHide = selfie.highLowGenericHide;
|
this.highLowGenericHide = selfie.highLowGenericHide;
|
||||||
this.highLowGenericDonthide = selfie.highLowGenericDonthide;
|
this.highLowGenericDonthide = selfie.highLowGenericDonthide;
|
||||||
@ -1156,14 +1163,18 @@ FilterContainer.prototype.retrieveDomainSelectors = function(request) {
|
|||||||
if ( bucket = this.hostnameFilters[this.type0NoDomainHash] ) {
|
if ( bucket = this.hostnameFilters[this.type0NoDomainHash] ) {
|
||||||
bucket.retrieve(hostname, r.cosmeticHide);
|
bucket.retrieve(hostname, r.cosmeticHide);
|
||||||
}
|
}
|
||||||
hash = makeHash(0, r.entity, this.domainHashMask);
|
|
||||||
if ( bucket = this.entityFilters[hash] ) {
|
// entity filter buckets are always plain js array
|
||||||
bucket.retrieve(pos === -1 ? domain : hostname.slice(0, pos - domain.length), r.cosmeticHide);
|
if ( bucket = this.entityFilters[r.entity] ) {
|
||||||
|
r.cosmeticHide = r.cosmeticHide.concat(bucket);
|
||||||
}
|
}
|
||||||
|
// No entity exceptions as of now
|
||||||
|
|
||||||
hash = makeHash(1, domain, this.domainHashMask);
|
hash = makeHash(1, domain, this.domainHashMask);
|
||||||
if ( bucket = this.hostnameFilters[hash] ) {
|
if ( bucket = this.hostnameFilters[hash] ) {
|
||||||
bucket.retrieve(hostname, r.cosmeticDonthide);
|
bucket.retrieve(hostname, r.cosmeticDonthide);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/188
|
// https://github.com/gorhill/uBlock/issues/188
|
||||||
// Special bucket for those filters without a valid domain name as per PSL
|
// Special bucket for those filters without a valid domain name as per PSL
|
||||||
if ( bucket = this.hostnameFilters[this.type1NoDomainHash] ) {
|
if ( bucket = this.hostnameFilters[this.type1NoDomainHash] ) {
|
||||||
|
@ -68,7 +68,7 @@ var onMessage = function(request, sender, callback) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'reloadAllFilters':
|
case 'reloadAllFilters':
|
||||||
µb.reloadPresetBlacklists(request.switches, request.update);
|
µb.reloadFilterLists(request.switches, request.update);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'reloadTab':
|
case 'reloadTab':
|
||||||
|
@ -20,11 +20,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* exported quickProfiler */
|
/* exported quickProfiler */
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var quickProfiler = (function() {
|
var quickProfiler = (function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
var timer = window.performance || Date;
|
var timer = window.performance || Date;
|
||||||
var time = 0;
|
var time = 0;
|
||||||
var count = 0;
|
var count = 0;
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
quickProfiler.start('start.js');
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// Final initialization steps after all needed assets are in memory.
|
// Final initialization steps after all needed assets are in memory.
|
||||||
@ -40,11 +42,15 @@ var onAllReady = function() {
|
|||||||
// Check for updates not too far in the future.
|
// Check for updates not too far in the future.
|
||||||
µb.assetUpdater.onStart.addEventListener(µb.updateStartHandler.bind(µb));
|
µb.assetUpdater.onStart.addEventListener(µb.updateStartHandler.bind(µb));
|
||||||
µb.assetUpdater.onCompleted.addEventListener(µb.updateCompleteHandler.bind(µb));
|
µb.assetUpdater.onCompleted.addEventListener(µb.updateCompleteHandler.bind(µb));
|
||||||
|
µb.assetUpdater.onAssetUpdated.addEventListener(µb.assetUpdatedHandler.bind(µb));
|
||||||
|
µb.assets.onAssetCacheRemoved.addEventListener(µb.assetCacheRemovedHandler.bind(µb));
|
||||||
|
|
||||||
// Important: remove barrier to remote fetching, this was useful only
|
// Important: remove barrier to remote fetching, this was useful only
|
||||||
// for launch time.
|
// for launch time.
|
||||||
µb.assets.allowRemoteFetch = true;
|
µb.assets.allowRemoteFetch = true;
|
||||||
|
|
||||||
|
quickProfiler.stop(0);
|
||||||
|
|
||||||
vAPI.onLoadAllCompleted();
|
vAPI.onLoadAllCompleted();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -155,9 +161,34 @@ var onUserSettingsReady = function(userSettings) {
|
|||||||
µb.XAL.keyvalRemoveOne('logRequests');
|
µb.XAL.keyvalRemoveOne('logRequests');
|
||||||
};
|
};
|
||||||
|
|
||||||
µBlock.loadUserSettings(onUserSettingsReady);
|
/******************************************************************************/
|
||||||
µBlock.loadWhitelist(onWhitelistReady);
|
|
||||||
µBlock.loadLocalSettings();
|
// Housekeeping, as per system setting changes
|
||||||
|
|
||||||
|
var onSystemSettingsReady = function(system) {
|
||||||
|
var µb = µBlock;
|
||||||
|
|
||||||
|
var mustSaveSystemSettings = false;
|
||||||
|
if ( system.compiledMagic !== µb.systemSettings.compiledMagic ) {
|
||||||
|
µb.assets.purge(/^cache:\/\/compiled-/);
|
||||||
|
mustSaveSystemSettings = true;
|
||||||
|
}
|
||||||
|
if ( system.selfieMagic !== µb.systemSettings.selfieMagic ) {
|
||||||
|
µb.destroySelfie();
|
||||||
|
mustSaveSystemSettings = true;
|
||||||
|
}
|
||||||
|
if ( mustSaveSystemSettings ) {
|
||||||
|
µb.saveSystemSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
µb.loadUserSettings(onUserSettingsReady);
|
||||||
|
µb.loadWhitelist(onWhitelistReady);
|
||||||
|
µb.loadLocalSettings();
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
µBlock.loadSystemSettings(onSystemSettingsReady);
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ 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.fid = FilterPlain.prototype.fid = 'a';
|
||||||
|
|
||||||
FilterPlain.prototype.toString = function() {
|
FilterPlain.prototype.toString = function() {
|
||||||
return this.s;
|
return this.s;
|
||||||
@ -238,6 +238,10 @@ FilterPlain.prototype.toSelfie = function() {
|
|||||||
this.tokenBeg;
|
this.tokenBeg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlain.compile = function(details) {
|
||||||
|
return details.f + '\t' + details.tokenBeg;
|
||||||
|
};
|
||||||
|
|
||||||
FilterPlain.fromSelfie = function(s) {
|
FilterPlain.fromSelfie = function(s) {
|
||||||
var pos = s.indexOf('\t');
|
var pos = s.indexOf('\t');
|
||||||
return new FilterPlain(s.slice(0, pos), atoi(s.slice(pos + 1)));
|
return new FilterPlain(s.slice(0, pos), atoi(s.slice(pos + 1)));
|
||||||
@ -256,7 +260,7 @@ 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.fid = FilterPlainHostname.prototype.fid = 'ah';
|
||||||
|
|
||||||
FilterPlainHostname.prototype.toString = function() {
|
FilterPlainHostname.prototype.toString = function() {
|
||||||
return this.s + '$domain=' + this.hostname;
|
return this.s + '$domain=' + this.hostname;
|
||||||
@ -268,6 +272,12 @@ FilterPlainHostname.prototype.toSelfie = function() {
|
|||||||
this.hostname;
|
this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainHostname.compile = function(details, hostname) {
|
||||||
|
return details.f + '\t' +
|
||||||
|
details.tokenBeg + '\t' +
|
||||||
|
hostname;
|
||||||
|
};
|
||||||
|
|
||||||
FilterPlainHostname.fromSelfie = function(s) {
|
FilterPlainHostname.fromSelfie = function(s) {
|
||||||
var args = s.split('\t');
|
var args = s.split('\t');
|
||||||
return new FilterPlainHostname(args[0], atoi(args[1]), args[2]);
|
return new FilterPlainHostname(args[0], atoi(args[1]), args[2]);
|
||||||
@ -283,7 +293,7 @@ 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.fid = FilterPlainPrefix0.prototype.fid = '0a';
|
||||||
|
|
||||||
FilterPlainPrefix0.prototype.toString = function() {
|
FilterPlainPrefix0.prototype.toString = function() {
|
||||||
return this.s;
|
return this.s;
|
||||||
@ -293,6 +303,10 @@ FilterPlainPrefix0.prototype.toSelfie = function() {
|
|||||||
return this.s;
|
return this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainPrefix0.compile = function(details) {
|
||||||
|
return details.f;
|
||||||
|
};
|
||||||
|
|
||||||
FilterPlainPrefix0.fromSelfie = function(s) {
|
FilterPlainPrefix0.fromSelfie = function(s) {
|
||||||
return new FilterPlainPrefix0(s);
|
return new FilterPlainPrefix0(s);
|
||||||
};
|
};
|
||||||
@ -309,7 +323,7 @@ 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.fid = FilterPlainPrefix0Hostname.prototype.fid = '0ah';
|
||||||
|
|
||||||
FilterPlainPrefix0Hostname.prototype.toString = function() {
|
FilterPlainPrefix0Hostname.prototype.toString = function() {
|
||||||
return this.s + '$domain=' + this.hostname;
|
return this.s + '$domain=' + this.hostname;
|
||||||
@ -320,6 +334,10 @@ FilterPlainPrefix0Hostname.prototype.toSelfie = function() {
|
|||||||
this.hostname;
|
this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainPrefix0Hostname.compile = function(details, hostname) {
|
||||||
|
return details.f + '\t' + hostname;
|
||||||
|
};
|
||||||
|
|
||||||
FilterPlainPrefix0Hostname.fromSelfie = function(s) {
|
FilterPlainPrefix0Hostname.fromSelfie = function(s) {
|
||||||
var pos = s.indexOf('\t');
|
var pos = s.indexOf('\t');
|
||||||
return new FilterPlainPrefix0Hostname(s.slice(0, pos), s.slice(pos + 1));
|
return new FilterPlainPrefix0Hostname(s.slice(0, pos), s.slice(pos + 1));
|
||||||
@ -335,7 +353,7 @@ 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.fid = FilterPlainPrefix1.prototype.fid = '1a';
|
||||||
|
|
||||||
FilterPlainPrefix1.prototype.toString = function() {
|
FilterPlainPrefix1.prototype.toString = function() {
|
||||||
return this.s;
|
return this.s;
|
||||||
@ -345,6 +363,10 @@ FilterPlainPrefix1.prototype.toSelfie = function() {
|
|||||||
return this.s;
|
return this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainPrefix1.compile = function(details) {
|
||||||
|
return details.f;
|
||||||
|
};
|
||||||
|
|
||||||
FilterPlainPrefix1.fromSelfie = function(s) {
|
FilterPlainPrefix1.fromSelfie = function(s) {
|
||||||
return new FilterPlainPrefix1(s);
|
return new FilterPlainPrefix1(s);
|
||||||
};
|
};
|
||||||
@ -361,7 +383,7 @@ 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.fid = FilterPlainPrefix1Hostname.prototype.fid = '1ah';
|
||||||
|
|
||||||
FilterPlainPrefix1Hostname.prototype.toString = function() {
|
FilterPlainPrefix1Hostname.prototype.toString = function() {
|
||||||
return this.s + '$domain=' + this.hostname;
|
return this.s + '$domain=' + this.hostname;
|
||||||
@ -372,6 +394,10 @@ FilterPlainPrefix1Hostname.prototype.toSelfie = function() {
|
|||||||
this.hostname;
|
this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainPrefix1Hostname.compile = function(details, hostname) {
|
||||||
|
return details.f + '\t' + hostname;
|
||||||
|
};
|
||||||
|
|
||||||
FilterPlainPrefix1Hostname.fromSelfie = function(s) {
|
FilterPlainPrefix1Hostname.fromSelfie = function(s) {
|
||||||
var pos = s.indexOf('\t');
|
var pos = s.indexOf('\t');
|
||||||
return new FilterPlainPrefix1Hostname(s.slice(0, pos), s.slice(pos + 1));
|
return new FilterPlainPrefix1Hostname(s.slice(0, pos), s.slice(pos + 1));
|
||||||
@ -387,7 +413,7 @@ 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.fid = FilterPlainLeftAnchored.prototype.fid = '|a';
|
||||||
|
|
||||||
FilterPlainLeftAnchored.prototype.toString = function() {
|
FilterPlainLeftAnchored.prototype.toString = function() {
|
||||||
return '|' + this.s;
|
return '|' + this.s;
|
||||||
@ -397,6 +423,10 @@ FilterPlainLeftAnchored.prototype.toSelfie = function() {
|
|||||||
return this.s;
|
return this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainLeftAnchored.compile = function(details) {
|
||||||
|
return details.f;
|
||||||
|
};
|
||||||
|
|
||||||
FilterPlainLeftAnchored.fromSelfie = function(s) {
|
FilterPlainLeftAnchored.fromSelfie = function(s) {
|
||||||
return new FilterPlainLeftAnchored(s);
|
return new FilterPlainLeftAnchored(s);
|
||||||
};
|
};
|
||||||
@ -413,7 +443,7 @@ 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.fid = FilterPlainLeftAnchoredHostname.prototype.fid = '|ah';
|
||||||
|
|
||||||
FilterPlainLeftAnchoredHostname.prototype.toString = function() {
|
FilterPlainLeftAnchoredHostname.prototype.toString = function() {
|
||||||
return '|' + this.s + '$domain=' + this.hostname;
|
return '|' + this.s + '$domain=' + this.hostname;
|
||||||
@ -424,6 +454,10 @@ FilterPlainLeftAnchoredHostname.prototype.toSelfie = function() {
|
|||||||
this.hostname;
|
this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainLeftAnchoredHostname.compile = function(details, hostname) {
|
||||||
|
return details.f + '\t' + hostname;
|
||||||
|
};
|
||||||
|
|
||||||
FilterPlainLeftAnchoredHostname.fromSelfie = function(s) {
|
FilterPlainLeftAnchoredHostname.fromSelfie = function(s) {
|
||||||
var pos = s.indexOf('\t');
|
var pos = s.indexOf('\t');
|
||||||
return new FilterPlainLeftAnchoredHostname(s.slice(0, pos), s.slice(pos + 1));
|
return new FilterPlainLeftAnchoredHostname(s.slice(0, pos), s.slice(pos + 1));
|
||||||
@ -439,7 +473,7 @@ 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.fid = FilterPlainRightAnchored.prototype.fid = 'a|';
|
||||||
|
|
||||||
FilterPlainRightAnchored.prototype.toString = function() {
|
FilterPlainRightAnchored.prototype.toString = function() {
|
||||||
return this.s + '|';
|
return this.s + '|';
|
||||||
@ -449,6 +483,10 @@ FilterPlainRightAnchored.prototype.toSelfie = function() {
|
|||||||
return this.s;
|
return this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainRightAnchored.compile = function(details) {
|
||||||
|
return details.f;
|
||||||
|
};
|
||||||
|
|
||||||
FilterPlainRightAnchored.fromSelfie = function(s) {
|
FilterPlainRightAnchored.fromSelfie = function(s) {
|
||||||
return new FilterPlainRightAnchored(s);
|
return new FilterPlainRightAnchored(s);
|
||||||
};
|
};
|
||||||
@ -465,7 +503,7 @@ 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.fid = 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;
|
||||||
@ -476,6 +514,10 @@ FilterPlainRightAnchoredHostname.prototype.toSelfie = function() {
|
|||||||
this.hostname;
|
this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainRightAnchoredHostname.compile = function(details, hostname) {
|
||||||
|
return details.f + '\t' + hostname;
|
||||||
|
};
|
||||||
|
|
||||||
FilterPlainRightAnchoredHostname.fromSelfie = function(s) {
|
FilterPlainRightAnchoredHostname.fromSelfie = function(s) {
|
||||||
var pos = s.indexOf('\t');
|
var pos = s.indexOf('\t');
|
||||||
return new FilterPlainRightAnchoredHostname(s.slice(0, pos), s.slice(pos + 1));
|
return new FilterPlainRightAnchoredHostname(s.slice(0, pos), s.slice(pos + 1));
|
||||||
@ -500,7 +542,7 @@ FilterPlainHnAnchored.prototype.match = function(url, tokenBeg) {
|
|||||||
reURLPostHostnameAnchors.test(url.slice(pos + 3, tokenBeg)) === false;
|
reURLPostHostnameAnchors.test(url.slice(pos + 3, tokenBeg)) === false;
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterPlainHnAnchored.prototype.fid = 'h|a';
|
FilterPlainHnAnchored.fid = FilterPlainHnAnchored.prototype.fid = 'h|a';
|
||||||
|
|
||||||
FilterPlainHnAnchored.prototype.toString = function() {
|
FilterPlainHnAnchored.prototype.toString = function() {
|
||||||
return '||' + this.s;
|
return '||' + this.s;
|
||||||
@ -510,6 +552,10 @@ FilterPlainHnAnchored.prototype.toSelfie = function() {
|
|||||||
return this.s;
|
return this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterPlainHnAnchored.compile = function(details) {
|
||||||
|
return details.f;
|
||||||
|
};
|
||||||
|
|
||||||
FilterPlainHnAnchored.fromSelfie = function(s) {
|
FilterPlainHnAnchored.fromSelfie = function(s) {
|
||||||
return new FilterPlainHnAnchored(s);
|
return new FilterPlainHnAnchored(s);
|
||||||
};
|
};
|
||||||
@ -535,7 +581,7 @@ 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.fid = FilterSingleWildcard.prototype.fid = '*';
|
||||||
|
|
||||||
FilterSingleWildcard.prototype.toString = function() {
|
FilterSingleWildcard.prototype.toString = function() {
|
||||||
return this.lSegment + '*' + this.rSegment;
|
return this.lSegment + '*' + this.rSegment;
|
||||||
@ -547,6 +593,14 @@ FilterSingleWildcard.prototype.toSelfie = function() {
|
|||||||
this.tokenBeg;
|
this.tokenBeg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcard.compile = function(details) {
|
||||||
|
var s = details.f;
|
||||||
|
var pos = s.indexOf('*');
|
||||||
|
return s.slice(0, pos) + '\t' +
|
||||||
|
s.slice(pos + 1) + '\t' +
|
||||||
|
details.tokenBeg;
|
||||||
|
};
|
||||||
|
|
||||||
FilterSingleWildcard.fromSelfie = function(s) {
|
FilterSingleWildcard.fromSelfie = function(s) {
|
||||||
var args = s.split('\t');
|
var args = s.split('\t');
|
||||||
return new FilterSingleWildcard(args[0], args[1], atoi(args[2]));
|
return new FilterSingleWildcard(args[0], args[1], atoi(args[2]));
|
||||||
@ -568,7 +622,7 @@ 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.fid = 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;
|
||||||
@ -581,6 +635,15 @@ FilterSingleWildcardHostname.prototype.toSelfie = function() {
|
|||||||
this.hostname;
|
this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardHostname.compile = function(details, hostname) {
|
||||||
|
var s = details.f;
|
||||||
|
var pos = s.indexOf('*');
|
||||||
|
return s.slice(0, pos) + '\t' +
|
||||||
|
s.slice(pos + 1) + '\t' +
|
||||||
|
details.tokenBeg + '\t' +
|
||||||
|
hostname;
|
||||||
|
};
|
||||||
|
|
||||||
FilterSingleWildcardHostname.fromSelfie = function(s) {
|
FilterSingleWildcardHostname.fromSelfie = function(s) {
|
||||||
var args = s.split('\t');
|
var args = s.split('\t');
|
||||||
return new FilterSingleWildcardHostname(args[0], args[1], atoi(args[2]), args[3]);
|
return new FilterSingleWildcardHostname(args[0], args[1], atoi(args[2]), args[3]);
|
||||||
@ -598,7 +661,7 @@ 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.fid = FilterSingleWildcardPrefix0.prototype.fid = '0*';
|
||||||
|
|
||||||
FilterSingleWildcardPrefix0.prototype.toString = function() {
|
FilterSingleWildcardPrefix0.prototype.toString = function() {
|
||||||
return this.lSegment + '*' + this.rSegment;
|
return this.lSegment + '*' + this.rSegment;
|
||||||
@ -609,6 +672,12 @@ FilterSingleWildcardPrefix0.prototype.toSelfie = function() {
|
|||||||
this.rSegment;
|
this.rSegment;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardPrefix0.compile = function(details) {
|
||||||
|
var s = details.f;
|
||||||
|
var pos = s.indexOf('*');
|
||||||
|
return s.slice(0, pos) + '\t' + s.slice(pos + 1);
|
||||||
|
};
|
||||||
|
|
||||||
FilterSingleWildcardPrefix0.fromSelfie = function(s) {
|
FilterSingleWildcardPrefix0.fromSelfie = function(s) {
|
||||||
var pos = s.indexOf('\t');
|
var pos = s.indexOf('\t');
|
||||||
return new FilterSingleWildcardPrefix0(s.slice(0, pos), s.slice(pos + 1));
|
return new FilterSingleWildcardPrefix0(s.slice(0, pos), s.slice(pos + 1));
|
||||||
@ -628,7 +697,7 @@ 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.fid = 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;
|
||||||
@ -640,6 +709,14 @@ FilterSingleWildcardPrefix0Hostname.prototype.toSelfie = function() {
|
|||||||
this.hostname;
|
this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardPrefix0Hostname.compile = function(details, hostname) {
|
||||||
|
var s = details.f;
|
||||||
|
var pos = s.indexOf('*');
|
||||||
|
return s.slice(0, pos) + '\t' +
|
||||||
|
s.slice(pos + 1) + '\t' +
|
||||||
|
hostname;
|
||||||
|
};
|
||||||
|
|
||||||
FilterSingleWildcardPrefix0Hostname.fromSelfie = function(s) {
|
FilterSingleWildcardPrefix0Hostname.fromSelfie = function(s) {
|
||||||
var args = s.split('\t');
|
var args = s.split('\t');
|
||||||
return new FilterSingleWildcardPrefix0Hostname(args[0], args[1], args[2]);
|
return new FilterSingleWildcardPrefix0Hostname(args[0], args[1], args[2]);
|
||||||
@ -657,7 +734,7 @@ 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.fid = FilterSingleWildcardLeftAnchored.prototype.fid = '|*';
|
||||||
|
|
||||||
FilterSingleWildcardLeftAnchored.prototype.toString = function() {
|
FilterSingleWildcardLeftAnchored.prototype.toString = function() {
|
||||||
return '|' + this.lSegment + '*' + this.rSegment;
|
return '|' + this.lSegment + '*' + this.rSegment;
|
||||||
@ -668,6 +745,13 @@ FilterSingleWildcardLeftAnchored.prototype.toSelfie = function() {
|
|||||||
this.rSegment;
|
this.rSegment;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardLeftAnchored.compile = function(details) {
|
||||||
|
var s = details.f;
|
||||||
|
var pos = s.indexOf('*');
|
||||||
|
return s.slice(0, pos) + '\t' +
|
||||||
|
s.slice(pos + 1) + '\t';
|
||||||
|
};
|
||||||
|
|
||||||
FilterSingleWildcardLeftAnchored.fromSelfie = function(s) {
|
FilterSingleWildcardLeftAnchored.fromSelfie = function(s) {
|
||||||
var pos = s.indexOf('\t');
|
var pos = s.indexOf('\t');
|
||||||
return new FilterSingleWildcardLeftAnchored(s.slice(0, pos), s.slice(pos + 1));
|
return new FilterSingleWildcardLeftAnchored(s.slice(0, pos), s.slice(pos + 1));
|
||||||
@ -687,7 +771,7 @@ 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.fid = 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;
|
||||||
@ -699,6 +783,14 @@ FilterSingleWildcardLeftAnchoredHostname.prototype.toSelfie = function() {
|
|||||||
this.hostname;
|
this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardLeftAnchoredHostname.compile = function(details, hostname) {
|
||||||
|
var s = details.f;
|
||||||
|
var pos = s.indexOf('*');
|
||||||
|
return s.slice(0, pos) + '\t' +
|
||||||
|
s.slice(pos + 1) + '\t' +
|
||||||
|
hostname;
|
||||||
|
};
|
||||||
|
|
||||||
FilterSingleWildcardLeftAnchoredHostname.fromSelfie = function(s) {
|
FilterSingleWildcardLeftAnchoredHostname.fromSelfie = function(s) {
|
||||||
var args = s.split('\t');
|
var args = s.split('\t');
|
||||||
return new FilterSingleWildcardLeftAnchoredHostname(args[0], args[1], args[2]);
|
return new FilterSingleWildcardLeftAnchoredHostname(args[0], args[1], args[2]);
|
||||||
@ -716,7 +808,7 @@ 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.fid = FilterSingleWildcardRightAnchored.prototype.fid = '*|';
|
||||||
|
|
||||||
FilterSingleWildcardRightAnchored.prototype.toString = function() {
|
FilterSingleWildcardRightAnchored.prototype.toString = function() {
|
||||||
return this.lSegment + '*' + this.rSegment + '|';
|
return this.lSegment + '*' + this.rSegment + '|';
|
||||||
@ -727,6 +819,13 @@ FilterSingleWildcardRightAnchored.prototype.toSelfie = function() {
|
|||||||
this.rSegment;
|
this.rSegment;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardRightAnchored.compile = function(details) {
|
||||||
|
var s = details.f;
|
||||||
|
var pos = s.indexOf('*');
|
||||||
|
return s.slice(0, pos) + '\t' +
|
||||||
|
s.slice(pos + 1) + '\t';
|
||||||
|
};
|
||||||
|
|
||||||
FilterSingleWildcardRightAnchored.fromSelfie = function(s) {
|
FilterSingleWildcardRightAnchored.fromSelfie = function(s) {
|
||||||
var pos = s.indexOf('\t');
|
var pos = s.indexOf('\t');
|
||||||
return new FilterSingleWildcardRightAnchored(s.slice(0, pos), s.slice(pos + 1));
|
return new FilterSingleWildcardRightAnchored(s.slice(0, pos), s.slice(pos + 1));
|
||||||
@ -746,7 +845,7 @@ 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.fid = 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;
|
||||||
@ -758,6 +857,14 @@ FilterSingleWildcardRightAnchoredHostname.prototype.toSelfie = function() {
|
|||||||
this.hostname;
|
this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterSingleWildcardRightAnchoredHostname.compile = function(details, hostname) {
|
||||||
|
var s = details.f;
|
||||||
|
var pos = s.indexOf('*');
|
||||||
|
return s.slice(0, pos) + '\t' +
|
||||||
|
s.slice(pos + 1) + '\t' +
|
||||||
|
hostname;
|
||||||
|
};
|
||||||
|
|
||||||
FilterSingleWildcardRightAnchoredHostname.fromSelfie = function(s) {
|
FilterSingleWildcardRightAnchoredHostname.fromSelfie = function(s) {
|
||||||
var args = s.split('\t');
|
var args = s.split('\t');
|
||||||
return new FilterSingleWildcardRightAnchoredHostname(args[0], args[1], args[2]);
|
return new FilterSingleWildcardRightAnchoredHostname(args[0], args[1], args[2]);
|
||||||
@ -781,15 +888,18 @@ 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.fid = FilterManyWildcards.prototype.fid = '*+';
|
||||||
|
|
||||||
FilterManyWildcards.prototype.toString = function() {
|
FilterManyWildcards.prototype.toString = function() {
|
||||||
return this.s;
|
return this.s;
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterManyWildcards.prototype.toSelfie = function() {
|
FilterManyWildcards.prototype.toSelfie = function() {
|
||||||
return this.s + '\t' +
|
return this.s + '\t' + this.tokenBeg;
|
||||||
this.tokenBeg;
|
};
|
||||||
|
|
||||||
|
FilterManyWildcards.compile = function(details) {
|
||||||
|
return details.f + '\t' + details.tokenBeg;
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterManyWildcards.fromSelfie = function(s) {
|
FilterManyWildcards.fromSelfie = function(s) {
|
||||||
@ -811,7 +921,7 @@ 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.fid = FilterManyWildcardsHostname.prototype.fid = '*+h';
|
||||||
|
|
||||||
FilterManyWildcardsHostname.prototype.toString = function() {
|
FilterManyWildcardsHostname.prototype.toString = function() {
|
||||||
return this.s + '$domain=' + this.hostname;
|
return this.s + '$domain=' + this.hostname;
|
||||||
@ -823,6 +933,12 @@ FilterManyWildcardsHostname.prototype.toSelfie = function() {
|
|||||||
this.hostname;
|
this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterManyWildcardsHostname.compile = function(details, hostname) {
|
||||||
|
return details.f + '\t' +
|
||||||
|
details.tokenBeg + '\t' +
|
||||||
|
hostname;
|
||||||
|
};
|
||||||
|
|
||||||
FilterManyWildcardsHostname.fromSelfie = function(s) {
|
FilterManyWildcardsHostname.fromSelfie = function(s) {
|
||||||
var args = s.split('\t');
|
var args = s.split('\t');
|
||||||
return new FilterManyWildcardsHostname(args[0], atoi(args[1]), args[2]);
|
return new FilterManyWildcardsHostname(args[0], atoi(args[1]), args[2]);
|
||||||
@ -840,7 +956,7 @@ FilterRegex.prototype.match = function(url) {
|
|||||||
return this.re.test(url);
|
return this.re.test(url);
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterRegex.prototype.fid = '//';
|
FilterRegex.fid = FilterRegex.prototype.fid = '//';
|
||||||
|
|
||||||
FilterRegex.prototype.toString = function() {
|
FilterRegex.prototype.toString = function() {
|
||||||
return '/' + this.re.source + '/';
|
return '/' + this.re.source + '/';
|
||||||
@ -850,6 +966,10 @@ FilterRegex.prototype.toSelfie = function() {
|
|||||||
return this.re.source;
|
return this.re.source;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FilterRegex.compile = function(details) {
|
||||||
|
return details.f;
|
||||||
|
};
|
||||||
|
|
||||||
FilterRegex.fromSelfie = function(s) {
|
FilterRegex.fromSelfie = function(s) {
|
||||||
return new FilterRegex(s);
|
return new FilterRegex(s);
|
||||||
};
|
};
|
||||||
@ -867,15 +987,18 @@ FilterRegexHostname.prototype.match = function(url) {
|
|||||||
this.re.test(url);
|
this.re.test(url);
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterRegexHostname.prototype.fid = '//h';
|
FilterRegexHostname.fid = FilterRegexHostname.prototype.fid = '//h';
|
||||||
|
|
||||||
FilterRegexHostname.prototype.toString = function() {
|
FilterRegexHostname.prototype.toString = function() {
|
||||||
return '/' + this.re.source + '/$domain=' + this.hostname;
|
return '/' + this.re.source + '/$domain=' + this.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterRegexHostname.prototype.toSelfie = function() {
|
FilterRegexHostname.prototype.toSelfie = function() {
|
||||||
return this.re.source + '\t' +
|
return this.re.source + '\t' + this.hostname;
|
||||||
this.hostname;
|
};
|
||||||
|
|
||||||
|
FilterRegexHostname.compile = function(details, hostname) {
|
||||||
|
return details.f + '\t' + hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterRegexHostname.fromSelfie = function(s) {
|
FilterRegexHostname.fromSelfie = function(s) {
|
||||||
@ -981,12 +1104,12 @@ FilterHostnameDict.prototype.add = function(hn) {
|
|||||||
if ( typeof bucket === 'string' ) {
|
if ( typeof bucket === 'string' ) {
|
||||||
bucket = this.dict[key] = this.meltBucket(hn.len, bucket);
|
bucket = this.dict[key] = this.meltBucket(hn.len, bucket);
|
||||||
}
|
}
|
||||||
if ( bucket[hn] === undefined ) {
|
if ( bucket.hasOwnProperty(hn) ) {
|
||||||
bucket[hn] = true;
|
return false;
|
||||||
this.count += 1;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
bucket[hn] = true;
|
||||||
|
this.count += 1;
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterHostnameDict.prototype.freeze = function() {
|
FilterHostnameDict.prototype.freeze = function() {
|
||||||
@ -1041,7 +1164,7 @@ FilterHostnameDict.prototype.matchesExactly = function(hn) {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterHostnameDict.prototype.match = function(hn) {
|
FilterHostnameDict.prototype.match = function() {
|
||||||
// TODO: mind IP addresses
|
// TODO: mind IP addresses
|
||||||
|
|
||||||
var pos,
|
var pos,
|
||||||
@ -1058,7 +1181,7 @@ FilterHostnameDict.prototype.match = function(hn) {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterHostnameDict.prototype.fid = '{h}';
|
FilterHostnameDict.fid = FilterHostnameDict.prototype.fid = '{h}';
|
||||||
|
|
||||||
FilterHostnameDict.prototype.toString = function() {
|
FilterHostnameDict.prototype.toString = function() {
|
||||||
return this.h;
|
return this.h;
|
||||||
@ -1186,85 +1309,81 @@ FilterBucket.fromSelfie = function() {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var makeFilter = function(details) {
|
var getFilterClass = function(details) {
|
||||||
var s = details.f;
|
|
||||||
if ( details.isRegex ) {
|
if ( details.isRegex ) {
|
||||||
return new FilterRegex(s);
|
return FilterRegex;
|
||||||
}
|
}
|
||||||
|
var s = details.f;
|
||||||
var wcOffset = s.indexOf('*');
|
var wcOffset = s.indexOf('*');
|
||||||
if ( wcOffset !== -1 ) {
|
if ( wcOffset !== -1 ) {
|
||||||
if ( s.indexOf('*', wcOffset + 1) !== -1 ) {
|
if ( s.indexOf('*', wcOffset + 1) !== -1 ) {
|
||||||
return details.anchor === 0 ? new FilterManyWildcards(s, details.tokenBeg) : null;
|
return details.anchor === 0 ? FilterManyWildcards : null;
|
||||||
}
|
}
|
||||||
var lSegment = s.slice(0, wcOffset);
|
|
||||||
var rSegment = s.slice(wcOffset + 1);
|
|
||||||
if ( details.anchor < 0 ) {
|
if ( details.anchor < 0 ) {
|
||||||
return new FilterSingleWildcardLeftAnchored(lSegment, rSegment);
|
return FilterSingleWildcardLeftAnchored;
|
||||||
}
|
}
|
||||||
if ( details.anchor > 0 ) {
|
if ( details.anchor > 0 ) {
|
||||||
return new FilterSingleWildcardRightAnchored(lSegment, rSegment);
|
return FilterSingleWildcardRightAnchored;
|
||||||
}
|
}
|
||||||
if ( details.tokenBeg === 0 ) {
|
if ( details.tokenBeg === 0 ) {
|
||||||
return new FilterSingleWildcardPrefix0(lSegment, rSegment);
|
return FilterSingleWildcardPrefix0;
|
||||||
}
|
}
|
||||||
return new FilterSingleWildcard(lSegment, rSegment, details.tokenBeg);
|
return FilterSingleWildcard;
|
||||||
}
|
}
|
||||||
if ( details.anchor < 0 ) {
|
if ( details.anchor < 0 ) {
|
||||||
return new FilterPlainLeftAnchored(s);
|
return FilterPlainLeftAnchored;
|
||||||
}
|
}
|
||||||
if ( details.anchor > 0 ) {
|
if ( details.anchor > 0 ) {
|
||||||
return new FilterPlainRightAnchored(s);
|
return FilterPlainRightAnchored;
|
||||||
}
|
}
|
||||||
if ( details.hostnameAnchored ) {
|
if ( details.hostnameAnchored ) {
|
||||||
return new FilterPlainHnAnchored(s);
|
return FilterPlainHnAnchored;
|
||||||
}
|
}
|
||||||
if ( details.tokenBeg === 0 ) {
|
if ( details.tokenBeg === 0 ) {
|
||||||
return new FilterPlainPrefix0(s);
|
return FilterPlainPrefix0;
|
||||||
}
|
}
|
||||||
if ( details.tokenBeg === 1 ) {
|
if ( details.tokenBeg === 1 ) {
|
||||||
return new FilterPlainPrefix1(s);
|
return FilterPlainPrefix1;
|
||||||
}
|
}
|
||||||
return new FilterPlain(s, details.tokenBeg);
|
return FilterPlain;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var makeHostnameFilter = function(details, hostname) {
|
var getHostnameBasedFilterClass = function(details) {
|
||||||
var s = details.f;
|
|
||||||
if ( details.isRegex ) {
|
if ( details.isRegex ) {
|
||||||
return new FilterRegexHostname(s, hostname);
|
return FilterRegexHostname;
|
||||||
}
|
}
|
||||||
|
var s = details.f;
|
||||||
var wcOffset = s.indexOf('*');
|
var wcOffset = s.indexOf('*');
|
||||||
if ( wcOffset !== -1 ) {
|
if ( wcOffset !== -1 ) {
|
||||||
if ( s.indexOf('*', wcOffset + 1) !== -1 ) {
|
if ( s.indexOf('*', wcOffset + 1) !== -1 ) {
|
||||||
return details.anchor === 0 ? new FilterManyWildcardsHostname(s, details.tokenBeg, hostname) : null;
|
return details.anchor === 0 ? FilterManyWildcardsHostname : null;
|
||||||
}
|
}
|
||||||
var lSegment = s.slice(0, wcOffset);
|
|
||||||
var rSegment = s.slice(wcOffset + 1);
|
|
||||||
if ( details.anchor < 0 ) {
|
if ( details.anchor < 0 ) {
|
||||||
return new FilterSingleWildcardLeftAnchoredHostname(lSegment, rSegment, hostname);
|
return FilterSingleWildcardLeftAnchoredHostname;
|
||||||
}
|
}
|
||||||
if ( details.anchor > 0 ) {
|
if ( details.anchor > 0 ) {
|
||||||
return new FilterSingleWildcardRightAnchoredHostname(lSegment, rSegment, hostname);
|
return FilterSingleWildcardRightAnchoredHostname;
|
||||||
}
|
}
|
||||||
if ( details.tokenBeg === 0 ) {
|
if ( details.tokenBeg === 0 ) {
|
||||||
return new FilterSingleWildcardPrefix0Hostname(lSegment, rSegment, hostname);
|
return FilterSingleWildcardPrefix0Hostname;
|
||||||
}
|
}
|
||||||
return new FilterSingleWildcardHostname(lSegment, rSegment, details.tokenBeg, hostname);
|
return FilterSingleWildcardHostname;
|
||||||
}
|
}
|
||||||
if ( details.anchor < 0 ) {
|
if ( details.anchor < 0 ) {
|
||||||
return new FilterPlainLeftAnchoredHostname(s, hostname);
|
return FilterPlainLeftAnchoredHostname;
|
||||||
}
|
}
|
||||||
if ( details.anchor > 0 ) {
|
if ( details.anchor > 0 ) {
|
||||||
return new FilterPlainRightAnchoredHostname(s, hostname);
|
return FilterPlainRightAnchoredHostname;
|
||||||
}
|
}
|
||||||
if ( details.tokenBeg === 0 ) {
|
if ( details.tokenBeg === 0 ) {
|
||||||
return new FilterPlainPrefix0Hostname(s, hostname);
|
return FilterPlainPrefix0Hostname;
|
||||||
}
|
}
|
||||||
if ( details.tokenBeg === 1 ) {
|
if ( details.tokenBeg === 1 ) {
|
||||||
return new FilterPlainPrefix1Hostname(s, hostname);
|
return FilterPlainPrefix1Hostname;
|
||||||
}
|
}
|
||||||
return new FilterPlainHostname(s, details.tokenBeg, hostname);
|
return FilterPlainHostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -1615,8 +1734,8 @@ FilterContainer.prototype.reset = function() {
|
|||||||
this.allowFilterCount = 0;
|
this.allowFilterCount = 0;
|
||||||
this.blockFilterCount = 0;
|
this.blockFilterCount = 0;
|
||||||
this.duplicateCount = 0;
|
this.duplicateCount = 0;
|
||||||
|
this.duplicateBuster = {};
|
||||||
this.categories = Object.create(null);
|
this.categories = Object.create(null);
|
||||||
this.duplicates = Object.create(null);
|
|
||||||
this.filterParser.reset();
|
this.filterParser.reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1624,6 +1743,8 @@ FilterContainer.prototype.reset = function() {
|
|||||||
|
|
||||||
FilterContainer.prototype.freeze = function() {
|
FilterContainer.prototype.freeze = function() {
|
||||||
histogram('allFilters', this.categories);
|
histogram('allFilters', this.categories);
|
||||||
|
this.duplicateBuster = {};
|
||||||
|
|
||||||
var categories = this.categories;
|
var categories = this.categories;
|
||||||
var bucket;
|
var bucket;
|
||||||
for ( var k in categories ) {
|
for ( var k in categories ) {
|
||||||
@ -1632,13 +1753,43 @@ FilterContainer.prototype.freeze = function() {
|
|||||||
bucket.freeze();
|
bucket.freeze();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.duplicates = Object.create(null);
|
|
||||||
this.filterParser.reset();
|
this.filterParser.reset();
|
||||||
this.frozen = true;
|
this.frozen = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
FilterContainer.prototype.factories = {
|
||||||
|
'[]': FilterBucket,
|
||||||
|
'a': FilterPlain,
|
||||||
|
'ah': FilterPlainHostname,
|
||||||
|
'0a': FilterPlainPrefix0,
|
||||||
|
'0ah': FilterPlainPrefix0Hostname,
|
||||||
|
'1a': FilterPlainPrefix1,
|
||||||
|
'1ah': FilterPlainPrefix1Hostname,
|
||||||
|
'|a': FilterPlainLeftAnchored,
|
||||||
|
'|ah': FilterPlainLeftAnchoredHostname,
|
||||||
|
'a|': FilterPlainRightAnchored,
|
||||||
|
'a|h': FilterPlainRightAnchoredHostname,
|
||||||
|
'h|a': FilterPlainHnAnchored,
|
||||||
|
'*': FilterSingleWildcard,
|
||||||
|
'*h': FilterSingleWildcardHostname,
|
||||||
|
'0*': FilterSingleWildcardPrefix0,
|
||||||
|
'0*h': FilterSingleWildcardPrefix0Hostname,
|
||||||
|
'|*': FilterSingleWildcardLeftAnchored,
|
||||||
|
'|*h': FilterSingleWildcardLeftAnchoredHostname,
|
||||||
|
'*|': FilterSingleWildcardRightAnchored,
|
||||||
|
'*|h': FilterSingleWildcardRightAnchoredHostname,
|
||||||
|
'*+': FilterManyWildcards,
|
||||||
|
'*+h': FilterManyWildcardsHostname,
|
||||||
|
'//': FilterRegex,
|
||||||
|
'//h': FilterRegexHostname,
|
||||||
|
'{h}': FilterHostnameDict
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.toSelfie = function() {
|
FilterContainer.prototype.toSelfie = function() {
|
||||||
var categoryToSelfie = function(dict) {
|
var categoryToSelfie = function(dict) {
|
||||||
var selfie = [];
|
var selfie = [];
|
||||||
@ -1697,34 +1848,6 @@ FilterContainer.prototype.fromSelfie = function(selfie) {
|
|||||||
this.blockFilterCount = selfie.blockFilterCount;
|
this.blockFilterCount = selfie.blockFilterCount;
|
||||||
this.duplicateCount = selfie.duplicateCount;
|
this.duplicateCount = selfie.duplicateCount;
|
||||||
|
|
||||||
var factories = {
|
|
||||||
'[]': FilterBucket,
|
|
||||||
'a': FilterPlain,
|
|
||||||
'ah': FilterPlainHostname,
|
|
||||||
'0a': FilterPlainPrefix0,
|
|
||||||
'0ah': FilterPlainPrefix0Hostname,
|
|
||||||
'1a': FilterPlainPrefix1,
|
|
||||||
'1ah': FilterPlainPrefix1Hostname,
|
|
||||||
'|a': FilterPlainLeftAnchored,
|
|
||||||
'|ah': FilterPlainLeftAnchoredHostname,
|
|
||||||
'a|': FilterPlainRightAnchored,
|
|
||||||
'a|h': FilterPlainRightAnchoredHostname,
|
|
||||||
'h|a': FilterPlainHnAnchored,
|
|
||||||
'*': FilterSingleWildcard,
|
|
||||||
'*h': FilterSingleWildcardHostname,
|
|
||||||
'0*': FilterSingleWildcardPrefix0,
|
|
||||||
'0*h': FilterSingleWildcardPrefix0Hostname,
|
|
||||||
'|*': FilterSingleWildcardLeftAnchored,
|
|
||||||
'|*h': FilterSingleWildcardLeftAnchoredHostname,
|
|
||||||
'*|': FilterSingleWildcardRightAnchored,
|
|
||||||
'*|h': FilterSingleWildcardRightAnchoredHostname,
|
|
||||||
'*+': FilterManyWildcards,
|
|
||||||
'*+h': FilterManyWildcardsHostname,
|
|
||||||
'//': FilterRegex,
|
|
||||||
'//h': FilterRegexHostname,
|
|
||||||
'{h}': FilterHostnameDict
|
|
||||||
};
|
|
||||||
|
|
||||||
var catKey, tokenKey;
|
var catKey, tokenKey;
|
||||||
var dict = this.categories, subdict;
|
var dict = this.categories, subdict;
|
||||||
var bucket = null;
|
var bucket = null;
|
||||||
@ -1752,7 +1875,7 @@ FilterContainer.prototype.fromSelfie = function(selfie) {
|
|||||||
bucket = null;
|
bucket = null;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
factory = factories[what];
|
factory = this.factories[what];
|
||||||
if ( bucket === null ) {
|
if ( bucket === null ) {
|
||||||
bucket = subdict[tokenKey] = factory.fromSelfie(line.slice(pos + 1));
|
bucket = subdict[tokenKey] = factory.fromSelfie(line.slice(pos + 1));
|
||||||
continue;
|
continue;
|
||||||
@ -1766,12 +1889,12 @@ FilterContainer.prototype.fromSelfie = function(selfie) {
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.makeCategoryKey = function(category) {
|
FilterContainer.prototype.makeCategoryKey = function(category) {
|
||||||
return String.fromCharCode(category);
|
return category.toString(16);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.add = function(raw) {
|
FilterContainer.prototype.compile = function(raw, out) {
|
||||||
// ORDER OF TESTS IS IMPORTANT!
|
// ORDER OF TESTS IS IMPORTANT!
|
||||||
|
|
||||||
// Ignore empty lines
|
// Ignore empty lines
|
||||||
@ -1795,40 +1918,22 @@ FilterContainer.prototype.add = function(raw) {
|
|||||||
|
|
||||||
// Ignore filters with unsupported options
|
// Ignore filters with unsupported options
|
||||||
if ( parsed.unsupported ) {
|
if ( parsed.unsupported ) {
|
||||||
this.rejectedCount += 1;
|
|
||||||
//console.log('static-net-filtering.js > FilterContainer.add(): unsupported filter "%s"', raw);
|
//console.log('static-net-filtering.js > FilterContainer.add(): unsupported filter "%s"', raw);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.processedFilterCount += 1;
|
|
||||||
this.acceptedCount += 1;
|
|
||||||
|
|
||||||
// Pure hostnames, use more efficient liquid dict
|
// Pure hostnames, use more efficient liquid dict
|
||||||
// https://github.com/gorhill/uBlock/issues/665
|
// https://github.com/gorhill/uBlock/issues/665
|
||||||
// Create a dict keyed on request type etc.
|
// Create a dict keyed on request type etc.
|
||||||
if ( parsed.hostnamePure && this.addHostnameOnlyFilter(parsed) ) {
|
if ( parsed.hostnamePure && this.compileHostnameOnlyFilter(parsed, out) ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( this.duplicates[s] ) {
|
var r = this.compileFilter(parsed, out);
|
||||||
//console.log('static-net-filtering.js > FilterContainer.add(): duplicate filter "%s"', raw);
|
|
||||||
this.duplicateCount++;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( this.frozen === false ) {
|
|
||||||
this.duplicates[s] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var r = this.addFilter(parsed);
|
|
||||||
if ( r === false ) {
|
if ( r === false ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( parsed.action ) {
|
|
||||||
this.allowFilterCount += 1;
|
|
||||||
} else {
|
|
||||||
this.blockFilterCount += 1;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1836,55 +1941,37 @@ FilterContainer.prototype.add = function(raw) {
|
|||||||
|
|
||||||
// Using fast/compact dictionary when filter is a (or portion of) pure hostname.
|
// Using fast/compact dictionary when filter is a (or portion of) pure hostname.
|
||||||
|
|
||||||
FilterContainer.prototype.addHostnameOnlyFilter = function(parsed) {
|
FilterContainer.prototype.compileHostnameOnlyFilter = function(parsed, out) {
|
||||||
// Can't fit the filter in a pure hostname dictionary.
|
// Can't fit the filter in a pure hostname dictionary.
|
||||||
if ( parsed.hostnames.length !== 0 || parsed.notHostnames.length !== 0 ) {
|
if ( parsed.hostnames.length !== 0 || parsed.notHostnames.length !== 0 ) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var isNewFilter = false;
|
|
||||||
var party = AnyParty;
|
var party = AnyParty;
|
||||||
if ( parsed.firstParty !== parsed.thirdParty ) {
|
if ( parsed.firstParty !== parsed.thirdParty ) {
|
||||||
party = parsed.firstParty ? FirstParty : ThirdParty;
|
party = parsed.firstParty ? FirstParty : ThirdParty;
|
||||||
}
|
}
|
||||||
var keyShard = parsed.action | parsed.important | party;
|
var keyShard = parsed.action | parsed.important | party;
|
||||||
var key, bucket;
|
|
||||||
var type = parsed.types >>> 1 || 1; // bit 0 is unused; also, default to AnyType
|
var type = parsed.types >>> 1 || 1; // bit 0 is unused; also, default to AnyType
|
||||||
var bitOffset = 1;
|
var bitOffset = 1;
|
||||||
while ( type !== 0 ) {
|
while ( type !== 0 ) {
|
||||||
if ( type & 1 ) {
|
if ( type & 1 ) {
|
||||||
key = this.makeCategoryKey(keyShard | (bitOffset << 4));
|
out.push(
|
||||||
bucket = this.categories[key];
|
'n\v' +
|
||||||
if ( bucket === undefined ) {
|
this.makeCategoryKey(keyShard | (bitOffset << 4)) + '\v' +
|
||||||
bucket = this.categories[key] = Object.create(null);
|
'.\v' +
|
||||||
}
|
parsed.f
|
||||||
if ( bucket['.'] === undefined ) {
|
);
|
||||||
bucket['.'] = new FilterHostnameDict();
|
|
||||||
}
|
|
||||||
if ( bucket['.'].add(parsed.f) ) {
|
|
||||||
isNewFilter = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
bitOffset += 1;
|
bitOffset += 1;
|
||||||
type >>>= 1;
|
type >>>= 1;
|
||||||
}
|
}
|
||||||
// https://github.com/gorhill/uBlock/issues/719
|
|
||||||
// Count whole filter, not its decomposed versions
|
|
||||||
if ( isNewFilter ) {
|
|
||||||
if ( parsed.action ) {
|
|
||||||
this.allowFilterCount += 1;
|
|
||||||
} else {
|
|
||||||
this.blockFilterCount += 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.duplicateCount += 1;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.addFilter = function(parsed) {
|
FilterContainer.prototype.compileFilter = function(parsed, out) {
|
||||||
parsed.makeToken();
|
parsed.makeToken();
|
||||||
if ( parsed.token === '' ) {
|
if ( parsed.token === '' ) {
|
||||||
console.error('static-net-filtering.js > FilterContainer.addFilter("%s"): can\'t tokenize', parsed.f);
|
console.error('static-net-filtering.js > FilterContainer.addFilter("%s"): can\'t tokenize', parsed.f);
|
||||||
@ -1896,28 +1983,28 @@ FilterContainer.prototype.addFilter = function(parsed) {
|
|||||||
party = parsed.firstParty ? FirstParty : ThirdParty;
|
party = parsed.firstParty ? FirstParty : ThirdParty;
|
||||||
}
|
}
|
||||||
|
|
||||||
var filter;
|
var filterClass;
|
||||||
var i = parsed.hostnames.length;
|
var i = parsed.hostnames.length;
|
||||||
var j = parsed.notHostnames.length;
|
var j = parsed.notHostnames.length;
|
||||||
|
|
||||||
// Applies to all domains without exceptions
|
// Applies to all domains without exceptions
|
||||||
if ( i === 0 && j === 0 ) {
|
if ( i === 0 && j === 0 ) {
|
||||||
filter = makeFilter(parsed);
|
filterClass = getFilterClass(parsed);
|
||||||
if ( !filter ) {
|
if ( filterClass === null ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.addFilterEntry(filter, parsed, party);
|
this.compileToAtomicFilter(filterClass, parsed, party, out);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Applies to specific domains
|
// Applies to specific domains
|
||||||
if ( i !== 0 ) {
|
if ( i !== 0 ) {
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
filter = makeHostnameFilter(parsed, parsed.hostnames[i]);
|
filterClass = getHostnameBasedFilterClass(parsed);
|
||||||
if ( !filter ) {
|
if ( filterClass === null ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.addFilterEntry(filter, parsed, party);
|
this.compileToAtomicFilter(filterClass, parsed, party, out, parsed.hostnames[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// No exceptions
|
// No exceptions
|
||||||
@ -1930,13 +2017,13 @@ FilterContainer.prototype.addFilter = function(parsed) {
|
|||||||
// Example:
|
// Example:
|
||||||
// - ||adm.fwmrm.net/p/msnbc_live/$object-subrequest,third-party,domain=~msnbc.msn.com|~www.nbcnews.com
|
// - ||adm.fwmrm.net/p/msnbc_live/$object-subrequest,third-party,domain=~msnbc.msn.com|~www.nbcnews.com
|
||||||
if ( i === 0 ) {
|
if ( i === 0 ) {
|
||||||
filter = makeFilter(parsed);
|
filterClass = getFilterClass(parsed);
|
||||||
if ( !filter ) {
|
if ( filterClass === null ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// https://github.com/gorhill/uBlock/issues/251
|
// https://github.com/gorhill/uBlock/issues/251
|
||||||
// Apply third-party option if it is present
|
// Apply third-party option if it is present
|
||||||
this.addFilterEntry(filter, parsed, party);
|
this.compileToAtomicFilter(filterClass, parsed, party, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cases:
|
// Cases:
|
||||||
@ -1948,8 +2035,8 @@ FilterContainer.prototype.addFilter = function(parsed) {
|
|||||||
// Reverse purpose of filter
|
// Reverse purpose of filter
|
||||||
parsed.action ^= ToggleAction;
|
parsed.action ^= ToggleAction;
|
||||||
while ( j-- ) {
|
while ( j-- ) {
|
||||||
filter = makeHostnameFilter(parsed, parsed.notHostnames[j]);
|
filterClass = getHostnameBasedFilterClass(parsed);
|
||||||
if ( !filter ) {
|
if ( filterClass === null ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// https://github.com/gorhill/uBlock/issues/191#issuecomment-53654024
|
// https://github.com/gorhill/uBlock/issues/191#issuecomment-53654024
|
||||||
@ -1958,20 +2045,26 @@ FilterContainer.prototype.addFilter = function(parsed) {
|
|||||||
if ( parsed.action === BlockAction ) {
|
if ( parsed.action === BlockAction ) {
|
||||||
parsed.important = Important;
|
parsed.important = Important;
|
||||||
}
|
}
|
||||||
this.addFilterEntry(filter, parsed, party);
|
this.compileToAtomicFilter(filterClass, parsed, party, out, parsed.notHostnames[j]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.addFilterEntry = function(filter, parsed, party) {
|
FilterContainer.prototype.compileToAtomicFilter = function(filterClass, parsed, party, out, hostname) {
|
||||||
var bits = parsed.action | parsed.important | party;
|
var bits = parsed.action | parsed.important | party;
|
||||||
var type = parsed.types >>> 1 || 1; // bit 0 is unused; also, default to AnyType
|
var type = parsed.types >>> 1 || 1; // bit 0 is unused; also, default to AnyType
|
||||||
var bitOffset = 1;
|
var bitOffset = 1;
|
||||||
while ( type !== 0 ) {
|
while ( type !== 0 ) {
|
||||||
if ( type & 1 ) {
|
if ( type & 1 ) {
|
||||||
this.addToCategory(bits | (bitOffset << 4), parsed.token, filter);
|
out.push(
|
||||||
|
'n\v' +
|
||||||
|
this.makeCategoryKey(bits | (bitOffset << 4)) + '\v' +
|
||||||
|
parsed.token + '\v' +
|
||||||
|
filterClass.fid + '\v' +
|
||||||
|
filterClass.compile(parsed, hostname)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
bitOffset += 1;
|
bitOffset += 1;
|
||||||
type >>>= 1;
|
type >>>= 1;
|
||||||
@ -1980,22 +2073,60 @@ FilterContainer.prototype.addFilterEntry = function(filter, parsed, party) {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.addToCategory = function(category, tokenKey, filter) {
|
FilterContainer.prototype.fromCompiledContent = function(text, lineBeg) {
|
||||||
var categoryKey = this.makeCategoryKey(category);
|
var lineEnd;
|
||||||
var categoryBucket = this.categories[categoryKey];
|
var textEnd = text.length;
|
||||||
if ( !categoryBucket ) {
|
var line, fields, bucket, entry, factory, filter;
|
||||||
categoryBucket = this.categories[categoryKey] = Object.create(null);
|
|
||||||
|
while ( lineBeg < textEnd ) {
|
||||||
|
if ( text.charAt(lineBeg) !== 'n' ) {
|
||||||
|
return lineBeg;
|
||||||
|
}
|
||||||
|
lineEnd = text.indexOf('\n', lineBeg);
|
||||||
|
if ( lineEnd === -1 ) {
|
||||||
|
lineEnd = textEnd;
|
||||||
|
}
|
||||||
|
line = text.slice(lineBeg + 2, lineEnd);
|
||||||
|
fields = line.split('\v');
|
||||||
|
lineBeg = lineEnd + 1;
|
||||||
|
|
||||||
|
this.acceptedCount += 1;
|
||||||
|
|
||||||
|
bucket = this.categories[fields[0]];
|
||||||
|
if ( bucket === undefined ) {
|
||||||
|
bucket = this.categories[fields[0]] = Object.create(null);
|
||||||
|
}
|
||||||
|
entry = bucket[fields[1]];
|
||||||
|
|
||||||
|
if ( fields[1] === '.' ) {
|
||||||
|
if ( entry === undefined ) {
|
||||||
|
entry = bucket['.'] = new FilterHostnameDict();
|
||||||
|
}
|
||||||
|
if ( entry.add(fields[2]) === false ) {
|
||||||
|
this.duplicateCount += 1;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( this.duplicateBuster.hasOwnProperty(line) ) {
|
||||||
|
this.duplicateCount += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.duplicateBuster[line] = true;
|
||||||
|
|
||||||
|
factory = this.factories[fields[2]];
|
||||||
|
filter = factory.fromSelfie(fields[3]);
|
||||||
|
if ( entry === undefined ) {
|
||||||
|
bucket[fields[1]] = filter;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( entry.fid === '[]' ) {
|
||||||
|
entry.add(filter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bucket[fields[1]] = new FilterBucket(entry, filter);
|
||||||
}
|
}
|
||||||
var filterEntry = categoryBucket[tokenKey];
|
return textEnd;
|
||||||
if ( filterEntry === undefined ) {
|
|
||||||
categoryBucket[tokenKey] = filter;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ( filterEntry.fid === '[]' ) {
|
|
||||||
filterEntry.add(filter);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
categoryBucket[tokenKey] = new FilterBucket(filterEntry, filter);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -2275,7 +2406,7 @@ FilterContainer.prototype.matchString = function(context) {
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.getFilterCount = function() {
|
FilterContainer.prototype.getFilterCount = function() {
|
||||||
return this.blockFilterCount + this.allowFilterCount;
|
return this.acceptedCount - this.duplicateCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
Home: https://github.com/gorhill/uBlock
|
Home: https://github.com/gorhill/uBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global µBlock, vAPI, punycode, publicSuffixList */
|
/* global YaMD5, µBlock, vAPI, punycode, publicSuffixList */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
@ -53,6 +53,21 @@
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
µBlock.saveSystemSettings = function() {
|
||||||
|
vAPI.storage.set(this.systemSettings, this.noopFunc);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
µBlock.loadSystemSettings = function(callback) {
|
||||||
|
vAPI.storage.get({
|
||||||
|
compiledMagic: '',
|
||||||
|
selfieMagic: ''
|
||||||
|
}, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
// Save local settings regularly. Not critical.
|
// Save local settings regularly. Not critical.
|
||||||
|
|
||||||
µBlock.asyncJobs.add(
|
µBlock.asyncJobs.add(
|
||||||
@ -133,17 +148,30 @@
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.appendUserFilters = function(content) {
|
µBlock.appendUserFilters = function(content) {
|
||||||
|
if ( content.length === 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var µb = this;
|
var µb = this;
|
||||||
|
|
||||||
|
var onCompiledListLoaded = function(details) {
|
||||||
|
var snfe = µb.staticNetFilteringEngine;
|
||||||
|
var cfe = µb.cosmeticFilteringEngine;
|
||||||
|
var acceptedCount = snfe.acceptedCount + cfe.acceptedCount;
|
||||||
|
var duplicateCount = snfe.duplicateCount + cfe.duplicateCount;
|
||||||
|
µb.applyCompiledFilters(details.content);
|
||||||
|
var entry = µb.remoteBlacklists[µb.userFiltersPath];
|
||||||
|
entry.entryCount = snfe.acceptedCount + cfe.acceptedCount - acceptedCount;
|
||||||
|
entry.entryUsedCount = entry.entryCount - snfe.duplicateCount - cfe.duplicateCount + duplicateCount;
|
||||||
|
µb.staticNetFilteringEngine.freeze();
|
||||||
|
µb.cosmeticFilteringEngine.freeze();
|
||||||
|
};
|
||||||
|
|
||||||
var onSaved = function(details) {
|
var onSaved = function(details) {
|
||||||
if ( details.error ) {
|
if ( details.error ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
µb.mergeFilterText(content);
|
µb.getCompiledFilterList(µb.userFiltersPath, onCompiledListLoaded);
|
||||||
µb.staticNetFilteringEngine.freeze();
|
|
||||||
µb.cosmeticFilteringEngine.freeze();
|
|
||||||
µb.destroySelfie();
|
|
||||||
µb.toSelfieAsync();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var onLoaded = function(details) {
|
var onLoaded = function(details) {
|
||||||
@ -153,12 +181,10 @@
|
|||||||
if ( details.content.indexOf(content.trim()) !== -1 ) {
|
if ( details.content.indexOf(content.trim()) !== -1 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
µb.saveUserFilters(details.content + '\n' + content, onSaved);
|
µb.saveUserFilters(details.content.trim() + '\n' + content.trim(), onSaved);
|
||||||
};
|
};
|
||||||
|
|
||||||
if ( content.length > 0 ) {
|
this.loadUserFilters(onLoaded);
|
||||||
this.loadUserFilters(onLoaded);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -260,111 +286,152 @@
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
µBlock.createShortUniqueId = function(path) {
|
||||||
|
var md5 = YaMD5.hashStr(path);
|
||||||
|
return md5.slice(0, 4) + md5.slice(-4);
|
||||||
|
};
|
||||||
|
|
||||||
|
µBlock.createShortUniqueId.idLength = 8;
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.loadFilterLists = function(callback) {
|
µBlock.loadFilterLists = function(callback) {
|
||||||
|
|
||||||
|
//quickProfiler.start('µBlock.loadFilterLists()');
|
||||||
|
|
||||||
var µb = this;
|
var µb = this;
|
||||||
var filterlistCount;
|
var filterlistsCount = 0;
|
||||||
|
|
||||||
if ( typeof callback !== 'function' ) {
|
if ( typeof callback !== 'function' ) {
|
||||||
callback = this.noopFunc;
|
callback = this.noopFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
var loadBlacklistsEnd = function() {
|
var onDone = function() {
|
||||||
µb.staticNetFilteringEngine.freeze();
|
µb.staticNetFilteringEngine.freeze();
|
||||||
µb.cosmeticFilteringEngine.freeze();
|
µb.cosmeticFilteringEngine.freeze();
|
||||||
vAPI.storage.set({ 'remoteBlacklists': µb.remoteBlacklists });
|
vAPI.storage.set({ 'remoteBlacklists': µb.remoteBlacklists });
|
||||||
vAPI.messaging.broadcast({ what: 'loadUbiquitousBlacklistCompleted' });
|
vAPI.messaging.broadcast({ what: 'allFilterListsReloaded' });
|
||||||
µb.toSelfieAsync();
|
|
||||||
callback();
|
callback();
|
||||||
|
|
||||||
|
µb.toSelfieAsync();
|
||||||
|
|
||||||
|
//quickProfiler.stop(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
var mergeBlacklist = function(details) {
|
var applyCompiledFilters = function(path, compiled) {
|
||||||
µb.mergeFilterList(details);
|
var snfe = µb.staticNetFilteringEngine;
|
||||||
filterlistCount -= 1;
|
var cfe = µb.cosmeticFilteringEngine;
|
||||||
if ( filterlistCount === 0 ) {
|
var acceptedCount = snfe.acceptedCount + cfe.acceptedCount;
|
||||||
loadBlacklistsEnd();
|
var duplicateCount = snfe.duplicateCount + cfe.duplicateCount;
|
||||||
|
µb.applyCompiledFilters(compiled);
|
||||||
|
if ( µb.remoteBlacklists.hasOwnProperty(path) ) {
|
||||||
|
var entry = µb.remoteBlacklists[path];
|
||||||
|
entry.entryCount = snfe.acceptedCount + cfe.acceptedCount - acceptedCount;
|
||||||
|
entry.entryUsedCount = entry.entryCount - snfe.duplicateCount - cfe.duplicateCount + duplicateCount;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var loadBlacklistsStart = function(lists) {
|
var onCompiledListLoaded = function(details) {
|
||||||
µb.remoteBlacklists = lists;
|
applyCompiledFilters(details.path, details.content);
|
||||||
µb.staticNetFilteringEngine.reset();
|
filterlistsCount -= 1;
|
||||||
µb.cosmeticFilteringEngine.reset();
|
if ( filterlistsCount === 0 ) {
|
||||||
µb.destroySelfie();
|
onDone();
|
||||||
var locations = Object.keys(lists);
|
}
|
||||||
filterlistCount = locations.length;
|
};
|
||||||
|
|
||||||
// Load all filter lists which are not disabled
|
var onFilterListsReady = function(lists) {
|
||||||
var location;
|
µb.remoteBlacklists = lists;
|
||||||
while ( location = locations.pop() ) {
|
|
||||||
// rhill 2013-12-09:
|
µb.cosmeticFilteringEngine.reset();
|
||||||
// Ignore list if disabled
|
µb.staticNetFilteringEngine.reset();
|
||||||
// https://github.com/gorhill/httpswitchboard/issues/78
|
µb.destroySelfie();
|
||||||
if ( lists[location].off ) {
|
|
||||||
filterlistCount -= 1;
|
// We need to build a complete list of assets to pull first: this is
|
||||||
|
// because it *may* happens that some load operations are synchronous:
|
||||||
|
// This happens for assets which do not exist, ot assets with no
|
||||||
|
// content.
|
||||||
|
var toLoad = [];
|
||||||
|
for ( var path in lists ) {
|
||||||
|
if ( lists.hasOwnProperty(path) === false ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
µb.assets.get(location, mergeBlacklist);
|
if ( lists[path].off ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
toLoad.push(path);
|
||||||
}
|
}
|
||||||
// https://github.com/gorhill/uBlock/issues/695
|
filterlistsCount = toLoad.length;
|
||||||
// It may happen not a single filter list is selected
|
if ( filterlistsCount === 0 ) {
|
||||||
if ( filterlistCount === 0 ) {
|
onDone();
|
||||||
loadBlacklistsEnd();
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var i = toLoad.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
µb.getCompiledFilterList(toLoad[i], onCompiledListLoaded);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getAvailableLists(loadBlacklistsStart);
|
this.getAvailableLists(onFilterListsReady);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.mergeFilterList = function(details) {
|
µBlock.getCompiledFilterListPath = function(path) {
|
||||||
// console.log('µBlock > mergeFilterList from "%s": "%s..."', details.path, details.content.slice(0, 40));
|
return 'cache://compiled-filter-list:' + this.createShortUniqueId(path);
|
||||||
|
};
|
||||||
|
|
||||||
var staticNetFilteringEngine = this.staticNetFilteringEngine;
|
/******************************************************************************/
|
||||||
var cosmeticFilteringEngine = this.cosmeticFilteringEngine;
|
|
||||||
var duplicateCount = staticNetFilteringEngine.duplicateCount + cosmeticFilteringEngine.duplicateCount;
|
|
||||||
var acceptedCount = staticNetFilteringEngine.acceptedCount + cosmeticFilteringEngine.acceptedCount;
|
|
||||||
|
|
||||||
this.mergeFilterText(details.content);
|
µBlock.getCompiledFilterList = function(path, callback) {
|
||||||
|
var compiledPath = this.getCompiledFilterListPath(path);
|
||||||
|
var µb = this;
|
||||||
|
|
||||||
// For convenience, store the number of entries for this
|
var onRawListLoaded = function(details) {
|
||||||
// blacklist, user might be happy to know this information.
|
if ( details.content !== '' ) {
|
||||||
duplicateCount = staticNetFilteringEngine.duplicateCount + cosmeticFilteringEngine.duplicateCount - duplicateCount;
|
//console.debug('µBlock.getCompiledFilterList/onRawListLoaded: compiling "%s"', path);
|
||||||
acceptedCount = staticNetFilteringEngine.acceptedCount + cosmeticFilteringEngine.acceptedCount - acceptedCount;
|
details.content = µb.compileFilters(details.content);
|
||||||
|
µb.assets.put(compiledPath, details.content);
|
||||||
var filterListMeta = this.remoteBlacklists[details.path];
|
|
||||||
|
|
||||||
filterListMeta.entryCount = acceptedCount;
|
|
||||||
filterListMeta.entryUsedCount = acceptedCount - duplicateCount;
|
|
||||||
|
|
||||||
// Try to extract a human-friendly name (works only for
|
|
||||||
// ABP-compatible filter lists)
|
|
||||||
if ( filterListMeta.title === '' ) {
|
|
||||||
var matches = details.content.slice(0, 1024).match(/(?:^|\n)!\s*Title:([^\n]+)/i);
|
|
||||||
if ( matches !== null ) {
|
|
||||||
filterListMeta.title = matches[1].trim();
|
|
||||||
}
|
}
|
||||||
}
|
callback(details);
|
||||||
|
};
|
||||||
|
|
||||||
|
var onCompiledListLoaded = function(details) {
|
||||||
|
if ( details.content === '' ) {
|
||||||
|
//console.debug('µBlock.getCompiledFilterList/onCompiledListLoaded: no compiled version for "%s"', path);
|
||||||
|
µb.assets.get(path, onRawListLoaded);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//console.debug('µBlock.getCompiledFilterList/onCompiledListLoaded: using compiled version for "%s"', path);
|
||||||
|
details.path = path;
|
||||||
|
callback(details);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assets.get(compiledPath, onCompiledListLoaded);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.mergeFilterText = function(rawText) {
|
µBlock.purgeCompiledFilterList = function(path) {
|
||||||
|
this.assets.purge(this.getCompiledFilterListPath(path));
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
µBlock.compileFilters = function(rawText) {
|
||||||
var rawEnd = rawText.length;
|
var rawEnd = rawText.length;
|
||||||
|
var compiledFilters = [];
|
||||||
|
|
||||||
// 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 staticNetFilteringEngine = this.staticNetFilteringEngine;
|
var staticNetFilteringEngine = this.staticNetFilteringEngine;
|
||||||
var cosmeticFilteringEngine = this.cosmeticFilteringEngine;
|
var cosmeticFilteringEngine = this.cosmeticFilteringEngine;
|
||||||
var parseCosmeticFilters = this.userSettings.parseAllABPHideFilters;
|
|
||||||
|
|
||||||
var reIsCosmeticFilter = /#[@#]/;
|
|
||||||
var reIsWhitespaceChar = /\s/;
|
var reIsWhitespaceChar = /\s/;
|
||||||
var reMaybeLocalIp = /^[\d:f]/;
|
var reMaybeLocalIp = /^[\d:f]/;
|
||||||
var reIsLocalhostRedirect = /\s+(?:broadcasthost|local|localhost|localhost\.localdomain)(?=\s|$)/;
|
var reIsLocalhostRedirect = /\s+(?:broadcasthost|local|localhost|localhost\.localdomain)(?=\s|$)/;
|
||||||
var reLocalIp = /^(?:0\.0\.0\.0|127\.0\.0\.1|::1|fe80::1%lo0)/;
|
var reLocalIp = /^(?:0\.0\.0\.0|127\.0\.0\.1|::1|fe80::1%lo0)/;
|
||||||
//var reAsciiSegment = /^[\x21-\x7e]+$/;
|
|
||||||
var lineBeg = 0, lineEnd, currentLineBeg;
|
var lineBeg = 0, lineEnd, currentLineBeg;
|
||||||
var line, lineRaw, c, pos;
|
var line, lineRaw, c, pos;
|
||||||
|
|
||||||
@ -396,11 +463,7 @@
|
|||||||
|
|
||||||
// Parse or skip cosmetic filters
|
// Parse or skip cosmetic filters
|
||||||
// All cosmetic filters are caught here
|
// All cosmetic filters are caught here
|
||||||
if ( parseCosmeticFilters ) {
|
if ( cosmeticFilteringEngine.compile(line, compiledFilters) ) {
|
||||||
if ( cosmeticFilteringEngine.add(line) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else if ( reIsCosmeticFilter.test(line) ) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,41 +503,46 @@
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The filter is whatever sequence of printable ascii character without
|
//staticNetFilteringEngine.add(line);
|
||||||
// whitespaces
|
staticNetFilteringEngine.compile(line, compiledFilters);
|
||||||
//matches = reAsciiSegment.exec(line);
|
}
|
||||||
//if ( matches === null ) {
|
|
||||||
// console.debug('storage.js > µBlock.mergeFilterList(): skipping "%s"', lineRaw);
|
|
||||||
// continue;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Bypass anomalies
|
return compiledFilters.join('\n');
|
||||||
// For example, when a filter contains whitespace characters, or
|
};
|
||||||
// whatever else outside the range of printable ascii characters.
|
|
||||||
//if ( matches[0] !== line ) {
|
|
||||||
// console.error('"%s" !== "%s"', matches[0], line);
|
|
||||||
// continue;
|
|
||||||
//}
|
|
||||||
|
|
||||||
staticNetFilteringEngine.add(line);
|
/******************************************************************************/
|
||||||
|
|
||||||
|
µBlock.applyCompiledFilters = function(rawText) {
|
||||||
|
var skipCosmetic = !this.userSettings.parseAllABPHideFilters;
|
||||||
|
var staticNetFilteringEngine = this.staticNetFilteringEngine;
|
||||||
|
var cosmeticFilteringEngine = this.cosmeticFilteringEngine;
|
||||||
|
var lineBeg = 0;
|
||||||
|
var rawEnd = rawText.length;
|
||||||
|
while ( lineBeg < rawEnd ) {
|
||||||
|
lineBeg = cosmeticFilteringEngine.fromCompiledContent(rawText, lineBeg, skipCosmetic);
|
||||||
|
lineBeg = staticNetFilteringEngine.fromCompiledContent(rawText, lineBeg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// `switches` contains the preset blacklists for which the switch must be
|
// `switches` contains the filter lists for which the switch must be revisited.
|
||||||
// revisited.
|
|
||||||
|
|
||||||
µBlock.reloadPresetBlacklists = function(switches, update) {
|
µBlock.reloadFilterLists = function(switches, update) {
|
||||||
var µb = µBlock;
|
var µb = this;
|
||||||
|
|
||||||
var onFilterListsReady = function() {
|
var onFilterListsReady = function() {
|
||||||
µb.loadUpdatableAssets({ update: update, psl: update });
|
µb.loadUpdatableAssets({ update: update, psl: update });
|
||||||
};
|
};
|
||||||
|
|
||||||
// Toggle switches, if any
|
var onPurgeDone = function() {
|
||||||
if ( switches !== undefined ) {
|
// Toggle switches, if any
|
||||||
var filterLists = this.remoteBlacklists;
|
if ( switches === undefined ) {
|
||||||
|
onFilterListsReady();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var filterLists = µb.remoteBlacklists;
|
||||||
var i = switches.length;
|
var i = switches.length;
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
if ( filterLists.hasOwnProperty(switches[i].location) === false ) {
|
if ( filterLists.hasOwnProperty(switches[i].location) === false ) {
|
||||||
@ -484,26 +552,76 @@
|
|||||||
}
|
}
|
||||||
// Save switch states
|
// Save switch states
|
||||||
vAPI.storage.set({ 'remoteBlacklists': filterLists }, onFilterListsReady);
|
vAPI.storage.set({ 'remoteBlacklists': filterLists }, onFilterListsReady);
|
||||||
} else {
|
};
|
||||||
onFilterListsReady();
|
|
||||||
|
// If we must update, we need to purge the compiled versions of
|
||||||
|
// obsolete assets.
|
||||||
|
if ( update !== true ) {
|
||||||
|
onPurgeDone();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var onMetadataReady = function(metadata) {
|
||||||
|
var filterLists = µb.remoteBlacklists;
|
||||||
|
var entry;
|
||||||
|
// Purge obsolete filter lists
|
||||||
|
for ( var path in filterLists ) {
|
||||||
|
if ( filterLists.hasOwnProperty(path) === false ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( metadata.hasOwnProperty(path) === false ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
entry = metadata[path];
|
||||||
|
if ( entry.repoObsolete !== true && entry.cacheObsolete !== true ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
µb.purgeCompiledFilterList(path);
|
||||||
|
}
|
||||||
|
// Purge obsolete PSL
|
||||||
|
if ( metadata.hasOwnProperty(µb.pslPath) === false ) {
|
||||||
|
entry = metadata[µb.pslPath];
|
||||||
|
if ( entry.repoObsolete === true ) {
|
||||||
|
µb.assets.purge('cache://compiled-publicsuffixlist');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onPurgeDone();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assets.metadata(onMetadataReady);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.loadPublicSuffixList = function(callback) {
|
µBlock.loadPublicSuffixList = function(callback) {
|
||||||
|
var µb = this;
|
||||||
|
var path = µb.pslPath;
|
||||||
|
var compiledPath = 'cache://compiled-publicsuffixlist';
|
||||||
|
|
||||||
if ( typeof callback !== 'function' ) {
|
if ( typeof callback !== 'function' ) {
|
||||||
callback = this.noopFunc;
|
callback = this.noopFunc;
|
||||||
}
|
}
|
||||||
var applyPublicSuffixList = function(details) {
|
var onRawListLoaded = function(details) {
|
||||||
// TODO: Not getting proper suffix list is a bit serious, I think
|
if ( details.content !== '' ) {
|
||||||
// the extension should be force-restarted if it occurs..
|
//console.debug('µBlock.loadPublicSuffixList/onRawListLoaded: compiling "%s"', path);
|
||||||
if ( !details.error ) {
|
|
||||||
publicSuffixList.parse(details.content, punycode.toASCII);
|
publicSuffixList.parse(details.content, punycode.toASCII);
|
||||||
|
µb.assets.put(compiledPath, JSON.stringify(publicSuffixList.toSelfie()));
|
||||||
}
|
}
|
||||||
callback();
|
callback();
|
||||||
};
|
};
|
||||||
this.assets.get(this.pslPath, applyPublicSuffixList);
|
|
||||||
|
var onCompiledListLoaded = function(details) {
|
||||||
|
if ( details.content === '' ) {
|
||||||
|
//console.debug('µBlock.loadPublicSuffixList/onCompiledListLoaded: no compiled version for "%s"', path);
|
||||||
|
µb.assets.get(path, onRawListLoaded);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//console.debug('µBlock.loadPublicSuffixList/onCompiledListLoaded: using compiled version for "%s"', path);
|
||||||
|
publicSuffixList.fromSelfie(JSON.parse(details.content));
|
||||||
|
callback();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assets.get(compiledPath, onCompiledListLoaded);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -540,7 +658,7 @@
|
|||||||
|
|
||||||
µBlock.toSelfie = function() {
|
µBlock.toSelfie = function() {
|
||||||
var selfie = {
|
var selfie = {
|
||||||
magic: this.selfieMagic,
|
magic: this.systemSettings.selfieMagic,
|
||||||
publicSuffixList: publicSuffixList.toSelfie(),
|
publicSuffixList: publicSuffixList.toSelfie(),
|
||||||
filterLists: this.remoteBlacklists,
|
filterLists: this.remoteBlacklists,
|
||||||
staticNetFilteringEngine: this.staticNetFilteringEngine.toSelfie(),
|
staticNetFilteringEngine: this.staticNetFilteringEngine.toSelfie(),
|
||||||
@ -578,7 +696,7 @@
|
|||||||
|
|
||||||
var onSelfieReady = function(store) {
|
var onSelfieReady = function(store) {
|
||||||
var selfie = store.selfie;
|
var selfie = store.selfie;
|
||||||
if ( typeof selfie !== 'object' || selfie.magic !== µb.selfieMagic ) {
|
if ( typeof selfie !== 'object' || selfie.magic !== µb.systemSettings.selfieMagic ) {
|
||||||
callback(false);
|
callback(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -586,7 +704,7 @@
|
|||||||
callback(false);
|
callback(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// console.log('µBlock.fromSelfie> selfie looks good');
|
//console.log('µBlock.fromSelfie> selfie looks good');
|
||||||
µb.remoteBlacklists = selfie.filterLists;
|
µb.remoteBlacklists = selfie.filterLists;
|
||||||
µb.staticNetFilteringEngine.fromSelfie(selfie.staticNetFilteringEngine);
|
µb.staticNetFilteringEngine.fromSelfie(selfie.staticNetFilteringEngine);
|
||||||
µb.cosmeticFilteringEngine.fromSelfie(selfie.cosmeticFilteringEngine);
|
µb.cosmeticFilteringEngine.fromSelfie(selfie.cosmeticFilteringEngine);
|
||||||
@ -601,7 +719,7 @@
|
|||||||
µBlock.destroySelfie = function() {
|
µBlock.destroySelfie = function() {
|
||||||
vAPI.storage.remove('selfie');
|
vAPI.storage.remove('selfie');
|
||||||
this.asyncJobs.remove('toSelfie');
|
this.asyncJobs.remove('toSelfie');
|
||||||
//console.debug('storage.js > µBlock.destroySelfie()');
|
//console.debug('µBlock.destroySelfie()');
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -626,6 +744,25 @@
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
µBlock.assetUpdatedHandler = function(details) {
|
||||||
|
var path = details.path || '';
|
||||||
|
if ( this.remoteBlacklists.hasOwnProperty(path) === false ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var entry = this.remoteBlacklists[path];
|
||||||
|
if ( entry.off ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Compile the list while we have the raw version in memory
|
||||||
|
//console.debug('µBlock.getCompiledFilterList/onRawListLoaded: compiling "%s"', path);
|
||||||
|
this.assets.put(
|
||||||
|
this.getCompiledFilterListPath(path),
|
||||||
|
this.compileFilters(details.content)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.updateCompleteHandler = function(details) {
|
µBlock.updateCompleteHandler = function(details) {
|
||||||
var µb = this;
|
var µb = this;
|
||||||
var updatedCount = details.updatedCount;
|
var updatedCount = details.updatedCount;
|
||||||
@ -659,3 +796,35 @@
|
|||||||
onPSLReady();
|
onPSLReady();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
µBlock.assetCacheRemovedHandler = (function() {
|
||||||
|
var barrier = false;
|
||||||
|
|
||||||
|
var handler = function(paths) {
|
||||||
|
if ( barrier ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
barrier = true;
|
||||||
|
var i = paths.length;
|
||||||
|
var path;
|
||||||
|
while ( i-- ) {
|
||||||
|
path = paths[i];
|
||||||
|
if ( this.remoteBlacklists.hasOwnProperty(path) ) {
|
||||||
|
//console.debug('µBlock.assetCacheRemovedHandler: decompiling "%s"', path);
|
||||||
|
this.purgeCompiledFilterList(path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( path === this.pslPath ) {
|
||||||
|
//console.debug('µBlock.assetCacheRemovedHandler: decompiling "%s"', path);
|
||||||
|
this.assets.purge('cache://compiled-publicsuffixlist');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.destroySelfie();
|
||||||
|
barrier = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
return handler;
|
||||||
|
})();
|
||||||
|
Loading…
Reference in New Issue
Block a user