如何查看哪个选项卡打开(弹出)窗口?

Mar*_*lli 17 javascript google-chrome-extension

问题

我已经有好几个月的问题,但这个概念很简单:我想阻止一些恶意网站™以编程方式打开标签或弹出窗口.

使用chrome.tabsAPI,我可以onCreated在创建新选项卡时监听,并且我可以轻松地检查谁(即哪个选项卡)打开该特定选项卡访问openerTabIdTab传递给回调函数对象属性.

现在,我想在创建一个新窗口时做同样的事情:我想知道哪个选项卡打开了窗口(如果有的话,因为它也可能已被用户打开),检查其URL以查看是否它是恶意网站™,并采取相应行动(即阻止弹出窗口).我尝试以完全相同的方式执行它:请求新窗口中的选项卡数组并检查它们的openerTabId属性,但不幸的是这样的属性没有定义!我搜索了文档和谷歌搜索几个小时,但遗憾的是,看起来没有简单的方法来检查谁打开了一个窗口.

一个非常笨拙的解决方案

说明以上内容,我能够做到甚至远远接近我真正想要的东西的唯一方法是:

  1. 每一个新的时间窗口创建,其ID被添加到称为阵列windowWatchlist.
  2. 每一个时间更新(注意:更新,而不是创建),脚本注入里面,以检查它document.referrer,它应该包含哪些打开的标签网站的URL:如果参照网址包含恶意网站™的地址我想阻止弹出窗口,然后关闭窗口并从中删除windowWatchlist.
  3. 每一个时间窗口关闭,如果它的ID是在windowWatchlist,它会从它删除.

这是代码(在我的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);
Run Code Online (Sandbox Code Playgroud)

现在,你可能想知道:为什么你只需要检查推荐人所有这些混乱?难道你不能只是在窗口打开时检查窗口中包含的选项卡,并在回调中直接检查他们的引用者chrome.window.onCreated?这是一个聪明的问题,答案很简单:问题是我无法在创建选项卡时检查它们的引用者,因为它们几乎总是需要一些时间来加载,并且在页面启动之前不会加载引用者在标签内加载.因此,我需要检查选项卡何时更新,查看其窗口是否在我的监视列表中,然后检查其引用者.这就是chrome.tabs.onUpdated需要的原因,因为只要选项卡改变状态(例如tab.status从更改"loading"到状态"complete"),它就会触发其监听器.

为什么这个解决方案不起作用

我之所以称这个解决方案"笨拙"并且之所以没有真正起作用的原因应该已经让任何具有JavaScript和网络开发经验的人都清楚了:document.referrer根本不可靠,并且经常undefined或(以防万一)多个重定向)不是正确的重定向.这使得我的脚本在大约90%的时间内失败,因为它无法确定弹出窗口是否被恶意网站™打开.

此外,Malicious Site™通常会打开带有URL about:blank或没有URL的弹出窗口,并且只有在加载它们时才会向其中注入数据,使得它们基本上无法检测到,即使chrome.tabs.onUpdated在这种情况下不会触发任何侦听器.

我可以决定阻止与URL任何弹出about:blank或者undefined,这是我在做什么,现在确实是,但是是一个非常糟糕的妥协,因为我最终通过使用此方法的任何站点打开关闭弹出窗口,而不是只恶意网站™我想阻止.

结论

我的问题很简单,但我不知道它的解决方案:有没有人知道任何其他更可靠的方法,可用于检测谁打开了一个新窗口?我没有想到任何事情,也许使用chrome.webRequestAPI可以实现某些目标?我真的不知道.几个月来,我一直在接受这样一个事实:一个简单的解决方案是不可能的,并且无助地等待更新或其他什么,但我从来没有想过要问这里,因为问题看起来高于一般Chrome扩展程序员的能力,但希望我错了.


更新:在站点内部注入脚本并window.open用其他东西替换该函数的解决方案是不可行的:如果<iframe>加载时没有src属性,但在srcdoc属性中已经写入了DOM ,Chrome将不会在其中执行内容脚本,即使调用chrome.tabs.executeScriptallFrames: true,即使内容脚本在扩展的清单中声明.

小智 3

我遇到了同样的问题,并发现webNavigation.onCreatedNavigationTarget打开新窗口时产生源选项卡/框架 ID 的事件。

从这篇文章中找到的解决方案:Is it possible to certain a tab's opener inside a Google Chrome extension?


归档时间:

查看次数:

1062 次

最近记录:

7 年,6 月 前