dom/settings/SettingsService.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 "use strict"
michael@0 6
michael@0 7 /* static functions */
michael@0 8 let DEBUG = 0;
michael@0 9 let debug;
michael@0 10 if (DEBUG)
michael@0 11 debug = function (s) { dump("-*- SettingsService: " + s + "\n"); }
michael@0 12 else
michael@0 13 debug = function (s) {}
michael@0 14
michael@0 15 const Ci = Components.interfaces;
michael@0 16 const Cu = Components.utils;
michael@0 17
michael@0 18 Cu.import("resource://gre/modules/SettingsQueue.jsm");
michael@0 19 Cu.import("resource://gre/modules/SettingsDB.jsm");
michael@0 20 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 21 Cu.import("resource://gre/modules/Services.jsm");
michael@0 22
michael@0 23 const nsIClassInfo = Ci.nsIClassInfo;
michael@0 24
michael@0 25 const SETTINGSSERVICELOCK_CONTRACTID = "@mozilla.org/settingsServiceLock;1";
michael@0 26 const SETTINGSSERVICELOCK_CID = Components.ID("{d7a395a0-e292-11e1-834e-1761d57f5f99}");
michael@0 27 const nsISettingsServiceLock = Ci.nsISettingsServiceLock;
michael@0 28
michael@0 29 function SettingsServiceLock(aSettingsService)
michael@0 30 {
michael@0 31 if (DEBUG) debug("settingsServiceLock constr!");
michael@0 32 this._open = true;
michael@0 33 this._busy = false;
michael@0 34 this._requests = new Queue();
michael@0 35 this._settingsService = aSettingsService;
michael@0 36 this._transaction = null;
michael@0 37 }
michael@0 38
michael@0 39 SettingsServiceLock.prototype = {
michael@0 40
michael@0 41 callHandle: function callHandle(aCallback, aName, aValue) {
michael@0 42 try {
michael@0 43 aCallback ? aCallback.handle(aName, aValue) : null;
michael@0 44 } catch (e) {
michael@0 45 dump("settings 'handle' callback threw an exception, dropping: " + e + "\n");
michael@0 46 }
michael@0 47 },
michael@0 48
michael@0 49 callAbort: function callAbort(aCallback, aMessage) {
michael@0 50 try {
michael@0 51 aCallback ? aCallback.handleAbort(aMessage) : null;
michael@0 52 } catch (e) {
michael@0 53 dump("settings 'abort' callback threw an exception, dropping: " + e + "\n");
michael@0 54 }
michael@0 55 },
michael@0 56
michael@0 57 callError: function callError(aCallback, aMessage) {
michael@0 58 try {
michael@0 59 aCallback ? aCallback.handleError(aMessage) : null;
michael@0 60 } catch (e) {
michael@0 61 dump("settings 'error' callback threw an exception, dropping: " + e + "\n");
michael@0 62 }
michael@0 63 },
michael@0 64
michael@0 65 process: function process() {
michael@0 66 debug("process!");
michael@0 67 let lock = this;
michael@0 68 lock._open = false;
michael@0 69 let store = lock._transaction.objectStore(SETTINGSSTORE_NAME);
michael@0 70
michael@0 71 while (!lock._requests.isEmpty()) {
michael@0 72 if (lock._isBusy) {
michael@0 73 return;
michael@0 74 }
michael@0 75 let info = lock._requests.dequeue();
michael@0 76 if (DEBUG) debug("info:" + info.intent);
michael@0 77 let callback = info.callback;
michael@0 78 let name = info.name;
michael@0 79 switch (info.intent) {
michael@0 80 case "set":
michael@0 81 let value = info.value;
michael@0 82 let message = info.message;
michael@0 83 if(DEBUG && typeof(value) == 'object') {
michael@0 84 debug("object name:" + name + ", val: " + JSON.stringify(value));
michael@0 85 }
michael@0 86 lock._isBusy = true;
michael@0 87 let checkKeyRequest = store.get(name);
michael@0 88
michael@0 89 checkKeyRequest.onsuccess = function (event) {
michael@0 90 let defaultValue;
michael@0 91 if (event.target.result) {
michael@0 92 defaultValue = event.target.result.defaultValue;
michael@0 93 } else {
michael@0 94 defaultValue = null;
michael@0 95 if (DEBUG) debug("MOZSETTINGS-SET-WARNING: " + name + " is not in the database.\n");
michael@0 96 }
michael@0 97 let setReq = store.put({ settingName: name, defaultValue: defaultValue, userValue: value });
michael@0 98
michael@0 99 setReq.onsuccess = function() {
michael@0 100 lock._isBusy = false;
michael@0 101 lock._open = true;
michael@0 102 lock.callHandle(callback, name, value);
michael@0 103 Services.obs.notifyObservers(lock, "mozsettings-changed", JSON.stringify({
michael@0 104 key: name,
michael@0 105 value: value,
michael@0 106 message: message
michael@0 107 }));
michael@0 108 lock._open = false;
michael@0 109 lock.process();
michael@0 110 };
michael@0 111
michael@0 112 setReq.onerror = function(event) {
michael@0 113 lock._isBusy = false;
michael@0 114 lock.callError(callback, event.target.errorMessage);
michael@0 115 lock.process();
michael@0 116 };
michael@0 117 }
michael@0 118
michael@0 119 checkKeyRequest.onerror = function(event) {
michael@0 120 lock._isBusy = false;
michael@0 121 lock.callError(callback, event.target.errorMessage);
michael@0 122 lock.process();
michael@0 123 };
michael@0 124 break;
michael@0 125 case "get":
michael@0 126 let getReq = store.mozGetAll(name);
michael@0 127 getReq.onsuccess = function(event) {
michael@0 128 if (DEBUG) {
michael@0 129 debug("Request successful. Record count:" + event.target.result.length);
michael@0 130 debug("result: " + JSON.stringify(event.target.result));
michael@0 131 }
michael@0 132 this._open = true;
michael@0 133 if (callback) {
michael@0 134 if (event.target.result[0]) {
michael@0 135 if (event.target.result.length > 1) {
michael@0 136 if (DEBUG) debug("Warning: overloaded setting:" + name);
michael@0 137 }
michael@0 138 let result = event.target.result[0];
michael@0 139 let value = result.userValue !== undefined
michael@0 140 ? result.userValue
michael@0 141 : result.defaultValue;
michael@0 142 lock.callHandle(callback, name, value);
michael@0 143 } else {
michael@0 144 lock.callHandle(callback, name, null);
michael@0 145 }
michael@0 146 } else {
michael@0 147 if (DEBUG) debug("no callback defined!");
michael@0 148 }
michael@0 149 this._open = false;
michael@0 150 }.bind(lock);
michael@0 151 getReq.onerror = function error(event) {
michael@0 152 lock.callError(callback, event.target.errorMessage);
michael@0 153 };
michael@0 154 break;
michael@0 155 }
michael@0 156 }
michael@0 157 lock._open = true;
michael@0 158 },
michael@0 159
michael@0 160 createTransactionAndProcess: function(aCallback) {
michael@0 161 if (this._settingsService._settingsDB._db) {
michael@0 162 let lock;
michael@0 163 while (lock = this._settingsService._locks.dequeue()) {
michael@0 164 if (!lock._transaction) {
michael@0 165 lock._transaction = lock._settingsService._settingsDB._db.transaction(SETTINGSSTORE_NAME, "readwrite");
michael@0 166 if (aCallback) {
michael@0 167 lock._transaction.oncomplete = aCallback.handle;
michael@0 168 lock._transaction.onabort = function(event) {
michael@0 169 let message = '';
michael@0 170 if (event.target.error) {
michael@0 171 message = event.target.error.name + ': ' + event.target.error.message;
michael@0 172 }
michael@0 173 this.callAbort(aCallback, message);
michael@0 174 };
michael@0 175 }
michael@0 176 }
michael@0 177 if (!lock._isBusy) {
michael@0 178 lock.process();
michael@0 179 } else {
michael@0 180 this._settingsService._locks.enqueue(lock);
michael@0 181 return;
michael@0 182 }
michael@0 183 }
michael@0 184 if (!this._requests.isEmpty() && !this._isBusy) {
michael@0 185 this.process();
michael@0 186 }
michael@0 187 }
michael@0 188 },
michael@0 189
michael@0 190 get: function get(aName, aCallback) {
michael@0 191 if (DEBUG) debug("get: " + aName + ", " + aCallback);
michael@0 192 this._requests.enqueue({ callback: aCallback, intent:"get", name: aName });
michael@0 193 this.createTransactionAndProcess();
michael@0 194 },
michael@0 195
michael@0 196 set: function set(aName, aValue, aCallback, aMessage) {
michael@0 197 debug("set: " + aName + ": " + JSON.stringify(aValue));
michael@0 198 if (aMessage === undefined)
michael@0 199 aMessage = null;
michael@0 200 this._requests.enqueue({ callback: aCallback,
michael@0 201 intent: "set",
michael@0 202 name: aName,
michael@0 203 value: this._settingsService._settingsDB.prepareValue(aValue),
michael@0 204 message: aMessage });
michael@0 205 this.createTransactionAndProcess();
michael@0 206 },
michael@0 207
michael@0 208 classID : SETTINGSSERVICELOCK_CID,
michael@0 209 QueryInterface : XPCOMUtils.generateQI([nsISettingsServiceLock])
michael@0 210 };
michael@0 211
michael@0 212 const SETTINGSSERVICE_CID = Components.ID("{f656f0c0-f776-11e1-a21f-0800200c9a66}");
michael@0 213
michael@0 214 function SettingsService()
michael@0 215 {
michael@0 216 debug("settingsService Constructor");
michael@0 217 this._locks = new Queue();
michael@0 218 this._settingsDB = new SettingsDB();
michael@0 219 this._settingsDB.init();
michael@0 220 }
michael@0 221
michael@0 222 SettingsService.prototype = {
michael@0 223
michael@0 224 nextTick: function nextTick(aCallback, thisObj) {
michael@0 225 if (thisObj)
michael@0 226 aCallback = aCallback.bind(thisObj);
michael@0 227
michael@0 228 Services.tm.currentThread.dispatch(aCallback, Ci.nsIThread.DISPATCH_NORMAL);
michael@0 229 },
michael@0 230
michael@0 231 createLock: function createLock(aCallback) {
michael@0 232 var lock = new SettingsServiceLock(this);
michael@0 233 this._locks.enqueue(lock);
michael@0 234 this._settingsDB.ensureDB(
michael@0 235 function() { lock.createTransactionAndProcess(aCallback); },
michael@0 236 function() { dump("SettingsService failed to open DB!\n"); }
michael@0 237 );
michael@0 238 this.nextTick(function() { this._open = false; }, lock);
michael@0 239 return lock;
michael@0 240 },
michael@0 241
michael@0 242 classID : SETTINGSSERVICE_CID,
michael@0 243 QueryInterface : XPCOMUtils.generateQI([Ci.nsISettingsService])
michael@0 244 }
michael@0 245
michael@0 246 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SettingsService, SettingsServiceLock])

mercurial