I´m working on a chrome-extension which uses the indexedDB-Wrapper Dexie, several jQuery-Libraries and syncfusions eGrid to display and modify the database. I know this question was asked several times before, but now I discovered some weird behaviour.
My Setup:
- background-script
- content-script (injected into a website)
- index.html (for displaying the Grid)
- manifest.json
When I´m reloading my extension everything is fine. I´m injecting a scrollable list of names with my content-script. This also works when I´m reloading the tab. But when I opened the index.html before (popup.html in the official documentation) the sendResponse from background-script stops working after some time. Reloading the tab would not help then. I was searching for hours, found a lot of similiar cases and some entrys on googles bugtracker where they claimed this problem was already fixed. I also know that I have to use return true if I have async funtions like with indexedDB.
So to give you some more information, I will list my shortened scripts.
Content-Script
chrome.runtime.sendMessage({greeting: 'getNames'},function(response){
$('.names-container').append(response.farewell);
});
chrome.runtime.sendMessage({greeting: 'getData'+name},function(name){
chrome.runtime.sendMessage({greeting: 'delete'},function(response){
console.log(response.farewell);
});
chrome.runtime.sendMessage({greeting: 'set'}, function(response) {
console.log(response.farewell);
});
});
Background-Script
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
if(message.greeting == 'getNames'){
// Get array of names from idb and send it back
idb.opendb().then(function(a){
sendResponse(a);
});
return true;
} else if(message.greeting.indexOf('getData') >= 0){
// get more information for selected name
idb.opendb().then(function(a){
sendResponse(a);
});
return true;
} else if(message.greeting == 'delete'){
// further processing to delete some stuff
idb.opendb().then(function(a){
sendResponse(a);
});
return true;
} else if(message.greeting == 'set'){
// synchronous function
// do something ...
return false;
} else {
// Do something
}
//return true;
});
funtion indexhtml(){
chrome.runtime.sendMessage(
"notifications",
function (response) {
console.log(response);
}
);
}
Index.html
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){
if(request == 'notifications'){
notifications();
}
sendResponse("Message received from background-page for "+request);
});
Manifest
{
"manifest_version": 2,
"name": "MyExtension",
"description": "Some desc...",
"version": "0.2",
"background": {
"scripts": ["js/jquery-2.1.4.min.js", "js/background.js", "...",
"persistent": true
},
"default_locale": "en",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["js/jquery-2.1.4.min.js"]
},
{
"matches": ["https://domain.tld/*"],
"js": ["js/jquery-2.1.4.min.js", "js/contentscript.js"],
"css" : ["css/contentscript.css",
"run_at": "document_start"
}
],
"icons": {
"16": "images/icon-16x16.png",
"48": "images/icon-48x48.png",
"128": "images/icon-128x128.png"
},
"browser_action": {
"default_icon": "images/icon-128x128.png"
},
"permissions": [
"cookies", "tabs", "alarms", "webRequest", "webRequestBlocking",
"contextMenus", "<all_urls>", "storage"
],
"content_security_policy": "script-src 'self' 'unsafe-eval';
object-src 'self'"
}
It is difficult for me to debug this behaviour, since I can´t exactly know when the Error Attempting to use a disconnected port object appears. It looks like the port doesn´t gets closed correctly after the sendResponse is executed and only if the index.html was opened.
Finally the shortened Error-Message:
Error: Attempting to use a disconnected port object
at Error (native)
at PortImpl.postMessage (extensions::messaging:65:22)
at Port.publicClass.(anonymous function) [as postMessage] (extensions::utils:94:26)
at responseCallback (extensions::messaging:163:16)
The idb-Functions are customized and won´t work like I wrote them here, but I just want to show what I´m doing there. I´m using .then() to sendReponse when the result is available and return true; to wait for the result if async. I also searched every script for onMessage and sendMessage. The listed functions related to onMessage/sendMessage are all that I´m using, they are not used elsewhere. I´m using a timer for indexhtml() to save an array containing the notifications in a specified interval and then executing a function at index.html to reload the notifications.
The index.html Tab gets opened via browserAction:
chrome.browserAction.onClicked.addListener(function(tab){
chrome.tabs.create({url: chrome.extension.getURL('index.html')});
});