DEV Community

Emile M.
Emile M.

Posted on • Edited on

How to send native message via Dart for Browser Extensions (Chrome, Firefox)

When developing an extension for multiple browsers, you may need an application (either local or cloud-based) that can manage or share state & logic across the extensions/browsers. If the local application route is your preferred choice, browsers have a protocol, called Native Messaging Protocol, to communicate with local applications via standard-in and standard-out.

This post explains how to send & receive those native messages in a compiled Dart code host application.

Context

Mozilla's Excellent Docs on Native Messaging

Introduction to Native Message Protocol specifics

Native Message image

Messages are sent as UTF8-encoded JSON preceded by a 32bit unsigned length in native byte order.

stdout.write() encodes the output provided to the write() function which causes issues since the native messaging protocol requires header have length of data sent in bytes.
So stdout.add() (which does not encode during output) needs to be used

data being send should be valid JSON, in order to match native messaging protocol requirements

Sample Code

import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

/// Send out JSON String native message to browser extension 
static sendNativeMessage(String data) {
  //Convert int to bytes
  Uint8List int32bytes(int value) => Uint8List(4)..buffer.asByteData().setUint32(0, value, Endian.host);

  //Convert data into utf8-encoded bytes
  final encodedData = utf8.encode(data) as Uint8List;

  //Output the encoded data's length as bytes
  stdout.add(int32bytes(encodedData.length));
  //Output the encoded data's bytes
  stdout.add(encodedData);
  stdout.flush();
}

/// Receive Native Message bytes and decode to JSON String
static String receiveNativeMessage(List<int> data) {
  //Get new mutable list from a immutable list
  final dataBytes = List.of(data);

  //Remove the length bytes from bytes list that are part of native messaing protocol spec.
  //(The first 4 hex bytes)
  dataBytes.removeRange(0, 4);

  //Decode from bytes list to JSON string
  return utf8.decode(dataBytes);
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)