/******************************************************************************* ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors Copyright (C) 2019-2020 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://libregit.org/heckyel/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ 'use strict'; /******************************************************************************/ (function () { Cu.import('chrome://ematrix/content/lib/CallbackWrapper.jsm'); 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})); }; })();