summaryrefslogtreecommitdiffstats
path: root/remote/shared/messagehandler/Module.sys.mjs
blob: c526c7ce6c9b9da116c259da58d13fcd80e4bda9 (plain)
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

const lazy = {};

ChromeUtils.defineESModuleGetters(lazy, {
  error: "chrome://remote/content/shared/webdriver/Errors.sys.mjs",
  Log: "chrome://remote/content/shared/Log.sys.mjs",
});

ChromeUtils.defineLazyGetter(lazy, "disabledExperimentalAPI", () => {
  return !Services.prefs.getBoolPref("remote.experimental.enabled");
});

ChromeUtils.defineLazyGetter(lazy, "logger", () => lazy.Log.get());

export class Module {
  #messageHandler;

  /**
   * Create a new module instance.
   *
   * @param {MessageHandler} messageHandler
   *     The MessageHandler instance which owns this Module instance.
   */
  constructor(messageHandler) {
    this.#messageHandler = messageHandler;
  }

  /**
   * Clean-up the module instance.
   */
  destroy() {
    lazy.logger.warn(
      `Module ${this.constructor.name} is missing a destroy method`
    );
  }

  /**
   * Emit a message handler event.
   *
   * Such events should bubble up to the root of a MessageHandler network.
   *
   * @param {string} name
   *     Name of the event. Protocol level events should be of the
   *     form [module name].[event name].
   * @param {object} data
   *     The event's data.
   * @param {ContextInfo=} contextInfo
   *     The event's context info, see MessageHandler:emitEvent. Optional.
   */
  emitEvent(name, data, contextInfo) {
    this.messageHandler.emitEvent(name, data, contextInfo);
  }

  /**
   * Intercept an event and modify the payload.
   *
   * It's required to be implemented in windowglobal-in-root modules.
   *
   * @param {string} name
   *     Name of the event.
   * @param {object} _payload
   *    The event's payload.
   * @returns {object}
   *     The modified event payload.
   */
  interceptEvent(name, _payload) {
    throw new Error(
      `Could not intercept event ${name}, interceptEvent is not implemented in windowglobal-in-root module`
    );
  }

  /**
   * Assert if experimental commands are enabled.
   *
   * @param {string} methodName
   *     Name of the command.
   *
   * @throws {UnknownCommandError}
   *     If experimental commands are disabled.
   */
  assertExperimentalCommandsEnabled(methodName) {
    // TODO: 1778987. Move it to a BiDi specific place.
    if (lazy.disabledExperimentalAPI) {
      throw new lazy.error.UnknownCommandError(methodName);
    }
  }

  /**
   * Assert if experimental events are enabled.
   *
   * @param {string} moduleName
   *     Name of the module.
   *
   * @param {string} event
   *     Name of the event.
   *
   * @throws {InvalidArgumentError}
   *     If experimental events are disabled.
   */
  assertExperimentalEventsEnabled(moduleName, event) {
    // TODO: 1778987. Move it to a BiDi specific place.
    if (lazy.disabledExperimentalAPI) {
      throw new lazy.error.InvalidArgumentError(
        `Module ${moduleName} does not support event ${event}`
      );
    }
  }

  /**
   * Instance shortcut for supportsMethod to avoid reaching the constructor for
   * consumers which directly deal with an instance.
   */
  supportsMethod(methodName) {
    return this.constructor.supportsMethod(methodName);
  }

  get messageHandler() {
    return this.#messageHandler;
  }

  static get supportedEvents() {
    return [];
  }

  static supportsEvent(event) {
    return this.supportedEvents.includes(event);
  }

  static supportsMethod(methodName) {
    return typeof this.prototype[methodName] === "function";
  }
}