Revert "Prevent highly generic cosmetic filters from affecting html/body elements"

This reverts commit 7c8aec250f.

This will be brought back in a future dev cycle. Potentially
related issues:

- https://github.com/uBlockOrigin/uBlock-issues/issues/1978
- https://github.com/uBlockOrigin/uBlock-issues/issues/1983
This commit is contained in:
Raymond Hill 2022-02-16 12:21:10 -05:00
parent 9726e899e5
commit 5178b91fa1
No known key found for this signature in database
GPG key ID: 25E1490B761470C2
4 changed files with 23 additions and 39 deletions

View file

@ -676,11 +676,6 @@ vAPI.DOMFilterer = class {
getAllExceptionSelectors() { getAllExceptionSelectors() {
return this.exceptions.join(',\n'); return this.exceptions.join(',\n');
} }
unwrapSelector(s) {
const match = /^:is\((.+)\):not\(html,body\)\/\*hg\*\/$/.exec(s);
return match !== null ? match[1] : s;
}
}; };
/******************************************************************************/ /******************************************************************************/

View file

@ -227,11 +227,13 @@ const FilterContainer = function() {
this.highlyGeneric.simple = { this.highlyGeneric.simple = {
canonical: 'highGenericHideSimple', canonical: 'highGenericHideSimple',
dict: new Set(), dict: new Set(),
str: '',
mru: new µb.MRUCache(16) mru: new µb.MRUCache(16)
}; };
this.highlyGeneric.complex = { this.highlyGeneric.complex = {
canonical: 'highGenericHideComplex', canonical: 'highGenericHideComplex',
dict: new Set(), dict: new Set(),
str: '',
mru: new µb.MRUCache(16) mru: new µb.MRUCache(16)
}; };
@ -279,16 +281,11 @@ FilterContainer.prototype.reset = function() {
// highly generic selectors sets // highly generic selectors sets
this.highlyGeneric.simple.dict.clear(); this.highlyGeneric.simple.dict.clear();
this.highlyGeneric.simple.str = '';
this.highlyGeneric.simple.mru.reset(); this.highlyGeneric.simple.mru.reset();
this.highlyGeneric.complex.dict.clear(); this.highlyGeneric.complex.dict.clear();
this.highlyGeneric.complex.str = '';
this.highlyGeneric.complex.mru.reset(); this.highlyGeneric.complex.mru.reset();
// https://developer.mozilla.org/en-US/docs/Web/CSS/:is#browser_compatibility
// https://developer.mozilla.org/en-US/docs/Web/CSS/:not#browser_compatibility
// Need support for both `:is()` and `:not()` with selector list.
this.cssIs =
vAPI.webextFlavor.soup.has('firefox') && vAPI.webextFlavor.major >= 84 ||
vAPI.webextFlavor.soup.has('chromium') && vAPI.webextFlavor.major >= 88;
}; };
/******************************************************************************/ /******************************************************************************/
@ -303,7 +300,9 @@ FilterContainer.prototype.freeze = function() {
this.lowlyGeneric.cl.simple.size !== 0 || this.lowlyGeneric.cl.simple.size !== 0 ||
this.lowlyGeneric.cl.complex.size !== 0; this.lowlyGeneric.cl.complex.size !== 0;
this.highlyGeneric.simple.str = Array.from(this.highlyGeneric.simple.dict).join(',\n');
this.highlyGeneric.simple.mru.reset(); this.highlyGeneric.simple.mru.reset();
this.highlyGeneric.complex.str = Array.from(this.highlyGeneric.complex.dict).join(',\n');
this.highlyGeneric.complex.mru.reset(); this.highlyGeneric.complex.mru.reset();
this.frozen = true; this.frozen = true;
@ -707,7 +706,9 @@ FilterContainer.prototype.fromSelfie = function(selfie) {
this.lowlyGeneric.cl.simple = new Set(selfie.lowlyGenericSCL); this.lowlyGeneric.cl.simple = new Set(selfie.lowlyGenericSCL);
this.lowlyGeneric.cl.complex = new Map(selfie.lowlyGenericCCL); this.lowlyGeneric.cl.complex = new Map(selfie.lowlyGenericCCL);
this.highlyGeneric.simple.dict = new Set(selfie.highSimpleGenericHideArray); this.highlyGeneric.simple.dict = new Set(selfie.highSimpleGenericHideArray);
this.highlyGeneric.simple.str = selfie.highSimpleGenericHideArray.join(',\n');
this.highlyGeneric.complex.dict = new Set(selfie.highComplexGenericHideArray); this.highlyGeneric.complex.dict = new Set(selfie.highComplexGenericHideArray);
this.highlyGeneric.complex.str = selfie.highComplexGenericHideArray.join(',\n');
this.needDOMSurveyor = this.needDOMSurveyor =
selfie.lowlyGenericSID.length !== 0 || selfie.lowlyGenericSID.length !== 0 ||
selfie.lowlyGenericCID.length !== 0 || selfie.lowlyGenericCID.length !== 0 ||
@ -1041,19 +1042,14 @@ FilterContainer.prototype.retrieveSpecificSelectors = function(
// indirectly in the mru cache: this is to prevent duplication of the // indirectly in the mru cache: this is to prevent duplication of the
// string in memory, which I have observed occurs when the string is // string in memory, which I have observed occurs when the string is
// stored directly as a value in a Map. // stored directly as a value in a Map.
//
// https://github.com/uBlockOrigin/uBlock-issues/issues/1692
// Wrap generic selectors to prevent matching `html` or `body`
// elements. Content script-side code must unwrap those selectors
// before reporting them in a user interface.
if ( options.noGenericCosmeticFiltering !== true ) { if ( options.noGenericCosmeticFiltering !== true ) {
const exceptionSetHash = out.exceptionFilters.join(); const exceptionSetHash = out.exceptionFilters.join();
for ( const key in this.highlyGeneric ) { for ( const key in this.highlyGeneric ) {
const entry = this.highlyGeneric[key]; const entry = this.highlyGeneric[key];
let genericSet = entry.dict; let str = entry.mru.lookup(exceptionSetHash);
let cache = entry.mru.lookup(exceptionSetHash); if ( str === undefined ) {
if ( cache === undefined ) { str = { s: entry.str, excepted: [] };
cache = { s: '', excepted: [] }; let genericSet = entry.dict;
let hit = false; let hit = false;
for ( const exception of exceptionSet ) { for ( const exception of exceptionSet ) {
if ( (hit = genericSet.has(exception)) ) { break; } if ( (hit = genericSet.has(exception)) ) { break; }
@ -1062,23 +1058,18 @@ FilterContainer.prototype.retrieveSpecificSelectors = function(
genericSet = new Set(entry.dict); genericSet = new Set(entry.dict);
for ( const exception of exceptionSet ) { for ( const exception of exceptionSet ) {
if ( genericSet.delete(exception) ) { if ( genericSet.delete(exception) ) {
cache.excepted.push(exception); str.excepted.push(exception);
} }
} }
str.s = Array.from(genericSet).join(',\n');
} }
let genericArr = Array.from(genericSet); entry.mru.add(exceptionSetHash, str);
if ( this.cssIs ) {
genericArr =
genericArr.map(a => `:is(${a}):not(html,body)/*hg*/`);
}
cache.s = genericArr.join(',\n');
entry.mru.add(exceptionSetHash, cache);
} }
if ( cache.excepted.length !== 0 ) { if ( str.excepted.length !== 0 ) {
out.exceptedFilters.push(...cache.excepted); out.exceptedFilters.push(...str.excepted);
} }
if ( cache.s.length !== 0 ) { if ( str.s.length !== 0 ) {
injectedHideFilters.push(cache.s); injectedHideFilters.push(str.s);
} }
} }
} }

View file

@ -91,7 +91,6 @@ const processDeclarativeSimple = function(node, out) {
) { ) {
return; return;
} }
const unwrapSelector = vAPI.domFilterer.unwrapSelector;
for ( const selector of simpleDeclarativeSet ) { for ( const selector of simpleDeclarativeSet ) {
if ( if (
(node === document || safeMatchSelector(selector, node) === false) && (node === document || safeMatchSelector(selector, node) === false) &&
@ -99,7 +98,7 @@ const processDeclarativeSimple = function(node, out) {
) { ) {
continue; continue;
} }
out.push(`##${unwrapSelector(selector)}`); out.push(`##${selector}`);
simpleDeclarativeSet.delete(selector); simpleDeclarativeSet.delete(selector);
simpleDeclarativeStr = undefined; simpleDeclarativeStr = undefined;
loggedSelectors.add(selector); loggedSelectors.add(selector);
@ -114,10 +113,9 @@ const processDeclarativeComplex = function(out) {
complexDeclarativeStr = safeGroupSelectors(complexDeclarativeSet); complexDeclarativeStr = safeGroupSelectors(complexDeclarativeSet);
} }
if ( document.querySelector(complexDeclarativeStr) === null ) { return; } if ( document.querySelector(complexDeclarativeStr) === null ) { return; }
const unwrapSelector = vAPI.domFilterer.unwrapSelector;
for ( const selector of complexDeclarativeSet ) { for ( const selector of complexDeclarativeSet ) {
if ( safeQuerySelector(selector) === null ) { continue; } if ( safeQuerySelector(selector) === null ) { continue; }
out.push(`##${unwrapSelector(selector)}`); out.push(`##${selector}`);
complexDeclarativeSet.delete(selector); complexDeclarativeSet.delete(selector);
complexDeclarativeStr = undefined; complexDeclarativeStr = undefined;
loggedSelectors.add(selector); loggedSelectors.add(selector);

View file

@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
uBlock Origin - a browser extension to block requests. uBlock Origin - a browser extension to block requests.
Copyright (C) 2015-present Raymond Hill Copyright (C) 2015-2018 Raymond Hill
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -509,7 +509,7 @@ const cosmeticFilterMapper = (function() {
// Declarative selectors. // Declarative selectors.
for ( const entry of (details.declarative || []) ) { for ( const entry of (details.declarative || []) ) {
for ( const selector of entry[0].split(',\n') ) { for ( const selector of entry[0].split(',\n') ) {
let canonical = vAPI.domFilterer.unwrapSelector(selector); let canonical = selector;
let nodes; let nodes;
if ( entry[1] !== vAPI.hideStyle ) { if ( entry[1] !== vAPI.hideStyle ) {
canonical += ':style(' + entry[1] + ')'; canonical += ':style(' + entry[1] + ')';