Bug 1611178 [wpt PR 21377] - Update wpt metadata, a=testonly
[gecko.git] / toolkit / modules / AsyncPrefs.jsm
blobb209f98d73ea77a943395e820baa616e3bedd19d
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.ssl.errorReporting.automatic",
31   "security.tls.version.enable-deprecated",
32 ]);
34 const kPrefTypeMap = new Map([
35   ["boolean", Services.prefs.PREF_BOOL],
36   ["number", Services.prefs.PREF_INT],
37   ["string", Services.prefs.PREF_STRING],
38 ]);
40 function maybeReturnErrorForReset(pref) {
41   if (!kAllowedPrefs.has(pref)) {
42     return `Resetting pref ${pref} from content is not allowed.`;
43   }
44   return false;
47 function maybeReturnErrorForSet(pref, value) {
48   if (!kAllowedPrefs.has(pref)) {
49     return `Setting pref ${pref} from content is not allowed.`;
50   }
52   let valueType = typeof value;
53   if (!kPrefTypeMap.has(valueType)) {
54     return `Can't set pref ${pref} to value of type ${valueType}.`;
55   }
56   let prefType = Services.prefs.getPrefType(pref);
57   if (
58     prefType != Services.prefs.PREF_INVALID &&
59     prefType != kPrefTypeMap.get(valueType)
60   ) {
61     return `Can't set pref ${pref} to a value with type ${valueType} that doesn't match the pref's type ${prefType}.`;
62   }
63   return false;
66 var AsyncPrefs;
67 if (kInChildProcess) {
68   let gUniqueId = 0;
69   let gMsgMap = new Map();
71   AsyncPrefs = {
72     set(pref, value) {
73       let error = maybeReturnErrorForSet(pref, value);
74       if (error) {
75         return Promise.reject(error);
76       }
78       let msgId = ++gUniqueId;
79       return new Promise((resolve, reject) => {
80         gMsgMap.set(msgId, { resolve, reject });
81         Services.cpmm.sendAsyncMessage("AsyncPrefs:SetPref", {
82           pref,
83           value,
84           msgId,
85         });
86       });
87     },
89     reset(pref) {
90       let error = maybeReturnErrorForReset(pref);
91       if (error) {
92         return Promise.reject(error);
93       }
95       let msgId = ++gUniqueId;
96       return new Promise((resolve, reject) => {
97         gMsgMap.set(msgId, { resolve, reject });
98         Services.cpmm.sendAsyncMessage("AsyncPrefs:ResetPref", { pref, msgId });
99       });
100     },
102     receiveMessage(msg) {
103       let promiseRef = gMsgMap.get(msg.data.msgId);
104       if (promiseRef) {
105         gMsgMap.delete(msg.data.msgId);
106         if (msg.data.success) {
107           promiseRef.resolve();
108         } else {
109           promiseRef.reject(msg.data.message);
110         }
111       }
112     },
113   };
115   Services.cpmm.addMessageListener("AsyncPrefs:PrefSetFinished", AsyncPrefs);
116   Services.cpmm.addMessageListener("AsyncPrefs:PrefResetFinished", AsyncPrefs);
117 } else {
118   AsyncPrefs = {
119     methodForType: {
120       number: "setIntPref",
121       boolean: "setBoolPref",
122       string: "setCharPref",
123     },
125     set(pref, value) {
126       let error = maybeReturnErrorForSet(pref, value);
127       if (error) {
128         return Promise.reject(error);
129       }
130       let methodToUse = this.methodForType[typeof value];
131       try {
132         Services.prefs[methodToUse](pref, value);
133         return Promise.resolve(value);
134       } catch (ex) {
135         Cu.reportError(ex);
136         return Promise.reject(ex.message);
137       }
138     },
140     reset(pref) {
141       let error = maybeReturnErrorForReset(pref);
142       if (error) {
143         return Promise.reject(error);
144       }
146       try {
147         Services.prefs.clearUserPref(pref);
148         return Promise.resolve();
149       } catch (ex) {
150         Cu.reportError(ex);
151         return Promise.reject(ex.message);
152       }
153     },
155     receiveMessage(msg) {
156       if (msg.name == "AsyncPrefs:SetPref") {
157         this.onPrefSet(msg);
158       } else {
159         this.onPrefReset(msg);
160       }
161     },
163     onPrefReset(msg) {
164       let { pref, msgId } = msg.data;
165       this.reset(pref).then(
166         function() {
167           msg.target.sendAsyncMessage("AsyncPrefs:PrefResetFinished", {
168             msgId,
169             success: true,
170           });
171         },
172         function(msg) {
173           msg.target.sendAsyncMessage("AsyncPrefs:PrefResetFinished", {
174             msgId,
175             success: false,
176             message: msg,
177           });
178         }
179       );
180     },
182     onPrefSet(msg) {
183       let { pref, value, msgId } = msg.data;
184       this.set(pref, value).then(
185         function() {
186           msg.target.sendAsyncMessage("AsyncPrefs:PrefSetFinished", {
187             msgId,
188             success: true,
189           });
190         },
191         function(msg) {
192           msg.target.sendAsyncMessage("AsyncPrefs:PrefSetFinished", {
193             msgId,
194             success: false,
195             message: msg,
196           });
197         }
198       );
199     },
201     init() {
202       // PLEASE KEEP THIS LIST IN SYNC WITH THE LISTENERS ADDED IN nsBrowserGlue
203       Services.ppmm.addMessageListener("AsyncPrefs:SetPref", this);
204       Services.ppmm.addMessageListener("AsyncPrefs:ResetPref", this);
205       // PLEASE KEEP THIS LIST IN SYNC WITH THE LISTENERS ADDED IN nsBrowserGlue
206     },
207   };