this fixes #58

This commit is contained in:
gorhill 2014-07-14 11:24:59 -04:00
parent 1bfc107cdf
commit 6050ab3959
5 changed files with 108 additions and 41 deletions

View File

@ -28,6 +28,17 @@
/******************************************************************************/ /******************************************************************************/
// fedcba9876543210
// | | |
// | | |
// | | |
// | | |
// | | |
// | | |
// | | +---- party [0 - 7]
// | +---- type [0 - 15]
// +---- [BlockAction | AllowAction]
const BlockAction = 0 << 15; const BlockAction = 0 << 15;
const AllowAction = 1 << 15; const AllowAction = 1 << 15;
@ -74,7 +85,8 @@ var typeNameToTypeValue = {
'script': 5 << 11, 'script': 5 << 11,
'xmlhttprequest': 6 << 11, 'xmlhttprequest': 6 << 11,
'sub_frame': 7 << 11, 'sub_frame': 7 << 11,
'other': 8 << 11 'other': 8 << 11,
'popup': 9 << 11
}; };
// ABP filters: https://adblockplus.org/en/filters // ABP filters: https://adblockplus.org/en/filters
@ -805,7 +817,8 @@ FilterParser.prototype.toNormalizedType = {
'script': 'script', 'script': 'script',
'xmlhttprequest': 'xmlhttprequest', 'xmlhttprequest': 'xmlhttprequest',
'subdocument': 'sub_frame', 'subdocument': 'sub_frame',
'other': 'other' 'other': 'other',
'popup': 'popup'
}; };
/******************************************************************************/ /******************************************************************************/
@ -955,7 +968,7 @@ FilterParser.prototype.parse = function(s) {
continue; continue;
} }
if ( opt === 'popup' ) { if ( opt === 'popup' ) {
this.elemHiding = true; this.parseOptType('popup', not);
break; break;
} }
this.unsupported = true; this.unsupported = true;

View File

@ -61,7 +61,6 @@ return {
}, },
pageStores: {}, pageStores: {},
pageStoreDump: {},
storageQuota: chrome.storage.local.QUOTA_BYTES, storageQuota: chrome.storage.local.QUOTA_BYTES,
storageUsed: 0, storageUsed: 0,

View File

