mirror of https://github.com/gorhill/uBlock.git
this fixes #967
This commit is contained in:
parent
252eb1b4dc
commit
8341fb2193
|
@ -71,6 +71,17 @@ vAPI.noTabId = '-1';
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
var onCreatedNavigationTarget = function(details) {
|
||||
vAPI.tabs.onPopup({
|
||||
openerTabId: details.sourceTabId,
|
||||
openerURL: '',
|
||||
targetURL: details.url,
|
||||
targetTabId: details.tabId
|
||||
});
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.tabs.registerListeners = function() {
|
||||
if ( typeof this.onNavigation === 'function' ) {
|
||||
chrome.webNavigation.onCommitted.addListener(this.onNavigation);
|
||||
|
@ -85,7 +96,7 @@ vAPI.tabs.registerListeners = function() {
|
|||
}
|
||||
|
||||
if ( typeof this.onPopup === 'function' ) {
|
||||
chrome.webNavigation.onCreatedNavigationTarget.addListener(this.onPopup);
|
||||
chrome.webNavigation.onCreatedNavigationTarget.addListener(onCreatedNavigationTarget);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -493,15 +504,6 @@ vAPI.net.registerListeners = function() {
|
|||
this.onBeforeRequest.extra
|
||||
);
|
||||
|
||||
chrome.webRequest.onBeforeSendHeaders.addListener(
|
||||
this.onBeforeSendHeaders.callback,
|
||||
{
|
||||
'urls': this.onBeforeSendHeaders.urls || ['<all_urls>'],
|
||||
'types': this.onBeforeSendHeaders.types || []
|
||||
},
|
||||
this.onBeforeSendHeaders.extra
|
||||
);
|
||||
|
||||
var onHeadersReceivedClient = this.onHeadersReceived.callback;
|
||||
var onHeadersReceived = function(details) {
|
||||
normalizeRequestDetails(details);
|
||||
|
@ -515,6 +517,56 @@ vAPI.net.registerListeners = function() {
|
|||
},
|
||||
this.onHeadersReceived.extra
|
||||
);
|
||||
|
||||
// Intercept root frame requests.
|
||||
// This is where we identify and block popups early, whenever possible.
|
||||
|
||||
var onBeforeSendHeaders = function(details) {
|
||||
// Do not block behind the scene requests.
|
||||
if ( vAPI.isNoTabId(details.tabId) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only root document.
|
||||
if ( details.parentFrameId !== -1 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var referrer = headerValue(details.requestHeaders, 'referer');
|
||||
if ( referrer === '' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var result = vAPI.tabs.onPopup({
|
||||
openerTabId: undefined,
|
||||
openerURL: referrer,
|
||||
targetTabId: details.tabId,
|
||||
targetURL: details.url
|
||||
});
|
||||
|
||||
if ( result ) {
|
||||
return { 'cancel': true };
|
||||
}
|
||||
};
|
||||
|
||||
var headerValue = function(headers, name) {
|
||||
var i = headers.length;
|
||||
while ( i-- ) {
|
||||
if ( headers[i].name.toLowerCase() === name ) {
|
||||
return headers[i].value;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
chrome.webRequest.onBeforeSendHeaders.addListener(
|
||||
onBeforeSendHeaders,
|
||||
{
|
||||
'urls': [ 'http://*/*', 'https://*/*' ],
|
||||
'types': [ 'main_frame' ]
|
||||
},
|
||||
[ 'blocking', 'requestHeaders' ]
|
||||
);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -1118,9 +1118,9 @@ var httpObserver = {
|
|||
}
|
||||
|
||||
var result = vAPI.tabs.onPopup({
|
||||
tabId: tabId,
|
||||
sourceTabId: sourceTabId,
|
||||
url: URI.asciiSpec
|
||||
targetTabId: tabId,
|
||||
openerTabId: sourceTabId,
|
||||
targetURL: URI.asciiSpec
|
||||
});
|
||||
|
||||
return result === true;
|
||||
|
|
|
@ -209,15 +209,15 @@
|
|||
var url = e.url,
|
||||
tabId = vAPI.tabs.getTabId(e.target);
|
||||
var details = {
|
||||
url: url,
|
||||
tabId: tabId,
|
||||
sourceTabId: vAPI.tabs.popupCandidate
|
||||
targetURL: url,
|
||||
targetTabId: tabId,
|
||||
openerTabId: vAPI.tabs.popupCandidate
|
||||
};
|
||||
vAPI.tabs.popupCandidate = false;
|
||||
if(vAPI.tabs.onPopup(details)) {
|
||||
e.preventDefault();
|
||||
if(vAPI.tabs.stack[details.sourceTabId]) {
|
||||
vAPI.tabs.stack[details.sourceTabId].activate();
|
||||
if(vAPI.tabs.stack[details.openerTabId]) {
|
||||
vAPI.tabs.stack[details.openerTabId].activate();
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
|
@ -663,9 +663,9 @@
|
|||
}
|
||||
else {
|
||||
e.message = !vAPI.tabs.onPopup({
|
||||
url: e.message.url,
|
||||
tabId: 0,
|
||||
sourceTabId: vAPI.tabs.getTabId(e.target)
|
||||
targetURL: e.message.url,
|
||||
targetTabId: 0,
|
||||
openerTabId: vAPI.tabs.getTabId(e.target)
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -37,6 +37,7 @@ var µb = µBlock;
|
|||
|
||||
// When the DOM content of root frame is loaded, this means the tab
|
||||
// content has changed.
|
||||
|
||||
vAPI.tabs.onNavigation = function(details) {
|
||||
if ( details.frameId !== 0 ) {
|
||||
return;
|
||||
|
@ -55,9 +56,12 @@ vAPI.tabs.onNavigation = function(details) {
|
|||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// It may happen the URL in the tab changes, while the page's document
|
||||
// stays the same (for instance, Google Maps). Without this listener,
|
||||
// the extension icon won't be properly refreshed.
|
||||
|
||||
vAPI.tabs.onUpdated = function(tabId, changeInfo, tab) {
|
||||
if ( !tab.url || tab.url === '' ) {
|
||||
return;
|
||||
|
@ -68,6 +72,8 @@ vAPI.tabs.onUpdated = function(tabId, changeInfo, tab) {
|
|||
µb.bindTabToPageStats(tabId, changeInfo.url, 'tabUpdated');
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.tabs.onClosed = function(tabId) {
|
||||
if ( tabId < 0 ) {
|
||||
return;
|
||||
|
@ -75,28 +81,49 @@ vAPI.tabs.onClosed = function(tabId) {
|
|||
µb.unbindTabFromPageStats(tabId);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/297
|
||||
|
||||
vAPI.tabs.onPopup = function(details) {
|
||||
//console.debug('vAPI.tabs.onPopup: url="%s"', details.url);
|
||||
|
||||
var pageStore = µb.pageStoreFromTabId(details.sourceTabId);
|
||||
if ( !pageStore ) {
|
||||
var pageStore = µb.pageStoreFromTabId(details.openerTabId);
|
||||
var openerURL = details.openerURL || '';
|
||||
|
||||
if ( openerURL === '' && pageStore ) {
|
||||
openerURL = pageStore.pageURL;
|
||||
}
|
||||
|
||||
if ( openerURL === '' ) {
|
||||
return;
|
||||
}
|
||||
var requestURL = details.url;
|
||||
|
||||
var µburi = µb.URI;
|
||||
var openerHostname = µburi.hostnameFromURI(openerURL);
|
||||
var openerDomain = µburi.domainFromHostname(openerHostname);
|
||||
|
||||
var context = {
|
||||
pageHostname: openerHostname,
|
||||
pageDomain: openerDomain,
|
||||
rootHostname: openerHostname,
|
||||
rootDomain: openerDomain
|
||||
};
|
||||
|
||||
var targetURL = details.targetURL;
|
||||
var result = '';
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/323
|
||||
// If popup URL is whitelisted, do not block it
|
||||
if ( µb.getNetFilteringSwitch(requestURL) ) {
|
||||
result = µb.staticNetFilteringEngine.matchStringExactType(pageStore, requestURL, 'popup');
|
||||
if ( µb.getNetFilteringSwitch(targetURL) ) {
|
||||
result = µb.staticNetFilteringEngine.matchStringExactType(context, targetURL, 'popup');
|
||||
}
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/91
|
||||
if ( result !== '' ) {
|
||||
if ( pageStore ) {
|
||||
var context = {
|
||||
requestURL: requestURL,
|
||||
requestHostname: µb.URI.hostnameFromURI(requestURL),
|
||||
requestURL: targetURL,
|
||||
requestHostname: µb.URI.hostnameFromURI(targetURL),
|
||||
requestType: 'popup'
|
||||
};
|
||||
pageStore.logRequest(context, result);
|
||||
|
@ -110,10 +137,9 @@ vAPI.tabs.onPopup = function(details) {
|
|||
// Blocked
|
||||
|
||||
// It is a popup, block and remove the tab.
|
||||
µb.unbindTabFromPageStats(details.tabId);
|
||||
vAPI.tabs.remove(details.tabId);
|
||||
µb.unbindTabFromPageStats(details.targetTabId);
|
||||
vAPI.tabs.remove(details.targetTabId);
|
||||
|
||||
// for Safari and Firefox
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
|
@ -185,89 +185,6 @@ var onBeforeBehindTheSceneRequest = function(details) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
// Intercept root frame requests. This is where we identify and block popups.
|
||||
|
||||
var onBeforeSendHeaders = function(details) {
|
||||
// TODO: I vaguely remember reading that when pre-fetch is enabled,
|
||||
// the tab id could be -1, despite the request not really being a
|
||||
// behind-the-scene request. If true, the test below would prevent
|
||||
// the popup blocker from working. Need to check this.
|
||||
//console.debug('traffic.js > onBeforeSendHeaders(): "%s" (%o) because "%s"', details.url, details, result);
|
||||
|
||||
// Do not block behind the scene requests.
|
||||
var tabId = details.tabId;
|
||||
if ( vAPI.isNoTabId(tabId) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only root document.
|
||||
if ( details.parentFrameId !== -1 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var µb = µBlock;
|
||||
var requestURL = details.url;
|
||||
|
||||
// Lookup the page store associated with this tab id.
|
||||
var pageStore = µb.pageStoreFromTabId(tabId);
|
||||
if ( !pageStore ) {
|
||||
// This happens under normal circumstances in Opera.
|
||||
return;
|
||||
}
|
||||
|
||||
// Heuristic to determine whether we are dealing with a popup:
|
||||
// - the page store is new (it's not a reused one)
|
||||
// - the referrer is not nil
|
||||
|
||||
// Can't be a popup, the tab was in use previously.
|
||||
if ( pageStore.previousPageURL !== '' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var referrer = headerValue(details.requestHeaders, 'referer');
|
||||
if ( referrer === '' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/323
|
||||
if ( pageStore.getNetFilteringSwitch() === false ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: I think I should test the switch of the referrer instead, not the
|
||||
// switch of the popup. If so, that would require being able to lookup
|
||||
// a page store from a URL. Have to keep in mind the same URL can appear
|
||||
// in multiple tabs.
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/67
|
||||
// We need to pass the details of the page which opened this popup,
|
||||
// so that the `third-party` option works.
|
||||
// Create a synthetic context based on the referrer.
|
||||
var µburi = µb.URI;
|
||||
var referrerHostname = µburi.hostnameFromURI(referrer);
|
||||
var pageDetails = {
|
||||
pageHostname: referrerHostname,
|
||||
pageDomain: µburi.domainFromHostname(referrerHostname)
|
||||
};
|
||||
pageDetails.rootHostname = pageDetails.pageHostname;
|
||||
pageDetails.rootDomain = pageDetails.pageDomain;
|
||||
//console.debug('traffic.js > Referrer="%s"', referrer);
|
||||
var result = µb.staticNetFilteringEngine.matchStringExactType(pageDetails, requestURL, 'popup');
|
||||
|
||||
// Not blocked?
|
||||
if ( µb.isAllowResult(result) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// It is a popup, block and remove the tab.
|
||||
µb.unbindTabFromPageStats(tabId);
|
||||
vAPI.tabs.remove(tabId);
|
||||
|
||||
return { 'cancel': true };
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// To handle `inline-script`.
|
||||
|
||||
var onHeadersReceived = function(details) {
|
||||
|
@ -343,18 +260,6 @@ var onHeadersReceived = function(details) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
var headerValue = function(headers, name) {
|
||||
var i = headers.length;
|
||||
while ( i-- ) {
|
||||
if ( headers[i].name.toLowerCase() === name ) {
|
||||
return headers[i].value;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var headerStartsWith = function(headers, prefix) {
|
||||
var i = headers.length;
|
||||
while ( i-- ) {
|
||||
|
@ -386,18 +291,6 @@ vAPI.net.onBeforeRequest = {
|
|||
callback: onBeforeRequest
|
||||
};
|
||||
|
||||
vAPI.net.onBeforeSendHeaders = {
|
||||
urls: [
|
||||
'http://*/*',
|
||||
'https://*/*'
|
||||
],
|
||||
types: [
|
||||
"main_frame"
|
||||
],
|
||||
extra: [ 'blocking', 'requestHeaders' ],
|
||||
callback: onBeforeSendHeaders
|
||||
};
|
||||
|
||||
vAPI.net.onHeadersReceived = {
|
||||
urls: [
|
||||
'http://*/*',
|
||||
|
|
Loading…
Reference in New Issue