使用 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 不是内容脚本。它们实际上是可以直接访问后台页面的特权上下文。
我想做什么
一个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 不是内容脚本。它们实际上是可以直接访问后台页面的特权上下文。