mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-10 09:07:54 +01:00
fix #2053
This commit is contained in:
parent
41733339d3
commit
3ff3ae7d70
7 changed files with 135 additions and 91 deletions
|
@ -89,8 +89,8 @@ return {
|
|||
blockedRequestCount: 0,
|
||||
allowedRequestCount: 0
|
||||
},
|
||||
localSettingsModifyTime: 0,
|
||||
localSettingsSaveTime: 0,
|
||||
localSettingsLastModified: 0,
|
||||
localSettingsLastSaved: 0,
|
||||
|
||||
// read-only
|
||||
systemSettings: {
|
||||
|
|
|
@ -217,9 +217,6 @@ Matrix.prototype.hasSameRules = function(other, srcHostname, desHostnames) {
|
|||
|
||||
// Specific destinations
|
||||
for ( var desHostname in desHostnames ) {
|
||||
if ( desHostnames.hasOwnProperty(desHostname) === false ) {
|
||||
continue;
|
||||
}
|
||||
ruleKey = '* ' + desHostname;
|
||||
if ( (thisRules[ruleKey] || 0) !== (otherRules[ruleKey] || 0) ) {
|
||||
return false;
|
||||
|
|
|
@ -199,22 +199,27 @@ var µb = µBlock;
|
|||
/******************************************************************************/
|
||||
|
||||
var getHostnameDict = function(hostnameToCountMap) {
|
||||
var r = {}, de;
|
||||
var domainFromHostname = µb.URI.domainFromHostname;
|
||||
var domain, counts, blockCount, allowCount;
|
||||
for ( var hostname in hostnameToCountMap ) {
|
||||
if ( hostnameToCountMap.hasOwnProperty(hostname) === false ) {
|
||||
continue;
|
||||
var r = Object.create(null),
|
||||
domainEntry,
|
||||
domainFromHostname = µb.URI.domainFromHostname,
|
||||
domain, blockCount, allowCount,
|
||||
iter = hostnameToCountMap.entries(),
|
||||
entry, hostname, counts;
|
||||
for (;;) {
|
||||
entry = iter.next();
|
||||
if ( entry.done ) {
|
||||
break;
|
||||
}
|
||||
if ( r.hasOwnProperty(hostname) ) {
|
||||
hostname = entry.value[0];
|
||||
if ( r[hostname] !== undefined ) {
|
||||
continue;
|
||||
}
|
||||
domain = domainFromHostname(hostname) || hostname;
|
||||
counts = hostnameToCountMap[domain] || 0;
|
||||
counts = hostnameToCountMap.get(domain) || 0;
|
||||
blockCount = counts & 0xFFFF;
|
||||
allowCount = counts >>> 16 & 0xFFFF;
|
||||
if ( r.hasOwnProperty(domain) === false ) {
|
||||
de = r[domain] = {
|
||||
if ( r[domain] === undefined ) {
|
||||
domainEntry = r[domain] = {
|
||||
domain: domain,
|
||||
blockCount: blockCount,
|
||||
allowCount: allowCount,
|
||||
|
@ -222,13 +227,13 @@ var getHostnameDict = function(hostnameToCountMap) {
|
|||
totalAllowCount: allowCount
|
||||
};
|
||||
} else {
|
||||
de = r[domain];
|
||||
domainEntry = r[domain];
|
||||
}
|
||||
counts = hostnameToCountMap[hostname] || 0;
|
||||
counts = entry.value[1];
|
||||
blockCount = counts & 0xFFFF;
|
||||
allowCount = counts >>> 16 & 0xFFFF;
|
||||
de.totalBlockCount += blockCount;
|
||||
de.totalAllowCount += allowCount;
|
||||
domainEntry.totalBlockCount += blockCount;
|
||||
domainEntry.totalAllowCount += allowCount;
|
||||
if ( hostname === domain ) {
|
||||
continue;
|
||||
}
|
||||
|
@ -268,10 +273,8 @@ var getFirewallRules = function(srcHostname, desHostnames) {
|
|||
r['. * 3p-frame'] = df.evaluateCellZY(srcHostname, '*', '3p-frame').toFilterString();
|
||||
|
||||
for ( var desHostname in desHostnames ) {
|
||||
if ( desHostnames.hasOwnProperty(desHostname) ) {
|
||||
r['/ ' + desHostname + ' *'] = df.evaluateCellZY('*', desHostname, '*').toFilterString();
|
||||
r['. ' + desHostname + ' *'] = df.evaluateCellZY(srcHostname, desHostname, '*').toFilterString();
|
||||
}
|
||||
r['/ ' + desHostname + ' *'] = df.evaluateCellZY('*', desHostname, '*').toFilterString();
|
||||
r['. ' + desHostname + ' *'] = df.evaluateCellZY(srcHostname, desHostname, '*').toFilterString();
|
||||
}
|
||||
return r;
|
||||
};
|
||||
|
|
|
@ -266,6 +266,10 @@ var pageStoreJunkyardMax = 10;
|
|||
|
||||
var PageStore = function(tabId) {
|
||||
this.init(tabId);
|
||||
this.journal = [];
|
||||
this.journalTimer = null;
|
||||
this.journalLastCommitted = this.journalLastUncommitted = undefined;
|
||||
this.journalLastUncommittedURL = undefined;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -298,7 +302,7 @@ PageStore.prototype.init = function(tabId) {
|
|||
this.tabHostname = tabContext.rootHostname;
|
||||
this.title = tabContext.rawURL;
|
||||
this.rawURL = tabContext.rawURL;
|
||||
this.hostnameToCountMap = {};
|
||||
this.hostnameToCountMap = new Map();
|
||||
this.contentLastModified = 0;
|
||||
this.frames = Object.create(null);
|
||||
this.perLoadBlockedRequestCount = 0;
|
||||
|
@ -388,10 +392,6 @@ PageStore.prototype.reuse = function(context) {
|
|||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.dispose = function() {
|
||||
// rhill 2013-11-07: Even though at init time these are reset, I still
|
||||
// need to release the memory taken by these, which can amount to
|
||||
// sizeable enough chunks (especially requests, through the request URL
|
||||
// used as a key).
|
||||
this.tabHostname = '';
|
||||
this.title = '';
|
||||
this.rawURL = '';
|
||||
|
@ -403,6 +403,12 @@ PageStore.prototype.dispose = function() {
|
|||
}
|
||||
this.disposeFrameStores();
|
||||
this.netFilteringCache = this.netFilteringCache.dispose();
|
||||
if ( this.journalTimer !== null ) {
|
||||
clearTimeout(this.journalTimer);
|
||||
this.journalTimer = null;
|
||||
}
|
||||
this.journal = [];
|
||||
this.journalLastUncommittedURL = undefined;
|
||||
if ( pageStoreJunkyard.length < pageStoreJunkyardMax ) {
|
||||
pageStoreJunkyard.push(this);
|
||||
}
|
||||
|
@ -519,6 +525,92 @@ PageStore.prototype.temporarilyAllowLargeMediaElements = function() {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/2053
|
||||
// There is no way around using journaling to ensure we deal properly with
|
||||
// potentially out of order navigation events vs. network request events.
|
||||
|
||||
PageStore.prototype.journalAddRequest = function(hostname, result) {
|
||||
if ( hostname === '' ) { return; }
|
||||
this.journal.push(
|
||||
hostname,
|
||||
result.charCodeAt(1) === 0x62 /* 'b' */ ? 0x00000001 : 0x00010000
|
||||
);
|
||||
if ( this.journalTimer === null ) {
|
||||
this.journalTimer = vAPI.setTimeout(this.journalProcess.bind(this, true), 1000);
|
||||
}
|
||||
};
|
||||
|
||||
PageStore.prototype.journalAddRootFrame = function(type, url) {
|
||||
if ( type === 'committed' ) {
|
||||
this.journalLastCommitted = this.journal.length;
|
||||
if (
|
||||
this.journalLastUncommitted !== undefined &&
|
||||
this.journalLastUncommitted < this.journalLastCommitted &&
|
||||
this.journalLastUncommittedURL === url
|
||||
) {
|
||||
this.journalLastCommitted = this.journalLastUncommitted;
|
||||
this.journalLastUncommitted = undefined;
|
||||
}
|
||||
} else if ( type === 'uncommitted' ) {
|
||||
this.journalLastUncommitted = this.journal.length;
|
||||
this.journalLastUncommittedURL = url;
|
||||
}
|
||||
if ( this.journalTimer !== null ) {
|
||||
clearTimeout(this.journalTimer);
|
||||
}
|
||||
this.journalTimer = vAPI.setTimeout(this.journalProcess.bind(this, true), 1000);
|
||||
};
|
||||
|
||||
PageStore.prototype.journalProcess = function(fromTimer) {
|
||||
if ( !fromTimer ) {
|
||||
clearTimeout(this.journalTimer);
|
||||
}
|
||||
this.journalTimer = null;
|
||||
|
||||
var journal = this.journal,
|
||||
i, n = journal.length,
|
||||
hostname, count, hostnameCounts,
|
||||
aggregateCounts = 0,
|
||||
now = Date.now(),
|
||||
pivot = this.journalLastCommitted || 0;
|
||||
|
||||
// Everything after pivot originates from current page.
|
||||
for ( i = pivot; i < n; i += 2 ) {
|
||||
hostname = journal[i];
|
||||
hostnameCounts = this.hostnameToCountMap.get(hostname);
|
||||
if ( hostnameCounts === undefined ) {
|
||||
hostnameCounts = 0;
|
||||
this.contentLastModified = now;
|
||||
}
|
||||
count = journal[i+1];
|
||||
this.hostnameToCountMap.set(hostname, hostnameCounts + count);
|
||||
aggregateCounts += count;
|
||||
}
|
||||
this.perLoadBlockedRequestCount += aggregateCounts & 0xFFFF;
|
||||
this.perLoadAllowedRequestCount += aggregateCounts >>> 16 & 0xFFFF;
|
||||
this.journalLastCommitted = undefined;
|
||||
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/905#issuecomment-76543649
|
||||
// No point updating the badge if it's not being displayed.
|
||||
if ( (aggregateCounts & 0xFFFF) && µb.userSettings.showIconBadge ) {
|
||||
µb.updateBadgeAsync(this.tabId);
|
||||
}
|
||||
|
||||
// Everything before pivot does not originate from current page -- we still
|
||||
// need to bump global blocked/allowed counts.
|
||||
for ( i = 0; i < pivot; i += 2 ) {
|
||||
aggregateCounts += journal[i+1];
|
||||
}
|
||||
if ( aggregateCounts !== 0 ) {
|
||||
µb.localSettings.blockedRequestCount += aggregateCounts & 0xFFFF;
|
||||
µb.localSettings.allowedRequestCount += aggregateCounts >>> 16 & 0xFFFF;
|
||||
µb.localSettingsLastModified = now;
|
||||
}
|
||||
journal.length = 0;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.filterRequest = function(context) {
|
||||
var requestType = context.requestType;
|
||||
|
||||
|
@ -625,34 +717,6 @@ PageStore.prototype.filterRequestNoCache = function(context) {
|
|||
return result;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.logRequest = function(context, result) {
|
||||
var requestHostname = context.requestHostname;
|
||||
// rhill 20150206:
|
||||
// be prepared to handle invalid requestHostname, I've seen this
|
||||
// happen: http://./
|
||||
if ( requestHostname === '' ) {
|
||||
requestHostname = context.rootHostname;
|
||||
}
|
||||
var now = Date.now();
|
||||
if ( this.hostnameToCountMap.hasOwnProperty(requestHostname) === false ) {
|
||||
this.hostnameToCountMap[requestHostname] = 0;
|
||||
this.contentLastModified = now;
|
||||
}
|
||||
var c = result.charAt(1);
|
||||
if ( c === 'b' ) {
|
||||
this.hostnameToCountMap[requestHostname] += 0x00000001;
|
||||
this.perLoadBlockedRequestCount++;
|
||||
µb.localSettings.blockedRequestCount++;
|
||||
} else /* if ( c === '' || c === 'a' || c === 'n' ) */ {
|
||||
this.hostnameToCountMap[requestHostname] += 0x00010000;
|
||||
this.perLoadAllowedRequestCount++;
|
||||
µb.localSettings.allowedRequestCount++;
|
||||
}
|
||||
µb.localSettingsModifyTime = now;
|
||||
};
|
||||
|
||||
// https://www.youtube.com/watch?v=drW8p_dTLD4
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -50,13 +50,13 @@
|
|||
var saveAfter = 4 * 60 * 1000;
|
||||
|
||||
var save = function() {
|
||||
this.localSettingsSaveTime = Date.now();
|
||||
this.localSettingsLastSaved = Date.now();
|
||||
vAPI.storage.set(this.localSettings);
|
||||
};
|
||||
|
||||
var onTimeout = function() {
|
||||
var µb = µBlock;
|
||||
if ( µb.localSettingsModifyTime > µb.localSettingsSaveTime ) {
|
||||
if ( µb.localSettingsLastModified > µb.localSettingsLastSaved ) {
|
||||
save.call(µb);
|
||||
}
|
||||
vAPI.setTimeout(onTimeout, saveAfter);
|
||||
|
|
|
@ -465,23 +465,10 @@ vAPI.tabs.onNavigation = function(details) {
|
|||
if ( details.frameId !== 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var tabContext = µb.tabContextManager.commit(details.tabId, details.url);
|
||||
var pageStore = µb.bindTabToPageStats(details.tabId, 'tabChanged');
|
||||
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/630
|
||||
// The hostname of the bound document must always be present in the
|
||||
// mini-matrix. That's the best place I could find for the fix, all other
|
||||
// options had bad side-effects or complications.
|
||||
// TODO: Eventually, we will have to use an API to check whether a scheme
|
||||
// is supported as I suspect we are going to start to see `ws`, `wss`
|
||||
// as well soon.
|
||||
if (
|
||||
pageStore &&
|
||||
tabContext.rawURL.startsWith('http') &&
|
||||
pageStore.hostnameToCountMap.hasOwnProperty(tabContext.rootHostname) === false
|
||||
) {
|
||||
pageStore.hostnameToCountMap[tabContext.rootHostname] = 0x00010000;
|
||||
µb.tabContextManager.commit(details.tabId, details.url);
|
||||
var pageStore = µb.bindTabToPageStats(details.tabId, 'tabCommitted');
|
||||
if ( pageStore ) {
|
||||
pageStore.journalAddRootFrame('committed', details.url);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -778,7 +765,7 @@ vAPI.tabs.onPopupUpdated = (function() {
|
|||
// filtering pane.
|
||||
var pageStore = µb.pageStoreFromTabId(openerTabId);
|
||||
if ( pageStore ) {
|
||||
pageStore.logRequest(context, result);
|
||||
pageStore.journalAddRequest(context.requestHostname, result);
|
||||
pageStore.popupBlockedCount += 1;
|
||||
}
|
||||
|
||||
|
@ -827,13 +814,13 @@ vAPI.tabs.registerListeners();
|
|||
}
|
||||
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/516
|
||||
// Never rebind behind-the-scene scope
|
||||
// Never rebind behind-the-scene scope.
|
||||
if ( vAPI.isBehindTheSceneTabId(tabId) ) {
|
||||
return pageStore;
|
||||
}
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/516
|
||||
// If context if 'beforeRequest', do not rebind, wait for confirmation.
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/516
|
||||
// If context is 'beforeRequest', do not rebind, wait for confirmation.
|
||||
if ( context === 'beforeRequest' ) {
|
||||
return pageStore;
|
||||
}
|
||||
|
|
|
@ -89,9 +89,7 @@ var onBeforeRequest = function(details) {
|
|||
|
||||
var result = pageStore.filterRequest(requestContext);
|
||||
|
||||
// Possible outcomes: blocked, allowed-passthru, allowed-mirror
|
||||
|
||||
pageStore.logRequest(requestContext, result);
|
||||
pageStore.journalAddRequest(requestContext.requestHostname, result);
|
||||
|
||||
if ( µb.logger.isEnabled() ) {
|
||||
µb.logger.writeOne(
|
||||
|
@ -117,12 +115,6 @@ var onBeforeRequest = function(details) {
|
|||
|
||||
// Blocked
|
||||
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/905#issuecomment-76543649
|
||||
// No point updating the badge if it's not being displayed.
|
||||
if ( µb.userSettings.showIconBadge ) {
|
||||
µb.updateBadgeAsync(tabId);
|
||||
}
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/949
|
||||
// Redirect blocked request?
|
||||
var url = µb.redirectEngine.toURL(requestContext);
|
||||
|
@ -222,7 +214,8 @@ var onBeforeRootFrameRequest = function(details) {
|
|||
// Log
|
||||
var pageStore = µb.bindTabToPageStats(tabId, 'beforeRequest');
|
||||
if ( pageStore ) {
|
||||
pageStore.logRequest(context, result);
|
||||
pageStore.journalAddRootFrame('uncommitted', requestURL);
|
||||
pageStore.journalAddRequest(requestHostname, result);
|
||||
}
|
||||
|
||||
if ( µb.logger.isEnabled() ) {
|
||||
|
@ -299,7 +292,7 @@ var onBeforeBeacon = function(details) {
|
|||
context.requestType = details.type;
|
||||
// "g" in "gb:" stands for "global setting"
|
||||
var result = µb.userSettings.hyperlinkAuditingDisabled ? 'gb:' : '';
|
||||
pageStore.logRequest(context, result);
|
||||
pageStore.journalAddRequest(context.requestHostname, result);
|
||||
if ( µb.logger.isEnabled() ) {
|
||||
µb.logger.writeOne(
|
||||
tabId,
|
||||
|
@ -343,7 +336,7 @@ var onBeforeBehindTheSceneRequest = function(details) {
|
|||
result = pageStore.filterRequestNoCache(context);
|
||||
}
|
||||
|
||||
pageStore.logRequest(context, result);
|
||||
pageStore.journalAddRequest(context.requestHostname, result);
|
||||
|
||||
if ( µb.logger.isEnabled() ) {
|
||||
µb.logger.writeOne(
|
||||
|
|
Loading…
Reference in a new issue