summaryrefslogtreecommitdiff
path: root/src/lib/Messages.js
blob: f33b62174f9797507f96c32a61c9563ccf3c55de (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
"use strict";
{
  let handlers = new Set();

  let dispatch = (msg, sender) => {
    let {__meta, _messageName} = msg;
    if (!__meta) {
      // legacy message from embedder or library? ignore it
      if (!_messageName) {
        debug(`Message not in NoScript-specific format: %s`, JSON.stringify(msg));
        return undefined;
      }
      __meta = {name: _messageName};
    }
    let {name} = __meta;
    let responderFound = false;
    let exception = null;
    for (let h of handlers) {
      let f = h[name];

      if (typeof f === "function") {
        let result;
        try {
          result = f(msg, sender);
        } catch (e) {
          error(e);
          exception = e;
          continue;
        }
        if (typeof result === "undefined") {
          responderFound = true;
          continue;
        }
        return (result instanceof Promise) ? result
          : new Promise(r => r(result));
      }
    }
    if (exception) throw exception;
    if (!responderFound) {
      debug("Warning: no handler for message %s %s in context %s", name, JSON.stringify(msg), document.URL);
    }
  };

  var Messages = {
    addHandler(handler) {
      let originalSize = handlers.size;
      handlers.add(handler);
      if (originalSize === 0 && handlers.size === 1) {
        browser.runtime.onMessage.addListener(dispatch);
      }
    },
    removeHandler(handler) {
      let originalSize = handlers.size;
      handlers.delete(handler);
      if (originalSize === 1 && handlers.size === 0) {
        browser.runtime.onMessage.removeListener(dispatch);
      }
    },
    async send(name, args = {}, recipientInfo = null) {
      args.__meta = {name, recipientInfo};
      args._messageName = name; // legacy protocol, for embedders
      if (recipientInfo && "tabId" in recipientInfo) {
        let opts;
        if ("frameId" in recipientInfo) opts = {frameId: recipientInfo.frameId};
        return await browser.tabs.sendMessage(recipientInfo.tabId, args, opts);
      }
      return await browser.runtime.sendMessage(args);
    },
    isMissingEndpoint(error) {
      return error && error.message ===
        "Could not esablish connection. Receiving end does not exist.";
    }
  }
}