mirror of
https://github.com/gorhill/uBlock.git
synced 2024-10-06 09:37:12 +02:00
Match static popup filter against local context
Related feedback: - https://www.reddit.com/r/uBlockOrigin/comments/d6zbqv/ For static filter `popup` filter purpose, the URL of the embedded frame from which the popup was launched will be used in the matching algorithm.
This commit is contained in:
parent
d15163d3bb
commit
f204d24bf4
@ -260,10 +260,7 @@ vAPI.Tabs = class {
|
|||||||
details.url = this.sanitizeURL(details.url);
|
details.url = this.sanitizeURL(details.url);
|
||||||
this.onNavigation(details);
|
this.onNavigation(details);
|
||||||
}
|
}
|
||||||
this.onCreated(
|
this.onCreated(details);
|
||||||
details.tabId,
|
|
||||||
details.sourceTabId
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
browser.webNavigation.onCommitted.addListener(details => {
|
browser.webNavigation.onCommitted.addListener(details => {
|
||||||
@ -592,7 +589,7 @@ vAPI.Tabs = class {
|
|||||||
onClosed(/* tabId, details */) {
|
onClosed(/* tabId, details */) {
|
||||||
}
|
}
|
||||||
|
|
||||||
onCreated(/* openedTabId, openerTabId */) {
|
onCreated(/* details */) {
|
||||||
}
|
}
|
||||||
|
|
||||||
onNavigation(/* details */) {
|
onNavigation(/* details */) {
|
||||||
@ -655,7 +652,7 @@ if ( browser.windows instanceof Object ) {
|
|||||||
// Ensure ImageData for toolbar icon is valid before use.
|
// Ensure ImageData for toolbar icon is valid before use.
|
||||||
|
|
||||||
vAPI.setIcon = (( ) => {
|
vAPI.setIcon = (( ) => {
|
||||||
const browserAction = browser.browserAction;
|
const browserAction = webext.browserAction;
|
||||||
const titleTemplate =
|
const titleTemplate =
|
||||||
browser.runtime.getManifest().browser_action.default_title +
|
browser.runtime.getManifest().browser_action.default_title +
|
||||||
' ({badge})';
|
' ({badge})';
|
||||||
|
@ -32,7 +32,9 @@ const promisifyNoFail = function(thisArg, fnName, outFn = r => r) {
|
|||||||
return function() {
|
return function() {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
fn.call(thisArg, ...arguments, function() {
|
fn.call(thisArg, ...arguments, function() {
|
||||||
void chrome.runtime.lastError;
|
if ( chrome.runtime.lastError instanceof Object ) {
|
||||||
|
void chrome.runtime.lastError.message;
|
||||||
|
}
|
||||||
resolve(outFn(...arguments));
|
resolve(outFn(...arguments));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -55,6 +57,14 @@ const promisify = function(thisArg, fnName) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const webext = {
|
const webext = {
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/browserAction
|
||||||
|
browserAction: {
|
||||||
|
onClicked: chrome.browserAction.onClicked,
|
||||||
|
setBadgeBackgroundColor: promisifyNoFail(chrome.browserAction, 'setBadgeBackgroundColor'),
|
||||||
|
setBadgeText: promisifyNoFail(chrome.browserAction, 'setBadgeText'),
|
||||||
|
setIcon: promisifyNoFail(chrome.browserAction, 'setIcon'),
|
||||||
|
setTitle: promisifyNoFail(chrome.browserAction, 'setTitle'),
|
||||||
|
},
|
||||||
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/menus
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/menus
|
||||||
menus: {
|
menus: {
|
||||||
create: function() {
|
create: function() {
|
||||||
@ -89,6 +99,10 @@ const webext = {
|
|||||||
remove: promisifyNoFail(chrome.tabs, 'remove'),
|
remove: promisifyNoFail(chrome.tabs, 'remove'),
|
||||||
update: promisifyNoFail(chrome.tabs, 'update', tab => tab instanceof Object ? tab : null),
|
update: promisifyNoFail(chrome.tabs, 'update', tab => tab instanceof Object ? tab : null),
|
||||||
},
|
},
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webNavigation
|
||||||
|
webNavigation: {
|
||||||
|
getFrame: promisify(chrome.webNavigation, 'getFrame'),
|
||||||
|
},
|
||||||
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows
|
||||||
windows: {
|
windows: {
|
||||||
get: promisifyNoFail(chrome.windows, 'get', win => win instanceof Object ? win : null),
|
get: promisifyNoFail(chrome.windows, 'get', win => win instanceof Object ? win : null),
|
||||||
|
109
src/js/tab.js
109
src/js/tab.js
@ -103,12 +103,13 @@
|
|||||||
|
|
||||||
const popupMatch = function(
|
const popupMatch = function(
|
||||||
fctxt,
|
fctxt,
|
||||||
openerURL,
|
rootOpenerURL,
|
||||||
|
localOpenerURL,
|
||||||
targetURL,
|
targetURL,
|
||||||
popupType
|
popupType = 'popup'
|
||||||
) {
|
) {
|
||||||
fctxt.setTabOriginFromURL(openerURL)
|
fctxt.setTabOriginFromURL(rootOpenerURL)
|
||||||
.setDocOriginFromURL(openerURL)
|
.setDocOriginFromURL(localOpenerURL || rootOpenerURL)
|
||||||
.setURL(targetURL)
|
.setURL(targetURL)
|
||||||
.setType('popup');
|
.setType('popup');
|
||||||
let result;
|
let result;
|
||||||
@ -231,10 +232,17 @@
|
|||||||
|
|
||||||
const popunderMatch = function(
|
const popunderMatch = function(
|
||||||
fctxt,
|
fctxt,
|
||||||
openerURL,
|
rootOpenerURL,
|
||||||
|
localOpenerURL,
|
||||||
targetURL
|
targetURL
|
||||||
) {
|
) {
|
||||||
let result = popupMatch(fctxt, targetURL, openerURL, 'popunder');
|
let result = popupMatch(
|
||||||
|
fctxt,
|
||||||
|
targetURL,
|
||||||
|
undefined,
|
||||||
|
rootOpenerURL,
|
||||||
|
'popunder'
|
||||||
|
);
|
||||||
if ( result === 1 ) { return result; }
|
if ( result === 1 ) { return result; }
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/1010#issuecomment-186824878
|
// https://github.com/gorhill/uBlock/issues/1010#issuecomment-186824878
|
||||||
@ -243,7 +251,7 @@
|
|||||||
// a broad one, we will consider the opener tab to be a popunder tab.
|
// a broad one, we will consider the opener tab to be a popunder tab.
|
||||||
// For now, a "broad" filter is one which does not touch any part of
|
// For now, a "broad" filter is one which does not touch any part of
|
||||||
// the hostname part of the opener URL.
|
// the hostname part of the opener URL.
|
||||||
let popunderURL = openerURL,
|
let popunderURL = rootOpenerURL,
|
||||||
popunderHostname = µb.URI.hostnameFromURI(popunderURL);
|
popunderHostname = µb.URI.hostnameFromURI(popunderURL);
|
||||||
if ( popunderHostname === '' ) { return 0; }
|
if ( popunderHostname === '' ) { return 0; }
|
||||||
|
|
||||||
@ -251,7 +259,7 @@
|
|||||||
fctxt,
|
fctxt,
|
||||||
popunderURL,
|
popunderURL,
|
||||||
popunderHostname,
|
popunderHostname,
|
||||||
popupMatch(fctxt, targetURL, popunderURL, 'popup')
|
popupMatch(fctxt, targetURL, undefined, popunderURL)
|
||||||
);
|
);
|
||||||
if ( result !== 0 ) { return result; }
|
if ( result !== 0 ) { return result; }
|
||||||
|
|
||||||
@ -264,7 +272,7 @@
|
|||||||
fctxt,
|
fctxt,
|
||||||
popunderURL,
|
popunderURL,
|
||||||
popunderHostname,
|
popunderHostname,
|
||||||
popupMatch(fctxt, targetURL, popunderURL, 'popup')
|
popupMatch(fctxt, targetURL, undefined, popunderURL)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -273,8 +281,11 @@
|
|||||||
const openerTabId = openerDetails.tabId;
|
const openerTabId = openerDetails.tabId;
|
||||||
let tabContext = µb.tabContextManager.lookup(openerTabId);
|
let tabContext = µb.tabContextManager.lookup(openerTabId);
|
||||||
if ( tabContext === null ) { return; }
|
if ( tabContext === null ) { return; }
|
||||||
const openerURL = tabContext.rawURL;
|
const rootOpenerURL = tabContext.rawURL;
|
||||||
if ( openerURL === '' ) { return; }
|
if ( rootOpenerURL === '' ) { return; }
|
||||||
|
const localOpenerURL = openerDetails.frameId !== 0
|
||||||
|
? openerDetails.frameURL
|
||||||
|
: undefined;
|
||||||
|
|
||||||
// Popup details.
|
// Popup details.
|
||||||
tabContext = µb.tabContextManager.lookup(targetTabId);
|
tabContext = µb.tabContextManager.lookup(targetTabId);
|
||||||
@ -283,21 +294,20 @@
|
|||||||
if ( targetURL === '' ) { return; }
|
if ( targetURL === '' ) { return; }
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/341
|
// https://github.com/gorhill/uBlock/issues/341
|
||||||
// Allow popups if uBlock is turned off in opener's context.
|
// Allow popups if uBlock is turned off in opener's context.
|
||||||
if ( µb.getNetFilteringSwitch(openerURL) === false ) { return; }
|
if ( µb.getNetFilteringSwitch(rootOpenerURL) === false ) { return; }
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/1538
|
// https://github.com/gorhill/uBlock/issues/1538
|
||||||
if (
|
if (
|
||||||
µb.getNetFilteringSwitch(µb.normalizePageURL(
|
µb.getNetFilteringSwitch(
|
||||||
openerTabId,
|
µb.normalizePageURL(openerTabId, rootOpenerURL)
|
||||||
openerURL)
|
|
||||||
) === false
|
) === false
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the page URL is that of our "blocked page" URL, extract the URL of
|
// If the page URL is that of our "blocked page" URL, extract the URL
|
||||||
// the page which was blocked.
|
// of the page which was blocked.
|
||||||
if ( targetURL.startsWith(vAPI.getURL('document-blocked.html')) ) {
|
if ( targetURL.startsWith(vAPI.getURL('document-blocked.html')) ) {
|
||||||
const matches = /details=([^&]+)/.exec(targetURL);
|
const matches = /details=([^&]+)/.exec(targetURL);
|
||||||
if ( matches !== null ) {
|
if ( matches !== null ) {
|
||||||
@ -314,12 +324,12 @@
|
|||||||
// https://github.com/gorhill/uBlock/issues/2919
|
// https://github.com/gorhill/uBlock/issues/2919
|
||||||
// - If the target tab matches a clicked link, assume it's legit.
|
// - If the target tab matches a clicked link, assume it's legit.
|
||||||
if ( areDifferentURLs(targetURL, openerDetails.trustedURL) ) {
|
if ( areDifferentURLs(targetURL, openerDetails.trustedURL) ) {
|
||||||
result = popupMatch(fctxt, openerURL, targetURL, 'popup');
|
result = popupMatch(fctxt, rootOpenerURL, localOpenerURL, targetURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Popunder test.
|
// Popunder test.
|
||||||
if ( result === 0 && openerDetails.popunder ) {
|
if ( result === 0 && openerDetails.popunder ) {
|
||||||
result = popunderMatch(fctxt, openerURL, targetURL);
|
result = popunderMatch(fctxt, rootOpenerURL, localOpenerURL, targetURL);
|
||||||
if ( result === 1 ) {
|
if ( result === 1 ) {
|
||||||
popupType = 'popunder';
|
popupType = 'popunder';
|
||||||
}
|
}
|
||||||
@ -332,10 +342,10 @@
|
|||||||
if ( popupType === 'popup' ) {
|
if ( popupType === 'popup' ) {
|
||||||
fctxt.setURL(targetURL)
|
fctxt.setURL(targetURL)
|
||||||
.setTabId(openerTabId)
|
.setTabId(openerTabId)
|
||||||
.setTabOriginFromURL(openerURL)
|
.setTabOriginFromURL(rootOpenerURL)
|
||||||
.setDocOriginFromURL(openerURL);
|
.setDocOriginFromURL(localOpenerURL);
|
||||||
} else {
|
} else {
|
||||||
fctxt.setURL(openerURL)
|
fctxt.setURL(rootOpenerURL)
|
||||||
.setTabId(targetTabId)
|
.setTabId(targetTabId)
|
||||||
.setTabOriginFromURL(targetURL)
|
.setTabOriginFromURL(targetURL)
|
||||||
.setDocOriginFromURL(targetURL);
|
.setDocOriginFromURL(targetURL);
|
||||||
@ -446,12 +456,15 @@ housekeep itself.
|
|||||||
const popupCandidates = new Map();
|
const popupCandidates = new Map();
|
||||||
|
|
||||||
const PopupCandidate = class {
|
const PopupCandidate = class {
|
||||||
constructor(targetTabId, openerTabId) {
|
constructor(createDetails, openerDetails) {
|
||||||
this.targetTabId = targetTabId;
|
this.targetTabId = createDetails.tabId;
|
||||||
this.opener = {
|
this.opener = {
|
||||||
tabId: openerTabId,
|
tabId: createDetails.sourceTabId,
|
||||||
|
tabURL: openerDetails[0].url,
|
||||||
|
frameId: createDetails.sourceFrameId,
|
||||||
|
frameURL: openerDetails[1].url,
|
||||||
popunder: false,
|
popunder: false,
|
||||||
trustedURL: openerTabId === µb.maybeGoodPopup.tabId
|
trustedURL: createDetails.tabId === µb.maybeGoodPopup.tabId
|
||||||
? µb.maybeGoodPopup.url
|
? µb.maybeGoodPopup.url
|
||||||
: ''
|
: ''
|
||||||
};
|
};
|
||||||
@ -477,10 +490,8 @@ housekeep itself.
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const popupCandidateTest = function(targetTabId) {
|
const popupCandidateTest = async function(targetTabId) {
|
||||||
for ( const entry of popupCandidates ) {
|
for ( const [ tabId, candidate ] of popupCandidates ) {
|
||||||
const tabId = entry[0];
|
|
||||||
const candidate = entry[1];
|
|
||||||
if (
|
if (
|
||||||
targetTabId !== tabId &&
|
targetTabId !== tabId &&
|
||||||
targetTabId !== candidate.opener.tabId
|
targetTabId !== candidate.opener.tabId
|
||||||
@ -493,7 +504,8 @@ housekeep itself.
|
|||||||
if ( targetTabId === candidate.opener.tabId ) {
|
if ( targetTabId === candidate.opener.tabId ) {
|
||||||
candidate.opener.popunder = true;
|
candidate.opener.popunder = true;
|
||||||
}
|
}
|
||||||
if ( µb.onPopupUpdated(tabId, candidate.opener) === true ) {
|
const result = await µb.onPopupUpdated(tabId, candidate.opener);
|
||||||
|
if ( result === true ) {
|
||||||
candidate.destroy();
|
candidate.destroy();
|
||||||
} else {
|
} else {
|
||||||
candidate.launchSelfDestruction();
|
candidate.launchSelfDestruction();
|
||||||
@ -501,15 +513,32 @@ housekeep itself.
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onTabCreated = function(targetTabId, openerTabId) {
|
const onTabCreated = async function(createDetails) {
|
||||||
const popup = popupCandidates.get(targetTabId);
|
const { sourceTabId, sourceFrameId, tabId } = createDetails;
|
||||||
|
const popup = popupCandidates.get(tabId);
|
||||||
if ( popup === undefined ) {
|
if ( popup === undefined ) {
|
||||||
|
let openerDetails;
|
||||||
|
try {
|
||||||
|
openerDetails = await Promise.all([
|
||||||
|
webext.webNavigation.getFrame({
|
||||||
|
tabId: createDetails.sourceTabId,
|
||||||
|
frameId: 0,
|
||||||
|
}),
|
||||||
|
webext.webNavigation.getFrame({
|
||||||
|
tabId: sourceTabId,
|
||||||
|
frameId: sourceFrameId,
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
catch (reason) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
popupCandidates.set(
|
popupCandidates.set(
|
||||||
targetTabId,
|
tabId,
|
||||||
new PopupCandidate(targetTabId, openerTabId)
|
new PopupCandidate(createDetails, openerDetails)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
popupCandidateTest(targetTabId);
|
popupCandidateTest(tabId);
|
||||||
};
|
};
|
||||||
|
|
||||||
const gcPeriod = 10 * 60 * 1000;
|
const gcPeriod = 10 * 60 * 1000;
|
||||||
@ -818,9 +847,9 @@ vAPI.Tabs = class extends vAPI.Tabs {
|
|||||||
µBlock.contextMenu.update();
|
µBlock.contextMenu.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
onCreated(targetTabId, openerTabId) {
|
onCreated(details) {
|
||||||
super.onCreated(targetTabId, openerTabId);
|
super.onCreated(details);
|
||||||
µBlock.tabContextManager.onTabCreated(targetTabId, openerTabId);
|
µBlock.tabContextManager.onTabCreated(details);
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the DOM content of root frame is loaded, this means the tab
|
// When the DOM content of root frame is loaded, this means the tab
|
||||||
|
Loading…
Reference in New Issue
Block a user