Bumping gaia.json for 2 gaia revision(s) a=gaia-bump
[gecko.git] / dom / settings / SettingsService.js
blob9f71d50adc63316eb4c52378bc5d9f90bfe5210a
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 "use strict";
7 const Ci = Components.interfaces;
8 const Cu = Components.utils;
10 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
11 Cu.import("resource://gre/modules/Services.jsm");
12 Cu.import('resource://gre/modules/SettingsRequestManager.jsm');
14 /* static functions */
15 let DEBUG = false;
16 let VERBOSE = false;
18 try {
19   DEBUG   =
20     Services.prefs.getBoolPref("dom.mozSettings.SettingsService.debug.enabled");
21   VERBOSE =
22     Services.prefs.getBoolPref("dom.mozSettings.SettingsService.verbose.enabled");
23 } catch (ex) { }
25 function debug(s) {
26   dump("-*- SettingsService: " + s + "\n");
29 XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
30                                    "@mozilla.org/uuid-generator;1",
31                                    "nsIUUIDGenerator");
32 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
33                                    "@mozilla.org/childprocessmessagemanager;1",
34                                    "nsIMessageSender");
36 const nsIClassInfo            = Ci.nsIClassInfo;
38 const SETTINGSSERVICELOCK_CONTRACTID = "@mozilla.org/settingsServiceLock;1";
39 const SETTINGSSERVICELOCK_CID        = Components.ID("{d7a395a0-e292-11e1-834e-1761d57f5f99}");
40 const nsISettingsServiceLock         = Ci.nsISettingsServiceLock;
42 function makeSettingsServiceRequest(aCallback, aName, aValue) {
43   return {
44     callback: aCallback,
45     name: aName,
46     value: aValue
47   };
50 function SettingsServiceLock(aSettingsService, aTransactionCallback) {
51   if (VERBOSE) debug("settingsServiceLock constr!");
52   this._open = true;
53   this._settingsService = aSettingsService;
54   this._id = uuidgen.generateUUID().toString();
55   this._transactionCallback = aTransactionCallback;
56   this._requests = {};
57   let closeHelper = function() {
58     if (VERBOSE) debug("closing lock " + this._id);
59     this._open = false;
60     this.runOrFinalizeQueries();
61   }.bind(this);
63   let msgs =   ["Settings:Get:OK", "Settings:Get:KO",
64                 "Settings:Clear:OK", "Settings:Clear:KO",
65                 "Settings:Set:OK", "Settings:Set:KO",
66                 "Settings:Finalize:OK", "Settings:Finalize:KO"];
68   for (let msg in msgs) {
69     cpmm.addMessageListener(msgs[msg], this);
70   }
72   cpmm.sendAsyncMessage("Settings:CreateLock", {lockID: this._id, isServiceLock: true}, undefined, Services.scriptSecurityManager.getSystemPrincipal());
73   Services.tm.currentThread.dispatch(closeHelper, Ci.nsIThread.DISPATCH_NORMAL);
76 SettingsServiceLock.prototype = {
77   get closed() {
78     return !this._open;
79   },
81   runOrFinalizeQueries: function() {
82     if (!this._requests || Object.keys(this._requests).length == 0) {
83       cpmm.sendAsyncMessage("Settings:Finalize", {lockID: this._id}, undefined, Services.scriptSecurityManager.getSystemPrincipal());
84     } else {
85       cpmm.sendAsyncMessage("Settings:Run", {lockID: this._id}, undefined, Services.scriptSecurityManager.getSystemPrincipal());
86     }
87   },
89   receiveMessage: function(aMessage) {
91     let msg = aMessage.data;
92     // SettingsRequestManager broadcasts changes to all locks in the child. If
93     // our lock isn't being addressed, just return.
94     if(msg.lockID != this._id) {
95       return;
96     }
97     if (VERBOSE) debug("receiveMessage (" + this._id + "): " + aMessage.name);
98     // Finalizing a transaction does not return a request ID since we are
99     // supposed to fire callbacks.
100     if (!msg.requestID) {
101       switch (aMessage.name) {
102         case "Settings:Finalize:OK":
103           if (VERBOSE) debug("Lock finalize ok!");
104           this.callTransactionHandle();
105           break;
106         case "Settings:Finalize:KO":
107           if (DEBUG) debug("Lock finalize failed!");
108           this.callAbort();
109           break;
110         default:
111           if (DEBUG) debug("Message type " + aMessage.name + " is missing a requestID");
112       }
113       return;
114     }
116     let req = this._requests[msg.requestID];
117     if (!req) {
118       if (DEBUG) debug("Matching request not found.");
119       return;
120     }
121     delete this._requests[msg.requestID];
122     switch (aMessage.name) {
123       case "Settings:Get:OK":
124         this._open = true;
125         let settings_names = Object.keys(msg.settings);
126         if (settings_names.length > 0) {
127           let name = settings_names[0];        
128           if (DEBUG && settings_names.length > 1) {
129             debug("Warning: overloaded setting:" + name);
130           }
131           let result = msg.settings[name];
132           this.callHandle(req.callback, name, result);
133         } else {
134           this.callHandle(req.callback, req.name, null);
135         }
136         this._open = false;
137         break;
138       case "Settings:Set:OK":
139         this._open = true;
140         // We don't pass values back from sets in SettingsManager...
141         this.callHandle(req.callback, req.name, req.value);
142         this._open = false;
143         break;
144       case "Settings:Get:KO":
145       case "Settings:Set:KO":
146         if (DEBUG) debug("error:" + msg.errorMsg);
147         this.callError(req.callback, msg.error);
148         break;
149       default:
150         if (DEBUG) debug("Wrong message: " + aMessage.name);
151     }
152     this.runOrFinalizeQueries();
153   },
155   get: function get(aName, aCallback) {
156     if (VERBOSE) debug("get (" + this._id + "): " + aName);
157     if (!this._open) {
158       dump("Settings lock not open!\n");
159       throw Components.results.NS_ERROR_ABORT;
160     }
161     let reqID = uuidgen.generateUUID().toString();
162     this._requests[reqID] = makeSettingsServiceRequest(aCallback, aName);
163     cpmm.sendAsyncMessage("Settings:Get", {requestID: reqID,
164                                            lockID: this._id,
165                                            name: aName},
166                                            undefined,
167                                            Services.scriptSecurityManager.getSystemPrincipal());
168   },
170   set: function set(aName, aValue, aCallback) {
171     if (VERBOSE) debug("set: " + aName + " " + aValue);
172     if (!this._open) {
173       throw "Settings lock not open";
174     }
175     let reqID = uuidgen.generateUUID().toString();
176     this._requests[reqID] = makeSettingsServiceRequest(aCallback, aName, aValue);
177     let settings = {};
178     settings[aName] = aValue;
179     cpmm.sendAsyncMessage("Settings:Set", {requestID: reqID,
180                                            lockID: this._id,
181                                            settings: settings},
182                                            undefined,
183                                            Services.scriptSecurityManager.getSystemPrincipal());
184   },
186   callHandle: function callHandle(aCallback, aName, aValue) {
187     try {
188       aCallback ? aCallback.handle(aName, aValue) : null;
189     } catch (e) {
190       dump("settings 'handle' callback threw an exception, dropping: " + e + "\n");
191     }
192   },
194   callAbort: function callAbort(aCallback, aMessage) {
195     try {
196       aCallback ? aCallback.handleAbort(aMessage) : null;
197     } catch (e) {
198       dump("settings 'abort' callback threw an exception, dropping: " + e + "\n");
199     }
200   },
202   callError: function callError(aCallback, aMessage) {
203     try {
204       aCallback ? aCallback.handleError(aMessage) : null;
205     } catch (e) {
206       dump("settings 'error' callback threw an exception, dropping: " + e + "\n");
207     }
208   },
210   callTransactionHandle: function callTransactionHandle() {
211     try {
212       this._transactionCallback ? this._transactionCallback.handle() : null;
213     } catch (e) {
214       dump("settings 'Transaction handle' callback threw an exception, dropping: " + e + "\n");
215     }
216   },
218   classID : SETTINGSSERVICELOCK_CID,
219   QueryInterface : XPCOMUtils.generateQI([nsISettingsServiceLock])
222 const SETTINGSSERVICE_CID        = Components.ID("{f656f0c0-f776-11e1-a21f-0800200c9a66}");
224 function SettingsService()
226   if (VERBOSE) debug("settingsService Constructor");
229 SettingsService.prototype = {
231   createLock: function createLock(aCallback) {
232     var lock = new SettingsServiceLock(this, aCallback);
233     return lock;
234   },
236   classID : SETTINGSSERVICE_CID,
237   QueryInterface : XPCOMUtils.generateQI([Ci.nsISettingsService])
240 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SettingsService, SettingsServiceLock]);