Как отправить сообщение дочернему процессу в Firefox add-on, как Chrome native messaging
Я пытаюсь эмулировать родную функцию обмена сообщениями Chrome с помощью дополнения Firefox SDK. В частности, я использую модуль child_process вместе с методом emit для связи с дочерним процессом python.
Я могу успешно отправлять сообщения в дочерний процесс, но у меня возникли проблемы с отправкой сообщений обратно в надстройку. Собственная функция обмена сообщениями Chrome использует stdin/stdout. Первые 4 байта каждого сообщения в обоих направлениях представляет размер в байтах следующего сообщения, чтобы получатель знал, сколько читать. Вот что у меня есть до сих пор:
Дополнение к дочернему процессу
var utf8 = new TextEncoder("utf-8").encode(message);
var latin = new TextDecoder("latin1").decode(utf8);
emit(childProcess.stdin, "data", new TextDecoder("latin1").decode(new Uint32Array([utf8.length])));
emit(childProcess.stdin, "data", latin);
emit(childProcess.stdin, "end");
Дочерний процесс (Python) из дополнения
text_length_bytes = sys.stdin.read(4)
text_length = struct.unpack('i', text_length_bytes)[0]
text = sys.stdin.read(text_length).decode('utf-8')
Дочерний процесс для дополнения
sys.stdout.write(struct.pack('I', len(message)))
sys.stdout.write(message)
sys.stdout.flush()
Дополнение из дочернего процесса
Вот где я борюсь. У меня он работает, когда длина меньше 255. Например, если длина равна 55, это работает:
childProcess.stdout.on('data', (data) => { // data is '7' (55 UTF-8 encoded)
var utf8Encoded = new TextEncoder("utf-8).encode(data);
console.log(utf8Encoded[0]); // 55
}
Но, как я уже сказал, это не работает. для всех чисел. Я уверен, что должен что-то сделать с TypedArrays, но я изо всех сил пытаюсь собрать все вместе.2 ответа:
Проблема здесь в том, что Firefox по умолчанию пытается читать stdout как поток UTF-8. Поскольку UTF-8 не использует полный первый байт, вы получаете поврежденные символы, например, для 255. Решение состоит в том, чтобы сказать Firefox читать в двоичном кодировании, что означает, что вам придется вручную анализировать фактическое содержание сообщения позже.
var childProcess = spawn("mybin", [ '-a' ], { encoding: null });
Тогда ваш слушатель будет работать как
var decoder = new TextDecoder("utf-8"); var readIncoming = (data) => { // read the first four bytes, which indicate the size of the following message var size = (new Uint32Array(data.subarray(0, 4).buffer))[0]; //TODO: handle size > data.byteLength - 4 // read the message var message = decoder.decode(data.subarray(4, size)); //TODO: do stuff with message // Read the next message if there are more bytes. if(data.byteLength > 4 + size) readIncoming(data.subarray(4 + size)); }; childProcess.stdout.on('data', (data) => { // convert the data string to a byte array // The bytes got converted by char code, see https://dxr.mozilla.org/mozilla-central/source/addon-sdk/source/lib/sdk/system/child_process/subprocess.js#357 var bytes = Uint8Array.from(data, (c) => c.charCodeAt(0)); readIncoming(bytes); });
Может быть, это похоже на эту проблему: Chrome native messaging не принимает сообщения определенного размера (Windows)
Только для Windows: убедитесь, что режим ввода-вывода программы установлен в O_BINARY. По умолчанию режим ввода-вывода-O_TEXT, который искажает формат сообщения, поскольку разрывы строк (\n = 0A) заменяются окончаниями строк в стиле Windows (\r\n = 0D 0A). Режим ввода-вывода можно задать с помощью __setmode.