从 iframe 发送消息 and/or 获取选项卡焦点事件的通知

Sending a message from an iframe and/or getting notification of a tab focus event

我需要一种方法来检测选项卡(在 Chrome 中)是否具有焦点。

我试过这个:

window.addEventListener("focus",function(){
    console.log("Focus event fired")
});

但该事件仅在用户单击页面某处后触发。我需要它在用户单击选项卡 header 时触发,使该选项卡成为焦点。经过一些研究,我找到了 visibilitychange 事件,它做了我需要的,但只在 HTML5 页面上。所以我想我可以动态创建一个包含事件侦听器的 iframe(带有 <!DOCTYPE html> 声明)并将其注入网页:

var iframeId = "pmIframeId";
var iframe = document.createElement("iframe");
iframe.id = iframeId;
document.body.appendChild(iframe);

// Set up the iframe structure and declare it HTML5
var idocument = iframe.contentDocument;
idocument.open();
idocument.write("<!DOCTYPE html>");
idocument.write("<html>");
idocument.write("<head></head>");
idocument.write("<body>");

// Write the event listener code to the iframe
var source = chrome.extension.getURL("pmIframe.js");
idocument.write("<script src='"+source+"'></script>");
idocument.write("</body>");
idocument.write("</html>");
idocument.close();

pmIframe.js 的源代码是:

function setup(){
    console.log("iframe dom loaded")    // This does indeed write to the console
    document.addEventListener('visibilitychange', function(){
        var obj = {};
        obj.action = 'visibilitychange';

        // The following two lines are hardcoded just for testing
        // but refer to a real extension id and an active tab
        var extId = 'jbkncfmkbfgbfcjhchonlpbgajopfbgc';
        var tabId = '17';

        // The following two lines appear to execute (no errors), but my
        // background nor content pages ever get the message
        chrome.runtime.sendMessage(tabId, obj, function(){});
        chrome.runtime.sendMessage(extId, obj, function(){});
    });
}
window.addEventListener('DOMContentLoaded', setup);

我很确定邮件没有被发送,因为我的 manifest.json 不包含 externally_connectable 密钥。但即使是这样,指定的值也必须至少是二级域 - 不允许使用“*” - 这必须适用于所有页面。

我的问题是:我可以从我创建并注入网页的 iframe 发送消息吗?有没有更好的方法来检测选项卡焦点事件?

您可以监听 chrome.tabs.onActivated 事件,它会在 window 中的活动选项卡更改时触发。

chrome.tabs.onActivated.addListener(function(activeInfo) {
    console.log("Active tab has changed");
});