diff --git a/platform/chromium/vapi-background.js b/platform/chromium/vapi-background.js index 0036ed518..54d70491e 100644 --- a/platform/chromium/vapi-background.js +++ b/platform/chromium/vapi-background.js @@ -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('/'); diff --git a/platform/chromium/vapi-common.js b/platform/chromium/vapi-common.js index 0454086d3..0184bc94f 100644 --- a/platform/chromium/vapi-common.js +++ b/platform/chromium/vapi-common.js @@ -43,7 +43,7 @@ vAPI.webextFlavor = { soup: new Set() }; -(function() { +(( ) => { const ua = navigator.userAgent; const flavor = vAPI.webextFlavor; const soup = flavor.soup; diff --git a/src/js/cosmetic-filtering.js b/src/js/cosmetic-filtering.js index 393b814c1..a4f044ef4 100644 --- a/src/js/cosmetic-filtering.js +++ b/src/js/cosmetic-filtering.js @@ -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 ) { diff --git a/src/js/messaging.js b/src/js/messaging.js index bc79b36dd..e2da76682 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -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 +} /******************************************************************************/ diff --git a/src/js/scriptlets/dom-survey.js b/src/js/scriptlets/dom-survey.js index b00306807..b31778a98 100644 --- a/src/js/scriptlets/dom-survey.js +++ b/src/js/scriptlets/dom-survey.js @@ -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, } diff --git a/src/js/storage.js b/src/js/storage.js index 2d1619b77..f9af48ebc 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -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) {