我正在使用Chrome的本机消息传递API将页面的DOM传递给主机。当我尝试将一个小字符串从扩展名传递到主机时,一切正常,但是当我尝试传递整个DOM(不是那么大…仅260KB左右)时,一切运行都慢得多,最终我得到了Native host has exited error阻止主机响应。
Native host has exited error
我的主要问题:为什么将250KB-350KB的消息从扩展名传递到主机需要这么长时间?
根据开发者的网站:
Chrome会在一个单独的进程中启动每个本机消息传递主机,并使用标准输入(stdin)和标准输出(stdout)与之通信。双向使用相同的格式发送消息:每条消息都使用JSON(UTF-8编码)进行序列化,并以本机字节顺序开头32位消息长度。来自本地消息传递主机的单个消息的最大大小为1 MB,主要是为了防止Chrome出现异常的本地应用程序行为。 发送到本地消息传递主机的消息的最大大小为4 GB。
我有兴趣发送给主机的页面的DOM不超过260KB(有时为300KB),远低于施加的最大4GB。
popup.js
document.addEventListener('DOMContentLoaded', function() { var downloadButton = document.getElementById('download_button'); downloadButton.addEventListener('click', function() { chrome.tabs.query({currentWindow: true, active: true}, function (tabs) { chrome.tabs.executeScript(tabs[0].id, {file: "getDOM.js"}, function (data) { chrome.runtime.sendNativeMessage('com.google.example', {"text":data[0]}, function (response) { if (chrome.runtime.lastError) { console.log("Error: " + chrome.runtime.lastError.message); } else { console.log("Response: " + response); } }); }); }); }); });
主机程序
private static string StandardOutputStreamIn() { Stream stdin = new Console.OpenStandardInput(); int length = 0; byte[] bytes = new byte[4]; stdin.Read(bytes, 0, 4); length = System.BitConverter.ToInt32(bytes, 0); string = ""; for (int i=0; i < length; i++) string += (char)stdin.ReadByte(); return string; }
请注意,我从这个问题中找到了上述方法。
目前,我只是想将字符串写入.txt文件:
public void Main(String[] args) { string msg = OpenStandardStreamIn(); System.IO.File.WriteAllText(@"path_to_file.txt", msg); }
我已经getDOM.js通过下载文件测试了我的功能,并且整个过程几乎是瞬时的。
getDOM.js
我不确定为什么这个过程要花费这么长时间,为什么文件如此之大,或者为什么实际上几乎没有发送任何消息。
我不确定这是否与以特定方式反序列化消息有关,是否应该创建端口而不是使用chrome.runtime.sendNativeMessage(...);方法,或者是否完全缺少其他内容。
chrome.runtime.sendNativeMessage(...);
非常感谢所有帮助!谢谢!
编辑
尽管我的消息是正确地从扩展名发送到主机的,但我现在Native host has exited error在扩展名接收到主机的消息之前收到了。
这个问题本质上是在问: “我如何高效,快速地从标准输入中读取信息?”
在上面的代码中,问题不在Chrome扩展程序和主机之间,而是在标准输入和从标准输入流读取的方法之间,即StandardOutputStreamIn()。
StandardOutputStreamIn()
该方法在OP代码中的工作方式是,循环在标准输入流中运行,并将input字符串与新字符串(即从字节流中读取的字符)连续连接在一起。这是一项 昂贵的 操作,我们可以通过创建一个StreamReader对象来立即抓取整个流来解决此问题(特别是因为我们知道前4个字节中包含的长度信息)。因此,我们通过以下方式解决了速度问题:
input
StreamReader
public static string OpenStandardStreamIn() { //Read 4 bytes of length information System.IO.Stream stdin = Console.OpenStandardInput(); int length = 0; byte[] bytes = new byte[4]; stdin.Read(bytes, 0, 4); length = System.BitConverter.ToInt32(bytes, 0); char[] buffer = new char[length]; using (System.IO.StreamReader sr = new System.IO.StreamReader(stdin)) { while (sr.Peek() >= 0) { sr.Read(buffer, 0, buffer.Length); } } string input = new string(buffer); return input; }
虽然这解决了速度问题,但我不确定扩展名为何抛出Native host has exited error。