A Chrome extension can quick search evernote. It's quite like vimium but for evernote searching. When The 'e/E' key pressed, an omnibar show. Then I can input some query strings, suggestions will be fetched asynchronized. Press ESC to hide it. This is my extension
Append the omnibar(iframe) when web page loaded, then using chrome message passing to communicate between iframe and the background.js to call the searching function
At the beginning it works fine, but when I opened several chrome windows, and after a few hours, then perform the search again, error occurred.
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)
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});
}
});
}
});
Which part goes wrong? I don't have any clue how to debug this since it doesn't happen every time.
That error message definitely means the port has been disconnected. There are a few reasons this might happen. A common one is that the extension reloaded/updated/reinstalled. If you hit the reload button from chrome://extensions, all old ports disconnect. Another possible cause is that something anomalous happened (e.g. your laptop's battery ran low and entered low-power mode).
The fix is a little bit complicated... You have to detect the port's disconnection (using port.onDisconnect form the content script) and establish a new connection. Unfortunately, it's not as simple as calling chrome.runtime.connect() again. If your extension was updated to a new version, you lose access to the old extension context and its chrome.* APIs. You have to reload a whole new iframe (and remove the old iframe).
I do this in my extension Saka Key. You can check its source code.
By the way, iframes that contain extension pages aren't content scripts. They actually are privileged contexts with direct access to the background page.