3

I have problem with Native messaging synchronization on windows. I am trying to synchronize the message between backgroundPage and hostApp. normally, we use native messaging like this:

//popup.js
function appendMessage(text) {
  document.getElementById('response').innerHTML += "<p>" + text + "</p>";
}

function sendNativeMessage() {
  message = {"command": document.getElementById('input-text').value};
  port.postMessage(message);
  appendMessage("Sent message: <b>" + JSON.stringify(message) + "</b>");
}
function onNativeMessage(message) {
  appendMessage("Received message: <b>" + JSON.stringify(message) + "</b>");
}

function onDisconnected() {
  appendMessage("Failed to connect: " + chrome.runtime.lastError.message);
  port = null;
  updateUiState();
}

function connect() {
  var hostName = "com.google.chrome.example.dmtest1";
  appendMessage("Connecting to native messaging host <b>" + hostName + "</b>");
  port = chrome.runtime.connectNative(hostName);
  port.onMessage.addListener(onNativeMessage);
  port.onDisconnect.addListener(onDisconnected);
  updateUiState();
}

document.addEventListener('DOMContentLoaded', function () {
  document.getElementById('connect-button').addEventListener(
      'click', connect);
  document.getElementById('send-message-button').addEventListener(
      'click', sendNativeMessage);
  updateUiState();
});


<html>
  <head>
    <script src='./popup.js'></script>
  </head>
  <body>
    <button id='connect-button'>Connect</button>
    <input id='input-text' type='text' />
    <button id='send-message-button'>Send</button>
    <div id='response'></div>
  </body>
</html>

but the sendNativeMessage() and onNativeMessage(..) functions are asynchronous, and I want to make them synchronous. I tried the method below but it failed to get the response data from the host(c++ exe), and it made chrome crash.

function sendNativeMessage() {
  var message = {"command": document.getElementById('input-text').value};
  port.postMessage(message);
  appendMessage("Sent message: <b>" + JSON.stringify(message) + "</b>");

  port.onMessage.addListener(function(msg) { 
    appendMessage("Receive message: <b>" + JSON.stringify(msg) + "</b>");
  });
}

How can I do this, is it possible, Any help?

Marco A.
  • 43,032
  • 26
  • 132
  • 246
SevenWow
  • 305
  • 3
  • 14
  • Is function `port.sendMessage` exists? – SevenWow Jul 03 '15 at 07:55
  • Why do you want them synchronous ? You have to rember that the ui will not update during the execution of a function... So if the call take a ltile time, your page will freeze. But it's not impossible to do. – Emrys Myrooin Jul 03 '15 at 07:58
  • thanks for your reply @EmrysMyrooin, I have a button on page1.html, it will send message to content script when I click it. Then the content script sends message to a background page of the extension, the extension sends data to the host and get some data back which will finally shows on page1.html. I hope to get the data shown on page1.html right after I finish the button click action, can you get me? – SevenWow Jul 03 '15 at 08:21
  • Okey. So why do you want it synchronous ? You can specify a callback function that you will call when you want to send back data to the content script. – Emrys Myrooin Jul 03 '15 at 08:24
  • @EmrysMyrooin, It is like calling a function, pass a parameter and get a result when the function finished running. And the caller do not continue running until it get th result. – SevenWow Jul 03 '15 at 08:28
  • I see what you want. But it's not a "good" way to do it. If want, You can look for Promise in javascript that alow you to define what to do after an ansychronous call with a "better looking" code. – Emrys Myrooin Jul 03 '15 at 08:32
  • @EmrysMyrooin, I am not familiar with js, any example? All I am doing here is to call local functions and get some data. It is so troublesome to call functions in dll, as NPAPI is deprecated. – SevenWow Jul 03 '15 at 08:43
  • If you're not familliar to javascript, you have first to understand how it's work. Javascript is mainly driven by anonymous function and callbacks. It's not easy to understand at the begining. It's particulary true when you work with google api's that are totaly asynchronous. Instead of waiting the result of a function, it's the function that will call an other (given in parameter) to give the result. It's because if you wait for the result, the page freeze because javascript is fully monothread. – Emrys Myrooin Jul 03 '15 at 08:49
  • @EmrysMyrooin, function `onNativeMessage(message)` will only be fired when the port receives data, how can I use it properly in Promise? This function is not called right after `sendNativeMessage()` but called after the host sends response data to the port. Can you get me? – SevenWow Jul 03 '15 at 10:17
  • You can't. It's handler of event. So you have to move the code that need the response in this onNativeMessage – Emrys Myrooin Jul 03 '15 at 10:19
  • Then, I think Promise in js cannot do what I intend to do. `port.postMessage()` is not block, `onNativeMessage(message)` should not be called but fire itself. It seems nothing can be done, :( – SevenWow Jul 03 '15 at 10:35
  • Nop, it's what i'm trying to say ^^ You can't change the javascript style of code... And yes at the begining it's a litle confusing and boring – Emrys Myrooin Jul 03 '15 at 10:37
  • @EmrysMyrooin, That' s too bad, I cannot finish my work :{ . But thank you anyway, :) – SevenWow Jul 03 '15 at 10:41
  • You can finish :-) You just have to modify a litle the structure of you're code ;-) – Emrys Myrooin Jul 03 '15 at 10:43
  • @EmrysMyrooin, really? but how? – SevenWow Jul 06 '15 at 01:47
  • @EmrysMyrooin, post an answer here, I will accept it. :-) – SevenWow Jul 06 '15 at 02:19

1 Answers1

4

After several days of search and test, I finally found an answer(here: how to handle chrome.runtime.sendNativeMessage() in native app) and solved my problem. I give up the idea about making my callback functions synchronous, I just use another way of communicating between Chrome extension backpage and my local host app. Instead of var port = chrome.runtime.connectNative(hostName);port.onMessage.addListener(onNativeMessage);port.postMessage(message); I used the code below to send and receive data between backpage and hostapp, and it is synchronous:

chrome.runtime.sendNativeMessage(hostName, sendMsg, function(response) {
            if (chrome.runtime.lastError) {
                alert("ERROR: " + chrome.runtime.lastError.message);
            } else {
                sendResponse({farewell: ParseJSON(response)});
            }
        });
Community
  • 1
  • 1
SevenWow
  • 305
  • 3
  • 14
  • Could you please edit snippet tags out of your question and answer? They are meant _only_ for self-contained HTML/JS examples (like JSFiddle) and of course they can't run extension code. – Xan Jul 16 '15 at 07:20