Webpage-to-extension messaging

Safari 15.4 Release Notes shows that webpage-to-extension messaging using externally_connectable is supported. https://developer.apple.com/documentation/safari-release-notes/safari-15_4-release-notes

However, when I tried testing it, I was not really able to get it to work. What I have tried:

  • Added matches array to the externally_connectable object in manifest.json
  • Obtain the extensionID using browser.runtime.id
  • Added listener to onMessageExternal for extension
  • Send a message from a webpage, that is in the matches array, using chrome.runtime.sendMessage with the extensionID obtained above

With these steps, I wasn't able to receive a message sending to the extension. I am not sure if the extensionID is wrong or if I am missing any crucial steps. Can someone please recommend what I should try?

Replies

It's hard to say exactly what the issue is without a sample project/website.

Could you file a bug report on https://feedbackassistant.apple.com with a sample extension (and a website that it is meant to work with), and we could help determine exactly what is going on?

did you find an answer for this? i encounter the same problem..

No answer yet, I have currently put this on hold and plan to visit it some time in the next couple of weeks.

I found underneath (scroll down a bit). Did not try yet

https://www.wwdcnotes.com/notes/wwdc22/10099/

Weird, just tried out the above. I run code underneath, I always see "Received response from the background page" in the console but response is always undefined. Even in cases where I do not listen for messages from website in my background page.

browser.runtime.sendMessage( extensionID, { greeting: "Hello!" }, function(response) { console.log("Received response from the background page" ); console.log(response); } );

I managed to get the basic example to work. There were some errors on my side, but things were quit hard to debug. For example; there was an error in my background script that was not shown in the console log in safari web inspector. After clicking option-command-r (clear cache) the console alerted that there was an error in my background script and then displayed the error after which I could fix and the basic example worked! (Now I am going to try out some more complex information exchanges, let's hope for the best ;-)

@SafariLearner: I noticed that you mentioned "chrome.runtime.sendMessage" --> this should be "browser.runtime.sendMessage"

  • Hey, thank you so much for the replies.

    I just have a few more questions regarding your implementation. Are you using manifest v3? And how did you find the extensionID?

  • Hey, I tried manifest v3, then switched back to manifest v2. Then I discovered the error in my background script. I've got things working now in manifest v2, but I expect it to work as well in manifest v3. (will try later)

    I captured the extensionId by console.log(browser.runtime.id) in my background script. (and then use safari desktop browser to capture this log)

  • Hi @tim177, could you please tell me how you implemented the solution? Did you try on macOS or iOS? The documentation doesn't state clearly if the onMessageExternal event is available to which OS, and although it said to use runtime.sendMessage to send the message to a given ID, I'm not sure if that API is available outside of an extension's context. Thank you so much. I know it's been quite some time since your last reply, but I couldn't find anywhere else for assistance.

Add a Comment

I am also facing the same issue. Using Safari version 16.6 and Manifest V3. Added matches array to externally_connectable object correctly, still not able to receive the message in the web extension from the webpage.

I was using http webpage to send message, but safari doesn't allow websites without https to send message to the extension.

I am experiencing the same behaviour.

Listener in background script:

browser.runtime.onMessageExternal.addListener((request, sender, sendResponse) => {
    console.log("Received request: ", request);
    sendResponse({farewell: "Goodbye from the background page!"});
});
console.log("background script onMessageExternal subscribed by", browser.runtime.id);

and web page is this:

<html>

<head>
</head>

<body>
  <h1>testing sendMessage</h1>
  <script>
    console.log("abc....");
    browser.runtime.sendMessage("com.example.Sample-App.Extension (DY.....84)", { greeting: "Hello!" }, function (response) {
      console.log("Received response from the background page:", response);
    });
  </script>
</body>

</html>

I'm hosting it via https, like https://83cc-82-172-140-54.ngrok-free.app and manifest is this:

{
  "manifest_version": 3,
  "default_locale": "en",
  "name": "__MSG_extension_name__",
  "description": "__MSG_extension_description__",
  "version": "1.0.5",
  "icons": {
    "16": "images/icon-16.png",
    "32": "images/icon-32.png",
    "48": "images/icon-48.png",
    "96": "images/icon-96.png",
    "128": "images/icon-128.png",
    "256": "images/icon-256.png",
    "512": "images/icon-512.png"
  },
  "background": {
    "service_worker": "scripts/background.js"
  },
  "content_scripts": [
    {
      "js": [
        "scripts/content.js"
      ],
      "css": [
        "styles.css"
      ],
      "matches": [
        "https://example.com/messages/*"
      ],
      "all_frames": true
    }
  ],
  "options_ui": {
    "page": "options/browser/options.html",
    "open_in_tab": true
  },
  "action": {
    "default_popup": "popup/browser/popup.html",
    "default_icon": {
      "16": "images/toolbar-icon-16.png",
      "19": "images/toolbar-icon-19.png",
      "32": "images/toolbar-icon-32.png",
      "38": "images/toolbar-icon-38.png",
      "48": "images/toolbar-icon-48.png",
      "72": "images/toolbar-icon-72.png"
    }
  },
  "permissions": [
    "storage"
  ],
  "externally_connectable": {
    "matches": [
      "https://83cc-82-172-140-54.ngrok-free.app/*"
    ]
  }
}

And still opening the page, I see in console logs only:

[Log] abc.... (83cc-82-172-140-54.ngrok-free.app, line 10)
[Log] Received response from the background page: – undefined (83cc-82-172-140-54.ngrok-free.app, line 12)

What I am missing?

Running on Safari Version 17.0 (19616.1.27.211.1).

If I replace browser with chrome -- it is working on Chrome BTW.