From dec0b80a7214ae2296bbe74654617c14fb48738c Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sun, 17 Dec 2017 08:09:47 -0500 Subject: [PATCH] fix #2877 --- src/js/background.js | 2 +- src/js/cosmetic-filtering.js | 108 ++++++++++++++++++++--------------- src/js/messaging.js | 11 +++- 3 files changed, 71 insertions(+), 50 deletions(-) diff --git a/src/js/background.js b/src/js/background.js index a60e2ea05..c1a85de06 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -121,7 +121,7 @@ var µBlock = (function() { // jshint ignore:line // read-only systemSettings: { compiledMagic: 'vrgorlgelgws', - selfieMagic: 'vrgorlgelgws' + selfieMagic: 'pxpclstriajk' }, restoreBackupSettings: { diff --git a/src/js/cosmetic-filtering.js b/src/js/cosmetic-filtering.js index 9baf3a5ee..502df46d9 100644 --- a/src/js/cosmetic-filtering.js +++ b/src/js/cosmetic-filtering.js @@ -673,6 +673,7 @@ var FilterContainer = function() { this.setRegister0 = new Set(); this.setRegister1 = new Set(); this.setRegister2 = new Set(); + this.mapRegister0 = new Map(); this.reset(); }; @@ -722,7 +723,6 @@ FilterContainer.prototype.reset = function() { this.scriptTagFilters = {}; this.scriptTagFilterCount = 0; this.userScripts.clear(); - this.userScriptCount = 0; }; /******************************************************************************/ @@ -1603,8 +1603,12 @@ FilterContainer.prototype.retrieveScriptTagRegex = function(domain, hostname) { // userScripts{hash} => FilterHostname | FilterBucket -FilterContainer.prototype.createUserScriptRule = function(hash, hostname, selector) { - var filter = new FilterHostname(selector, hostname); +FilterContainer.prototype.createUserScriptRule = function( + hash, + hostname, + selector +) { + var filter = new FilterHostname(selector.slice(14, -1).trim(), hostname); var bucket = this.userScripts.get(hash); if ( bucket === undefined ) { this.userScripts.set(hash, filter); @@ -1613,7 +1617,6 @@ FilterContainer.prototype.createUserScriptRule = function(hash, hostname, select } else { this.userScripts.set(hash, new FilterBucket(bucket, filter)); } - this.userScriptCount += 1; }; /******************************************************************************/ @@ -1625,29 +1628,34 @@ FilterContainer.prototype.createUserScriptRule = function(hash, hostname, select // ^ ^ // 14 -1 -FilterContainer.prototype.retrieveUserScripts = function(domain, hostname) { - if ( this.userScriptCount === 0 ) { return; } +FilterContainer.prototype.retrieveUserScripts = function( + domain, + hostname, + details +) { + if ( this.userScripts.size === 0 ) { return; } if ( µb.hiddenSettings.ignoreScriptInjectFilters === true ) { return; } var reng = µb.redirectEngine; if ( !reng ) { return; } - var out = [], - scripts = new Map(), + this.mapRegister0.clear(); + + var toInject = this.mapRegister0, pos = domain.indexOf('.'), entity = pos !== -1 ? domain.slice(0, pos) + '.*' : ''; // Implicit var hn = hostname; for (;;) { - this._lookupUserScript(scripts, hn + '.js', reng, out); + this._lookupUserScript(hn + '.js', reng, toInject); if ( hn === domain ) { break; } pos = hn.indexOf('.'); if ( pos === -1 ) { break; } hn = hn.slice(pos + 1); } if ( entity !== '' ) { - this._lookupUserScript(scripts, entity + '.js', reng, out); + this._lookupUserScript(entity + '.js', reng, toInject); } // Explicit (hash is domain). @@ -1660,12 +1668,10 @@ FilterContainer.prototype.retrieveUserScripts = function(domain, hostname) { bucket.retrieve(entity, selectors); } for ( var selector of selectors ) { - this._lookupUserScript(scripts, selector.slice(14, -1).trim(), reng, out); + this._lookupUserScript(selector, reng, toInject); } - if ( out.length === 0 ) { - return; - } + if ( toInject.size === 0 ) { return; } // https://github.com/gorhill/uBlock/issues/2835 // Do not inject scriptlets if the site is under an `allow` rule. @@ -1678,26 +1684,43 @@ FilterContainer.prototype.retrieveUserScripts = function(domain, hostname) { // Exceptions should be rare, so we check for exception only if there are // scriptlets returned. - var exceptions = new Set(), - j, token; + var exceptions = new Set(); if ( (bucket = this.userScripts.get('!' + domain)) ) { bucket.retrieve(hostname, exceptions); } if ( entity !== '' && (bucket = this.userScripts.get('!' + entity)) ) { bucket.retrieve(hostname, exceptions); } - for ( var exception of exceptions ) { - token = exception.slice(14, -1); - if ( (j = scripts.get(token)) !== undefined ) { - out[j] = '// User script "' + token + '" excepted.\n'; + + // Return an array of scriptlets, and log results if needed. + var out = [], + logger = µb.logger.isEnabled() ? µb.logger : null, + isException; + + for ( var entry of toInject ) { + if ( (isException = exceptions.has(entry[0])) === false ) { + out.push(entry[1]); } + if ( logger === null ) { continue; } + logger.writeOne( + details.tabId, + 'cosmetic', + { + source: 'cosmetic', + raw: (isException ? '#@#' : '##') + 'script:inject(' + entry[0] + ')' + }, + 'dom', + details.locationURL, + null, + hostname + ); } return out.join('\n'); }; -FilterContainer.prototype._lookupUserScript = function(dict, raw, reng, out) { - if ( dict.has(raw) ) { return; } +FilterContainer.prototype._lookupUserScript = function(raw, reng, toInject) { + if ( toInject.has(raw) ) { return; } var token, args, pos = raw.indexOf(','); if ( pos === -1 ) { @@ -1712,8 +1735,7 @@ FilterContainer.prototype._lookupUserScript = function(dict, raw, reng, out) { content = this._fillupUserScript(content, args); if ( !content ) { return; } } - dict.set(raw, out.length); - out.push(content); + toInject.set(raw, content); }; // Fill template placeholders. Return falsy if: @@ -1762,8 +1784,7 @@ FilterContainer.prototype.toSelfie = function() { genericDonthideArray: µb.arrayFrom(this.genericDonthideSet), scriptTagFilters: this.scriptTagFilters, scriptTagFilterCount: this.scriptTagFilterCount, - userScripts: selfieFromMap(this.userScripts), - userScriptCount: this.userScriptCount + userScripts: selfieFromMap(this.userScripts) }; }; @@ -1798,7 +1819,6 @@ FilterContainer.prototype.fromSelfie = function(selfie) { this.scriptTagFilters = selfie.scriptTagFilters; this.scriptTagFilterCount = selfie.scriptTagFilterCount; this.userScripts = mapFromSelfie(selfie.userScripts); - this.userScriptCount = selfie.userScriptCount; this.frozen = true; }; @@ -1911,10 +1931,7 @@ FilterContainer.prototype.randomAlphaToken = function() { /******************************************************************************/ -FilterContainer.prototype.retrieveGenericSelectors = function( - request, - sender -) { +FilterContainer.prototype.retrieveGenericSelectors = function(request) { if ( this.acceptedCount === 0 ) { return; } if ( !request.ids && !request.classes ) { return; } @@ -1995,9 +2012,8 @@ FilterContainer.prototype.retrieveGenericSelectors = function( // cosmetic filters now. if ( this.supportsUserStylesheets && - sender instanceof Object && - sender.tab instanceof Object && - typeof sender.frameId === 'number' + request.tabId !== undefined && + request.frameId !== undefined ) { var injected = []; if ( out.simple.length !== 0 ) { @@ -2009,10 +2025,10 @@ FilterContainer.prototype.retrieveGenericSelectors = function( out.complex = []; } out.injected = injected.join(',\n'); - vAPI.insertCSS(sender.tab.id, { + vAPI.insertCSS(request.tabId, { code: out.injected + '\n{display:none!important;}', cssOrigin: 'user', - frameId: sender.frameId, + frameId: request.frameId, runAt: 'document_start' }); } @@ -2030,7 +2046,6 @@ FilterContainer.prototype.retrieveGenericSelectors = function( FilterContainer.prototype.retrieveDomainSelectors = function( request, - sender, options ) { if ( !request.locationURL ) { return; } @@ -2041,7 +2056,8 @@ FilterContainer.prototype.retrieveDomainSelectors = function( domain = this.µburi.domainFromHostname(hostname) || hostname, pos = domain.indexOf('.'), entity = pos === -1 ? '' : domain.slice(0, pos - domain.length) + '.*', - cacheEntry = this.selectorCache.get(hostname); + cacheEntry = this.selectorCache.get(hostname), + entry; // https://github.com/chrisaljoudi/uBlock/issues/587 // out.ready will tell the content script the cosmetic filtering engine is @@ -2177,7 +2193,7 @@ FilterContainer.prototype.retrieveDomainSelectors = function( if ( options.noGenericCosmeticFiltering !== true ) { var exceptionHash = out.exceptionFilters.join(); for ( var type in this.highlyGeneric ) { - var entry = this.highlyGeneric[type]; + entry = this.highlyGeneric[type]; var str = entry.mru.lookup(exceptionHash); if ( str === undefined ) { str = { s: entry.str }; @@ -2206,8 +2222,9 @@ FilterContainer.prototype.retrieveDomainSelectors = function( } // Scriptlet injection. - out.scripts = this.retrieveUserScripts(domain, hostname); + out.scripts = this.retrieveUserScripts(domain, hostname, request); + // CSS selectors for collapsible blocked elements if ( cacheEntry ) { var networkFilters = []; cacheEntry.retrieve('net', networkFilters); @@ -2219,9 +2236,8 @@ FilterContainer.prototype.retrieveDomainSelectors = function( // cosmetic filters now. if ( this.supportsUserStylesheets && - sender instanceof Object && - sender.tab instanceof Object && - typeof sender.frameId === 'number' + request.tabId !== undefined && + request.frameId !== undefined ) { var injectedHideFilters = []; if ( out.declarativeFilters.length !== 0 ) { @@ -2244,16 +2260,16 @@ FilterContainer.prototype.retrieveDomainSelectors = function( var details = { code: '', cssOrigin: 'user', - frameId: sender.frameId, + frameId: request.frameId, runAt: 'document_start' }; if ( out.injectedHideFilters.length !== 0 ) { details.code = out.injectedHideFilters + '\n{display:none!important;}'; - vAPI.insertCSS(sender.tab.id, details); + vAPI.insertCSS(request.tabId, details); } if ( out.networkFilters.length !== 0 ) { details.code = out.networkFilters + '\n{display:none!important;}'; - vAPI.insertCSS(sender.tab.id, details); + vAPI.insertCSS(request.tabId, details); out.networkFilters = ''; } } diff --git a/src/js/messaging.js b/src/js/messaging.js index 508d1166a..40ccaee61 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -464,11 +464,12 @@ var onMessage = function(request, sender, callback) { // Sync var µb = µBlock, response, - tabId, + tabId, frameId, pageStore; if ( sender && sender.tab ) { tabId = sender.tab.id; + frameId = sender.frameId; pageStore = µb.pageStoreFromTabId(tabId); } @@ -497,9 +498,11 @@ var onMessage = function(request, sender, callback) { noGenericCosmeticFiltering: pageStore.noGenericCosmeticFiltering === true }; + request.tabId = tabId; + request.frameId = frameId; response.specificCosmeticFilters = µb.cosmeticFilteringEngine - .retrieveDomainSelectors(request, sender, response); + .retrieveDomainSelectors(request, response); if ( request.isRootFrame && µb.logger.isEnabled() ) { µb.logCosmeticFilters(tabId); } @@ -508,9 +511,11 @@ var onMessage = function(request, sender, callback) { case 'retrieveGenericCosmeticSelectors': if ( pageStore && pageStore.getGenericCosmeticFilteringSwitch() ) { + request.tabId = tabId; + request.frameId = frameId; response = { result: µb.cosmeticFilteringEngine - .retrieveGenericSelectors(request, sender) + .retrieveGenericSelectors(request) }; } break;