mobile/android/modules/SharedPreferences.jsm

branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
equal deleted inserted replaced
-1:000000000000 0:793998da9e5b
1 // -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 "use strict";
7
8 this.EXPORTED_SYMBOLS = ["SharedPreferences"];
9
10 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
11
12 // For adding observers.
13 Cu.import("resource://gre/modules/Services.jsm");
14 Cu.import("resource://gre/modules/Messaging.jsm");
15
16 /**
17 * Create an interface to an Android SharedPreferences branch.
18 *
19 * branch {String} should be a string describing a preferences branch,
20 * like "UpdateService" or "background.data", or null to access the
21 * default preferences branch for the application.
22 */
23 function SharedPreferences(branch) {
24 if (!(this instanceof SharedPreferences)) {
25 return new SharedPreferences(branch);
26 }
27 this._branch = branch || null;
28 this._observers = {};
29 };
30
31 SharedPreferences.prototype = Object.freeze({
32 _set: function _set(prefs) {
33 sendMessageToJava({
34 type: "SharedPreferences:Set",
35 preferences: prefs,
36 branch: this._branch,
37 });
38 },
39
40 _setOne: function _setOne(prefName, value, type) {
41 let prefs = [];
42 prefs.push({
43 name: prefName,
44 value: value,
45 type: type,
46 });
47 this._set(prefs);
48 },
49
50 setBoolPref: function setBoolPref(prefName, value) {
51 this._setOne(prefName, value, "bool");
52 },
53
54 setCharPref: function setCharPref(prefName, value) {
55 this._setOne(prefName, value, "string");
56 },
57
58 setIntPref: function setIntPref(prefName, value) {
59 this._setOne(prefName, value, "int");
60 },
61
62 _get: function _get(prefs, callback) {
63 let result = null;
64 sendMessageToJava({
65 type: "SharedPreferences:Get",
66 preferences: prefs,
67 branch: this._branch,
68 }, (data) => {
69 result = data.values;
70 });
71
72 let thread = Services.tm.currentThread;
73 while (result == null)
74 thread.processNextEvent(true);
75
76 return result;
77 },
78
79 _getOne: function _getOne(prefName, type) {
80 let prefs = [];
81 prefs.push({
82 name: prefName,
83 type: type,
84 });
85 let values = this._get(prefs);
86 if (values.length != 1) {
87 throw new Error("Got too many values: " + values.length);
88 }
89 return values[0].value;
90 },
91
92 getBoolPref: function getBoolPref(prefName) {
93 return this._getOne(prefName, "bool");
94 },
95
96 getCharPref: function getCharPref(prefName) {
97 return this._getOne(prefName, "string");
98 },
99
100 getIntPref: function getIntPref(prefName) {
101 return this._getOne(prefName, "int");
102 },
103
104 /**
105 * Invoke `observer` after a change to the preference `domain` in
106 * the current branch.
107 *
108 * `observer` should implement the nsIObserver.observe interface.
109 */
110 addObserver: function addObserver(domain, observer, holdWeak) {
111 if (!domain)
112 throw new Error("domain must not be null");
113 if (!observer)
114 throw new Error("observer must not be null");
115 if (holdWeak)
116 throw new Error("Weak references not yet implemented.");
117
118 if (!this._observers.hasOwnProperty(domain))
119 this._observers[domain] = [];
120 if (this._observers[domain].indexOf(observer) > -1)
121 return;
122
123 this._observers[domain].push(observer);
124
125 this._updateAndroidListener();
126 },
127
128 /**
129 * Do not invoke `observer` after a change to the preference
130 * `domain` in the current branch.
131 */
132 removeObserver: function removeObserver(domain, observer) {
133 if (!this._observers.hasOwnProperty(domain))
134 return;
135 let index = this._observers[domain].indexOf(observer);
136 if (index < 0)
137 return;
138
139 this._observers[domain].splice(index, 1);
140 if (this._observers[domain].length < 1)
141 delete this._observers[domain];
142
143 this._updateAndroidListener();
144 },
145
146 _updateAndroidListener: function _updateAndroidListener() {
147 if (this._listening && Object.keys(this._observers).length < 1)
148 this._uninstallAndroidListener();
149 if (!this._listening && Object.keys(this._observers).length > 0)
150 this._installAndroidListener();
151 },
152
153 _installAndroidListener: function _installAndroidListener() {
154 if (this._listening)
155 return;
156 this._listening = true;
157
158 Services.obs.addObserver(this, "SharedPreferences:Changed", false);
159 sendMessageToJava({
160 type: "SharedPreferences:Observe",
161 enable: true,
162 branch: this._branch,
163 });
164 },
165
166 observe: function observe(subject, topic, data) {
167 if (topic != "SharedPreferences:Changed") {
168 return;
169 }
170
171 let msg = JSON.parse(data);
172 if (msg.branch != this._branch) {
173 return;
174 }
175
176 if (!this._observers.hasOwnProperty(msg.key)) {
177 return;
178 }
179
180 let observers = this._observers[msg.key];
181 for (let obs of observers) {
182 obs.observe(obs, msg.key, msg.value);
183 }
184 },
185
186 _uninstallAndroidListener: function _uninstallAndroidListener() {
187 if (!this._listening)
188 return;
189 this._listening = false;
190
191 Services.obs.removeObserver(this, "SharedPreferences:Changed");
192 sendMessageToJava({
193 type: "SharedPreferences:Observe",
194 enable: false,
195 branch: this._branch,
196 });
197 },
198 });

mercurial