summaryrefslogtreecommitdiffstats
path: root/remote/shared/listeners/NavigationListener.sys.mjs
blob: c911bb53f6fcd2f5e666bcae986d6087d35a8a85 (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
/* 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, {
  EventEmitter: "resource://gre/modules/EventEmitter.sys.mjs",
});

/**
 * The NavigationListener simply wraps a NavigationManager instance and exposes
 * it with a convenient listener API, more consistent with the rest of the
 * remote codebase. NavigationManager is a singleton per session so it can't
 * be instanciated for each and every consumer.
 *
 * Example:
 * ```
 * const onNavigationStarted = (eventName, data = {}) => {
 *   const { level, message, stacktrace, timestamp } = data;
 *   ...
 * };
 *
 * const listener = new NavigationListener(this.messageHandler.navigationManager);
 * listener.on("navigation-started", onNavigationStarted);
 * listener.startListening();
 * ...
 * listener.stopListening();
 * ```
 *
 * @fires message
 *    The NavigationListener emits "navigation-started", "location-changed" and
 *    "navigation-stopped" events, with the following object as payload:
 *      - {string} navigationId - The UUID for the navigation.
 *      - {string} navigableId - The UUID for the navigable.
 *      - {string} url - The target url for the navigation.
 */
export class NavigationListener {
  #listening;
  #navigationManager;

  /**
   * Create a new NavigationListener instance.
   *
   * @param {NavigationManager} navigationManager
   *     The underlying NavigationManager for this listener.
   */
  constructor(navigationManager) {
    lazy.EventEmitter.decorate(this);

    this.#listening = false;
    this.#navigationManager = navigationManager;
  }

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

  destroy() {
    this.stopListening();
  }

  startListening() {
    if (this.#listening) {
      return;
    }

    this.#navigationManager.on("navigation-started", this.#forwardEvent);
    this.#navigationManager.on("navigation-stopped", this.#forwardEvent);
    this.#navigationManager.on("location-changed", this.#forwardEvent);

    this.#listening = true;
  }

  stopListening() {
    if (!this.#listening) {
      return;
    }

    this.#navigationManager.off("navigation-started", this.#forwardEvent);
    this.#navigationManager.off("navigation-stopped", this.#forwardEvent);
    this.#navigationManager.off("location-changed", this.#forwardEvent);

    this.#listening = false;
  }

  #forwardEvent = (name, data) => {
    this.emit(name, data);
  };
}