javascript - 在Chrome native 消息传递中: how long is the native app instance object lifetime?

标签 javascript google-chrome-extension chrome-native-messaging nativeapplication

与 Chrome 扩展程序交互的 native 应用程序会永远存在吗?我的意思是它是否应该存在,例如在回发发生之前?我找不到任何要添加到 list 文件中的配置。

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

我的确切问题: native 应用实例对象的生命周期是多长?该对象是否应该响应,例如永远?或者我需要一个循环,例如如果这是连续通信,则从标准输入读取消息?

这是我的背景脚本:

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;
}

我的扩展 list :

{
  "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 日志,我可以看到这些消息:

  • Native Messaging 主机尝试发送长度为 1936028240 字节的消息。
  • {"message":"与 native 消息传递主机通信时出错。"}",来源:chrome-extension://XXX

我正在 Win 8.0 64 位机器上测试这些。

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

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

最佳答案

如果使用 chrome.runtime.sendNativeMessage , native 应用程序将在收到消息后和发送消息之前立即出现。由于消息的接收是异步的,因此当调用 sendNativeMessage 回调时,您不能假设应用程序仍然处于事件状态。

如果您想确保 native 应用程序停留更长时间,请使用 chrome.runtime.connectNative 。这会创建一个端口,并且 native 应用程序将一直处于事件状态,直到退出或扩展在端口上调用 disconnect() 为止。如果您的应用程序意外提前终止,那么您很可能在实现 native 消息传递协议(protocol)时犯了错误。

有关 native 消息协议(protocol)的确切格式,请查看文档: https://developer.chrome.com/extensions/nativeMessaging#native-messaging-host-protocol


对于您的编辑,错误消息非常明确:长度无效。长度应该采用系统的 native 字节顺序(可能是 little endianbig endian )。当您收到以下错误消息且偏移量差异过大时,有两种可能:

  1. 整数的字节顺序不正确,或者
  2. 您的输出包含一些意外字符,这会导致字节移位并导致字节位于不正确的位置。

要了解您属于哪种情况,请查看十六进制数字。如果有很多尾随零,则表明字节顺序不正确。例如,如果您的消息长度为 59,则十六进制值为 3b。如果字节序不正确,则会显示以下消息:

Native Messaging host tried sending a message that is 989855744 bytes long.

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

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

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

在 Windows 上,还请检查您是否已 set the mode对于标准输出(和标准输入)到 O_BINARY。否则Windows将在0A之前插入一个额外的字节(0D 0A),这会导致所有字节移位并且数字不正确。 The Java Runtime already enables binary mode ,所以对于你的情况来说它不相关。

关于javascript - 在Chrome native 消息传递中: how long is the native app instance object lifetime?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31515791/

相关文章:

javascript - jquery 代码在 ajax 加载的内容中不起作用

google-chrome-extension - 当我单击 Google Chrome 扩展程序的弹出图标时,如何触发内容脚本运行?

javascript - native 应用程序和 chrome-extension 之间的连接在一段时间后中断

google-chrome - 从 chrome 浏览器启动我安装的应用程序

javascript - 谷歌打包应用原生消息

javascript - 如何使用 select 和对象数组在 AngularJS 中设置模型的值

c# - 当计数超过最大限制时,取消选中第一个选中的复选框

javascript - 处理 aurelia 中的集合更新

javascript - Chrome 扩展 - 写入不同域的本地存储

javascript - 内容脚本在 Chrome 扩展中不起作用