2

Chrome 拡張機能と対話するネイティブ アプリケーションは永遠に存続しますか? たとえば、ポストバックが発生する前に存在する必要がありますか?マニフェスト ファイルに追加する構成が見つかりませんでした。

私はページを持っています。ページにはいくつかのオブジェクトがあります。オブジェクトをクリックし、ネイティブ アプリで 1 つのメッセージを送受信すると、残りのオブジェクトでは機能しなくなります。

私の正確な質問: ネイティブ アプリ インスタンス オブジェクトの有効期間はどのくらいですか? そのオブジェクトは、たとえば永遠に応答する必要がありますか? または、これが継続的な通信である場合、stdin からメッセージを読み取るなどのループが必要ですか?

これが私のバックグラウンドスクリプトです:

var host_name = "files.mffta.java.nativeapp";
var port = null;
initPort();
function initPort() {
    console.log( 'Connecting to native host: ' + host_name );
    port = chrome.runtime.connectNative( host_name );
    port.onMessage.addListener( onNativeMessage );
    port.onDisconnect.addListener( onDisconnected );
}

// Listen for messages that come from the content script.
chrome.runtime.onMessage.addListener(
  function( messageData, sender, sendResponse ) {
    if( messageData ) {
        sendNativeMessage(messageData);
        sendResponse( { res: 'done!' } );
    }
  } );

// Sending a message to the port.
function sendNativeMessage(messageData) {
    if( port == null )
        initPort();
    console.log( 'Sending message to native app: ' + JSON.stringify( messageData ) );
    port.postMessage( messageData );
    console.log( 'Sent message to native app.' );
}

// Receiving a message back from the Native Client API.
function onNativeMessage( message ) {
    console.log( 'recieved message from native app: ' + JSON.stringify( message ) );

    alert( "messaged received from Native: " + JSON.stringify( message ) );
    //sending a message to Content Script to call a function
    if( message.methodName && message.methodName != "" ) {
        chrome.tabs.query( { active: true, currentWindow: true }, function( tabs ) {
            chrome.tabs.sendMessage( tabs[0].id, message, function( response ) {
                // Call native again to return JavaScript callback function results
                alert ("calc res received by extension : " + response);
                sendNativeMessage({ type: "JSCallbackRes", callbackRes: response });
            } );
        } );
    }
}

// Disconnecting the port.
function onDisconnected() {
    console.log( "ERROR: " + JSON.stringify( chrome.runtime.lastError ) );
    console.log( 'disconnected from native app.' );
    port = null;
}

私の拡張マニフェスト:

{
  "name": "Files.ChromeExt.Operarations",
  "version": "1.0",
  "manifest_version": 2,
  "description": "This extension calls a Native API which that API calls some x-Files related operations.",
  "icons": {
    "128": "x-files_icon.png"
  },
  "permissions": [
    "nativeMessaging", "activeTab"
  ],
  "background": {
    "persistent": true,
    "scripts": ["main.js"]
  },
  "content_scripts" : [{"matches": ["http://localhost/*","https://localhost/*"], 
    "js": ["contentscripts/page.js"]}]
} 

Javaプログラム: [コメントで尋ねられたように]

import java.io.IOException;
import javax.swing.JOptionPane;

public class Applet {

    public Applet(){}

    public static void main(String[] args) {
        try {
            readMessage();
            sendMessage("{\"msg\" : \"hello\"}");

        } catch (Exception ex) {
            JOptionPane.showMessageDialog(null, ex.getMessage());
        }
    }

    public static String readMessage() {
        String msg = "";
        try {
            int c, t = 0;
            for (int i = 0; i <= 3; i++) {
                t += Math.pow(256.0f, i) * System.in.read();
            }

            for (int i = 0; i < t; i++) {
                c = System.in.read();
                msg += (char) c;
            }
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, "error in reading message from JS");
        }
        return msg;
    }

    public static void sendMessage(String msgdata) {
        try {
            int dataLength = msgdata.length();
            System.out.write((byte) (dataLength & 0xFF));
            System.out.write((byte) ((dataLength >> 8) & 0xFF));
            System.out.write((byte) ((dataLength >> 16) & 0xFF));
            System.out.write((byte) ((dataLength >> 24) & 0xFF));

            // Writing the message itself
            System.out.write(msgdata.getBytes());
            System.out.flush();
        } catch (IOException e) {
            JOptionPane.showMessageDialog(null, "error in sending message to JS");
        }
    }
}

