mirror of
https://github.com/gorhill/uBlock.git
synced 2024-10-04 16:47:15 +02:00
fix #3160
This commit is contained in:
parent
6112a68faf
commit
4f7aab695c
@ -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() {
|
||||
this.commitTimer = new vAPI.SafeAnimationFrame(this.commitNow.bind(this));
|
||||
this.domIsReady = document.readyState !== 'loading';
|
||||
this.listeners = [];
|
||||
this.hideNodeId = vAPI.randomToken();
|
||||
this.hideNodeAttr = vAPI.randomToken();
|
||||
this.hideNodeStylesheet = false;
|
||||
this.excludedNodeSet = new WeakSet();
|
||||
this.addedNodes = new Set();
|
||||
@ -48,73 +103,10 @@ vAPI.DOMFilterer = function() {
|
||||
this.specificComplexHide = new Set();
|
||||
this.specificComplexHideAggregated = undefined;
|
||||
this.addedSpecificComplexHide = [];
|
||||
|
||||
this.specificOthers = [];
|
||||
this.genericSimpleHide = 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.hideNodeBatchProcessTimer = undefined;
|
||||
this.hiddenNodeObserver = undefined;
|
||||
@ -135,7 +127,7 @@ vAPI.DOMFilterer.prototype = {
|
||||
commitNow: function() {
|
||||
this.commitTimer.clear();
|
||||
|
||||
if ( this.domIsReady !== true || this.userStylesheet.disabled ) {
|
||||
if ( this.domIsReady !== true || vAPI.userStylesheet.disabled ) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -227,28 +219,31 @@ vAPI.DOMFilterer.prototype = {
|
||||
|
||||
if ( details === undefined ) { details = {}; }
|
||||
|
||||
var isGeneric= details.lazy === true,
|
||||
isSimple = details.type === 'simple',
|
||||
isComplex = details.type === 'complex',
|
||||
selector;
|
||||
|
||||
var selectorsStr = Array.isArray(selectors) ?
|
||||
selectors.join(',\n') :
|
||||
selectors;
|
||||
if ( selectorsStr.length === 0 ) { return; }
|
||||
|
||||
this.userStylesheet.add(
|
||||
selectorsStr +
|
||||
'\n{ ' + declarations + ' }'
|
||||
);
|
||||
vAPI.userStylesheet.add(selectorsStr + '\n{ ' + declarations + ' }');
|
||||
this.commit();
|
||||
|
||||
this.triggerListeners('declarative', selectorsStr);
|
||||
|
||||
if ( this.reHideStyle.test(declarations) === false ) {
|
||||
this.specificOthers.push({
|
||||
selectors: selectorsStr,
|
||||
declarations: declarations
|
||||
});
|
||||
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 ( isSimple ) {
|
||||
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() {
|
||||
this.domIsReady = true;
|
||||
this.addedNodes.clear();
|
||||
@ -391,7 +361,7 @@ vAPI.DOMFilterer.prototype = {
|
||||
},
|
||||
|
||||
hideNodeObserverHandler: function(mutations) {
|
||||
if ( this.userStylesheet.disabled ) { return; }
|
||||
if ( vAPI.userStylesheet.disabled ) { return; }
|
||||
var i = mutations.length,
|
||||
stagedNodes = this.hiddenNodesetToProcess;
|
||||
while ( i-- ) {
|
||||
@ -413,8 +383,8 @@ vAPI.DOMFilterer.prototype = {
|
||||
new MutationObserver(this.hideNodeObserverHandler.bind(this));
|
||||
if ( this.hideNodeStylesheet === false ) {
|
||||
this.hideNodeStylesheet = true;
|
||||
this.userStylesheet.add(
|
||||
'[' + this.hideNodeId + ']\n{ display: none !important; }'
|
||||
vAPI.userStylesheet.add(
|
||||
'[' + this.hideNodeAttr + ']\n{ display: none !important; }'
|
||||
);
|
||||
}
|
||||
},
|
||||
@ -424,12 +394,16 @@ vAPI.DOMFilterer.prototype = {
|
||||
this.unhideNode(node);
|
||||
},
|
||||
|
||||
unexcludeNode: function(node) {
|
||||
this.excludedNodeSet.delete(node);
|
||||
},
|
||||
|
||||
hideNode: function(node) {
|
||||
if ( this.excludedNodeSet.has(node) ) { return; }
|
||||
if ( this.hiddenNodeset.has(node) ) { return; }
|
||||
this.hiddenNodeset.add(node);
|
||||
if ( this.hideNodeExpando === undefined ) { this.hideNodeInit(); }
|
||||
node.setAttribute(this.hideNodeId, '');
|
||||
node.setAttribute(this.hideNodeAttr, '');
|
||||
if ( node[this.hideNodeExpando] === undefined ) {
|
||||
node[this.hideNodeExpando] =
|
||||
node.hasAttribute('style') &&
|
||||
@ -442,7 +416,7 @@ vAPI.DOMFilterer.prototype = {
|
||||
|
||||
unhideNode: function(node) {
|
||||
if ( this.hiddenNodeset.has(node) === false ) { return; }
|
||||
node.removeAttribute(this.hideNodeId);
|
||||
node.removeAttribute(this.hideNodeAttr);
|
||||
this.hiddenNodesetToProcess.delete(node);
|
||||
if ( this.hideNodeExpando === undefined ) { return; }
|
||||
var attr = node[this.hideNodeExpando];
|
||||
@ -469,9 +443,9 @@ vAPI.DOMFilterer.prototype = {
|
||||
},
|
||||
|
||||
toggle: function(state) {
|
||||
this.userStylesheet.toggle(state);
|
||||
var disabled = this.userStylesheet.disabled,
|
||||
nodes = document.querySelectorAll('[' + this.hideNodeId + ']');
|
||||
vAPI.userStylesheet.toggle(state);
|
||||
var disabled = vAPI.userStylesheet.disabled,
|
||||
nodes = document.querySelectorAll('[' + this.hideNodeAttr + ']');
|
||||
for ( var node of nodes ) {
|
||||
if ( disabled ) {
|
||||
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() {
|
||||
return document.querySelectorAll(
|
||||
this.userStylesheet.getAllSelectors().join(',\n')
|
||||
).length;
|
||||
var selectors = this.getAllDeclarativeSelectors_(true);
|
||||
if ( selectors.length === 0 ) { return 0; }
|
||||
return document.querySelectorAll(selectors).length;
|
||||
},
|
||||
|
||||
getAllDeclarativeSelectors: function() {
|
||||
return [].concat(
|
||||
Array.from(this.specificSimpleHide),
|
||||
Array.from(this.specificComplexHide),
|
||||
Array.from(this.genericSimpleHide),
|
||||
Array.from(this.genericComplexHide)
|
||||
).join(',\n');
|
||||
return this.getAllDeclarativeSelectors_();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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() {
|
||||
this.commitTimer = new vAPI.SafeAnimationFrame(this.commitNow.bind(this));
|
||||
this.domIsReady = document.readyState !== 'loading';
|
||||
this.disabled = false;
|
||||
this.listeners = [];
|
||||
this.filterset = new Set();
|
||||
this.hideNodeId = vAPI.randomToken();
|
||||
this.hideNodeStylesheet = false;
|
||||
this.excludedNodeSet = new WeakSet();
|
||||
this.addedCSSRules = [];
|
||||
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
|
||||
});
|
||||
}
|
||||
};
|
||||
this.addedCSSRules = new Set();
|
||||
|
||||
if ( this.domIsReady !== true ) {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
@ -108,30 +76,27 @@ vAPI.DOMFilterer = function() {
|
||||
|
||||
vAPI.DOMFilterer.prototype = {
|
||||
reOnlySelectors: /\n\{[^\n]+/g,
|
||||
|
||||
// Here we will deal with:
|
||||
// - Injecting low priority user styles;
|
||||
// - Notifying listeners about changed filterset.
|
||||
commitNow: function() {
|
||||
this.commitTimer.clear();
|
||||
var i, entry, ruleText;
|
||||
i = this.addedCSSRules.length;
|
||||
while ( i-- ) {
|
||||
entry = this.addedCSSRules[i];
|
||||
if ( entry.lazy !== true || this.domIsReady ) {
|
||||
ruleText = entry.selectors + '\n{ ' + entry.declarations + ' }';
|
||||
this.userStylesheets.add(ruleText);
|
||||
this.addedCSSRules.splice(i, 1);
|
||||
if ( entry.internal ) {
|
||||
this.internalRules.add(ruleText);
|
||||
}
|
||||
var userStylesheet = vAPI.userStylesheet,
|
||||
addedSelectors = [];
|
||||
for ( var entry of this.addedCSSRules ) {
|
||||
if ( this.disabled === false && entry.lazy ) {
|
||||
userStylesheet.add(
|
||||
entry.selectors + '\n{' + entry.declarations + '}'
|
||||
);
|
||||
}
|
||||
addedSelectors.push(entry.selectors);
|
||||
}
|
||||
i = this.removedCSSRules.length;
|
||||
while ( i-- ) {
|
||||
entry = this.removedCSSRules[i];
|
||||
ruleText = entry.selectors + '\n{ ' + entry.declarations + ' }';
|
||||
this.userStylesheets.remove(ruleText);
|
||||
this.internalRules.delete(ruleText);
|
||||
this.addedCSSRules.clear();
|
||||
userStylesheet.apply();
|
||||
if ( addedSelectors.length !== 0 ) {
|
||||
this.triggerListeners('declarative', addedSelectors.join(',\n'));
|
||||
}
|
||||
this.removedCSSRules = [];
|
||||
this.userStylesheets.apply();
|
||||
},
|
||||
|
||||
commit: function(commitNow) {
|
||||
@ -149,25 +114,17 @@ vAPI.DOMFilterer.prototype = {
|
||||
? selectors.join(',\n')
|
||||
: selectors;
|
||||
if ( selectorsStr.length === 0 ) { return; }
|
||||
this.addedCSSRules.push({
|
||||
var entry = {
|
||||
selectors: selectorsStr,
|
||||
declarations,
|
||||
lazy: details && details.lazy === true,
|
||||
lazy: details !== undefined && details.lazy === true,
|
||||
internal: details && details.internal === true
|
||||
});
|
||||
this.commit();
|
||||
this.triggerListeners('declarative', selectorsStr);
|
||||
},
|
||||
|
||||
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.addedCSSRules.add(entry);
|
||||
this.filterset.add(entry);
|
||||
if ( this.disabled === false && entry.lazy !== true ) {
|
||||
vAPI.userStylesheet.add(selectorsStr + '\n{' + declarations + '}');
|
||||
}
|
||||
this.commit();
|
||||
},
|
||||
|
||||
@ -194,6 +151,10 @@ vAPI.DOMFilterer.prototype = {
|
||||
this.unhideNode(node);
|
||||
},
|
||||
|
||||
unexcludeNode: function(node) {
|
||||
this.excludedNodeSet.delete(node);
|
||||
},
|
||||
|
||||
hideNode: function(node) {
|
||||
if ( this.excludedNodeSet.has(node) ) { return; }
|
||||
node.setAttribute(this.hideNodeId, '');
|
||||
@ -212,16 +173,26 @@ vAPI.DOMFilterer.prototype = {
|
||||
},
|
||||
|
||||
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) {
|
||||
let selectors = [];
|
||||
for ( var sheet of this.userStylesheets.current ) {
|
||||
if ( all === false && this.internalRules.has(sheet) ) { continue; }
|
||||
selectors.push(
|
||||
sheet.replace(this.reOnlySelectors, ',').trim().slice(0, -1)
|
||||
);
|
||||
for ( var entry of this.filterset ) {
|
||||
if ( all === false && entry.internal ) { continue; }
|
||||
selectors.push(entry.selectors);
|
||||
}
|
||||
return selectors.join(',\n');
|
||||
},
|
||||
|
@ -774,7 +774,7 @@ vAPI.domCollapser = (function() {
|
||||
iframeLoadEventPatch(target);
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
if ( selectors.length !== 0 ) {
|
||||
messaging.send(
|
||||
'contentscript',
|
||||
@ -786,7 +786,6 @@ vAPI.domCollapser = (function() {
|
||||
}
|
||||
);
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
var send = function() {
|
||||
@ -1292,25 +1291,21 @@ vAPI.domSurveyor = (function() {
|
||||
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;
|
||||
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:
|
||||
// https://github.com/gorhill/uBlock/blob/master/assets/ublock/resources.txt
|
||||
if ( cfeDetails.scripts ) {
|
||||
// Have the injected script tag remove itself when execution completes:
|
||||
// to keep DOM as clean as possible.
|
||||
text = cfeDetails.scripts +
|
||||
var text = cfeDetails.scripts +
|
||||
"\n" +
|
||||
"(function() {\n" +
|
||||
" var c = document.currentScript,\n" +
|
||||
|
@ -408,7 +408,7 @@ SelectorCacheEntry.factory = function() {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// var netSelectorCacheLowWaterMark = 20;
|
||||
var netSelectorCacheLowWaterMark = 20;
|
||||
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' ) {
|
||||
this.addNetOne(selectors, Date.now());
|
||||
} else {
|
||||
@ -470,7 +469,6 @@ SelectorCacheEntry.prototype.addNet = function(/* selectors */) {
|
||||
while ( 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) {
|
||||
this.lastAccessTime = Date.now();
|
||||
var dict = type === 'cosmetic' ? this.cosmetic : this.net;
|
||||
for ( var selector of dict ) {
|
||||
out.add(selector);
|
||||
var iterator = type === 'cosmetic' ? this.cosmetic : this.net.keys();
|
||||
if ( Array.isArray(out) ) {
|
||||
this.retrieveToArray(iterator, out);
|
||||
} else {
|
||||
this.retrieveToSet(iterator, out);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1964,7 +1976,8 @@ FilterContainer.prototype.retrieveDomainSelectors = function(
|
||||
var hostname = this.µburi.hostnameFromURI(request.locationURL),
|
||||
domain = this.µburi.domainFromHostname(hostname) || hostname,
|
||||
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
|
||||
// r.ready will tell the content script the cosmetic filtering engine is
|
||||
@ -1982,9 +1995,10 @@ FilterContainer.prototype.retrieveDomainSelectors = function(
|
||||
exceptionFilters: [],
|
||||
highGenericSimple: '',
|
||||
highGenericComplex: '',
|
||||
netHide: [],
|
||||
netFilters: '',
|
||||
proceduralFilters: [],
|
||||
scripts: undefined
|
||||
scripts: undefined,
|
||||
cssRulesInjected: false
|
||||
};
|
||||
|
||||
if ( options.noCosmeticFiltering !== true ) {
|
||||
@ -2038,7 +2052,6 @@ FilterContainer.prototype.retrieveDomainSelectors = function(
|
||||
bucket.retrieve(hostname, specificSet);
|
||||
}
|
||||
// Cached cosmetic filters: these are always declarative.
|
||||
var cacheEntry = this.selectorCache.get(hostname);
|
||||
if ( cacheEntry !== undefined ) {
|
||||
cacheEntry.retrieve('cosmetic', specificSet);
|
||||
if ( r.noDOMSurveying === false ) {
|
||||
@ -2107,13 +2120,11 @@ FilterContainer.prototype.retrieveDomainSelectors = function(
|
||||
// Scriptlet injection.
|
||||
r.scripts = this.retrieveUserScripts(domain, hostname);
|
||||
|
||||
// TODO: Is it *really* worth to cache selectors of collapsed resources?
|
||||
// This adds code complexity and I am having doubts about the
|
||||
// benefits. Investigate.
|
||||
// Collapsible blocked resources.
|
||||
//if ( cacheEntry ) {
|
||||
// cacheEntry.retrieve('net', r.netHide);
|
||||
//}
|
||||
if ( cacheEntry ) {
|
||||
var netFilters = [];
|
||||
cacheEntry.retrieve('net', netFilters);
|
||||
r.netFilters = netFilters.join(',\n');
|
||||
}
|
||||
|
||||
console.timeEnd('cosmeticFilteringEngine.retrieveDomainSelectors');
|
||||
|
||||
|
@ -1400,9 +1400,11 @@ var stopPicker = function() {
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/2060
|
||||
if ( vAPI.domFilterer instanceof Object ) {
|
||||
vAPI.domFilterer.removeCSSRule(pickerCSSSelector1, pickerCSSDeclaration1);
|
||||
vAPI.domFilterer.removeCSSRule(pickerCSSSelector2, pickerCSSDeclaration2);
|
||||
vAPI.userStylesheet.remove(pickerCSS1);
|
||||
vAPI.userStylesheet.remove(pickerCSS2);
|
||||
vAPI.userStylesheet.apply();
|
||||
}
|
||||
vAPI.domFilterer.unexcludeNode(pickerRoot);
|
||||
|
||||
window.removeEventListener('scroll', onScrolled, true);
|
||||
pickerRoot.contentWindow.removeEventListener('keydown', onKeyPressed, true);
|
||||
@ -1546,47 +1548,46 @@ var bootstrapPicker = function() {
|
||||
pickerRoot = document.createElement('iframe');
|
||||
pickerRoot.id = vAPI.sessionId;
|
||||
|
||||
var pickerCSSSelector1 = '#' + pickerRoot.id;
|
||||
var pickerCSSDeclaration1 = [
|
||||
'background: transparent',
|
||||
'border: 0',
|
||||
'border-radius: 0',
|
||||
'box-shadow: none',
|
||||
'display: block',
|
||||
'height: 100%',
|
||||
'left: 0',
|
||||
'margin: 0',
|
||||
'max-height: none',
|
||||
'max-width: none',
|
||||
'opacity: 1',
|
||||
'outline: 0',
|
||||
'padding: 0',
|
||||
'position: fixed',
|
||||
'top: 0',
|
||||
'visibility: visible',
|
||||
'width: 100%',
|
||||
'z-index: 2147483647',
|
||||
''
|
||||
].join(' !important;');
|
||||
var pickerCSSSelector2 = '[' + pickerRoot.id + '-clickblind]';
|
||||
var pickerCSSDeclaration2 = 'pointer-events: none !important;';
|
||||
var pickerCSSStyle = [
|
||||
'background: transparent',
|
||||
'border: 0',
|
||||
'border-radius: 0',
|
||||
'box-shadow: none',
|
||||
'display: block',
|
||||
'height: 100%',
|
||||
'left: 0',
|
||||
'margin: 0',
|
||||
'max-height: none',
|
||||
'max-width: none',
|
||||
'opacity: 1',
|
||||
'outline: 0',
|
||||
'padding: 0',
|
||||
'position: fixed',
|
||||
'top: 0',
|
||||
'visibility: visible',
|
||||
'width: 100%',
|
||||
'z-index: 2147483647',
|
||||
''
|
||||
].join(' !important;');
|
||||
pickerRoot.style.cssText = pickerCSSStyle;
|
||||
|
||||
|
||||
pickerRoot.style.cssText = pickerCSSDeclaration1;
|
||||
var pickerCSS1 = [
|
||||
'#' + pickerRoot.id + ' {',
|
||||
pickerCSSStyle,
|
||||
'}'
|
||||
].join('\n');
|
||||
var pickerCSS2 = [
|
||||
'[' + pickerRoot.id + '-clickblind] {',
|
||||
'pointer-events: none !important;',
|
||||
'}'
|
||||
].join('\n');
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/1529
|
||||
// In addition to inline styles, harden the element picker styles by using
|
||||
// dedicated CSS rules.
|
||||
vAPI.domFilterer.addCSSRule(
|
||||
pickerCSSSelector1,
|
||||
pickerCSSDeclaration1,
|
||||
{ internal: true }
|
||||
);
|
||||
vAPI.domFilterer.addCSSRule(
|
||||
pickerCSSSelector2,
|
||||
pickerCSSDeclaration2,
|
||||
{ internal: true }
|
||||
);
|
||||
vAPI.userStylesheet.add(pickerCSS1);
|
||||
vAPI.userStylesheet.add(pickerCSS2);
|
||||
vAPI.userStylesheet.apply();
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/2060
|
||||
vAPI.domFilterer.excludeNode(pickerRoot);
|
||||
|
Loading…
Reference in New Issue
Block a user