1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/modules/SharedPreferences.jsm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,198 @@ 1.4 +// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*- 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.7 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +"use strict"; 1.10 + 1.11 +this.EXPORTED_SYMBOLS = ["SharedPreferences"]; 1.12 + 1.13 +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; 1.14 + 1.15 +// For adding observers. 1.16 +Cu.import("resource://gre/modules/Services.jsm"); 1.17 +Cu.import("resource://gre/modules/Messaging.jsm"); 1.18 + 1.19 +/** 1.20 + * Create an interface to an Android SharedPreferences branch. 1.21 + * 1.22 + * branch {String} should be a string describing a preferences branch, 1.23 + * like "UpdateService" or "background.data", or null to access the 1.24 + * default preferences branch for the application. 1.25 + */ 1.26 +function SharedPreferences(branch) { 1.27 + if (!(this instanceof SharedPreferences)) { 1.28 + return new SharedPreferences(branch); 1.29 + } 1.30 + this._branch = branch || null; 1.31 + this._observers = {}; 1.32 +}; 1.33 + 1.34 +SharedPreferences.prototype = Object.freeze({ 1.35 + _set: function _set(prefs) { 1.36 + sendMessageToJava({ 1.37 + type: "SharedPreferences:Set", 1.38 + preferences: prefs, 1.39 + branch: this._branch, 1.40 + }); 1.41 + }, 1.42 + 1.43 + _setOne: function _setOne(prefName, value, type) { 1.44 + let prefs = []; 1.45 + prefs.push({ 1.46 + name: prefName, 1.47 + value: value, 1.48 + type: type, 1.49 + }); 1.50 + this._set(prefs); 1.51 + }, 1.52 + 1.53 + setBoolPref: function setBoolPref(prefName, value) { 1.54 + this._setOne(prefName, value, "bool"); 1.55 + }, 1.56 + 1.57 + setCharPref: function setCharPref(prefName, value) { 1.58 + this._setOne(prefName, value, "string"); 1.59 + }, 1.60 + 1.61 + setIntPref: function setIntPref(prefName, value) { 1.62 + this._setOne(prefName, value, "int"); 1.63 + }, 1.64 + 1.65 + _get: function _get(prefs, callback) { 1.66 + let result = null; 1.67 + sendMessageToJava({ 1.68 + type: "SharedPreferences:Get", 1.69 + preferences: prefs, 1.70 + branch: this._branch, 1.71 + }, (data) => { 1.72 + result = data.values; 1.73 + }); 1.74 + 1.75 + let thread = Services.tm.currentThread; 1.76 + while (result == null) 1.77 + thread.processNextEvent(true); 1.78 + 1.79 + return result; 1.80 + }, 1.81 + 1.82 + _getOne: function _getOne(prefName, type) { 1.83 + let prefs = []; 1.84 + prefs.push({ 1.85 + name: prefName, 1.86 + type: type, 1.87 + }); 1.88 + let values = this._get(prefs); 1.89 + if (values.length != 1) { 1.90 + throw new Error("Got too many values: " + values.length); 1.91 + } 1.92 + return values[0].value; 1.93 + }, 1.94 + 1.95 + getBoolPref: function getBoolPref(prefName) { 1.96 + return this._getOne(prefName, "bool"); 1.97 + }, 1.98 + 1.99 + getCharPref: function getCharPref(prefName) { 1.100 + return this._getOne(prefName, "string"); 1.101 + }, 1.102 + 1.103 + getIntPref: function getIntPref(prefName) { 1.104 + return this._getOne(prefName, "int"); 1.105 + }, 1.106 + 1.107 + /** 1.108 + * Invoke `observer` after a change to the preference `domain` in 1.109 + * the current branch. 1.110 + * 1.111 + * `observer` should implement the nsIObserver.observe interface. 1.112 + */ 1.113 + addObserver: function addObserver(domain, observer, holdWeak) { 1.114 + if (!domain) 1.115 + throw new Error("domain must not be null"); 1.116 + if (!observer) 1.117 + throw new Error("observer must not be null"); 1.118 + if (holdWeak) 1.119 + throw new Error("Weak references not yet implemented."); 1.120 + 1.121 + if (!this._observers.hasOwnProperty(domain)) 1.122 + this._observers[domain] = []; 1.123 + if (this._observers[domain].indexOf(observer) > -1) 1.124 + return; 1.125 + 1.126 + this._observers[domain].push(observer); 1.127 + 1.128 + this._updateAndroidListener(); 1.129 + }, 1.130 + 1.131 + /** 1.132 + * Do not invoke `observer` after a change to the preference 1.133 + * `domain` in the current branch. 1.134 + */ 1.135 + removeObserver: function removeObserver(domain, observer) { 1.136 + if (!this._observers.hasOwnProperty(domain)) 1.137 + return; 1.138 + let index = this._observers[domain].indexOf(observer); 1.139 + if (index < 0) 1.140 + return; 1.141 + 1.142 + this._observers[domain].splice(index, 1); 1.143 + if (this._observers[domain].length < 1) 1.144 + delete this._observers[domain]; 1.145 + 1.146 + this._updateAndroidListener(); 1.147 + }, 1.148 + 1.149 + _updateAndroidListener: function _updateAndroidListener() { 1.150 + if (this._listening && Object.keys(this._observers).length < 1) 1.151 + this._uninstallAndroidListener(); 1.152 + if (!this._listening && Object.keys(this._observers).length > 0) 1.153 + this._installAndroidListener(); 1.154 + }, 1.155 + 1.156 + _installAndroidListener: function _installAndroidListener() { 1.157 + if (this._listening) 1.158 + return; 1.159 + this._listening = true; 1.160 + 1.161 + Services.obs.addObserver(this, "SharedPreferences:Changed", false); 1.162 + sendMessageToJava({ 1.163 + type: "SharedPreferences:Observe", 1.164 + enable: true, 1.165 + branch: this._branch, 1.166 + }); 1.167 + }, 1.168 + 1.169 + observe: function observe(subject, topic, data) { 1.170 + if (topic != "SharedPreferences:Changed") { 1.171 + return; 1.172 + } 1.173 + 1.174 + let msg = JSON.parse(data); 1.175 + if (msg.branch != this._branch) { 1.176 + return; 1.177 + } 1.178 + 1.179 + if (!this._observers.hasOwnProperty(msg.key)) { 1.180 + return; 1.181 + } 1.182 + 1.183 + let observers = this._observers[msg.key]; 1.184 + for (let obs of observers) { 1.185 + obs.observe(obs, msg.key, msg.value); 1.186 + } 1.187 + }, 1.188 + 1.189 + _uninstallAndroidListener: function _uninstallAndroidListener() { 1.190 + if (!this._listening) 1.191 + return; 1.192 + this._listening = false; 1.193 + 1.194 + Services.obs.removeObserver(this, "SharedPreferences:Changed"); 1.195 + sendMessageToJava({ 1.196 + type: "SharedPreferences:Observe", 1.197 + enable: false, 1.198 + branch: this._branch, 1.199 + }); 1.200 + }, 1.201 +});