1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/addon-sdk/source/lib/sdk/preferences/service.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,178 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +"use strict"; 1.9 + 1.10 +module.metadata = { 1.11 + "stability": "unstable" 1.12 +}; 1.13 + 1.14 +// The minimum and maximum integers that can be set as preferences. 1.15 +// The range of valid values is narrower than the range of valid JS values 1.16 +// because the native preferences code treats integers as NSPR PRInt32s, 1.17 +// which are 32-bit signed integers on all platforms. 1.18 +const MAX_INT = 0x7FFFFFFF; 1.19 +const MIN_INT = -0x80000000; 1.20 + 1.21 +const {Cc,Ci,Cr} = require("chrome"); 1.22 + 1.23 +const prefService = Cc["@mozilla.org/preferences-service;1"]. 1.24 + getService(Ci.nsIPrefService); 1.25 +const prefSvc = prefService.getBranch(null); 1.26 +const defaultBranch = prefService.getDefaultBranch(null); 1.27 + 1.28 +function Branch(branchName) { 1.29 + function getPrefKeys() { 1.30 + return keys(branchName).map(function(key) { 1.31 + return key.replace(branchName, ""); 1.32 + }); 1.33 + } 1.34 + 1.35 + return Proxy.create({ 1.36 + get: function(receiver, pref) { 1.37 + return get(branchName + pref); 1.38 + }, 1.39 + set: function(receiver, pref, val) { 1.40 + set(branchName + pref, val); 1.41 + }, 1.42 + delete: function(pref) { 1.43 + reset(branchName + pref); 1.44 + return true; 1.45 + }, 1.46 + has: function hasPrefKey(pref) { 1.47 + return has(branchName + pref) 1.48 + }, 1.49 + getPropertyDescriptor: function(name) { 1.50 + return { 1.51 + value: get(branchName + name) 1.52 + }; 1.53 + }, 1.54 + enumerate: getPrefKeys, 1.55 + keys: getPrefKeys 1.56 + }, Branch.prototype); 1.57 +} 1.58 + 1.59 +function get(name, defaultValue) { 1.60 + switch (prefSvc.getPrefType(name)) { 1.61 + case Ci.nsIPrefBranch.PREF_STRING: 1.62 + return prefSvc.getComplexValue(name, Ci.nsISupportsString).data; 1.63 + 1.64 + case Ci.nsIPrefBranch.PREF_INT: 1.65 + return prefSvc.getIntPref(name); 1.66 + 1.67 + case Ci.nsIPrefBranch.PREF_BOOL: 1.68 + return prefSvc.getBoolPref(name); 1.69 + 1.70 + case Ci.nsIPrefBranch.PREF_INVALID: 1.71 + return defaultValue; 1.72 + 1.73 + default: 1.74 + // This should never happen. 1.75 + throw new Error("Error getting pref " + name + 1.76 + "; its value's type is " + 1.77 + prefSvc.getPrefType(name) + 1.78 + ", which I don't know " + 1.79 + "how to handle."); 1.80 + } 1.81 +} 1.82 +exports.get = get; 1.83 + 1.84 +function set(name, value) { 1.85 + var prefType; 1.86 + if (typeof value != "undefined" && value != null) 1.87 + prefType = value.constructor.name; 1.88 + 1.89 + switch (prefType) { 1.90 + case "String": 1.91 + { 1.92 + var string = Cc["@mozilla.org/supports-string;1"]. 1.93 + createInstance(Ci.nsISupportsString); 1.94 + string.data = value; 1.95 + prefSvc.setComplexValue(name, Ci.nsISupportsString, string); 1.96 + } 1.97 + break; 1.98 + 1.99 + case "Number": 1.100 + // We throw if the number is outside the range or not an integer, since 1.101 + // the result will not be what the consumer wanted to store. 1.102 + if (value > MAX_INT || value < MIN_INT) 1.103 + throw new Error("you cannot set the " + name + 1.104 + " pref to the number " + value + 1.105 + ", as number pref values must be in the signed " + 1.106 + "32-bit integer range -(2^31) to 2^31-1. " + 1.107 + "To store numbers outside that range, store " + 1.108 + "them as strings."); 1.109 + if (value % 1 != 0) 1.110 + throw new Error("cannot store non-integer number: " + value); 1.111 + prefSvc.setIntPref(name, value); 1.112 + break; 1.113 + 1.114 + case "Boolean": 1.115 + prefSvc.setBoolPref(name, value); 1.116 + break; 1.117 + 1.118 + default: 1.119 + throw new Error("can't set pref " + name + " to value '" + value + 1.120 + "'; it isn't a string, integer, or boolean"); 1.121 + } 1.122 +} 1.123 +exports.set = set; 1.124 + 1.125 +function has(name) { 1.126 + return (prefSvc.getPrefType(name) != Ci.nsIPrefBranch.PREF_INVALID); 1.127 +} 1.128 +exports.has = has; 1.129 + 1.130 +function keys(root) { 1.131 + return prefSvc.getChildList(root); 1.132 +} 1.133 +exports.keys = keys; 1.134 + 1.135 +function isSet(name) { 1.136 + return (has(name) && prefSvc.prefHasUserValue(name)); 1.137 +} 1.138 +exports.isSet = isSet; 1.139 + 1.140 +function reset(name) { 1.141 + try { 1.142 + prefSvc.clearUserPref(name); 1.143 + } 1.144 + catch (e) { 1.145 + // The pref service throws NS_ERROR_UNEXPECTED when the caller tries 1.146 + // to reset a pref that doesn't exist or is already set to its default 1.147 + // value. This interface fails silently in those cases, so callers 1.148 + // can unconditionally reset a pref without having to check if it needs 1.149 + // resetting first or trap exceptions after the fact. It passes through 1.150 + // other exceptions, however, so callers know about them, since we don't 1.151 + // know what other exceptions might be thrown and what they might mean. 1.152 + if (e.result != Cr.NS_ERROR_UNEXPECTED) { 1.153 + throw e; 1.154 + } 1.155 + } 1.156 +} 1.157 +exports.reset = reset; 1.158 + 1.159 +function getLocalized(name, defaultValue) { 1.160 + let value = null; 1.161 + try { 1.162 + value = prefSvc.getComplexValue(name, Ci.nsIPrefLocalizedString).data; 1.163 + } 1.164 + finally { 1.165 + return value || defaultValue; 1.166 + } 1.167 +} 1.168 +exports.getLocalized = getLocalized; 1.169 + 1.170 +function setLocalized(name, value) { 1.171 + // We can't use `prefs.set` here as we have to use `getDefaultBranch` 1.172 + // (instead of `getBranch`) in order to have `mIsDefault` set to true, here: 1.173 + // http://mxr.mozilla.org/mozilla-central/source/modules/libpref/src/nsPrefBranch.cpp#233 1.174 + // Otherwise, we do not enter into this expected condition: 1.175 + // http://mxr.mozilla.org/mozilla-central/source/modules/libpref/src/nsPrefBranch.cpp#244 1.176 + defaultBranch.setCharPref(name, value); 1.177 +} 1.178 +exports.setLocalized = setLocalized; 1.179 + 1.180 +exports.Branch = Branch; 1.181 +