Javascript 在Chrome本机消息中:本机应用程序实例对象的生命周期有多长?

Javascript 在Chrome本机消息中:本机应用程序实例对象的生命周期有多长?,javascript,google-chrome-extension,chrome-native-messaging,nativeapplication,Javascript,Google Chrome Extension,Chrome Native Messaging,Nativeapplication,与Chrome扩展通信的本机应用程序是否永远处于活动状态?我的意思是它是否应该出现,例如在回发之前?我找不到要添加到清单文件中的任何配置 我有一个页面,页面上有一些对象。单击一个对象并使用本机应用发送/接收一条消息后,它将不再适用于其他对象 我的确切问题:本机应用实例对象的生命周期有多长?该对象是否应响应,例如永久?或者,如果这是连续通信,我是否需要一个循环,例如从stdin读取消息 这是我的背景脚本: var host_name = "files.mffta.java.nativeapp";

与Chrome扩展通信的本机应用程序是否永远处于活动状态?我的意思是它是否应该出现,例如在回发之前?我找不到要添加到清单文件中的任何配置

我有一个页面,页面上有一些对象。单击一个对象并使用本机应用发送/接收一条消息后,它将不再适用于其他对象

我的确切问题:本机应用实例对象的生命周期有多长?该对象是否应响应,例如永久?或者,如果这是连续通信,我是否需要一个循环,例如从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"]}]
} 
我的扩展清单:

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");
        }
    }
}
import java.io.IOException;
导入javax.swing.JOptionPane;
公共类小程序{
公共小程序(){}
公共静态void main(字符串[]args){
试一试{
readMessage();
sendMessage(“{\“msg\”:\“hello\”);
}捕获(例外情况除外){
showMessageDialog(null,例如getMessage());
}
}
公共静态字符串readMessage(){
字符串msg=“”;
试一试{
int c,t=0;
对于(int i=0;i>8)&0xFF);
系统输出写入((字节)((数据长度>>16)和0xFF));
系统输出写入((字节)((数据长度>>24)和0xFF));
//写信息本身
System.out.write(msgdata.getBytes());
System.out.flush();
}捕获(IOE异常){
showMessageDialog(null,“向JS发送消息时出错”);
}
}
}
通过查看chrome日志,我可以看到以下消息:

  • 本机消息传递主机尝试发送1936028240字节长的消息
  • {“消息”:“与本机消息传递主机通信时出错。”},来源:chrome-extension://XXX
我正在64位Win 8.0机器上测试这些

更新: 我现在确信,如果调用connectNative并且端口没有因错误而停止,那么主机将永远处于活动状态。因此,上述错误消息的根本原因肯定不是端口生存期。我的意思是,通信中的某些错误会强制停止端口

我非常感谢您提供的任何意见。

如果使用,本机应用程序将在收到消息后和发送消息前立即出现。由于消息的接收是异步的,因此在调用
sendNativeMessage
的回调时,您不能假定应用程序仍然处于活动状态

如果要确保本机应用停留的时间更长,请使用。这将创建一个端口,本机应用将一直处于活动状态,直到退出或扩展调用
disconnect()
在端口上。如果您的应用程序意外提前终止,则您很可能在执行本机消息传递协议时出错

有关本机消息传递协议的确切格式,请参阅文档:


对于您的编辑,错误消息非常清楚:长度无效。长度应为系统的本机字节顺序(可以是或)。当您收到以下偏移量差异过大的arror消息时,有两种可能性:

  • 整数的字节顺序不正确,或
  • 您的输出包含一些意外字符,这会导致字节移位,并导致字节位于不正确的位置
  • 要知道您处于哪种情况,请将该数字视为十六进制数字。如果有许多尾随的零,则表明字节顺序不正确。例如,如果消息长度为59,则十六进制值为
    3b
    。如果尾数不正确,则显示以下消息:

    本机消息传递主机尝试发送长度为9855744字节的消息

    1493172224是十六进制表示法中的
    3b 00 00
    ,您可以观察到
    3b
    在那里,但在错误的一端(换句话说,字节顺序颠倒)。系统解决此问题的方法是编辑代码,以相反的顺序打印字节

    如果数字的十六进制视图看起来与您的数字不太接近,则消息长度可能不正确。回想一下,stdio是用于通信的,因此如果您向stdout(
    System.out
    )而不是stderr(
    System.err
    )输出任何其他内容(例如错误),则违反协议,您的应用程序将被终止


    System.err.println(例如getStackTrace());//有一件事我没有测试:如果端口对象是垃圾收集的,这会杀死进程吗?@Xan一个好问题,我现在不知道答案。我知道当响应回调未被调用时,端口会断开连接并被销毁
    onMessage
    (尽管
    return true;
    ),但我不确定当创建者丢弃端口时端口会发生什么情况。它可能会继续存在,但您必须测试这一点或深入源代码才能确定。嗯,什么?“当消息上未调用响应回调时,端口断开连接并被销毁“-听起来很奇怪-你必须用消息回答每个传入消息?@Xan通常不是,我之前的评论是指当扩展是端口的接收器时的情况(这与本机消息无关,仅与扩展/外部可连接消息相关)。发送
    onMessage
    后,端口会自动关闭,除非使用了
    return true;
    。如果分机忘记调用响应回调,Chrome仍会在garbag期间销毁接收到的端口