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
|
"use strict";
{
let handlers = new Set();
let dispatch = async (msg, sender) => {
let {__meta, _messageName} = msg;
if (!__meta) {
// legacy message from embedder?
if (!_messageName) {
throw new Error(`NoScript cannot handle message %s`, JSON.stringify(msg));
}
__meta = {name: _messageName};
}
let {name} = __meta;
let answers = [];
for (let h of handlers) {
let f = h[name];
if (typeof f === "function") {
answers.push(f(msg, sender));
}
}
if (answers.length) {
return await (
answers.length === 1 ? answers.pop(): Promise.all(answers)
);
}
let context = typeof window === "object" && window.location.href || "?";
let originalSender = __meta.originalSender || sender;
let {url} = originalSender;
if (url && context.replace(/[?#].*/, '') === url.replace(/[?#].*/, '')) {
throw new Error(`Message ${name} ${JSON.stringify(msg)} looping to its sender (${context})`);
}
console.debug("Warning: no handler for message %o in context %s", msg, context);
if (originalSender.tab && originalSender.tab.id) {
// if we're receiving a message from content, there might be another
// Messages instance in a different context (e.g. background page vs
// options page vs browser action) capable of processing it, and we've
// just "steal" it. Let's rebroadcast.
return await Messages.send(name, msg, {originalSender});
}
throw new Error(`No handler registered for message "${name}" in context ${context}`);
};
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);
}
}
}
|