本机消息传递主机 chrome-token-signing

Posted

技术标签:

【中文标题】本机消息传递主机 chrome-token-signing【英文标题】:native messaging host chrome-token-signing 【发布时间】:2017-05-19 10:27:02 【问题描述】:

我正在尝试制作一个与本地消息传递主机 chrome-token-signing (https://github.com/open-eid/chrome-token-signing) 通信的扩展。 我已经安装了扩展,但是 EXE 没有启动。我有消息日志 TEST: "message":"Invalid argument","re​​sult":"invalid_argument" 我需要做些什么吗

我已经在注册表中安装了主机,例如 HKEY_LOCAL_MACHINE\software\Google\Chrome\NativeMessagingHosts\ee.ria.esteid 和值 C:\Users\dev\Desktop\chrome-token-signing\host-windows\ee.ria.esteid.json

原生应用 manifest.json:



"name": "ee.ria.esteid",

"description": "Give signatures with your eID on the web",

"path": "chrome-token-signing.exe",

"type": "stdio",

"allowed_origins": [

    "chrome-extension://ckjefchnfjhjfedoccjbhjpbncimppeg/"

]

   

扩展名的manifest.json



"name": "Token signing",
"version": "0.0.24",
"minimum_chrome_version": "40.0",
"manifest_version": 2,
"description": "Use your eID smart card on the web",
"icons": 
    "48": "icon48.png",
    "128": "icon128.png"
,
"content_scripts": [
    "matches": ["*://*/*", "file:///*"],
    "exclude_matches": ["*://www.overdrive.com/*"],
    "js": ["content.js"],
    "run_at": "document_end",
    "all_frames": true
],
"background": 
    "scripts": ["background.js"]
,
"permissions": ["nativeMessaging"],
"applications": 
    "gecko": 
        "id": "443830f0-1fff-4f9a-aa1e-444bafbc7319"
  
   
    

background.js

      var NO_NATIVE_URL = "https://open-eid.github.io/chrome-token-signing/missing.html";

      var HELLO_URL = "https://open-eid.github.io/chrome-token-signing/hello.html";

      var DEVELOPER_URL = "https://github.com/open-eid/chrome-token-  signing/wiki/DeveloperTips";

      var NATIVE_HOST = "ee.ria.esteid";

      var K_SRC = "src";
      var K_ORIGIN = "origin";
      var K_NONCE = "nonce";
      var K_RESULT = "result";
      var K_TAB = "tab";
      var K_EXTENSION = "extension";

      // Stores the longrunning ports per tab
      // Used to route all request from a tab to the same host instance
      var ports = ;

      // Probed to false if host component is OK.
       var missing = true;

      console.log("Background page activated");

      // XXX: probe test, because connectNative() does not allow to check the presence
       // of native component for some reason
      typeof chrome.runtime.onStartup !== 'undefined' &&       chrome.runtime.onStartup.addListener(function() 
// Also probed for in onInstalled()
_testNativeComponent().then(function(result) 
    if (result === "ok") 
        missing = false;
    
);
      );

    // Force kill of native process
   // Becasue Port.disconnect() does not work
   function _killPort(tab) 
if (tab in ports) 
    console.log("KILL " + tab);
    // Force killing with an empty message
    ports[tab].postMessage();

     

       // Check if native implementation is OK resolves with "ok", "missing" or "forbidden"
      function _testNativeComponent() 
return new Promise(function(resolve, reject) 
    chrome.runtime.sendNativeMessage(NATIVE_HOST, , function(response) 
        if (!response) 
            console.log("TEST: ERROR " + JSON.stringify(chrome.runtime.lastError));
            // Try to be smart and do some string matching
            var permissions = "Access to the specified native messaging host is forbidden.";
            var missing = "Specified native messaging host not found.";
            if (chrome.runtime.lastError.message === permissions) 
                resolve("forbidden")
             else if (chrome.runtime.lastError.message === missing) 
                resolve("missing");
             else 
                resolve("missing");
            
         else 
            console.log("TEST: " + JSON.stringify(response));
            if (response["result"] === "invalid_argument") 
                resolve("ok");
             else 
                resolve("missing"); // TODO: something better here
            
        
    );
);
        

      // When extension is installed, check for native component or direct to helping page
      typeof chrome.runtime.onInstalled !== 'undefined' && chrome.runtime.onInstalled.addListener(function(details) 
if (details.reason === "install" || details.reason === "update") 
    _testNativeComponent().then(function(result) 
            var url = null;
            if (result === "ok" && details.reason === "install") 
                // Also set the flag, onStartup() shall be called only
                // on next startup
                missing = false;
                // TODO: Add back HELLO page on install
                // once there is a nice tutorial
                 url = HELLO_URL;
             else if (result === "forbidden") 
                url = DEVELOPER_URL;
             else if (result === "missing")
                url = NO_NATIVE_URL;
            
            if (url) 
                chrome.tabs.create('url': url + "?" + details.reason);
            
    );

     );

   // When message is received from page send it to native
   chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) 
