如何在Firefox插件中向子进程发送消息,如Chrome原生消息

How to message child process in Firefox add-on like Chrome native messaging

本文关键字:消息 原生 Chrome Firefox 插件 子进程      更新时间:2023-09-26

我正在尝试使用Firefox的附加SDK来模拟Chrome的本地消息传递功能。具体来说,我使用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做些什么,但我很难把所有东西都放在一起。

这里的问题是,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原生消息;t接受特定大小的消息(Windows)

仅限Windows:确保程序的I/O模式设置为O_BINARY。默认情况下,I/O模式为O_TEXT,这会破坏消息格式,因为换行符(=0A)被替换为Windows样式的换行符(''r''n=0D 0A)。可以使用__setmode设置I/O模式。