summaryrefslogtreecommitdiffstats
path: root/devtools/client/aboutdebugging/src/modules/runtime-default-preferences.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/aboutdebugging/src/modules/runtime-default-preferences.js')
-rw-r--r--devtools/client/aboutdebugging/src/modules/runtime-default-preferences.js101
1 files changed, 101 insertions, 0 deletions
diff --git a/devtools/client/aboutdebugging/src/modules/runtime-default-preferences.js b/devtools/client/aboutdebugging/src/modules/runtime-default-preferences.js
new file mode 100644
index 0000000000..02c06334f7
--- /dev/null
+++ b/devtools/client/aboutdebugging/src/modules/runtime-default-preferences.js
@@ -0,0 +1,101 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+/**
+ * This module provides a workaround for remote debugging when a preference is
+ * defined in the firefox preference file (browser/app/profile/firefox.js) but
+ * still read from the server, without any default value.
+ *
+ * This causes the server to crash and can't easily be recovered.
+ *
+ * While we work on better linting to prevent such issues (Bug 1660182), this
+ * module will be able to set default values for all missing preferences.
+ */
+
+const PREFERENCE_TYPES = {
+ BOOL: "BOOL",
+ CHAR: "CHAR",
+ INT: "INT",
+};
+exports.PREFERENCE_TYPES = PREFERENCE_TYPES;
+
+/**
+ * Expected properties for the preference descriptors:
+ * - prefName {String}: the name of the preference.
+ * - defaultValue {String|Bool|Number}: the value to set if the preference is
+ * missing.
+ * - trait {String}: the name of the trait corresponding to this pref on the
+ * PreferenceFront.
+ * - type {String}: the preference type (either BOOL, CHAR or INT).
+ */
+const DEFAULT_PREFERENCES = [];
+exports.DEFAULT_PREFERENCES = DEFAULT_PREFERENCES;
+
+const METHODS = {
+ [PREFERENCE_TYPES.BOOL]: {
+ setPref: "setBoolPref",
+ getPref: "getBoolPref",
+ },
+ [PREFERENCE_TYPES.CHAR]: {
+ setPref: "setCharPref",
+ getPref: "getCharPref",
+ },
+ [PREFERENCE_TYPES.INT]: {
+ setPref: "setIntPref",
+ getPref: "getIntPref",
+ },
+};
+
+/**
+ * Set default values for all the provided preferences on the runtime
+ * corresponding to the provided clientWrapper, if needed.
+ *
+ * Note: prefDescriptors will most likely be DEFAULT_PREFERENCES when
+ * used in production code, but can be parameterized for tests.
+ *
+ * @param {ClientWrapper} clientWrapper
+ * @param {Array} prefDescriptors
+ * Array of preference descriptors, see DEFAULT_PREFERENCES.
+ */
+async function setDefaultPreferencesIfNeeded(clientWrapper, prefDescriptors) {
+ if (!prefDescriptors || prefDescriptors.length === 0) {
+ return;
+ }
+
+ const preferenceFront = await clientWrapper.getFront("preference");
+ const preferenceTraits = await preferenceFront.getTraits();
+
+ // Note: using Promise.all here fails because the request/responses get mixed.
+ for (const prefDescriptor of prefDescriptors) {
+ // If the fix for this preference is already on this server, skip it.
+ if (preferenceTraits[prefDescriptor.trait]) {
+ continue;
+ }
+
+ await setDefaultPreference(preferenceFront, prefDescriptor);
+ }
+}
+exports.setDefaultPreferencesIfNeeded = setDefaultPreferencesIfNeeded;
+
+async function setDefaultPreference(preferenceFront, prefDescriptor) {
+ const { prefName, type, defaultValue } = prefDescriptor;
+
+ if (!Object.values(PREFERENCE_TYPES).includes(type)) {
+ throw new Error(`Unsupported type for setDefaultPreference "${type}"`);
+ }
+
+ const prefMethods = METHODS[type];
+ try {
+ // Try to read the preference only to check if the call is successful.
+ // If not, this means the preference is missing and should be initialized.
+ await preferenceFront[prefMethods.getPref](prefName);
+ } catch (e) {
+ console.warn(
+ `Preference "${prefName}"" is not set on the remote runtime. Setting default value.`
+ );
+ await preferenceFront[prefMethods.setPref](prefName, defaultValue);
+ }
+}