How do I use a shell-script as Chrome Native Messaging host application

前端 未结 1 620
独厮守ぢ
独厮守ぢ 2020-12-03 12:50

How do you process a Chrome Native Messaging API-call with a bash script?

I succeeded in doing it with python with this example

Sure I can call bash

相关标签:
1条回答
  • 2020-12-03 13:25

    I suggest to not use (bash) shell scripts as a native messaging host, because bash is too limited to be useful.

    read without any parameters reads a whole line before terminating, while the native messaging protocol specifies that the first four bytes specify the length of the following message (in native byte order).

    Bash is a terrible tool for processing binary data. An improved version of your read command would specify the -n N parameter to stop reading after N characters (note: not bytes) and -r to remove some processing. E.g. the following would store the first four characters in a variable called var_prefix:

    IFS= read -rn 4 var_prefix
    

    Even if you assume that this stores the first four bytes in the variable (it does not!), then you have to convert the bytes to an integer. Did I already mention that bash automatically drops all NUL bytes? This characteristics makes Bash utterly worthless for being a fully capable native messaging host.

    You could cope with this shortcoming by ignoring the first few bytes, and start parsing the result when you spot a { character, the beginning of the JSON-formatted request. After this, you have to read all input until the end of the input is found. You need a JSON parser that stops reading input when it encounters the end of the JSON string. Good luck with writing that.

    Generating output is a easier, just use echo -n or printf.

    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, I strongly recommend to not use bash, but a richer (scripting) language such as Python or C++.

    #!/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": "Hello world!"}'
        # 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
    
    0 讨论(0)
提交回复
热议问题