0

I am trying to establish the communication between the web page and the native application, so that

  1. The web page could send events to the native application, for example, by clicking a button
  2. The native application could send events back to the web page which could be handled by JavaScript handlers

I'm trying to use Chrome Native Messaging: https://developer.chrome.com/extensions/nativeMessaging

The example provided by Chrome works well (needed however some adjustment to run on Python 3.8), but that example is the Chrome application which doesn't seem to fit my purposes.

I changed the code so that the Application became the Extension, and the application JS script became the extension content script.

Here is the updated manifest.json:

{
  // Extension ID: knldjmfmopnpolahpmmgbagdohdnhkik
  "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcBHwzDvyBQ6bDppkIs9MP4ksKqCMyXQ/A52JivHZKh4YO/9vJsT3oaYhSpDCE9RPocOEQvwsHsFReW2nUEc6OLLyoCFFxIb7KkLGsmfakkut/fFdNJYh0xOTbSN8YvLWcqph09XAY2Y/f0AL7vfO1cuCqtkMt8hFrBGWxDdf9CQIDAQAB",
  "name": "Native Messaging Example",
  "version": "1.0",
  "manifest_version": 2,
  "description": "Send a message to a native application.",
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["main.js"]
    }
  ],
  "icons": {
    "128": "icon-128.png"
  },
  "permissions": [
    "nativeMessaging"
  ]
}

The extension starts after the webpage is loaded. To send events from the webpage to the extension, I used "Communication with the embedded page" mechanism described here: https://developer.chrome.com/extensions/content_scripts

Here's the code of the extension content script main.js:

var webPort = chrome.runtime.connect();
var nativePort = null;

function sendNativeMessage(text) {
  message = {"text": text};
  nativePort.postMessage(message);
}

function onNativeMessage(message) {
    webPort.postMessage({"type": "response", "text": message.text});
}

function onDisconnected() {
    webPort.postMessage({"type": "connect-error", "text": chrome.runtime.lastError.message});
    nativePort = null;
}

function connect() {
  var hostName = "com.google.chrome.example.echo";
  nativePort = chrome.runtime.connectNative(hostName);
  nativePort.onMessage.addListener(onNativeMessage);
  nativePort.onDisconnect.addListener(onDisconnected);
}

window.addEventListener("message", function(event) {
    // We only accept messages from ourselves
    if (event.source != window || !event.data.type) {
        return;
    }

    console.log("Content script received message, type: " + event.data.type);
    if (event.data.type === "connect") {
        connect();
    } else if (event.data.type === "send") {
        sendNativeMessage(event.data.text);
    }
}, false);

But, when I'm opening the web page, I'm getting two issues.

  1. The code chrome.runtime.connect() raises an error:

    Could not establish connection. Receiving end does not exist.

  2. The code chrome.runtime.connectNative(hostName) raises an error:

    Uncaught TypeError: chrome.runtime.connectNative is not a function.

What I am doing wrong?

The full code of the test project is here: https://github.com/h-mdm/test-chrome-ext

Subdirectories app and host contain a working example by Chrome. Subdirectories ext and web contain the extension example which is raising errors.

vmayorow
  • 630
  • 5
  • 15
  • connect() needs a background script to connect to ([info](https://developer.chrome.com/extensions/messaging)), connectNative() can be used only in that background script. So, your workflow will be web page -> content script -> background script -> native host. – wOxxOm Jun 06 '20 at 09:56
  • Thank you, will try this. Can a web page communicate directly with a background script without content script? – vmayorow Jun 06 '20 at 10:41
  • Yes, but it won't work with ``, see "Sending messages from web pages" in the link I gave. – wOxxOm Jun 06 '20 at 10:46
  • 1
    Thank you, I managed to get it working (but on website only, localhost and local drive are not supported!). The final code is here: https://github.com/h-mdm/test-chrome-ext Please arrange your comment as an answer and I'll accept it! – vmayorow Jun 07 '20 at 10:08
  • @vmayorow, are localhost and local drive not supported because of security restrictions, or is it part of your implementation? – Chris Kennedy Aug 01 '22 at 15:22
  • @vmayorow I think I understand, the externally_connectable property in the manifest.json file requires a second level domain, and does not allow 'localhost'. – Chris Kennedy Aug 02 '22 at 01:08
  • @ChrisKennedy you are right, localhost doesn't work, not sure why. I simulated a second level domain by adding it to the hosts file. – vmayorow Aug 02 '22 at 16:17

0 Answers0