WebExtension with Native messaging C++ App side

Hope this will we helpful :slight_smile:

App side C++ porting

#include <iostream>
#include <string>
#include <json.hpp>

using namespace std;
using namespace nlohmann;


struct message_t {
    string content;
    uint32_t length;
};

// Read a message from stdin and decode it.
json get_message() {
    char raw_length[4];
    fread(raw_length, 4, sizeof(char), stdin);
    uint32_t message_length = *reinterpret_cast<uint32_t*>(raw_length);
    if(!message_length)
        exit(EXIT_SUCCESS);

    char message[message_length];
    fread(message, message_length, sizeof(char), stdin);
    string m( message, message + sizeof message / sizeof message[0] );
    return json::parse(m);
}

// Encode a message for transmission, given its content.
message_t encode_message(json content) {
    string encoded_content = content.dump();
    message_t m;  
    m.content = encoded_content;
    m.length = (uint32_t) encoded_content.length();    
    return m;
}

// Send an encoded message to stdout.
void send_message(message_t encoded_message) {
    char* raw_length = reinterpret_cast<char*>(&encoded_message.length);
    fwrite (raw_length , 4, sizeof(char), stdout);
    fwrite (encoded_message.content.c_str(), encoded_message.length, sizeof(char), stdout);
    fflush(stdout);
}

int main(int argc, char *argv[])
{
    while(true) {
        json message = get_message();
        if(message == "ping")
            send_message(encode_message("pong"));
    }
}
1 Like

You can use ``` to start and end code blocks, and if you do ```cpp or similar you start a code block with c++ syntax highlighting.

2 Likes

Thx for you suggestion freaktechnik

Very useful! Thanks very much.

Can you please explain what exactly is going on here? As I understand it, the first fread() gets the length, i.e. number of bytes, of the JSON that is present on stdin?

NVM I should have read the docs:

Each message is serialized using JSON, UTF-8 encoded and is preceded with a 32-bit value containing the message length in native byte order.

1 Like

Thanks for sharing the code.

A version that does not rely on <nlohmann/json> (json.hpp).

Note exclusion of beginning and ending dounble quotation marks in input to pass to popen().

// C++ Native Messaging host
// https://browserext.github.io/native-messaging/
// https://developer.chrome.com/docs/apps/nativeMessaging/
// https://discourse.mozilla.org/t/webextension-with-native-messaging-c-app-side/30821
#include <iostream>
#include <sstream>
using namespace std;

void sendMessage(string message) {
  auto* data = message.data();
  auto size = uint32_t(message.size());
  char* length = reinterpret_cast<char*>(&size);
  fwrite(length, 4, sizeof(char), stdout);
  fwrite(message.c_str(), message.length(), sizeof(char), stdout);
  fflush(stdout);
}

string getMessage() {
  char length[4];
  fread(length, 4, sizeof(char), stdin);
  uint32_t len = *reinterpret_cast<uint32_t*>(length);
  if (!len) {
    exit(EXIT_SUCCESS);
  }
  char message[len];
  fread(message, len, sizeof(char), stdin);
  string content(message, message + sizeof message / sizeof message[0]);
  return content;
}

int main() {
  while (true) {
    auto message = getMessage();
    const char* command = message.data();
    stringstream input;
    // Exclude double quotation marks from beginning and end of string
    for (int j = 1; j < message.length() - 1; j++) {
      input << message[j];
    }
    FILE* pipe = popen(input.str().c_str(), "r");
    while (true) {
      unsigned char buffer[1024];
      int count = fread(buffer, 1, sizeof buffer, pipe);
      if (count == 0 || count == -1) {
        break;
      }
      stringstream output;
      output << "[";
      for (int i = 0; i < count; i++) {
        output << (int)buffer[i];
        if (i < count - 1) {
          output << ",";
        }
      }
      output << "]";
      sendMessage(output.str());
    }
  }
}