【问题标题】:Error occurred when using chrome.runtime.connect and postMessage使用 chrome.runtime.connect 和 postMessage 时发生错误
【发布时间】:2017-10-01 14:15:40
【问题描述】:

我想做什么

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

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

一开始还可以,但是当我打开几个chrome窗口时,几个小时后,再次执行搜索,出现错误。

错误

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});
            }
        });
    }
});

我的问题

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

【问题讨论】:

  • Chrome 会为多功能框搜索创建和销毁隐藏的预呈现标签,因此我认为您应该检查网页是否加载到带有tab.index == -1 的标签中。根据您在问题中的描述,我不知道您的扩展实际上做了什么,所以要么发布完整扩展代码的链接,要么......祝你好运:)
  • @wOxxOm 我认为没有人可能有耐心浏览这些代码。但是,是的,你是对的。我在我的问题中添加了链接。你可以在 Chrome 上试一试。这对于使用 Linux 的 Evernote 用户来说非常方便。基本上,它很像 vimium,但仅用于 Evernote 搜索。
  • @wOxxOm 我也按照你说的尝试过,使用chrome.tabs.getSelected检查iframe js中的标签ID,只是普通数字而不是-1
  • 不是id,而是index
  • @wOxxOm 对不起,我的错。索引为 0。omnibar 只是附加在当前页面中的常规 iframe。我不太明白它对标签的作用。

标签: google-chrome-extension postmessage message-passing


【解决方案1】:

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

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

我在我的扩展程序Saka Key 中执行此操作。你可以查看它的源代码。

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

【讨论】:

  • 似乎是扩展重新加载问题。我会做进一步的测试。我安装了 Saka Key,设计得非常好,干得好:)
  • 另一个相关问题,你用什么来进行页面和 iframe 通信?我使用MessageChannel,端口断开问题也时有发生。您知道可能的原因是什么吗?
  • 我使用我自己的库mosi,它建立在常规扩展消息的基础上。现在想想,Saka Key 并没有真正使用 iframe。我的另一个扩展 Saka 可以,但它不是开源的。我从来没有使用过MessageChannels,所以我不知道。
猜你喜欢
  • 2022-11-11
  • 2022-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-07
  • 2023-03-12
  • 2017-11-06
相关资源
最近更新 更多