/** * This file is part of Haketilo. * * Function: Message server. * * Copyright (C) 2021 Wojtek Kosior * * 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. * * As additional permission under GNU GPL version 3 section 7, you * may distribute forms of that code without the copy of the GNU * GPL normally required by section 4, provided you include this * license notice and, in case of non-source distribution, a URL * through which recipients can access the Corresponding Source. * If you modify file(s) with this exception, you may extend this * exception to your version of the file(s), but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. * * As a special exception to the GPL, any HTML file which merely * makes function calls to this code, and for that purpose * includes it by reference shall be deemed a separate work for * copyright law purposes. If you modify this code, you may extend * this exception to your version of the code, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * I, Wojtek Kosior, thereby promise not to sue for violation of this file's * license. Although I request that you do not make use of this code in a * proprietary program, I am not going to enforce this in court. */ #FROM common/browser.js IMPORT browser let listeners = {}; let listening = false; function raw_listen(port) { if (listeners[port.name] === undefined) return; listeners[port.name](port); } /* magic should be one of the constants from /common/connection_types.js */ function listen_for_connection(magic, cb) { if (!listening) { listening = true; browser.runtime.onConnect.addListener(raw_listen); } listeners[magic] = cb; } #EXPORT listen_for_connection /* * Messaging background page from itself might result in messages being silently * discarded. Here we implement an interface (somewhat) compatible with the one * provided by the browser, but which allows for background page to communicate * with itself. */ function EvTarget() { this.listeners = new Set(); this.addListener = cb => this.listeners.add(cb); this.removeListener = cb => this.listeners.delete(cb); this.dispatch = msg => this.listeners.forEach(l => l(msg)); } function Port(magic) { this.name = magic; this.onDisconnect = new EvTarget(); this.onMessage = new EvTarget(); this.postMessage = msg => this.other.onMessage.dispatch(msg); this.disconnect = () => this.other.onDisconnect.dispatch(this.other); } let bg_page_url; function connect_to_background(magic) { if (bg_page_url === undefined) bg_page_url = browser.runtime.getURL("_generated_background_page.html"); if (typeof document === "undefined" || document.URL !== bg_page_url) return browser.runtime.connect({name: magic}); if (!(magic in listeners)) throw `no listener for '${magic}'`; const ports = [new Port(magic), new Port(magic)]; ports[0].other = ports[1]; ports[1].other = ports[0]; listeners[magic](ports[0]); return ports[1]; } #EXPORT connect_to_background