blob: 2e620ff7141413e2e2e478cb09d5838caccdcf8f [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview A collection of functions and behaviors helpful for message
* passing between renderers.
*/
import {BridgeAction, BridgeTarget} from './bridge_constants.js';
/** @typedef {!Object<BridgeAction|string, Function>}*/
let TargetHandlers;
export class BridgeHelper {
/**
* This function should only be used by Bridges (e.g. BackgroundBridge,
* PanelBridge) and not called directly by other classes.
*
* @param {BridgeTarget|string} target The name of the class that will handle
* this request.
* @param {BridgeAction|string} action The name of the intended function or,
* if not a direct method of the class, a pseudo-function name.
*
* Any arguments to be passed through can be appended to the function. They
* must be convertible to JSON objects for message passing - i.e., no
* functions or type information will be retained, and no direct
* modification of the original context is possible.
*
* @return {!Promise} A promise, that resolves when the handler function has
* finished and contains any value returned by the handler.
*/
static sendMessage(target, action, ...args) {
return new Promise(
resolve => chrome.runtime.sendMessage({target, action, args}, resolve));
}
/** @param {BridgeTarget|string} target */
static clearAllHandlersForTarget(target) {
BridgeHelper.handlers_[target] = {};
}
/**
* @param {BridgeTarget|string} target The name of the class that is
* registering the handler.
* @param {BridgeAction|string} action The name of the intended function or,
* if not a direct method of the class, a pseudo-function name.
* @param {Function} handler A function that performs the indicated action. It
* may optionally take a single parameter, and may have an optional return
* value that will be forwarded to the requestor.
* If the method takes multiple parameters, they are passed as named
* members of an object literal.
*/
static registerHandler(target, action, handler) {
if (!target || !action) {
return;
}
if (!BridgeHelper.handlers_[target]) {
BridgeHelper.handlers_[target] = {};
}
if (BridgeHelper.handlers_[target][action]) {
throw 'Error: Re-assigning handlers for a specific target/action (' +
target + '.' + action + ') is not permitted';
}
BridgeHelper.handlers_[target][action] = handler;
}
}
/** @private {!Object<BridgeTarget|string, TargetHandlers>} */
BridgeHelper.handlers_ = {};
chrome.runtime.onMessage.addListener((message, sender, respond) => {
const targetHandlers = BridgeHelper.handlers_[message.target];
if (!targetHandlers || !targetHandlers[message.action]) {
return;
}
const handler = targetHandlers[message.action];
Promise.resolve(handler(...message.args)).then(respond);
return true; /** Wait for asynchronous response. */
});