NSExtensionRequestHandling not handling native messages

1.4k Views Asked by At

I'm trying to create a Safari Web Extension to my native app. I want to have a popup with a button which when clicked will communicate with my native app. Before I get to this part I have a problem sending a native message and handling it in beginRequest function from class conforming to the NSExtensionRequestHandling protocol. I didn't do much because I'm relying on the code generated by Xcode.

in manifest.json I added nativeMessaging permission like that:

"permissions": [ "nativeMessaging" ]

popup.js which contains event listener:

console.log("Hello World!", browser);

document.addEventListener('DOMContentLoaded', function() {
    var checkPageButton = document.getElementById('clickIt');
    checkPageButton.addEventListener('click', function() {
        console.log("click")
        browser.runtime.sendNativeMessage({ message: "Hello" });
    }, false)
}, false)

When I inspect the popup element I can see Hello World and click message but as I mentioned before - beginRequest is not called. Is there anything missing? I also watched Meet Safari Web Extensions session from WWDC20 but I didn't find an answer.

1

There are 1 best solutions below

0
On

Because it could be several things causing this, I'd try the following to help debug the issue.

  • Make sure you have set up an App Group in your capabilities and set extension and app to the same App Group in Xcode.

  • Check the Safari menu that "Developer" -> "Allow Unsigned Extensions" is enabled. (if you don't see "Developer" you will need to enable it in "Preferences" -> "Advanced".

  • make sure you have the correct permissions in your manifest.json example:

 "permissions": [ "nativeMessaging", "<all_urls>" ] 

I don't think you can call sendNativeMessage from popup.js or content.js. I believe you can only call it from background.js. So you'd have to call popup.js -> background.js -> sendNativeMessage.

If you look in your Safari develop the menu, inspector, you might see something like "undefined is not a function (sendNativeMessage)". This happens when not called from background.js or other permissions issues.

Safari Extension Native Messaging Flow

  • Also, look in your Console.app -> errors and faults (filter by bundle id) and see if there are any sort of permissions issues.

You cannot "see" if beginRequest is called by looking at your Xcode log or setting a breakpoint in this func. It will never hit a breakpoint or print to the Xcode logs as it's running in its own process. Your debugger attaches to your app and not the extension process.

In order to use the debugger on SafariWebExtensionHandler, you will have to attach the Xcode debugger to the running Safari extension process to hit your breakpoint. Xcode -> Debug -> attach to process.

Additionally, if you're using the default template from Xcode, it calls os_log which again, logs to the Console.app not to Xcode (the extension is running in its own process).

I highly recommend to anyone having native messaging issues or wanting a more thorough explanation to watch at least the last 5 minutes of this session for more info: WWDC 2020: Meet Safari Web Extensions

Apple's docs are also very helpful: Messaging Between the App and JavaScript in a Safari Web Extension

and Passing Messages Between Safari App Extensions and Injected Scripts