Bug 1625482 [wpt PR 22496] - [ScrollTimeline] Do not show scrollbar to bypass flakine...
[gecko.git] / toolkit / modules / AsyncPrefs.jsm
blobaca86556cd5e273e4c808cac9ef983ac4d43ba2a
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   "browser.contentblocking.report.hide_lockwise_app",
33   "browser.contentblocking.report.show_mobile_app",
34 ]);
36 const kPrefTypeMap = new Map([
37   ["boolean", Services.prefs.PREF_BOOL],
38   ["number", Services.prefs.PREF_INT],
39   ["string", Services.prefs.PREF_STRING],
40 ]);
42 function maybeReturnErrorForReset(pref) {
43   if (!kAllowedPrefs.has(pref)) {
44     return `Resetting pref ${pref} from content is not allowed.`;
45   }
46   return false;
49 function maybeReturnErrorForSet(pref, value) {
50   if (!kAllowedPrefs.has(pref)) {
51     return `Setting pref ${pref} from content is not allowed.`;
52   }
54   let valueType = typeof value;
55   if (!kPrefTypeMap.has(valueType)) {
56     return `Can't set pref ${pref} to value of type ${valueType}.`;
57   }
58   let prefType = Services.prefs.getPrefType(pref);
59   if (
60     prefType != Services.prefs.PREF_INVALID &&
61     prefType != kPrefTypeMap.get(valueType)
62   ) {
63     return `Can't set pref ${pref} to a value with type ${valueType} that doesn't match the pref's type ${prefType}.`;
64   }
65   return false;
68 var AsyncPrefs;
69 if (kInChildProcess) {
70   let gUniqueId = 0;
71   let gMsgMap = new Map();
73   AsyncPrefs = {
74     set(pref, value) {
75       let error = maybeReturnErrorForSet(pref, value);
76       if (error) {
77         return Promise.reject(error);
78       }
80       let msgId = ++gUniqueId;
81       return new Promise((resolve, reject) => {
82         gMsgMap.set(msgId, { resolve, reject });
83         Services.cpmm.sendAsyncMessage("AsyncPrefs:SetPref", {
84           pref,
85           value,
86           msgId,
87         });
88       });
89     },
91     reset(pref) {
92       let error = maybeReturnErrorForReset(pref);
93       if (error) {
94         return Promise.reject(error);
95       }
97       let msgId = ++gUniqueId;
98       return new Promise((resolve, reject) => {
99         gMsgMap.set(msgId, { resolve, reject });
100         Services.cpmm.sendAsyncMessage("AsyncPrefs:ResetPref", { pref, msgId });
101       });
102     },
104     receiveMessage(msg) {
105       let promiseRef = gMsgMap.get(msg.data.msgId);
106       if (promiseRef) {
107         gMsgMap.delete(msg.data.msgId);
108         if (msg.data.success) {
109           promiseRef.resolve();
110         } else {
111           promiseRef.reject(msg.data.message);
112         }
113       }
114     },
115   };
117   Services.cpmm.addMessageListener("AsyncPrefs:PrefSetFinished", AsyncPrefs);
118   Services.cpmm.addMessageListener("AsyncPrefs:PrefResetFinished", AsyncPrefs);
119 } else {
120   AsyncPrefs = {
121     methodForType: {
122       number: "setIntPref",
123       boolean: "setBoolPref",
124       string: "setCharPref",
125     },
127     set(pref, value) {
128       let error = maybeReturnErrorForSet(pref, value);
129       if (error) {
130         return Promise.reject(error);
131       }
132       let methodToUse = this.methodForType[typeof value];
133       try {
134         Services.prefs[methodToUse](pref, value);
135         return Promise.resolve(value);
136       } catch (ex) {
137         Cu.reportError(ex);
138         return Promise.reject(ex.message);
139       }
140     },
142     reset(pref) {
143       let error = maybeReturnErrorForReset(pref);
144       if (error) {
145         return Promise.reject(error);
146       }
148       try {
149         Services.prefs.clearUserPref(pref);
150         return Promise.resolve();
151       } catch (ex) {
152         Cu.reportError(ex);
153         return Promise.reject(ex.message);
154       }
155     },
157     receiveMessage(msg) {
158       if (msg.name == "AsyncPrefs:SetPref") {
159         this.onPrefSet(msg);
160       } else {
161         this.onPrefReset(msg);
162       }
163     },
165     onPrefReset(msg) {
166       let { pref, msgId } = msg.data;
167       this.reset(pref).then(
168         function() {
169           msg.target.sendAsyncMessage("AsyncPrefs:PrefResetFinished", {
170             msgId,
171             success: true,
172           });
173         },
174         function(msg) {
175           msg.target.sendAsyncMessage("AsyncPrefs:PrefResetFinished", {
176             msgId,
177             success: false,
178             message: msg,
179           });
180         }
181       );
182     },
184     onPrefSet(msg) {
185       let { pref, value, msgId } = msg.data;
186       this.set(pref, value).then(
187         function() {
188           msg.target.sendAsyncMessage("AsyncPrefs:PrefSetFinished", {
189             msgId,
190             success: true,
191           });
192         },
193         function(msg) {
194           msg.target.sendAsyncMessage("AsyncPrefs:PrefSetFinished", {
195             msgId,
196             success: false,
197             message: msg,
198           });
199         }
200       );
201     },
203     init() {
204       // PLEASE KEEP THIS LIST IN SYNC WITH THE LISTENERS ADDED IN nsBrowserGlue
205       Services.ppmm.addMessageListener("AsyncPrefs:SetPref", this);
206       Services.ppmm.addMessageListener("AsyncPrefs:ResetPref", this);
207       // PLEASE KEEP THIS LIST IN SYNC WITH THE LISTENERS ADDED IN nsBrowserGlue
208     },
209   };