mirror of https://github.com/gorhill/uBlock.git
add to #2984: fix regressions, as per feedback and code review
This commit is contained in:
parent
14109b33d6
commit
6e18829f02
|
@ -60,6 +60,7 @@ vAPI.supportsUserStylesheets =
|
||||||
chrome.extensionTypes instanceof Object &&
|
chrome.extensionTypes instanceof Object &&
|
||||||
chrome.extensionTypes.CSSOrigin instanceof Object &&
|
chrome.extensionTypes.CSSOrigin instanceof Object &&
|
||||||
'USER' in chrome.extensionTypes.CSSOrigin;
|
'USER' in chrome.extensionTypes.CSSOrigin;
|
||||||
|
vAPI.insertCSS = chrome.tabs.insertCSS;
|
||||||
|
|
||||||
var noopFunc = function(){};
|
var noopFunc = function(){};
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,11 @@ vAPI.DOMFilterer.prototype = {
|
||||||
var userStylesheet = vAPI.userStylesheet,
|
var userStylesheet = vAPI.userStylesheet,
|
||||||
addedSelectors = [];
|
addedSelectors = [];
|
||||||
for ( var entry of this.addedCSSRules ) {
|
for ( var entry of this.addedCSSRules ) {
|
||||||
if ( this.disabled === false && entry.lazy ) {
|
if (
|
||||||
|
this.disabled === false &&
|
||||||
|
entry.lazy &&
|
||||||
|
entry.injected === false
|
||||||
|
) {
|
||||||
userStylesheet.add(
|
userStylesheet.add(
|
||||||
entry.selectors + '\n{' + entry.declarations + '}'
|
entry.selectors + '\n{' + entry.declarations + '}'
|
||||||
);
|
);
|
||||||
|
@ -114,15 +118,21 @@ vAPI.DOMFilterer.prototype = {
|
||||||
? selectors.join(',\n')
|
? selectors.join(',\n')
|
||||||
: selectors;
|
: selectors;
|
||||||
if ( selectorsStr.length === 0 ) { return; }
|
if ( selectorsStr.length === 0 ) { return; }
|
||||||
|
if ( details === undefined ) { details = {}; }
|
||||||
var entry = {
|
var entry = {
|
||||||
selectors: selectorsStr,
|
selectors: selectorsStr,
|
||||||
declarations,
|
declarations,
|
||||||
lazy: details !== undefined && details.lazy === true,
|
lazy: details.lazy === true,
|
||||||
internal: details && details.internal === true
|
internal: details.internal === true,
|
||||||
|
injected: details.injected === true
|
||||||
};
|
};
|
||||||
this.addedCSSRules.add(entry);
|
this.addedCSSRules.add(entry);
|
||||||
this.filterset.add(entry);
|
this.filterset.add(entry);
|
||||||
if ( this.disabled === false && entry.lazy !== true ) {
|
if (
|
||||||
|
this.disabled === false &&
|
||||||
|
entry.lazy !== true &&
|
||||||
|
entry.injected !== true
|
||||||
|
) {
|
||||||
vAPI.userStylesheet.add(selectorsStr + '\n{' + declarations + '}');
|
vAPI.userStylesheet.add(selectorsStr + '\n{' + declarations + '}');
|
||||||
}
|
}
|
||||||
this.commit();
|
this.commit();
|
||||||
|
|
|
@ -455,6 +455,7 @@ vAPI.DOMFilterer = (function() {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
this.raw = o.raw;
|
this.raw = o.raw;
|
||||||
|
this.cost = 0;
|
||||||
this.selector = o.selector;
|
this.selector = o.selector;
|
||||||
this.tasks = [];
|
this.tasks = [];
|
||||||
var tasks = o.tasks;
|
var tasks = o.tasks;
|
||||||
|
@ -575,16 +576,24 @@ vAPI.DOMFilterer = (function() {
|
||||||
|
|
||||||
this.addedNodes = this.removedNodes = false;
|
this.addedNodes = this.removedNodes = false;
|
||||||
|
|
||||||
var afterResultset = new Set();
|
var afterResultset = new Set(),
|
||||||
|
t0 = Date.now(), t1, pselector;
|
||||||
|
|
||||||
for ( entry of this.selectors ) {
|
for ( entry of this.selectors ) {
|
||||||
nodes = entry[1].exec();
|
pselector = entry[1];
|
||||||
|
if ( pselector.cost > 100 ) { continue; }
|
||||||
|
nodes = pselector.exec();
|
||||||
i = nodes.length;
|
i = nodes.length;
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
node = nodes[i];
|
node = nodes[i];
|
||||||
this.domFilterer.hideNode(node);
|
this.domFilterer.hideNode(node);
|
||||||
afterResultset.add(node);
|
afterResultset.add(node);
|
||||||
}
|
}
|
||||||
|
t1 = Date.now();
|
||||||
|
pselector.cost += t1 - t0;
|
||||||
|
t0 = t1;
|
||||||
|
// TODO: Consider adding logging ability to report disabled
|
||||||
|
// precedural filter in the logger.
|
||||||
}
|
}
|
||||||
if ( afterResultset.size !== currentResultset.size ) {
|
if ( afterResultset.size !== currentResultset.size ) {
|
||||||
this.addedNodesHandlerMissCount = 0;
|
this.addedNodesHandlerMissCount = 0;
|
||||||
|
@ -1265,6 +1274,8 @@ vAPI.domSurveyor = (function() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var injected = cfeDetails.rulesInjected === true;
|
||||||
|
|
||||||
if ( response.noCosmeticFiltering ) {
|
if ( response.noCosmeticFiltering ) {
|
||||||
vAPI.domFilterer = null;
|
vAPI.domFilterer = null;
|
||||||
vAPI.domSurveyor = null;
|
vAPI.domSurveyor = null;
|
||||||
|
@ -1276,30 +1287,29 @@ vAPI.domSurveyor = (function() {
|
||||||
domFilterer.exceptions = cfeDetails.exceptionFilters;
|
domFilterer.exceptions = cfeDetails.exceptionFilters;
|
||||||
domFilterer.addCSSRule(
|
domFilterer.addCSSRule(
|
||||||
cfeDetails.declarativeFilters,
|
cfeDetails.declarativeFilters,
|
||||||
'display: none !important;'
|
'display:none!important;',
|
||||||
|
{ injected: injected }
|
||||||
);
|
);
|
||||||
domFilterer.addCSSRule(
|
domFilterer.addCSSRule(
|
||||||
cfeDetails.highGenericHideSimple,
|
cfeDetails.highGenericHideSimple,
|
||||||
'display:none!important;',
|
'display:none!important;',
|
||||||
{ type: 'simple', lazy: true }
|
{ type: 'simple', lazy: true, injected: injected }
|
||||||
);
|
);
|
||||||
domFilterer.addCSSRule(
|
domFilterer.addCSSRule(
|
||||||
cfeDetails.highGenericHideComplex,
|
cfeDetails.highGenericHideComplex,
|
||||||
'display:none!important;',
|
'display:none!important;',
|
||||||
{ type: 'complex', lazy: true }
|
{ type: 'complex', lazy: true, injected: injected }
|
||||||
);
|
);
|
||||||
domFilterer.addProceduralSelectors(cfeDetails.proceduralFilters);
|
domFilterer.addProceduralSelectors(cfeDetails.proceduralFilters);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( cfeDetails.netFilters.length !== 0 ) {
|
if ( cfeDetails.netFilters.length !== 0 && injected !== true ) {
|
||||||
vAPI.userStylesheet.add(
|
vAPI.userStylesheet.add(
|
||||||
cfeDetails.netFilters + '\n{display:none!important;}');
|
cfeDetails.netFilters + '\n{display:none!important;}');
|
||||||
}
|
}
|
||||||
|
|
||||||
vAPI.userStylesheet.apply();
|
vAPI.userStylesheet.apply();
|
||||||
|
|
||||||
var parent = document.head || document.documentElement;
|
|
||||||
if ( parent ) {
|
|
||||||
// Library of resources is located at:
|
// Library of resources is located at:
|
||||||
// https://github.com/gorhill/uBlock/blob/master/assets/ublock/resources.txt
|
// https://github.com/gorhill/uBlock/blob/master/assets/ublock/resources.txt
|
||||||
if ( cfeDetails.scripts ) {
|
if ( cfeDetails.scripts ) {
|
||||||
|
@ -1317,7 +1327,6 @@ vAPI.domSurveyor = (function() {
|
||||||
vAPI.injectScriptlet(document, text);
|
vAPI.injectScriptlet(document, text);
|
||||||
vAPI.injectedScripts = text;
|
vAPI.injectedScripts = text;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/587
|
// https://github.com/chrisaljoudi/uBlock/issues/587
|
||||||
// If no filters were found, maybe the script was injected before
|
// If no filters were found, maybe the script was injected before
|
||||||
|
|
|
@ -625,6 +625,8 @@ var FilterContainer = function() {
|
||||||
this.netSelectorCacheCountMax = netSelectorCacheHighWaterMark;
|
this.netSelectorCacheCountMax = netSelectorCacheHighWaterMark;
|
||||||
this.selectorCacheTimer = null;
|
this.selectorCacheTimer = null;
|
||||||
|
|
||||||
|
this.supportsUserStylesheets = vAPI.supportsUserStylesheets;
|
||||||
|
|
||||||
// generic exception filters
|
// generic exception filters
|
||||||
this.genericDonthideSet = new Set();
|
this.genericDonthideSet = new Set();
|
||||||
|
|
||||||
|
@ -1964,6 +1966,26 @@ FilterContainer.prototype.retrieveGenericSelectors = function(request) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
FilterContainer.prototype.injectHideRules = function(
|
||||||
|
tabId,
|
||||||
|
frameId,
|
||||||
|
selectors,
|
||||||
|
runAt
|
||||||
|
) {
|
||||||
|
var details = {
|
||||||
|
code: '',
|
||||||
|
cssOrigin: 'user',
|
||||||
|
frameId: frameId,
|
||||||
|
runAt: runAt
|
||||||
|
};
|
||||||
|
for ( var selector of selectors ) {
|
||||||
|
details.code = selector + '\n{display:none!important;}';
|
||||||
|
vAPI.insertCSS(tabId, details);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.retrieveDomainSelectors = function(
|
FilterContainer.prototype.retrieveDomainSelectors = function(
|
||||||
request,
|
request,
|
||||||
sender,
|
sender,
|
||||||
|
@ -1973,6 +1995,9 @@ FilterContainer.prototype.retrieveDomainSelectors = function(
|
||||||
|
|
||||||
console.time('cosmeticFilteringEngine.retrieveDomainSelectors');
|
console.time('cosmeticFilteringEngine.retrieveDomainSelectors');
|
||||||
|
|
||||||
|
// TODO: consider using MRUCache to quickly lookup all the previously
|
||||||
|
// looked-up data.
|
||||||
|
|
||||||
var hostname = this.µburi.hostnameFromURI(request.locationURL),
|
var hostname = this.µburi.hostnameFromURI(request.locationURL),
|
||||||
domain = this.µburi.domainFromHostname(hostname) || hostname,
|
domain = this.µburi.domainFromHostname(hostname) || hostname,
|
||||||
pos = domain.indexOf('.'),
|
pos = domain.indexOf('.'),
|
||||||
|
@ -1998,7 +2023,7 @@ FilterContainer.prototype.retrieveDomainSelectors = function(
|
||||||
netFilters: '',
|
netFilters: '',
|
||||||
proceduralFilters: [],
|
proceduralFilters: [],
|
||||||
scripts: undefined,
|
scripts: undefined,
|
||||||
cssRulesInjected: false
|
rulesInjected: false
|
||||||
};
|
};
|
||||||
|
|
||||||
if ( options.noCosmeticFiltering !== true ) {
|
if ( options.noCosmeticFiltering !== true ) {
|
||||||
|
@ -2027,6 +2052,22 @@ FilterContainer.prototype.retrieveDomainSelectors = function(
|
||||||
if ( (bucket = this.specificFilters.get('!' + this.noDomainHash)) ) {
|
if ( (bucket = this.specificFilters.get('!' + this.noDomainHash)) ) {
|
||||||
bucket.retrieve(hostname, exceptionSet);
|
bucket.retrieve(hostname, exceptionSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Specific exception procedural cosmetic filters.
|
||||||
|
if ( (bucket = this.proceduralFilters.get('!' + domainHash)) ) {
|
||||||
|
bucket.retrieve(hostname, exceptionSet);
|
||||||
|
}
|
||||||
|
// Specific entity-based exception procedural cosmetic filters.
|
||||||
|
if ( entityHash !== undefined ) {
|
||||||
|
if ( (bucket = this.proceduralFilters.get('!' + entityHash)) ) {
|
||||||
|
bucket.retrieve(entity, exceptionSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Special bucket for those filters without a valid
|
||||||
|
// domain name as per PSL.
|
||||||
|
if ( (bucket = this.proceduralFilters.get('!' + this.noDomainHash)) ) {
|
||||||
|
bucket.retrieve(hostname, exceptionSet);
|
||||||
|
}
|
||||||
if ( exceptionSet.size !== 0 ) {
|
if ( exceptionSet.size !== 0 ) {
|
||||||
r.exceptionFilters = µb.arrayFrom(exceptionSet);
|
r.exceptionFilters = µb.arrayFrom(exceptionSet);
|
||||||
}
|
}
|
||||||
|
@ -2126,6 +2167,27 @@ FilterContainer.prototype.retrieveDomainSelectors = function(
|
||||||
r.netFilters = netFilters.join(',\n');
|
r.netFilters = netFilters.join(',\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.supportsUserStylesheets &&
|
||||||
|
sender instanceof Object &&
|
||||||
|
sender.tab instanceof Object &&
|
||||||
|
typeof sender.frameId === 'number'
|
||||||
|
) {
|
||||||
|
this.injectHideRules(
|
||||||
|
sender.tab.id,
|
||||||
|
sender.frameId,
|
||||||
|
[ r.declarativeFilters.join(',\n'), r.netFilters ],
|
||||||
|
'document_start'
|
||||||
|
);
|
||||||
|
this.injectHideRules(
|
||||||
|
sender.tab.id,
|
||||||
|
sender.frameId,
|
||||||
|
[ r.highGenericHideSimple, r.highGenericHideComplex ],
|
||||||
|
'document_end'
|
||||||
|
);
|
||||||
|
r.rulesInjected = true;
|
||||||
|
}
|
||||||
|
|
||||||
console.timeEnd('cosmeticFilteringEngine.retrieveDomainSelectors');
|
console.timeEnd('cosmeticFilteringEngine.retrieveDomainSelectors');
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -98,34 +98,13 @@ var fromNetFilter = function(details) {
|
||||||
var fromCosmeticFilter = function(details) {
|
var fromCosmeticFilter = function(details) {
|
||||||
var match = /^#@?#/.exec(details.rawFilter),
|
var match = /^#@?#/.exec(details.rawFilter),
|
||||||
prefix = match[0],
|
prefix = match[0],
|
||||||
needle = details.rawFilter.slice(prefix.length),
|
selector = details.rawFilter.slice(prefix.length);
|
||||||
selector = needle;
|
|
||||||
|
|
||||||
// With low generic simple cosmetic filters, the class or id prefix
|
// The longer the needle, the lower the number of false positives.
|
||||||
// character is not part of the compiled data. So we must be ready to
|
var needles = selector.match(/\w+/g).sort(function(a, b) {
|
||||||
// look-up version of the selector without the prefix character.
|
return b.length - a.length;
|
||||||
var idOrClassPrefix = needle.charAt(0),
|
});
|
||||||
cssPrefixMatcher;
|
var reNeedle = new RegExp(needles[0], 'g');
|
||||||
if ( idOrClassPrefix === '#' ) {
|
|
||||||
cssPrefixMatcher = '#?';
|
|
||||||
needle = needle.slice(1);
|
|
||||||
} else if ( idOrClassPrefix === '.' ) {
|
|
||||||
cssPrefixMatcher = '\\.?';
|
|
||||||
needle = needle.slice(1);
|
|
||||||
} else {
|
|
||||||
idOrClassPrefix = '';
|
|
||||||
cssPrefixMatcher = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/3101
|
|
||||||
// Use `m` flag for efficient regex execution.
|
|
||||||
var reFilter = new RegExp(
|
|
||||||
'^\\[\\d,[^\\n]*\\\\*"' +
|
|
||||||
cssPrefixMatcher +
|
|
||||||
reEscapeCosmetic(needle) +
|
|
||||||
'\\\\*"[^\\n]*\\]$',
|
|
||||||
'gm'
|
|
||||||
);
|
|
||||||
|
|
||||||
var reHostname = new RegExp(
|
var reHostname = new RegExp(
|
||||||
'^' +
|
'^' +
|
||||||
|
@ -159,7 +138,7 @@ var fromCosmeticFilter = function(details) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = Object.create(null),
|
var response = Object.create(null),
|
||||||
assetKey, entry, content, found, fargs;
|
assetKey, entry, content, found, beg, end, fargs;
|
||||||
|
|
||||||
for ( assetKey in listEntries ) {
|
for ( assetKey in listEntries ) {
|
||||||
entry = listEntries[assetKey];
|
entry = listEntries[assetKey];
|
||||||
|
@ -169,28 +148,61 @@ var fromCosmeticFilter = function(details) {
|
||||||
filterClassSeparator.length
|
filterClassSeparator.length
|
||||||
);
|
);
|
||||||
found = undefined;
|
found = undefined;
|
||||||
while ( (match = reFilter.exec(content)) !== null ) {
|
while ( (match = reNeedle.exec(content)) !== null ) {
|
||||||
fargs = JSON.parse(match[0]);
|
beg = content.lastIndexOf('\n', match.index);
|
||||||
|
if ( beg === -1 ) { beg = 0; }
|
||||||
|
end = content.indexOf('\n', reNeedle.lastIndex);
|
||||||
|
if ( end === -1 ) { end = content.length; }
|
||||||
|
fargs = JSON.parse(content.slice(beg, end));
|
||||||
switch ( fargs[0] ) {
|
switch ( fargs[0] ) {
|
||||||
case 0: // id-based
|
case 0: // id-based
|
||||||
case 2: // class-based
|
if (
|
||||||
|
fargs[1] === selector.slice(1) &&
|
||||||
|
selector.charAt(0) === '#'
|
||||||
|
) {
|
||||||
found = prefix + selector;
|
found = prefix + selector;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1: // id-based
|
||||||
|
if (
|
||||||
|
fargs[2] === selector.slice(1) &&
|
||||||
|
selector.charAt(0) === '#'
|
||||||
|
) {
|
||||||
|
found = prefix + selector;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: // class-based
|
||||||
|
if (
|
||||||
|
fargs[1] === selector.slice(1) &&
|
||||||
|
selector.charAt(0) === '.'
|
||||||
|
) {
|
||||||
|
found = prefix + selector;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (
|
||||||
|
fargs[2] === selector.slice(1) &&
|
||||||
|
selector.charAt(0) === '.'
|
||||||
|
) {
|
||||||
|
found = prefix + selector;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
case 5:
|
case 5:
|
||||||
case 7:
|
case 7:
|
||||||
found = prefix + selector;
|
if ( fargs[1] === selector ) {
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
case 3:
|
|
||||||
if ( fargs[2] === selector ) {
|
|
||||||
found = prefix + selector;
|
found = prefix + selector;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
case 8:
|
case 8:
|
||||||
case 9:
|
case 9:
|
||||||
if ( fargs[3] !== selector ) { break; }
|
if (
|
||||||
|
fargs[0] === 8 && fargs[3] !== selector ||
|
||||||
|
fargs[0] === 9 && JSON.parse(fargs[3]).raw !== selector
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
fargs[2] === '' ||
|
fargs[2] === '' ||
|
||||||
reHostname.test(fargs[2]) === true ||
|
reHostname.test(fargs[2]) === true ||
|
||||||
|
@ -219,15 +231,6 @@ var fromCosmeticFilter = function(details) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/2666
|
|
||||||
// Raw filters in compiled filter lists may have been JSON-stringified one or
|
|
||||||
// multiple times.
|
|
||||||
|
|
||||||
var reEscapeCosmetic = function(s) {
|
|
||||||
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
||||||
.replace(/"/g, '\\\\*"');
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
onmessage = function(e) { // jshint ignore:line
|
onmessage = function(e) { // jshint ignore:line
|
||||||
|
|
Loading…
Reference in New Issue