/*** Native messaging "ping_pong" example in C. | |
* | |
* It is reimplementation of the corresponding Python example from | |
* https://github.com/mdn/webextensions-examples/tree/master/native-messaging | |
* | |
* # Python 3.x version | |
* # Read a message from stdin and decode it. | |
* def getMessage(): | |
* rawLength = sys.stdin.buffer.read(4) | |
* if len(rawLength) == 0: | |
* sys.exit(0) | |
* messageLength = struct.unpack('@I', rawLength)[0] | |
* message = sys.stdin.buffer.read(messageLength).decode('utf-8') | |
* return json.loads(message) | |
* | |
* # Encode a message for transmission, | |
* # given its content. | |
* def encodeMessage(messageContent): | |
* encodedContent = json.dumps(messageContent).encode('utf-8') | |
* encodedLength = struct.pack('@I', len(encodedContent)) | |
* return {'length': encodedLength, 'content': encodedContent} | |
* | |
* # Send an encoded message to stdout | |
* def sendMessage(encodedMessage): | |
* sys.stdout.buffer.write(encodedMessage['length']) | |
* sys.stdout.buffer.write(encodedMessage['content']) | |
* sys.stdout.buffer.flush() | |
* | |
* while True: | |
* receivedMessage = getMessage() | |
* if receivedMessage == "ping": | |
* sendMessage(encodeMessage("pong3")) | |
* | |
*/ | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
int main(void) | |
{ | |
uint32_t message_length; | |
// read messages and send response | |
while (fread(&message_length, sizeof message_length, 1, stdin) == 1) { | |
// read message into buffer | |
char *buf = malloc(message_length); | |
if (!buf) { | |
perror("malloc"); | |
return EXIT_FAILURE; | |
} | |
if (fread(buf, sizeof *buf, message_length, stdin) != message_length) { | |
perror("fread"); | |
return EXIT_FAILURE; | |
} | |
// check we got the "ping" message (JSON string) | |
char expected[] = u8"\"ping\""; | |
const uint32_t expected_length = (sizeof expected) - 1; // - null byte | |
if (strncmp(buf, expected, expected_length)) { | |
fprintf(stderr, "error: expected '%s', got: '%.*s' instead\n", expected, message_length, buf); | |
return EXIT_FAILURE; | |
} | |
// write response (JSON prefixed with its utf-8 length) | |
char response[] = u8"\"pong\""; | |
const uint32_t response_length = (sizeof response) - 1; // - null byte | |
if (fwrite(&response_length, sizeof response_length, 1, stdout) != 1 | |
|| fwrite(response, response_length, 1, stdout) != 1) { | |
perror("fwrite"); | |
return EXIT_FAILURE; | |
} | |
fflush(stdout); | |
// cleanup | |
free(buf); | |
} // end while | |
if (ferror(stdin)) | |
perror("can't read message length"); | |
// return success on EOF | |
return ! feof(stdin); | |
} |
It is not a good idea to ignore error in C. Switch to Python if you need an executable pseudo-code kind-of feel (at least Python would raise exceptions).
If there are errors the Native Messaging host will either not send the message or exit. I wrote the same code in Python, C++, C, and JavaScript.
It is not a good idea to ignore error in C. Switch to Python if you need an executable pseudo-code kind-of feel (at least Python would raise exceptions).
I don't think the errors from from C reach native_message_process_host.cc. E.g., on Chromium when passing a message from client to host that is greater than 1024*1024 (new Array(458*458)
) chrome.runtime.lastError
logs {message: 'Error when communicating with the native messaging host.'}
. To get the error message in native_message_process_host.cc I had to use
--enable-logging \
--log-level=0 \
--vmodule=native_message_process_host=0 \
--v=0
then search for
[...:ERROR:native_message_process_host.cc(300)] Native Messaging host tried sending a message that is 1048821 bytes long.
Echo input message