0

I am new to the world of creating Chrome Extensions, and is facing a problem of keeping a connection open from my background script (event page) to the content script. I have been searching all day with no luck. Most examples are with non-persistent connections.

My extension needs to send some data from a web page to the content script. From the content script to the background script, where a native message communicates with a native application, which returns an answer that goes through the background script to the content script and finally is received at the web page again.

I am able to pass the message all the way to the native application and have an answer returned, but my challenge is passing it on from here as the connection between the background script and the content script is dead.

The files:

manifest.json

{
  "manifest_version": 2,

  "name": "MyExtenesion",
  "description": "MyExtension",
  "version": "0.1",

  "background": {
    "scripts": ["eventPage.js"],
    "persistent": false
  },
  "browser_action": {
    "default_title": "MyExtension",
    "default_icon": "icon.png"    
  },
  "content_scripts": [
    {
        "matches": ["<all_urls>"],
        "js": ["content.js"]
    }
  ],
  "externally_connectable": {
    "matches": ["http://localhost/*"]
   },
  "permissions": [
    "tabs",
    "nativeMessaging",
    "http://localhost:5661/*"
  ]
}

content.js

var port = chrome.runtime.connect();

// Event sent from the web page is caught and the data is sent to the event page (background script)
document.addEventListener("MsgToContent", function(data) {  
    console.log('1 content MsgToContent');
    port.postMessage(data.detail);
});

// When the event page script connects to the content script
chrome.runtime.onConnect.addListener(function(port) {

    // When a message to the content script has been received
    //port.onMessage.addListener(function(msg) {
    chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
        alert('fra content: ' + msg);

        sendResponse();
    });
});

eventPage.js

var contentPort = null;

// Connect to native app
var port = chrome.runtime.connectNative('com.nativeApp');

chrome.tabs.onActivated.addListener(function(tabId, changeInfo, tab) {

    // When the page/tab loads, connect to its content script scope
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {

        contentPort = chrome.tabs.connect(tabs[0].id);

        contentPort.onDisconnect.addListener(function() {
            console.log('tabs.query contentPort onDisconnect');
        });

        // When the content script has received a message
        contentPort.onMessage.addListener(function(msg) {
            console.log('x eventPage currentPort onMessage');
        });
    });
});

chrome.runtime.onConnect.addListener(function(pPort) {
    console.log('2 eventPage onConnect');

    // When receiving a message from the content script
    pPort.onMessage.addListener(function(msg) {
        console.log('3 eventPage onConnect onMessage');
        // Send message to the native app
        port.postMessage({ text: msg });  
    });
});

// Handles incoming messages from the native app
port.onMessage.addListener(function(msg) {
  console.log('4 eventPage port onMessage');
  contentPort.postMessage(msg); 
});

The problem is in the eventPage.js. I try to make contentPort the current connection to the content script, but when I get into the onMessage event from the native app, where I want to pass on the message, I get the error:

Error in event handler for (unknown): Error: Attempting to use a disconnected port object

In the line contentPort.postMessage(msg);

How do I keep the connection open, so I can send a message back? I appreciate any hints that can help me solve this issue.

I am not really aware of the best way of doing the communication, so any advices are most welcome.

Casper
  • 1
  • Probably duplicate with this one: http://stackoverflow.com/questions/11782875/chrome-message-passing-error-attempting-to-use-a-disconnected-port-object – Dayton Wang Mar 23 '15 at 20:01
  • Thank you for your comment. I'm having trouble seeing how the solution translates to my issue. In the answer it's suggested to inject the content script on page action. I don't use that and I need my content script running all the time (not just on page action), as it listens for messages from the web page. – Casper Mar 24 '15 at 08:46
  • I found the same problem when trying to communicate with my server. The connection to background appears to only allow "fast" operations, else it never calls back. My own solution was to wrap all background message sending in a function that stores the callback, against a unique ID (same was Ajax calls do), and then catches a returned message from the background, finds any stored matching callback for the id and executes that. It makes the code pattern look like you would expect then. – iCollect.it Ltd Mar 25 '15 at 11:27

0 Answers0