# WebExtension with Native messaging C++ App side

**URL:** <https://discourse.mozilla.org/t/webextension-with-native-messaging-c-app-side/30821>\
**Category:** Development\
**Created:** [August 9, 2018, 6:36pm UTC](https://discourse.mozilla.org/t/webextension-with-native-messaging-c-app-side/30821 "2018-08-09T18:36:24Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![mr.yattle](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/mr.yattle/32/23911_2.png) [@mr.yattle](https://discourse.mozilla.org/u/mr.yattle)\
**Post date:** [August 9, 2018, 6:36pm UTC](https://discourse.mozilla.org/t/webextension-with-native-messaging-c-app-side/30821/1 "2018-08-09T18:36:24Z")

</div>

Hope this will we helpful 🙂

> **[Native messaging - Mozilla | MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging)**
>
> Native messaging enables an extension to exchange messages with a native application, installed on the user's computer. The native messaging serves the extensions without additional accesses over the web.

App side C++ porting

```auto
#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"));
    }
}

```

---

<div class="post-metadata">

**Author:** ![freaktechnik](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/freaktechnik/32/37766_2.png) [@freaktechnik](https://discourse.mozilla.org/u/freaktechnik)\
**Post date:** [August 9, 2018, 10:01pm UTC](https://discourse.mozilla.org/t/webextension-with-native-messaging-c-app-side/30821/2 "2018-08-09T22:01:17Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![mr.yattle](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/mr.yattle/32/23911_2.png) [@mr.yattle](https://discourse.mozilla.org/u/mr.yattle)\
**Post date:** [August 11, 2018, 7:00am UTC](https://discourse.mozilla.org/t/webextension-with-native-messaging-c-app-side/30821/4 "2018-08-11T07:00:54Z")

</div>

Thx for you suggestion [freaktechnik](https://discourse.mozilla.org/t/webextension-with-native-messaging-c-app-side/30821/2)

---

<div class="post-metadata">

**Author:** ![LeonIRL](https://avatars.discourse-cdn.com/v4/letter/l/a6a055/32.png) [@LeonIRL](https://discourse.mozilla.org/u/LeonIRL)\
**Post date:** [December 1, 2019, 6:02am UTC](https://discourse.mozilla.org/t/webextension-with-native-messaging-c-app-side/30821/5 "2019-12-01T06:02:11Z")

</div>

Very useful! Thanks very much.

---

<div class="post-metadata">

**Author:** ![LeonIRL](https://avatars.discourse-cdn.com/v4/letter/l/a6a055/32.png) [@LeonIRL](https://discourse.mozilla.org/u/LeonIRL)\
**Post date:** [December 1, 2019, 7:27am UTC](https://discourse.mozilla.org/t/webextension-with-native-messaging-c-app-side/30821/6 "2019-12-01T07:27:45Z")

</div>

> [@mr.yattle](#):
>
> // 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);

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?

---

<div class="post-metadata">

**Author:** ![LeonIRL](https://avatars.discourse-cdn.com/v4/letter/l/a6a055/32.png) [@LeonIRL](https://discourse.mozilla.org/u/LeonIRL)\
**Post date:** [December 1, 2019, 7:35am UTC](https://discourse.mozilla.org/t/webextension-with-native-messaging-c-app-side/30821/7 "2019-12-01T07:35:25Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![guest271314](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/guest271314/32/29915_2.png) [@guest271314](https://discourse.mozilla.org/u/guest271314)\
**Post date:** [March 27, 2022, 6:21am UTC](https://discourse.mozilla.org/t/webextension-with-native-messaging-c-app-side/30821/8 "2022-03-27T06:21:30Z")

</div>

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());
    }
  }
}
```
