从内容脚本向页面 Javascript 发送消息

Sending messages to page Javascript from a content script

我在 Javascript 运行时中有一个选项卡方法,我想从我的扩展程序的内容脚本中触发该选项卡。从表面上看,这需要在上下文之间传递消息,但我找不到任何关于 CS 到选项卡消息的文档,只有选项卡到 CS 或 CS 到背景。本质上,我想翻转内容脚本参考的 Communication with the embedding page 部分。

到目前为止,我通过注入一个小的 Javascript 负载将事件监听器附加到选项卡的 window(这将在正确的消息类型上触发选项卡方法):

listenerScript = document.createElement('script');
listenerScript.textContent = "window.addEventListener('message',function(ev){console.log('New event: ' + ev);},false);console.log('installed');";
(document.head||document.documentElement).appendChild(listenerScript);
listenerScript.remove();

此侦听器已注册,但我不知道如何从我的内容脚本中触发它。内容脚本中的window.postMessage()好像没有做任何事情,文档只讲了使用chrome.runtime创建一个端口,用于后台脚本。

如何以最简单的方式将消息从内容脚本传递到选项卡?

代码是正确的,因此,考虑到您在控制台中看到 installed,唯一的解释是:

  1. 页面被重定向,整个 DOM 及其侦听器被销毁。
  2. 该页面欺骗了 window.addEventListener 或附加了自己的 'message' 侦听器,并在您的侦听器看到它之前取消了事件(例如,通过使用 event.stopPropagation() 等)

    在这种情况下,您需要将内容脚本声明为 运行 before the page starts loading 并使用监听器在事件沿 DOM 链冒泡之前捕获事件(useCapture, addEventListener的第3个参数应该是true).

    manifest.json:

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

    content.js:

    // this code runs before page starts loading
    var injected = document.documentElement.appendChild(document.createElement('script'));
    injected.text = '(' + function() {
        window.addEventListener('message', function(ev) {
            console.log('New event:', ev);
        }, true); // useCapture: true
        console.log('installed');
    } + ')()';
    injected.remove();
    
    document.addEventListener('DOMContentLoaded', function() {
        // this code will run when the DOM is ready
        window.postMessage({ foo: 'bar', text: "Hello from content script!" }, "*");
    });
    

    请注意,我们将脚本添加到 documentElement,因为 document_start 通常没有 head。 另见:other methods of injecting a DOM script.