OLD | NEW |
| (Empty) |
1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
4 | |
5 let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); | |
6 let {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {}); | |
7 | |
8 let {addonRoot, addonName} = require("info"); | |
9 let branchName = "extensions." + addonName + "."; | |
10 let branch = Services.prefs.getBranch(branchName); | |
11 let preconfiguredBranch = | |
12 Services.prefs.getBranch(branchName + "preconfigured."); | |
13 let ignorePrefChanges = false; | |
14 | |
15 function init() | |
16 { | |
17 // Load default preferences and set up properties for them | |
18 let defaultBranch = Services.prefs.getDefaultBranch(branchName); | |
19 | |
20 let prefsData = require("prefs.json"); | |
21 let defaults = prefsData.defaults; | |
22 let preconfigurable = new Set(prefsData.preconfigurable); | |
23 for (let pref in defaults) | |
24 { | |
25 let value = defaults[pref]; | |
26 let [getter, setter] = typeMap[typeof value]; | |
27 if (preconfigurable.has(pref)) | |
28 { | |
29 try | |
30 { | |
31 value = getter(preconfiguredBranch, pref); | |
32 } | |
33 catch (e) {} | |
34 } | |
35 setter(defaultBranch, pref, value); | |
36 defineProperty(pref, false, getter, setter); | |
37 } | |
38 | |
39 // Add preference change observer | |
40 try | |
41 { | |
42 branch.QueryInterface(Ci.nsIPrefBranch2).addObserver("", Prefs, true); | |
43 onShutdown.add(() => branch.removeObserver("", Prefs)); | |
44 } | |
45 catch (e) | |
46 { | |
47 Cu.reportError(e); | |
48 } | |
49 } | |
50 | |
51 /** | |
52 * Sets up getter/setter on Prefs object for preference. | |
53 */ | |
54 function defineProperty(/**String*/ name, defaultValue, /**Function*/ readFunc,
/**Function*/ writeFunc) | |
55 { | |
56 let value = defaultValue; | |
57 Prefs["_update_" + name] = () => | |
58 { | |
59 try | |
60 { | |
61 value = readFunc(branch, name); | |
62 triggerListeners(name); | |
63 } | |
64 catch(e) | |
65 { | |
66 Cu.reportError(e); | |
67 } | |
68 }; | |
69 Object.defineProperty(Prefs, name, { | |
70 enumerable: true, | |
71 get: () => value, | |
72 set: (newValue) => | |
73 { | |
74 if (value == newValue) | |
75 return value; | |
76 | |
77 try | |
78 { | |
79 ignorePrefChanges = true; | |
80 writeFunc(branch, name, newValue); | |
81 value = newValue; | |
82 Services.prefs.savePrefFile(null); | |
83 triggerListeners(name); | |
84 } | |
85 catch(e) | |
86 { | |
87 Cu.reportError(e); | |
88 } | |
89 finally | |
90 { | |
91 ignorePrefChanges = false; | |
92 } | |
93 return value; | |
94 } | |
95 }); | |
96 Prefs["_update_" + name](); | |
97 } | |
98 | |
99 let listeners = []; | |
100 function triggerListeners(/**String*/ name) | |
101 { | |
102 for (let i = 0; i < listeners.length; i++) | |
103 { | |
104 try | |
105 { | |
106 listeners[i](name); | |
107 } | |
108 catch(e) | |
109 { | |
110 Cu.reportError(e); | |
111 } | |
112 } | |
113 } | |
114 | |
115 /** | |
116 * Manages the preferences for an extension, object properties corresponding | |
117 * to extension's preferences are added automatically. Setting the property | |
118 * will automatically change the preference, external preference changes are | |
119 * also recognized automatically. | |
120 */ | |
121 let Prefs = exports.Prefs = | |
122 { | |
123 /** | |
124 * Migrates an old preference to a new name. | |
125 */ | |
126 migrate: function(/**String*/ oldName, /**String*/ newName) | |
127 { | |
128 if (newName in this && Services.prefs.prefHasUserValue(oldName)) | |
129 { | |
130 let [getter, setter] = typeMap[typeof this[newName]]; | |
131 try | |
132 { | |
133 this[newName] = getter(Services.prefs, oldName); | |
134 } catch(e) {} | |
135 Services.prefs.clearUserPref(oldName); | |
136 } | |
137 }, | |
138 | |
139 /** | |
140 * Adds a preferences listener that will be fired whenever a preference | |
141 * changes. | |
142 */ | |
143 addListener: function(/**Function*/ listener) | |
144 { | |
145 if (listeners.indexOf(listener) < 0) | |
146 listeners.push(listener); | |
147 }, | |
148 | |
149 /** | |
150 * Removes a preferences listener. | |
151 */ | |
152 removeListener: function(/**Function*/ listener) | |
153 { | |
154 let index = listeners.indexOf(listener); | |
155 if (index >= 0) | |
156 listeners.splice(index, 1); | |
157 }, | |
158 | |
159 observe: function(subject, topic, data) | |
160 { | |
161 if (ignorePrefChanges || topic != "nsPref:changed") | |
162 return; | |
163 | |
164 if ("_update_" + data in this) | |
165 this["_update_" + data](); | |
166 }, | |
167 | |
168 QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIObse
rver]) | |
169 }; | |
170 | |
171 let getIntPref = (branch, pref) => branch.getIntPref(pref); | |
172 let setIntPref = (branch, pref, newValue) => branch.setIntPref(pref, newValue); | |
173 | |
174 let getBoolPref = (branch, pref) => branch.getBoolPref(pref); | |
175 let setBoolPref = (branch, pref, newValue) => branch.setBoolPref(pref, newValue)
; | |
176 | |
177 let getCharPref = (branch, pref) => branch.getComplexValue(pref, Ci.nsISupportsS
tring).data; | |
178 let setCharPref = (branch, pref, newValue) => | |
179 { | |
180 let str = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsSt
ring); | |
181 str.data = newValue; | |
182 branch.setComplexValue(pref, Ci.nsISupportsString, str); | |
183 }; | |
184 | |
185 let getJSONPref = (branch, pref) => JSON.parse(getCharPref(branch, pref)); | |
186 let setJSONPref = (branch, pref, newValue) => setCharPref(branch, pref, JSON.str
ingify(newValue)); | |
187 | |
188 // Getter/setter functions for difference preference types | |
189 let typeMap = | |
190 { | |
191 boolean: [getBoolPref, setBoolPref], | |
192 number: [getIntPref, setIntPref], | |
193 string: [getCharPref, setCharPref], | |
194 object: [getJSONPref, setJSONPref] | |
195 }; | |
196 | |
197 init(); | |
OLD | NEW |