Transport Mechanisms
Relevant source files
The following files were used as context for generating this wiki page:webext-bridge provides a simplified and consistent messaging API by abstracting the underlying communication channels used in web extensions. The library employs two primary transport mechanisms to facilitate communication between different parts of an extension: one for intra-extension communication between contexts like background, popup, and content-script, and another for communication between a content-script and the host page's window context.
The core of the intra-extension transport is the browser.runtime.Port API, with the background script acting as a central message-passing hub. For communication with the host page, the library utilizes window.postMessage in conjunction with a MessageChannel to ensure namespaced and secure message passing. The content-script plays a unique role, acting as a gateway that leverages both transport mechanisms to bridge communication between the host page and the rest of the extension.
Extension Context Transport (runtime.Port)
Communication between the standard, sandboxed parts of a web extension (background, popup, options page, devtools, and content scripts) is handled via long-lived message ports, as defined by the browser.runtime.Port API. This creates a robust and stateful connection between client contexts and a central background script router.
Central Hub: Background Script
The background script is the heart of the transport system. It listens for new connections from other extension contexts using browser.runtime.onConnect. When a context connects, the background script registers the port in a connection map (connMap), associating the port with the endpoint's unique identifier and fingerprint. This map is crucial for routing messages to the correct destination.
The background script is responsible for message delivery logic, including handling cases where a destination is not yet connected (queuing) or when a session terminates unexpectedly. It notifies senders about message delivery status, undeliverability, and session terminations.
Sources: src/background.ts:18-28, src/background.ts:245-265
The following diagram illustrates the central router architecture, with various extension contexts establishing connections to the background script.
Client-Side Connection: PersistentPort
To simplify port management for client contexts (popup, options, devtools, content-script), the library provides a createPersistentPort utility. This wrapper around browser.runtime.connect is designed to handle the ephemeral nature of extension contexts, particularly the Manifest V3 service worker (background script). If the port disconnects (e.g., the service worker is terminated by the browser), the PersistentPort automatically attempts to reconnect, ensuring a resilient communication channel.
Upon connection and reconnection, the PersistentPort sends a sync message to the background script. This message synchronizes the state of pending messages and undelivered messages, ensuring that communication can resume seamlessly after a disconnect.
Sources: src/internal/persistent-port.ts:1-19, src/internal/persistent-port.ts:133-136
This sequence diagram shows the automatic reconnection logic of PersistentPort.
Port Message Protocol
The communication over the runtime.Port uses a specific protocol defined by RequestMessage (client to background) and StatusMessage (background to client).
Sources: src/internal/port-message.ts:1-36
Request Messages (Client -> Background)
These are messages sent from a client context to the background script.
| Type | Description |
|---|---|
deliver | Asks the background script to deliver an InternalMessage to its destination. This is the primary message type for sending data. |
sync | Sent upon connection/reconnection. It informs the background script of any responses the client is still waiting for and any messages it has failed to deliver so far. |
Sources: src/internal/port-message.ts:26-34
Status Messages (Background -> Client)
These are messages sent from the background script to a client context to inform it of the state of its sent messages.
| Status | Description |
|---|---|
undeliverable | Informs the sender that the destination endpoint is not currently connected. The message will be queued on the client side. |
deliverable | Informs a client that a previously undeliverable destination is now connected, prompting the client to re-send queued messages. |
delivered | A receipt confirming that a message has been successfully passed to the destination port. |
incoming | An incoming message (a new message or a reply) from another context, forwarded by the background script. |
terminated | Informs a client that the session for a recipient endpoint has ended (e.g., tab closed) before a reply could be sent. This causes the original sendMessage promise to reject. |
Sources: src/internal/port-message.ts:6-24, src/internal/persistent-port.ts:114-121
Window-to-Content-Script Transport (postMessage)
webext-bridge supports messaging between a content script and scripts running in the main window context of the host page. This is achieved using the standard window.postMessage API, but with additional logic to ensure security and prevent conflicts.
The postMessage Bridge
The usePostMessaging utility establishes this communication channel. To avoid using the global window object directly for event listening, which can be insecure and prone to conflicts, it creates a MessageChannel. One port of this channel is kept within the isolated world of the content script, and the other is transferred to the window context. All subsequent communication happens securely over this private channel.
Sources: src/internal/post-message.ts:1-49
A namespace must be configured using setNamespace(nsps) in the window script and allowWindowMessaging(nsps) in the content-script. This namespace is used to identify the correct MessageChannel and ensures that a page with multiple extensions or scripts using webext-bridge does not have message collisions.
Sources: src/internal/post-message.ts:33-49, src/window.ts:18-21, src/content-script.ts:39-42
Sources: src/window.ts:1-25, src/content-script.ts:7-19
The Content Script as a Gateway
The content script is a special context that acts as a bidirectional gateway, utilizing both transport mechanisms.
- From Extension to Window: When a message from an extension context (e.g.,
popup) is destined for thewindow, the background script routes it to the content script viaruntime.Port. The content script then forwards this message to thewindowusing itspostMessagechannel. - From Window to Extension: When a message originates from the
window, it's sent to the content script viapostMessage. The content script receives it, stamps it with the correct origin context (window), and forwards it to the background script via itsPersistentPortfor routing to the final destination.
Sources: src/content-script.ts:9-19
This flow diagram shows the content script's role as a message gateway.
Sources: src/content-script.ts:9-19
Conclusion
The transport layer of webext-bridge is a well-architected system that abstracts the complexities of web extension messaging. By using a centralized runtime.Port-based router for intra-extension communication and a secure postMessage channel for window interaction, it provides a unified and resilient API for developers. The PersistentPort ensures stability in the face of service worker terminations, and the content script acts as an effective gateway, seamlessly connecting all parts of the extension ecosystem.
Sources: README.md:1-12, src/background.ts, src/internal/persistent-port.ts, src/internal/post-message.ts