Chrome ログを調べると、次のメッセージが表示されます。

  • ネイティブ メッセージング ホストは、長さが 1936028240 バイトのメッセージを送信しようとしました。
  • {"メッセージ":"ネイティブ メッセージング ホストとの通信中にエラーが発生しました。"}"、ソース: chrome-extension://XXX

これらを Win 8.0 マシン 64 ビットでテストしています。

更新: connectNative が呼び出され、ポートがエラーによって停止されていない場合、ホストは永遠に生きていると確信しています。したがって、上記のエラー メッセージの根本的な原因は、ポートの有効期間以外にあるはずです。つまり、通信エラーによりポートが強制的に停止されているということです。

コメントをいただければ幸いです。

4

1 に答える 1

3

を使用する場合chrome.runtime.sendNativeMessage、ネイティブ アプリは、メッセージを受信した直後と送信する前に存在します。メッセージの受信は非同期であるため、 のコールバックsendNativeMessageが呼び出されたときにアプリがまだ生きていると想定することはできません。

ネイティブ アプリをより長く存続させたい場合は、 を使用しますchrome.runtime.connectNative。これによりポートが作成され、ネイティブ アプリは終了するまで、またはdisconnect()ポートで拡張機能が呼び出されるまで存続します。アプリが予期せず早期に終了する場合は、ネイティブ メッセージング プロトコルの実装でエラーが発生した可能性があります。

ネイティブ メッセージング プロトコルの正確な形式については、 https ://developer.chrome.com/extensions/nativeMessaging#native-messaging-host-protocol のドキュメントをご覧ください。


編集に関しては、エラー メッセージは非常に明確です: 長さが無効です。長さは、システムのネイティブ バイト オーダー(リトル エンディアンまたはビッグ エンディアン) であると想定されています。オフセットの差が大きすぎる次のエラー メッセージが表示された場合は、次の 2 つの可能性があります。

  1. 整数のバイト順が正しくない、または
  2. 出力に予期しない文字が含まれているため、バイトがシフトされ、バイトが正しくない場所に配置されます。

どちらのケースに該当するかを知るには、数字を 16 進数として表示します。後続のゼロが多数ある場合は、バイト順が正しくないことを示しています。たとえば、メッセージの長さが 59 の場合、16 進数値は3b. エンディアンが正しくない場合、次のメッセージが表示されます。

ネイティブ メッセージング ホストが、長さが 989855744 バイトのメッセージを送信しようとしました。

1493172224 は3b 00 00 0016 進数表記で3bあり、 が存在することを確認できますが、末尾が間違っています (つまり、バイト順が逆になっています)。システムでこの問題を解決するには、コードを編集してバイトを逆順に出力します。

数値の 16 進数表示が実際の数値とあまり似ていない場合は、メッセージの長さが正しくない可能性があります。stdio が通信に使用されることを思い出してください。したがって、他のもの (エラーなど) をSystem.outstderr ( ) ではなく stdout ( ) に出力System.errすると、プロトコルに違反し、アプリが終了します。

        System.err.println(ex.getStackTrace());                     // <-- OK
        System.out.println("[ error -> " + ex.getMessage() + " ]"); // <-- BAD

Windows では、 stdout (および stdin)のモードが O_BINARY に設定されているかどうかも確認してください。0Aそうしないと、Windows は( ) の前に余分なバイトを挿入するため、0D 0Aすべてのバイトがシフトし、数値が正しくなくなります。Java ランタイムは既にバイナリ モードを有効にしているため、この場合は関係ありません。

于 2015-07-20T13:13:41.120 に答える