@ -60,6 +60,22 @@ function PageStore(tabId, pageURL) {
PageStore.prototype.init = function(tabId, pageURL) { PageStore.prototype.init = function(tabId, pageURL) {
this.tabId = tabId; this.tabId = tabId;
this.previousPageURL = '';
this.pageURL = pageURL;
this.pageHostname = µb.URI.hostnameFromURI(pageURL);
this.pageDomain = µb.URI.domainFromHostname(this.pageHostname);
this.perLoadBlockedRequestCount = 0;
this.perLoadAllowedRequestCount = 0;
this.blockedRequests = {};
this.allowedRequests = {};
this.disposeTime = 0;
return this;
};
/******************************************************************************/
PageStore.prototype.reuse = function(pageURL) {
this.previousPageURL = this.pageURL;
this.pageURL = pageURL; this.pageURL = pageURL;
this.pageHostname = µb.URI.hostnameFromURI(pageURL); this.pageHostname = µb.URI.hostnameFromURI(pageURL);
this.pageDomain = µb.URI.domainFromHostname(this.pageHostname); this.pageDomain = µb.URI.domainFromHostname(this.pageHostname);

View File

@ -41,9 +41,15 @@
if ( !tab.url || tab.url === '' ) { if ( !tab.url || tab.url === '' ) {
return; return;
} }
if ( changeInfo.url && µBlock.pageStores[tabId] ) { var µb = µBlock;
µBlock.updateBadgeAsync(tabId); if ( !changeInfo.url || !µb.pageStores[tabId] ) {
return;
} }
// If URL is unsupported scheme, unbind tab
if ( changeInfo.url && changeInfo.url.slice(0, 4) !== 'http' ) {
µb.unbindTabFromPageStats(tabId);
}
µb.updateBadgeAsync(tabId);
} }
chrome.tabs.onUpdated.addListener(onTabUpdated); chrome.tabs.onUpdated.addListener(onTabUpdated);
@ -92,32 +98,23 @@
µBlock.bindTabToPageStats = function(tabId, pageURL) { µBlock.bindTabToPageStats = function(tabId, pageURL) {
this.updateBadgeAsync(tabId); this.updateBadgeAsync(tabId);
// First unbind whatever page store is bound to the tab id.
this.unbindTabFromPageStats(tabId);
// https://github.com/gorhill/httpswitchboard/issues/303 // https://github.com/gorhill/httpswitchboard/issues/303
// Normalize to a page-URL. // Normalize page URL
pageURL = this.normalizePageURL(pageURL); pageURL = this.normalizePageURL(pageURL);
// do not create stats store for urls which are of no interests // Do not create a page store for URLs which are of no interests
if ( pageURL === '' ) { if ( pageURL === '' ) {
this.unbindTabFromPageStats(tabId);
return null; return null;
} }
// Bring back existing page store or create new one. // Reuse page store if one exists: this allows to guess if a tab is
// a popup.
var pageStore = this.pageStores[tabId]; var pageStore = this.pageStores[tabId];
if ( !pageStore ) { if ( pageStore ) {
var k = pageURL + ' ' + tabId; pageStore.reuse(pageURL);
pageStore = this.pageStoreDump[k]; } else {
if ( pageStore ) {
delete this.pageStoreDump[k];
}
}
if ( !pageStore ) {
pageStore = this.PageStore.factory(tabId, pageURL); pageStore = this.PageStore.factory(tabId, pageURL);
pageStore.perLoadAllowedRequestCount =
pageStore.perLoadBlockedRequestCount = 0;
} }
//console.log('µBlock> bindTabToPageStats(%d, "%s")', tabId, pageURL); //console.log('µBlock> bindTabToPageStats(%d, "%s")', tabId, pageURL);
@ -127,12 +124,6 @@
}; };
µBlock.unbindTabFromPageStats = function(tabId) { µBlock.unbindTabFromPageStats = function(tabId) {
var pageStore = this.pageStores[tabId];
if ( pageStore ) {
//pageStore.disposeTime = Date.now();
//this.pageStoreDump[pageStore.pageURL + ' ' + tabId] = pageStore;
//console.log('µBlock> unbindTabFromPageStats(%d)', tabId);
}
delete this.pageStores[tabId]; delete this.pageStores[tabId];
}; };

View File

@ -29,6 +29,58 @@
/******************************************************************************/ /******************************************************************************/
// Intercept root frame requests. This is where we identify and block popups.
var onBeforeRootDocumentRequestHandler = function(tabId, details) {
var µb = µBlock;
// Ignore non-http schemes: I don't think this could ever happened
// because of filters at addListener() time... Will see.
var requestURL = details.url;
if ( requestURL.slice(0, 4) !== 'http' ) {
console.error('onBeforeRootDocumentRequestHandler(): Unexpected scheme!');
µb.unbindTabFromPageStats(tabId);
return;
}
// Lookup the page store associated with this tab id.
var pageStore = µb.bindTabToPageStats(tabId, requestURL);
if ( !pageStore ) {
return;
}
// Heuristic to determine whether we are dealing with a popup:
// - the page store is new (it's not a reused one)
// Can't be a popup, the tab was in use previously.
if ( pageStore.previousPageURL !== '' ) {
return;
}
var reason = false;
if ( µb.getNetFilteringSwitch(pageStore.pageHostname) ) {
reason = µb.abpFilters.matchString(
pageStore,
requestURL,
'popup',
µb.URI.hostnameFromURI(requestURL)
);
}
// Not blocked?
if ( reason === false || reason.slice(0, 2) === '@@' ) {
return;
}
// It is a popup, block and remove the tab.
µb.unbindTabFromPageStats(tabId);
chrome.tabs.remove(tabId);
return { 'cancel': true };
};
/******************************************************************************/
// Intercept and filter web requests according to white and black lists. // Intercept and filter web requests according to white and black lists.
var onBeforeRequestHandler = function(details) { var onBeforeRequestHandler = function(details) {
@ -40,24 +92,22 @@ var onBeforeRequestHandler = function(details) {
return; return;
} }
var µb = µBlock; // Special handling for root document.
var requestType = details.type; var requestType = details.type;
// Never block root main doc.
if ( requestType === 'main_frame' && details.parentFrameId < 0 ) { if ( requestType === 'main_frame' && details.parentFrameId < 0 ) {
µb.bindTabToPageStats(tabId, details.url); return onBeforeRootDocumentRequestHandler(tabId, details);
return;
} }
// Ignore non-http schemes: I don't think this could ever happened
// because of filters at addListener() time... Will see.
var requestURL = details.url; var requestURL = details.url;
var µburi = µb.URI.set(details.url); if ( requestURL.slice(0, 4) !== 'http' ) {
console.error('onBeforeRequestHandler(): Unexpected scheme!');
// Ignore non-http schemes
var requestScheme = µburi.scheme;
if ( requestScheme.indexOf('http') !== 0 ) {
return; return;
} }
var µb = µBlock;
var µburi = µb.URI.set(requestURL);
var requestHostname = µburi.hostname; var requestHostname = µburi.hostname;
var requestPath = µburi.path; var requestPath = µburi.path;
@ -76,9 +126,7 @@ var onBeforeRequestHandler = function(details) {
var reason = false; var reason = false;
if ( µb.getNetFilteringSwitch(pageStore.pageHostname) ) { if ( µb.getNetFilteringSwitch(pageStore.pageHostname) ) {
//quickProfiler.start('abpFilters.matchString');
reason = µb.abpFilters.matchString(pageStore, requestURL, requestType, requestHostname); reason = µb.abpFilters.matchString(pageStore, requestURL, requestType, requestHostname);
//quickProfiler.stop();
} }
// Record what happened. // Record what happened.
pageStore.recordRequest(requestType, requestURL, reason); pageStore.recordRequest(requestType, requestURL, reason);