1 /* coded by Ketmar // Invisible Vector (psyc://ketmar.no-ip.org/~Ketmar)
2 * Understanding is not required. Only obedience.
4 * This program is free software. It comes without any warranty, to
5 * the extent permitted by applicable law. You can redistribute it
6 * and/or modify it under the terms of the Do What The Fuck You Want
7 * To Public License, Version 2, as published by Sam Hocevar. See
8 * http://www.wtfpl.net/txt/copying/ for more details.
10 ////////////////////////////////////////////////////////////////////////////////
11 this.EXPORTED_SYMBOLS = [
13 "removeSignalListener",
18 ////////////////////////////////////////////////////////////////////////////////
19 const {utils:Cu, classes:Cc, interfaces:Ci, results:Cr} = Components;
23 let uuidgen = Cc["@mozilla.org/uuid-generator;1"].createInstance(Ci.nsIUUIDGenerator);
24 if (!uuidgen) throw new Error("no UUID generator available!");
25 return uuidgen.generateUUID().toString().replace(/[^-a-z0-9]/ig, "");
29 ////////////////////////////////////////////////////////////////////////////////
30 const signalNamePrefix = "signal-"+genUUID()+"-";
31 const obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
34 ////////////////////////////////////////////////////////////////////////////////
41 function addSignalListener (name, cback) {
42 if (typeof(name) !== "string" || !name) throw new Error("invalid signal name");
43 if (typeof(cback) !== "function") throw new Error("callback function expected");
44 // check if already here
45 let nfo = observers[name];
46 if (nfo !== undefined) {
47 for (let cb of nfo.callbacks) if (cb === cback) return; // nothing to do
49 // no observer, create one
52 observe: function (subject, topic, data) {
53 topic = topic.substr(signalNamePrefix.length); // remove prefix
54 if (data && data.length) {
55 try { data = JSON.parse(data); } catch (e) { Cu.reportError(e); return; }
59 for (let cb of nfo.callbacks) {
60 try { cb(topic, data); } catch (e) { Cu.reportError(e); }
64 obs.addObserver(nfo.observer, signalNamePrefix+name, false);
65 observers[name] = nfo;
67 nfo.callbacks.push(cback);
71 function removeSignalListener (name, cback) {
72 if (typeof(name) !== "string" || !name) throw new Error("invalid signal name");
73 if (typeof(cback) !== "function") throw new Error("callback function expected");
75 let nfo = observers[name];
76 if (nfo !== undefined) {
77 for (let [idx, cb] of Iterator(nfo.callbacks)) {
80 nfo.callbacks.splice(idx, 1);
81 // if there's no more callbacks, remove observer
82 if (nfo.callbacks.length === 0) {
83 obs.removeObserver(nfo.observer, signalNamePrefix+name);
84 delete observers[name];
93 function emitSignal (name, data) {
94 if (typeof(name) !== "string" || !name) throw new Error("invalid signal name");
95 if (!(name in observers)) return; // no listeners -- no need to send anything
96 data = (typeof(data) === "undefined" ? null : (data !== null ? JSON.stringify(data) : null));
97 obs.notifyObservers(null, signalNamePrefix+name, data);