summaryrefslogtreecommitdiffstats
path: root/remote/shared/messagehandler/transports/js-window-actors/MessageHandlerFrameChild.sys.mjs
blob: 4f0430df1b4497a0f0ff0682416b97851be733b4 (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
/* 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, {
  isBrowsingContextCompatible:
    "chrome://remote/content/shared/messagehandler/transports/FrameContextUtils.sys.mjs",
  MessageHandlerRegistry:
    "chrome://remote/content/shared/messagehandler/MessageHandlerRegistry.sys.mjs",
  WindowGlobalMessageHandler:
    "chrome://remote/content/shared/messagehandler/WindowGlobalMessageHandler.sys.mjs",
});

/**
 * Child actor for the MessageHandlerFrame JSWindowActor. The
 * MessageHandlerFrame actor is used by FrameTransport to communicate between
 * ROOT MessageHandlers and WINDOW_GLOBAL MessageHandlers.
 */
export class MessageHandlerFrameChild extends JSWindowActorChild {
  actorCreated() {
    this.type = lazy.WindowGlobalMessageHandler.type;
    this.context = this.manager.browsingContext;

    this._registry = new lazy.MessageHandlerRegistry(this.type, this.context);
    this._onRegistryEvent = this._onRegistryEvent.bind(this);

    // MessageHandlerFrameChild is responsible for forwarding events from
    // WindowGlobalMessageHandler to the parent process.
    // Such events are re-emitted on the MessageHandlerRegistry to avoid
    // setting up listeners on individual MessageHandler instances.
    this._registry.on("message-handler-registry-event", this._onRegistryEvent);
  }

  handleEvent({ type }) {
    if (type == "DOMWindowCreated") {
      if (lazy.isBrowsingContextCompatible(this.manager.browsingContext)) {
        this._registry.createAllMessageHandlers();
      }
    }
  }

  async receiveMessage(message) {
    if (message.name === "MessageHandlerFrameParent:sendCommand") {
      const { sessionId, command } = message.data;
      const messageHandler = this._registry.getOrCreateMessageHandler(
        sessionId
      );
      try {
        return await messageHandler.handleCommand(command);
      } catch (e) {
        if (e?.isRemoteError) {
          return {
            error: e.toJSON(),
            isMessageHandlerError: e.isMessageHandlerError,
          };
        }
        throw e;
      }
    }

    return null;
  }

  _onRegistryEvent(eventName, wrappedEvent) {
    this.sendAsyncMessage(
      "MessageHandlerFrameChild:messageHandlerEvent",
      wrappedEvent
    );
  }

  didDestroy() {
    this._registry.off("message-handler-registry-event", this._onRegistryEvent);
    this._registry.destroy();
  }
}