Usage: Popup
Relevant source files
The following files were used as context for generating this wiki page:
The webext-bridge/popup module provides the necessary functionality for scripts running in a browser extension's popup context to communicate with other parts of the extension, such as the background script. It is one of several context-specific entry points offered by the library, each tailored to its specific runtime environment. This module simplifies message passing by abstracting the underlying runtime.Port connection details and providing a promise-based API for request-response cycles.
The primary goal is to establish a resilient communication channel to the background script, which acts as the central message router. This setup allows popup scripts to send messages, listen for incoming messages, and establish long-lived stream connections for continuous data exchange.
Sources: README.md:16-19, package.json:29-32, src/popup.ts
Architecture and Initialization
The popup module's architecture is centered around two key components: a PersistentPort and an EndpointRuntime. On initialization, a persistent port is created to connect to the background script, and an endpoint runtime is instantiated to manage the logic of sending and receiving messages through that port.
Sources: src/popup.ts:5-12
The initialization flow is as follows:
createPersistentPort('popup')is called to establish a named, resilient connection to the background script.createEndpointRuntime('popup', ...)is called, providing the runtime context name and a routing function that uses the persistent port to send messages.- The
endpointRuntime.handleMessagemethod is registered as the listener for incoming messages on the persistent port. - The
sendMessage,onMessage,openStream, andonOpenStreamChannelfunctions are exported from the module for application use.
Sources: src/popup.ts:5-14
This diagram illustrates the initialization process within the popup script.
Sources: src/popup.ts:1-14
Key Components
| Component | Description | Source File |
|---|---|---|
PersistentPort | A wrapper around browser.runtime.Port that automatically reconnects to the background script if the connection is lost, which is common in Manifest V3 service worker environments. It is identified as 'popup' to the background script. | src/internal/persistent-port.ts:1-16 |
EndpointRuntime | Manages the message lifecycle. It tracks outgoing messages and their corresponding reply promises (transactions), and it routes incoming messages to the correct listeners registered via onMessage. | src/internal/endpoint-runtime.ts:24-32 |
Message Passing
The core functionality of the popup module is sending and receiving messages. This is handled by the sendMessage and onMessage functions, which are powered by the EndpointRuntime.
Sending Messages (sendMessage)
When sendMessage is called from the popup script, the EndpointRuntime creates an InternalMessage object containing the payload, a unique transaction ID, and destination information. This message is then passed to the PersistentPort, which forwards it to the background script for routing. The function returns a Promise that resolves or rejects when a reply is received or an error occurs.
Sources: src/internal/endpoint-runtime.ts:133-161
The following sequence diagram shows the flow of sending a message from the popup to the background script and receiving a response.
Receiving Messages (onMessage)
To receive messages, a handler is registered using onMessage(messageID, callback). The EndpointRuntime stores this callback in a map. When the PersistentPort receives an incoming message from the background script, it invokes endpointRuntime.handleMessage. This function looks up the appropriate callback based on the messageID and executes it with the message payload.
Sources: src/popup.ts:12-13, src/internal/endpoint-runtime.ts:40-48, 162-165
Stream Communication
For continuous, bidirectional communication, the popup module provides a stream API. Streams are namespaced channels ideal for scenarios requiring more than a single request-response cycle.
Sources: src/internal/stream.ts:8-13
Opening a Stream (openStream)
A client (e.g., the popup) can initiate a stream to a destination by calling openStream(channel, destination). This sends a special __crx_bridge_stream_open__ message to the destination. If the destination has a listener for that channel (registered via onOpenStreamChannel), a Stream object is created on both ends, establishing a persistent communication link.
The Stream class provides send(), onMessage(), and close() methods to manage the communication over the channel.
Sources: src/popup.ts:14, src/internal/stream.ts:129-142
This diagram illustrates the process of opening a stream from the popup to the background script.
Exposed API
The webext-bridge/popup module exports the following functions for use in popup scripts.
| Function | Description |
|---|---|
sendMessage | Sends a one-time message to a specific endpoint and returns a Promise that resolves with the response. |
onMessage | Registers a listener to handle incoming messages with a specific ID. |
openStream | Opens a long-lived, namespaced communication channel to another endpoint. |
onOpenStreamChannel | Registers a listener to accept incoming stream requests on a specific channel. |
Sources: src/popup.ts:13-14, src/internal/endpoint-runtime.ts:24-32, src/internal/stream.ts:151-157
Summary
The webext-bridge/popup module provides a robust and developer-friendly API for handling communication within an extension's popup. By leveraging a persistent port for connection resilience and an endpoint runtime for message and stream management, it abstracts away the complexities of the underlying WebExtension APIs. This allows developers to focus on application logic rather than the intricacies of inter-context communication.
Sources: src/popup.ts, README.md:16-19