mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1015518 - Use SettingsRequestManager as SettingsService Backend; r=bent
This commit is contained in:
parent
41a4e59da7
commit
fb56d9d590
@ -108,11 +108,13 @@ SettingsLock.prototype = {
|
|||||||
|
|
||||||
receiveMessage: function(aMessage) {
|
receiveMessage: function(aMessage) {
|
||||||
let msg = aMessage.data;
|
let msg = aMessage.data;
|
||||||
|
|
||||||
// SettingsRequestManager broadcasts changes to all locks in the child. If
|
// SettingsRequestManager broadcasts changes to all locks in the child. If
|
||||||
// our lock isn't being addressed, just return.
|
// our lock isn't being addressed, just return.
|
||||||
if (msg.lockID != this._id) {
|
if (msg.lockID != this._id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (DEBUG) debug("receiveMessage (" + this._id + "): " + aMessage.name);
|
||||||
|
|
||||||
// Finalizing a transaction does not return a request ID since we are
|
// Finalizing a transaction does not return a request ID since we are
|
||||||
// supposed to fire callbacks.
|
// supposed to fire callbacks.
|
||||||
|
@ -5,20 +5,24 @@
|
|||||||
"use strict"
|
"use strict"
|
||||||
|
|
||||||
/* static functions */
|
/* static functions */
|
||||||
let DEBUG = 0;
|
const DEBUG = false;
|
||||||
let debug;
|
function debug(s) {
|
||||||
if (DEBUG)
|
dump("-*- SettingsService: " + s + "\n");
|
||||||
debug = function (s) { dump("-*- SettingsService: " + s + "\n"); }
|
}
|
||||||
else
|
|
||||||
debug = function (s) {}
|
|
||||||
|
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
const Cu = Components.utils;
|
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/XPCOMUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
Cu.import('resource://gre/modules/SettingsRequestManager.jsm');
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
|
||||||
|
"@mozilla.org/uuid-generator;1",
|
||||||
|
"nsIUUIDGenerator");
|
||||||
|
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||||
|
"@mozilla.org/childprocessmessagemanager;1",
|
||||||
|
"nsIMessageSender");
|
||||||
|
|
||||||
const nsIClassInfo = Ci.nsIClassInfo;
|
const nsIClassInfo = Ci.nsIClassInfo;
|
||||||
|
|
||||||
@ -26,18 +30,149 @@ const SETTINGSSERVICELOCK_CONTRACTID = "@mozilla.org/settingsServiceLock;1";
|
|||||||
const SETTINGSSERVICELOCK_CID = Components.ID("{d7a395a0-e292-11e1-834e-1761d57f5f99}");
|
const SETTINGSSERVICELOCK_CID = Components.ID("{d7a395a0-e292-11e1-834e-1761d57f5f99}");
|
||||||
const nsISettingsServiceLock = Ci.nsISettingsServiceLock;
|
const nsISettingsServiceLock = Ci.nsISettingsServiceLock;
|
||||||
|
|
||||||
function SettingsServiceLock(aSettingsService, aTransactionCallback)
|
function makeSettingsServiceRequest(aCallback, aName, aValue) {
|
||||||
{
|
return {
|
||||||
|
callback: aCallback,
|
||||||
|
name: aName,
|
||||||
|
value: aValue
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function SettingsServiceLock(aSettingsService, aTransactionCallback) {
|
||||||
if (DEBUG) debug("settingsServiceLock constr!");
|
if (DEBUG) debug("settingsServiceLock constr!");
|
||||||
this._open = true;
|
this._open = true;
|
||||||
this._busy = false;
|
|
||||||
this._requests = new Queue();
|
|
||||||
this._settingsService = aSettingsService;
|
this._settingsService = aSettingsService;
|
||||||
this._transaction = null;
|
this._id = uuidgen.generateUUID().toString();
|
||||||
this._transactionCallback = aTransactionCallback;
|
this._transactionCallback = aTransactionCallback;
|
||||||
|
this._requests = {};
|
||||||
|
let closeHelper = function() {
|
||||||
|
if (DEBUG) debug("closing lock " + this._id);
|
||||||
|
this._open = false;
|
||||||
|
this.runOrFinalizeQueries();
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
let msgs = ["Settings:Get:OK", "Settings:Get:KO",
|
||||||
|
"Settings:Clear:OK", "Settings:Clear:KO",
|
||||||
|
"Settings:Set:OK", "Settings:Set:KO",
|
||||||
|
"Settings:Finalize:OK", "Settings:Finalize:KO"];
|
||||||
|
|
||||||
|
for (let msg in msgs) {
|
||||||
|
cpmm.addMessageListener(msgs[msg], this);
|
||||||
|
}
|
||||||
|
|
||||||
|
cpmm.sendAsyncMessage("Settings:CreateLock", {lockID: this._id, isServiceLock: true}, undefined, Services.scriptSecurityManager.getSystemPrincipal());
|
||||||
|
Services.tm.currentThread.dispatch(closeHelper, Ci.nsIThread.DISPATCH_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsServiceLock.prototype = {
|
SettingsServiceLock.prototype = {
|
||||||
|
get closed() {
|
||||||
|
return !this._open;
|
||||||
|
},
|
||||||
|
|
||||||
|
runOrFinalizeQueries: function() {
|
||||||
|
if (!this._requests || Object.keys(this._requests).length == 0) {
|
||||||
|
cpmm.sendAsyncMessage("Settings:Finalize", {lockID: this._id}, undefined, Services.scriptSecurityManager.getSystemPrincipal());
|
||||||
|
} else {
|
||||||
|
cpmm.sendAsyncMessage("Settings:Run", {lockID: this._id}, undefined, Services.scriptSecurityManager.getSystemPrincipal());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
receiveMessage: function(aMessage) {
|
||||||
|
|
||||||
|
let msg = aMessage.data;
|
||||||
|
// SettingsRequestManager broadcasts changes to all locks in the child. If
|
||||||
|
// our lock isn't being addressed, just return.
|
||||||
|
if(msg.lockID != this._id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (DEBUG) debug("receiveMessage (" + this._id + "): " + aMessage.name);
|
||||||
|
// Finalizing a transaction does not return a request ID since we are
|
||||||
|
// supposed to fire callbacks.
|
||||||
|
if (!msg.requestID) {
|
||||||
|
switch (aMessage.name) {
|
||||||
|
case "Settings:Finalize:OK":
|
||||||
|
if (DEBUG) debug("Lock finalize ok!");
|
||||||
|
this.callTransactionHandle();
|
||||||
|
break;
|
||||||
|
case "Settings:Finalize:KO":
|
||||||
|
if (DEBUG) debug("Lock finalize failed!");
|
||||||
|
this.callAbort();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (DEBUG) debug("Message type " + aMessage.name + " is missing a requestID");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let req = this._requests[msg.requestID];
|
||||||
|
if (!req) {
|
||||||
|
if (DEBUG) debug("Matching request not found.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
delete this._requests[msg.requestID];
|
||||||
|
switch (aMessage.name) {
|
||||||
|
case "Settings:Get:OK":
|
||||||
|
this._open = true;
|
||||||
|
let settings_names = Object.keys(msg.settings);
|
||||||
|
if (settings_names.length > 0) {
|
||||||
|
let name = settings_names[0];
|
||||||
|
if (DEBUG && settings_names.length > 1) {
|
||||||
|
debug("Warning: overloaded setting:" + name);
|
||||||
|
}
|
||||||
|
let result = msg.settings[name];
|
||||||
|
this.callHandle(req.callback, name, result);
|
||||||
|
} else {
|
||||||
|
this.callHandle(req.callback, req.name, null);
|
||||||
|
}
|
||||||
|
this._open = false;
|
||||||
|
break;
|
||||||
|
case "Settings:Set:OK":
|
||||||
|
this._open = true;
|
||||||
|
// We don't pass values back from sets in SettingsManager...
|
||||||
|
this.callHandle(req.callback, req.name, req.value);
|
||||||
|
this._open = false;
|
||||||
|
break;
|
||||||
|
case "Settings:Get:KO":
|
||||||
|
case "Settings:Set:KO":
|
||||||
|
if (DEBUG) debug("error:" + msg.errorMsg);
|
||||||
|
this.callError(req.callback, msg.error);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (DEBUG) debug("Wrong message: " + aMessage.name);
|
||||||
|
}
|
||||||
|
this.runOrFinalizeQueries();
|
||||||
|
},
|
||||||
|
|
||||||
|
get: function get(aName, aCallback) {
|
||||||
|
if (DEBUG) debug("get (" + this._id + "): " + aName);
|
||||||
|
if (!this._open) {
|
||||||
|
dump("Settings lock not open!\n");
|
||||||
|
throw Components.results.NS_ERROR_ABORT;
|
||||||
|
}
|
||||||
|
let reqID = uuidgen.generateUUID().toString();
|
||||||
|
this._requests[reqID] = makeSettingsServiceRequest(aCallback, aName);
|
||||||
|
cpmm.sendAsyncMessage("Settings:Get", {requestID: reqID,
|
||||||
|
lockID: this._id,
|
||||||
|
name: aName},
|
||||||
|
undefined,
|
||||||
|
Services.scriptSecurityManager.getSystemPrincipal());
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function set(aName, aValue, aCallback) {
|
||||||
|
if (DEBUG) debug("set: " + aName + " " + aValue);
|
||||||
|
if (!this._open) {
|
||||||
|
throw "Settings lock not open";
|
||||||
|
}
|
||||||
|
let reqID = uuidgen.generateUUID().toString();
|
||||||
|
this._requests[reqID] = makeSettingsServiceRequest(aCallback, aName, aValue);
|
||||||
|
let settings = {};
|
||||||
|
settings[aName] = aValue;
|
||||||
|
cpmm.sendAsyncMessage("Settings:Set", {requestID: reqID,
|
||||||
|
lockID: this._id,
|
||||||
|
settings: settings},
|
||||||
|
undefined,
|
||||||
|
Services.scriptSecurityManager.getSystemPrincipal());
|
||||||
|
},
|
||||||
|
|
||||||
callHandle: function callHandle(aCallback, aName, aValue) {
|
callHandle: function callHandle(aCallback, aName, aValue) {
|
||||||
try {
|
try {
|
||||||
@ -71,149 +206,6 @@ SettingsServiceLock.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
process: function process() {
|
|
||||||
debug("process!");
|
|
||||||
let lock = this;
|
|
||||||
lock._open = false;
|
|
||||||
let store = lock._transaction.objectStore(SETTINGSSTORE_NAME);
|
|
||||||
|
|
||||||
while (!lock._requests.isEmpty()) {
|
|
||||||
if (lock._isBusy) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let info = lock._requests.dequeue();
|
|
||||||
if (DEBUG) debug("info:" + info.intent);
|
|
||||||
let callback = info.callback;
|
|
||||||
let name = info.name;
|
|
||||||
switch (info.intent) {
|
|
||||||
case "set":
|
|
||||||
let value = info.value;
|
|
||||||
let message = info.message;
|
|
||||||
if(DEBUG && typeof(value) == 'object') {
|
|
||||||
debug("object name:" + name + ", val: " + JSON.stringify(value));
|
|
||||||
}
|
|
||||||
lock._isBusy = true;
|
|
||||||
let checkKeyRequest = store.get(name);
|
|
||||||
|
|
||||||
checkKeyRequest.onsuccess = function (event) {
|
|
||||||
let defaultValue;
|
|
||||||
if (event.target.result) {
|
|
||||||
defaultValue = event.target.result.defaultValue;
|
|
||||||
} else {
|
|
||||||
defaultValue = null;
|
|
||||||
if (DEBUG) debug("MOZSETTINGS-SET-WARNING: " + name + " is not in the database.\n");
|
|
||||||
}
|
|
||||||
let setReq = store.put({ settingName: name, defaultValue: defaultValue, userValue: value });
|
|
||||||
|
|
||||||
setReq.onsuccess = function() {
|
|
||||||
lock._isBusy = false;
|
|
||||||
lock._open = true;
|
|
||||||
lock.callHandle(callback, name, value);
|
|
||||||
Services.obs.notifyObservers(lock, "mozsettings-changed", JSON.stringify({
|
|
||||||
key: name,
|
|
||||||
value: value,
|
|
||||||
message: message
|
|
||||||
}));
|
|
||||||
lock._open = false;
|
|
||||||
lock.process();
|
|
||||||
};
|
|
||||||
|
|
||||||
setReq.onerror = function(event) {
|
|
||||||
lock._isBusy = false;
|
|
||||||
lock.callError(callback, event.target.errorMessage);
|
|
||||||
lock.process();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
checkKeyRequest.onerror = function(event) {
|
|
||||||
lock._isBusy = false;
|
|
||||||
lock.callError(callback, event.target.errorMessage);
|
|
||||||
lock.process();
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case "get":
|
|
||||||
let getReq = store.mozGetAll(name);
|
|
||||||
getReq.onsuccess = function(event) {
|
|
||||||
if (DEBUG) {
|
|
||||||
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) {
|
|
||||||
if (DEBUG) debug("Warning: overloaded setting:" + name);
|
|
||||||
}
|
|
||||||
let result = event.target.result[0];
|
|
||||||
let value = result.userValue !== undefined
|
|
||||||
? result.userValue
|
|
||||||
: result.defaultValue;
|
|
||||||
lock.callHandle(callback, name, value);
|
|
||||||
} else {
|
|
||||||
lock.callHandle(callback, name, null);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (DEBUG) debug("no callback defined!");
|
|
||||||
}
|
|
||||||
this._open = false;
|
|
||||||
}.bind(lock);
|
|
||||||
getReq.onerror = function error(event) {
|
|
||||||
lock.callError(callback, event.target.errorMessage);
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lock._open = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
createTransactionAndProcess: function() {
|
|
||||||
if (this._settingsService._settingsDB._db) {
|
|
||||||
let lock;
|
|
||||||
while (lock = this._settingsService._locks.dequeue()) {
|
|
||||||
if (!lock._transaction) {
|
|
||||||
lock._transaction = lock._settingsService._settingsDB._db.transaction(SETTINGSSTORE_NAME, "readwrite");
|
|
||||||
if (lock._transactionCallback) {
|
|
||||||
lock._transaction.oncomplete = lock.callTransactionHandle.bind(lock);
|
|
||||||
lock._transaction.onabort = function(event) {
|
|
||||||
let message = '';
|
|
||||||
if (event.target.error) {
|
|
||||||
message = event.target.error.name + ': ' + event.target.error.message;
|
|
||||||
}
|
|
||||||
this.callAbort(lock._transactionCallback.handleAbort, message);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!lock._isBusy) {
|
|
||||||
lock.process();
|
|
||||||
} else {
|
|
||||||
this._settingsService._locks.enqueue(lock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!this._requests.isEmpty() && !this._isBusy) {
|
|
||||||
this.process();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
get: function get(aName, aCallback) {
|
|
||||||
if (DEBUG) debug("get: " + aName + ", " + aCallback);
|
|
||||||
this._requests.enqueue({ callback: aCallback, intent:"get", name: aName });
|
|
||||||
this.createTransactionAndProcess();
|
|
||||||
},
|
|
||||||
|
|
||||||
set: function set(aName, aValue, aCallback, aMessage) {
|
|
||||||
debug("set: " + aName + ": " + JSON.stringify(aValue));
|
|
||||||
if (aMessage === undefined)
|
|
||||||
aMessage = null;
|
|
||||||
this._requests.enqueue({ callback: aCallback,
|
|
||||||
intent: "set",
|
|
||||||
name: aName,
|
|
||||||
value: this._settingsService._settingsDB.prepareValue(aValue),
|
|
||||||
message: aMessage });
|
|
||||||
this.createTransactionAndProcess();
|
|
||||||
},
|
|
||||||
|
|
||||||
classID : SETTINGSSERVICELOCK_CID,
|
classID : SETTINGSSERVICELOCK_CID,
|
||||||
QueryInterface : XPCOMUtils.generateQI([nsISettingsServiceLock])
|
QueryInterface : XPCOMUtils.generateQI([nsISettingsServiceLock])
|
||||||
};
|
};
|
||||||
@ -222,34 +214,18 @@ const SETTINGSSERVICE_CID = Components.ID("{f656f0c0-f776-11e1-a21f-08002
|
|||||||
|
|
||||||
function SettingsService()
|
function SettingsService()
|
||||||
{
|
{
|
||||||
debug("settingsService Constructor");
|
if (DEBUG) debug("settingsService Constructor");
|
||||||
this._locks = new Queue();
|
|
||||||
this._settingsDB = new SettingsDB();
|
|
||||||
this._settingsDB.init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsService.prototype = {
|
SettingsService.prototype = {
|
||||||
|
|
||||||
nextTick: function nextTick(aCallback, thisObj) {
|
|
||||||
if (thisObj)
|
|
||||||
aCallback = aCallback.bind(thisObj);
|
|
||||||
|
|
||||||
Services.tm.currentThread.dispatch(aCallback, Ci.nsIThread.DISPATCH_NORMAL);
|
|
||||||
},
|
|
||||||
|
|
||||||
createLock: function createLock(aCallback) {
|
createLock: function createLock(aCallback) {
|
||||||
var lock = new SettingsServiceLock(this, aCallback);
|
var lock = new SettingsServiceLock(this, aCallback);
|
||||||
this._locks.enqueue(lock);
|
|
||||||
this._settingsDB.ensureDB(
|
|
||||||
function() { lock.createTransactionAndProcess(); },
|
|
||||||
function() { dump("SettingsService failed to open DB!\n"); }
|
|
||||||
);
|
|
||||||
this.nextTick(function() { this._open = false; }, lock);
|
|
||||||
return lock;
|
return lock;
|
||||||
},
|
},
|
||||||
|
|
||||||
classID : SETTINGSSERVICE_CID,
|
classID : SETTINGSSERVICE_CID,
|
||||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsISettingsService])
|
QueryInterface : XPCOMUtils.generateQI([Ci.nsISettingsService])
|
||||||
}
|
};
|
||||||
|
|
||||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SettingsService, SettingsServiceLock])
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SettingsService, SettingsServiceLock]);
|
||||||
|
Loading…
Reference in New Issue
Block a user