diff --git a/src/js/messaging.js b/src/js/messaging.js index a0b6d7339..63473e960 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -497,8 +497,8 @@ var onMessage = function(request, sender, callback) { } // Sync - var µb = µBlock, - response, + const µb = µBlock; + let response, tabId, frameId, pageStore = null; @@ -527,7 +527,7 @@ var onMessage = function(request, sender, callback) { case 'shouldRenderNoscriptTags': if ( pageStore === null ) { break; } - const fctxt = µBlock.filteringContext.fromTabId(tabId); + const fctxt = µb.filteringContext.fromTabId(tabId); if ( pageStore.filterScripting(fctxt, undefined) ) { vAPI.tabs.injectScript( tabId, @@ -567,8 +567,11 @@ var onMessage = function(request, sender, callback) { if ( µb.canInjectScriptletsNow === false ) { response.scriptlets = µb.scriptletFilteringEngine.retrieve(request); } - if ( response.noCosmeticFiltering !== true ) { - µb.logCosmeticFilters(tabId, frameId); + if ( µb.logger.enabled ) { + if ( response.noCosmeticFiltering !== true ) { + µb.logCosmeticFilters(tabId, frameId); + } + µb.logInlineScript(tabId, frameId); } break; @@ -1317,15 +1320,15 @@ vAPI.messaging.listen('documentBlocked', onMessage); /******************************************************************************/ -let µb = µBlock; -let broadcastTimers = new Map(); +const µb = µBlock; +const broadcastTimers = new Map(); /******************************************************************************/ -var domSurveyFinalReport = function(tabId) { +const domSurveyFinalReport = function(tabId) { broadcastTimers.delete(tabId + '-domSurveyReport'); - let pageStore = µb.pageStoreFromTabId(tabId); + const pageStore = µb.pageStoreFromTabId(tabId); if ( pageStore === null ) { return; } vAPI.messaging.broadcast({ @@ -1358,8 +1361,8 @@ const logCosmeticFilters = function(tabId, details) { /******************************************************************************/ var onMessage = function(request, sender, callback) { - let tabId = sender && sender.tab ? sender.tab.id : 0; - let pageStore = µb.pageStoreFromTabId(tabId); + const tabId = sender && sender.tab ? sender.tab.id : 0; + const pageStore = µb.pageStoreFromTabId(tabId); // Async switch ( request.what ) { @@ -1389,6 +1392,19 @@ var onMessage = function(request, sender, callback) { } break; + case 'inlinescriptFound': + if ( µb.logger.enabled && pageStore !== null ) { + const fctxt = µb.filteringContext.duplicate(); + fctxt.fromTabId(tabId) + .setType('inline-script') + .setURL(request.docURL) + .setDocOriginFromURL(request.docURL); + if ( pageStore.filterRequest(fctxt) === 0 ) { + fctxt.setRealm('net').toLogger(); + } + } + break; + case 'logCosmeticFilteringData': logCosmeticFilters(tabId, request); break; diff --git a/src/js/pagestore.js b/src/js/pagestore.js index d7f9891d0..255a6e09d 100644 --- a/src/js/pagestore.js +++ b/src/js/pagestore.js @@ -44,145 +44,127 @@ const µb = µBlock; // To mitigate memory churning const netFilteringCacheJunkyard = []; -const netFilteringCacheJunkyardMax = 10; +const netFilteringCacheJunkyardMax = 10; /******************************************************************************/ const NetFilteringResultCache = function() { - this.boundPruneAsyncCallback = this.pruneAsyncCallback.bind(this); this.init(); }; -/******************************************************************************/ +NetFilteringResultCache.prototype = { + shelfLife: 15000, -NetFilteringResultCache.prototype.shelfLife = 15 * 1000; + init: function() { + this.blocked = new Map(); + this.results = new Map(); + this.hash = 0; + this.timer = undefined; + return this; + }, -/******************************************************************************/ + dispose: function() { + this.empty(); + if ( netFilteringCacheJunkyard.length < netFilteringCacheJunkyardMax ) { + netFilteringCacheJunkyard.push(this); + } + return null; + }, + + rememberResult: function(fctxt, result) { + if ( fctxt.tabId <= 0 ) { return; } + if ( this.results.size === 0 ) { + this.pruneAsync(); + } + const key = fctxt.getDocHostname() + ' ' + fctxt.type + ' ' + fctxt.url; + this.results.set(key, { + result: result, + logData: fctxt.filter, + tstamp: Date.now() + }); + if ( result !== 1 ) { return; } + const now = Date.now(); + this.blocked.set(key, now); + this.hash = now; + }, + + rememberBlock: function(fctxt) { + if ( fctxt.tabId <= 0 ) { return; } + if ( this.blocked.size === 0 ) { + this.pruneAsync(); + } + const now = Date.now(); + this.blocked.set( + fctxt.getDocHostname() + ' ' + fctxt.type + ' ' + fctxt.url, + now + ); + this.hash = now; + }, + + empty: function() { + this.blocked.clear(); + this.results.clear(); + this.hash = 0; + if ( this.timer !== undefined ) { + clearTimeout(this.timer); + this.timer = undefined; + } + }, + + prune: function() { + const obsolete = Date.now() - this.shelfLife; + for ( const entry of this.blocked ) { + if ( entry[1] <= obsolete ) { + this.results.delete(entry[0]); + this.blocked.delete(entry[0]); + } + } + for ( const entry of this.results ) { + if ( entry[1].tstamp <= obsolete ) { + this.results.delete(entry[0]); + } + } + if ( this.blocked.size !== 0 || this.results.size !== 0 ) { + this.pruneAsync(); + } + }, + + pruneAsync: function() { + if ( this.timer !== undefined ) { return; } + this.timer = vAPI.setTimeout( + ( ) => { + this.timer = undefined; + this.prune(); + }, + this.shelfLife + ); + }, + + lookupResult: function(fctxt) { + return this.results.get( + fctxt.getDocHostname() + ' ' + + fctxt.type + ' ' + + fctxt.url + ); + }, + + lookupAllBlocked: function(hostname) { + const result = []; + for ( const entry of this.blocked ) { + const pos = entry[0].indexOf(' '); + if ( entry[0].slice(0, pos) === hostname ) { + result[result.length] = entry[0].slice(pos + 1); + } + } + return result; + }, +}; NetFilteringResultCache.factory = function() { - let entry = netFilteringCacheJunkyard.pop(); - if ( entry === undefined ) { - entry = new NetFilteringResultCache(); - } else { - entry.init(); - } - return entry; -}; - -/******************************************************************************/ - -NetFilteringResultCache.prototype.init = function() { - this.blocked = new Map(); - this.results = new Map(); - this.hash = 0; - this.timer = null; -}; - -/******************************************************************************/ - -NetFilteringResultCache.prototype.dispose = function() { - this.empty(); - if ( netFilteringCacheJunkyard.length < netFilteringCacheJunkyardMax ) { - netFilteringCacheJunkyard.push(this); - } - return null; -}; - -/******************************************************************************/ - -NetFilteringResultCache.prototype.rememberResult = function(fctxt, result) { - if ( fctxt.tabId <= 0 ) { return; } - if ( this.results.size === 0 ) { - this.pruneAsync(); - } - const key = fctxt.getDocHostname() + ' ' + fctxt.type + ' ' + fctxt.url; - this.results.set(key, { - result: result, - logData: fctxt.filter, - tstamp: Date.now() - }); - if ( result !== 1 ) { return; } - const now = Date.now(); - this.blocked.set(key, now); - this.hash = now; -}; - -/******************************************************************************/ - -NetFilteringResultCache.prototype.rememberBlock = function(fctxt) { - if ( fctxt.tabId <= 0 ) { return; } - if ( this.blocked.size === 0 ) { - this.pruneAsync(); - } - const now = Date.now(); - this.blocked.set( - fctxt.getDocHostname() + ' ' + fctxt.type + ' ' + fctxt.url, - now - ); - this.hash = now; -}; - -/******************************************************************************/ - -NetFilteringResultCache.prototype.empty = function() { - this.blocked.clear(); - this.results.clear(); - this.hash = 0; - if ( this.timer !== null ) { - clearTimeout(this.timer); - this.timer = null; - } -}; - -/******************************************************************************/ - -NetFilteringResultCache.prototype.pruneAsync = function() { - if ( this.timer === null ) { - this.timer = vAPI.setTimeout(this.boundPruneAsyncCallback, this.shelfLife * 2); - } -}; - -NetFilteringResultCache.prototype.pruneAsyncCallback = function() { - this.timer = null; - var obsolete = Date.now() - this.shelfLife, - entry; - for ( entry of this.blocked ) { - if ( entry[1] <= obsolete ) { - this.results.delete(entry[0]); - this.blocked.delete(entry[0]); - } - } - for ( entry of this.results ) { - if ( entry[1].tstamp <= obsolete ) { - this.results.delete(entry[0]); - } - } - if ( this.blocked.size !== 0 || this.results.size !== 0 ) { - this.pruneAsync(); - } -}; - -/******************************************************************************/ - -NetFilteringResultCache.prototype.lookupResult = function(fctxt) { - return this.results.get( - fctxt.getDocHostname() + ' ' + - fctxt.type + ' ' + - fctxt.url - ); -}; - -/******************************************************************************/ - -NetFilteringResultCache.prototype.lookupAllBlocked = function(hostname) { - const result = []; - for ( const entry of this.blocked ) { - const pos = entry[0].indexOf(' '); - if ( entry[0].slice(0, pos) === hostname ) { - result[result.length] = entry[0].slice(pos + 1); - } - } - return result; + const entry = netFilteringCacheJunkyard.pop(); + return entry !== undefined + ? entry.init() + : new NetFilteringResultCache(); }; /******************************************************************************/ @@ -203,7 +185,23 @@ const FrameStore = function(frameURL) { this.init(frameURL); }; -/******************************************************************************/ +FrameStore.prototype = { + init: function(frameURL) { + const µburi = µb.URI; + this.pageHostname = µburi.hostnameFromURI(frameURL); + this.pageDomain = + µburi.domainFromHostname(this.pageHostname) || this.pageHostname; + return this; + }, + + dispose: function() { + this.pageHostname = this.pageDomain = ''; + if ( frameStoreJunkyard.length < frameStoreJunkyardMax ) { + frameStoreJunkyard.push(this); + } + return null; + }, +}; FrameStore.factory = function(frameURL) { const entry = frameStoreJunkyard.pop(); @@ -213,25 +211,6 @@ FrameStore.factory = function(frameURL) { return entry.init(frameURL); }; -/******************************************************************************/ - -FrameStore.prototype.init = function(frameURL) { - const µburi = µb.URI; - this.pageHostname = µburi.hostnameFromURI(frameURL); - this.pageDomain = µburi.domainFromHostname(this.pageHostname) || this.pageHostname; - return this; -}; - -/******************************************************************************/ - -FrameStore.prototype.dispose = function() { - this.pageHostname = this.pageDomain = ''; - if ( frameStoreJunkyard.length < frameStoreJunkyardMax ) { - frameStoreJunkyard.push(this); - } - return null; -}; - /******************************************************************************/ /******************************************************************************/ diff --git a/src/js/traffic.js b/src/js/traffic.js index 355f1a30b..bf84bd17d 100644 --- a/src/js/traffic.js +++ b/src/js/traffic.js @@ -425,10 +425,6 @@ const onHeadersReceived = function(details) { const isRootDoc = requestType === 'main_frame'; const isDoc = isRootDoc || requestType === 'sub_frame'; - if ( isRootDoc ) { - µb.tabContextManager.push(details.tabId, details.url); - } - let pageStore = µb.pageStoreFromTabId(fctxt.tabId); if ( pageStore === null ) { if ( isRootDoc === false ) { return; } @@ -783,11 +779,12 @@ const injectCSP = function(fctxt, pageStore, responseHeaders) { } } else { fctxt.type = 'inline-script'; - if ( pageStore.filterRequest(fctxt) === 1 ) { + const result = pageStore.filterRequest(fctxt); + if ( result === 1 ) { builtinDirectives.push("script-src 'unsafe-eval' * blob: data:"); - if ( loggerEnabled ) { - fctxt.setRealm('net').toLogger(); - } + } + if ( result !== 0 && loggerEnabled ) { + fctxt.setRealm('net').toLogger(); } } diff --git a/src/js/ublock.js b/src/js/ublock.js index 758a6c7c1..a26d22ae8 100644 --- a/src/js/ublock.js +++ b/src/js/ublock.js @@ -548,13 +548,19 @@ var matchBucket = function(url, hostname, bucket, start) { // cosmetic filters. µBlock.logCosmeticFilters = function(tabId, frameId) { - if ( this.logger.enabled ) { - vAPI.tabs.injectScript(tabId, { - file: '/js/scriptlets/cosmetic-logger.js', - frameId: frameId, - runAt: 'document_start' - }); - } + vAPI.tabs.injectScript(tabId, { + file: '/js/scriptlets/cosmetic-logger.js', + frameId: frameId, + runAt: 'document_start' + }); +}; + +µBlock.logInlineScript = function(tabId, frameId) { + vAPI.tabs.injectScript(tabId, { + frameId: frameId, + file: '/js/scriptlets/inlinescript-logger.js', + runAt: 'document_start' + }); }; /******************************************************************************/