使用 chrome.runtime.connect 和 postMessage 时出错

Error occurred when using chrome.runtime.connect and postMessage

我想做什么

一个Chrome扩展可以快速搜索印象笔记。它很像 vimium,但用于 evernote 搜索。当按下 'e/E' 键时,会显示一个多功能栏。然后我可以输入一些查询字符串,建议将被异步获取。按 ESC 隐藏它。 This is my extension

在加载网页时附加 omnibar(iframe),然后使用 chrome 消息传递在 iframe 和 background.js 之间进行通信以调用搜索功能

一开始还好,打开几个chromewindows,过几个小时再搜索,就出错了。

错误

Uncaught TypeError: Cannot read property 'impl' of undefined
    at getPrivateImpl (extensions::utils:121:30)
    at Port.publicClassPrototype.(anonymous function) [as postMessage] (extensions::utils:139:20)
    at EomnibarIn.onInput (chrome-extension://khjineoieblnbagekihfblbfkkapcbda/js/eomnibarIn.js:76:29)
    at HTMLInputElement.input.on (chrome-extension://khjineoieblnbagekihfblbfkkapcbda/js/eomnibarIn.js:60:49)
    at HTMLInputElement.dispatch (chrome-extension://khjineoieblnbagekihfblbfkkapcbda/js/jquery-3.2.1.min.js:3:10316)
    at HTMLInputElement.q.handle (chrome-extension://khjineoieblnbagekihfblbfkkapcbda/js/jquery-3.2.1.min.js:3:8343)

代码

iframe页面内嵌js代码

class EomnibarIn {
    constructor() {
        this.backgroundPort = chrome.runtime.connect({name: 'eomnibarPort'});
        this.backgroundPort.onMessage.addListener((msg) => {
                console.log(msg);
                this._displaySuggestions(msg.queryString, msg.suggestions);
        });
    }

    onInput(event) {
        // Get queryString and other staff

        this.backgroundPort.postMessage({
            action: 'performSearch',
            queryString: queryString,
            maxSuggestion: this.maxSuggestion
        });
    }
}

$(document).ready(function(){
    var barIn = new EomnibarIn();
});

背景页

chrome.runtime.onConnect.addListener(function(port) {
    if (port.name == 'eomnibarPort') {
        port.onMessage.addListener(function(msg) {
            console.log(msg);
            if (msg.action === 'performSearch') {
                const suggestions = eomnibarController.performSearch(
                    msg.queryString, msg.maxSuggestion);
                port.postMessage({queryString: msg.queryString, suggestions: suggestions});
            }
        });
    }
});

我的问题

哪一部分出了问题?我不知道如何调试它,因为它不会每次都发生。

该错误消息肯定意味着端口已断开连接。发生这种情况的原因有几个。一个常见的是扩展名 reloaded/updated/reinstalled。如果您从 chrome://extensions 中点击重新加载按钮,所有旧端口将断开连接。另一个可能的原因是发生了异常情况(例如,您的笔记本电脑电池 运行 电量不足并进入了低功耗模式)。

修复有点复杂...您必须检测端口断开(使用 port.onDisconnect 形成内容脚本)并建立新连接。不幸的是,这并不像再次调用 chrome.runtime.connect() 那样简单。如果您的扩展已更新到新版本,您将无法访问旧扩展上下文及其 chrome.* API。您必须重新加载一个全新的 iframe(并删除旧的 iframe)。

我在我的扩展中这样做 Saka Key。你可以查看它的源代码。

顺便说一下,包含扩展页面的 iframe 不是内容脚本。它们实际上是可以直接访问后台页面的特权上下文。