[英]How can I check which tab opened a (popup) window?
I've had this issue for months now, but the concept is pretty straightforward: I want to block some Malicious Site™ from programmatically opening tabs or popup windows.我已经有这个问题几个月了,但这个概念非常简单:我想阻止一些 Malicious Site™ 以编程方式打开选项卡或弹出窗口。
With the chrome.tabs
API , I can listen with onCreated
when a new tab is created, and I can easily check who (ie which tab) opened that particular tab accessing the openerTabId
property of the Tab
object passed to the callback function.使用
chrome.tabs
API ,我可以在创建新选项卡时使用onCreated
进行侦听,并且我可以轻松检查谁(即哪个选项卡)打开了该特定选项卡,访问传递给回调函数的Tab
对象的openerTabId
属性。
Now, I would like to do the exact same thing when a new window is created : I would like to know which tab opened the window (if any, because it could have been opened by the user too), check its URL to see if it is the Malicious Site™, and act accordingly (ie block the popup).现在,我想在创建新窗口时做完全相同的事情:我想知道哪个选项卡打开了窗口(如果有,因为它也可能被用户打开),检查它的 URL 以查看是否它是 Malicious Site™,并采取相应措施(即阻止弹出窗口)。 I tried doing it in the exact same way: request the array of tabs in the new window and check their
openerTabId
property, but unfortunately such property is not defined!我尝试以完全相同的方式执行此操作:在新窗口中请求选项卡数组并检查其
openerTabId
属性,但不幸的是未定义此类属性! I searched the documentation and Googled for hours, but sadly it looks like there's no simple way to check who opened a window.我搜索了文档并用谷歌搜索了几个小时,但遗憾的是,似乎没有简单的方法来检查谁打开了一个窗口。
Stated the above, the only way I was able to do something even remotely close to what I really want, is the following:如上所述,我能够做一些甚至远接近我真正想要的事情的唯一方法是:
windowWatchlist
.windowWatchlist
的数组中。document.referrer
, which should contain the URL of the site which opened the tab: if the referrer URL contains the address of the Malicious Site™ I want to block popups from, the window is then closed and removed from the windowWatchlist
.document.referrer
,其中应包含打开该选项卡的站点的 URL:如果引用 URL 包含恶意站点™ 我想阻止弹出窗口,然后关闭窗口并将其从windowWatchlist
删除。windowWatchlist
, it gets removed from it.windowWatchlist
,它就会从中删除。 Here's the code (which runs in my background.js
script):这是代码(在我的
background.js
脚本中运行):
// Called on chrome.windows.onCreated
function watchPopupWindow(window) {
windowWatchlist.push(window.id);
console.log('Added window #' + window.id + ' to watchlist.');
}
// Called on chrome.windows.onRemoved
function unwatchPopupWindow(windowID) {
var index = windowWatchlist.indexOf(windowID);
// If the windowID is in the watchlist:
if (index != -1) {
// Remove it:
windowWatchlist.splice(index, 1);
console.log('Removed window #' + windowID + ' from watchlist.');
}
}
// Called on chrome.tabs.onUpdated
function blockPopupWindow(tabID, info, tab) {
// If this tab is in a window which is in the watchlist:
if (windowWatchlist.indexOf(tab.windowId) != -1 && info.url && info.url != 'about:blank') {
// Check the referrer of this tab:
chrome.tabs.executeScript(tabID, {code: 'document.referrer;'}, function(ref) {
// If the referrer is the malicious site to block:
if (ref && ref[0] && ref[0].indexOf("http://MALICIOUS-SITE.XXX") != -1) {
// Close the popup window:
chrome.windows.remove(tab.windowId, function() {
console.log('Blocked popup window #' + tab.windowId + '.');
if (chrome.runtime.lastError)
console.error(chrome.runtime.lastError.message);
});;
}
});
}
}
var windowWatchlist = [];
chrome.windows.onCreated.addListener(watchPopupWindow, {windowTypes: ['popup']});
chrome.windows.onRemoved.addListener(unwatchPopupWindow, {windowTypes: ['popup']});
chrome.tabs.onUpdated.addListener(blockPopupWindow);
Now, you may be wondering: why do you need all this mess only to check a referrer?现在,您可能想知道:为什么只需要检查引用者就需要所有这些混乱? Couldn't you just check the tabs contained in the window when the window is opened and check their referrer directly inside the callback of
chrome.window.onCreated
?难道你不能在窗口打开时检查窗口中包含的选项卡,并直接在
chrome.window.onCreated
的回调中检查它们的引用吗? That's a clever question, and the answer is simple: the problem is that I cannot check the referrer of the tabs right when they are created, because they almost always need some time to load , and the referrer isn't loaded until the page starts loading inside the tab.这是一个聪明的问题,答案很简单:问题是我无法在创建选项卡时立即检查它们的引用,因为它们几乎总是需要一些时间来加载,并且引用直到页面开始才会加载在选项卡内加载。 Therefore, I need to check when a tab is updated , see if its window is in my watchlist, and then check its referrer.
因此,我需要检查选项卡何时更新,查看其窗口是否在我的监视列表中,然后检查其引用。 This is why
chrome.tabs.onUpdated
is needed, since it fires its listeners whenever a tab changes state (eg tab.status
changes from "loading"
to "complete"
).这就是需要
chrome.tabs.onUpdated
原因,因为它会在选项卡更改状态时触发其侦听器(例如tab.status
从"loading"
更改为"complete"
)。
The reason why I call this solution "clumsy" and the reason why it doesn't really work should be already clear to anyone with some experience of JavaScript and web developing: document.referrer
isn't reliable at all , and is very often undefined
or (in case of multiple redirects) not the right one.我称此解决方案为“笨拙”的原因以及它实际上不起作用的原因对于具有一些 JavaScript 和 Web 开发经验的人来说应该已经很清楚:
document.referrer
根本不可靠,并且通常是undefined
或者(在多次重定向的情况下)不是正确的。 This makes my script fail about 90% of the times, because it is unable to determine whether the popup window was opened by the Malicious Site™ or not.这使我的脚本在大约 90% 的情况下失败,因为它无法确定弹出窗口是否由 Malicious Site™ 打开。
Moreover, the Malicious Site™ often opens popups with URL about:blank
or no URL at all, and only when they are loaded, injects data into them, making them basically impossible to detect, even with chrome.tabs.onUpdated
which doesn't fire any listener in this situation.此外,Malicious Site™ 经常打开带有 URL
about:blank
或根本没有 URL 的弹出窗口,并且只有在加载它们时才会向其中注入数据,这使得它们基本上无法被检测到,即使使用chrome.tabs.onUpdated
也不行在这种情况下解雇任何侦听器。
I could decide to block any popup with URL about:blank
or undefined
, and this is what I'm doing right now indeed, but is a pretty bad compromise, since that I end up closing popups opened by any site which uses this method, and not only the Malicious Site™ I want to block.我可以决定阻止任何带有 URL
about:blank
或undefined
弹出窗口,这确实是我现在正在做的事情,但这是一个非常糟糕的妥协,因为我最终关闭了任何使用此方法的站点打开的弹出窗口,不仅是我想要阻止的 Malicious Site™。
My question is simple, but I don't know about its solution: does anyone know any other more reliable method which could be used to detect which tab opened a new window?我的问题很简单,但我不知道它的解决方案:有没有人知道其他更可靠的方法可以用来检测哪个选项卡打开了一个新窗口? Nothing comes to my mind, maybe something could be possible using the
chrome.webRequest
API ?我什么都没想,也许可以使用
chrome.webRequest
API chrome.webRequest
什么? I don't really know.我真的不知道。 For months I've been accepting the fact that a simple solution just wasn't possible, and helplessly waited for an update or something, but I never actually thought about asking here, because the problem looked above the competence of an average Chrome Extension programmer, but hopefully I was wrong.
几个月以来,我一直接受一个简单的解决方案是不可能的事实,无奈地等待更新或其他什么,但我从来没有真正想过在这里问,因为这个问题超出了普通 Chrome 扩展程序程序员的能力,但希望我错了。
UPDATE : The solution to inject a script inside the site and replace the window.open
function with something else isn't viable: if an <iframe>
is loaded without a src
attribute, but with an already written DOM inside the srcdoc
attribute, Chrome will not execute a content script inside it, even if the call to chrome.tabs.executeScript
is made with allFrames: true
, and even if the content script is declared inside the extension's manifest.更新:在站点内注入脚本并用其他东西替换
window.open
函数的解决方案是不可行的:如果加载<iframe>
没有src
属性,但在srcdoc
属性中已经写入了 DOM,Chrome不会在其中执行内容脚本,即使对chrome.tabs.executeScript
的调用是使用allFrames: true
,并且即使内容脚本在扩展的清单中声明。
I came across the same problem and found the webNavigation.onCreatedNavigationTarget
event that yields the source tab/frame id when a new window is opened.我遇到了同样的问题,发现
webNavigation.onCreatedNavigationTarget
事件会在打开新窗口时产生源选项卡/框架 ID。
Solution found from this post: Is it possible to determine a tab's opener within a Google Chrome extension?从这篇文章中找到的解决方案: Is it possible to determine a tab's opener within a Google Chrome extension?
Since you are already doing code injection this is what I would do.由于您已经在进行代码注入,这就是我要做的。
Inject code to override window.open
and have it window.postMessage
to child window telling them who opened them.注入代码来覆盖
window.open
并将window.postMessage
传递给子窗口,告诉他们谁打开了它们。 Also will need to inject code to listen to the effect of window.addEventListener('message', messageHandler)
which will decided if they should window.close()
.还需要注入代码来监听
window.addEventListener('message', messageHandler)
的效果,这将决定是否应该使用window.close()
。
On second though I think I would just override window.open
and not even open the child windows if you don't want to allow a give site to open windows.其次,如果您不想让给定站点打开窗口,我认为我只会覆盖
window.open
甚至不打开子窗口。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.