2 Copyright (C) 2017 Kai Uwe Broulik <kde@privat.broulik.de>
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 3 of
7 the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 var callbacks = {}; // TODO rename to "portCallbacks"?
21 var runtimeCallbacks = {};
23 let currentMessageSerial = 0;
24 let pendingMessageReplyResolvers = {};
26 // Callback is called with following arguments (in that order);
27 // - The actual message data/payload
28 // - The name of the action triggered
29 function addCallback(subsystem, action, callback) // TODO rename to "addPortCallbacks"?
31 if (Array.isArray(action)) {
32 action.forEach(function(item) {
33 addCallback(subsystem, item, callback);
38 if (!callbacks[subsystem]) {
39 callbacks[subsystem] = {};
41 callbacks[subsystem][action] = callback;
44 function sendPortMessage(subsystem, event, payload)
46 // why do we put stuff on root level here but otherwise have a "payload"? :(
47 var message = payload || {}
48 message.subsystem = subsystem;
49 message.event = event;
51 port.postMessage(message);
54 function sendPortMessageWithReply(subsystem, event, payload)
56 return new Promise((resolve, reject) => {
57 let message = payload || {};
58 message.subsystem = subsystem;
59 message.event = event;
60 ++currentMessageSerial;
61 if (currentMessageSerial >= Math.pow(2, 31) - 1) { // INT_MAX
62 currentMessageSerial = 0;
64 message.serial = currentMessageSerial;
66 port.postMessage(message);
68 pendingMessageReplyResolvers[message.serial] = resolve;
72 // Callback is called with following arguments (in that order);
73 // - The actual message data/payload
74 // - Information about the sender of the message (including tab and frameId)
75 // - The name of the action triggered
76 // Return a Promise from the callback if you wish to send a reply to the sender
77 function addRuntimeCallback(subsystem, action, callback)
79 if (action.constructor === Array) {
80 action.forEach(function(item) {
81 addRuntimeCallback(subsystem, item, callback);
86 if (!runtimeCallbacks[subsystem]) {
87 runtimeCallbacks[subsystem] = {};
89 runtimeCallbacks[subsystem][action] = callback;
92 // returns an Object which only contains values for keys in allowedKeys
93 function filterObject(obj, allowedKeys) {
96 // I bet this can be done in a more efficient way
98 if (obj.hasOwnProperty(key) && allowedKeys.indexOf(key) > -1) {
99 newObj[key] = obj[key];
106 // filters objects within an array so they only contain values for keys in allowedKeys
107 function filterArrayObjects(arr, allowedKeys) {
108 return arr.map(function (item) {
109 return filterObject(item, allowedKeys);
113 chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
114 // TODO check sender for privilege
116 var subsystem = message.subsystem;
117 var action = message.action;
119 if (!subsystem || !action) {
123 if (runtimeCallbacks[subsystem] && runtimeCallbacks[subsystem][action]) {
124 let result = runtimeCallbacks[subsystem][action](message.payload, sender, action);
127 if (typeof result !== "object" || typeof result.then !== "function") {
131 result.then((response) => {
132 sendResponse(response);
143 console.warn("Don't know what to do with runtime message", subsystem, action);