michael@0: /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / michael@0: /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: "use strict;" michael@0: michael@0: const Cc = Components.classes; michael@0: const Ci = Components.interfaces; michael@0: const Cu = Components.utils; michael@0: const Cr = Components.results; michael@0: michael@0: Cu.import('resource://gre/modules/XPCOMUtils.jsm'); michael@0: Cu.import('resource://gre/modules/Services.jsm'); michael@0: michael@0: #ifdef MOZ_WIDGET_GONK michael@0: XPCOMUtils.defineLazyGetter(this, "libcutils", function () { michael@0: Cu.import("resource://gre/modules/systemlibs.js"); michael@0: return libcutils; michael@0: }); michael@0: #endif michael@0: michael@0: XPCOMUtils.defineLazyServiceGetter(this, "uuidgen", michael@0: "@mozilla.org/uuid-generator;1", michael@0: "nsIUUIDGenerator"); michael@0: michael@0: // Once Bug 731746 - Allow chrome JS object to implement nsIDOMEventTarget michael@0: // is resolved this helper could be removed. michael@0: var SettingsListener = { michael@0: _callbacks: {}, michael@0: michael@0: init: function sl_init() { michael@0: if ('mozSettings' in navigator && navigator.mozSettings) { michael@0: navigator.mozSettings.onsettingchange = this.onchange.bind(this); michael@0: } michael@0: }, michael@0: michael@0: onchange: function sl_onchange(evt) { michael@0: var callback = this._callbacks[evt.settingName]; michael@0: if (callback) { michael@0: callback(evt.settingValue); michael@0: } michael@0: }, michael@0: michael@0: observe: function sl_observe(name, defaultValue, callback) { michael@0: var settings = window.navigator.mozSettings; michael@0: if (!settings) { michael@0: window.setTimeout(function() { callback(defaultValue); }); michael@0: return; michael@0: } michael@0: michael@0: if (!callback || typeof callback !== 'function') { michael@0: throw new Error('Callback is not a function'); michael@0: } michael@0: michael@0: var req = settings.createLock().get(name); michael@0: req.addEventListener('success', (function onsuccess() { michael@0: callback(typeof(req.result[name]) != 'undefined' ? michael@0: req.result[name] : defaultValue); michael@0: })); michael@0: michael@0: this._callbacks[name] = callback; michael@0: } michael@0: }; michael@0: michael@0: SettingsListener.init(); michael@0: michael@0: // =================== Console ====================== michael@0: michael@0: SettingsListener.observe('debug.console.enabled', true, function(value) { michael@0: Services.prefs.setBoolPref('consoleservice.enabled', value); michael@0: Services.prefs.setBoolPref('layout.css.report_errors', value); michael@0: }); michael@0: michael@0: // =================== Languages ==================== michael@0: SettingsListener.observe('language.current', 'en-US', function(value) { michael@0: Services.prefs.setCharPref('general.useragent.locale', value); michael@0: michael@0: let prefName = 'intl.accept_languages'; michael@0: if (Services.prefs.prefHasUserValue(prefName)) { michael@0: Services.prefs.clearUserPref(prefName); michael@0: } michael@0: michael@0: let intl = ''; michael@0: try { michael@0: intl = Services.prefs.getComplexValue(prefName, michael@0: Ci.nsIPrefLocalizedString).data; michael@0: } catch(e) {} michael@0: michael@0: // Bug 830782 - Homescreen is in English instead of selected locale after michael@0: // the first run experience. michael@0: // In order to ensure the current intl value is reflected on the child michael@0: // process let's always write a user value, even if this one match the michael@0: // current localized pref value. michael@0: if (!((new RegExp('^' + value + '[^a-z-_] *[,;]?', 'i')).test(intl))) { michael@0: value = value + ', ' + intl; michael@0: } else { michael@0: value = intl; michael@0: } michael@0: Services.prefs.setCharPref(prefName, value); michael@0: michael@0: if (shell.hasStarted() == false) { michael@0: shell.start(); michael@0: } michael@0: }); michael@0: michael@0: // =================== RIL ==================== michael@0: (function RILSettingsToPrefs() { michael@0: let strPrefs = ['ril.mms.mmsc', 'ril.mms.mmsproxy']; michael@0: strPrefs.forEach(function(key) { michael@0: SettingsListener.observe(key, "", function(value) { michael@0: Services.prefs.setCharPref(key, value); michael@0: }); michael@0: }); michael@0: michael@0: ['ril.mms.mmsport'].forEach(function(key) { michael@0: SettingsListener.observe(key, null, function(value) { michael@0: if (value != null) { michael@0: Services.prefs.setIntPref(key, value); michael@0: } michael@0: }); michael@0: }); michael@0: michael@0: // DSDS default service IDs michael@0: ['mms', 'sms', 'telephony', 'voicemail'].forEach(function(key) { michael@0: SettingsListener.observe('ril.' + key + '.defaultServiceId', 0, michael@0: function(value) { michael@0: if (value != null) { michael@0: Services.prefs.setIntPref('dom.' + key + '.defaultServiceId', value); michael@0: } michael@0: }); michael@0: }); michael@0: })(); michael@0: michael@0: //=================== DeviceInfo ==================== michael@0: Components.utils.import('resource://gre/modules/XPCOMUtils.jsm'); michael@0: Components.utils.import('resource://gre/modules/ctypes.jsm'); michael@0: (function DeviceInfoToSettings() { michael@0: // MOZ_B2G_VERSION is set in b2g/confvars.sh, and is output as a #define value michael@0: // from configure.in, defaults to 1.0.0 if this value is not exist. michael@0: #filter attemptSubstitution michael@0: let os_version = '@MOZ_B2G_VERSION@'; michael@0: let os_name = '@MOZ_B2G_OS_NAME@'; michael@0: #unfilter attemptSubstitution michael@0: michael@0: let appInfo = Cc["@mozilla.org/xre/app-info;1"] michael@0: .getService(Ci.nsIXULAppInfo); michael@0: michael@0: // Get the hardware info and firmware revision from device properties. michael@0: let hardware_info = null; michael@0: let firmware_revision = null; michael@0: let product_model = null; michael@0: #ifdef MOZ_WIDGET_GONK michael@0: hardware_info = libcutils.property_get('ro.hardware'); michael@0: firmware_revision = libcutils.property_get('ro.firmware_revision'); michael@0: product_model = libcutils.property_get('ro.product.model'); michael@0: #endif michael@0: michael@0: let software = os_name + ' ' + os_version; michael@0: let setting = { michael@0: 'deviceinfo.os': os_version, michael@0: 'deviceinfo.software': software, michael@0: 'deviceinfo.platform_version': appInfo.platformVersion, michael@0: 'deviceinfo.platform_build_id': appInfo.platformBuildID, michael@0: 'deviceinfo.hardware': hardware_info, michael@0: 'deviceinfo.firmware_revision': firmware_revision, michael@0: 'deviceinfo.product_model': product_model michael@0: } michael@0: window.navigator.mozSettings.createLock().set(setting); michael@0: })(); michael@0: michael@0: // =================== DevTools ==================== michael@0: michael@0: let developerHUD; michael@0: SettingsListener.observe('devtools.overlay', false, (value) => { michael@0: if (value) { michael@0: if (!developerHUD) { michael@0: let scope = {}; michael@0: Services.scriptloader.loadSubScript('chrome://b2g/content/devtools.js', scope); michael@0: developerHUD = scope.developerHUD; michael@0: } michael@0: developerHUD.init(); michael@0: } else { michael@0: if (developerHUD) { michael@0: developerHUD.uninit(); michael@0: } michael@0: } michael@0: }); michael@0: michael@0: // =================== Debugger / ADB ==================== michael@0: michael@0: #ifdef MOZ_WIDGET_GONK michael@0: let AdbController = { michael@0: DEBUG: false, michael@0: locked: undefined, michael@0: remoteDebuggerEnabled: undefined, michael@0: lockEnabled: undefined, michael@0: disableAdbTimer: null, michael@0: disableAdbTimeoutHours: 12, michael@0: umsActive: false, michael@0: michael@0: debug: function(str) { michael@0: dump("AdbController: " + str + "\n"); michael@0: }, michael@0: michael@0: setLockscreenEnabled: function(value) { michael@0: this.lockEnabled = value; michael@0: if (this.DEBUG) { michael@0: this.debug("setLockscreenEnabled = " + this.lockEnabled); michael@0: } michael@0: this.updateState(); michael@0: }, michael@0: michael@0: setLockscreenState: function(value) { michael@0: this.locked = value; michael@0: if (this.DEBUG) { michael@0: this.debug("setLockscreenState = " + this.locked); michael@0: } michael@0: this.updateState(); michael@0: }, michael@0: michael@0: setRemoteDebuggerState: function(value) { michael@0: this.remoteDebuggerEnabled = value; michael@0: if (this.DEBUG) { michael@0: this.debug("setRemoteDebuggerState = " + this.remoteDebuggerEnabled); michael@0: } michael@0: this.updateState(); michael@0: }, michael@0: michael@0: startDisableAdbTimer: function() { michael@0: if (this.disableAdbTimer) { michael@0: this.disableAdbTimer.cancel(); michael@0: } else { michael@0: this.disableAdbTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); michael@0: try { michael@0: this.disableAdbTimeoutHours = michael@0: Services.prefs.getIntPref("b2g.adb.timeout-hours"); michael@0: } catch (e) { michael@0: // This happens if the pref doesn't exist, in which case michael@0: // disableAdbTimeoutHours will still be set to the default. michael@0: } michael@0: } michael@0: if (this.disableAdbTimeoutHours <= 0) { michael@0: if (this.DEBUG) { michael@0: this.debug("Timer to disable ADB not started due to zero timeout"); michael@0: } michael@0: return; michael@0: } michael@0: michael@0: if (this.DEBUG) { michael@0: this.debug("Starting timer to disable ADB in " + michael@0: this.disableAdbTimeoutHours + " hours"); michael@0: } michael@0: let timeoutMilliseconds = this.disableAdbTimeoutHours * 60 * 60 * 1000; michael@0: this.disableAdbTimer.initWithCallback(this, timeoutMilliseconds, michael@0: Ci.nsITimer.TYPE_ONE_SHOT); michael@0: }, michael@0: michael@0: stopDisableAdbTimer: function() { michael@0: if (this.DEBUG) { michael@0: this.debug("Stopping timer to disable ADB"); michael@0: } michael@0: if (this.disableAdbTimer) { michael@0: this.disableAdbTimer.cancel(); michael@0: this.disableAdbTimer = null; michael@0: } michael@0: }, michael@0: michael@0: notify: function(aTimer) { michael@0: if (aTimer == this.disableAdbTimer) { michael@0: this.disableAdbTimer = null; michael@0: // The following dump will be the last thing that shows up in logcat, michael@0: // and will at least give the user a clue about why logcat was michael@0: // disconnected, if the user happens to be using logcat. michael@0: dump("AdbController: ADB timer expired - disabling ADB\n"); michael@0: navigator.mozSettings.createLock().set( michael@0: {'devtools.debugger.remote-enabled': false}); michael@0: } michael@0: }, michael@0: michael@0: updateState: function() { michael@0: this.umsActive = false; michael@0: this.storages = navigator.getDeviceStorages('sdcard'); michael@0: this.updateStorageState(0); michael@0: }, michael@0: michael@0: updateStorageState: function(storageIndex) { michael@0: if (storageIndex >= this.storages.length) { michael@0: // We've iterated through all of the storage objects, now we can michael@0: // really do updateStateInternal. michael@0: this.updateStateInternal(); michael@0: return; michael@0: } michael@0: let storage = this.storages[storageIndex]; michael@0: if (this.DEBUG) { michael@0: this.debug("Checking availability of storage: '" + michael@0: storage.storageName); michael@0: } michael@0: michael@0: let req = storage.available(); michael@0: req.onsuccess = function(e) { michael@0: if (this.DEBUG) { michael@0: this.debug("Storage: '" + storage.storageName + "' is '" + michael@0: e.target.result); michael@0: } michael@0: if (e.target.result == 'shared') { michael@0: // We've found a storage area that's being shared with the PC. michael@0: // We can stop looking now. michael@0: this.umsActive = true; michael@0: this.updateStateInternal(); michael@0: return; michael@0: } michael@0: this.updateStorageState(storageIndex + 1); michael@0: }.bind(this); michael@0: req.onerror = function(e) { michael@0: dump("AdbController: error querying storage availability for '" + michael@0: this.storages[storageIndex].storageName + "' (ignoring)\n"); michael@0: this.updateStorageState(storageIndex + 1); michael@0: }.bind(this); michael@0: }, michael@0: michael@0: updateStateInternal: function() { michael@0: if (this.DEBUG) { michael@0: this.debug("updateStateInternal: called"); michael@0: } michael@0: michael@0: if (this.remoteDebuggerEnabled === undefined || michael@0: this.lockEnabled === undefined || michael@0: this.locked === undefined) { michael@0: // Part of initializing the settings database will cause the observers michael@0: // to trigger. We want to wait until both have been initialized before michael@0: // we start changing ther adb state. Without this then we can wind up michael@0: // toggling adb off and back on again (or on and back off again). michael@0: // michael@0: // For completeness, one scenario which toggles adb is using the unagi. michael@0: // The unagi has adb enabled by default (prior to b2g starting). If you michael@0: // have the phone lock disabled and remote debugging enabled, then we'll michael@0: // receive an unlock event and an rde event. However at the time we michael@0: // receive the unlock event we haven't yet received the rde event, so michael@0: // we turn adb off momentarily, which disconnects a logcat that might michael@0: // be running. Changing the defaults (in AdbController) just moves the michael@0: // problem to a different phone, which has adb disabled by default and michael@0: // we wind up turning on adb for a short period when we shouldn't. michael@0: // michael@0: // By waiting until both values are properly initialized, we avoid michael@0: // turning adb on or off accidentally. michael@0: if (this.DEBUG) { michael@0: this.debug("updateState: Waiting for all vars to be initialized"); michael@0: } michael@0: return; michael@0: } michael@0: michael@0: // Check if we have a remote debugging session going on. If so, we won't michael@0: // disable adb even if the screen is locked. michael@0: let isDebugging = RemoteDebugger.isDebugging; michael@0: if (this.DEBUG) { michael@0: this.debug("isDebugging=" + isDebugging); michael@0: } michael@0: michael@0: // If USB Mass Storage, USB tethering, or a debug session is active, michael@0: // then we don't want to disable adb in an automatic fashion (i.e. michael@0: // when the screen locks or due to timeout). michael@0: let sysUsbConfig = libcutils.property_get("sys.usb.config"); michael@0: let rndisActive = (sysUsbConfig.split(",").indexOf("rndis") >= 0); michael@0: let usbFuncActive = rndisActive || this.umsActive || isDebugging; michael@0: michael@0: let enableAdb = this.remoteDebuggerEnabled && michael@0: (!(this.lockEnabled && this.locked) || usbFuncActive); michael@0: michael@0: let useDisableAdbTimer = true; michael@0: try { michael@0: if (Services.prefs.getBoolPref("marionette.defaultPrefs.enabled")) { michael@0: // Marionette is enabled. Marionette requires that adb be on (and also michael@0: // requires that remote debugging be off). The fact that marionette michael@0: // is enabled also implies that we're doing a non-production build, so michael@0: // we want adb enabled all of the time. michael@0: enableAdb = true; michael@0: useDisableAdbTimer = false; michael@0: } michael@0: } catch (e) { michael@0: // This means that the pref doesn't exist. Which is fine. We just leave michael@0: // enableAdb alone. michael@0: } michael@0: if (this.DEBUG) { michael@0: this.debug("updateState: enableAdb = " + enableAdb + michael@0: " remoteDebuggerEnabled = " + this.remoteDebuggerEnabled + michael@0: " lockEnabled = " + this.lockEnabled + michael@0: " locked = " + this.locked + michael@0: " usbFuncActive = " + usbFuncActive); michael@0: } michael@0: michael@0: // Configure adb. michael@0: let currentConfig = libcutils.property_get("persist.sys.usb.config"); michael@0: let configFuncs = currentConfig.split(","); michael@0: let adbIndex = configFuncs.indexOf("adb"); michael@0: michael@0: if (enableAdb) { michael@0: // Add adb to the list of functions, if not already present michael@0: if (adbIndex < 0) { michael@0: configFuncs.push("adb"); michael@0: } michael@0: } else { michael@0: // Remove adb from the list of functions, if present michael@0: if (adbIndex >= 0) { michael@0: configFuncs.splice(adbIndex, 1); michael@0: } michael@0: } michael@0: let newConfig = configFuncs.join(","); michael@0: if (newConfig != currentConfig) { michael@0: if (this.DEBUG) { michael@0: this.debug("updateState: currentConfig = " + currentConfig); michael@0: this.debug("updateState: newConfig = " + newConfig); michael@0: } michael@0: try { michael@0: libcutils.property_set("persist.sys.usb.config", newConfig); michael@0: } catch(e) { michael@0: dump("Error configuring adb: " + e); michael@0: } michael@0: } michael@0: if (useDisableAdbTimer) { michael@0: if (enableAdb && !usbFuncActive) { michael@0: this.startDisableAdbTimer(); michael@0: } else { michael@0: this.stopDisableAdbTimer(); michael@0: } michael@0: } michael@0: } michael@0: }; michael@0: michael@0: SettingsListener.observe("lockscreen.locked", false, michael@0: AdbController.setLockscreenState.bind(AdbController)); michael@0: SettingsListener.observe("lockscreen.enabled", false, michael@0: AdbController.setLockscreenEnabled.bind(AdbController)); michael@0: #endif michael@0: michael@0: // Keep the old setting to not break people that won't have updated michael@0: // gaia and gecko. michael@0: SettingsListener.observe('devtools.debugger.remote-enabled', false, function(value) { michael@0: Services.prefs.setBoolPref('devtools.debugger.remote-enabled', value); michael@0: // This preference is consulted during startup michael@0: Services.prefs.savePrefFile(null); michael@0: try { michael@0: value ? RemoteDebugger.start() : RemoteDebugger.stop(); michael@0: } catch(e) { michael@0: dump("Error while initializing devtools: " + e + "\n" + e.stack + "\n"); michael@0: } michael@0: michael@0: #ifdef MOZ_WIDGET_GONK michael@0: AdbController.setRemoteDebuggerState(value); michael@0: #endif michael@0: }); michael@0: michael@0: SettingsListener.observe('debugger.remote-mode', false, function(value) { michael@0: if (['disabled', 'adb-only', 'adb-devtools'].indexOf(value) == -1) { michael@0: dump('Illegal value for debugger.remote-mode: ' + value + '\n'); michael@0: return; michael@0: } michael@0: michael@0: Services.prefs.setBoolPref('devtools.debugger.remote-enabled', michael@0: value == 'adb-devtools'); michael@0: // This preference is consulted during startup michael@0: Services.prefs.savePrefFile(null); michael@0: michael@0: try { michael@0: (value == 'adb-devtools') ? RemoteDebugger.start() michael@0: : RemoteDebugger.stop(); michael@0: } catch(e) { michael@0: dump("Error while initializing devtools: " + e + "\n" + e.stack + "\n"); michael@0: } michael@0: michael@0: #ifdef MOZ_WIDGET_GONK michael@0: AdbController.setRemoteDebuggerState(value != 'disabled'); michael@0: #endif michael@0: }); michael@0: michael@0: // =================== Device Storage ==================== michael@0: SettingsListener.observe('device.storage.writable.name', 'sdcard', function(value) { michael@0: if (Services.prefs.getPrefType('device.storage.writable.name') != Ci.nsIPrefBranch.PREF_STRING) { michael@0: // We clear the pref because it used to be erroneously written as a bool michael@0: // and we need to clear it before we can change it to have the correct type. michael@0: Services.prefs.clearUserPref('device.storage.writable.name'); michael@0: } michael@0: Services.prefs.setCharPref('device.storage.writable.name', value); michael@0: }); michael@0: michael@0: // =================== Privacy ==================== michael@0: SettingsListener.observe('privacy.donottrackheader.value', 1, function(value) { michael@0: Services.prefs.setIntPref('privacy.donottrackheader.value', value); michael@0: // If the user specifically disallows tracking, we set the value of michael@0: // app.update.custom (update tracking ID) to an empty string. michael@0: if (value == 1) { michael@0: Services.prefs.setCharPref('app.update.custom', ''); michael@0: return; michael@0: } michael@0: // Otherwise, we assure that the update tracking ID exists. michael@0: setUpdateTrackingId(); michael@0: }); michael@0: michael@0: // =================== Crash Reporting ==================== michael@0: SettingsListener.observe('app.reportCrashes', 'ask', function(value) { michael@0: if (value == 'always') { michael@0: Services.prefs.setBoolPref('app.reportCrashes', true); michael@0: } else if (value == 'never') { michael@0: Services.prefs.setBoolPref('app.reportCrashes', false); michael@0: } else { michael@0: Services.prefs.clearUserPref('app.reportCrashes'); michael@0: } michael@0: // This preference is consulted during startup. michael@0: Services.prefs.savePrefFile(null); michael@0: }); michael@0: michael@0: // ================ Updates ================ michael@0: /** michael@0: * For tracking purposes some partners require us to add an UUID to the michael@0: * update URL. The update tracking ID will be an empty string if the michael@0: * do-not-track feature specifically disallows tracking and it is reseted michael@0: * to a different ID if the do-not-track value changes from disallow to allow. michael@0: */ michael@0: function setUpdateTrackingId() { michael@0: try { michael@0: let dntEnabled = Services.prefs.getBoolPref('privacy.donottrackheader.enabled'); michael@0: let dntValue = Services.prefs.getIntPref('privacy.donottrackheader.value'); michael@0: // If the user specifically decides to disallow tracking (1), we just bail out. michael@0: if (dntEnabled && (dntValue == 1)) { michael@0: return; michael@0: } michael@0: michael@0: let trackingId = michael@0: Services.prefs.getPrefType('app.update.custom') == michael@0: Ci.nsIPrefBranch.PREF_STRING && michael@0: Services.prefs.getCharPref('app.update.custom'); michael@0: michael@0: // If there is no previous registered tracking ID, we generate a new one. michael@0: // This should only happen on first usage or after changing the michael@0: // do-not-track value from disallow to allow. michael@0: if (!trackingId) { michael@0: trackingId = uuidgen.generateUUID().toString().replace(/[{}]/g, ""); michael@0: Services.prefs.setCharPref('app.update.custom', trackingId); michael@0: } michael@0: } catch(e) { michael@0: dump('Error getting tracking ID ' + e + '\n'); michael@0: } michael@0: } michael@0: setUpdateTrackingId(); michael@0: michael@0: michael@0: // ================ Debug ================ michael@0: (function Composer2DSettingToPref() { michael@0: //layers.composer.enabled can be enabled in three ways michael@0: //In order of precedence they are: michael@0: // michael@0: //1. mozSettings "layers.composer.enabled" michael@0: //2. a gecko pref "layers.composer.enabled" michael@0: //3. presence of ro.display.colorfill at the Gonk level michael@0: michael@0: var req = navigator.mozSettings.createLock().get('layers.composer2d.enabled'); michael@0: req.onsuccess = function() { michael@0: if (typeof(req.result['layers.composer2d.enabled']) === 'undefined') { michael@0: var enabled = false; michael@0: if (Services.prefs.getPrefType('layers.composer2d.enabled') == Ci.nsIPrefBranch.PREF_BOOL) { michael@0: enabled = Services.prefs.getBoolPref('layers.composer2d.enabled'); michael@0: } else { michael@0: #ifdef MOZ_WIDGET_GONK michael@0: enabled = (libcutils.property_get('ro.display.colorfill') === '1'); michael@0: #endif michael@0: } michael@0: navigator.mozSettings.createLock().set({'layers.composer2d.enabled': enabled }); michael@0: } michael@0: michael@0: SettingsListener.observe("layers.composer2d.enabled", true, function(value) { michael@0: Services.prefs.setBoolPref("layers.composer2d.enabled", value); michael@0: }); michael@0: }; michael@0: req.onerror = function() { michael@0: dump("Error configuring layers.composer2d.enabled setting"); michael@0: }; michael@0: michael@0: })(); michael@0: michael@0: // ================ Accessibility ============ michael@0: SettingsListener.observe("accessibility.screenreader", false, function(value) { michael@0: if (value && !("AccessFu" in this)) { michael@0: Cu.import('resource://gre/modules/accessibility/AccessFu.jsm'); michael@0: AccessFu.attach(window); michael@0: } michael@0: }); michael@0: michael@0: // ================ Theming ============ michael@0: (function themingSettingsListener() { michael@0: let themingPrefs = ['ui.menu', 'ui.menutext', 'ui.infobackground', 'ui.infotext', michael@0: 'ui.window', 'ui.windowtext', 'ui.highlight']; michael@0: michael@0: themingPrefs.forEach(function(pref) { michael@0: SettingsListener.observe('gaia.' + pref, null, function(value) { michael@0: if (value) { michael@0: Services.prefs.setCharPref(pref, value); michael@0: } michael@0: }); michael@0: }); michael@0: })(); michael@0: michael@0: // =================== AsyncPanZoom ====================== michael@0: SettingsListener.observe('apz.displayport.heuristics', 'default', function(value) { michael@0: // first reset everything to default michael@0: Services.prefs.clearUserPref('apz.velocity_bias'); michael@0: Services.prefs.clearUserPref('apz.use_paint_duration'); michael@0: Services.prefs.clearUserPref('apz.x_skate_size_multiplier'); michael@0: Services.prefs.clearUserPref('apz.y_skate_size_multiplier'); michael@0: Services.prefs.clearUserPref('apz.allow-checkerboarding'); michael@0: // and then set the things that we want to change michael@0: switch (value) { michael@0: case 'default': michael@0: break; michael@0: case 'center-displayport': michael@0: Services.prefs.setCharPref('apz.velocity_bias', '0.0'); michael@0: break; michael@0: case 'perfect-paint-times': michael@0: Services.prefs.setBoolPref('apz.use_paint_duration', false); michael@0: Services.prefs.setCharPref('apz.velocity_bias', '0.32'); // 16/50 (assumes 16ms paint times instead of 50ms) michael@0: break; michael@0: case 'taller-displayport': michael@0: Services.prefs.setCharPref('apz.y_skate_size_multiplier', '3.5'); michael@0: break; michael@0: case 'faster-paint': michael@0: Services.prefs.setCharPref('apz.x_skate_size_multiplier', '1.0'); michael@0: Services.prefs.setCharPref('apz.y_skate_size_multiplier', '1.5'); michael@0: break; michael@0: case 'no-checkerboard': michael@0: Services.prefs.setBoolPref('apz.allow-checkerboarding', false); michael@0: break; michael@0: } michael@0: }); michael@0: michael@0: // =================== Various simple mapping ====================== michael@0: let settingsToObserve = { michael@0: 'ril.mms.retrieval_mode': { michael@0: prefName: 'dom.mms.retrieval_mode', michael@0: defaultValue: 'manual' michael@0: }, michael@0: 'ril.sms.strict7BitEncoding.enabled': { michael@0: prefName: 'dom.sms.strict7BitEncoding', michael@0: defaultValue: false michael@0: }, michael@0: 'ril.sms.requestStatusReport.enabled': { michael@0: prefName: 'dom.sms.requestStatusReport', michael@0: defaultValue: false michael@0: }, michael@0: 'ril.mms.requestStatusReport.enabled': { michael@0: prefName: 'dom.mms.requestStatusReport', michael@0: defaultValue: false michael@0: }, michael@0: 'ril.mms.requestReadReport.enabled': { michael@0: prefName: 'dom.mms.requestReadReport', michael@0: defaultValue: true michael@0: }, michael@0: 'ril.cellbroadcast.disabled': false, michael@0: 'ril.radio.disabled': false, michael@0: 'wap.UAProf.url': '', michael@0: 'wap.UAProf.tagname': 'x-wap-profile', michael@0: 'devtools.eventlooplag.threshold': 100, michael@0: 'privacy.donottrackheader.enabled': false, michael@0: 'apz.force-enable': { michael@0: prefName: 'dom.browser_frames.useAsyncPanZoom', michael@0: defaultValue: false michael@0: }, michael@0: 'layers.enable-tiles': true, michael@0: 'layers.simple-tiles': false, michael@0: 'layers.progressive-paint': false, michael@0: 'layers.draw-tile-borders': false, michael@0: 'layers.dump': false, michael@0: 'debug.fps.enabled': { michael@0: prefName: 'layers.acceleration.draw-fps', michael@0: defaultValue: false michael@0: }, michael@0: 'debug.paint-flashing.enabled': { michael@0: prefName: 'nglayout.debug.paint_flashing', michael@0: defaultValue: false michael@0: }, michael@0: 'layers.draw-borders': false, michael@0: 'app.update.interval': 86400, michael@0: 'app.update.url': { michael@0: resetToPref: true michael@0: }, michael@0: 'app.update.channel': { michael@0: resetToPref: true michael@0: }, michael@0: 'debug.log-animations.enabled': { michael@0: prefName: 'layers.offmainthreadcomposition.log-animations', michael@0: defaultValue: false michael@0: } michael@0: }; michael@0: michael@0: for (let key in settingsToObserve) { michael@0: let setting = settingsToObserve[key]; michael@0: michael@0: // Allow setting to contain flags redefining prefName and defaultValue. michael@0: let prefName = setting.prefName || key; michael@0: let defaultValue = setting.defaultValue; michael@0: if (defaultValue === undefined) { michael@0: defaultValue = setting; michael@0: } michael@0: michael@0: let prefs = Services.prefs; michael@0: michael@0: // If requested, reset setting value and defaultValue to the pref value. michael@0: if (setting.resetToPref) { michael@0: switch (prefs.getPrefType(prefName)) { michael@0: case Ci.nsIPrefBranch.PREF_BOOL: michael@0: defaultValue = prefs.getBoolPref(prefName); michael@0: break; michael@0: michael@0: case Ci.nsIPrefBranch.PREF_INT: michael@0: defaultValue = prefs.getIntPref(prefName); michael@0: break; michael@0: michael@0: case Ci.nsIPrefBranch.PREF_STRING: michael@0: defaultValue = prefs.getCharPref(prefName); michael@0: break; michael@0: } michael@0: michael@0: let setting = {}; michael@0: setting[key] = defaultValue; michael@0: window.navigator.mozSettings.createLock().set(setting); michael@0: } michael@0: michael@0: // Figure out the right setter function for this type of pref. michael@0: let setPref; michael@0: switch (typeof defaultValue) { michael@0: case 'boolean': michael@0: setPref = prefs.setBoolPref.bind(prefs); michael@0: break; michael@0: michael@0: case 'number': michael@0: setPref = prefs.setIntPref.bind(prefs); michael@0: break; michael@0: michael@0: case 'string': michael@0: setPref = prefs.setCharPref.bind(prefs); michael@0: break; michael@0: } michael@0: michael@0: SettingsListener.observe(key, defaultValue, function(value) { michael@0: setPref(prefName, value); michael@0: }); michael@0: }; michael@0: