diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..c577136 --- /dev/null +++ b/Readme.md @@ -0,0 +1,63 @@ +# webextension-rpc + +This module provides a *Remote Procedure Call* abstraction around the message passing that is +available to WebExtension (browser extension) scripts. It makes it easier to call a function in the +background script from a tab’s content script, or vice versa. + + +## Example use + +In `background.js`: + + function myFunc(arg) { + return arg * 2 + } + makeRemotelyCallable({ myFunc }) + +In `content_script.js`: + + const myRemoteFunc = remoteFunction('myFunc') + myRemoteFunc(21).then(result => { ... result is 42! ... }) + +Note that the remote function always returns a `Promise`, which resolves with the remote function’s +actual return value (if the return value is itself a Promise, its result is awaited too). + + +## Install + +### Using NPM + +This module is published [on npm](https://www.npmjs.com/package/webextension-rpc). + +Run `npm install webextension-rpc` or equivalent. + +### Standalone + +Try one of the magic npm bundlers, for example: + +`wget https://wzrd.in/standalone/webextension-rpc -O webextension-rpc.js` + + +## API + +### `remoteFunction(functionName, { tabId })` + +Create a proxy function that invokes the specified remote function. + +- `functionName` (string, required): name of the function as registered on the remote side. +- `options` (object, optional): + - `tabId` (number): The id of the tab whose content script is the remote side. Leave undefined + to call the background script (from a content script). + +### `makeRemotelyCallable(functions, { insertExtraArg })` + +Register one or more functions to enable remote scripts to call them. Arguments: + +- `functions` (object, required): An object with a `{ functionName: function }` mapping. Each + function will be remotely callable using the given name. +- `options` (object, optional): + - `insertExtraArg` (boolean, default is `false`): If truthy, each executed function also + receives, as its first argument before the arguments it was invoked with, a [Tab][] object, + which contains the details of the tab that sent the message. + +[Tab]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/Tab diff --git a/src/webextension-rpc.js b/src/webextension-rpc.js index 01d0cfd..d097854 100644 --- a/src/webextension-rpc.js +++ b/src/webextension-rpc.js @@ -1,24 +1,4 @@ -// A Remote Procedure Call abstraction around the message passing available to -// WebExtension scripts. Usable to call a function in the background script from -// a tab's content script, or vice versa. -// -// The calling side always gets a Promise of the return value. The executing -// (remote) function can be an async function (= it returns a Promise), whose -// completion then will then be waited for. - -// Example use: -// -// === background.js === -// function myFunc(arg) { -// return arg*2 -// } -// makeRemotelyCallable({myFunc}) -// -// === content_script.js === -// const myRemoteFunc = remoteFunction('myFunc') -// myRemoteFunc(21).then(result => { ... result is 42! ... }) - // Our secret tokens to recognise our messages const RPC_CALL = '__RPC_CALL__' const RPC_RESPONSE = '__RPC_RESPONSE__' @@ -37,15 +17,9 @@ export class RemoteError extends Error { } } + // === Initiating side === -// Create a proxy function that invokes the specified remote function. -// Arguments -// - funcName (required): name of the function as registered on the remote side. -// - options (optional): { -// tabId: The id of the tab whose content script is the remote side. -// Leave undefined to call the background script (from a tab). -// } export function remoteFunction(funcName, { tabId } = {}) { const otherSide = (tabId !== undefined) ? "the tab's content script" @@ -145,18 +119,6 @@ function incomingRPCListener(message, sender) { // A bit of global state to ensure we only attach the event listener once. let enabled = false -// Register a function to allow remote scripts to call it. -// Arguments: -// - functions (required): -// An object with a {functionName: function} mapping. -// Each function will be callable with the given name. -// - options (optional): { -// insertExtraArg: -// If truthy, each executed function also receives, as its first -// argument before the arguments it was invoked with, an object with -// the details of the tab that sent the message. -// } - export function makeRemotelyCallable(functions, { insertExtraArg = false } = {}) { // Every function is passed an extra argument with sender information, // so remove this from the call if this was not desired.