bugfix for `GM_getValue()`, as suggested by https://github.com/qsniyg/
[guerillascript.git] / main / prefsengine.js
blobdc0a8e2669a3a5c6c41479c67181446a69eabed6
1 /* coded by Ketmar // Invisible Vector (psyc://ketmar.no-ip.org/~Ketmar)
2  * Understanding is not required. Only obedience.
3  *
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.
9  */
10 ////////////////////////////////////////////////////////////////////////////////
11 // user code should define `PREFS_BRANCH`, `PREFS` and `PREFS_DIR_NAMES`
14 ////////////////////////////////////////////////////////////////////////////////
15 function setDefaultPrefs () {
16   let branch = Services.prefs.getDefaultBranch(PREFS_BRANCH);
17   for (let [key, val] in Iterator(PREFS)) {
18     switch (typeof(val)) {
19       case "boolean": branch.setBoolPref(key, val); break;
20       case "number": branch.setIntPref(key, val); break;
21       case "string": branch.setCharPref(key, val); break;
22     }
23   }
27 ////////////////////////////////////////////////////////////////////////////////
28 let knownDirs = {};
30 function getUserXXDir (name, createit) {
31   let res = knownDirs[name];
32   if (res) {
33     // cached
34     res = res.clone();
35   } else {
36     if (!(name in PREFS_DIR_NAMES)) throw new Error("unknown 'known' dir: '"+name+"'");
37     //logError("getting dir '"+name+"'");
38     // new, cache it
39     let dn = "";
40     try { dn = Services.prefs.getCharPref(PREFS_BRANCH+name); } catch (e) {}
41     if (dn.length && dn[0] == '/') {
42       res = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
43       res.initWithPath(dn);
44     } else {
45       const dirSvcProps = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
46       // get profile directory
47       res = dirSvcProps.get("ProfD", Ci.nsIFile);
48       if (dn.length) {
49         for (let d of dn.split("/")) if (d.length) res.append(d);
50       }
51     }
52     //logError("dir ["+name+"] = ["+res.path+"]");
53     knownDirs[name] = res.clone();
54   }
55   if (createit && !res.exists()) res.create(res.DIRECTORY_TYPE, 0700);
56   return res;
59 exportsGlobal.resetUserDirCache = function () { knownDirs = {}; };
62 // build dir getters
63 if ("PREFS_DIR_NAMES" in this) {
64   let userdirs = {};
65   for (let [iname, oname] in Iterator(PREFS_DIR_NAMES)) {
66     let getter = tieto(this, getUserXXDir, iname, true);
67     exportsGlobal["getUser"+oname] = getter;
68     Object.defineProperty(userdirs, oname, {get: getter});
69   }
70   exportsGlobal.userdirs = userdirs;
74 ////////////////////////////////////////////////////////////////////////////////
75 function getAddonPref (name) {
76   if (typeof(name) == "string" && (name in PREFS)) {
77     try {
78       switch (typeof(PREFS[name])) {
79         case "boolean": return Services.prefs.getBoolPref(PREFS_BRANCH+name);
80         case "number": return Services.prefs.getIntPref(PREFS_BRANCH+name);
81         case "string": return Services.prefs.getCharPref(PREFS_BRANCH+name);
82       }
83     } catch (e) {}
84     return PREFS[name];
85   }
86   logError("k8extcarcass: invalid preference request for '"+name+"'");
87   return null;
91 ////////////////////////////////////////////////////////////////////////////////
92 function setAddonPref (name, val) {
93   if (typeof(name) == "string" && (name in PREFS)) {
94     try {
95       switch (typeof(PREFS[name])) {
96         case "boolean": val = !!val; Services.prefs.setBoolPref(PREFS_BRANCH+name, val); break;
97         case "number": val = parseInt(val); Services.prefs.setIntPref(PREFS_BRANCH+name, val); break;
98         case "string": val = ""+val; Services.prefs.setCharPref(PREFS_BRANCH+name, val); break;
99       }
100       return val;
101     } catch (e) {}
102   }
103   logError("k8extcarcass: invalid preference set request for '"+name+"'");
104   return null;
108 ////////////////////////////////////////////////////////////////////////////////
109 let addonOptions = {
110   _cache: {},
111   _resetCache: function () { addonOptions._cache = {}; },
112   _getOpt: function (name) {
113     if (!(name in addonOptions._cache)) addonOptions._cache[name] = getAddonPref(name);
114     //print("_getOpt: name='"+name+"'; val='"+addonOptions._cache[name]+"'");
115     return addonOptions._cache[name];
116   },
117   _setOpt: function (name, val) {
118     //print("_setOpt: name='", name, "'; val='", val, "'");
119     addonOptions._cache[name] = val;
120     return setAddonPref(name, val);
121   },
122   _setIntOpt: function (name, val) {
123     if (typeof(val) !== "number") {
124       let i = parseInt(""+val, 10);
125       if (isNaN(i)) throw new Error("invalid integer for option '"+name+"': '"+val+"'");
126       val = i;
127     } else {
128       val = Math.floor(val);
129     }
130     addonOptions._setOpt(name, val);
131   },
132   _setBoolOpt: function (name, val) { addonOptions._setOpt(name, !!val); },
133   _setStrOpt: function (name, val) { addonOptions._setOpt(name, ""+val); },
136 // fill properties
137 (function () {
138   for (let [n, v] in Iterator(PREFS)) {
139     if (!n || typeof(n) !== "string") continue; // just in case
140     if (n in PREFS_DIR_NAMES) continue; // this has special getters
141     let getter = tieto(addonOptions, "_getOpt", n);
142     let setter = false;
143     switch (typeof(v)) {
144       case "boolean": setter = tieto(addonOptions, "_setBoolOpt", n); break;
145       case "number": setter = tieto(addonOptions, "_setIntOpt", n); break;
146       case "string": setter = tieto(addonOptions, "_setStrOpt", n); break;
147     }
148     if (setter) Object.defineProperty(addonOptions, n, {get:getter, set:setter});
149   }
150 })();
151 exportsGlobal.addonOptions = addonOptions;
154 ////////////////////////////////////////////////////////////////////////////////
155 let prefObserver = {
156   observe: function (aSubject, aTopic, aData) {
157     //conlog("data: ["+aData+"]; subj="+aSubject+"; topic="+aTopic);
158     //let name = aData.substr(PREFS_BRANCH.length);
159     //conlog("name: ["+name+"]");
160     //let prf = Services.prefs;
161     //if (name == "openErrorConsoleOnStartup") addonOptions.openConsole = prf.getBoolPref(aData);
162     if (aData.indexOf("dir") > 0) {
163       resetUserDirCache();
164     } else {
165       addonOptions._resetCache();
166     }
167   },
171 ////////////////////////////////////////////////////////////////////////////////
172 registerStartupHook("preferences", function () {
173   setDefaultPrefs(); // always set the default prefs as they disappear on restart
174   Services.prefs.addObserver(PREFS_BRANCH, prefObserver, false);
178 registerShutdownHook("preferences", function () {
179   Services.prefs.removeObserver(PREFS_BRANCH, prefObserver);