File: notifyTools.js

package info (click to toggle)
quicktext 6.4.6-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 696 kB
  • sloc: javascript: 3,228; makefile: 24; sh: 8
file content (165 lines) | stat: -rw-r--r-- 4,879 bytes parent folder | download | duplicates (3)
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// Set this to the ID of your add-on, or call notifyTools.setAddonID().
const ADDON_ID = "{8845E3B3-E8FB-40E2-95E9-EC40294818C4}";

/*
 * This file is provided by the addon-developer-support repository at
 * https://github.com/thundernest/addon-developer-support
 *
 * For usage descriptions, please check:
 * https://github.com/thundernest/addon-developer-support/tree/master/scripts/notifyTools
 *
 * Version 1.6
 * - adjusted to Thunderbird Supernova (Services is now in globalThis)
 *
 * Version 1.5
 * - deprecate enable(), disable() and registerListener()
 * - add setAddOnId()
 *
 * Version 1.4
 * - auto enable/disable
 *
 * Version 1.3
 * - registered listeners for notifyExperiment can return a value
 * - remove WindowListener from name of observer
 *
 * Author: John Bieling (john@thunderbird.net)
 *
 * 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/.
 */

var notifyTools = {
  registeredCallbacks: {},
  registeredCallbacksNextId: 1,
  addOnId: ADDON_ID,

  setAddOnId: function (addOnId) {
    this.addOnId = addOnId;
  },

  onNotifyExperimentObserver: {
    observe: async function (aSubject, aTopic, aData) {
      if (notifyTools.addOnId == "") {
        throw new Error("notifyTools: ADDON_ID is empty!");
      }
      if (aData != notifyTools.addOnId) {
        return;
      }
      let payload = aSubject.wrappedJSObject;

      // Make sure payload has a resolve function, which we use to resolve the
      // observer notification.
      if (payload.resolve) {
        let observerTrackerPromises = [];
        // Push listener into promise array, so they can run in parallel
        for (let registeredCallback of Object.values(
          notifyTools.registeredCallbacks
        )) {
          observerTrackerPromises.push(registeredCallback(payload.data));
        }
        // We still have to await all of them but wait time is just the time needed
        // for the slowest one.
        let results = [];
        for (let observerTrackerPromise of observerTrackerPromises) {
          let rv = await observerTrackerPromise;
          if (rv != null) results.push(rv);
        }
        if (results.length == 0) {
          payload.resolve();
        } else {
          if (results.length > 1) {
            console.warn(
              "Received multiple results from onNotifyExperiment listeners. Using the first one, which can lead to inconsistent behavior.",
              results
            );
          }
          payload.resolve(results[0]);
        }
      } else {
        // Older version of NotifyTools, which is not sending a resolve function, deprecated.
        console.log("Please update the notifyTools API to at least v1.5");
        for (let registeredCallback of Object.values(
          notifyTools.registeredCallbacks
        )) {
          registeredCallback(payload.data);
        }
      }
    },
  },

  addListener: function (listener) {
    if (Object.values(this.registeredCallbacks).length == 0) {
      Services.obs.addObserver(
        this.onNotifyExperimentObserver,
        "NotifyExperimentObserver",
        false
      );
    }

    let id = this.registeredCallbacksNextId++;
    this.registeredCallbacks[id] = listener;
    return id;
  },

  removeListener: function (id) {
    delete this.registeredCallbacks[id];
    if (Object.values(this.registeredCallbacks).length == 0) {
      Services.obs.removeObserver(
        this.onNotifyExperimentObserver,
        "NotifyExperimentObserver"
      );
    }
  },

  removeAllListeners: function () {
    if (Object.values(this.registeredCallbacks).length != 0) {
      Services.obs.removeObserver(
        this.onNotifyExperimentObserver,
        "NotifyExperimentObserver"
      );
    }
    this.registeredCallbacks = {};
  },

  notifyBackground: function (data) {
    if (this.addOnId == "") {
      throw new Error("notifyTools: ADDON_ID is empty!");
    }
    return new Promise((resolve) => {
      Services.obs.notifyObservers(
        { data, resolve },
        "NotifyBackgroundObserver",
        this.addOnId
      );
    });
  },


  // Deprecated.

  enable: function () {
    console.log("Manually calling notifyTools.enable() is no longer needed.");
  },

  disable: function () {
    console.log("notifyTools.disable() has been deprecated, use notifyTools.removeAllListeners() instead.");
    this.removeAllListeners();
  },

  registerListener: function (listener) {
    console.log("notifyTools.registerListener() has been deprecated, use notifyTools.addListener() instead.");
    this.addListener(listener);
  },

};

if (typeof window != "undefined" && window) {
  window.addEventListener(
    "unload",
    function (event) {
      notifyTools.removeAllListeners();
    },
    false
  );
}