NativeMessaging addon with error in console: "Attempt to postMessage on disconnected port"

I’m developing an NewTab extension (already published, here: https://addons.mozilla.org/en-US/firefox/addon/floflisnewtab/) and soon it will receive the feature of NativeMessages, for communicating with its own program/binary.

In order to independently test this feature out of my main addon, I’ve forked webextensions-examples and made my modification for /native-messaging.

When I click its toolbar button, it simply doesn’t logs anything in Console.

Mozilla’s troubleshooting page (https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#troubleshooting) doesn’t mentions this issue of not logging when clicked.

Source of binary (bash) used: https://github.com/Floflis/browsernewtab/tree/main/root-in-progress/bin
Addon’s source: https://github.com/Floflis/browsernewtab/tree/main/root-in-progress/native-ext
XPI download for testing: https://drive.google.com/file/d/1TOVKeBxRIW0WyptVfgeXdsjPYc7rpCYE/view?usp=sharing

I appreciate if anyone can help and tell me what its missing for this extension to work.
EDIT: yes, its logging in the console, but not working with the binary (bash script). More details in the replies bellow.

Related posts:



With good answers from: @hans_squared and @juraj.masiar
(hope they can help here, too).

Looking at your bash script, I don’t think it properly handles the native messaging format. The messages have a 32 bit int in front to indicate their length.

https://developer.mozilla.org/en-us/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#app_side

Looking at your bash script, I don’t think it properly handles the native messaging format. The messages have a 32 bit int in front to indicate their length.

Ok, but then why the addon doesn’t even logs errors on Console?
EDIT: yes, its logging in the console, but not working with the binary (bash script). More details in the replies bellow.

And, if it isn’t too much to ask, how could an shell script properly manage these messages sent by the addon?

I just would need an example of how this message is formatted, then I use sed to separate the lenght and jq to read the JSON.

@freaktechnik

To simplify it, I would myself figure how to modify my bash script to recognize/parse the format of the stdin messages received, but: the addon isn’t logging on Console.
EDIT: yes, its logging in the console, but not working with the binary (bash script). More details in the replies bellow.

@freaktechnik

To simplify it, I would myself figure how to modify my bash script to recognize/parse the format of the stdin messages received, but: the addon isn’t logging on Console.

Good news.
The Console to open isn’t in any tab, but the specific Console of the addon in debugging.

  1. Access about:debugging#/runtime/this-firefox
  2. Open the extension to be observed: about:devtools-toolbox?type=extension&id=floflis_browser%40floflis.eth

And yeah, the addon is working:

What is the RAW output of this “ping” message? So I can parse it on my binary.
EDIT: first things, first. Before wanting to parse the message sent to the bash script, I had to know if the addon even is calling this binary. More about that, bellow:

cd /usr/lib/floflis/browser
echo "ping" | ./flobrowser

outputs this: pong


I modified the bash script to write an text file with the stdin input as title, which worked.

But when I click the button of the addon and it logs “Sending: ping” in the console, no file is written (which means the addon isn’t calling the binary).
EDIT: discovered what caused this issue. Details bellow:

Ok, discovered what caused the previous issue.

First, for transparency, here is my addon’s manifest.json:

About the issue, addons have more than one “ID”, so I had to add it to its NativeApplication manifest:



So, this was the missing piece to enable this addon to communicate with its NativeApplication JSON file, located at ~/.mozilla/native-messaging-hosts/floflis_browser.json.

Now, the addon’s console displays the following error:

Attempt to postMessage on disconnected port

What is causing this issue?
I don’t know who tried it, but I’m pretty sure that an bash script can work as native application.

Things that are okay:

  1. the nativeapplication json file points to the correct extension IDs
  2. this nativeapplication json file is recognized by the addon
  3. the addon logs on console
  4. the binary/nativeapplication (bash script) has been made an executable

Things that can be wrong, to be checked:

  1. use “/” or “//” in the path to the binary? https://github.com/sammacbeth/dat-fox-helper uses the standard “/” for the path
  2. is the “name” entry wrong, and/or should use the same name of the binary?
  3. should the binary be at /usr/bin?
  4. Any typo on its native messaging host configuration?
    {
    “name”: “floflis_browser”,
    “description”: “Manage Plasmozill Firefloflis, Plasmoogle Fhrome and others, mediating the communication between an extension and the OS. This is an host using native messaging.”,
    “path”: “/usr/lib/floflis/browser/flobrowser”,
    “type”: “stdio”,
    “allowed_extensions”: [ “{0d9010b7-f270-4893-9a4f-da4d5aef4b3b}”, “floflis_browser@floflis.eth”, “96b0ae5c-33c3-4821-a122-ffd1af16caf0”, “{96b0ae5c-33c3-4821-a122-ffd1af16caf0}” ]
    }
    None of the above seems to be the issue causing this error.
    Based on this post by @Mert:
    Native messaging api disconnected port error

I’m researching on other posts about the “Attempt to postMessage on disconnected port” error logged.

@anon48797620 wrote some threads about NativeMessaging, with replies from @zombie and @mig.

I’m pretty sure an bash script can work as native application. I just would like to understand the “Attempt to postMessage on disconnected port background.js:18” in the console.

Indeed, see also

That sounds like the script terminated the stdout stream/stopped execution, and thus the port was closed.

1 Like

Have you read the documentation or tried to understand the example before modifying it? Your “modification for /native-messaging” wasn’t a minor, it completely changed the logic, to the extent that your new program isn’t correct any more.

What your program does is simply echoing the “pong” message to stdout.
What it should do at minimum is to prepend the length of the message in a 32-bit value in native byte order. See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#app_side for the expected protocol that you need to adhere to.

Note: unless you’re very experienced with Bash, bash is not a good choice for developing a native messaging host, because null bytes are not consistently preserved. For example, when stdin is \0x06\0x00\x00\x00"ping", your bit of code with while read line will contain \0x06"ping" without the NULL bytes, which is incorrect. The examples use Python and Node.js, which more fitting scripting languages than shell scripting in Bash.

1 Like

That sounds like the script terminated the stdout stream/stopped execution, and thus the port was closed.

I don’t think the script did it. Source:
#!/bin/bash
while read line; do
cat > /home/daniell/${line}.txty << ENDOFFILE
thanks
ENDOFFILE
if [ “${line}” = “ping” ]; then
echo “pong”
fi
done

This script should identify that an stdin message has been sent (${line}) and write its content into an texty file.

To test, this works:

cd /usr/lib/floflis/browser
echo "ping" | ./flobrowser

Is this an issue in the script or in the addon’s manifest?

So once again:

  1. If you send “ping” from your extension, the message it receives on STDIN isn’t “ping”, it’s 32 bits indicating the length of the string that follows and then it is “ping”.
  2. If you use a port, your script/application needs to keep running as long as you want to be able to send messages to it. Typically you need to use a loop that keeps reading the stdin.
  3. If you want to read a single input and have the script process that, https://developer.mozilla.org/en-us/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendNativeMessage is a better fit than a port. However, I am not sure that it guarantees to have the same timings of piping a value to the application, there might be a delay until the message from the extension is written to the stdin.

There are multiple problems with your bash script.

  • You need an infinite loop, like the Python script in the native messaging documentation. Otherwise, the script runs only once, before it has a chance to receive the message from Firefox. That’s what causes the “Attempt to postMessage on disconnected port” error.
  • When you wrap the code in an infinite loop, it creates a new file during every loop iteration. Manjaro Linux, at least, doesn’t like this; when I navigate the file manager to the directory where the file gets written, the file manager becomes unresponsive.
  • From what I’ve read, bash scripts can’t read binary data from stdin. And Firefox sends binary data to the native app; see freaktechnik’s post. The variable “line” contains the size header, or at least part of it, and in the next iteration, it contains the text “ping” (I think).

Have you read the documentation or tried to understand the example before modifying it?

So, I need to be an professional programmer to build this?

Your “modification for /native-messaging” wasn’t a minor, it completely changed the logic, to the extent that your new program isn’t correct any more.

The addon’s logic is the same. There are no breaking modifications in the addon itself. What was replaced (not modified, but completely replaced) is the native application used. NodeJS and Python are possible examples, but I would like to add an Bash example to it.

What your program does is simply echoing the “pong” message to stdout.
What it should do at minimum is to prepend the length of the message in a 32-bit value in native byte order. See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#app_side for the expected protocol that you need to adhere to.

See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#app_side

Instead:
See https://stackoverflow.com/questions/24764657/how-do-i-use-a-shell-script-as-chrome-native-messaging-host-application

Remember what yourself have posted?

Here is a minimal example that assumes that the input ends with a } , reads it (without processing) and replies with a result. Although this demo works,

It was very helpful for me, and I thank you for that!
I’ve applied it to my native application:
#!/bin/bash
# Loop forever, to deal with chrome.runtime.connectNative
while IFS= read -r -n1 c; do
# Read the first message
# Assuming that the message ALWAYS ends with a },
# with no }s in the string. Adopt this piece of code if needed.
if [ “$c” != ‘}’ ] ; then
continue
fi

    message='{"message": "pong"}'
    # Calculate the byte size of the string.
    # NOTE: This assumes that byte length is identical to the string length!
    # Do not use multibyte (unicode) characters, escape them instead, e.g.
    # message='"Some unicode character:\u1234"'
    messagelen=${#message}

    # Convert to an integer in native byte order.
    # If you see an error message in Chrome's stdout with
    # "Native Messaging host tried sending a message that is ... bytes long.",
    # then just swap the order, i.e. messagelen1 <-> messagelen4 and
    # messagelen2 <-> messagelen3
    messagelen1=$(( ($messagelen      ) & 0xFF ))               
    messagelen2=$(( ($messagelen >>  8) & 0xFF ))               
    messagelen3=$(( ($messagelen >> 16) & 0xFF ))               
    messagelen4=$(( ($messagelen >> 24) & 0xFF ))               

    # Print the message byte length followed by the actual message.
    printf "$(printf '\\x%x\\x%x\\x%x\\x%x' \
        $messagelen1 $messagelen2 $messagelen3 $messagelen4)%s" "$message"

done

#while read line; do
#  cat > /home/daniell/${line}.txty << ENDOFFILE
#thanks
#ENDOFFILE
#  if [ "${line}" = "ping" ]; then
#     echo "pong"
#fi
#done

But, still, the addon logs this error: “Attempt to postMessage on disconnected port”.

Note: unless you’re very experienced with Bash

That’s why I like shell script. Its the most democratic language I’ve found, that enables anyone to make beauty things.

bash is not a good choice for developing a native messaging host, because null bytes are not consistently preserved. For example, when stdin is \0x06\0x00\x00\x00"ping" , your bit of code with while read line will contain \0x06"ping"

Not even that my bash script is doing, simply because the addon isn’t even sending the message, I think. So, if bash “is so horrible” but at least can read \0x06"ping", why its not doing it?

without the NULL bytes, which is incorrect. The examples use Python and Node.js, which more fitting scripting languages than shell scripting in Bash.

There are workarounds for that: https://unix.stackexchange.com/questions/174016/how-do-i-use-null-bytes-in-bash
Also, bash can run an Python or NodeJS script that directly receives the addon’s message, formats it and repasses to the bash script (but I’m opposed to it, as it isn’t anymore the bash script as the native application).

I’ll truly appreciate if you help me putting this bash script to work with the addon, and I will even send you a tip.

If you send “ping” from your extension, the message it receives on STDIN isn’t “ping”, it’s 32 bits indicating the length of the string that follows and then it is “ping”.

It’s okay. And to remember, what follows isn’t a plain “ping”, but formatted in JSON.

If you use a port, your script/application needs to keep running as long as you want to be able to send messages to it. Typically you need to use a loop that keeps reading the stdin.

As you could read both the old an the updated version of my script, both uses the “while” loop.

There are multiple problems with your bash script.

:scream:

You need an infinite loop, like the Python script in the native messaging documentation. Otherwise, the script runs only once, before it has a chance to receive the message from Firefox. That’s what causes the “Attempt to postMessage on disconnected port” error.

Isn’t “while read line” an infinite loop?

When you wrap the code in an infinite loop, it creates a new file during every loop iteration. Manjaro Linux, at least, doesn’t like this; when I navigate the file manager to the directory where the file gets written, the file manager becomes unresponsive.

Sorry, but its irrelevant.

  1. This file is for tests (to know how the bash script performed when running out of a CLI window)
  2. Such file is written only once the addon’s button is clicked
  3. Nice promotion of Manjaro. I use my modified Ubuntu.

From what I’ve read, bash scripts can’t read binary data from stdin. And Firefox sends binary data to the native app; see freaktechnik’s post. The variable “line” contains the size header, or at least part of it, and in the next iteration, it contains the text “ping” (I think).

There are workarounds for that:


So instead of using echo , you can use printf , which supports the same sorts of escape sequences as `` -style strings. That way, you can print a null byte without having to have a null byte inside a string. That would look like this:…’` -style strings. That way, you can print a null byte without having to have a null byte inside a string. That would look like this:

That’s exactly what @rob did on its bash implementation that I’ve re-used.
Also, using an script based on zsh instead of bash can make this script less limited.

@rob
BTW there is an unanswered question using your bash implementation:

This could be very relevant to the purpose of the script you said that works and how I want to use it.