1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-09-02 09:09:38 +02:00

fix #781: support for explicit style properties

This commit is contained in:
gorhill 2016-06-29 17:07:33 -04:00
parent 09d35b65e0
commit 3752ac4880
2 changed files with 96 additions and 52 deletions

View File

@ -66,6 +66,7 @@ vAPI.domFilterer = {
hiddenId: String.fromCharCode(Date.now() % 26 + 97) + Math.floor(Math.random() * 982451653 + 982451653).toString(36),
hiddenNodeCount: 0,
matchesProp: vAPI.matchesProp,
newCSSRules: [],
newDeclarativeSelectors: [],
shadowId: String.fromCharCode(Date.now() % 26 + 97) + Math.floor(Math.random() * 982451653 + 982451653).toString(36),
styleTags: [],
@ -94,32 +95,13 @@ vAPI.domFilterer = {
}
},
addHasSelector: function(s1, s2) {
var entry = { a: s1, b: s2.slice(5, -1) };
if ( s1.indexOf(' ') === -1 ) {
this.simpleHasSelectors.push(entry);
} else {
this.complexHasSelectors.push(entry);
this.complexHasSelectorsCost = 0;
}
},
addSelector: function(s) {
if ( this.allSelectors[s] || this.allExceptions[s] ) {
return;
}
this.allSelectors[s] = true;
var pos = s.indexOf(':');
if ( pos !== -1 ) {
pos = s.indexOf(':has(');
if ( pos !== -1 ) {
this.addHasSelector(s.slice(0, pos), s.slice(pos));
return;
}
if ( s.lastIndexOf(':xpath(', 0) === 0 ) {
this.addXpathSelector('', s);
return;
}
if ( s.indexOf(':') !== -1 && this.addSelectorEx(s) ) {
return;
}
if ( s.indexOf(' ') === -1 ) {
this.simpleSelectors.push(s);
@ -132,18 +114,41 @@ vAPI.domFilterer = {
this.newDeclarativeSelectors.push(s);
},
addSelectorEx: function(s) {
var pos = s.indexOf(':has(');
if ( pos !== -1 ) {
var entry = {
a: s.slice(0, pos),
b: s.slice(pos + 5, -1)
};
if ( entry.a.indexOf(' ') === -1 ) {
this.simpleHasSelectors.push(entry);
} else {
this.complexHasSelectors.push(entry);
this.complexHasSelectorsCost = 0;
}
return true;
}
pos = s.indexOf(':style(');
if ( pos !== -1 ) {
this.newCSSRules.push(s.slice(0, pos) + ' {' + s.slice(pos + 7, -1) + '}');
return true;
}
if ( s.lastIndexOf(':xpath(', 0) === 0 ) {
this.xpathExpression = null;
this.xpathSelectorsCost = 0;
this.addXpathSelector('', s.slice(7, -1));
return true;
}
return false;
},
addSelectors: function(aa) {
for ( var i = 0, n = aa.length; i < n; i++ ) {
this.addSelector(aa[i]);
}
},
addXpathSelector: function(s1, s2) {
this.xpathSelectors.push(s2.slice(7, -1));
this.xpathExpression = null;
this.xpathSelectorsCost = 0;
},
checkStyleTags: function(commitIfNeeded) {
var doc = document,
html = doc.documentElement,
@ -188,8 +193,9 @@ vAPI.domFilterer = {
}
// Inject new declarative selectors.
var styleTag;
if ( this.newDeclarativeSelectors.length ) {
var styleTag = document.createElement('style');
styleTag = document.createElement('style');
styleTag.setAttribute('type', 'text/css');
styleTag.textContent =
':root ' +
@ -199,6 +205,15 @@ vAPI.domFilterer = {
this.styleTags.push(styleTag);
this.newDeclarativeSelectors.length = 0;
}
// Inject new CSS rules.
if ( this.newCSSRules.length ) {
styleTag = document.createElement('style');
styleTag.setAttribute('type', 'text/css');
styleTag.textContent = ':root ' + this.newCSSRules.join(',\n:root ');
document.head.appendChild(styleTag);
this.styleTags.push(styleTag);
this.newCSSRules.length = 0;
}
// Simple `:has()` selectors.
if ( this.simpleHasSelectors.length ) {

View File

@ -297,17 +297,29 @@ FilterParser.prototype.parse = function(raw) {
// https://github.com/gorhill/uBlock/issues/952
// Find out whether we are dealing with an Adguard-specific cosmetic
// filter, and if so, discard the filter.
// filter, and if so, translate it if supported, or discard it if not
// supported.
var cCode = raw.charCodeAt(rpos - 1);
if ( cCode !== 0x23 /* '#' */ && cCode !== 0x40 /* '@' */ ) {
// We have an Adguard cosmetic filter if and only if the character is
// `$` or `%`, otherwise it's not a cosmetic filter.
if ( cCode === 0x24 /* '$' */ || cCode === 0x25 /* '%' */ ) {
this.invalid = true;
} else {
// Not a cosmetic filter.
if ( cCode !== 0x24 /* '$' */ && cCode !== 0x25 /* '%' */ ) {
this.cosmetic = false;
return this;
}
return this;
// Not supported.
if ( cCode !== 0x24 /* '$' */ ) {
this.invalid = true;
return this;
}
// CSS injection rule: supported, but translate into uBO's own format.
raw = this.translateAdguardCSSInjectionFilter(raw);
if ( raw === '' ) {
this.invalid = true;
return this;
}
rpos = raw.indexOf('#', lpos + 1);
}
// Extract the hostname(s).
@ -322,17 +334,6 @@ FilterParser.prototype.parse = function(raw) {
return this;
}
// Cosmetic filters with explicit style properties can apply only:
// - to specific cosmetic filters (those which apply to a specific site)
// - to block cosmetic filters (not exception cosmetic filters)
if ( this.suffix.endsWith('}') ) {
// Not supported for now: this code will ensure some backward
// compatibility for when cosmetic filters with explicit style
// properties start to be in use.
this.invalid = true;
return this;
}
// 2014-05-23:
// https://github.com/gorhill/httpswitchboard/issues/260
// Any sequence of `#` longer than one means the line is not a valid
@ -380,6 +381,21 @@ FilterParser.prototype.parse = function(raw) {
/******************************************************************************/
// Reference: https://adguard.com/en/filterrules.html#cssInjection
FilterParser.prototype.translateAdguardCSSInjectionFilter = function(raw) {
var matches = /^([^#]*)#(@?)\$#([^{]+)\{([^}]+)\}$/.exec(raw);
if ( matches === null ) {
return '';
}
return matches[1] +
'#' + matches[2] + '#' +
matches[3].trim() +
':style(' + matches[4].trim() + ')';
};
/******************************************************************************/
FilterParser.prototype.parseScriptTagFilter = function(matches) {
// Currently supported only as non-generic selector. Also, exception
// script tag filter makes no sense, ignore.
@ -699,6 +715,10 @@ FilterContainer.prototype.reset = function() {
// https://github.com/chrisaljoudi/uBlock/issues/1004
// Detect and report invalid CSS selectors.
// Discard new ABP's `-abp-properties` directive until it is
// implemented (if ever). Unlikely, see:
// https://github.com/gorhill/uBlock/issues/1752
FilterContainer.prototype.isValidSelector = (function() {
var div = document.createElement('div');
var matchesProp = (function() {
@ -722,18 +742,22 @@ FilterContainer.prototype.isValidSelector = (function() {
}
var reHasSelector = /^(.+?):has\((.+?)\)$/;
var reStyleSelector = /^(.+?):style\((.+?)\)$/;
var reXpathSelector = /^:xpath\((.+?)\)$/;
return function(s) {
// Keep in mind: https://github.com/gorhill/uBlock/issues/693
var isValidCSSSelector = function(s) {
try {
// https://github.com/gorhill/uBlock/issues/693
div[matchesProp](s + ',\n#foo');
// Discard new ABP's `-abp-properties` directive until it is
// implemented (if ever).
if ( s.indexOf('[-abp-properties=') === -1 ) {
return true;
}
} catch (e) {
} catch (ex) {
return false;
}
return true;
};
return function(s) {
if ( isValidCSSSelector(s) && s.indexOf('[-abp-properties=') === -1 ) {
return true;
}
// We reach this point very rarely.
var matches;
@ -753,6 +777,11 @@ FilterContainer.prototype.isValidSelector = (function() {
}
return false;
}
// `:style` selector?
matches = reStyleSelector.exec(s);
if ( matches !== null ) {
return isValidCSSSelector(matches[1]);
}
// Special `script:` filter?
if ( s.startsWith('script') ) {
if ( s.startsWith('?', 6) || s.startsWith('+', 6) ) {