Chrome.tabs.sendMessage doesn't work while sendResponse is running

Here is the chrome extension manifest:

{
  "name": "myconnector",
  "short_name": "myconnector",
  "version": "1.1",
  "manifest_version": 2,
  "description": "myapp",
  "background": {
    "scripts": ["main.js"],
    "persistent": true
    },
    "externally_connectable": {
      "ids": ["*"],
      "matches": ["*://*.myurl.fr/*"]
  },
  "web_accessible_resources": [ "emulation.js", "content_scripts.js" ],
  "icons": {
    "16": "icon-16.png",
    "128": "icon-128.png"
  },
  "permissions": [
    "tabs",
    "nativeMessaging"
  ]
}

      

Chrome extension background page:

//------ Message received from external web site

chrome.runtime.onMessageExternal.addListener(
  function(request, sender, sendResponse) {

    if(request.areYouThere) {
        onNativeMessage(true);
    }

    if(!port) {
        port = chrome.runtime.connectNative(hostName);
        //port.onMessage.addListener( onNativeMessage );
    }

    port.onMessage.addListener(function(msg) {sendResponse(msg);});

     port.onDisconnect.addListener(function() {
        console.log("Disconnected from native App");
        port = null;
    });

    if (request.data) {
      var data = request.data;
      console.log(JSON.stringify(request));
      port.postMessage(data);
    }

    return true;

  });

// ----- Message received from Native Host App

function onNativeMessage( message ) {
    console.log( 'received message from native app: ' + JSON.stringify( message ) );
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
        chrome.tabs.sendMessage(tabs[0].id, message, function(response){});
    });
}

      

And here is the code of the website calling the extension:

$("#my-action").click(function(){

            console.log("calling method MyAction");

            chrome.runtime.sendMessage( "<extension id>",  
                                {data: 
                                    {action:"MyAction"}
                                    }, 
                                function(response) {
                console.log(JSON.stringify(response));
                $("#result").text(JSON.stringify(response));
            });
        });

      

When I do this:

port.onMessage.addListener(function(msg) {sendResponse(msg);});

      

The answer posted correctly, but I get chrome.native.lastError.message:

It is not possible to send a response more than once per chrome .runtime.onMessage listener per document (the message was sent by extension for undefined url).

But when I do this:

port.onMessage.addListener( onNativeMessage );

      

This method, which calls onNativeMessage, sends a message to the website (presumably?) Using the chrome.tabs.sendMessage method. But the website never gets a response.

Also, my extension needs to instantiate the port so that it can use a persistent connection with my own host application.

Am I doing something wrong?

+3


source to share


1 answer


When I do this:

port.onMessage.addListener(function(msg) {sendResponse(msg);});

      

The answer was sent correctly, but I get chrome.runtime.lastError.message

:

It is not possible to send a response more than once to a chrome.runtime.onMessage

listener per document (the message was posted by extension for URL undefined).

This is because you add a listener EVERY time you receive an external message. So after receiving the second message, it sendResponse()

tries to start twice (new and old again).


But when I do this:

port.onMessage.addListener( onNativeMessage );

      

This method, the caller onNativeMessage

, sends a message to the website (presumably?) Using the method chrome.tabs.sendMessage

. But the website never gets a response.

You cannot do this; chrome.tabs.sendMessage

sends the message to the content script context , not the web page.




You should change your code to only add listeners once, or at least provide simultaneous listening.

The trick, of course, is that the link sendResponse

changes every time. I think you can do it with a self destruct listener:

if(!port) {
    port = chrome.runtime.connectNative(hostName);

    port.onDisconnect.addListener(function() {
      console.log("Disconnected from native App");
      port = null;
    });
}

var callback = function(msg) {
  sendResponse(msg);
  port.onMessage.removeListener(callback); // The power of closures!
};

port.onMessage.addListener(callback);

      

+2


source







All Articles