10

When I try to send a message to another extension, occasionally I might have an invalid id (the extension may have been removed), but sendMessage does not ever notify me of this. As far as I can tell, it just prints to console.error:

This is miscellaneous_bindings Line 235 of Chrome's source code:

chromeHidden.Port.dispatchOnDisconnect = function(  portId, errorMessage)
{
    var port = ports[portId];
    if (port) {
        // Update the renderer's port bookkeeping, without notifying the browser.
        CloseChannel(portId, false);
        if (errorMessage) {
            lastError.set(errorMessage, chrome);
            //It prints: Port error: Could not establish connection. Receiving end does not exist.
            console.error("Port error: " + errorMessage);
        }
        try {
            port.onDisconnect.dispatch(port);
        } finally {
            port.destroy_();
            lastError.clear(chrome);
        }
    }
};

As a result, my app is left trying over and over to send a message. The only hint I have is an empty response send back from sendResponse(), but any app can send an empty response object! How do I know it failed?

Pacerier
  • 86,231
  • 106
  • 366
  • 634
Don Rhummy
  • 24,730
  • 42
  • 175
  • 330

1 Answers1

15

In the callback of sendResponse, look at the chrome.runtime.lastError property.

chrome.runtime.sendMessage("ID of extension", "message", function(response) {
    var lastError = chrome.runtime.lastError;
    if (lastError) {
        console.log(lastError.message);
        // 'Could not establish connection. Receiving end does not exist.'
        return;
    }
    // Success, do something with response...
});
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • 2
    Thanks. That's not perfect as it doesn't guarantee I can properly react to the reason for the error: the lastError object has only one property `message`. The message can change in wording at any time, so relying on that is not a good idea. So again, there seems to be no *safe* way to know why it failed. – Don Rhummy Jun 11 '13 at 18:57
  • @DonRhummy You'll only get an error if something went wrong with sending the message. Currently, the only errors are "Attempting to use a disconnected port object" and "Could not establish connection. Receiving end does not exist." (see [miscellaneous_bindings.cc](https://code.google.com/p/chromium/codesearch#chromium/src/chrome/renderer/extensions/miscellaneous_bindings.cc&q=%22Could%20not%20establish%20connection.%20Receiving%20end%20does%20not%20exist.%22&sq=package:chromium&dr=C&l=71)) – Rob W Jun 11 '13 at 19:09
  • I'm getting a weird issue in trying to use your code. Since in the callback, there's no information on which `appId` I tried to send the message to, I create a local variable that's referenced in that function (or I've also tried binding it to the appId), but when I do either of those, it somehow results in all id's (even valid ones) ending up in there because even though it's called on the invalid one, I'm creating these `sendMessage` calls in a loop and when it calls the next one, the previous one now gets **that** appId passed in! How do I pass the right appId? – Don Rhummy Jun 11 '13 at 22:30
  • Introduce a closure. Google /search on Stack Overflow for "function in loop" or something along these lines to get an example. – Rob W Jun 11 '13 at 22:39
  • I tried that, it also does not work. I tried this: http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example but it tells me that the appId "ipjhikigpnphblkgqpiihlpfnkigcjiq" does not exist but it does and I can see it installed. – Don Rhummy Jun 11 '13 at 22:45
  • Any code? The other extension or app must have registered an external message handler by the way – Rob W Jun 11 '13 at 22:56
  • 1
    Yep, in the other one I have: `chrome.runtime.onMessageExternal.addListener(function(request,sender, sendResponse) { console.log( "got it!" ); } );` but this is never called. – Don Rhummy Jun 11 '13 at 22:59
  • 1
    is there anything in Chrome that blocks an app if they try to contact too many apps that aren't there? I think that might be what's happening. I created two new apps (sender, receiver) and sent a message and it sent correctly. But when I copied sender's code into my previous app, it still gets the same error! – Don Rhummy Jun 11 '13 at 23:27
  • I found the problem!!! Since I normally use js libraries, one of them defined a "bind" function (so you could call `myFunc.bind( this );`. However, this causes the issue! Any idea why? This seems to be a weird bug. – Don Rhummy Jun 11 '13 at 23:33
  • @DonRhummy Can't say anything without more info about the library. Just a heads-up: You don't need any library for a correct implementation of `.bind`. See [`Funcion.prototype.bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind). – Rob W Jun 12 '13 at 08:27
  • I'm used to having to code for both old and new browsers, which is why I have a library that tried defining that. – Don Rhummy Jun 12 '13 at 16:05
  • How do you do it in Manifest v3, where it returns a Promise. I've tried wrapping it in try catch but it doesn't intercept the error. – The.Wolfgang.Grimmer Feb 21 '23 at 04:57