Related posts:
With good answers from: @hans_squared and @juraj.masiar
(hope they can help here, too).
Related posts:
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.
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.
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.
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
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:
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:
Things that can be wrong, to be checked:
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.
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.
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:
There are multiple problems with your bash script.
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 withwhile 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.
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.
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 useprintf
, 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.
BTW I can do it: Python script gets the ping, repasses to the Bash script, and pong: the bash script repasses to the Python script that repasses to the addon.
So, the browser/addon and the Bash script are still the transmitters/receivers, and the Python script is the medium.