From 4452644980ca0f1647d9d120c2f916b6ed746e0a Mon Sep 17 00:00:00 2001 From: gorhill Date: Fri, 15 Aug 2014 10:34:13 -0400 Subject: [PATCH] this fixes #156 --- js/abp-hide-filters.js | 50 +++++++++++++++++++++++++------------ js/contentscript-end.js | 53 +++++++++++++++++++++++++++++++++++++--- js/messaging-handlers.js | 7 ++++++ 3 files changed, 91 insertions(+), 19 deletions(-) diff --git a/js/abp-hide-filters.js b/js/abp-hide-filters.js index 96ae6633c..486e87696 100644 --- a/js/abp-hide-filters.js +++ b/js/abp-hide-filters.js @@ -258,29 +258,47 @@ SelectorCacheEntry.prototype.addCosmetic = function(selectors) { } }; -SelectorCacheEntry.prototype.addNet = function(selector) { - if ( typeof selector !== 'string' || selector === '' ) { - return; +SelectorCacheEntry.prototype.addNet = function(selectors) { + if ( typeof selectors === 'string' ) { + this.addNetOne(selectors, Date.now()); + } else { + this.addNetMany(selectors, Date.now()); } // Net request-derived selectors: I limit the number of cached selectors, // as I expect cases where the blocked net-requests are never the // exact same URL. - var dict = this.net; - if ( dict[selector] !== undefined ) { - dict[selector] = Date.now(); + if ( this.netCount < this.netHighWaterMark ) { return; } - if ( this.netCount >= this.netHighWaterMark ) { - var keys = Object.keys(dict).sort(function(a, b) { - return dict[b] - dict[a]; - }).slice(this.netLowWaterMark); - var i = keys.length; - while ( i-- ) { - delete dict[keys[i]]; - } + var dict = this.net; + var keys = Object.keys(dict).sort(function(a, b) { + return dict[b] - dict[a]; + }).slice(this.netLowWaterMark); + var i = keys.length; + while ( i-- ) { + delete dict[keys[i]]; + } +}; + +SelectorCacheEntry.prototype.addNetOne = function(selector, now) { + var dict = this.net; + if ( dict[selector] === undefined ) { + this.netCount += 1; + } + dict[selector] = now; +}; + +SelectorCacheEntry.prototype.addNetMany = function(selectors, now) { + var dict = this.net; + var i = selectors.length || 0; + var selector; + while ( i-- ) { + selector = selectors[i]; + if ( dict[selector] === undefined ) { + this.netCount += 1; + } + dict[selector] = now; } - dict[selector] = Date.now(); - this.netCount += 1; }; SelectorCacheEntry.prototype.add = function(selectors, type) { diff --git a/js/contentscript-end.js b/js/contentscript-end.js index f10095e27..5c6b2c21d 100644 --- a/js/contentscript-end.js +++ b/js/contentscript-end.js @@ -504,6 +504,53 @@ var uBlockMessaging = (function(name){ (function() { var messaging = uBlockMessaging; + var blockableElements = { + 'embed': 'src', + 'iframe': 'src', + 'img': 'src', + 'object': 'data' + }; + + // First pass + messaging.ask({ what: 'blockedRequests' }, function(details) { + var elems = document.querySelectorAll('embed,iframe,img,object'); + var blockedRequests = details.blockedRequests; + var collapse = details.collapse; + var i = elems.length; + var elem, tagName, prop, src; + var selectors = []; + while ( i-- ) { + elem = elems[i]; + tagName = elem.tagName.toLowerCase(); + prop = blockableElements[tagName]; + if ( prop === undefined ) { + continue; + } + src = elem[prop]; + if ( typeof src !== 'string' || src === '' ) { + continue; + } + if ( blockedRequests[src] === undefined ) { + continue; + } + // If `!important` is not there, going back using history will + // likely cause the hidden element to re-appear. + elem.style.visibility = 'hidden !important'; + if ( collapse ) { + elem.parentNode.removeChild(elem); + } + selectors.push(tagName + '[' + prop + '="' + src + '"]'); + } + if ( selectors.length !== 0 ) { + messaging.tell({ + what: 'injectedSelectors', + type: 'net', + hostname: window.location.hostname, + selectors: selectors + }); + } + }); + // Listeners to mop up whatever is otherwise missed: // - Future requests not blocked yet // - Elements dynamically added to the page @@ -542,7 +589,7 @@ var uBlockMessaging = (function(name){ // If `!important` is not there, going back using history will // likely cause the hidden element to re-appear. target.style.visibility = 'hidden !important'; - if ( details.collapse ) { + if ( details.collapse && target.parentNode ) { target.parentNode.removeChild(target); } messaging.tell({ @@ -556,12 +603,12 @@ var uBlockMessaging = (function(name){ }; var onResourceLoaded = function(ev) { - //console.debug('Loaded %s[src="%s"]', target.tagName, target.src); + //console.debug('Loaded %s[src="%s"]', ev.target.tagName, ev.target.src); onResource(ev.target, loadedElements); }; var onResourceFailed = function(ev) { - //console.debug('Failed to load %o[src="%s"]', target, target.src); + //console.debug('Failed to load %o[src="%s"]', eev.target.tagName, ev.target.src); onResource(ev.target, failedElements); }; diff --git a/js/messaging-handlers.js b/js/messaging-handlers.js index 190557c60..3a93f81b5 100644 --- a/js/messaging-handlers.js +++ b/js/messaging-handlers.js @@ -170,6 +170,13 @@ var onMessage = function(request, sender, callback) { µb.abpHideFilters.addToSelectorCache(request); break; + case 'blockedRequests': + response = { + collapse: µb.userSettings.collapseBlocked, + blockedRequests: pageStore ? pageStore.blockedRequests : {} + }; + break; + // Check a single request case 'blockedRequest': response = {