-
Notifications
You must be signed in to change notification settings - Fork 1
/
browser-runtime-port.ts
70 lines (65 loc) · 2.21 KB
/
browser-runtime-port.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import { type Browser, type Chrome } from "browser-namespace";
import {
rpcTransportMessageIn,
rpcTransportMessageOut,
type RPCTransportOptions,
} from "../transport-utils.js";
import { type RPCTransport } from "../types.js";
type Port = Browser.Runtime.Port | Chrome.runtime.Port;
/**
* Options for the browser runtime port transport.
*/
export type RPCBrowserRuntimePortTransportOptions = Pick<
RPCTransportOptions,
"transportId"
> & {
/**
* A filter function that determines if a message should be processed or
* ignored. Like the `transportId` option, but more flexible to allow for
* more complex use-cases.
*
* It receives the message and the
* [`runtime.Port`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/Port)
* as arguments. For example, messages can be filtered
* based on `port.name` or `port.sender`.
*/
filter?: (message: any, port: Browser.Runtime.Port) => boolean;
};
/**
* Creates a transport from a browser runtime port. Useful for RPCs
* in browser extensions, like between content scripts and service workers
* (background scripts). [Learn more on MDN.](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/Port)
*/
export function createTransportFromBrowserRuntimePort(
/**
* The browser runtime port.
*/
port: Port,
/**
* Options for the browser runtime port transport.
*/
options: RPCBrowserRuntimePortTransportOptions = {},
): RPCTransport {
const { transportId, filter } = options;
let transportHandler: ((message: any, port: Port) => void) | undefined;
return {
send(data) {
port.postMessage(rpcTransportMessageOut(data, { transportId }));
},
registerHandler(handler) {
transportHandler = (message, port) => {
const [ignore, data] = rpcTransportMessageIn(message, {
transportId,
filter: () => filter?.(message, port as Browser.Runtime.Port),
});
if (ignore) return;
handler(data);
};
port.onMessage.addListener(transportHandler);
},
unregisterHandler() {
if (transportHandler) port.onMessage.removeListener(transportHandler);
},
};
}
// TODO: browser runtime port transport tests.