mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 743336 - Settings API: Add service. r=fabrice
This commit is contained in:
parent
c9f620b2b3
commit
bc17675f66
@ -408,6 +408,8 @@
|
||||
@BINPATH@/components/messageWakeupService.manifest
|
||||
@BINPATH@/components/SettingsManager.js
|
||||
@BINPATH@/components/SettingsManager.manifest
|
||||
@BINPATH@/components/SettingsService.js
|
||||
@BINPATH@/components/SettingsService.manifest
|
||||
@BINPATH@/components/nsFilePicker.js
|
||||
@BINPATH@/components/nsFilePicker.manifest
|
||||
#ifdef MOZ_B2G_RIL
|
||||
|
@ -15,6 +15,7 @@ GRE_MODULE = 1
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIDOMSettingsManager.idl \
|
||||
nsISettingsService.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
27
dom/interfaces/settings/nsISettingsService.idl
Normal file
27
dom/interfaces/settings/nsISettingsService.idl
Normal file
@ -0,0 +1,27 @@
|
||||
/* 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/. */
|
||||
|
||||
#include "domstubs.idl"
|
||||
|
||||
[scriptable, uuid(83d67430-8516-11e1-b0c4-0800200c9a66)]
|
||||
interface nsISettingsServiceCallback : nsISupports
|
||||
{
|
||||
[implicit_jscontext]
|
||||
void handle(in DOMString aName, in jsval aResult);
|
||||
[implicit_jscontext]
|
||||
void handleError(in DOMString aErrorMessage);
|
||||
};
|
||||
|
||||
[scriptable, uuid(3ab3cbc0-8513-11e1-b0c4-0800200c9a66)]
|
||||
interface nsISettingsServiceLock : nsISupports
|
||||
{
|
||||
void set(in string aName, in jsval aValue, in nsISettingsServiceCallback aCallback);
|
||||
void get(in string aName, in nsISettingsServiceCallback aCallback);
|
||||
};
|
||||
|
||||
[scriptable, uuid(3458e760-8513-11e1-b0c4-0800200c9a66)]
|
||||
interface nsISettingsService : nsISupports
|
||||
{
|
||||
nsISettingsServiceLock getLock();
|
||||
};
|
@ -18,6 +18,13 @@ LIBXUL_LIBRARY = 1
|
||||
EXTRA_COMPONENTS = \
|
||||
SettingsManager.js \
|
||||
SettingsManager.manifest \
|
||||
SettingsService.js \
|
||||
SettingsService.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
SettingsQueue.jsm \
|
||||
SettingsDB.jsm \
|
||||
$(NULL)
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
|
36
dom/settings/SettingsDB.jsm
Normal file
36
dom/settings/SettingsDB.jsm
Normal file
@ -0,0 +1,36 @@
|
||||
/* 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/. */
|
||||
|
||||
let EXPORTED_SYMBOLS = ["SettingsDB", "SETTINGSDB_NAME", "SETTINGSSTORE_NAME"];
|
||||
|
||||
/* static functions */
|
||||
let DEBUG = 0;
|
||||
if (DEBUG) {
|
||||
debug = function (s) { dump("-*- SettingsDB: " + s + "\n"); }
|
||||
} else {
|
||||
debug = function (s) {}
|
||||
}
|
||||
|
||||
const SETTINGSDB_NAME = "settings";
|
||||
const SETTINGSDB_VERSION = 1;
|
||||
const SETTINGSSTORE_NAME = "settings";
|
||||
|
||||
Components.utils.import("resource://gre/modules/IndexedDBHelper.jsm");
|
||||
|
||||
function SettingsDB() {}
|
||||
|
||||
SettingsDB.prototype = {
|
||||
|
||||
__proto__: IndexedDBHelper.prototype,
|
||||
|
||||
createSchema: function createSchema(aDb) {
|
||||
let objectStore = aDb.createObjectStore(SETTINGSSTORE_NAME, { keyPath: "settingName" });
|
||||
objectStore.createIndex("settingValue", "settingValue", { unique: false });
|
||||
debug("Created object stores and indexes");
|
||||
},
|
||||
|
||||
init: function init(aGlobal) {
|
||||
this.initDBHelper(SETTINGSDB_NAME, SETTINGSDB_VERSION, SETTINGSSTORE_NAME, aGlobal);
|
||||
}
|
||||
}
|
@ -11,57 +11,12 @@ if (DEBUG)
|
||||
else
|
||||
debug = function (s) {}
|
||||
|
||||
function Queue() {
|
||||
this._queue = [];
|
||||
this._index = 0;
|
||||
}
|
||||
|
||||
Queue.prototype = {
|
||||
getLength: function() { return (this._queue.length - this._index); },
|
||||
|
||||
isEmpty: function() { return (this._queue.length == 0); },
|
||||
|
||||
enqueue: function(item) { this._queue.push(item); },
|
||||
|
||||
dequeue: function() {
|
||||
if(this.isEmpty())
|
||||
return undefined;
|
||||
|
||||
var item = this._queue[this._index];
|
||||
if (++this._index * 2 >= this._queue.length){
|
||||
this._queue = this._queue.slice(this._index);
|
||||
this._index = 0;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
|
||||
|
||||
const DB_NAME = "settings";
|
||||
const DB_VERSION = 1;
|
||||
const STORE_NAME = "settings";
|
||||
|
||||
function SettingsDB() {}
|
||||
|
||||
SettingsDB.prototype = {
|
||||
__proto__: IndexedDBHelper.prototype,
|
||||
|
||||
createSchema: function createSchema(aDb) {
|
||||
let objectStore = aDb.createObjectStore(STORE_NAME, { keyPath: "settingName" });
|
||||
objectStore.createIndex("settingValue", "settingValue", { unique: false });
|
||||
debug("Created object stores and indexes");
|
||||
},
|
||||
|
||||
init: function init(aGlobal) {
|
||||
this.initDBHelper(DB_NAME, DB_VERSION, STORE_NAME, aGlobal);
|
||||
}
|
||||
}
|
||||
|
||||
Cu.import("resource://gre/modules/SettingsQueue.jsm");
|
||||
Cu.import("resource://gre/modules/SettingsDB.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
@ -83,7 +38,7 @@ SettingsLock.prototype = {
|
||||
process: function process() {
|
||||
let lock = this;
|
||||
lock._open = false;
|
||||
let store = lock._transaction.objectStore(STORE_NAME);
|
||||
let store = lock._transaction.objectStore(SETTINGSSTORE_NAME);
|
||||
|
||||
while (!lock._requests.isEmpty()) {
|
||||
let info = lock._requests.dequeue();
|
||||
@ -152,7 +107,7 @@ SettingsLock.prototype = {
|
||||
var lock;
|
||||
while (lock = this._settingsManager._locks.dequeue()) {
|
||||
if (!lock._transaction) {
|
||||
lock._transaction = lock._settingsManager._settingsDB._db.transaction(STORE_NAME, "readwrite");
|
||||
lock._transaction = lock._settingsManager._settingsDB._db.transaction(SETTINGSSTORE_NAME, "readwrite");
|
||||
}
|
||||
lock.process();
|
||||
}
|
||||
|
30
dom/settings/SettingsQueue.jsm
Normal file
30
dom/settings/SettingsQueue.jsm
Normal file
@ -0,0 +1,30 @@
|
||||
/* 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/. */
|
||||
|
||||
let EXPORTED_SYMBOLS = ["Queue"];
|
||||
|
||||
function Queue() {
|
||||
this._queue = [];
|
||||
this._index = 0;
|
||||
}
|
||||
|
||||
Queue.prototype = {
|
||||
getLength: function() { return (this._queue.length - this._index); },
|
||||
|
||||
isEmpty: function() { return (this._queue.length == 0); },
|
||||
|
||||
enqueue: function(item) { this._queue.push(item); },
|
||||
|
||||
dequeue: function() {
|
||||
if(this.isEmpty())
|
||||
return undefined;
|
||||
|
||||
var item = this._queue[this._index];
|
||||
if (++this._index * 2 >= this._queue.length){
|
||||
this._queue = this._queue.slice(this._index);
|
||||
this._index = 0;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
183
dom/settings/SettingsService.js
Normal file
183
dom/settings/SettingsService.js
Normal file
@ -0,0 +1,183 @@
|
||||
/* 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"
|
||||
|
||||
/* static functions */
|
||||
let DEBUG = 0;
|
||||
if (DEBUG)
|
||||
debug = function (s) { dump("-*- SettingsService: " + s + "\n"); }
|
||||
else
|
||||
debug = function (s) {}
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/SettingsQueue.jsm");
|
||||
Cu.import("resource://gre/modules/SettingsDB.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const nsIClassInfo = Ci.nsIClassInfo;
|
||||
|
||||
const SETTINGSSERVICELOCK_CONTRACTID = "@mozilla.org/settingsServiceLock;1";
|
||||
const SETTINGSSERVICELOCK_CID = Components.ID("{3ab3cbc0-8513-11e1-b0c4-0800200c9a66}");
|
||||
const nsISettingsServiceLock = Ci.nsISettingsServiceLock;
|
||||
|
||||
function SettingsServiceLock(aSettingsService)
|
||||
{
|
||||
debug("settingsServiceLock constr!");
|
||||
this._open = true;
|
||||
this._requests = new Queue();
|
||||
this._settingsService = aSettingsService;
|
||||
this._transaction = null;
|
||||
}
|
||||
|
||||
SettingsServiceLock.prototype = {
|
||||
|
||||
process: function process() {
|
||||
debug("process!");
|
||||
let lock = this;
|
||||
lock._open = false;
|
||||
let store = lock._transaction.objectStore(SETTINGSSTORE_NAME);
|
||||
|
||||
while (!lock._requests.isEmpty()) {
|
||||
let info = lock._requests.dequeue();
|
||||
debug("info:" + info.intent);
|
||||
let callback = info.callback;
|
||||
let req;
|
||||
let name = info.name;
|
||||
switch (info.intent) {
|
||||
case "set":
|
||||
let value = info.value;
|
||||
if(typeof(value) == 'object')
|
||||
debug("object name:" + name + ", val: " + JSON.stringify(value));
|
||||
req = store.put({settingName: name, settingValue: value});
|
||||
|
||||
req.onsuccess = function() {
|
||||
debug("set on success");
|
||||
lock._open = true;
|
||||
if (callback)
|
||||
callback.handle(name, value);
|
||||
Services.obs.notifyObservers(lock, "mozsettings-changed", JSON.stringify({
|
||||
key: name,
|
||||
value: value
|
||||
}));
|
||||
lock._open = false;
|
||||
};
|
||||
|
||||
req.onerror = function(event) { callback ? callback.handleError(event.target.errorMessage) : null; };
|
||||
break;
|
||||
case "get":
|
||||
req = store.getAll(name);
|
||||
req.onsuccess = function(event) {
|
||||
debug("Request successful. Record count:" + event.target.result.length);
|
||||
debug("result: " + JSON.stringify(event.target.result));
|
||||
this._open = true;
|
||||
if (callback) {
|
||||
if (event.target.result[0]) {
|
||||
if (event.target.result.length > 1) {
|
||||
debug("Warning: overloaded setting:" + name);
|
||||
}
|
||||
callback.handle(name, event.target.result[0].settingValue);
|
||||
} else
|
||||
callback.handle(name, null);
|
||||
} else {
|
||||
debug("no callback defined!");
|
||||
}
|
||||
this._open = false;
|
||||
}.bind(lock);
|
||||
req.onerror = function error(event) { callback ? callback.handleError(event.target.errorMessage) : null; };
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!lock._requests.isEmpty())
|
||||
throw Components.results.NS_ERROR_ABORT;
|
||||
lock._open = true;
|
||||
},
|
||||
|
||||
createTransactionAndProcess: function createTransactionAndProcess() {
|
||||
if (this._settingsService._settingsDB._db) {
|
||||
var lock;
|
||||
while (lock = this._settingsService._locks.dequeue()) {
|
||||
if (!lock._transaction) {
|
||||
lock._transaction = lock._settingsService._settingsDB._db.transaction(SETTINGSSTORE_NAME, "readwrite");
|
||||
}
|
||||
lock.process();
|
||||
}
|
||||
if (!this._requests.isEmpty())
|
||||
this.process();
|
||||
}
|
||||
},
|
||||
|
||||
get: function get(aName, aCallback) {
|
||||
debug("get: " + aName + ", " + aCallback);
|
||||
this._requests.enqueue({ callback: aCallback, intent:"get", name: aName });
|
||||
this.createTransactionAndProcess();
|
||||
},
|
||||
|
||||
set: function set(aName, aValue, aCallback) {
|
||||
debug("set: " + aName + ": " + JSON.stringify(aValue));
|
||||
this._requests.enqueue({ callback: aCallback, intent: "set", name: aName, value: aValue});
|
||||
this.createTransactionAndProcess();
|
||||
},
|
||||
|
||||
classID : SETTINGSSERVICELOCK_CID,
|
||||
QueryInterface : XPCOMUtils.generateQI([nsISettingsServiceLock]),
|
||||
|
||||
classInfo : XPCOMUtils.generateCI({classID: SETTINGSSERVICELOCK_CID,
|
||||
contractID: SETTINGSSERVICELOCK_CONTRACTID,
|
||||
classDescription: "SettingsServiceLock",
|
||||
interfaces: [nsISettingsServiceLock],
|
||||
flags: nsIClassInfo.DOM_OBJECT})
|
||||
};
|
||||
|
||||
const SETTINGSSERVICE_CONTRACTID = "@mozilla.org/settingsService;1";
|
||||
const SETTINGSSERVICE_CID = Components.ID("{3458e760-8513-11e1-b0c4-0800200c9a66}");
|
||||
const nsISettingsService = Ci.nsISettingsService;
|
||||
|
||||
let myGlobal = this;
|
||||
|
||||
function SettingsService()
|
||||
{
|
||||
debug("settingsService Constructor");
|
||||
this._locks = new Queue();
|
||||
var idbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"].getService(Ci.nsIIndexedDatabaseManager);
|
||||
idbManager.initWindowless(myGlobal);
|
||||
this._settingsDB = new SettingsDB();
|
||||
this._settingsDB.init(myGlobal);
|
||||
}
|
||||
|
||||
SettingsService.prototype = {
|
||||
|
||||
nextTick: function nextTick(aCallback, thisObj) {
|
||||
if (thisObj)
|
||||
aCallback = aCallback.bind(thisObj);
|
||||
|
||||
Services.tm.currentThread.dispatch(aCallback, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
},
|
||||
|
||||
getLock: function getLock() {
|
||||
debug("get lock!");
|
||||
var lock = new SettingsServiceLock(this);
|
||||
this._locks.enqueue(lock);
|
||||
this._settingsDB.ensureDB(
|
||||
function() { lock.createTransactionAndProcess(); },
|
||||
function() { dump("ensureDB error cb!\n"); },
|
||||
myGlobal );
|
||||
this.nextTick(function() { this._open = false; }, lock);
|
||||
return lock;
|
||||
},
|
||||
|
||||
classID : SETTINGSSERVICE_CID,
|
||||
QueryInterface : XPCOMUtils.generateQI([nsISettingsService]),
|
||||
|
||||
classInfo : XPCOMUtils.generateCI({classID: SETTINGSSERVICE_CID,
|
||||
contractID: SETTINGSSERVICE_CONTRACTID,
|
||||
classDescription: "SettingsService",
|
||||
interfaces: [nsISettingsService],
|
||||
flags: nsIClassInfo.DOM_OBJECT})
|
||||
}
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([SettingsService, SettingsServiceLock])
|
5
dom/settings/SettingsService.manifest
Normal file
5
dom/settings/SettingsService.manifest
Normal file
@ -0,0 +1,5 @@
|
||||
component {3ab3cbc0-8513-11e1-b0c4-0800200c9a66} SettingsService.js
|
||||
contract @mozilla.org/settingsServiceLock;1 {3ab3cbc0-8513-11e1-b0c4-0800200c9a66}
|
||||
|
||||
component {3458e760-8513-11e1-b0c4-0800200c9a66} SettingsService.js
|
||||
contract @mozilla.org/settingsService;1 {3458e760-8513-11e1-b0c4-0800200c9a66}
|
@ -11,9 +11,6 @@ relativesrcdir = dom/settings/tests
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES = \
|
||||
|
Loading…
Reference in New Issue
Block a user