mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-13 02:14:17 +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() {
|
var SelectorCacheEntry = function() {
|
||||||
this.selectors = [];
|
this.cosmetic = {};
|
||||||
|
this.net = {};
|
||||||
|
this.netCount = 0;
|
||||||
this.lastAccessTime = Date.now();
|
this.lastAccessTime = Date.now();
|
||||||
};
|
};
|
||||||
|
|
||||||
SelectorCacheEntry.prototype.add = function(selectors) {
|
SelectorCacheEntry.prototype.netLowWaterMark = 20;
|
||||||
this.lastAccessTime = Date.now();
|
SelectorCacheEntry.prototype.netHighWaterMark = 30;
|
||||||
this.selectors.push(selectors);
|
|
||||||
};
|
|
||||||
|
|
||||||
SelectorCacheEntry.prototype.retrieve = function(out) {
|
SelectorCacheEntry.prototype.addCosmetic = function(selectors) {
|
||||||
this.lastAccessTime = Date.now();
|
var dict = this.cosmetic;
|
||||||
var i = this.selectors.length;
|
var i = selectors.length || 0;
|
||||||
while ( i-- ) {
|
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
|
// High-high generic: everything else
|
||||||
// Specific
|
// Specific
|
||||||
// Specfic hostname
|
// Specfic hostname
|
||||||
//
|
// Specific entity
|
||||||
// Generic filters can only be enforced once the main document is loaded.
|
// Generic filters can only be enforced once the main document is loaded.
|
||||||
// Specific filers can be enforced before 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.highGenericDonthide = {};
|
||||||
this.hostnameHide = {};
|
this.hostnameHide = {};
|
||||||
this.hostnameDonthide = {};
|
this.hostnameDonthide = {};
|
||||||
|
this.entityHide = {};
|
||||||
|
this.entityDonthide = {};
|
||||||
// permanent
|
// permanent
|
||||||
// [class], [id]
|
// [class], [id]
|
||||||
this.lowGenericFilters = {};
|
this.lowGenericFilters = {};
|
||||||
|
@ -367,6 +429,7 @@ FilterContainer.prototype.reset = function() {
|
||||||
this.highHighGenericDonthideCount = 0;
|
this.highHighGenericDonthideCount = 0;
|
||||||
|
|
||||||
this.hostnameFilters = {};
|
this.hostnameFilters = {};
|
||||||
|
this.entityFilters = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -394,7 +457,7 @@ FilterContainer.prototype.add = function(s) {
|
||||||
if ( hostname.charAt(0) !== '~' ) {
|
if ( hostname.charAt(0) !== '~' ) {
|
||||||
applyGlobally = false;
|
applyGlobally = false;
|
||||||
}
|
}
|
||||||
this.addHostnameSelector(hostname, parsed);
|
this.addSpecificSelector(hostname, parsed);
|
||||||
}
|
}
|
||||||
if ( applyGlobally ) {
|
if ( applyGlobally ) {
|
||||||
this.addGenericSelector(parsed);
|
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) {
|
FilterContainer.prototype.addHostnameSelector = function(hostname, parsed) {
|
||||||
// https://github.com/gorhill/uBlock/issues/145
|
// https://github.com/gorhill/uBlock/issues/145
|
||||||
var unhide = parsed.unhide;
|
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) {
|
FilterContainer.prototype.freezeLowGenerics = function(what, type) {
|
||||||
var selectors = this[what];
|
var selectors = this[what];
|
||||||
var matches, selectorPrefix, f, hash, bucket;
|
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) {
|
FilterContainer.prototype.freezeHighGenerics = function(what) {
|
||||||
var selectors = this['highGeneric' + what];
|
var selectors = this['highGeneric' + what];
|
||||||
|
|
||||||
|
@ -564,6 +682,8 @@ FilterContainer.prototype.freeze = function() {
|
||||||
this.freezeHighGenerics('Donthide');
|
this.freezeHighGenerics('Donthide');
|
||||||
this.freezeHostnameSpecifics('hostnameHide', 0);
|
this.freezeHostnameSpecifics('hostnameHide', 0);
|
||||||
this.freezeHostnameSpecifics('hostnameDonthide', 1);
|
this.freezeHostnameSpecifics('hostnameDonthide', 1);
|
||||||
|
this.freezeEntitySpecifics('entityHide', 0);
|
||||||
|
this.freezeEntitySpecifics('entityDonthide', 1);
|
||||||
this.filterParser.reset();
|
this.filterParser.reset();
|
||||||
this.frozen = true;
|
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 === '' ) {
|
if ( typeof hostname !== 'string' || hostname === '' ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( typeof selectors !== 'string' || selectors === '' ) {
|
var selectors = details.selectors;
|
||||||
|
if ( !selectors ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var entry = this.selectorCache[hostname];
|
var entry = this.selectorCache[hostname];
|
||||||
|
@ -588,17 +710,17 @@ FilterContainer.prototype.addToSelectorCache = function(hostname, selectors) {
|
||||||
this.pruneSelectorCache();
|
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];
|
var entry = this.selectorCache[hostname];
|
||||||
if ( entry === undefined ) {
|
if ( entry === undefined ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
entry.retrieve(out);
|
entry.retrieve(type, out);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -691,30 +813,41 @@ FilterContainer.prototype.retrieveDomainSelectors = function(request) {
|
||||||
//quickProfiler.start('FilterContainer.retrieve()');
|
//quickProfiler.start('FilterContainer.retrieve()');
|
||||||
|
|
||||||
var hostname = µb.URI.hostnameFromURI(request.locationURL);
|
var hostname = µb.URI.hostnameFromURI(request.locationURL);
|
||||||
|
var domain = µb.URI.domainFromHostname(hostname);
|
||||||
|
var pos = domain.indexOf('.');
|
||||||
|
|
||||||
var r = {
|
var r = {
|
||||||
domain: µb.URI.domainFromHostname(hostname),
|
domain: domain,
|
||||||
hide: [],
|
entity: pos === -1 ? domain : domain.slice(0, pos - domain.length),
|
||||||
donthide: []
|
cosmeticHide: [],
|
||||||
|
cosmeticDonthide: [],
|
||||||
|
netHide: [],
|
||||||
|
netCollapse: µb.userSettings.collapseBlocked
|
||||||
};
|
};
|
||||||
|
|
||||||
var hash, bucket;
|
var hash, bucket;
|
||||||
hash = makeHash(0, r.domain, this.domainHashMask);
|
hash = makeHash(0, r.domain, this.domainHashMask);
|
||||||
if ( bucket = this.hostnameFilters[hash] ) {
|
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);
|
hash = makeHash(1, r.domain, this.domainHashMask);
|
||||||
if ( bucket = this.hostnameFilters[hash] ) {
|
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();
|
//quickProfiler.stop();
|
||||||
|
|
||||||
//console.log(
|
//console.log(
|
||||||
// 'µBlock> abp-hide-filters.js: "%s" => %d selectors out',
|
// 'µBlock> abp-hide-filters.js: "%s" => %d selectors out',
|
||||||
// request.locationURL,
|
// request.locationURL,
|
||||||
// r.hide.length + r.donthide.length
|
// r.cosmeticHide.length + r.cosmeticDonthide.length
|
||||||
//);
|
//);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -130,15 +130,16 @@ var uBlockMessaging = (function(name){
|
||||||
var idSelectors = null;
|
var idSelectors = null;
|
||||||
var highGenerics = null;
|
var highGenerics = null;
|
||||||
var contextNodes = [document];
|
var contextNodes = [document];
|
||||||
|
var nullArray = { push: function(){} };
|
||||||
|
|
||||||
var domLoaded = function() {
|
var domLoaded = function() {
|
||||||
var style = document.getElementById('uBlockPreload-1ae7a5f130fc79b4fdb8a4272d9426b5');
|
var style = document.getElementById('ublock-preload-1ae7a5f130fc79b4fdb8a4272d9426b5');
|
||||||
if ( style ) {
|
if ( style ) {
|
||||||
// https://github.com/gorhill/uBlock/issues/14
|
// https://github.com/gorhill/uBlock/issues/14
|
||||||
// Treat any existing domain-specific exception selectors as if
|
// Treat any existing domain-specific exception selectors as if
|
||||||
// they had been injected already.
|
// they had been injected already.
|
||||||
var selectors, i;
|
var selectors, i;
|
||||||
var exceptions = style.getAttribute('uBlockExceptions');
|
var exceptions = style.getAttribute('data-ublock-exceptions');
|
||||||
if ( exceptions ) {
|
if ( exceptions ) {
|
||||||
selectors = JSON.parse(exceptions);
|
selectors = JSON.parse(exceptions);
|
||||||
i = selectors.length;
|
i = selectors.length;
|
||||||
|
@ -208,19 +209,19 @@ var uBlockMessaging = (function(name){
|
||||||
highGenerics = selectors.highGenerics;
|
highGenerics = selectors.highGenerics;
|
||||||
}
|
}
|
||||||
if ( selectors && selectors.donthide.length ) {
|
if ( selectors && selectors.donthide.length ) {
|
||||||
processLowGenerics(selectors.donthide);
|
processLowGenerics(selectors.donthide, nullArray);
|
||||||
}
|
}
|
||||||
if ( highGenerics ) {
|
if ( highGenerics ) {
|
||||||
if ( highGenerics.donthideLowCount ) {
|
if ( highGenerics.donthideLowCount ) {
|
||||||
processHighLowGenerics(highGenerics.donthideLow);
|
processHighLowGenerics(highGenerics.donthideLow, nullArray);
|
||||||
}
|
}
|
||||||
if ( highGenerics.donthideMediumCount ) {
|
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 ) {
|
//if ( highGenerics.donthideHighCount ) {
|
||||||
// processHighHighGenerics(document, highGenerics.donthideHigh);
|
// processHighHighGenerics(document, highGenerics.donthideHigh, nullArray);
|
||||||
//}
|
//}
|
||||||
var hideSelectors = [];
|
var hideSelectors = [];
|
||||||
if ( selectors && selectors.hide.length ) {
|
if ( selectors && selectors.hide.length ) {
|
||||||
|
@ -240,18 +241,18 @@ var uBlockMessaging = (function(name){
|
||||||
if ( hideSelectors.length ) {
|
if ( hideSelectors.length ) {
|
||||||
applyCSS(hideSelectors, 'display', 'none');
|
applyCSS(hideSelectors, 'display', 'none');
|
||||||
var style = document.createElement('style');
|
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!
|
// The linefeed before the style block is very important: do no remove!
|
||||||
var text = hideSelectors.join(',\n');
|
style.appendChild(document.createTextNode(hideSelectors.join(',\n') + '\n{display:none !important;}'));
|
||||||
style.appendChild(document.createTextNode(text + '\n{display:none !important;}'));
|
|
||||||
var parent = document.body || document.documentElement;
|
var parent = document.body || document.documentElement;
|
||||||
if ( parent ) {
|
if ( parent ) {
|
||||||
parent.appendChild(style);
|
parent.appendChild(style);
|
||||||
}
|
}
|
||||||
messaging.tell({
|
messaging.tell({
|
||||||
what: 'injectedGenericCosmeticSelectors',
|
what: 'injectedSelectors',
|
||||||
|
type: 'cosmetic',
|
||||||
hostname: window.location.hostname,
|
hostname: window.location.hostname,
|
||||||
selectors: text
|
selectors: hideSelectors
|
||||||
});
|
});
|
||||||
//console.debug('µBlock> generic cosmetic filters: injecting %d CSS rules:', hideSelectors.length, text);
|
//console.debug('µBlock> generic cosmetic filters: injecting %d CSS rules:', hideSelectors.length, text);
|
||||||
}
|
}
|
||||||
|
@ -298,10 +299,8 @@ var uBlockMessaging = (function(name){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
injectedSelectors[selector] = true;
|
injectedSelectors[selector] = true;
|
||||||
if ( out !== undefined ) {
|
|
||||||
out.push(selector);
|
out.push(selector);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var processHighLowGenerics = function(generics, out) {
|
var processHighLowGenerics = function(generics, out) {
|
||||||
|
@ -319,22 +318,18 @@ var uBlockMessaging = (function(name){
|
||||||
if ( generics[selector] ) {
|
if ( generics[selector] ) {
|
||||||
if ( injectedSelectors[selector] === undefined ) {
|
if ( injectedSelectors[selector] === undefined ) {
|
||||||
injectedSelectors[selector] = true;
|
injectedSelectors[selector] = true;
|
||||||
if ( out !== undefined ) {
|
|
||||||
out.push(selector);
|
out.push(selector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
selector = node.tagName.toLowerCase() + selector;
|
selector = node.tagName.toLowerCase() + selector;
|
||||||
if ( generics[selector] ) {
|
if ( generics[selector] ) {
|
||||||
if ( injectedSelectors[selector] === undefined ) {
|
if ( injectedSelectors[selector] === undefined ) {
|
||||||
injectedSelectors[selector] = true;
|
injectedSelectors[selector] = true;
|
||||||
if ( out !== undefined ) {
|
|
||||||
out.push(selector);
|
out.push(selector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var processHighMediumGenerics = function(generics, out) {
|
var processHighMediumGenerics = function(generics, out) {
|
||||||
|
@ -356,12 +351,10 @@ var uBlockMessaging = (function(name){
|
||||||
selector = selectors[iSelector];
|
selector = selectors[iSelector];
|
||||||
if ( injectedSelectors[selector] === undefined ) {
|
if ( injectedSelectors[selector] === undefined ) {
|
||||||
injectedSelectors[selector] = true;
|
injectedSelectors[selector] = true;
|
||||||
if ( out !== undefined ) {
|
|
||||||
out.push(selector);
|
out.push(selector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var processHighHighGenerics = function(generics, out) {
|
var processHighHighGenerics = function(generics, out) {
|
||||||
|
@ -375,11 +368,9 @@ var uBlockMessaging = (function(name){
|
||||||
selector = selectors[iSelector];
|
selector = selectors[iSelector];
|
||||||
if ( injectedSelectors[selector] === undefined ) {
|
if ( injectedSelectors[selector] === undefined ) {
|
||||||
injectedSelectors[selector] = true;
|
injectedSelectors[selector] = true;
|
||||||
if ( out !== undefined ) {
|
|
||||||
out.push(selector);
|
out.push(selector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var idsFromNodeList = function(nodes) {
|
var idsFromNodeList = function(nodes) {
|
||||||
|
@ -460,10 +451,12 @@ var uBlockMessaging = (function(name){
|
||||||
}
|
}
|
||||||
|
|
||||||
var ignoreTags = {
|
var ignoreTags = {
|
||||||
'style': true,
|
'link': true,
|
||||||
'STYLE': true,
|
'LINK': true,
|
||||||
'script': true,
|
'script': true,
|
||||||
'SCRIPT': true
|
'SCRIPT': true,
|
||||||
|
'style': true,
|
||||||
|
'STYLE': true
|
||||||
};
|
};
|
||||||
|
|
||||||
var mutationObservedHandler = function(mutations) {
|
var mutationObservedHandler = function(mutations) {
|
||||||
|
@ -511,62 +504,67 @@ var uBlockMessaging = (function(name){
|
||||||
(function() {
|
(function() {
|
||||||
var messaging = uBlockMessaging;
|
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:
|
// Listeners to mop up whatever is otherwise missed:
|
||||||
// - Future requests not blocked yet
|
// - Future requests not blocked yet
|
||||||
// - Elements dynamically added to the page
|
// - Elements dynamically added to the page
|
||||||
// - Elements which resource URL changes
|
// - 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 onResourceLoaded = function(ev) {
|
||||||
var target = ev.target;
|
|
||||||
//console.debug('Loaded %s[src="%s"]', target.tagName, target.src);
|
//console.debug('Loaded %s[src="%s"]', target.tagName, target.src);
|
||||||
if ( !target || !target.src ) { return; }
|
onResource(ev.target, loadedElements);
|
||||||
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);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var onResourceFailed = function(ev) {
|
var onResourceFailed = function(ev) {
|
||||||
var target = ev.target;
|
//console.debug('Failed to load %o[src="%s"]', target, target.src);
|
||||||
//console.debug('Failed to load %s[src="%s"]', target.tagName, target.src);
|
onResource(ev.target, failedElements);
|
||||||
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);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener('load', onResourceLoaded, true);
|
document.addEventListener('load', onResourceLoaded, true);
|
||||||
document.addEventListener('error', onResourceFailed, true);
|
document.addEventListener('error', onResourceFailed, true);
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -133,21 +133,15 @@ var messaging = (function(name){
|
||||||
// Domain-based ABP cosmetic filters.
|
// Domain-based ABP cosmetic filters.
|
||||||
// These can be inserted before the DOM is loaded.
|
// These can be inserted before the DOM is loaded.
|
||||||
|
|
||||||
var domainCosmeticFilteringHandler = function(selectors) {
|
var cosmeticFilters = function(details) {
|
||||||
if ( !selectors ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ( selectors.hide.length === 0 && selectors.donthide.length === 0 ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var style = document.createElement('style');
|
var style = document.createElement('style');
|
||||||
style.setAttribute('id', 'uBlockPreload-1ae7a5f130fc79b4fdb8a4272d9426b5');
|
style.setAttribute('id', 'ublock-preload-1ae7a5f130fc79b4fdb8a4272d9426b5');
|
||||||
var donthide = selectors.donthide;
|
var donthide = details.cosmeticDonthide;
|
||||||
var hide = selectors.hide;
|
var hide = details.cosmeticHide;
|
||||||
if ( donthide.length !== 0 ) {
|
if ( donthide.length !== 0 ) {
|
||||||
donthide = donthide.length !== 1 ? donthide.join(',\n') : donthide[0];
|
donthide = donthide.length !== 1 ? donthide.join(',\n') : donthide[0];
|
||||||
donthide = donthide.split(',\n');
|
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
|
// https://github.com/gorhill/uBlock/issues/143
|
||||||
if ( hide.length !== 0 ) {
|
if ( hide.length !== 0 ) {
|
||||||
// I chose to use Array.indexOf() instead of converting the array to
|
// I chose to use Array.indexOf() instead of converting the array to
|
||||||
|
@ -167,10 +161,10 @@ var domainCosmeticFilteringHandler = function(selectors) {
|
||||||
}
|
}
|
||||||
if ( hide.length !== 0 ) {
|
if ( hide.length !== 0 ) {
|
||||||
var text = hide.join(',\n');
|
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!
|
// The linefeed before the style block is very important: do no remove!
|
||||||
style.appendChild(document.createTextNode(text + '\n{display:none !important;}'));
|
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;
|
var parent = document.head || document.documentElement;
|
||||||
if ( parent ) {
|
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 ) {
|
if ( document.body === null ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -195,7 +216,7 @@ messaging.ask(
|
||||||
pageURL: window.location.href,
|
pageURL: window.location.href,
|
||||||
locationURL: window.location.href
|
locationURL: window.location.href
|
||||||
},
|
},
|
||||||
domainCosmeticFilteringHandler
|
filteringHandler
|
||||||
);
|
);
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
|
@ -166,18 +166,8 @@ var onMessage = function(request, sender, callback) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'injectedGenericCosmeticSelectors':
|
case 'injectedSelectors':
|
||||||
µb.abpHideFilters.addToSelectorCache(
|
µb.abpHideFilters.addToSelectorCache(request);
|
||||||
request.hostname,
|
|
||||||
request.selectors
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'blockedRequests':
|
|
||||||
response = {
|
|
||||||
collapse: µb.userSettings.collapseBlocked,
|
|
||||||
blockedRequests: pageStore ? pageStore.blockedRequests : {}
|
|
||||||
};
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Check a single request
|
// Check a single request
|
||||||
|
|
Loading…
Reference in a new issue