summaryrefslogtreecommitdiffstats
path: root/addon-sdk/source/lib/sdk/preferences/service.js
blob: 231cd8e1405327482e7e85c21fd616ec0adaf5bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* 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";

module.metadata = {
  "stability": "unstable"
};

// The minimum and maximum integers that can be set as preferences.
// The range of valid values is narrower than the range of valid JS values
// because the native preferences code treats integers as NSPR PRInt32s,
// which are 32-bit signed integers on all platforms.
const MAX_INT = 0x7FFFFFFF;
const MIN_INT = -0x80000000;

const {Cc,Ci,Cr} = require("chrome");

const prefService = Cc["@mozilla.org/preferences-service;1"].
                getService(Ci.nsIPrefService);
const prefSvc = prefService.getBranch(null);
const defaultBranch = prefService.getDefaultBranch(null);

const { Preferences } = require("resource://gre/modules/Preferences.jsm");
const prefs = new Preferences({});

const branchKeys = branchName =>
  keys(branchName).map($ => $.replace(branchName, ""));

const Branch = function(branchName) {
  return new Proxy(Branch.prototype, {
    getOwnPropertyDescriptor(target, name, receiver) {
      return {
        configurable: true,
        enumerable: true,
        writable: false,
        value: this.get(target, name, receiver)
      };
    },
    ownKeys(target) {
      return branchKeys(branchName);
    },
    get(target, name, receiver) {
      return get(`${branchName}${name}`);
    },
    set(target, name, value, receiver) {
      set(`${branchName}${name}`, value);
      return true;
    },
    has(target, name) {
      return this.hasOwn(target, name);
    },
    hasOwn(target, name) {
      return has(`${branchName}${name}`);
    },
    deleteProperty(target, name) {
      reset(`${branchName}${name}`);
      return true;
    }
  });
}


function get(name, defaultValue) {
  return prefs.get(name, defaultValue);
}
exports.get = get;


function set(name, value) {
  var prefType;
  if (typeof value != "undefined" && value != null)
    prefType = value.constructor.name;

  switch (prefType) {
  case "Number":
    if (value % 1 != 0)
      throw new Error("cannot store non-integer number: " + value);
  }

  prefs.set(name, value);
}
exports.set = set;

const has = prefs.has.bind(prefs)
exports.has = has;

function keys(root) {
  return prefSvc.getChildList(root);
}
exports.keys = keys;

const isSet = prefs.isSet.bind(prefs);
exports.isSet = isSet;

function reset(name) {
  try {
    prefSvc.clearUserPref(name);
  }
  catch (e) {
    // The pref service throws NS_ERROR_UNEXPECTED when the caller tries
    // to reset a pref that doesn't exist or is already set to its default
    // value.  This interface fails silently in those cases, so callers
    // can unconditionally reset a pref without having to check if it needs
    // resetting first or trap exceptions after the fact.  It passes through
    // other exceptions, however, so callers know about them, since we don't
    // know what other exceptions might be thrown and what they might mean.
    if (e.result != Cr.NS_ERROR_UNEXPECTED) {
      throw e;
    }
  }
}
exports.reset = reset;

function getLocalized(name, defaultValue) {
  let value = null;
  try {
    value = prefSvc.getComplexValue(name, Ci.nsIPrefLocalizedString).data;
  }
  finally {
    return value || defaultValue;
  }
}
exports.getLocalized = getLocalized;

function setLocalized(name, value) {
  // We can't use `prefs.set` here as we have to use `getDefaultBranch`
  // (instead of `getBranch`) in order to have `mIsDefault` set to true, here:
  // http://mxr.mozilla.org/mozilla-central/source/modules/libpref/src/nsPrefBranch.cpp#233
  // Otherwise, we do not enter into this expected condition:
  // http://mxr.mozilla.org/mozilla-central/source/modules/libpref/src/nsPrefBranch.cpp#244
  defaultBranch.setCharPref(name, value);
}
exports.setLocalized = setLocalized;

exports.Branch = Branch;