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) {