Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion specification/index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ URL: https://w3c.github.io/webextensions/specification/index.html
Editor: Mukul Purohit, Microsoft Corporation https://www.microsoft.com, mpurohit@microsoft.com
Editor: Tomislav Jovanovic, Mozilla https://www.mozilla.org/, tjovanovic@mozilla.com
Editor: Oliver Dunk, Google https://www.google.com, oliverdunk@chromium.org
Editor: Kiara Rose, Apple https://www.apple.com, kiara_rose@apple.com
Abstract: [Placeholder] Abstract.
Markup Shorthands: markdown yes
</pre>
Expand Down Expand Up @@ -143,7 +144,21 @@ This key may be present.

### Key `externally_connectable`

This key may be present.
The <a href="#key-externally_connectable">`externally_connectable`</a> key declares which extensions and web pages can establish connections to the extension using [=runtime.connect()=] and [=runtime.sendMessage()=]. If omitted, all extensions may connect, but no web pages can connect.
Comment thread
Rob--W marked this conversation as resolved.

A connection from an external web page or extension triggers the [=runtime.onConnectExternal=] event listener to fire. Similarly, a message sent by an external web page or extension triggers the [=runtime.onMessageExternal=] event listener to fire.
Copy link
Copy Markdown
Member

@Rob--W Rob--W Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A connection from an external web page or extension triggers the [=runtime.onConnectExternal=] event listener to fire. Similarly, a message sent by an external web page or extension triggers the [=runtime.onMessageExternal=] event listener to fire.
A connection from an external web page or extension triggers the [=runtime.onConnectExternal=] event listener to fire. Similarly, a message sent by an external web page or extension triggers the [=runtime.onMessageExternal=] event listener to fire.
These events are not available to web pages, only in privileged extension contexts.


This key may be present and may include the following optional keys:

#### Key `ids`

A [=list=] of [=extension IDs=] that specifies which extensions can communicate with the extension. To allow all extensions to connect, include the wildcard pattern `*`. If left empty or omitted while the `externally_connectable` key is present, no extensions can connect.

#### Key `matches`

A [=list=] of [=match patterns=] that specifies which web pages can communicate with the extension. If left empty or omitted, no web pages can connect.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an edge case where document URLs cannot be described by a match pattern. For these cases, we specified an algorithm to determine the URL to use for matching content scripts, at specification/index.bs: "Determine the URL for matching a document".

Can we point to this?

@oliverdunk Could you confirm that this is what Chrome does (or intends to use)?

Copy link
Copy Markdown
Collaborator

@xeenon xeenon Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure pointing to that algorithm would be helpful, since it is more about content_scripts and match_origin_as_fallback and match_about_blank which don't exist for externally_connectable .

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked Chrome's source code for relevant behavior, which is at https://source.chromium.org/chromium/chromium/src/+/main:extensions/browser/api/messaging/message_service.cc;l=538-540;drc=373d7fdb08be061501a27cf72cb0ff846fbd0899

So it looks like these APIs can only be used from documents whose URL matches the match pattern. In practice, http(s): and file:-URLs. Not URLs like about:blank, blob:-, etc.

So let's resolve this thread by editing the section to emphasize that the match pattern should match the document's URL.


Any [=match patterns=] that include wildcard domains, or wildcard subdomains of a top-level domain, must be ignored.
Copy link
Copy Markdown

@MicahZoltu MicahZoltu Oct 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wildcard domains is, arguably, the most important thing that externally_connectable should support, and people have been asking for it for ~8 years. See https://bugzilla.mozilla.org/show_bug.cgi?id=1319168 for a long history, but the TL;DR is:

An extension can extend the built-in browser API via externall_connectable by enabling a wildcard externally_connectable. Websites can then probe to see if APIs of interest are exposed by any installed extensions and communicate with the extension without the extension needing to inject content scripts into the page which is currently the only way to achieve this behavior.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is inaccurate today (for Chrome) -- we allow wildcard domains / wildcard subdomains.


### Key `devtools_page`

Expand Down