diff options
Diffstat (limited to 'js/pagestats.js')
-rw-r--r-- | js/pagestats.js | 440 |
1 files changed, 220 insertions, 220 deletions
diff --git a/js/pagestats.js b/js/pagestats.js index 646bf01..276f099 100644 --- a/js/pagestats.js +++ b/js/pagestats.js @@ -27,248 +27,248 @@ ηMatrix.pageStoreFactory = (function() { -/******************************************************************************/ + /******************************************************************************/ -var ηm = ηMatrix; + var ηm = ηMatrix; -/******************************************************************************/ + /******************************************************************************/ -var BlockedCollapsibles = function() { - this.boundPruneAsyncCallback = this.pruneAsyncCallback.bind(this); - this.blocked = new Map(); - this.hash = 0; - this.timer = null; -}; - -BlockedCollapsibles.prototype = { - - shelfLife: 10 * 1000, - - add: function(type, url, isSpecific) { - if ( this.blocked.size === 0 ) { this.pruneAsync(); } - var now = Date.now() / 1000 | 0; - // The following "trick" is to encode the specifity into the lsb of the - // time stamp so as to avoid to have to allocate a memory structure to - // store both time stamp and specificity. - if ( isSpecific ) { - now |= 0x00000001; - } else { - now &= 0xFFFFFFFE; - } - this.blocked.set(type + ' ' + url, now); - this.hash = now; - }, - - reset: function() { - this.blocked.clear(); + var BlockedCollapsibles = function() { + this.boundPruneAsyncCallback = this.pruneAsyncCallback.bind(this); + this.blocked = new Map(); this.hash = 0; - if ( this.timer !== null ) { - clearTimeout(this.timer); - this.timer = null; - } - }, - - pruneAsync: function() { - if ( this.timer === null ) { - this.timer = vAPI.setTimeout( - this.boundPruneAsyncCallback, - this.shelfLife * 2 - ); - } - }, - - pruneAsyncCallback: function() { this.timer = null; - var obsolete = Date.now() - this.shelfLife; - for ( var entry of this.blocked ) { - if ( entry[1] <= obsolete ) { - this.blocked.delete(entry[0]); + }; + + BlockedCollapsibles.prototype = { + + shelfLife: 10 * 1000, + + add: function(type, url, isSpecific) { + if ( this.blocked.size === 0 ) { this.pruneAsync(); } + var now = Date.now() / 1000 | 0; + // The following "trick" is to encode the specifity into the lsb of the + // time stamp so as to avoid to have to allocate a memory structure to + // store both time stamp and specificity. + if ( isSpecific ) { + now |= 0x00000001; + } else { + now &= 0xFFFFFFFE; } - } - if ( this.blocked.size !== 0 ) { this.pruneAsync(); } - } -}; - -/******************************************************************************/ + this.blocked.set(type + ' ' + url, now); + this.hash = now; + }, + + reset: function() { + this.blocked.clear(); + this.hash = 0; + if ( this.timer !== null ) { + clearTimeout(this.timer); + this.timer = null; + } + }, + + pruneAsync: function() { + if ( this.timer === null ) { + this.timer = vAPI.setTimeout( + this.boundPruneAsyncCallback, + this.shelfLife * 2 + ); + } + }, -// Ref: Given a URL, returns a (somewhat) unique 32-bit value -// Based on: FNV32a -// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-reference-source -// The rest is custom, suited for uMatrix. - -var PageStore = function(tabContext) { - this.hostnameTypeCells = new Map(); - this.domains = new Set(); - this.blockedCollapsibles = new BlockedCollapsibles(); - this.requestStats = ηm.requestStatsFactory(); - this.off = false; - this.init(tabContext); -}; - -PageStore.prototype = { - - collapsibleTypes: new Set([ 'image' ]), - pageStoreJunkyard: [], - - init: function(tabContext) { - this.tabId = tabContext.tabId; - this.rawUrl = tabContext.rawURL; - this.pageUrl = tabContext.normalURL; - this.pageHostname = tabContext.rootHostname; - this.pageDomain = tabContext.rootDomain; - this.title = ''; - this.hostnameTypeCells.clear(); - this.domains.clear(); - this.allHostnamesString = ' '; - this.blockedCollapsibles.reset(); - this.requestStats.reset(); - this.distinctRequestCount = 0; - this.perLoadAllowedRequestCount = 0; - this.perLoadBlockedRequestCount = 0; - this.has3pReferrer = false; - this.hasMixedContent = false; - this.hasNoscriptTags = false; - this.hasWebWorkers = false; - this.incinerationTimer = null; - this.mtxContentModifiedTime = 0; - this.mtxCountModifiedTime = 0; - return this; - }, - - dispose: function() { - this.rawUrl = ''; - this.pageUrl = ''; - this.pageHostname = ''; - this.pageDomain = ''; - this.title = ''; - this.hostnameTypeCells.clear(); - this.domains.clear(); - this.allHostnamesString = ' '; - this.blockedCollapsibles.reset(); - if ( this.incinerationTimer !== null ) { - clearTimeout(this.incinerationTimer); - this.incinerationTimer = null; - } - if ( this.pageStoreJunkyard.length < 8 ) { - this.pageStoreJunkyard.push(this); - } - }, - - cacheBlockedCollapsible: function(type, url, specificity) { - if ( this.collapsibleTypes.has(type) ) { - this.blockedCollapsibles.add( - type, - url, - specificity !== 0 && specificity < 5 - ); + pruneAsyncCallback: function() { + this.timer = null; + var obsolete = Date.now() - this.shelfLife; + for ( var entry of this.blocked ) { + if ( entry[1] <= obsolete ) { + this.blocked.delete(entry[0]); + } + } + if ( this.blocked.size !== 0 ) { this.pruneAsync(); } } - }, - - lookupBlockedCollapsibles: function(request, response) { - var tabContext = ηm.tabContextManager.lookup(this.tabId); - if ( tabContext === null ) { return; } - - var collapseBlacklisted = ηm.userSettings.collapseBlacklisted, - collapseBlocked = ηm.userSettings.collapseBlocked, - entry; - - var blockedResources = response.blockedResources; - - if ( - Array.isArray(request.toFilter) && - request.toFilter.length !== 0 - ) { - var roothn = tabContext.rootHostname, - hnFromURI = ηm.URI.hostnameFromURI, - tMatrix = ηm.tMatrix; - for ( entry of request.toFilter ) { - if ( tMatrix.mustBlock(roothn, hnFromURI(entry.url), entry.type) === false ) { - continue; + }; + + /******************************************************************************/ + + // Ref: Given a URL, returns a (somewhat) unique 32-bit value + // Based on: FNV32a + // http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-reference-source + // The rest is custom, suited for uMatrix. + + var PageStore = function(tabContext) { + this.hostnameTypeCells = new Map(); + this.domains = new Set(); + this.blockedCollapsibles = new BlockedCollapsibles(); + this.requestStats = ηm.requestStatsFactory(); + this.off = false; + this.init(tabContext); + }; + + PageStore.prototype = { + + collapsibleTypes: new Set([ 'image' ]), + pageStoreJunkyard: [], + + init: function(tabContext) { + this.tabId = tabContext.tabId; + this.rawUrl = tabContext.rawURL; + this.pageUrl = tabContext.normalURL; + this.pageHostname = tabContext.rootHostname; + this.pageDomain = tabContext.rootDomain; + this.title = ''; + this.hostnameTypeCells.clear(); + this.domains.clear(); + this.allHostnamesString = ' '; + this.blockedCollapsibles.reset(); + this.requestStats.reset(); + this.distinctRequestCount = 0; + this.perLoadAllowedRequestCount = 0; + this.perLoadBlockedRequestCount = 0; + this.has3pReferrer = false; + this.hasMixedContent = false; + this.hasNoscriptTags = false; + this.hasWebWorkers = false; + this.incinerationTimer = null; + this.mtxContentModifiedTime = 0; + this.mtxCountModifiedTime = 0; + return this; + }, + + dispose: function() { + this.rawUrl = ''; + this.pageUrl = ''; + this.pageHostname = ''; + this.pageDomain = ''; + this.title = ''; + this.hostnameTypeCells.clear(); + this.domains.clear(); + this.allHostnamesString = ' '; + this.blockedCollapsibles.reset(); + if ( this.incinerationTimer !== null ) { + clearTimeout(this.incinerationTimer); + this.incinerationTimer = null; + } + if ( this.pageStoreJunkyard.length < 8 ) { + this.pageStoreJunkyard.push(this); + } + }, + + cacheBlockedCollapsible: function(type, url, specificity) { + if ( this.collapsibleTypes.has(type) ) { + this.blockedCollapsibles.add( + type, + url, + specificity !== 0 && specificity < 5 + ); + } + }, + + lookupBlockedCollapsibles: function(request, response) { + var tabContext = ηm.tabContextManager.lookup(this.tabId); + if ( tabContext === null ) { return; } + + var collapseBlacklisted = ηm.userSettings.collapseBlacklisted, + collapseBlocked = ηm.userSettings.collapseBlocked, + entry; + + var blockedResources = response.blockedResources; + + if ( + Array.isArray(request.toFilter) && + request.toFilter.length !== 0 + ) { + var roothn = tabContext.rootHostname, + hnFromURI = ηm.URI.hostnameFromURI, + tMatrix = ηm.tMatrix; + for ( entry of request.toFilter ) { + if ( tMatrix.mustBlock(roothn, hnFromURI(entry.url), entry.type) === false ) { + continue; + } + blockedResources.push([ + entry.type + ' ' + entry.url, + collapseBlocked || + collapseBlacklisted && tMatrix.specificityRegister !== 0 && + tMatrix.specificityRegister < 5 + ]); } + } + + if ( this.blockedCollapsibles.hash === response.hash ) { return; } + response.hash = this.blockedCollapsibles.hash; + + for ( entry of this.blockedCollapsibles.blocked ) { blockedResources.push([ - entry.type + ' ' + entry.url, - collapseBlocked || - collapseBlacklisted && tMatrix.specificityRegister !== 0 && - tMatrix.specificityRegister < 5 + entry[0], + collapseBlocked || collapseBlacklisted && (entry[1] & 1) !== 0 ]); } - } - - if ( this.blockedCollapsibles.hash === response.hash ) { return; } - response.hash = this.blockedCollapsibles.hash; + }, - for ( entry of this.blockedCollapsibles.blocked ) { - blockedResources.push([ - entry[0], - collapseBlocked || collapseBlacklisted && (entry[1] & 1) !== 0 - ]); - } - }, + recordRequest: function(type, url, block) { + if ( block !== false ) { + this.perLoadBlockedRequestCount++; + } else { + this.perLoadAllowedRequestCount++; + } - recordRequest: function(type, url, block) { - if ( block !== false ) { - this.perLoadBlockedRequestCount++; - } else { - this.perLoadAllowedRequestCount++; - } - - // Store distinct network requests. This is used to: - // - remember which hostname/type were seen - // - count the number of distinct URLs for any given - // hostname-type pair - var hostname = ηm.URI.hostnameFromURI(url), - key = hostname + ' ' + type, - uids = this.hostnameTypeCells.get(key); - if ( uids === undefined ) { - this.hostnameTypeCells.set(key, (uids = new Set())); - } else if ( uids.size > 99 ) { - return; - } - var uid = this.uidFromURL(url); - if ( uids.has(uid) ) { return; } - uids.add(uid); + // Store distinct network requests. This is used to: + // - remember which hostname/type were seen + // - count the number of distinct URLs for any given + // hostname-type pair + var hostname = ηm.URI.hostnameFromURI(url), + key = hostname + ' ' + type, + uids = this.hostnameTypeCells.get(key); + if ( uids === undefined ) { + this.hostnameTypeCells.set(key, (uids = new Set())); + } else if ( uids.size > 99 ) { + return; + } + var uid = this.uidFromURL(url); + if ( uids.has(uid) ) { return; } + uids.add(uid); - // Count blocked/allowed requests - this.requestStats.record(type, block); + // Count blocked/allowed requests + this.requestStats.record(type, block); - // https://github.com/gorhill/httpswitchboard/issues/306 - // If it is recorded locally, record globally - ηm.requestStats.record(type, block); - ηm.updateBadgeAsync(this.tabId); + // https://github.com/gorhill/httpswitchboard/issues/306 + // If it is recorded locally, record globally + ηm.requestStats.record(type, block); + ηm.updateBadgeAsync(this.tabId); - // this.distinctRequestCount++; - this.mtxCountModifiedTime = Date.now(); + // this.distinctRequestCount++; + this.mtxCountModifiedTime = Date.now(); - if ( this.domains.has(hostname) === false ) { - this.domains.add(hostname); - this.allHostnamesString += hostname + ' '; - this.mtxContentModifiedTime = Date.now(); - } - }, - - uidFromURL: function(uri) { - var hint = 0x811c9dc5, - i = uri.length; - while ( i-- ) { - hint ^= uri.charCodeAt(i) | 0; - hint += (hint<<1) + (hint<<4) + (hint<<7) + (hint<<8) + (hint<<24) | 0; - hint >>>= 0; + if ( this.domains.has(hostname) === false ) { + this.domains.add(hostname); + this.allHostnamesString += hostname + ' '; + this.mtxContentModifiedTime = Date.now(); + } + }, + + uidFromURL: function(uri) { + var hint = 0x811c9dc5, + i = uri.length; + while ( i-- ) { + hint ^= uri.charCodeAt(i) | 0; + hint += (hint<<1) + (hint<<4) + (hint<<7) + (hint<<8) + (hint<<24) | 0; + hint >>>= 0; + } + return hint; } - return hint; - } -}; + }; -/******************************************************************************/ + /******************************************************************************/ -return function pageStoreFactory(tabContext) { - var entry = PageStore.prototype.pageStoreJunkyard.pop(); - if ( entry ) { - return entry.init(tabContext); - } - return new PageStore(tabContext); -}; + return function pageStoreFactory(tabContext) { + var entry = PageStore.prototype.pageStoreJunkyard.pop(); + if ( entry ) { + return entry.init(tabContext); + } + return new PageStore(tabContext); + }; -/******************************************************************************/ + /******************************************************************************/ })(); |