aboutsummaryrefslogtreecommitdiffstats
path: root/js/vapi-messaging.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/vapi-messaging.js')
-rw-r--r--js/vapi-messaging.js144
1 files changed, 144 insertions, 0 deletions
diff --git a/js/vapi-messaging.js b/js/vapi-messaging.js
new file mode 100644
index 0000000..abed913
--- /dev/null
+++ b/js/vapi-messaging.js
@@ -0,0 +1,144 @@
+/*******************************************************************************
+
+ ηMatrix - a browser extension to black/white list requests.
+ Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors
+ Copyright (C) 2019 Alessio Vanni
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see {http://www.gnu.org/licenses/}.
+
+ Home: https://gitlab.com/vannilla/ematrix
+ uMatrix Home: https://github.com/gorhill/uMatrix
+*/
+
+/* global self, Components */
+
+// For background page (tabs management)
+
+'use strict';
+
+/******************************************************************************/
+
+(function () {
+ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+ const {Services} = Cu.import('resource://gre/modules/Services.jsm', null);
+
+ let vAPI = self.vAPI; // Guaranteed to be initialized by vapi-background.js
+
+ vAPI.messaging = {
+ get globalMessageManager() {
+ return Cc['@mozilla.org/globalmessagemanager;1']
+ .getService(Ci.nsIMessageListenerManager);
+ },
+ frameScript: vAPI.getURL('frameScript.js'),
+ listeners: {},
+ defaultHandler: null,
+ NOOPFUNC: function(){},
+ UNHANDLED: 'vAPI.messaging.notHandled'
+ };
+
+ vAPI.messaging.listen = function (listenerName, callback) {
+ this.listeners[listenerName] = callback;
+ };
+
+ vAPI.messaging.onMessage = function ({target, data}) {
+ let messageManager = target.messageManager;
+
+ if (!messageManager) {
+ // Message came from a popup, and its message manager is
+ // not usable. So instead we broadcast to the parent
+ // window.
+ messageManager =
+ vAPI.browser.
+ getOwnerWindow(target.webNavigation
+ .QueryInterface(Ci.nsIDocShell)
+ .chromeEventHandler).messageManager;
+ }
+
+ let channelNameRaw = data.channelName;
+ let pos = channelNameRaw.indexOf('|');
+ let channelName = channelNameRaw.slice(pos + 1);
+
+ let callback = vAPI.messaging.NOOPFUNC;
+ if (data.requestId !== undefined) {
+ callback = CallbackWrapper.factory(messageManager,
+ channelName,
+ channelNameRaw.slice(0, pos),
+ data.requestId).callback;
+ }
+
+ let sender = {
+ tab: {
+ id: vAPI.tabs.manager.tabIdFromTarget(target)
+ }
+ };
+
+ // Specific handler
+ let r = vAPI.messaging.UNHANDLED;
+ let listener = vAPI.messaging.listeners[channelName];
+
+ if (typeof listener === 'function') {
+ r = listener(data.msg, sender, callback);
+ }
+ if (r !== vAPI.messaging.UNHANDLED) {
+ return;
+ }
+
+ // Default handler
+ r = vAPI.messaging.defaultHandler(data.msg, sender, callback);
+ if (r !== vAPI.messaging.UNHANDLED) {
+ return;
+ }
+
+ console.error('eMatrix> messaging > unknown request: %o', data);
+
+ // Unhandled: Need to callback anyways in case caller expected
+ // an answer, or else there is a memory leak on caller's side
+ callback();
+ };
+
+ vAPI.messaging.setup = function (defaultHandler) {
+ // Already setup?
+ if (this.defaultHandler !== null) {
+ return;
+ }
+
+ if (typeof defaultHandler !== 'function') {
+ defaultHandler = function () {
+ return vAPI.messaging.UNHANDLED;
+ };
+ }
+
+ this.defaultHandler = defaultHandler;
+ this.globalMessageManager.addMessageListener(location.host
+ + ':background',
+ this.onMessage);
+ this.globalMessageManager.loadFrameScript(this.frameScript, true);
+
+ vAPI.addCleanUpTask(function () {
+ let gmm = vAPI.messaging.globalMessageManager;
+
+ gmm.removeDelayedFrameScript(vAPI.messaging.frameScript);
+ gmm.removeMessageListener(location.host + ':background',
+ vAPI.messaging.onMessage);
+ });
+ };
+
+ vAPI.messaging.broadcast = function (message) {
+ this.globalMessageManager
+ .broadcastAsyncMessage(location.host + ':broadcast',
+ JSON.stringify({
+ broadcast: true,
+ msg: message}));
+ };
+})();