Как отправить сообщение дочернему процессу в надстройке Firefox, например собственный обмен сообщениями Chrome

Я пытаюсь эмулировать встроенную функцию обмена сообщениями Chrome, используя дополнительный SDK Firefox. В частности, я использую модуль child_process. вместе с методом отправки для связи с дочерним процессом 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, но я изо всех сил пытаюсь собрать все вместе.


comment
А если отправить без кодировки в utf8? Делать кодировку на другой стороне? В OS.File мы должны иметь дело только с буфером массива и обрабатывать кодирование на концах.   -  person Noitidart    schedule 17.04.2016


Ответы (2)


Проблема здесь в том, что Firefox по умолчанию пытается прочитать стандартный вывод как поток 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);
});
person humanoid    schedule 18.04.2016
comment
не помогает, поскольку Firefox продолжает отправлять данные в кодировке utf8 в EXE. - person Alexander Dyagilev; 01.12.2016
comment
@AlexanderDyagilev Это решение не касается бита отправки, оно описывает, как декодировать входящий поток. См. вопрос об отправке бита (дополнение к дочернему процессу). Но я бы рекомендовал использовать WebExtensions или хотя бы встроенное WebExtension, чтобы сделать это сейчас и не использовать sdk/child-process - person humanoid; 04.12.2016

Возможно, это похоже на эту проблему: Собственный обмен сообщениями Chrome не не принимать сообщения определенных размеров (Windows)

Только для Windows: убедитесь, что режим ввода-вывода программы установлен на O_BINARY. По умолчанию режим ввода-вывода — O_TEXT, что искажает формат сообщения, поскольку разрывы строк (\n = 0A) заменяются окончаниями строк в стиле Windows (\r\n = 0D 0A). Режим ввода-вывода можно установить с помощью __setmode.

person DragoM    schedule 18.04.2016
comment
Спасибо. Я думаю, что это ценная информация, но не применимая к этой конкретной проблеме. Во-первых, я не на Windows. Во-вторых, я получаю правильные данные обратно в надстройку, просто они в неправильном формате (по умолчанию в кодировке символов UTF-8 вместо необработанных байтов). - person Kurt; 18.04.2016