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
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);
}
Top comments (0)