首页 > 解决方案 > content.js 在同一页面的不同框架上的所有单独执行如何相互通信?

问题描述

所以,我正在构建一个自动填充不同类型表单的扩展。由于从 url 中看不出在特定网站上使用哪种形式,我需要匹配清单中的所有 url。我正在尝试通过网页中的“src”属性检测表单。

某种形式的某些字段不在第一帧中。所以“all_frames”在我的清单中必须是真的。这意味着 content.js 会为每个框架或 iFrame 触发一次。

**content.js:**

async function checkForPaymentType(value, attribute = 'src') {
    return document.querySelectorAll(`[${attribute}*="${value}"]`);
}

let hasThisForm;

document.addEventListener('DOMContentLoaded', () => {
    checkForPaymentType('formJs.js').then((value) => {    
    if(value.length) {
        hasThisForm = true;
    }
    if(hasThisForm)
        fillForm();
    });
});

现在的问题是,只有第一帧在其一个元素中具有“src='formJs.js”属性。所以它只填写第一帧中的那些字段。

我的解决思路

我想做的是某种只能设置为真的全局布尔变量('hasThisForm')。因此,一旦第一个框架检测到网站上有表单,其他框架也会触发 fillForm()。

问题

1.我无法设置可以从所有执行中读取的变量。

2.我需要 content.js 的其他执行来等待第一个。

另一种解决方案是使用某种 window.querySelectorAll,因此 content.js 的每次执行都会在整个页面中搜索,而不仅仅是在其框架中。

提前致谢:)

标签: javascriptgoogle-chrome-extensionbackground

解决方案


所以我想通了。正如@wOxxOm 的评论或这个问题(如何让所有框架访问一个全局变量)中指出的那样,您需要通过后台页面管理所有内容。

您想在每个 Frame 中设置一个侦听器并仅从顶部框架发送消息(到将其发送回整个选项卡的背景页面)。

经过数小时的尝试,我注意到当来自 topFrame 的消息被发送时,听众甚至还没有准备好。我在发送消息之前放了一个卧铺,我猜这不是理想的方式。但是没有“listenerIsSet-Event”。

这是我的代码:

内容.js

document.addEventListener('DOMContentLoaded', () => {

    chrome.runtime.onMessage.addListener(
        function (msgFromTopFrame) {
            console.log(msgFromTopFrame)
        });

    if (window === top) {

        Sleep(1000).then(() => {
            const msgToOtherFrames = {'greeting': 'hello'};
            chrome.runtime.sendMessage(msgToOtherFrames);
        });

    }
});

背景.js

chrome.runtime.onMessage.addListener((msg, sender) => {
    if(('greeting' in msg)) {
        chrome.tabs.sendMessage(sender.tab.id, msg);  
    }
});

您可能希望根据收到的值执行一些代码。您只能在侦听器中编写一次。它将在包括顶部帧在内的所有帧中执行,因为 background.js 将其发送到选项卡中的所有帧。

注意:此代码中“发送”的消息中的字典/键可能存在一些错误。只需将消息记录在所有侦听器中即可获得正确的表达式。


推荐阅读