Bug 1586801 - Use the contextual WalkerFront in _duplicateNode(). r=pbro
[gecko.git] / toolkit / modules / AsyncPrefs.jsm
blob1a756afbb3dc8f7da58498a3c85e42512504fa24
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/. */
5 "use strict";
7 var EXPORTED_SYMBOLS = ["AsyncPrefs"];
9 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
11 const kInChildProcess =
12   Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT;
14 const kAllowedPrefs = new Set([
15   // NB: please leave the testing prefs at the top, and sort the rest alphabetically if you add
16   // anything.
17   "testing.allowed-prefs.some-bool-pref",
18   "testing.allowed-prefs.some-char-pref",
19   "testing.allowed-prefs.some-int-pref",
21   "narrate.rate",
22   "narrate.voice",
24   "reader.font_size",
25   "reader.font_type",
26   "reader.color_scheme",
27   "reader.content_width",
28   "reader.line_height",
30   "security.tls.version.enable-deprecated",
31 ]);
33 const kPrefTypeMap = new Map([
34   ["boolean", Services.prefs.PREF_BOOL],
35   ["number", Services.prefs.PREF_INT],
36   ["string", Services.prefs.PREF_STRING],
37 ]);
39 function maybeReturnErrorForReset(pref) {
40   if (!kAllowedPrefs.has(pref)) {
41     return `Resetting pref ${pref} from content is not allowed.`;
42   }
43   return false;
46 function maybeReturnErrorForSet(pref, value) {
47   if (!kAllowedPrefs.has(pref)) {
48     return `Setting pref ${pref} from content is not allowed.`;
49   }
51   let valueType = typeof value;
52   if (!kPrefTypeMap.has(valueType)) {
53     return `Can't set pref ${pref} to value of type ${valueType}.`;
54   }
55   let prefType = Services.prefs.getPrefType(pref);
56   if (
57     prefType != Services.prefs.PREF_INVALID &&
58     prefType != kPrefTypeMap.get(valueType)
59   ) {
60     return `Can't set pref ${pref} to a value with type ${valueType} that doesn't match the pref's type ${prefType}.`;
61   }
62   return false;
65 var AsyncPrefs;
66 if (kInChildProcess) {
67   let gUniqueId = 0;
68   let gMsgMap = new Map();
70   AsyncPrefs = {
71     set(pref, value) {
72       let error = maybeReturnErrorForSet(pref, value);
73       if (error) {
74         return Promise.reject(error);
75       }
77       let msgId = ++gUniqueId;
78       return new Promise((resolve, reject) => {
79         gMsgMap.set(msgId, { resolve, reject });
80         Services.cpmm.sendAsyncMessage("AsyncPrefs:SetPref", {
81           pref,
82           value,
83           msgId,
84         });
85       });
86     },
88     reset(pref) {
89       let error = maybeReturnErrorForReset(pref);
90       if (error) {
91         return Promise.reject(error);
92       }
94       let msgId = ++gUniqueId;
95       return new Promise((resolve, reject) => {
96         gMsgMap.set(msgId, { resolve, reject });
97         Services.cpmm.sendAsyncMessage("AsyncPrefs:ResetPref", { pref, msgId });
98       });
99     },
101     receiveMessage(msg) {
102       let promiseRef = gMsgMap.get(msg.data.msgId);
103       if (promiseRef) {
104         gMsgMap.delete(msg.data.msgId);
105         if (msg.data.success) {
106           promiseRef.resolve();
107         } else {
108           promiseRef.reject(msg.data.message);
109         }
110       }
111     },
112   };
114   Services.cpmm.addMessageListener("AsyncPrefs:PrefSetFinished", AsyncPrefs);
115   Services.cpmm.addMessageListener("AsyncPrefs:PrefResetFinished", AsyncPrefs);
116 } else {
117   AsyncPrefs = {
118     methodForType: {
119       number: "setIntPref",
120       boolean: "setBoolPref",
121       string: "setCharPref",
122     },
124     set(pref, value) {
125       let error = maybeReturnErrorForSet(pref, value);
126       if (error) {
127         return Promise.reject(error);
128       }
129       let methodToUse = this.methodForType[typeof value];
130       try {
131         Services.prefs[methodToUse](pref, value);
132         return Promise.resolve(value);
133       } catch (ex) {
134         Cu.reportError(ex);
135         return Promise.reject(ex.message);
136       }
137     },
139     reset(pref) {
140       let error = maybeReturnErrorForReset(pref);
141       if (error) {
142         return Promise.reject(error);
143       }
145       try {
146         Services.prefs.clearUserPref(pref);
147         return Promise.resolve();
148       } catch (ex) {
149         Cu.reportError(ex);
150         return Promise.reject(ex.message);
151       }
152     },
154     receiveMessage(msg) {
155       if (msg.name == "AsyncPrefs:SetPref") {
156         this.onPrefSet(msg);
157       } else {
158         this.onPrefReset(msg);
159       }
160     },
162     onPrefReset(msg) {
163       let { pref, msgId } = msg.data;
164       this.reset(pref).then(
165         function() {
166           msg.target.sendAsyncMessage("AsyncPrefs:PrefResetFinished", {
167             msgId,
168             success: true,
169           });
170         },
171         function(msg) {
172           msg.target.sendAsyncMessage("AsyncPrefs:PrefResetFinished", {
173             msgId,
174             success: false,
175             message: msg,
176           });
177         }
178       );
179     },
181     onPrefSet(msg) {
182       let { pref, value, msgId } = msg.data;
183       this.set(pref, value).then(
184         function() {
185           msg.target.sendAsyncMessage("AsyncPrefs:PrefSetFinished", {
186             msgId,
187             success: true,
188           });
189         },
190         function(msg) {
191           msg.target.sendAsyncMessage("AsyncPrefs:PrefSetFinished", {
192             msgId,
193             success: false,
194             message: msg,
195           });
196         }
197       );
198     },
200     init() {
201       // PLEASE KEEP THIS LIST IN SYNC WITH THE LISTENERS ADDED IN nsBrowserGlue
202       Services.ppmm.addMessageListener("AsyncPrefs:SetPref", this);
203       Services.ppmm.addMessageListener("AsyncPrefs:ResetPref", this);
204       // PLEASE KEEP THIS LIST IN SYNC WITH THE LISTENERS ADDED IN nsBrowserGlue
205     },
206   };