aboutsummaryrefslogtreecommitdiffstats
path: root/src/js/cosmetic-filtering.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/js/cosmetic-filtering.js')
-rw-r--r--src/js/cosmetic-filtering.js67
1 files changed, 64 insertions, 3 deletions
diff --git a/src/js/cosmetic-filtering.js b/src/js/cosmetic-filtering.js
index 5d386af..8a0afa8 100644
--- a/src/js/cosmetic-filtering.js
+++ b/src/js/cosmetic-filtering.js
@@ -237,6 +237,7 @@ var FilterParser = function() {
this.invalid = false;
this.cosmetic = true;
this.reParser = /^\s*([^#]*)(##|#@#)(.+)\s*$/;
+ this.reScriptSelectorParser = /^script:contains\(\/.+?\/\)$/;
};
/******************************************************************************/
@@ -286,8 +287,8 @@ FilterParser.prototype.parse = function(s) {
// Script tag filters: pre-process them so that can be used with minimal
// overhead in the content script.
if (
- this.suffix.lastIndexOf('script:contains(/', 0) === 0 &&
- this.suffix.slice(-2) === '/)'
+ this.suffix.charAt(0) === 's' &&
+ this.reScriptSelectorParser.test(this.suffix)
) {
// Currently supported only as non-generic selector.
if ( this.prefix.length === 0 ) {
@@ -568,6 +569,8 @@ FilterContainer.prototype.reset = function() {
// hostname, entity-based filters
this.hostnameFilters = {};
this.entityFilters = {};
+ this.scriptTagFilters = {};
+ this.scriptTagFilterCount = 0;
};
/******************************************************************************/
@@ -807,6 +810,11 @@ FilterContainer.prototype.fromCompiledContent = function(text, lineBeg, skip) {
// h ir twitter.com .promoted-tweet
if ( fields[0] === 'h' ) {
+ // Special filter: script tags. Not a real CSS selector.
+ if ( fields[3].lastIndexOf('script//:', 0) === 0 ) {
+ this.createScriptTagFilter(fields[2], fields[3].slice(9));
+ continue;
+ }
filter = new FilterHostname(fields[3], fields[2]);
bucket = this.hostnameFilters[fields[1]];
if ( bucket === undefined ) {
@@ -838,6 +846,11 @@ FilterContainer.prototype.fromCompiledContent = function(text, lineBeg, skip) {
// entity selector
if ( fields[0] === 'e' ) {
+ // Special filter: script tags. Not a real CSS selector.
+ if ( fields[2].lastIndexOf('script//:', 0) === 0 ) {
+ this.createScriptTagFilter(fields[1], fields[2].slice(9));
+ continue;
+ }
bucket = this.entityFilters[fields[1]];
if ( bucket === undefined ) {
this.entityFilters[fields[1]] = [fields[2]];
@@ -903,6 +916,49 @@ FilterContainer.prototype.skipCompiledContent = function(text, lineBeg) {
/******************************************************************************/
+FilterContainer.prototype.createScriptTagFilter = function(hostname, s) {
+ if ( this.scriptTagFilters.hasOwnProperty(hostname) ) {
+ this.scriptTagFilters[hostname] += '|' + s;
+ } else {
+ this.scriptTagFilters[hostname] = s;
+ }
+ this.scriptTagFilterCount += 1;
+};
+
+/******************************************************************************/
+
+FilterContainer.prototype.retrieveScriptTagRegex = function(domain, hostname) {
+ if ( this.scriptTagFilterCount === 0 ) {
+ return;
+ }
+ var out = [], hn = hostname, pos;
+ for (;;) {
+ if ( this.scriptTagFilters.hasOwnProperty(hn) ) {
+ out.push(this.scriptTagFilters[hn]);
+ }
+ if ( hn === domain ) {
+ break;
+ }
+ pos = hn.indexOf('.');
+ if ( pos === -1 ) {
+ break;
+ }
+ hn = hn.slice(pos + 1);
+ }
+ pos = domain.indexOf('.');
+ if ( pos !== -1 ) {
+ hn = domain.slice(0, pos);
+ if ( this.scriptTagFilters.hasOwnProperty(hn) ) {
+ out.push(this.scriptTagFilters[hn]);
+ }
+ }
+ if ( out.length !== 0 ) {
+ return out.join('|');
+ }
+};
+
+/******************************************************************************/
+
FilterContainer.prototype.freeze = function() {
this.duplicateBuster = {};
@@ -956,7 +1012,9 @@ FilterContainer.prototype.toSelfie = function() {
highMediumGenericHideCount: this.highMediumGenericHideCount,
highHighGenericHide: this.highHighGenericHide,
highHighGenericHideCount: this.highHighGenericHideCount,
- genericDonthide: this.genericDonthide
+ genericDonthide: this.genericDonthide,
+ scriptTagFilters: this.scriptTagFilters,
+ scriptTagFilterCount: this.scriptTagFilterCount
};
};
@@ -1017,6 +1075,8 @@ FilterContainer.prototype.fromSelfie = function(selfie) {
this.highHighGenericHide = selfie.highHighGenericHide;
this.highHighGenericHideCount = selfie.highHighGenericHideCount;
this.genericDonthide = selfie.genericDonthide;
+ this.scriptTagFilters = selfie.scriptTagFilters;
+ this.scriptTagFilterCount = selfie.scriptTagFilterCount;
this.frozen = true;
};
@@ -1197,6 +1257,7 @@ FilterContainer.prototype.retrieveDomainSelectors = function(request) {
cosmeticHide: [],
cosmeticDonthide: [],
netHide: [],
+ scriptTagRegex: this.retrieveScriptTagRegex(domain, hostname),
netCollapse: µb.userSettings.collapseBlocked
};