if(sender.id !== chrome.runtime.id && sender.extensionId !== chrome.runtime.id) 
    console.log('WARNING: Ignoring message not from our extension');
    // Not our extension, do nothing
    return;
    
if (sender.tab) 
    // Check if page is DONE and close the native component without doing anything else
    if (request["type"] === "DONE") 
        console.log("DONE " + sender.tab.id);
        if (sender.tab.id in ports) 
            // FIXME: would want to use Port.disconnect() here
            _killPort(sender.tab.id);
         
     else 
        request[K_TAB] = sender.tab.id;
        if (missing) 
            _testNativeComponent().then(function(result) 
                if (result === "ok") 
                    missing = false;
                    _forward(request);
                 else 
                    return _fail_with (request, "no_implementation");
                
            );
         else 
            // TODO: Check if the URL is in allowed list or not
            // Either way forward to native currently
            _forward(request);
        
    
    
        );

  // Send the message back to the originating tab
  function _reply(tab, msg) 
msg[K_SRC] = "background.js";
msg[K_EXTENSION] = chrome.runtime.getManifest().version;
chrome.tabs.sendMessage(tab, msg);
     

 // Fail an incoming message if the underlying implementation is not
 // present
 function _fail_with(msg, result) 
var resp = ;
resp[K_NONCE] = msg[K_NONCE];
resp[K_RESULT] = result;
_reply(msg[K_TAB], resp);
    

  // Forward a message to the native component
     function _forward(message) 
var tabid = message[K_TAB];
console.log("SEND " + tabid + ": " + JSON.stringify(message));
// Open a port if necessary
if(!ports[tabid]) 
    // For some reason there does not seem to be a way to detect missing components from longrunning ports
    // So we probe before opening a new port.
    console.log("OPEN " + tabid + ": " + NATIVE_HOST);
    // create a new port
    var port = chrome.runtime.connectNative(NATIVE_HOST);
    // XXX: does not indicate anything for some reason.
    if (!port) 
        console.log("OPEN ERROR: " + JSON.stringify(chrome.runtime.lastError));
    
    port.onMessage.addListener(function(response) 
        if (response) 
            console.log("RECV "+tabid+": " + JSON.stringify(response));
            _reply(tabid, response);
         else 
            console.log("ERROR "+tabid+": " + JSON.stringify(chrome.runtime.lastError));
            _fail_with(message, "technical_error");
        
    );
    port.onDisconnect.addListener(function() 
        console.log("QUIT " + tabid);
        delete ports[tabid];
        // TODO: reject all pending promises for tab, if any
    );
    ports[tabid] = port;
    ports[tabid].postMessage(message);
 else 
    // Port already open
    ports[tabid].postMessage(message);
   
         

【问题讨论】:

所以您在使用 chrome.runtime.sendNativeMessage 时会记录“无效参数”?在来自回调的“响应”参数不是 false/0 的分支中,对吗?如果是这样,则该分支适用于响应有效时,并且本机应用程序只会通知您您给它的参数无效。你确定原生应用没有启动吗? 当chrome作为原生应用启动时,控制台不会出现。它的输出流将“链接”到 chrome 应用程序,而不是控制台窗口。 可以通过在启动时添加UAC请求来检查程序是否启动。右键单击 chrome-token-signing.exe,选择属性,转到兼容性选项卡,然后选中“以管理员身份运行此程序”框。如果任何人(包括 chrome.exe)尝试执行该应用程序,则会出现 UAC 请求。 错误信息改了就好了。您是否收到了要求您提供管理员权限的 Windows 提示? 好的,表示本机应用程序EXE已启动。您需要在这里给它提供好的参数:“chrome.runtime.sendNativeMessage(NATIVE_HOST, ”在大括号之间。现在您需要检查哪些参数对其有效并将它们包含在您的代码中,例如:“chrome.runtime. sendNativeMessage(NATIVE_HOST, "some_valid_argument"" 【参考方案1】:

本机应用程序已启动,它会回复您您提供的参数无效。

您需要查看本机应用程序文档并查看哪些参数对于该特定应用程序有效,并在您从扩展程序发送的消息中使用它们。您的请求将如下所示:

chrome.runtime.sendNativeMessage(NATIVE_HOST, text: "some_valid_argument", function(response)
........

【讨论】:

非常感谢您的回复,现在我在控制台日志中没有消息

以上是关于本机消息传递主机 chrome-token-signing的主要内容,如果未能解决你的问题,请参考以下文章

如何使用本机消息传递主机调试未打包的 Microsoft Edge 扩展?

为 Chrome 扩展指定本机消息传递主机

本机消息传递主机 chrome-token-signing

Chrome 扩展的原生消息传递

Windows 上的 Chrome 原生消息传递

如何在 chrome 扩展本机消息传递和 c# 应用程序之间发送/接收消息