mirror of https://github.com/gorhill/uBlock.git
Distinguish between priviledge and unprivileged messages
Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/710 Messages from unprivileged ports (i.e. from content scripts) are no longer relayed to message handlers which are to be strictly used to execute privileged code. The last remaining case of unprivileged messages which should be converted into a privileged ones will be taken care of when the following issue is fixed: - https://github.com/gorhill/uBlock/issues/3497
This commit is contained in:
parent
ac56aabd7c
commit
ca9b29c7ec
|
@ -806,72 +806,96 @@ chrome.browserAction.onClicked.addListener(function(tab) {
|
|||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/710
|
||||
// uBO uses only ports to communicate with its auxiliary pages and
|
||||
// content scripts. Whether a message can trigger a privileged operation is
|
||||
// decided based on whether the port from which a message is received is
|
||||
// privileged, which is a status evaluated once, at port connection time.
|
||||
|
||||
vAPI.messaging = {
|
||||
ports: new Map(),
|
||||
listeners: {},
|
||||
listeners: new Map(),
|
||||
defaultHandler: null,
|
||||
PRIVILEGED_URL: vAPI.getURL(''),
|
||||
NOOPFUNC: noopFunc,
|
||||
UNHANDLED: 'vAPI.messaging.notHandled'
|
||||
};
|
||||
UNHANDLED: 'vAPI.messaging.notHandled',
|
||||
|
||||
/******************************************************************************/
|
||||
listen: function(details) {
|
||||
this.listeners.set(details.name, {
|
||||
fn: details.listener,
|
||||
privileged: details.privileged === true
|
||||
});
|
||||
},
|
||||
|
||||
vAPI.messaging.listen = function(listenerName, callback) {
|
||||
this.listeners[listenerName] = callback;
|
||||
};
|
||||
onPortDisconnect: function(port) {
|
||||
this.ports.delete(port.name);
|
||||
},
|
||||
|
||||
/******************************************************************************/
|
||||
onPortConnect: function(port) {
|
||||
port.onDisconnect.addListener(
|
||||
port => this.onPortDisconnect(port)
|
||||
);
|
||||
port.onMessage.addListener(
|
||||
(request, port) => this.onPortMessage(request, port)
|
||||
);
|
||||
this.ports.set(port.name, {
|
||||
port,
|
||||
privileged: port.sender.url.startsWith(this.PRIVILEGED_URL)
|
||||
});
|
||||
},
|
||||
|
||||
vAPI.messaging.onPortMessage = (function() {
|
||||
var messaging = vAPI.messaging;
|
||||
setup: function(defaultHandler) {
|
||||
if ( this.defaultHandler !== null ) { return; }
|
||||
|
||||
// Use a wrapper to avoid closure and to allow reuse.
|
||||
var CallbackWrapper = function(port, request) {
|
||||
this.callback = this.proxy.bind(this); // bind once
|
||||
this.init(port, request);
|
||||
};
|
||||
if ( typeof defaultHandler !== 'function' ) {
|
||||
defaultHandler = function() {
|
||||
return this.UNHANDLED;
|
||||
};
|
||||
}
|
||||
this.defaultHandler = defaultHandler;
|
||||
|
||||
CallbackWrapper.prototype = {
|
||||
init: function(port, request) {
|
||||
this.port = port;
|
||||
this.request = request;
|
||||
return this;
|
||||
},
|
||||
proxy: function(response) {
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/383
|
||||
if ( messaging.ports.has(this.port.name) ) {
|
||||
this.port.postMessage({
|
||||
auxProcessId: this.request.auxProcessId,
|
||||
channelName: this.request.channelName,
|
||||
msg: response !== undefined ? response : null
|
||||
});
|
||||
browser.runtime.onConnect.addListener(
|
||||
port => this.onPortConnect(port)
|
||||
);
|
||||
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1392067
|
||||
// Workaround: manually remove ports matching removed tab.
|
||||
if (
|
||||
vAPI.webextFlavor.soup.has('firefox') &&
|
||||
vAPI.webextFlavor.major < 61
|
||||
) {
|
||||
browser.tabs.onRemoved.addListener(tabId => {
|
||||
for ( const { port } of this.ports.values() ) {
|
||||
const tab = port.sender && port.sender.tab;
|
||||
if ( !tab ) { continue; }
|
||||
if ( tab.id === tabId ) {
|
||||
this.onPortDisconnect(port);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
broadcast: function(message) {
|
||||
const messageWrapper = { broadcast: true, msg: message };
|
||||
for ( const { port } of this.ports.values() ) {
|
||||
try {
|
||||
port.postMessage(messageWrapper);
|
||||
} catch(ex) {
|
||||
this.ports.delete(port.name);
|
||||
}
|
||||
// Mark for reuse
|
||||
this.port = this.request = null;
|
||||
callbackWrapperJunkyard.push(this);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
var callbackWrapperJunkyard = [];
|
||||
|
||||
var callbackWrapperFactory = function(port, request) {
|
||||
var wrapper = callbackWrapperJunkyard.pop();
|
||||
if ( wrapper ) {
|
||||
return wrapper.init(port, request);
|
||||
}
|
||||
return new CallbackWrapper(port, request);
|
||||
};
|
||||
|
||||
var toFramework = function(request, port, callback) {
|
||||
var sender = port && port.sender;
|
||||
onFrameworkMessage: function(request, port, callback) {
|
||||
const sender = port && port.sender;
|
||||
if ( !sender ) { return; }
|
||||
var tabId = sender.tab && sender.tab.id || undefined;
|
||||
var msg = request.msg,
|
||||
toPort;
|
||||
const tabId = sender.tab && sender.tab.id || undefined;
|
||||
const msg = request.msg;
|
||||
switch ( msg.what ) {
|
||||
case 'connectionAccepted':
|
||||
case 'connectionRefused':
|
||||
toPort = messaging.ports.get(msg.fromToken);
|
||||
case 'connectionRefused': {
|
||||
const { port: toPort } = this.ports.get(msg.fromToken);
|
||||
if ( toPort !== undefined ) {
|
||||
msg.tabId = tabId;
|
||||
toPort.postMessage(request);
|
||||
|
@ -880,16 +904,17 @@ vAPI.messaging.onPortMessage = (function() {
|
|||
port.postMessage(request);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'connectionRequested':
|
||||
msg.tabId = tabId;
|
||||
for ( toPort of messaging.ports.values() ) {
|
||||
for ( const { port: toPort } of this.ports.values() ) {
|
||||
toPort.postMessage(request);
|
||||
}
|
||||
break;
|
||||
case 'connectionBroken':
|
||||
case 'connectionCheck':
|
||||
case 'connectionMessage':
|
||||
toPort = messaging.ports.get(
|
||||
case 'connectionMessage': {
|
||||
const { port: toPort } = this.ports.get(
|
||||
port.name === msg.fromToken ? msg.toToken : msg.fromToken
|
||||
);
|
||||
if ( toPort !== undefined ) {
|
||||
|
@ -900,9 +925,10 @@ vAPI.messaging.onPortMessage = (function() {
|
|||
port.postMessage(request);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'userCSS':
|
||||
if ( tabId === undefined ) { break; }
|
||||
var details = {
|
||||
const details = {
|
||||
code: undefined,
|
||||
frameId: sender.frameId,
|
||||
matchAboutBlank: true
|
||||
|
@ -913,25 +939,24 @@ vAPI.messaging.onPortMessage = (function() {
|
|||
if ( msg.add ) {
|
||||
details.runAt = 'document_start';
|
||||
}
|
||||
var cssText;
|
||||
var countdown = 0;
|
||||
var countdownHandler = function() {
|
||||
let countdown = 0;
|
||||
const countdownHandler = function() {
|
||||
void chrome.runtime.lastError;
|
||||
countdown -= 1;
|
||||
if ( countdown === 0 && typeof callback === 'function' ) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
for ( cssText of msg.add ) {
|
||||
for ( const cssText of msg.add ) {
|
||||
countdown += 1;
|
||||
details.code = cssText;
|
||||
chrome.tabs.insertCSS(tabId, details, countdownHandler);
|
||||
browser.tabs.insertCSS(tabId, details, countdownHandler);
|
||||
}
|
||||
if ( typeof chrome.tabs.removeCSS === 'function' ) {
|
||||
for ( cssText of msg.remove ) {
|
||||
for ( const cssText of msg.remove ) {
|
||||
countdown += 1;
|
||||
details.code = cssText;
|
||||
chrome.tabs.removeCSS(tabId, details, countdownHandler);
|
||||
browser.tabs.removeCSS(tabId, details, countdownHandler);
|
||||
}
|
||||
}
|
||||
if ( countdown === 0 && typeof callback === 'function' ) {
|
||||
|
@ -939,100 +964,87 @@ vAPI.messaging.onPortMessage = (function() {
|
|||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1392067
|
||||
// Workaround: manually remove ports matching removed tab.
|
||||
chrome.tabs.onRemoved.addListener(function(tabId) {
|
||||
for ( var port of messaging.ports.values() ) {
|
||||
var tab = port.sender && port.sender.tab;
|
||||
if ( !tab ) { continue; }
|
||||
if ( tab.id === tabId ) {
|
||||
vAPI.messaging.onPortDisconnect(port);
|
||||
}
|
||||
// Use a wrapper to avoid closure and to allow reuse.
|
||||
CallbackWrapper: class {
|
||||
constructor(messaging, port, request) {
|
||||
this.messaging = messaging;
|
||||
this.callback = this.proxy.bind(this); // bind once
|
||||
this.init(port, request);
|
||||
}
|
||||
});
|
||||
init(port, request) {
|
||||
this.port = port;
|
||||
this.request = request;
|
||||
return this;
|
||||
}
|
||||
proxy(response) {
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/383
|
||||
if ( this.messaging.ports.has(this.port.name) ) {
|
||||
this.port.postMessage({
|
||||
auxProcessId: this.request.auxProcessId,
|
||||
channelName: this.request.channelName,
|
||||
msg: response !== undefined ? response : null
|
||||
});
|
||||
}
|
||||
// Store for reuse
|
||||
this.port = this.request = null;
|
||||
this.messaging.callbackWrapperJunkyard.push(this);
|
||||
}
|
||||
},
|
||||
|
||||
return function(request, port) {
|
||||
callbackWrapperJunkyard: [],
|
||||
|
||||
callbackWrapperFactory: function(port, request) {
|
||||
return this.callbackWrapperJunkyard.length !== 0
|
||||
? this.callbackWrapperJunkyard.pop().init(port, request)
|
||||
: new this.CallbackWrapper(this, port, request);
|
||||
},
|
||||
|
||||
onPortMessage: function(request, port) {
|
||||
// prepare response
|
||||
var callback = this.NOOPFUNC;
|
||||
let callback = this.NOOPFUNC;
|
||||
if ( request.auxProcessId !== undefined ) {
|
||||
callback = callbackWrapperFactory(port, request).callback;
|
||||
callback = this.callbackWrapperFactory(port, request).callback;
|
||||
}
|
||||
|
||||
// Content process to main process: framework handler.
|
||||
if ( request.channelName === 'vapi' ) {
|
||||
toFramework(request, port, callback);
|
||||
this.onFrameworkMessage(request, port, callback);
|
||||
return;
|
||||
}
|
||||
|
||||
// Auxiliary process to main process: specific handler
|
||||
var r = this.UNHANDLED,
|
||||
listener = this.listeners[request.channelName];
|
||||
if ( typeof listener === 'function' ) {
|
||||
r = listener(request.msg, port.sender, callback);
|
||||
const fromDetails = this.ports.get(port.name);
|
||||
if ( fromDetails === undefined ) { return; }
|
||||
|
||||
const listenerDetails = this.listeners.get(request.channelName);
|
||||
let r = this.UNHANDLED;
|
||||
if (
|
||||
(listenerDetails !== undefined) &&
|
||||
(listenerDetails.privileged === false || fromDetails.privileged)
|
||||
|
||||
) {
|
||||
r = listenerDetails.fn(request.msg, port.sender, callback);
|
||||
}
|
||||
if ( r !== this.UNHANDLED ) { return; }
|
||||
|
||||
// Auxiliary process to main process: default handler
|
||||
r = this.defaultHandler(request.msg, port.sender, callback);
|
||||
if ( r !== this.UNHANDLED ) { return; }
|
||||
if ( fromDetails.privileged ) {
|
||||
r = this.defaultHandler(request.msg, port.sender, callback);
|
||||
if ( r !== this.UNHANDLED ) { return; }
|
||||
}
|
||||
|
||||
// Auxiliary process to main process: no handler
|
||||
console.error(
|
||||
'vAPI.messaging.onPortMessage > unhandled request: %o',
|
||||
log.info(
|
||||
`vAPI.messaging.onPortMessage > unhandled request: ${JSON.stringify(request.msg)}`,
|
||||
request
|
||||
);
|
||||
|
||||
// Need to callback anyways in case caller expected an answer, or
|
||||
// else there is a memory leak on caller's side
|
||||
callback();
|
||||
}.bind(vAPI.messaging);
|
||||
})();
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.messaging.onPortDisconnect = function(port) {
|
||||
port.onDisconnect.removeListener(this.onPortDisconnect);
|
||||
port.onMessage.removeListener(this.onPortMessage);
|
||||
this.ports.delete(port.name);
|
||||
}.bind(vAPI.messaging);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.messaging.onPortConnect = function(port) {
|
||||
port.onDisconnect.addListener(this.onPortDisconnect);
|
||||
port.onMessage.addListener(this.onPortMessage);
|
||||
this.ports.set(port.name, port);
|
||||
}.bind(vAPI.messaging);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.messaging.setup = function(defaultHandler) {
|
||||
// Already setup?
|
||||
if ( this.defaultHandler !== null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( typeof defaultHandler !== 'function' ) {
|
||||
defaultHandler = function(){ return vAPI.messaging.UNHANDLED; };
|
||||
}
|
||||
this.defaultHandler = defaultHandler;
|
||||
|
||||
chrome.runtime.onConnect.addListener(this.onPortConnect);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.messaging.broadcast = function(message) {
|
||||
const messageWrapper = { broadcast: true, msg: message };
|
||||
for ( const port of this.ports.values() ) {
|
||||
try {
|
||||
port.postMessage(messageWrapper);
|
||||
} catch(ex) {
|
||||
this.ports.delete(port.name);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -1049,8 +1061,7 @@ vAPI.messaging.broadcast = function(message) {
|
|||
|
||||
vAPI.warSecret = (( ) => {
|
||||
const generateSecret = ( ) => {
|
||||
return Math.floor(Math.random() * 982451653 + 982451653).toString(36) +
|
||||
Math.floor(Math.random() * 982451653 + 982451653).toString(36);
|
||||
return Math.floor(Math.random() * 982451653 + 982451653).toString(36);
|
||||
};
|
||||
|
||||
const root = vAPI.getURL('/');
|
||||
|
|
|
@ -43,7 +43,7 @@ vAPI.webextFlavor = {
|
|||
soup: new Set()
|
||||
};
|
||||
|
||||
(function() {
|
||||
(( ) => {
|
||||
const ua = navigator.userAgent;
|
||||
const flavor = vAPI.webextFlavor;
|
||||
const soup = flavor.soup;
|
||||
|
|
|
@ -750,8 +750,8 @@ FilterContainer.prototype.addToSelectorCache = function(details) {
|
|||
/******************************************************************************/
|
||||
|
||||
FilterContainer.prototype.removeFromSelectorCache = function(
|
||||
targetHostname,
|
||||
type
|
||||
targetHostname = '*',
|
||||
type = undefined
|
||||
) {
|
||||
let targetHostnameLength = targetHostname.length;
|
||||
for ( let entry of this.selectorCache ) {
|
||||
|
|
|
@ -24,16 +24,23 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
// Default handler
|
||||
|
||||
(function() {
|
||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/710
|
||||
// Listeners have a name and a "privileged" status.
|
||||
// The nameless default handler is always deemed "privileged".
|
||||
// Messages from privileged ports must never relayed to listeners
|
||||
// which are not privileged.
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// Default handler
|
||||
// priviledged
|
||||
|
||||
{
|
||||
// >>>>> start of local scope
|
||||
|
||||
const µb = µBlock;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const getDomainNames = function(targets) {
|
||||
const µburi = µb.URI;
|
||||
return targets.map(target => {
|
||||
|
@ -44,8 +51,6 @@ const getDomainNames = function(targets) {
|
|||
});
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const onMessage = function(request, sender, callback) {
|
||||
// Async
|
||||
switch ( request.what ) {
|
||||
|
@ -82,8 +87,6 @@ const onMessage = function(request, sender, callback) {
|
|||
break;
|
||||
}
|
||||
|
||||
const tabId = sender && sender.tab ? sender.tab.id : 0;
|
||||
|
||||
// Sync
|
||||
var response;
|
||||
|
||||
|
@ -93,17 +96,13 @@ const onMessage = function(request, sender, callback) {
|
|||
break;
|
||||
|
||||
case 'compileCosmeticFilterSelector':
|
||||
response = µb.staticExtFilteringEngine.compileSelector(request.selector);
|
||||
break;
|
||||
|
||||
case 'cosmeticFiltersInjected':
|
||||
µb.cosmeticFilteringEngine.addToSelectorCache(request);
|
||||
response = µb.staticExtFilteringEngine.compileSelector(
|
||||
request.selector
|
||||
);
|
||||
break;
|
||||
|
||||
case 'createUserFilter':
|
||||
µb.appendUserFilters(request.filters, request);
|
||||
// https://github.com/gorhill/uBlock/issues/1786
|
||||
µb.cosmeticFilteringEngine.removeFromSelectorCache(request.pageDomain);
|
||||
µb.createUserFilters(request);
|
||||
break;
|
||||
|
||||
case 'forceUpdateAssets':
|
||||
|
@ -143,13 +142,6 @@ const onMessage = function(request, sender, callback) {
|
|||
µb.openNewTab(request.details);
|
||||
break;
|
||||
|
||||
case 'mouseClick':
|
||||
µb.mouseEventRegister.tabId = tabId;
|
||||
µb.mouseEventRegister.x = request.x;
|
||||
µb.mouseEventRegister.y = request.y;
|
||||
µb.mouseEventRegister.url = request.url;
|
||||
break;
|
||||
|
||||
case 'reloadTab':
|
||||
if ( vAPI.isBehindTheSceneTabId(request.tabId) === false ) {
|
||||
vAPI.tabs.reload(request.tabId, request.bypassCache === true);
|
||||
|
@ -159,10 +151,6 @@ const onMessage = function(request, sender, callback) {
|
|||
}
|
||||
break;
|
||||
|
||||
case 'scriptletResponse':
|
||||
µb.scriptlets.report(tabId, request.scriptlet, request.response);
|
||||
break;
|
||||
|
||||
case 'setWhitelist':
|
||||
µb.netWhitelist = µb.whitelistFromString(request.whitelist);
|
||||
µb.saveWhitelist();
|
||||
|
@ -185,51 +173,43 @@ const onMessage = function(request, sender, callback) {
|
|||
|
||||
vAPI.messaging.setup(onMessage);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
// <<<<< end of local scope
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// channel: popupPanel
|
||||
// Channel:
|
||||
// popupPanel
|
||||
// privileged
|
||||
|
||||
(function() {
|
||||
{
|
||||
// >>>>> start of local scope
|
||||
|
||||
/******************************************************************************/
|
||||
const µb = µBlock;
|
||||
|
||||
var µb = µBlock;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var getHostnameDict = function(hostnameToCountMap) {
|
||||
var r = Object.create(null),
|
||||
domainEntry,
|
||||
domainFromHostname = µb.URI.domainFromHostname,
|
||||
domain, blockCount, allowCount,
|
||||
hostname, counts;
|
||||
const getHostnameDict = function(hostnameToCountMap) {
|
||||
const r = Object.create(null);
|
||||
const domainFromHostname = µb.URI.domainFromHostname;
|
||||
// Note: destructuring assignment not supported before Chromium 49.
|
||||
for ( var entry of hostnameToCountMap ) {
|
||||
hostname = entry[0];
|
||||
for ( const [ hostname, hnCounts ] of hostnameToCountMap ) {
|
||||
if ( r[hostname] !== undefined ) { continue; }
|
||||
domain = domainFromHostname(hostname) || hostname;
|
||||
counts = hostnameToCountMap.get(domain) || 0;
|
||||
blockCount = counts & 0xFFFF;
|
||||
allowCount = counts >>> 16 & 0xFFFF;
|
||||
const domain = domainFromHostname(hostname) || hostname;
|
||||
const dnCounts = hostnameToCountMap.get(domain) || 0;
|
||||
let blockCount = dnCounts & 0xFFFF;
|
||||
let allowCount = dnCounts >>> 16 & 0xFFFF;
|
||||
if ( r[domain] === undefined ) {
|
||||
domainEntry = r[domain] = {
|
||||
r[domain] = {
|
||||
domain: domain,
|
||||
blockCount: blockCount,
|
||||
allowCount: allowCount,
|
||||
totalBlockCount: blockCount,
|
||||
totalAllowCount: allowCount
|
||||
};
|
||||
} else {
|
||||
domainEntry = r[domain];
|
||||
}
|
||||
counts = entry[1];
|
||||
blockCount = counts & 0xFFFF;
|
||||
allowCount = counts >>> 16 & 0xFFFF;
|
||||
const domainEntry = r[domain];
|
||||
blockCount = hnCounts & 0xFFFF;
|
||||
allowCount = hnCounts >>> 16 & 0xFFFF;
|
||||
domainEntry.totalBlockCount += blockCount;
|
||||
domainEntry.totalAllowCount += allowCount;
|
||||
if ( hostname === domain ) { continue; }
|
||||
|
@ -244,9 +224,7 @@ var getHostnameDict = function(hostnameToCountMap) {
|
|||
return r;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var getFirewallRules = function(srcHostname, desHostnames) {
|
||||
const getFirewallRules = function(srcHostname, desHostnames) {
|
||||
var r = {};
|
||||
var df = µb.sessionFirewall;
|
||||
r['/ * *'] = df.lookupRuleData('*', '*', '*');
|
||||
|
@ -256,32 +234,38 @@ var getFirewallRules = function(srcHostname, desHostnames) {
|
|||
r['/ * 1p-script'] = df.lookupRuleData('*', '*', '1p-script');
|
||||
r['/ * 3p-script'] = df.lookupRuleData('*', '*', '3p-script');
|
||||
r['/ * 3p-frame'] = df.lookupRuleData('*', '*', '3p-frame');
|
||||
if ( typeof srcHostname !== 'string' ) {
|
||||
return r;
|
||||
}
|
||||
if ( typeof srcHostname !== 'string' ) { return r; }
|
||||
|
||||
r['. * *'] = df.lookupRuleData(srcHostname, '*', '*');
|
||||
r['. * image'] = df.lookupRuleData(srcHostname, '*', 'image');
|
||||
r['. * 3p'] = df.lookupRuleData(srcHostname, '*', '3p');
|
||||
r['. * inline-script'] = df.lookupRuleData(srcHostname, '*', 'inline-script');
|
||||
r['. * inline-script'] = df.lookupRuleData(srcHostname,
|
||||
'*',
|
||||
'inline-script'
|
||||
);
|
||||
r['. * 1p-script'] = df.lookupRuleData(srcHostname, '*', '1p-script');
|
||||
r['. * 3p-script'] = df.lookupRuleData(srcHostname, '*', '3p-script');
|
||||
r['. * 3p-frame'] = df.lookupRuleData(srcHostname, '*', '3p-frame');
|
||||
|
||||
for ( var desHostname in desHostnames ) {
|
||||
r['/ ' + desHostname + ' *'] = df.lookupRuleData('*', desHostname, '*');
|
||||
r['. ' + desHostname + ' *'] = df.lookupRuleData(srcHostname, desHostname, '*');
|
||||
for ( const desHostname in desHostnames ) {
|
||||
r[`/ ${desHostname} *`] = df.lookupRuleData(
|
||||
'*',
|
||||
desHostname,
|
||||
'*'
|
||||
);
|
||||
r[`. ${desHostname} *`] = df.lookupRuleData(
|
||||
srcHostname,
|
||||
desHostname,
|
||||
'*'
|
||||
);
|
||||
}
|
||||
return r;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var popupDataFromTabId = function(tabId, tabTitle) {
|
||||
let tabContext = µb.tabContextManager.mustLookup(tabId),
|
||||
rootHostname = tabContext.rootHostname;
|
||||
|
||||
let r = {
|
||||
const popupDataFromTabId = function(tabId, tabTitle) {
|
||||
const tabContext = µb.tabContextManager.mustLookup(tabId);
|
||||
const rootHostname = tabContext.rootHostname;
|
||||
const r = {
|
||||
advancedUserEnabled: µb.userSettings.advancedUserEnabled,
|
||||
appName: vAPI.app.name,
|
||||
appVersion: vAPI.app.version,
|
||||
|
@ -305,13 +289,13 @@ var popupDataFromTabId = function(tabId, tabTitle) {
|
|||
tooltipsDisabled: µb.userSettings.tooltipsDisabled
|
||||
};
|
||||
|
||||
let pageStore = µb.pageStoreFromTabId(tabId);
|
||||
const pageStore = µb.pageStoreFromTabId(tabId);
|
||||
if ( pageStore ) {
|
||||
// https://github.com/gorhill/uBlock/issues/2105
|
||||
// Be sure to always include the current page's hostname -- it might
|
||||
// not be present when the page itself is pulled from the browser's
|
||||
// short-term memory cache. This needs to be done before calling
|
||||
// getHostnameDict().
|
||||
// Be sure to always include the current page's hostname -- it
|
||||
// might not be present when the page itself is pulled from the
|
||||
// browser's short-term memory cache. This needs to be done
|
||||
// before calling getHostnameDict().
|
||||
if (
|
||||
pageStore.hostnameToCountMap.has(rootHostname) === false &&
|
||||
µb.URI.isNetworkURI(tabContext.rawURL)
|
||||
|
@ -325,14 +309,29 @@ var popupDataFromTabId = function(tabId, tabTitle) {
|
|||
r.contentLastModified = pageStore.contentLastModified;
|
||||
r.firewallRules = getFirewallRules(rootHostname, r.hostnameDict);
|
||||
r.canElementPicker = µb.URI.isNetworkURI(r.rawURL);
|
||||
r.noPopups = µb.sessionSwitches.evaluateZ('no-popups', rootHostname);
|
||||
r.noPopups = µb.sessionSwitches.evaluateZ(
|
||||
'no-popups',
|
||||
rootHostname
|
||||
);
|
||||
r.popupBlockedCount = pageStore.popupBlockedCount;
|
||||
r.noCosmeticFiltering = µb.sessionSwitches.evaluateZ('no-cosmetic-filtering', rootHostname);
|
||||
r.noLargeMedia = µb.sessionSwitches.evaluateZ('no-large-media', rootHostname);
|
||||
r.noCosmeticFiltering = µb.sessionSwitches.evaluateZ(
|
||||
'no-cosmetic-filtering',
|
||||
rootHostname
|
||||
);
|
||||
r.noLargeMedia = µb.sessionSwitches.evaluateZ(
|
||||
'no-large-media',
|
||||
rootHostname
|
||||
);
|
||||
r.largeMediaCount = pageStore.largeMediaCount;
|
||||
r.noRemoteFonts = µb.sessionSwitches.evaluateZ('no-remote-fonts', rootHostname);
|
||||
r.noRemoteFonts = µb.sessionSwitches.evaluateZ(
|
||||
'no-remote-fonts',
|
||||
rootHostname
|
||||
);
|
||||
r.remoteFontCount = pageStore.remoteFontCount;
|
||||
r.noScripting = µb.sessionSwitches.evaluateZ('no-scripting', rootHostname);
|
||||
r.noScripting = µb.sessionSwitches.evaluateZ(
|
||||
'no-scripting',
|
||||
rootHostname
|
||||
);
|
||||
} else {
|
||||
r.hostnameDict = {};
|
||||
r.firewallRules = getFirewallRules();
|
||||
|
@ -352,9 +351,7 @@ var popupDataFromTabId = function(tabId, tabTitle) {
|
|||
return r;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var popupDataFromRequest = function(request, callback) {
|
||||
const popupDataFromRequest = function(request, callback) {
|
||||
if ( request.tabId ) {
|
||||
callback(popupDataFromTabId(request.tabId, ''));
|
||||
return;
|
||||
|
@ -372,10 +369,8 @@ var popupDataFromRequest = function(request, callback) {
|
|||
});
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var onMessage = function(request, sender, callback) {
|
||||
var pageStore;
|
||||
const onMessage = function(request, sender, callback) {
|
||||
let pageStore;
|
||||
|
||||
// Async
|
||||
switch ( request.what ) {
|
||||
|
@ -388,7 +383,7 @@ var onMessage = function(request, sender, callback) {
|
|||
}
|
||||
|
||||
// Sync
|
||||
var response;
|
||||
let response;
|
||||
|
||||
switch ( request.what ) {
|
||||
case 'getPopupLazyData':
|
||||
|
@ -462,7 +457,11 @@ var onMessage = function(request, sender, callback) {
|
|||
case 'toggleNetFiltering':
|
||||
pageStore = µb.pageStoreFromTabId(request.tabId);
|
||||
if ( pageStore ) {
|
||||
pageStore.toggleNetFilteringSwitch(request.url, request.scope, request.state);
|
||||
pageStore.toggleNetFilteringSwitch(
|
||||
request.url,
|
||||
request.scope,
|
||||
request.state
|
||||
);
|
||||
µb.updateToolbarIcon(request.tabId, 0b111);
|
||||
}
|
||||
break;
|
||||
|
@ -474,22 +473,28 @@ var onMessage = function(request, sender, callback) {
|
|||
callback(response);
|
||||
};
|
||||
|
||||
vAPI.messaging.listen('popupPanel', onMessage);
|
||||
vAPI.messaging.listen({
|
||||
name: 'popupPanel',
|
||||
listener: onMessage,
|
||||
privileged: true,
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
// <<<<< end of local scope
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// channel: contentscript
|
||||
// Channel:
|
||||
// contentscript
|
||||
// unprivileged
|
||||
|
||||
(function() {
|
||||
{
|
||||
// >>>>> start of local scope
|
||||
|
||||
/******************************************************************************/
|
||||
const µb = µBlock;
|
||||
|
||||
var onMessage = function(request, sender, callback) {
|
||||
const onMessage = function(request, sender, callback) {
|
||||
// Async
|
||||
switch ( request.what ) {
|
||||
default:
|
||||
|
@ -497,7 +502,6 @@ var onMessage = function(request, sender, callback) {
|
|||
}
|
||||
|
||||
// Sync
|
||||
const µb = µBlock;
|
||||
let response,
|
||||
tabId, frameId,
|
||||
pageStore = null;
|
||||
|
@ -509,6 +513,10 @@ var onMessage = function(request, sender, callback) {
|
|||
}
|
||||
|
||||
switch ( request.what ) {
|
||||
case 'cosmeticFiltersInjected':
|
||||
µb.cosmeticFilteringEngine.addToSelectorCache(request);
|
||||
break;
|
||||
|
||||
case 'getCollapsibleBlockedRequests':
|
||||
response = {
|
||||
id: request.id,
|
||||
|
@ -525,6 +533,13 @@ var onMessage = function(request, sender, callback) {
|
|||
}
|
||||
break;
|
||||
|
||||
case 'mouseClick':
|
||||
µb.mouseEventRegister.tabId = tabId;
|
||||
µb.mouseEventRegister.x = request.x;
|
||||
µb.mouseEventRegister.y = request.y;
|
||||
µb.mouseEventRegister.url = request.url;
|
||||
break;
|
||||
|
||||
case 'shouldRenderNoscriptTags':
|
||||
if ( pageStore === null ) { break; }
|
||||
const fctxt = µb.filteringContext.fromTabId(tabId);
|
||||
|
@ -604,20 +619,23 @@ var onMessage = function(request, sender, callback) {
|
|||
callback(response);
|
||||
};
|
||||
|
||||
vAPI.messaging.listen('contentscript', onMessage);
|
||||
vAPI.messaging.listen({
|
||||
name: 'contentscript',
|
||||
listener: onMessage,
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
// <<<<< end of local scope
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// channel: elementPicker
|
||||
// Channel:
|
||||
// elementPicker
|
||||
// unprivileged
|
||||
|
||||
(function() {
|
||||
|
||||
/******************************************************************************/
|
||||
{
|
||||
// >>>>> start of local scope
|
||||
|
||||
const onMessage = function(request, sender, callback) {
|
||||
const µb = µBlock;
|
||||
|
@ -669,6 +687,12 @@ const onMessage = function(request, sender, callback) {
|
|||
let response;
|
||||
|
||||
switch ( request.what ) {
|
||||
// https://github.com/gorhill/uBlock/issues/3497
|
||||
// This needs to be removed once issue is fixed.
|
||||
case 'createUserFilter':
|
||||
µb.createUserFilters(request);
|
||||
break;
|
||||
|
||||
case 'elementPickerEprom':
|
||||
µb.epickerEprom = request;
|
||||
break;
|
||||
|
@ -680,22 +704,25 @@ const onMessage = function(request, sender, callback) {
|
|||
callback(response);
|
||||
};
|
||||
|
||||
vAPI.messaging.listen('elementPicker', onMessage);
|
||||
vAPI.messaging.listen({
|
||||
name: 'elementPicker',
|
||||
listener: onMessage,
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
// <<<<< end of local scope
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// channel: cloudWidget
|
||||
// Channel:
|
||||
// cloudWidget
|
||||
// privileged
|
||||
|
||||
(function() {
|
||||
{
|
||||
// >>>>> start of local scope
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var onMessage = function(request, sender, callback) {
|
||||
const onMessage = function(request, sender, callback) {
|
||||
// Cloud storage support is optional.
|
||||
if ( µBlock.cloudStorageSupported !== true ) {
|
||||
callback();
|
||||
|
@ -726,7 +753,7 @@ var onMessage = function(request, sender, callback) {
|
|||
}
|
||||
|
||||
// Sync
|
||||
var response;
|
||||
let response;
|
||||
|
||||
switch ( request.what ) {
|
||||
// For when cloud storage is disabled.
|
||||
|
@ -742,27 +769,28 @@ var onMessage = function(request, sender, callback) {
|
|||
callback(response);
|
||||
};
|
||||
|
||||
vAPI.messaging.listen('cloudWidget', onMessage);
|
||||
vAPI.messaging.listen({
|
||||
name: 'cloudWidget',
|
||||
listener: onMessage,
|
||||
privileged: true,
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
// <<<<< end of local scope
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// channel: dashboard
|
||||
// Channel:
|
||||
// dashboard
|
||||
// privileged
|
||||
|
||||
(function() {
|
||||
|
||||
/******************************************************************************/
|
||||
{
|
||||
// >>>>> start of local scope
|
||||
|
||||
const µb = µBlock;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Settings
|
||||
|
||||
const getLocalData = function(callback) {
|
||||
const onStorageInfoReady = function(bytesInUse) {
|
||||
const o = µb.restoreBackupSettings;
|
||||
|
@ -874,7 +902,6 @@ const restoreUserData = function(request) {
|
|||
|
||||
// Remove all stored data but keep global counts, people can become
|
||||
// quite attached to numbers
|
||||
|
||||
const resetUserData = function() {
|
||||
let count = 3;
|
||||
const countdown = ( ) => {
|
||||
|
@ -889,10 +916,7 @@ const resetUserData = function() {
|
|||
vAPI.localStorage.removeItem('immediateHiddenSettings');
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// 3rd-party filters
|
||||
|
||||
const prepListEntries = function(entries) {
|
||||
const µburi = µb.URI;
|
||||
for ( const k in entries ) {
|
||||
|
@ -935,10 +959,7 @@ const getLists = function(callback) {
|
|||
µb.getAvailableLists(onLists);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// My rules
|
||||
|
||||
const getRules = function() {
|
||||
return {
|
||||
permanentRules:
|
||||
|
@ -1001,10 +1022,7 @@ const modifyRuleset = function(details) {
|
|||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Shortcuts pane
|
||||
|
||||
const getShortcuts = function(callback) {
|
||||
if ( µb.canUseShortcuts === false ) {
|
||||
return callback([]);
|
||||
|
@ -1038,8 +1056,6 @@ const setShortcut = function(details) {
|
|||
vAPI.storage.set({ commandShortcuts: Array.from(µb.commandShortcuts) });
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const onMessage = function(request, sender, callback) {
|
||||
// Async
|
||||
switch ( request.what ) {
|
||||
|
@ -1124,26 +1140,28 @@ const onMessage = function(request, sender, callback) {
|
|||
callback(response);
|
||||
};
|
||||
|
||||
vAPI.messaging.listen('dashboard', onMessage);
|
||||
vAPI.messaging.listen({
|
||||
name: 'dashboard',
|
||||
listener: onMessage,
|
||||
privileged: true,
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
// <<<<< end of local scope
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// channel: loggerUI
|
||||
// Channel:
|
||||
// loggerUI
|
||||
// privileged
|
||||
|
||||
(function() {
|
||||
|
||||
/******************************************************************************/
|
||||
{
|
||||
// >>>>> start of local scope
|
||||
|
||||
const µb = µBlock;
|
||||
const extensionOriginURL = vAPI.getURL('');
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const getLoggerData = function(details, activeTabId, callback) {
|
||||
const response = {
|
||||
colorBlind: µb.userSettings.colorBlindFriendly,
|
||||
|
@ -1195,8 +1213,6 @@ const getLoggerData = function(details, activeTabId, callback) {
|
|||
callback(response);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const getURLFilteringData = function(details) {
|
||||
const colors = {};
|
||||
const response = {
|
||||
|
@ -1229,8 +1245,6 @@ const getURLFilteringData = function(details) {
|
|||
return response;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const onMessage = function(request, sender, callback) {
|
||||
// Async
|
||||
switch ( request.what ) {
|
||||
|
@ -1288,20 +1302,24 @@ const onMessage = function(request, sender, callback) {
|
|||
callback(response);
|
||||
};
|
||||
|
||||
vAPI.messaging.listen('loggerUI', onMessage);
|
||||
vAPI.messaging.listen({
|
||||
name: 'loggerUI',
|
||||
listener: onMessage,
|
||||
privileged: true,
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
// <<<<< end of local scope
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// channel: documentBlocked
|
||||
// Channel:
|
||||
// documentBlocked
|
||||
// privileged
|
||||
|
||||
(( ) => {
|
||||
|
||||
/******************************************************************************/
|
||||
{
|
||||
// >>>>> start of local scope
|
||||
|
||||
const onMessage = function(request, sender, callback) {
|
||||
const tabId = sender && sender.tab ? sender.tab.id : 0;
|
||||
|
@ -1331,26 +1349,28 @@ const onMessage = function(request, sender, callback) {
|
|||
callback(response);
|
||||
};
|
||||
|
||||
vAPI.messaging.listen('documentBlocked', onMessage);
|
||||
vAPI.messaging.listen({
|
||||
name: 'documentBlocked',
|
||||
listener: onMessage,
|
||||
privileged: true,
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
// <<<<< end of local scope
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// channel: scriptlets
|
||||
// Channel:
|
||||
// scriptlets
|
||||
// unprivileged
|
||||
|
||||
(function() {
|
||||
|
||||
/******************************************************************************/
|
||||
{
|
||||
// >>>>> start of local scope
|
||||
|
||||
const µb = µBlock;
|
||||
const broadcastTimers = new Map();
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const domSurveyFinalReport = function(tabId) {
|
||||
broadcastTimers.delete(tabId + '-domSurveyReport');
|
||||
|
||||
|
@ -1365,8 +1385,6 @@ const domSurveyFinalReport = function(tabId) {
|
|||
});
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const logCosmeticFilters = function(tabId, details) {
|
||||
if ( µb.logger.enabled === false ) { return; }
|
||||
|
||||
|
@ -1384,8 +1402,6 @@ const logCosmeticFilters = function(tabId, details) {
|
|||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const logCSPViolations = function(pageStore, request) {
|
||||
if ( µb.logger.enabled === false || pageStore === null ) {
|
||||
return false;
|
||||
|
@ -1475,8 +1491,6 @@ logCSPViolations.policyDirectiveToTypeMap = new Map([
|
|||
[ 'style-src-elem', 'stylesheet' ],
|
||||
]);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const onMessage = function(request, sender, callback) {
|
||||
const tabId = sender && sender.tab ? sender.tab.id : 0;
|
||||
const pageStore = µb.pageStoreFromTabId(tabId);
|
||||
|
@ -1491,6 +1505,10 @@ const onMessage = function(request, sender, callback) {
|
|||
let response;
|
||||
|
||||
switch ( request.what ) {
|
||||
case 'applyFilterListSelection':
|
||||
response = µb.applyFilterListSelection(request);
|
||||
break;
|
||||
|
||||
case 'domSurveyTransientReport':
|
||||
if ( pageStore !== null ) {
|
||||
if ( request.filteredElementCount ) {
|
||||
|
@ -1499,11 +1517,11 @@ const onMessage = function(request, sender, callback) {
|
|||
if ( request.scriptCount ) {
|
||||
pageStore.scriptCount += request.scriptCount;
|
||||
}
|
||||
let broadcastKey = tabId + '-domSurveyReport';
|
||||
const broadcastKey = `${tabId}-domSurveyReport`;
|
||||
if ( broadcastTimers.has(broadcastKey) === false ) {
|
||||
broadcastTimers.set(broadcastKey, vAPI.setTimeout(
|
||||
( ) => { domSurveyFinalReport(tabId); },
|
||||
53
|
||||
103
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -1526,6 +1544,10 @@ const onMessage = function(request, sender, callback) {
|
|||
logCosmeticFilters(tabId, request);
|
||||
break;
|
||||
|
||||
case 'reloadAllFilters':
|
||||
µb.loadFilterLists();
|
||||
return;
|
||||
|
||||
case 'securityPolicyViolation':
|
||||
response = logCSPViolations(pageStore, request);
|
||||
break;
|
||||
|
@ -1549,11 +1571,13 @@ const onMessage = function(request, sender, callback) {
|
|||
callback(response);
|
||||
};
|
||||
|
||||
vAPI.messaging.listen('scriptlets', onMessage);
|
||||
vAPI.messaging.listen({
|
||||
name: 'scriptlets',
|
||||
listener: onMessage,
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
// <<<<< end of local scope
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2015-2018 Raymond Hill
|
||||
Copyright (C) 2015-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -23,7 +23,7 @@
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
(function() {
|
||||
(( ) => {
|
||||
if ( typeof vAPI !== 'object' ) { return; }
|
||||
|
||||
// https://github.com/gorhill/httpswitchboard/issues/25
|
||||
|
@ -47,7 +47,7 @@
|
|||
inlineScriptCount = 1;
|
||||
}
|
||||
|
||||
let scriptTags = document.querySelectorAll('script[src]');
|
||||
const scriptTags = document.querySelectorAll('script[src]');
|
||||
|
||||
let filteredElementCount = 0;
|
||||
if ( vAPI.domFilterer ) {
|
||||
|
@ -58,7 +58,6 @@
|
|||
'scriptlets',
|
||||
{
|
||||
what: 'domSurveyTransientReport',
|
||||
pageURL: window.location.href,
|
||||
filteredElementCount: filteredElementCount,
|
||||
scriptCount: inlineScriptCount + scriptTags.length,
|
||||
}
|
||||
|
|
|
@ -422,8 +422,6 @@
|
|||
return this.assets.get(this.userFiltersPath, callback);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
µBlock.appendUserFilters = function(filters, options) {
|
||||
filters = filters.trim();
|
||||
if ( filters.length === 0 ) { return; }
|
||||
|
@ -500,6 +498,12 @@
|
|||
this.loadUserFilters(onLoaded);
|
||||
};
|
||||
|
||||
µBlock.createUserFilters = function(details) {
|
||||
this.appendUserFilters(details.filters, details);
|
||||
// https://github.com/gorhill/uBlock/issues/1786
|
||||
this.cosmeticFilteringEngine.removeFromSelectorCache(details.pageDomain);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
µBlock.autoSelectRegionalFilterLists = function(lists) {
|
||||
|
|
Loading…
Reference in New Issue