0

I'm writing a simple Chrome Extension that communicates with a Native Host using Native messaging. I've closely followed the Chrome documentation for native messaging (extension <> native host) and also for host-page communication but I have to say that they leave a lot of important details open.

I can launch the native host without problems from the extension and communication between the extension and the host works as it should. However, none of the "front tiers" (page, content script and background script) can talk to each other.

The tiers are as follow:

The page:

window.postMessage({ type: "TO_THE_EXTENSION", text: "Hello from the webpage!" }, "*");
// this never reaches the content script

contentscript.js (script seems to load correctly on the page)

var port = chrome.runtime.connect(); // this throws an error

window.addEventListener("message", (event) => {
  // We only accept messages from ourselves
  if (event.source != window)
    return;

  if (event.data.type && (event.data.type === "TO_THE_EXTENSION")) {
    console.log("Content script received: " + event.data.text);
    port.postMessage(event.data.text);
  }
}, false);

The first line of the content script immediately throws

Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.

background.js (this works when reloading the extension from the Extensions toolbar)

var port = chrome.runtime.connectNative('my.example.app.com');

port.onMessage.addListener(function(msg) {
  console.log("Received" + msg);
});
port.onDisconnect.addListener(function() {
  console.log("Disconnected");
});
port.postMessage( {'text': 'Hello'} );

manifest.json

{
  "name": "Simple extension",
  "description": "Simple extension using native messaging",
  "version": "1.0",
  "manifest_version": 3,
  "content_scripts": [
   {
      "matches": ["http://*/*", "https://*/*"],
      "js": ["contentscript.js"]      
   }
  ],
  "background": {
      "service_worker": "background.js"
  },  
  "permissions": ["nativeMessaging"]
}

Any help is appreciated, and pointers to documentation that explains how the whole page -> content script -> background script -> native host chain is supposed to actually work. I can't believe that Chrome documentation doesn't have a minimal, complete and verifiable example of an extension using native messaging.

Mick Mnemonic
  • 7,808
  • 2
  • 26
  • 30
  • 1
    1) ManifestV3 doesn't support nativeMessaging fully, use ManifestV2. 2) chrome.runtime.connect needs a matching chrome.runtime.onConnect listener in the background script, see the [documentation](https://developer.chrome.com/extensions/messaging). – wOxxOm Apr 30 '21 at 04:55
  • Thanks! Nowhere in the documentation it's mentioned that version 3 doesn't support native messaging; does version 2 have a different syntax for declaring the background worker, or do I need to change other places than the manifest version? – Mick Mnemonic Apr 30 '21 at 05:07
  • Bugs in MV3 implementation are reported on https://crbug.com, not in the documentation. ManifestV2 has its own section in the documentation. The background script article: [link](https://developer.chrome.com/docs/extensions/mv2/background_pages/). – wOxxOm Apr 30 '21 at 05:38
  • MV3 is full of bugs so currently it's for early adopters who are implicitly used as beta testers. Something the documentation prefers not to tell. – wOxxOm Apr 30 '21 at 05:46
  • Thanks for the info, I'll try this based on v2. – Mick Mnemonic Apr 30 '21 at 06:03
  • @wOxxOm, indeed with manifest v2 I can communicate between the content script and the background script. Only thing that doesn't work is that `window.postMessage()` from the page isn't reaching the window event listener in the content script. Any ideas? Do I need to permit something else in the manifest? – Mick Mnemonic Apr 30 '21 at 08:14
  • Content scripts run after DOMContentLoaded by default so try [document_start](https://developer.chrome.com/extensions/content_scripts#run_time). And make sure to reload all tabs after reloading the extension or reinject the content scripts [manually](https://stackoverflow.com/questions/10994324/chrome-extension-content-script-re-injection-after-upgrade-or-install). – wOxxOm Apr 30 '21 at 08:17
  • I can see that the content script is running okay (from the debugger) when loading the page. Only problem is that the window messages sent from the page context never reach the extension context. If I post with `window.postMessage()` from the extension context in the debugger, the event listener fires as it should. So it looks like messages are not transferring between contexts.. – Mick Mnemonic Apr 30 '21 at 09:43
  • 1) "I can see" - do you mean the pause mode when hitting the breakpoint on postMessage? Otherwise it doesn't mean anything. 2) Maybe your page script runs in an iframe? In that case you need to run content scripts there too or use `top.postMessage` – wOxxOm Apr 30 '21 at 09:48
  • Ha-haa, it was the iframe that kept the messages contained -- who knew! Using `top.postMessage` does the job. Now I think I have everything in place. Big thanks! – Mick Mnemonic Apr 30 '21 at 09:57

0 Answers0