this fixes #99, #991: ability to block popunders

This commit is contained in:
gorhill 2015-11-30 18:50:22 -05:00
parent d2646b68ce
commit c39b892306
2 changed files with 146 additions and 105 deletions

View File

@ -369,6 +369,10 @@ Matrix.prototype.evaluateCellZY = function(srcHostname, desHostname, type) {
// Specific-destination, any party, any type // Specific-destination, any party, any type
var d = desHostname; var d = desHostname;
if ( d === '' ) {
this.r = 0;
return this;
}
while ( d !== '*' ) { while ( d !== '*' ) {
this.y = d; this.y = d;
if ( this.evaluateCellZ(srcHostname, d, '*') !== 0 ) { return this; } if ( this.evaluateCellZ(srcHostname, d, '*') !== 0 ) { return this; }

View File

@ -468,131 +468,168 @@ vAPI.tabs.onClosed = function(tabId) {
/******************************************************************************/ /******************************************************************************/
// https://github.com/chrisaljoudi/uBlock/issues/297 // https://github.com/gorhill/uBlock/issues/99
// https://github.com/gorhill/uBlock/issues/991
//
// popup:
// Test/close target URL
// popunder:
// Test/close opener URL
//
// popup filter match:
// 0 = false
// 1 = true
//
// opener: 0 0 1 1
// target: 0 1 0 1
// ---- ---- ---- ----
// result: a b c d
//
// a: do nothing
// b: close target
// c: close opener
// d: close target
vAPI.tabs.onPopup = function(details) { vAPI.tabs.onPopup = (function() {
//console.debug('vAPI.tabs.onPopup: details = %o', details); //console.debug('vAPI.tabs.onPopup: details = %o', details);
var tabContext = µb.tabContextManager.lookup(details.openerTabId); // The same context object will be reused everytime. This also allows to
var openerURL = ''; // remember whether a popup or popunder was matched.
if ( tabContext.tabId === details.openerTabId ) { var context = {};
openerURL = tabContext.normalURL;
}
if ( openerURL === '' ) {
return;
}
var µburi = µb.URI; var popupMatch = function(openerURL, targetURL, clickedURL) {
var openerHostname = µb.URI.hostnameFromURI(openerURL);
var openerDomain = µb.URI.domainFromHostname(openerHostname);
// https://github.com/gorhill/uBlock/issues/341 context.pageHostname = openerHostname;
// Allow popups if uBlock is turned off in opener's context. context.pageDomain = openerDomain;
if ( µb.getNetFilteringSwitch(openerURL) === false ) { context.rootURL = openerURL;
return; context.rootHostname = openerHostname;
} context.rootDomain = openerDomain;
context.requestURL = targetURL;
context.requestHostname = µb.URI.hostnameFromURI(targetURL);
context.requestType = 'popup';
var targetURL = details.targetURL; // Dynamic filtering makes sense only when we have a valid hostname.
if ( openerHostname !== '' ) {
// Check user switch first
if (
targetURL !== clickedURL &&
µb.hnSwitches.evaluateZ('no-popups', openerHostname)
) {
return 'ub:no-popups: ' + µb.hnSwitches.z + ' true';
}
// If the page URL is that of our "blocked page" URL, extract the URL of // https://github.com/gorhill/uBlock/issues/581
// the page which was blocked. // Take into account popup-specific rules in dynamic URL filtering, OR
if ( targetURL.lastIndexOf(vAPI.getURL('document-blocked.html'), 0) === 0 ) { // generic allow rules.
var matches = /details=([^&]+)/.exec(targetURL); µb.sessionURLFiltering.evaluateZ(openerHostname, targetURL, 'popup');
if ( matches !== null ) { if (
targetURL = JSON.parse(atob(matches[1])).url; µb.sessionURLFiltering.r === 1 && µb.sessionURLFiltering.type === 'popup' ||
µb.sessionURLFiltering.r === 2
) {
return µb.sessionURLFiltering.toFilterString();
}
// https://github.com/gorhill/uBlock/issues/581
// Take into account `allow` rules in dynamic filtering: `block` rules
// are ignored, as block rules are not meant to block specific types
// like `popup` (just like with static filters).
µb.sessionFirewall.evaluateCellZY(openerHostname, context.requestHostname, 'popup');
if ( µb.sessionFirewall.r === 2 ) {
return µb.sessionFirewall.toFilterString();
}
} }
}
var openerHostname = µburi.hostnameFromURI(openerURL); // https://github.com/chrisaljoudi/uBlock/issues/323
var openerDomain = µburi.domainFromHostname(openerHostname); // https://github.com/chrisaljoudi/uBlock/issues/1142
var context = { // Don't block if uBlock is turned off in popup's context
pageHostname: openerHostname, if (
pageDomain: openerDomain, µb.getNetFilteringSwitch(targetURL) &&
rootHostname: openerHostname, µb.staticNetFilteringEngine.matchStringExactType(context, targetURL, 'popup') !== undefined
rootDomain: openerDomain, ) {
requestURL: targetURL, return µb.staticNetFilteringEngine.toResultString(µb.logger.isEnabled());
requestHostname: µb.URI.hostnameFromURI(targetURL), }
requestType: 'popup'
return '';
}; };
var result = ''; return function(details) {
var loggerEnabled = µb.logger.isEnabled(); var tabContext = µb.tabContextManager.lookup(details.openerTabId);
var openerURL = '';
// Check user switch first if ( tabContext.tabId === details.openerTabId ) {
if ( openerURL = tabContext.normalURL;
targetURL !== µb.mouseURL &&
µb.hnSwitches.evaluateZ('no-popups', openerHostname)
) {
result = 'ub:no-popups: ' + µb.hnSwitches.z + ' true';
}
// https://github.com/gorhill/uBlock/issues/581
// Take into account popup-specific rules in dynamic URL filtering, OR
// generic allow rules.
if ( result === '' ) {
µb.sessionURLFiltering.evaluateZ(openerHostname, targetURL, 'popup');
if (
µb.sessionURLFiltering.r === 1 && µb.sessionURLFiltering.type === 'popup' ||
µb.sessionURLFiltering.r === 2
) {
result = µb.sessionURLFiltering.toFilterString();
} }
} if ( openerURL === '' ) {
return;
// https://github.com/gorhill/uBlock/issues/581
// Take into account `allow` rules in dynamic filtering: `block` rules
// are ignored, as block rules are not meant to block specific types
// like `popup` (just like with static filters).
if ( result === '' ) {
µb.sessionFirewall.evaluateCellZY(openerHostname, context.requestHostname, 'popup');
if ( µb.sessionFirewall.r === 2 ) {
result = µb.sessionFirewall.toFilterString();
} }
}
// https://github.com/chrisaljoudi/uBlock/issues/323 // https://github.com/gorhill/uBlock/issues/341
// https://github.com/chrisaljoudi/uBlock/issues/1142 // Allow popups if uBlock is turned off in opener's context.
// Don't block if uBlock is turned off in popup's context if ( µb.getNetFilteringSwitch(openerURL) === false ) {
if ( return;
result === '' && }
µb.getNetFilteringSwitch(targetURL) &&
µb.staticNetFilteringEngine.matchStringExactType(context, targetURL, 'popup') !== undefined
) {
result = µb.staticNetFilteringEngine.toResultString(loggerEnabled);
}
// https://github.com/chrisaljoudi/uBlock/issues/91 var targetURL = details.targetURL;
var pageStore = µb.pageStoreFromTabId(details.openerTabId);
if ( pageStore ) {
pageStore.logRequest(context, result);
}
if ( loggerEnabled ) { // If the page URL is that of our "blocked page" URL, extract the URL of
µb.logger.writeOne( // the page which was blocked.
details.openerTabId, if ( targetURL.lastIndexOf(vAPI.getURL('document-blocked.html'), 0) === 0 ) {
'net', var matches = /details=([^&]+)/.exec(targetURL);
result, if ( matches !== null ) {
'popup', targetURL = JSON.parse(atob(matches[1])).url;
targetURL, }
openerHostname, }
openerHostname
);
}
// Not blocked // Popup test.
if ( µb.isAllowResult(result) ) { var openerTabId = details.openerTabId;
return; var targetTabId = details.targetTabId;
} var result = popupMatch(openerURL, targetURL, µb.mouseURL);
// Blocked // Popunder test.
if ( µb.userSettings.showIconBadge ) { if ( result === '' ) {
µb.updateBadgeAsync(details.openerTabId); openerTabId = details.targetTabId;
} targetTabId = details.openerTabId;
result = popupMatch(targetURL, openerURL, µb.mouseURL);
}
// It is a popup, block and remove the tab. // Log only for when there was a hit against an actual filter (allow or block).
µb.unbindTabFromPageStats(details.targetTabId); if ( result !== '' && µb.logger.isEnabled() ) {
vAPI.tabs.remove(details.targetTabId); µb.logger.writeOne(
openerTabId,
'net',
result,
'popup',
context.requestURL,
µb.URI.hostnameFromURI(context.rootURL),
µb.URI.hostnameFromURI(context.rootURL)
);
}
return true; // Not blocked
}; if ( µb.isAllowResult(result) ) {
return;
}
// Only if a popup was blocked do we report it in the dynamic
// filtering pane.
var pageStore = µb.pageStoreFromTabId(openerTabId);
if ( pageStore ) {
pageStore.logRequest(context, result);
}
// Blocked
if ( µb.userSettings.showIconBadge ) {
µb.updateBadgeAsync(openerTabId);
}
// It is a popup, block and remove the tab.
µb.unbindTabFromPageStats(targetTabId);
vAPI.tabs.remove(targetTabId);
return true;
};
})();
vAPI.tabs.registerListeners(); vAPI.tabs.registerListeners();