1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-10-04 16:47:15 +02:00
This commit is contained in:
gorhill 2017-10-22 08:59:29 -04:00
parent 6112a68faf
commit 4f7aab695c
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
5 changed files with 261 additions and 291 deletions

View File

@ -32,11 +32,66 @@ if ( typeof vAPI === 'object' ) { // >>>>>>>> start of HUGE-IF-BLOCK
/******************************************************************************/ /******************************************************************************/
/******************************************************************************/ /******************************************************************************/
vAPI.userStylesheet = {
style: null,
css: new Map(),
disabled: false,
apply: function() {
},
add: function(cssText) {
if ( cssText === '' || this.css.has(cssText) ) { return; }
if ( this.style === null ) {
this.style = document.createElement('style');
this.style.disabled = this.disabled;
var parent = document.head || document.documentElement;
if ( parent !== null ) {
parent.appendChild(this.style);
}
}
var sheet = this.style.sheet,
i = sheet.cssRules.length;
if ( !sheet ) { return; }
sheet.insertRule(cssText, i);
this.css.set(cssText, sheet.cssRules[i]);
},
remove: function(cssText) {
if ( cssText === '' ) { return; }
var cssRule = this.css.get(cssText);
if ( cssRule === undefined ) { return; }
this.css.delete(cssText);
if ( this.style === null ) { return; }
var rules = this.style.sheet.cssRules,
i = rules.length;
while ( i-- ) {
if ( rules[i] !== cssRule ) { continue; }
this.style.sheet.deleteRule(i);
break;
}
if ( rules.length === 0 ) {
var parent = this.style.parentNode;
if ( parent !== null ) {
parent.removeChild(this.style);
}
this.style = null;
}
},
toggle: function(state) {
if ( state === undefined ) { state = this.disabled; }
if ( state !== this.disabled ) { return; }
this.disabled = !state;
if ( this.style !== null ) {
this.style.disabled = this.disabled;
}
}
};
/******************************************************************************/
vAPI.DOMFilterer = function() { vAPI.DOMFilterer = function() {
this.commitTimer = new vAPI.SafeAnimationFrame(this.commitNow.bind(this)); this.commitTimer = new vAPI.SafeAnimationFrame(this.commitNow.bind(this));
this.domIsReady = document.readyState !== 'loading'; this.domIsReady = document.readyState !== 'loading';
this.listeners = []; this.listeners = [];
this.hideNodeId = vAPI.randomToken(); this.hideNodeAttr = vAPI.randomToken();
this.hideNodeStylesheet = false; this.hideNodeStylesheet = false;
this.excludedNodeSet = new WeakSet(); this.excludedNodeSet = new WeakSet();
this.addedNodes = new Set(); this.addedNodes = new Set();
@ -48,73 +103,10 @@ vAPI.DOMFilterer = function() {
this.specificComplexHide = new Set(); this.specificComplexHide = new Set();
this.specificComplexHideAggregated = undefined; this.specificComplexHideAggregated = undefined;
this.addedSpecificComplexHide = []; this.addedSpecificComplexHide = [];
this.specificOthers = [];
this.genericSimpleHide = new Set(); this.genericSimpleHide = new Set();
this.genericComplexHide = new Set(); this.genericComplexHide = new Set();
this.userStylesheet = {
style: null,
css: new Map(),
disabled: false,
add: function(cssText) {
if ( cssText === '' || this.css.has(cssText) ) { return; }
if ( this.style === null ) {
this.style = document.createElement('style');
this.style.disabled = this.disabled;
var parent = document.head || document.documentElement;
if ( parent !== null ) {
parent.appendChild(this.style);
}
}
var sheet = this.style.sheet,
i = sheet.cssRules.length;
if ( !sheet ) { return; }
sheet.insertRule(cssText, i);
this.css.set(cssText, sheet.cssRules[i]);
},
remove: function(cssText) {
if ( cssText === '' ) { return; }
var cssRule = this.css.get(cssText);
if ( cssRule === undefined ) { return; }
this.css.delete(cssText);
if ( this.style === null ) { return; }
var rules = this.style.sheet.cssRules,
i = rules.length;
while ( i-- ) {
if ( rules[i] !== cssRule ) { continue; }
this.style.sheet.deleteRule(i);
break;
}
if ( rules.length === 0 ) {
var parent = this.style.parentNode;
if ( parent !== null ) {
parent.removeChild(this.style);
}
this.style = null;
}
},
toggle: function(state) {
if ( state === undefined ) { state = this.disabled; }
if ( state !== this.disabled ) { return; }
this.disabled = !state;
if ( this.style !== null ) {
this.style.disabled = this.disabled;
}
},
getAllSelectors: function() {
var out = [];
var rules = this.style &&
this.style.sheet &&
this.style.sheet.cssRules;
if ( rules instanceof Object === false ) { return out; }
var i = rules.length;
while ( i-- ) {
out.push(rules.item(i).selectorText);
}
return out;
}
};
this.hideNodeExpando = undefined; this.hideNodeExpando = undefined;
this.hideNodeBatchProcessTimer = undefined; this.hideNodeBatchProcessTimer = undefined;
this.hiddenNodeObserver = undefined; this.hiddenNodeObserver = undefined;
@ -135,7 +127,7 @@ vAPI.DOMFilterer.prototype = {
commitNow: function() { commitNow: function() {
this.commitTimer.clear(); this.commitTimer.clear();
if ( this.domIsReady !== true || this.userStylesheet.disabled ) { if ( this.domIsReady !== true || vAPI.userStylesheet.disabled ) {
return; return;
} }
@ -227,28 +219,31 @@ vAPI.DOMFilterer.prototype = {
if ( details === undefined ) { details = {}; } if ( details === undefined ) { details = {}; }
var isGeneric= details.lazy === true,
isSimple = details.type === 'simple',
isComplex = details.type === 'complex',
selector;
var selectorsStr = Array.isArray(selectors) ? var selectorsStr = Array.isArray(selectors) ?
selectors.join(',\n') : selectors.join(',\n') :
selectors; selectors;
if ( selectorsStr.length === 0 ) { return; } if ( selectorsStr.length === 0 ) { return; }
this.userStylesheet.add( vAPI.userStylesheet.add(selectorsStr + '\n{ ' + declarations + ' }');
selectorsStr +
'\n{ ' + declarations + ' }'
);
this.commit(); this.commit();
this.triggerListeners('declarative', selectorsStr); this.triggerListeners('declarative', selectorsStr);
if ( this.reHideStyle.test(declarations) === false ) { if ( this.reHideStyle.test(declarations) === false ) {
this.specificOthers.push({
selectors: selectorsStr,
declarations: declarations
});
return; return;
} }
// Do not strongly enforce internal CSS rules.
if ( details.internal ) { return; }
var isGeneric= details.lazy === true,
isSimple = details.type === 'simple',
isComplex = details.type === 'complex',
selector;
if ( isGeneric ) { if ( isGeneric ) {
if ( isSimple ) { if ( isSimple ) {
this.genericSimpleHide.add(selectorsStr); this.genericSimpleHide.add(selectorsStr);
@ -292,31 +287,6 @@ vAPI.DOMFilterer.prototype = {
} }
}, },
removeCSSRule: function(selectors, declarations) {
var selectorsStr = Array.isArray(selectors)
? selectors.join(',\n')
: selectors;
if ( selectorsStr.length === 0 ) { return; }
this.userStylesheet.remove(
selectorsStr +
'\n{ ' + declarations + ' }'
);
if ( this.reHideStyle.test(declarations) === false ) { return; }
var selectorsArr = Array.isArray(selectors) ?
selectors :
selectors.split(',\n');
for ( var selector of selectorsArr ) {
if ( this.reCSSCombinators.test(selector) ) {
this.specificComplexHide.remove(selector);
this.genericComplexHide.remove(selector);
} else {
this.specificSimpleHide.remove(selector);
this.genericSimpleHide.remove(selector);
}
}
this.commit();
},
onDOMCreated: function() { onDOMCreated: function() {
this.domIsReady = true; this.domIsReady = true;
this.addedNodes.clear(); this.addedNodes.clear();
@ -391,7 +361,7 @@ vAPI.DOMFilterer.prototype = {
}, },
hideNodeObserverHandler: function(mutations) { hideNodeObserverHandler: function(mutations) {
if ( this.userStylesheet.disabled ) { return; } if ( vAPI.userStylesheet.disabled ) { return; }
var i = mutations.length, var i = mutations.length,
stagedNodes = this.hiddenNodesetToProcess; stagedNodes = this.hiddenNodesetToProcess;
while ( i-- ) { while ( i-- ) {
@ -413,8 +383,8 @@ vAPI.DOMFilterer.prototype = {
new MutationObserver(this.hideNodeObserverHandler.bind(this)); new MutationObserver(this.hideNodeObserverHandler.bind(this));
if ( this.hideNodeStylesheet === false ) { if ( this.hideNodeStylesheet === false ) {
this.hideNodeStylesheet = true; this.hideNodeStylesheet = true;
this.userStylesheet.add( vAPI.userStylesheet.add(
'[' + this.hideNodeId + ']\n{ display: none !important; }' '[' + this.hideNodeAttr + ']\n{ display: none !important; }'
); );
} }
}, },
@ -424,12 +394,16 @@ vAPI.DOMFilterer.prototype = {
this.unhideNode(node); this.unhideNode(node);
}, },
unexcludeNode: function(node) {
this.excludedNodeSet.delete(node);
},
hideNode: function(node) { hideNode: function(node) {
if ( this.excludedNodeSet.has(node) ) { return; } if ( this.excludedNodeSet.has(node) ) { return; }
if ( this.hiddenNodeset.has(node) ) { return; } if ( this.hiddenNodeset.has(node) ) { return; }
this.hiddenNodeset.add(node); this.hiddenNodeset.add(node);
if ( this.hideNodeExpando === undefined ) { this.hideNodeInit(); } if ( this.hideNodeExpando === undefined ) { this.hideNodeInit(); }
node.setAttribute(this.hideNodeId, ''); node.setAttribute(this.hideNodeAttr, '');
if ( node[this.hideNodeExpando] === undefined ) { if ( node[this.hideNodeExpando] === undefined ) {
node[this.hideNodeExpando] = node[this.hideNodeExpando] =
node.hasAttribute('style') && node.hasAttribute('style') &&
@ -442,7 +416,7 @@ vAPI.DOMFilterer.prototype = {
unhideNode: function(node) { unhideNode: function(node) {
if ( this.hiddenNodeset.has(node) === false ) { return; } if ( this.hiddenNodeset.has(node) === false ) { return; }
node.removeAttribute(this.hideNodeId); node.removeAttribute(this.hideNodeAttr);
this.hiddenNodesetToProcess.delete(node); this.hiddenNodesetToProcess.delete(node);
if ( this.hideNodeExpando === undefined ) { return; } if ( this.hideNodeExpando === undefined ) { return; }
var attr = node[this.hideNodeExpando]; var attr = node[this.hideNodeExpando];
@ -469,9 +443,9 @@ vAPI.DOMFilterer.prototype = {
}, },
toggle: function(state) { toggle: function(state) {
this.userStylesheet.toggle(state); vAPI.userStylesheet.toggle(state);
var disabled = this.userStylesheet.disabled, var disabled = vAPI.userStylesheet.disabled,
nodes = document.querySelectorAll('[' + this.hideNodeId + ']'); nodes = document.querySelectorAll('[' + this.hideNodeAttr + ']');
for ( var node of nodes ) { for ( var node of nodes ) {
if ( disabled ) { if ( disabled ) {
this.showNode(node); this.showNode(node);
@ -484,19 +458,37 @@ vAPI.DOMFilterer.prototype = {
} }
}, },
getAllDeclarativeSelectors_: function(all) {
var out = [];
if ( this.specificSimpleHide.size !== 0 ) {
out.push(Array.from(this.specificSimpleHide).join(',\n'));
}
if ( this.specificComplexHide.size !== 0 ) {
out.push(Array.from(this.specificComplexHide).join(',\n'));
}
if ( this.genericSimpleHide.size !== 0 ) {
out.push(Array.from(this.genericSimpleHide).join(',\n'));
}
if ( this.genericComplexHide.size !== 0 ) {
out.push(Array.from(this.genericComplexHide).join(',\n'));
}
if ( all ) {
out.push('[' + this.hideNodeAttr + ']');
}
for ( var entry of this.specificOthers ) {
out.push(entry.selectors);
}
return out.join(',\n');
},
getFilteredElementCount: function() { getFilteredElementCount: function() {
return document.querySelectorAll( var selectors = this.getAllDeclarativeSelectors_(true);
this.userStylesheet.getAllSelectors().join(',\n') if ( selectors.length === 0 ) { return 0; }
).length; return document.querySelectorAll(selectors).length;
}, },
getAllDeclarativeSelectors: function() { getAllDeclarativeSelectors: function() {
return [].concat( return this.getAllDeclarativeSelectors_();
Array.from(this.specificSimpleHide),
Array.from(this.specificComplexHide),
Array.from(this.genericSimpleHide),
Array.from(this.genericComplexHide)
).join(',\n');
} }
}; };

View File

@ -28,75 +28,43 @@ if ( typeof vAPI === 'object' ) { // >>>>>>>> start of HUGE-IF-BLOCK
/******************************************************************************/ /******************************************************************************/
/******************************************************************************/ /******************************************************************************/
vAPI.userStylesheet = {
added: new Set(),
removed: new Set(),
apply: function() {
if ( this.added.size === 0 && this.removed.size === 0 ) { return; }
vAPI.messaging.send('vapi-background', {
what: 'userCSS',
add: Array.from(this.added),
remove: Array.from(this.removed)
});
this.added.clear();
this.removed.clear();
},
add: function(cssText, now) {
if ( cssText === '' ) { return; }
this.added.add(cssText);
if ( now ) { this.apply(); }
},
remove: function(cssText, now) {
if ( cssText === '' ) { return; }
this.removed.add(cssText);
if ( now ) { this.apply(); }
}
};
/******************************************************************************/
vAPI.DOMFilterer = function() { vAPI.DOMFilterer = function() {
this.commitTimer = new vAPI.SafeAnimationFrame(this.commitNow.bind(this)); this.commitTimer = new vAPI.SafeAnimationFrame(this.commitNow.bind(this));
this.domIsReady = document.readyState !== 'loading'; this.domIsReady = document.readyState !== 'loading';
this.disabled = false;
this.listeners = []; this.listeners = [];
this.filterset = new Set();
this.hideNodeId = vAPI.randomToken(); this.hideNodeId = vAPI.randomToken();
this.hideNodeStylesheet = false; this.hideNodeStylesheet = false;
this.excludedNodeSet = new WeakSet(); this.excludedNodeSet = new WeakSet();
this.addedCSSRules = []; this.addedCSSRules = new Set();
this.removedCSSRules = [];
this.internalRules = new Set();
this.userStylesheets = {
current: new Set(),
added: new Set(),
removed: new Set(),
disabled: false,
apply: function() {
for ( let cssText of this.added ) {
if ( this.current.has(cssText) || this.removed.has(cssText) ) {
this.added.delete(cssText);
} else {
this.current.add(cssText);
}
}
for ( let cssText of this.removed ) {
if ( this.current.has(cssText) === false ) {
this.removed.delete(cssText);
} else {
this.current.delete(cssText);
}
}
if ( this.added.size === 0 && this.removed.size === 0 ) { return; }
if ( this.disabled === false ) {
vAPI.messaging.send('vapi-background', {
what: 'userCSS',
add: Array.from(this.added),
remove: Array.from(this.removed)
});
}
this.added.clear();
this.removed.clear();
},
add: function(cssText) {
if ( cssText === '' ) { return; }
this.added.add(cssText);
},
remove: function(cssText) {
if ( cssText === '' ) { return; }
this.removed.add(cssText);
},
toggle: function(state) {
if ( state === undefined ) { state = this.disabled; }
if ( state !== this.disabled ) { return; }
this.disabled = !state;
if ( this.current.size === 0 ) { return; }
var all = Array.from(this.current);
var toAdd = [], toRemove = [];
if ( this.disabled ) {
toRemove = all;
} else {
toAdd = all;
}
vAPI.messaging.send('vapi-background', {
what: 'userCSS',
add: toAdd,
remove: toRemove
});
}
};
if ( this.domIsReady !== true ) { if ( this.domIsReady !== true ) {
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
@ -108,30 +76,27 @@ vAPI.DOMFilterer = function() {
vAPI.DOMFilterer.prototype = { vAPI.DOMFilterer.prototype = {
reOnlySelectors: /\n\{[^\n]+/g, reOnlySelectors: /\n\{[^\n]+/g,
// Here we will deal with:
// - Injecting low priority user styles;
// - Notifying listeners about changed filterset.
commitNow: function() { commitNow: function() {
this.commitTimer.clear(); this.commitTimer.clear();
var i, entry, ruleText; var userStylesheet = vAPI.userStylesheet,
i = this.addedCSSRules.length; addedSelectors = [];
while ( i-- ) { for ( var entry of this.addedCSSRules ) {
entry = this.addedCSSRules[i]; if ( this.disabled === false && entry.lazy ) {
if ( entry.lazy !== true || this.domIsReady ) { userStylesheet.add(
ruleText = entry.selectors + '\n{ ' + entry.declarations + ' }'; entry.selectors + '\n{' + entry.declarations + '}'
this.userStylesheets.add(ruleText); );
this.addedCSSRules.splice(i, 1);
if ( entry.internal ) {
this.internalRules.add(ruleText);
}
} }
addedSelectors.push(entry.selectors);
} }
i = this.removedCSSRules.length; this.addedCSSRules.clear();
while ( i-- ) { userStylesheet.apply();
entry = this.removedCSSRules[i]; if ( addedSelectors.length !== 0 ) {
ruleText = entry.selectors + '\n{ ' + entry.declarations + ' }'; this.triggerListeners('declarative', addedSelectors.join(',\n'));
this.userStylesheets.remove(ruleText);
this.internalRules.delete(ruleText);
} }
this.removedCSSRules = [];
this.userStylesheets.apply();
}, },
commit: function(commitNow) { commit: function(commitNow) {
@ -149,25 +114,17 @@ vAPI.DOMFilterer.prototype = {
? selectors.join(',\n') ? selectors.join(',\n')
: selectors; : selectors;
if ( selectorsStr.length === 0 ) { return; } if ( selectorsStr.length === 0 ) { return; }
this.addedCSSRules.push({ var entry = {
selectors: selectorsStr, selectors: selectorsStr,
declarations, declarations,
lazy: details && details.lazy === true, lazy: details !== undefined && details.lazy === true,
internal: details && details.internal === true internal: details && details.internal === true
}); };
this.commit(); this.addedCSSRules.add(entry);
this.triggerListeners('declarative', selectorsStr); this.filterset.add(entry);
}, if ( this.disabled === false && entry.lazy !== true ) {
vAPI.userStylesheet.add(selectorsStr + '\n{' + declarations + '}');
removeCSSRule: function(selectors, declarations) { }
var selectorsStr = Array.isArray(selectors)
? selectors.join(',\n')
: selectors;
if ( selectorsStr.length === 0 ) { return; }
this.removedCSSRules.push({
selectors: selectorsStr,
declarations,
});
this.commit(); this.commit();
}, },
@ -194,6 +151,10 @@ vAPI.DOMFilterer.prototype = {
this.unhideNode(node); this.unhideNode(node);
}, },
unexcludeNode: function(node) {
this.excludedNodeSet.delete(node);
},
hideNode: function(node) { hideNode: function(node) {
if ( this.excludedNodeSet.has(node) ) { return; } if ( this.excludedNodeSet.has(node) ) { return; }
node.setAttribute(this.hideNodeId, ''); node.setAttribute(this.hideNodeId, '');
@ -212,16 +173,26 @@ vAPI.DOMFilterer.prototype = {
}, },
toggle: function(state) { toggle: function(state) {
this.userStylesheets.toggle(state); if ( state === undefined ) { state = this.disabled; }
if ( state !== this.disabled ) { return; }
this.disabled = !state;
var userStylesheet = vAPI.userStylesheet;
for ( var entry of this.filterset ) {
var rule = entry.selectors + '\n{' + entry.declarations + '}';
if ( this.disabled ) {
userStylesheet.remove(rule);
} else {
userStylesheet.add(rule);
}
}
userStylesheet.apply();
}, },
getAllDeclarativeSelectors_: function(all) { getAllDeclarativeSelectors_: function(all) {
let selectors = []; let selectors = [];
for ( var sheet of this.userStylesheets.current ) { for ( var entry of this.filterset ) {
if ( all === false && this.internalRules.has(sheet) ) { continue; } if ( all === false && entry.internal ) { continue; }
selectors.push( selectors.push(entry.selectors);
sheet.replace(this.reOnlySelectors, ',').trim().slice(0, -1)
);
} }
return selectors.join(',\n'); return selectors.join(',\n');
}, },

View File

@ -774,7 +774,7 @@ vAPI.domCollapser = (function() {
iframeLoadEventPatch(target); iframeLoadEventPatch(target);
} }
} }
/*
if ( selectors.length !== 0 ) { if ( selectors.length !== 0 ) {
messaging.send( messaging.send(
'contentscript', 'contentscript',
@ -786,7 +786,6 @@ vAPI.domCollapser = (function() {
} }
); );
} }
*/
}; };
var send = function() { var send = function() {
@ -1292,25 +1291,21 @@ vAPI.domSurveyor = (function() {
domFilterer.addProceduralSelectors(cfeDetails.proceduralFilters); domFilterer.addProceduralSelectors(cfeDetails.proceduralFilters);
} }
if ( cfeDetails.netFilters.length !== 0 ) {
vAPI.userStylesheet.add(
cfeDetails.netFilters + '\n{ display: none !important; }');
}
vAPI.userStylesheet.apply();
var parent = document.head || document.documentElement; var parent = document.head || document.documentElement;
if ( parent ) { if ( parent ) {
var elem, text;
if ( cfeDetails.netHide.length !== 0 ) {
elem = document.createElement('style');
elem.setAttribute('type', 'text/css');
text = cfeDetails.netHide.join(',\n');
text += response.collapseBlocked ?
'\n{ display:none !important; }' :
'\n{ visibility:hidden !important; }';
elem.appendChild(document.createTextNode(text));
parent.appendChild(elem);
}
// Library of resources is located at: // Library of resources is located at:
// https://github.com/gorhill/uBlock/blob/master/assets/ublock/resources.txt // https://github.com/gorhill/uBlock/blob/master/assets/ublock/resources.txt
if ( cfeDetails.scripts ) { if ( cfeDetails.scripts ) {
// Have the injected script tag remove itself when execution completes: // Have the injected script tag remove itself when execution completes:
// to keep DOM as clean as possible. // to keep DOM as clean as possible.
text = cfeDetails.scripts + var text = cfeDetails.scripts +
"\n" + "\n" +
"(function() {\n" + "(function() {\n" +
" var c = document.currentScript,\n" + " var c = document.currentScript,\n" +

View File

@ -408,7 +408,7 @@ SelectorCacheEntry.factory = function() {
/******************************************************************************/ /******************************************************************************/
// var netSelectorCacheLowWaterMark = 20; var netSelectorCacheLowWaterMark = 20;
var netSelectorCacheHighWaterMark = 30; var netSelectorCacheHighWaterMark = 30;
/******************************************************************************/ /******************************************************************************/
@ -451,8 +451,7 @@ SelectorCacheEntry.prototype.addCosmetic = function(details) {
/******************************************************************************/ /******************************************************************************/
SelectorCacheEntry.prototype.addNet = function(/* selectors */) { SelectorCacheEntry.prototype.addNet = function(selectors) {
/*
if ( typeof selectors === 'string' ) { if ( typeof selectors === 'string' ) {
this.addNetOne(selectors, Date.now()); this.addNetOne(selectors, Date.now());
} else { } else {
@ -470,7 +469,6 @@ SelectorCacheEntry.prototype.addNet = function(/* selectors */) {
while ( i-- ) { while ( i-- ) {
dict.delete(keys[i]); dict.delete(keys[i]);
} }
*/
}; };
/******************************************************************************/ /******************************************************************************/
@ -515,11 +513,25 @@ SelectorCacheEntry.prototype.remove = function(type) {
/******************************************************************************/ /******************************************************************************/
SelectorCacheEntry.prototype.retrieveToArray = function(iterator, out) {
for ( var selector of iterator ) {
out.push(selector);
}
};
SelectorCacheEntry.prototype.retrieveToSet = function(iterator, out) {
for ( var selector of iterator ) {
out.add(selector);
}
};
SelectorCacheEntry.prototype.retrieve = function(type, out) { SelectorCacheEntry.prototype.retrieve = function(type, out) {
this.lastAccessTime = Date.now(); this.lastAccessTime = Date.now();
var dict = type === 'cosmetic' ? this.cosmetic : this.net; var iterator = type === 'cosmetic' ? this.cosmetic : this.net.keys();
for ( var selector of dict ) { if ( Array.isArray(out) ) {
out.add(selector); this.retrieveToArray(iterator, out);
} else {
this.retrieveToSet(iterator, out);
} }
}; };
@ -1964,7 +1976,8 @@ FilterContainer.prototype.retrieveDomainSelectors = function(
var hostname = this.µburi.hostnameFromURI(request.locationURL), var hostname = this.µburi.hostnameFromURI(request.locationURL),
domain = this.µburi.domainFromHostname(hostname) || hostname, domain = this.µburi.domainFromHostname(hostname) || hostname,
pos = domain.indexOf('.'), pos = domain.indexOf('.'),
entity = pos === -1 ? '' : domain.slice(0, pos - domain.length) + '.*'; entity = pos === -1 ? '' : domain.slice(0, pos - domain.length) + '.*',
cacheEntry = this.selectorCache.get(hostname);
// https://github.com/chrisaljoudi/uBlock/issues/587 // https://github.com/chrisaljoudi/uBlock/issues/587
// r.ready will tell the content script the cosmetic filtering engine is // r.ready will tell the content script the cosmetic filtering engine is
@ -1982,9 +1995,10 @@ FilterContainer.prototype.retrieveDomainSelectors = function(
exceptionFilters: [], exceptionFilters: [],
highGenericSimple: '', highGenericSimple: '',
highGenericComplex: '', highGenericComplex: '',
netHide: [], netFilters: '',
proceduralFilters: [], proceduralFilters: [],
scripts: undefined scripts: undefined,
cssRulesInjected: false
}; };
if ( options.noCosmeticFiltering !== true ) { if ( options.noCosmeticFiltering !== true ) {
@ -2038,7 +2052,6 @@ FilterContainer.prototype.retrieveDomainSelectors = function(
bucket.retrieve(hostname, specificSet); bucket.retrieve(hostname, specificSet);
} }
// Cached cosmetic filters: these are always declarative. // Cached cosmetic filters: these are always declarative.
var cacheEntry = this.selectorCache.get(hostname);
if ( cacheEntry !== undefined ) { if ( cacheEntry !== undefined ) {
cacheEntry.retrieve('cosmetic', specificSet); cacheEntry.retrieve('cosmetic', specificSet);
if ( r.noDOMSurveying === false ) { if ( r.noDOMSurveying === false ) {
@ -2107,13 +2120,11 @@ FilterContainer.prototype.retrieveDomainSelectors = function(
// Scriptlet injection. // Scriptlet injection.
r.scripts = this.retrieveUserScripts(domain, hostname); r.scripts = this.retrieveUserScripts(domain, hostname);
// TODO: Is it *really* worth to cache selectors of collapsed resources? if ( cacheEntry ) {
// This adds code complexity and I am having doubts about the var netFilters = [];
// benefits. Investigate. cacheEntry.retrieve('net', netFilters);
// Collapsible blocked resources. r.netFilters = netFilters.join(',\n');
//if ( cacheEntry ) { }
// cacheEntry.retrieve('net', r.netHide);
//}
console.timeEnd('cosmeticFilteringEngine.retrieveDomainSelectors'); console.timeEnd('cosmeticFilteringEngine.retrieveDomainSelectors');

View File

@ -1400,9 +1400,11 @@ var stopPicker = function() {
// https://github.com/gorhill/uBlock/issues/2060 // https://github.com/gorhill/uBlock/issues/2060
if ( vAPI.domFilterer instanceof Object ) { if ( vAPI.domFilterer instanceof Object ) {
vAPI.domFilterer.removeCSSRule(pickerCSSSelector1, pickerCSSDeclaration1); vAPI.userStylesheet.remove(pickerCSS1);
vAPI.domFilterer.removeCSSRule(pickerCSSSelector2, pickerCSSDeclaration2); vAPI.userStylesheet.remove(pickerCSS2);
vAPI.userStylesheet.apply();
} }
vAPI.domFilterer.unexcludeNode(pickerRoot);
window.removeEventListener('scroll', onScrolled, true); window.removeEventListener('scroll', onScrolled, true);
pickerRoot.contentWindow.removeEventListener('keydown', onKeyPressed, true); pickerRoot.contentWindow.removeEventListener('keydown', onKeyPressed, true);
@ -1546,47 +1548,46 @@ var bootstrapPicker = function() {
pickerRoot = document.createElement('iframe'); pickerRoot = document.createElement('iframe');
pickerRoot.id = vAPI.sessionId; pickerRoot.id = vAPI.sessionId;
var pickerCSSSelector1 = '#' + pickerRoot.id; var pickerCSSStyle = [
var pickerCSSDeclaration1 = [ 'background: transparent',
'background: transparent', 'border: 0',
'border: 0', 'border-radius: 0',
'border-radius: 0', 'box-shadow: none',
'box-shadow: none', 'display: block',
'display: block', 'height: 100%',
'height: 100%', 'left: 0',
'left: 0', 'margin: 0',
'margin: 0', 'max-height: none',
'max-height: none', 'max-width: none',
'max-width: none', 'opacity: 1',
'opacity: 1', 'outline: 0',
'outline: 0', 'padding: 0',
'padding: 0', 'position: fixed',
'position: fixed', 'top: 0',
'top: 0', 'visibility: visible',
'visibility: visible', 'width: 100%',
'width: 100%', 'z-index: 2147483647',
'z-index: 2147483647', ''
'' ].join(' !important;');
].join(' !important;'); pickerRoot.style.cssText = pickerCSSStyle;
var pickerCSSSelector2 = '[' + pickerRoot.id + '-clickblind]';
var pickerCSSDeclaration2 = 'pointer-events: none !important;';
var pickerCSS1 = [
pickerRoot.style.cssText = pickerCSSDeclaration1; '#' + pickerRoot.id + ' {',
pickerCSSStyle,
'}'
].join('\n');
var pickerCSS2 = [
'[' + pickerRoot.id + '-clickblind] {',
'pointer-events: none !important;',
'}'
].join('\n');
// https://github.com/gorhill/uBlock/issues/1529 // https://github.com/gorhill/uBlock/issues/1529
// In addition to inline styles, harden the element picker styles by using // In addition to inline styles, harden the element picker styles by using
// dedicated CSS rules. // dedicated CSS rules.
vAPI.domFilterer.addCSSRule( vAPI.userStylesheet.add(pickerCSS1);
pickerCSSSelector1, vAPI.userStylesheet.add(pickerCSS2);
pickerCSSDeclaration1, vAPI.userStylesheet.apply();
{ internal: true }
);
vAPI.domFilterer.addCSSRule(
pickerCSSSelector2,
pickerCSSDeclaration2,
{ internal: true }
);
// https://github.com/gorhill/uBlock/issues/2060 // https://github.com/gorhill/uBlock/issues/2060
vAPI.domFilterer.excludeNode(pickerRoot); vAPI.domFilterer.excludeNode(pickerRoot);