从后台脚本发送到内容脚本的消息重复

问题描述 投票:0回答:2

我正在编写一个谷歌浏览器扩展程序,可以单击链接和按钮。单击重定向按钮/链接并且页面发生更改后,我必须使用后台脚本撤销扩展。问题是该消息仅指示后台脚本中发送了一条消息,但内容脚本中的 onMessage 侦听器收到了两条消息。怎么解决这个问题?

背景.js

chrome.webNavigation.onCompleted.addListener((details) => {
  chrome.tabs &&
    chrome.tabs.query({ active: true, currentWindow: true }, () => {
      setTimeout(() => {
        const storage = chrome.storage.local;
        storage.get("activeProcess", (result) => {
          let activeProcess = Object.values(result)[0];
          if (activeProcess && details.frameType === "outermost_frame") {
            const tabId = details.tabId;
            storage.get("message", (result) => {
              result.message.url = details.url;
              result.message.source = "background";
              console.log("message sent");
              chrome.tabs.sendMessage(tabId, result.message, (res) => {
                console.log(res);
              });
            });
          }
        });
      }, 100);
    });
  return true;
});

message sent

内容.js



chrome.runtime.onMessage.addListener(messagesListener);

async function messagesListener(message, sender, response) {
  await processMessage(message, sender, response);
}

export const processMessage = async (message, sender, response) => {
  console.log("message received")
}

message received message received

javascript google-chrome-extension content-script
2个回答
0
投票
  1. 预渲染选项卡也会被报告,然后它会变为活动状态并再次被报告。

    解决方法:检查

    documentLifecycle参数
    中的
    details

  2. chrome.tabs.sendMessage 发送到选项卡的所有框架,因此如果您的内容脚本被注入到所有框架中,每个实例都将收到消息的副本。

    解决方案:在 sendMessage 选项参数中显式使用事件的

    frameId

  3. 如果您使用 chrome.scripting.executeScript 注入,它可能会运行两次。

    解决方案:首先发送消息以验证内容脚本运行或检查内容脚本内的全局变量(示例)。

chrome.webNavigation.onCompleted.addListener(d => {
  if (d.frameType !== 'outermost_frame' || d.documentLifecycle !== 'active')
    return;
  setTimeout(async () => {
    const {activeProcess, message} = await chrome.storage.local.get(
      ['activeProcess', 'message']);
    if (!activeProcess) return;
    message.url = d.url;
    message.source = 'background';
    const res = await chrome.tabs.sendMessage(d.tabId, message, {frameId: d.frameId});
    console.log(res);
  }, 100);
});

0
投票

您所需要做的就是仅在主机中监听消息。


// Check if the current window is top-level and not in an iframe
if (window.self === window.top && window.frameElement === null) {
    // listen to messages from background
    chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {

        // Handle the received message
    });
}
© www.soinside.com 2019 - 2024. All rights reserved.