Create mainWorldContentScriptBridge
These classes are the base of a communication bridge between the main
world and content scripts, which has been extracted from the main world
options watcher.
This will be used by the main world i18n component.
Bug: twpowertools:157
Change-Id: I08553b05648ad8453203ab08ecf01e824af15fea
diff --git a/src/common/mainWorldContentScriptBridge/Client.js b/src/common/mainWorldContentScriptBridge/Client.js
new file mode 100644
index 0000000..70e567b
--- /dev/null
+++ b/src/common/mainWorldContentScriptBridge/Client.js
@@ -0,0 +1,50 @@
+export const kDefaultTimeout = 10 * 1000; // 10 seconds
+
+export default class MainWorldContentScriptBridgeClient {
+ constructor(CSTarget, MWTarget, timeout) {
+ if (!CSTarget || !MWTarget) {
+ throw new Error(
+ `[MWOptionsWatcherClient] CSTarget and MWTarget are compulsory.`);
+ }
+
+ this.CSTarget = CSTarget;
+ this.MWTarget = MWTarget;
+ this.timeout = timeout ?? kDefaultTimeout;
+ }
+
+ _sendRequestWithoutCallback(action, request, uuid) {
+ if (!uuid) uuid = self.crypto.randomUUID();
+ const data = {
+ target: this.CSTarget,
+ uuid,
+ action,
+ request,
+ };
+ window.postMessage(data, '*');
+ }
+
+ _sendRequest(action, request) {
+ return new Promise((res, rej) => {
+ const uuid = self.crypto.randomUUID();
+
+ let timeoutId;
+ let listener = e => {
+ if (e.source !== window || e.data?.target !== this.MWTarget ||
+ e.data?.uuid !== uuid)
+ return;
+
+ window.removeEventListener('message', listener);
+ clearTimeout(timeoutId);
+ res(e.data?.response);
+ };
+ window.addEventListener('message', listener);
+
+ timeoutId = setTimeout(() => {
+ window.removeEventListener('message', listener);
+ rej(new Error('Timed out while waiting response.'));
+ }, this.timeout);
+
+ this._sendRequestWithoutCallback(action, request, uuid);
+ });
+ }
+}