【问题标题】:In a browser extension using manifest v3, how can I communicate between a content script and a devtools panel?在使用 manifest v3 的浏览器扩展中,如何在内容脚本和开发工具面板之间进行通信?
【发布时间】:2022-07-08 02:26:45
【问题描述】:

我正在开发一个新的浏览器扩展程序,这意味着要在 Chrome 网上应用店 I must use manifest v3 上公开提供它。我的扩展是 DevTools 扩展,这意味着要与内容脚本通信,我必须使用后台服务人员来代理消息。不幸的是,docs on DevTools extensions 尚未针对 manifest v3 进行更新,如果后台工作程序终止,则用于通过后台脚本在内容脚本和 DevTools 面板之间进行消息传递的 technique they suggest 将不起作用。

我看到一些answers hereChromium project issue report comments 建议唯一可用的解决方法是每五分钟重置一次连接。这似乎很老套且不可靠。有没有更好的机制,比任意计时器更基于事件?

【问题讨论】:

    标签: javascript google-chrome-extension chrome-extension-manifest-v3


    【解决方案1】:

    我们可以使用devtools_page 本身作为连接中继,而不是后台脚本。当打开当前选项卡的 devtools 时,此隐藏页面会在 devtools 内部运行,并且它可以完全访问与后台脚本相同的所有 chrome API。

    manifest.json:

      "devtools_page": "devtools.html",
      "content_scripts": [{
        "matches": ["<all_urls>"],
        "js": ["content.js"],
        "run_at": "document_start"
      }]
    

    devtools.html:

    <script src="devtools.js"></script>
    

    devtools.js:

    let portDev, portTab;
    const tabId = chrome.devtools.inspectedWindow.tabId;
    const onDevMessage = msg => portTab.postMessage(msg);
    const onTabMessage = msg => portDev.postMessage(msg);
    
    chrome.runtime.onConnect.addListener(port => {
      if (+port.name !== tabId) return;
      portDev = port;
      portDev.onMessage.addListener(onDevMessage);
      portTab = chrome.tabs.connect(tabId, {name: 'dev'});
      portTab.onMessage.addListener(onTabMessage);
    });
    
    // chrome.devtools.panels.create...
    

    panel.js:

    const port = chrome.runtime.connect({
      name: `${chrome.devtools.inspectedWindow.tabId}`,
    });
    port.onMessage.addListener(msg => {
      // This prints in devtools-on-devtools: https://stackoverflow.com/q/12291138
      // To print in tab's console see `chrome.devtools.inspectedWindow.eval`
      console.log(msg);
    });
    self.onclick = () => port.postMessage('foo');
    

    content.js:

    let portDev;
    const onMessage = msg => {
      console.log(msg);
      portDev.postMessage('bar');
    };
    const onDisconnect = () => {
      portDev = null;
    };
    chrome.runtime.onConnect.addListener(port => {
      if (port.name !== 'dev') return;
      portDev = port;
      portDev.onMessage.addListener(onMessage);
      portDev.onDisconnect.addListener(onDisconnect);
    });
    

    附:关于the 5-minute timer reset trick,在这种情况下它是相当可靠的,因为在此选项卡的开发工具打开时,该选项卡保证是打开的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-27
      • 2012-07-29
      • 2023-03-07
      • 2014-06-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多