1

Chrome のNative Messaging APIを使用して、ページの DOM をホストに渡しています。拡張機能からホストに小さな文字列を渡そうとすると、すべてが機能しますが、DOM 全体 (それほど大きくはありません... 約 260KB のみ) を渡そうとすると、すべての実行速度が大幅に低下し、最終的にはNative host has exited errorホストの応答を妨げます。

私の主な質問: 拡張機能からホストに 250KB から 350KB のメッセージを渡すのになぜそんなに時間がかかるのですか?

開発者のサイトによると:

Chrome は、個別のプロセスで各ネイティブ メッセージング ホストを起動し、標準入力 (stdin) と標準出力 (stdout) を使用して通信します。メッセージを両方向に送信するために同じ形式が使用されます。各メッセージは JSON を使用してシリアル化され、UTF-8 でエンコードされ、ネイティブ バイト オーダーで 32 ビット メッセージ長が前に付けられます。ネイティブ メッセージング ホストからの 1 つのメッセージの最大サイズは 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);
                    }
                });
            });
        });
    });
});

ホスト.exe

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);
}
  1. ファイルへの文字列の書き込みには長い時間がかかります (最大 4 秒、場合によっては最大 10 秒)。
  2. 実際に書き込まれるテキストの量はさまざまですが、最上位のドキュメント宣言といくつかの IE コメント タグ以上のものではありません。すべてのテキストが表示されるようになりました。
  3. テキストがほとんどないこのファイルは 649KB ですが、実際のドキュメントは 205KB しかないはずです (ダウンロード時)。ファイルは、本来あるべきサイズよりわずかに大きいままです (205KB のはずが 216KB)。

ファイルをダウンロードするだけで機能をテストしましgetDOM.jsたが、プロセス全体はほぼ瞬時です。

このプロセスに時間がかかる理由、ファイルが非常に大きい理由、または実際にメッセージがほとんど送信されていない理由がわかりません。

これが特定の方法でメッセージを逆シリアル化することと関係があるのか​​ 、メソッドを使用する代わりにポートを作成する必要chrome.runtime.sendNativeMessage(...);があるのか​​ 、それとも他に何か完全に欠けているものがあるのか​​ はわかりません.

すべてのヘルプは大歓迎です! ありがとうございました!


編集

私のメッセージは拡張機能からホストに正しく送信されていますが、Native host has exited error拡張機能がホストのメッセージを受信する前に受信しています。

4

1 に答える 1

2

この質問は本質的に、「標準入力から情報を効率的かつ迅速に読み取るにはどうすればよいですか?」という質問です。

上記のコードでは、問題は Chrome 拡張機能とホストの間ではなく、標準入力と標準入力ストリームから読み取るメソッド、つまりStandardOutputStreamIn().

OP のコードでメソッドが機能する方法は、ループが標準入力ストリームを実行し、input文字列を新しい文字列 (つまり、バイト ストリームから読み取る文字) と連続的に連結することです。これはコストのかかる操作であり、ストリーム全体を一度に取得するオブジェクトを作成することでこれを回避できますStreamReader(特に、最初の 4 バイトに含まれる長さ情報がわかっているため)。そのため、速度の問題を次のように修正します。

    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.

于 2014-12-26T23:08:09.813 に答える