Подтвердить что ты не робот

Как проверить, какая вкладка открыла окно (всплывающее окно)?

Проблема

У меня была эта проблема уже несколько месяцев, но концепция довольно проста: я хочу заблокировать некоторые вредоносные сайты ™ из программно открывающих вкладок или всплывающих окон.

С chrome.tabs API, я могу слушать onCreated, когда новая вкладка создана, и , я могу легко проверить, кто (т.е. какая вкладка) открыл эту конкретную вкладку, обращаясь к свойству openerTabId Tab объект, переданный функции обратного вызова.

Теперь я хотел бы сделать то же самое, когда будет создано новое окно. Я хотел бы узнать, какая вкладка открыла окно (если оно есть, потому что оно могло быть открыто пользователь), проверьте его URL-адрес, чтобы узнать, является ли это вредоносным сайтом ™, и действовать соответствующим образом (т.е. блокировать всплывающее окно). Я попытался сделать это точно так же: запросить массив вкладок в новом окне и проверить их свойство openerTabId, но, к сожалению, такое свойство не определено! Я искал документацию и Googled в течение нескольких часов, но, к сожалению, она выглядит как простой способ проверить, кто открыл окно.

Очень неуклюжее решение

Сказанное выше, единственный способ, которым я мог сделать что-то даже удаленно близко к тому, что я действительно хочу, следующее:

  • Каждый раз, когда создается новое окно, его идентификатор добавляется в массив с именем windowWatchlist.
  • Каждый раз, когда вкладка обновляется (NB: обновляется, не создается), внутри нее вводится script, чтобы проверить ее document.referrer, которая должна содержать URL-адрес сайта, который открыл вкладку: если URL-адрес реферера содержит адрес вредоносного сайта ™. Я хочу заблокировать всплывающие окна, окно затем закрывается и удаляется из windowWatchlist.
  • Каждый раз, когда окно закрывается, если его идентификатор находится в windowWatchlist, он удаляется из него.

Здесь код (который работает в моем background.js script):

// 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);

Теперь вам может быть интересно: зачем вам нужен весь этот беспорядок только для проверки реферера? Не могли бы вы просто проверить вкладки, содержащиеся в окне при открытии окна, и проверить их referrer непосредственно внутри обратного вызова chrome.window.onCreated? Это умный вопрос, и ответ прост: проблема в том, что я не могу проверить ссылку на вкладки правильно, когда они созданы, потому что они почти всегда нуждаются в некотором времени для загрузки, а referrer isn 't загружается, пока страница не начнет загружаться внутри вкладки. Поэтому мне нужно проверить, обновляется ли вкладка, видеть, находится ли его окно в моем списке наблюдения, а затем проверить его реферер. Вот почему chrome.tabs.onUpdated необходим, так как он запускает своих слушателей всякий раз, когда вкладка меняет состояние (например, tab.status изменяется от "loading" до "complete").

Почему это решение не работает

Причина, по которой я называю это решение "неуклюжей", и причина, по которой он действительно не работает, должен быть ясен всем, у кого есть опыт работы с JavaScript и веб-разработками: document.referrer не является надежным вообще, и очень часто undefined или (в случае нескольких переадресаций) не правильный. Это приводит к тому, что мой script выходит из строя примерно в 90% случаев, поскольку он не может определить, было ли всплывающее окно открыто Malicious Site ™ или нет.

Кроме того, Malicious Site ™ часто открывает всплывающие окна с URL-адресом about:blank или вообще не содержит URL-адреса, и только когда они загружаются, они вводят в них данные, что делает их в принципе невозможным для обнаружения даже при chrome.tabs.onUpdated t обстрелите любого слушателя в этой ситуации.

Я мог бы решить заблокировать всплывающее окно с URL about:blank или undefined, и это то, что я сейчас делаю, но довольно плохой компромисс, так как в итоге я закрываю всплывающие окна, открытые на любом сайте который использует этот метод, а не только Malicious Site ™, который я хочу заблокировать.

В заключение

Мой вопрос прост, но я не знаю его решения: Кто-нибудь знает какой-либо другой более надежный метод, который можно было бы использовать для определения того, кто открыл новое окно? Ничего не приходит в голову, возможно, что-то может быть возможно с помощью chrome.webRequest API? Я действительно не знаю. В течение нескольких месяцев я принимал тот факт, что простое решение просто невозможно, и беспомощно ждало обновления или что-то в этом роде, но я никогда не думал об этом здесь, потому что проблема была выше компетенции среднего программиста расширения Chrome, но, надеюсь, я ошибся.


UPDATE: Решение для инъекции script внутри сайта и замена функции window.open чем-то другим нецелесообразно: если <iframe> загружается без атрибута src, но с уже написанной DOM внутри srcdoc, Chrome не будет выполнять содержимое script внутри него, даже если вызов chrome.tabs.executeScript выполняется с помощью allFrames: true, и даже если содержимое script объявлено внутри манифеста расширения.

4b9b3361

Ответ 1

Поскольку вы уже выполняете инъекцию кода, это то, что я сделал бы.

Введите код для переопределения window.open и пусть он window.postMessage в дочернем окне сообщает им, кто их открыл. Также нужно будет ввести код, чтобы прослушать эффект window.addEventListener('message', messageHandler), который решил, должны ли они window.close().

На втором, хотя я думаю, что я бы просто переопределил window.open и даже не открыл дочерние окна, если вы не хотите разрешать открывать сайт для открытия.