mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-10 17:17:57 +01:00
code review + testing after fix to #131
This commit is contained in:
parent
1c219ef718
commit
3e47b8a962
4 changed files with 271 additions and 129 deletions
|
@ -127,6 +127,23 @@ FilterHostname.prototype.retrieve = function(hostname, out) {
|
|||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Any selector specific to an entity
|
||||
// Examples:
|
||||
// google.*###cnt #center_col > #res > #topstuff > .ts
|
||||
|
||||
var FilterEntity = function(s, entity) {
|
||||
this.s = s;
|
||||
this.entity = entity;
|
||||
};
|
||||
|
||||
FilterEntity.prototype.retrieve = function(entity, out) {
|
||||
if ( entity.slice(-this.entity.length) === this.entity ) {
|
||||
out.push(this.s);
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
|
@ -224,20 +241,64 @@ FilterParser.prototype.parse = function(s) {
|
|||
/******************************************************************************/
|
||||
|
||||
var SelectorCacheEntry = function() {
|
||||
this.selectors = [];
|
||||
this.cosmetic = {};
|
||||
this.net = {};
|
||||
this.netCount = 0;
|
||||
this.lastAccessTime = Date.now();
|
||||
};
|
||||
|
||||
SelectorCacheEntry.prototype.add = function(selectors) {
|
||||
this.lastAccessTime = Date.now();
|
||||
this.selectors.push(selectors);
|
||||
};
|
||||
SelectorCacheEntry.prototype.netLowWaterMark = 20;
|
||||
SelectorCacheEntry.prototype.netHighWaterMark = 30;
|
||||
|
||||
SelectorCacheEntry.prototype.retrieve = function(out) {
|
||||
this.lastAccessTime = Date.now();
|
||||
var i = this.selectors.length;
|
||||
SelectorCacheEntry.prototype.addCosmetic = function(selectors) {
|
||||
var dict = this.cosmetic;
|
||||
var i = selectors.length || 0;
|
||||
while ( i-- ) {
|
||||
out.push(this.selectors[i]);
|
||||
dict[selectors[i]] = true;
|
||||
}
|
||||
};
|
||||
|
||||
SelectorCacheEntry.prototype.addNet = function(selector) {
|
||||
if ( typeof selector !== 'string' || selector === '' ) {
|
||||
return;
|
||||
}
|
||||
// Net request-derived selectors: I limit the number of cached selectors,
|
||||
// as I expect cases where the blocked net-requests are never the
|
||||
// exact same URL.
|
||||
var dict = this.net;
|
||||
if ( dict[selector] !== undefined ) {
|
||||
dict[selector] = Date.now();
|
||||
return;
|
||||
}
|
||||
if ( this.netCount >= this.netHighWaterMark ) {
|
||||
var keys = Object.keys(dict).sort(function(a, b) {
|
||||
return dict[b] - dict[a];
|
||||
}).slice(this.netLowWaterMark);
|
||||
var i = keys.length;
|
||||
while ( i-- ) {
|
||||
delete dict[keys[i]];
|
||||
}
|
||||
}
|
||||
dict[selector] = Date.now();
|
||||
this.netCount += 1;
|
||||
};
|
||||
|
||||
SelectorCacheEntry.prototype.add = function(selectors, type) {
|
||||
this.lastAccessTime = Date.now();
|
||||
if ( type === 'cosmetic' ) {
|
||||
this.addCosmetic(selectors);
|
||||
} else {
|
||||
this.addNet(selectors);
|
||||
}
|
||||
};
|
||||
|
||||
SelectorCacheEntry.prototype.retrieve = function(type, out) {
|
||||
this.lastAccessTime = Date.now();
|
||||
var dict = type === 'cosmetic' ? this.cosmetic : this.net;
|
||||
for ( var selector in dict ) {
|
||||
if ( dict.hasOwnProperty(selector) ) {
|
||||
out.push(selector);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -310,7 +371,7 @@ var makeHash = function(unhide, token, mask) {
|
|||
// High-high generic: everything else
|
||||
// Specific
|
||||
// Specfic hostname
|
||||
//
|
||||
// Specific entity
|
||||
// Generic filters can only be enforced once the main document is loaded.
|
||||
// Specific filers can be enforced before the main document is loaded.
|
||||
|
||||
|
@ -343,7 +404,8 @@ FilterContainer.prototype.reset = function() {
|
|||
this.highGenericDonthide = {};
|
||||
this.hostnameHide = {};
|
||||
this.hostnameDonthide = {};
|
||||
|
||||
this.entityHide = {};
|
||||
this.entityDonthide = {};
|
||||
// permanent
|
||||
// [class], [id]
|
||||
this.lowGenericFilters = {};
|
||||
|
@ -367,6 +429,7 @@ FilterContainer.prototype.reset = function() {
|
|||
this.highHighGenericDonthideCount = 0;
|
||||
|
||||
this.hostnameFilters = {};
|
||||
this.entityFilters = {};
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -394,7 +457,7 @@ FilterContainer.prototype.add = function(s) {
|
|||
if ( hostname.charAt(0) !== '~' ) {
|
||||
applyGlobally = false;
|
||||
}
|
||||
this.addHostnameSelector(hostname, parsed);
|
||||
this.addSpecificSelector(hostname, parsed);
|
||||
}
|
||||
if ( applyGlobally ) {
|
||||
this.addGenericSelector(parsed);
|
||||
|
@ -427,6 +490,17 @@ FilterContainer.prototype.addGenericSelector = function(parsed) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
FilterContainer.prototype.addSpecificSelector = function(hostname, parsed) {
|
||||
// rhill 2014-07-13: new filter class: entity.
|
||||
if ( hostname.slice(-2) === '.*' ) {
|
||||
this.addEntitySelector(hostname, parsed);
|
||||
} else {
|
||||
this.addHostnameSelector(hostname, parsed);
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
FilterContainer.prototype.addHostnameSelector = function(hostname, parsed) {
|
||||
// https://github.com/gorhill/uBlock/issues/145
|
||||
var unhide = parsed.unhide;
|
||||
|
@ -452,6 +526,26 @@ FilterContainer.prototype.addHostnameSelector = function(hostname, parsed) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
FilterContainer.prototype.addEntitySelector = function(hostname, parsed) {
|
||||
var entries = parsed.unhide === 0 ?
|
||||
this.entityHide :
|
||||
this.entityDonthide;
|
||||
var entity = hostname.slice(0, -2);
|
||||
var entry = entries[entity];
|
||||
if ( entry === undefined ) {
|
||||
entry = entries[entity] = {};
|
||||
entry[parsed.suffix] = true;
|
||||
this.acceptedCount += 1;
|
||||
} else if ( entry[parsed.suffix] === undefined ) {
|
||||
entry[parsed.suffix] = true;
|
||||
this.acceptedCount += 1;
|
||||
} else {
|
||||
this.duplicateCount += 1;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
FilterContainer.prototype.freezeLowGenerics = function(what, type) {
|
||||
var selectors = this[what];
|
||||
var matches, selectorPrefix, f, hash, bucket;
|
||||
|
@ -509,6 +603,30 @@ FilterContainer.prototype.freezeHostnameSpecifics = function(what, type) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
FilterContainer.prototype.freezeEntitySpecifics = function(what, type) {
|
||||
var entries = this[what];
|
||||
var filters = this.entityFilters;
|
||||
var f, hash, bucket;
|
||||
for ( var entity in entries ) {
|
||||
if ( entries.hasOwnProperty(entity) === false ) {
|
||||
continue;
|
||||
}
|
||||
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];
|
||||
|
||||
|
@ -564,6 +682,8 @@ FilterContainer.prototype.freeze = function() {
|
|||
this.freezeHighGenerics('Donthide');
|
||||
this.freezeHostnameSpecifics('hostnameHide', 0);
|
||||
this.freezeHostnameSpecifics('hostnameDonthide', 1);
|
||||
this.freezeEntitySpecifics('entityHide', 0);
|
||||
this.freezeEntitySpecifics('entityDonthide', 1);
|
||||
this.filterParser.reset();
|
||||
this.frozen = true;
|
||||
|
||||
|
@ -573,11 +693,13 @@ FilterContainer.prototype.freeze = function() {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
FilterContainer.prototype.addToSelectorCache = function(hostname, selectors) {
|
||||
FilterContainer.prototype.addToSelectorCache = function(details) {
|
||||
var hostname = details.hostname;
|
||||
if ( typeof hostname !== 'string' || hostname === '' ) {
|
||||
return;
|
||||
}
|
||||
if ( typeof selectors !== 'string' || selectors === '' ) {
|
||||
var selectors = details.selectors;
|
||||
if ( !selectors ) {
|
||||
return;
|
||||
}
|
||||
var entry = this.selectorCache[hostname];
|
||||
|
@ -588,17 +710,17 @@ FilterContainer.prototype.addToSelectorCache = function(hostname, selectors) {
|
|||
this.pruneSelectorCache();
|
||||
}
|
||||
}
|
||||
entry.add(selectors);
|
||||
entry.add(selectors, details.type);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
FilterContainer.prototype.retrieveFromSelectorCache = function(hostname, out) {
|
||||
FilterContainer.prototype.retrieveFromSelectorCache = function(hostname, type, out) {
|
||||
var entry = this.selectorCache[hostname];
|
||||
if ( entry === undefined ) {
|
||||
return;
|
||||
}
|
||||
entry.retrieve(out);
|
||||
entry.retrieve(type, out);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -691,30 +813,41 @@ FilterContainer.prototype.retrieveDomainSelectors = function(request) {
|
|||
//quickProfiler.start('FilterContainer.retrieve()');
|
||||
|
||||
var hostname = µb.URI.hostnameFromURI(request.locationURL);
|
||||
var domain = µb.URI.domainFromHostname(hostname);
|
||||
var pos = domain.indexOf('.');
|
||||
|
||||
var r = {
|
||||
domain: µb.URI.domainFromHostname(hostname),
|
||||
hide: [],
|
||||
donthide: []
|
||||
domain: domain,
|
||||
entity: pos === -1 ? domain : domain.slice(0, pos - domain.length),
|
||||
cosmeticHide: [],
|
||||
cosmeticDonthide: [],
|
||||
netHide: [],
|
||||
netCollapse: µb.userSettings.collapseBlocked
|
||||
};
|
||||
|
||||
var hash, bucket;
|
||||
hash = makeHash(0, r.domain, this.domainHashMask);
|
||||
if ( bucket = this.hostnameFilters[hash] ) {
|
||||
bucket.retrieve(hostname, r.hide);
|
||||
bucket.retrieve(hostname, r.cosmeticHide);
|
||||
}
|
||||
hash = makeHash(0, r.entity, this.domainHashMask);
|
||||
if ( bucket = this.entityFilters[hash] ) {
|
||||
bucket.retrieve(pos === -1 ? domain : hostname.slice(0, pos - domain.length), r.cosmeticHide);
|
||||
}
|
||||
hash = makeHash(1, r.domain, this.domainHashMask);
|
||||
if ( bucket = this.hostnameFilters[hash] ) {
|
||||
bucket.retrieve(hostname, r.donthide);
|
||||
bucket.retrieve(hostname, r.cosmeticDonthide);
|
||||
}
|
||||
|
||||
this.retrieveFromSelectorCache(hostname, r.hide);
|
||||
this.retrieveFromSelectorCache(hostname, 'cosmetic', r.cosmeticHide);
|
||||
this.retrieveFromSelectorCache(hostname, 'net', r.netHide);
|
||||
|
||||
//quickProfiler.stop();
|
||||
|
||||
//console.log(
|
||||
// 'µBlock> abp-hide-filters.js: "%s" => %d selectors out',
|
||||
// request.locationURL,
|
||||
// r.hide.length + r.donthide.length
|
||||
// r.cosmeticHide.length + r.cosmeticDonthide.length
|
||||
//);
|
||||
|
||||
return r;
|
||||
|
|
|
@ -130,15 +130,16 @@ var uBlockMessaging = (function(name){
|
|||
var idSelectors = null;
|
||||
var highGenerics = null;
|
||||
var contextNodes = [document];
|
||||
var nullArray = { push: function(){} };
|
||||
|
||||
var domLoaded = function() {
|
||||
var style = document.getElementById('uBlockPreload-1ae7a5f130fc79b4fdb8a4272d9426b5');
|
||||
var style = document.getElementById('ublock-preload-1ae7a5f130fc79b4fdb8a4272d9426b5');
|
||||
if ( style ) {
|
||||
// https://github.com/gorhill/uBlock/issues/14
|
||||
// Treat any existing domain-specific exception selectors as if
|
||||
// they had been injected already.
|
||||
var selectors, i;
|
||||
var exceptions = style.getAttribute('uBlockExceptions');
|
||||
var exceptions = style.getAttribute('data-ublock-exceptions');
|
||||
if ( exceptions ) {
|
||||
selectors = JSON.parse(exceptions);
|
||||
i = selectors.length;
|
||||
|
@ -208,19 +209,19 @@ var uBlockMessaging = (function(name){
|
|||
highGenerics = selectors.highGenerics;
|
||||
}
|
||||
if ( selectors && selectors.donthide.length ) {
|
||||
processLowGenerics(selectors.donthide);
|
||||
processLowGenerics(selectors.donthide, nullArray);
|
||||
}
|
||||
if ( highGenerics ) {
|
||||
if ( highGenerics.donthideLowCount ) {
|
||||
processHighLowGenerics(highGenerics.donthideLow);
|
||||
processHighLowGenerics(highGenerics.donthideLow, nullArray);
|
||||
}
|
||||
if ( highGenerics.donthideMediumCount ) {
|
||||
processHighMediumGenerics(highGenerics.donthideMedium);
|
||||
processHighMediumGenerics(highGenerics.donthideMedium, nullArray);
|
||||
}
|
||||
}
|
||||
// No such thing as high-high generic exceptions
|
||||
// No such thing as high-high generic exceptions.
|
||||
//if ( highGenerics.donthideHighCount ) {
|
||||
// processHighHighGenerics(document, highGenerics.donthideHigh);
|
||||
// processHighHighGenerics(document, highGenerics.donthideHigh, nullArray);
|
||||
//}
|
||||
var hideSelectors = [];
|
||||
if ( selectors && selectors.hide.length ) {
|
||||
|
@ -240,18 +241,18 @@ var uBlockMessaging = (function(name){
|
|||
if ( hideSelectors.length ) {
|
||||
applyCSS(hideSelectors, 'display', 'none');
|
||||
var style = document.createElement('style');
|
||||
style.setAttribute('class', 'uBlockPostload-1ae7a5f130fc79b4fdb8a4272d9426b5');
|
||||
style.setAttribute('class', 'ublock-postload-1ae7a5f130fc79b4fdb8a4272d9426b5');
|
||||
// The linefeed before the style block is very important: do no remove!
|
||||
var text = hideSelectors.join(',\n');
|
||||
style.appendChild(document.createTextNode(text + '\n{display:none !important;}'));
|
||||
style.appendChild(document.createTextNode(hideSelectors.join(',\n') + '\n{display:none !important;}'));
|
||||
var parent = document.body || document.documentElement;
|
||||
if ( parent ) {
|
||||
parent.appendChild(style);
|
||||
}
|
||||
messaging.tell({
|
||||
what: 'injectedGenericCosmeticSelectors',
|
||||
what: 'injectedSelectors',
|
||||
type: 'cosmetic',
|
||||
hostname: window.location.hostname,
|
||||
selectors: text
|
||||
selectors: hideSelectors
|
||||
});
|
||||
//console.debug('µBlock> generic cosmetic filters: injecting %d CSS rules:', hideSelectors.length, text);
|
||||
}
|
||||
|
@ -298,10 +299,8 @@ var uBlockMessaging = (function(name){
|
|||
continue;
|
||||
}
|
||||
injectedSelectors[selector] = true;
|
||||
if ( out !== undefined ) {
|
||||
out.push(selector);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var processHighLowGenerics = function(generics, out) {
|
||||
|
@ -319,22 +318,18 @@ var uBlockMessaging = (function(name){
|
|||
if ( generics[selector] ) {
|
||||
if ( injectedSelectors[selector] === undefined ) {
|
||||
injectedSelectors[selector] = true;
|
||||
if ( out !== undefined ) {
|
||||
out.push(selector);
|
||||
}
|
||||
}
|
||||
}
|
||||
selector = node.tagName.toLowerCase() + selector;
|
||||
if ( generics[selector] ) {
|
||||
if ( injectedSelectors[selector] === undefined ) {
|
||||
injectedSelectors[selector] = true;
|
||||
if ( out !== undefined ) {
|
||||
out.push(selector);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var processHighMediumGenerics = function(generics, out) {
|
||||
|
@ -356,12 +351,10 @@ var uBlockMessaging = (function(name){
|
|||
selector = selectors[iSelector];
|
||||
if ( injectedSelectors[selector] === undefined ) {
|
||||
injectedSelectors[selector] = true;
|
||||
if ( out !== undefined ) {
|
||||
out.push(selector);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var processHighHighGenerics = function(generics, out) {
|
||||
|
@ -375,11 +368,9 @@ var uBlockMessaging = (function(name){
|
|||
selector = selectors[iSelector];
|
||||
if ( injectedSelectors[selector] === undefined ) {
|
||||
injectedSelectors[selector] = true;
|
||||
if ( out !== undefined ) {
|
||||
out.push(selector);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var idsFromNodeList = function(nodes) {
|
||||
|
@ -460,10 +451,12 @@ var uBlockMessaging = (function(name){
|
|||
}
|
||||
|
||||
var ignoreTags = {
|
||||
'style': true,
|
||||
'STYLE': true,
|
||||
'link': true,
|
||||
'LINK': true,
|
||||
'script': true,
|
||||
'SCRIPT': true
|
||||
'SCRIPT': true,
|
||||
'style': true,
|
||||
'STYLE': true
|
||||
};
|
||||
|
||||
var mutationObservedHandler = function(mutations) {
|
||||
|
@ -511,62 +504,67 @@ var uBlockMessaging = (function(name){
|
|||
(function() {
|
||||
var messaging = uBlockMessaging;
|
||||
|
||||
var hideOne = function(elem, collapse) {
|
||||
// If `!important` is not there, going back using history will likely
|
||||
// cause the hidden element to re-appear.
|
||||
elem.style.visibility = 'hidden !important';
|
||||
if ( collapse && elem.parentNode ) {
|
||||
elem.parentNode.removeChild(elem);
|
||||
}
|
||||
};
|
||||
|
||||
// First pass
|
||||
messaging.ask({ what: 'blockedRequests' }, function(details) {
|
||||
var elems = document.querySelectorAll('img,iframe,embed');
|
||||
var blockedRequests = details.blockedRequests;
|
||||
var collapse = details.collapse;
|
||||
var i = elems.length;
|
||||
var elem, src;
|
||||
while ( i-- ) {
|
||||
elem = elems[i];
|
||||
src = elem.src;
|
||||
if ( typeof src !== 'string' || src === '' ) {
|
||||
continue;
|
||||
}
|
||||
if ( blockedRequests[src] ) {
|
||||
hideOne(elem, collapse);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Listeners to mop up whatever is otherwise missed:
|
||||
// - Future requests not blocked yet
|
||||
// - Elements dynamically added to the page
|
||||
// - Elements which resource URL changes
|
||||
|
||||
var loadedElements = {
|
||||
'iframe': 'src'
|
||||
};
|
||||
|
||||
var failedElements = {
|
||||
'img': 'src',
|
||||
'object': 'data'
|
||||
};
|
||||
|
||||
var onResource = function(target, dict) {
|
||||
if ( !target ) {
|
||||
return;
|
||||
}
|
||||
var tagName = target.tagName.toLowerCase();
|
||||
var prop = dict[tagName];
|
||||
if ( prop === undefined ) {
|
||||
return;
|
||||
}
|
||||
var src = target[prop];
|
||||
if ( !src ) {
|
||||
return;
|
||||
}
|
||||
var pos = src.indexOf('#');
|
||||
if ( pos !== -1 ) {
|
||||
src = src.slice(0, pos);
|
||||
}
|
||||
var onAnswerReceived = function(details) {
|
||||
if ( !details.blocked ) {
|
||||
return;
|
||||
}
|
||||
// If `!important` is not there, going back using history will
|
||||
// likely cause the hidden element to re-appear.
|
||||
target.style.visibility = 'hidden !important';
|
||||
if ( details.collapse ) {
|
||||
target.parentNode.removeChild(target);
|
||||
}
|
||||
messaging.tell({
|
||||
what: 'injectedSelectors',
|
||||
type: 'net',
|
||||
hostname: window.location.hostname,
|
||||
selectors: tagName + '[' + prop + '="' + src + '"]'
|
||||
});
|
||||
};
|
||||
messaging.ask({ what: 'blockedRequest', url: src }, onAnswerReceived);
|
||||
};
|
||||
|
||||
var onResourceLoaded = function(ev) {
|
||||
var target = ev.target;
|
||||
//console.debug('Loaded %s[src="%s"]', target.tagName, target.src);
|
||||
if ( !target || !target.src ) { return; }
|
||||
if ( target.tagName.toLowerCase() !== 'iframe' ) { return; }
|
||||
var onAnswerReceived = function(details) {
|
||||
if ( details.blocked ) {
|
||||
hideOne(target, details.collapse);
|
||||
}
|
||||
};
|
||||
messaging.ask({ what: 'blockedRequest', url: target.src }, onAnswerReceived);
|
||||
onResource(ev.target, loadedElements);
|
||||
};
|
||||
|
||||
var onResourceFailed = function(ev) {
|
||||
var target = ev.target;
|
||||
//console.debug('Failed to load %s[src="%s"]', target.tagName, target.src);
|
||||
if ( !target || !target.src ) { return; }
|
||||
if ( target.tagName.toLowerCase() !== 'img' ) { return; }
|
||||
var onAnswerReceived = function(details) {
|
||||
if ( details.blocked ) {
|
||||
hideOne(target, details.collapse);
|
||||
}
|
||||
};
|
||||
messaging.ask({ what: 'blockedRequest', url: target.src }, onAnswerReceived);
|
||||
//console.debug('Failed to load %o[src="%s"]', target, target.src);
|
||||
onResource(ev.target, failedElements);
|
||||
};
|
||||
|
||||
document.addEventListener('load', onResourceLoaded, true);
|
||||
document.addEventListener('error', onResourceFailed, true);
|
||||
})();
|
||||
|
|
|
@ -133,21 +133,15 @@ var messaging = (function(name){
|
|||
// Domain-based ABP cosmetic filters.
|
||||
// These can be inserted before the DOM is loaded.
|
||||
|
||||
var domainCosmeticFilteringHandler = function(selectors) {
|
||||
if ( !selectors ) {
|
||||
return;
|
||||
}
|
||||
if ( selectors.hide.length === 0 && selectors.donthide.length === 0 ) {
|
||||
return;
|
||||
}
|
||||
var cosmeticFilters = function(details) {
|
||||
var style = document.createElement('style');
|
||||
style.setAttribute('id', 'uBlockPreload-1ae7a5f130fc79b4fdb8a4272d9426b5');
|
||||
var donthide = selectors.donthide;
|
||||
var hide = selectors.hide;
|
||||
style.setAttribute('id', 'ublock-preload-1ae7a5f130fc79b4fdb8a4272d9426b5');
|
||||
var donthide = details.cosmeticDonthide;
|
||||
var hide = details.cosmeticHide;
|
||||
if ( donthide.length !== 0 ) {
|
||||
donthide = donthide.length !== 1 ? donthide.join(',\n') : donthide[0];
|
||||
donthide = donthide.split(',\n');
|
||||
style.setAttribute('uBlockExceptions', JSON.stringify(donthide));
|
||||
style.setAttribute('data-ublock-exceptions', JSON.stringify(donthide));
|
||||
// https://github.com/gorhill/uBlock/issues/143
|
||||
if ( hide.length !== 0 ) {
|
||||
// I chose to use Array.indexOf() instead of converting the array to
|
||||
|
@ -167,10 +161,10 @@ var domainCosmeticFilteringHandler = function(selectors) {
|
|||
}
|
||||
if ( hide.length !== 0 ) {
|
||||
var text = hide.join(',\n');
|
||||
domainCosmeticFilteringApplyCSS(text, 'display', 'none');
|
||||
applyCSS(text, 'display', 'none');
|
||||
// The linefeed before the style block is very important: do no remove!
|
||||
style.appendChild(document.createTextNode(text + '\n{display:none !important;}'));
|
||||
//console.debug('µBlock> "%s" cosmetic filters: injecting %d CSS rules:', selectors.domain, selectors.hide.length, hideStyleText);
|
||||
//console.debug('µBlock> "%s" cosmetic filters: injecting %d CSS rules:', details.domain, details.hide.length, hideStyleText);
|
||||
}
|
||||
var parent = document.head || document.documentElement;
|
||||
if ( parent ) {
|
||||
|
@ -178,7 +172,34 @@ var domainCosmeticFilteringHandler = function(selectors) {
|
|||
}
|
||||
};
|
||||
|
||||
var domainCosmeticFilteringApplyCSS = function(selectors, prop, value) {
|
||||
var netFilters = function(details) {
|
||||
var parent = document.head || document.documentElement;
|
||||
if ( !parent ) {
|
||||
return;
|
||||
}
|
||||
var style = document.createElement('style');
|
||||
style.setAttribute('class', 'ublock-preload-1ae7a5f130fc79b4fdb8a4272d9426b5');
|
||||
var text = details.netHide.join(',\n');
|
||||
var css = details.netCollapse ?
|
||||
'\n{display:none !important;}' :
|
||||
'\n{visibility:hidden !important;}';
|
||||
style.appendChild(document.createTextNode(text + css));
|
||||
parent.appendChild(style);
|
||||
};
|
||||
|
||||
var filteringHandler = function(details) {
|
||||
if ( !details ) {
|
||||
return;
|
||||
}
|
||||
if ( details.cosmeticHide.length !== 0 || details.cosmeticDonthide.length !== 0 ) {
|
||||
cosmeticFilters(details);
|
||||
}
|
||||
if ( details.netHide.length !== 0 ) {
|
||||
netFilters(details);
|
||||
}
|
||||
};
|
||||
|
||||
var applyCSS = function(selectors, prop, value) {
|
||||
if ( document.body === null ) {
|
||||
return;
|
||||
}
|
||||
|
@ -195,7 +216,7 @@ messaging.ask(
|
|||
pageURL: window.location.href,
|
||||
locationURL: window.location.href
|
||||
},
|
||||
domainCosmeticFilteringHandler
|
||||
filteringHandler
|
||||
);
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -166,18 +166,8 @@ var onMessage = function(request, sender, callback) {
|
|||
}
|
||||
break;
|
||||
|
||||
case 'injectedGenericCosmeticSelectors':
|
||||
µb.abpHideFilters.addToSelectorCache(
|
||||
request.hostname,
|
||||
request.selectors
|
||||
);
|
||||
break;
|
||||
|
||||
case 'blockedRequests':
|
||||
response = {
|
||||
collapse: µb.userSettings.collapseBlocked,
|
||||
blockedRequests: pageStore ? pageStore.blockedRequests : {}
|
||||
};
|
||||
case 'injectedSelectors':
|
||||
µb.abpHideFilters.addToSelectorCache(request);
|
||||
break;
|
||||
|
||||
// Check a single request
|
||||
|
|
Loading…
Reference in a new issue