diff --git a/src/background.html b/src/background.html index 7edea355e..4565a2778 100644 --- a/src/background.html +++ b/src/background.html @@ -15,6 +15,7 @@ + @@ -24,7 +25,6 @@ - diff --git a/src/js/dynamic-net-filtering.js b/src/js/dynamic-net-filtering.js index 53d9885b6..c899ece3f 100644 --- a/src/js/dynamic-net-filtering.js +++ b/src/js/dynamic-net-filtering.js @@ -194,25 +194,24 @@ Matrix.prototype.evaluateCell = function(srcHostname, desHostname, type) { Matrix.prototype.clearRegisters = function() { this.r = 0; - this.type = ''; - this.y = ''; - this.z = ''; + this.type = this.y = this.z = ''; return this; }; /******************************************************************************/ -var isFirstParty = function(srcHostname, desHostname) { - if ( desHostname.slice(0 - srcHostname.length) !== srcHostname ) { - return false; - } - // Be sure to not confuse 'example.com' with 'anotherexample.com' - if ( desHostname.lenght === srcHostname.lenght ) { +var is3rdParty = function(srcHostname, desHostname) { + var srcDomain = domainFromHostname(srcHostname); + if ( desHostname.slice(0 - srcDomain.length) !== srcDomain ) { return true; } - return desHostname.charAt(desHostname.length - srcHostname.length - 1) === '.'; + // Do not confuse 'example.com' with 'anotherexample.com' + return desHostname.lenght !== srcDomain.lenght && + desHostname.charAt(desHostname.length - srcDomain.length - 1) !== '.'; }; +var domainFromHostname = µBlock.URI.domainFromHostname; + /******************************************************************************/ Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type) { @@ -262,20 +261,18 @@ Matrix.prototype.evaluateCellZY = function(srcHostname, desHostname, type) { this.y = '*'; if ( type === 'script' ) { - type = isFirstParty(srcHostname, desHostname) ? '1p-script' : '3p-script'; - } else if ( type === 'sub_frame' && isFirstParty(srcHostname, desHostname) === false ) { + type = is3rdParty(srcHostname, desHostname) ? '3p-script' : '1p-script'; + } else if ( type === 'sub_frame' && is3rdParty(srcHostname, desHostname) ) { type = '3p-frame'; } - // Is this a type suitable for dynamic filtering purpose? - if ( supportedDynamicTypes.hasOwnProperty(type) === false ) { - this.type = ''; - return this; + if ( supportedDynamicTypes.hasOwnProperty(type) ) { + this.type = type; + this.r = this.evaluateCellZ(srcHostname, '*', type); + if ( this.r !== 0 ) { return this; } } - this.type = type; - this.r = this.evaluateCellZ(srcHostname, '*', type); - + this.type = ''; return this; }; diff --git a/src/js/messaging.js b/src/js/messaging.js index 90ec132d4..fe19ef1b2 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -109,7 +109,7 @@ var µb = µBlock; var getHostnameDict = function(hostnameToCountMap) { var r = {}; - var µburi = µb.URI; + var domainFromHostname = µb.URI.domainFromHostname; var domain, counts; for ( var hostname in hostnameToCountMap ) { if ( hostnameToCountMap.hasOwnProperty(hostname) === false ) { @@ -118,7 +118,7 @@ var getHostnameDict = function(hostnameToCountMap) { if ( r.hasOwnProperty(hostname) ) { continue; } - domain = µburi.domainFromHostname(hostname); + domain = domainFromHostname(hostname); counts = hostnameToCountMap[domain] || 0; r[domain] = { domain: domain, diff --git a/src/js/uritools.js b/src/js/uritools.js index 5e37bd52f..45065fbc1 100644 --- a/src/js/uritools.js +++ b/src/js/uritools.js @@ -274,21 +274,98 @@ URI.hostnameFromURI = function(uri) { /******************************************************************************/ -// It is expected that there is higher-scoped `publicSuffixList` lingering -// somewhere. Cache it. See . -var psl = publicSuffixList; - URI.domainFromHostname = function(hostname) { - if ( !reIPAddressNaive.test(hostname) ) { - return psl.getDomain(hostname); + // Try to skip looking up the PSL database + if ( domainCache.hasOwnProperty(hostname) ) { + var entry = domainCache[hostname]; + entry.tstamp = Date.now(); + return entry.domain; } - return hostname; + // Meh.. will have to search it + if ( reIPAddressNaive.test(hostname) === false ) { + return domainCacheAdd(hostname, psl.getDomain(hostname)); + } + return domainCacheAdd(hostname, hostname); }; URI.domain = function() { return this.domainFromHostname(this.hostname); }; +// It is expected that there is higher-scoped `publicSuffixList` lingering +// somewhere. Cache it. See . +var psl = publicSuffixList; + +/******************************************************************************/ + +// Trying to alleviate the worries of looking up too often the domain name from +// a hostname. With a cache, uBlock benefits given that it deals with a +// specific set of hostnames within a narrow time span -- in other words, I +// believe probability of cache hit are high in uBlock. + +var DomainCacheEntry = function(domain) { + this.init(domain); +}; + +DomainCacheEntry.prototype.init = function(domain) { + this.domain = domain; + this.tstamp = Date.now(); + return this; +}; + +DomainCacheEntry.prototype.dispose = function() { + this.domain = ''; + if ( domainCacheEntryJunkyard.length < 25 ) { + domainCacheEntryJunkyard.push(this); + } +}; + +var domainCacheEntryFactory = function(domain) { + var entry = domainCacheEntryJunkyard.pop(); + if ( entry ) { + return entry.init(domain); + } + return new DomainCacheEntry(domain); +}; + +var domainCacheEntryJunkyard = []; + +var domainCacheAdd = function(hostname, domain) { + if ( domainCache.hasOwnProperty(hostname) ) { + domainCache[hostname].tstamp = Date.now(); + } else { + domainCache[hostname] = domainCacheEntryFactory(domain); + domainCacheCount += 1; + if ( domainCacheCount === domainCacheCountHighWaterMark ) { + domainCachePrune(); + } + } + return domain; +}; + +var domainCacheEntrySort = function(a, b) { + return b.tstamp - a.tstamp; +}; + +var domainCachePrune = function() { + var hostnames = Object.keys(domainCache) + .sort(domainCacheEntrySort) + .slice(domainCacheCountLowWaterMark); + var i = hostnames.length; + domainCacheCount -= i; + var hostname; + while ( i-- ) { + hostname = hostnames[i]; + domainCache[hostname].dispose(); + delete domainCache[hostname]; + } +}; + +var domainCache = {}; +var domainCacheCount = 0; +var domainCacheCountLowWaterMark = 75; +var domainCacheCountHighWaterMark = 100; + /******************************************************************************/ URI.domainFromURI = function(uri) {