Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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 DEBUG = false;
8 function debug(s) { dump("-*- Fallback ContactService component: " + s + "\n"); }
10 const Cu = Components.utils;
11 const Cc = Components.classes;
12 const Ci = Components.interfaces;
14 this.EXPORTED_SYMBOLS = ["ContactService"];
16 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
17 Cu.import("resource://gre/modules/Services.jsm");
18 Cu.import("resource://gre/modules/ContactDB.jsm");
19 Cu.import("resource://gre/modules/PhoneNumberUtils.jsm");
21 XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
22 "@mozilla.org/parentprocessmessagemanager;1",
23 "nsIMessageListenerManager");
26 /* all exported symbols need to be bound to this on B2G - Bug 961777 */
27 let ContactService = this.ContactService = {
28 init: function() {
29 if (DEBUG) debug("Init");
30 this._messages = ["Contacts:Find", "Contacts:GetAll", "Contacts:GetAll:SendNow",
31 "Contacts:Clear", "Contact:Save",
32 "Contact:Remove", "Contacts:RegisterForMessages",
33 "child-process-shutdown", "Contacts:GetRevision",
34 "Contacts:GetCount"];
35 this._children = [];
36 this._cursors = new Map();
37 this._messages.forEach(function(msgName) {
38 ppmm.addMessageListener(msgName, this);
39 }.bind(this));
41 this._db = new ContactDB();
42 this._db.init();
44 this.configureSubstringMatching();
46 Services.obs.addObserver(this, "profile-before-change", false);
47 Services.prefs.addObserver("ril.lastKnownSimMcc", this, false);
48 },
50 observe: function(aSubject, aTopic, aData) {
51 if (aTopic === 'profile-before-change') {
52 this._messages.forEach(function(msgName) {
53 ppmm.removeMessageListener(msgName, this);
54 }.bind(this));
55 Services.obs.removeObserver(this, "profile-before-change");
56 Services.prefs.removeObserver("dom.phonenumber.substringmatching", this);
57 ppmm = null;
58 this._messages = null;
59 if (this._db)
60 this._db.close();
61 this._db = null;
62 this._children = null;
63 this._cursors = null;
64 } else if (aTopic === 'nsPref:changed' && aData === "ril.lastKnownSimMcc") {
65 this.configureSubstringMatching();
66 }
67 },
69 configureSubstringMatching: function() {
70 let countryName = PhoneNumberUtils.getCountryName();
71 if (Services.prefs.getPrefType("dom.phonenumber.substringmatching." + countryName) == Ci.nsIPrefBranch.PREF_INT) {
72 let val = Services.prefs.getIntPref("dom.phonenumber.substringmatching." + countryName);
73 if (val) {
74 this._db.enableSubstringMatching(val);
75 return;
76 }
77 }
78 // if we got here, we dont have a substring setting
79 // for this country, so disable substring matching
80 this._db.disableSubstringMatching();
81 },
83 assertPermission: function(aMessage, aPerm) {
84 if (!aMessage.target.assertPermission(aPerm)) {
85 Cu.reportError("Contacts message " + aMessage.name +
86 " from a content process with no" + aPerm + " privileges.");
87 return false;
88 }
89 return true;
90 },
92 broadcastMessage: function broadcastMessage(aMsgName, aContent) {
93 this._children.forEach(function(msgMgr) {
94 msgMgr.sendAsyncMessage(aMsgName, aContent);
95 });
96 },
98 receiveMessage: function(aMessage) {
99 if (DEBUG) debug("receiveMessage " + aMessage.name);
100 let mm = aMessage.target;
101 let msg = aMessage.data;
103 switch (aMessage.name) {
104 case "Contacts:Find":
105 if (!this.assertPermission(aMessage, "contacts-read")) {
106 return null;
107 }
108 let result = [];
109 this._db.find(
110 function(contacts) {
111 for (let i in contacts) {
112 result.push(contacts[i]);
113 }
115 if (DEBUG) debug("result:" + JSON.stringify(result));
116 mm.sendAsyncMessage("Contacts:Find:Return:OK", {requestID: msg.requestID, contacts: result});
117 }.bind(this),
118 function(aErrorMsg) { mm.sendAsyncMessage("Contacts:Find:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this),
119 msg.options.findOptions);
120 break;
121 case "Contacts:GetAll":
122 if (!this.assertPermission(aMessage, "contacts-read")) {
123 return null;
124 }
125 let cursorList = this._cursors.get(mm);
126 if (!cursorList) {
127 cursorList = [];
128 this._cursors.set(mm, cursorList);
129 }
130 cursorList.push(msg.cursorId);
132 this._db.getAll(
133 function(aContacts) {
134 try {
135 mm.sendAsyncMessage("Contacts:GetAll:Next", {cursorId: msg.cursorId, contacts: aContacts});
136 if (aContacts === null) {
137 let cursorList = this._cursors.get(mm);
138 let index = cursorList.indexOf(msg.cursorId);
139 cursorList.splice(index, 1);
140 }
141 } catch (e) {
142 if (DEBUG) debug("Child is dead, DB should stop sending contacts");
143 throw e;
144 }
145 }.bind(this),
146 function(aErrorMsg) { mm.sendAsyncMessage("Contacts:GetAll:Return:KO", { requestID: msg.cursorId, errorMsg: aErrorMsg }); },
147 msg.findOptions, msg.cursorId);
148 break;
149 case "Contacts:GetAll:SendNow":
150 // sendNow is a no op if there isn't an existing cursor in the DB, so we
151 // don't need to assert the permission again.
152 this._db.sendNow(msg.cursorId);
153 break;
154 case "Contact:Save":
155 if (msg.options.reason === "create") {
156 if (!this.assertPermission(aMessage, "contacts-create")) {
157 return null;
158 }
159 } else {
160 if (!this.assertPermission(aMessage, "contacts-write")) {
161 return null;
162 }
163 }
164 this._db.saveContact(
165 msg.options.contact,
166 function() {
167 mm.sendAsyncMessage("Contact:Save:Return:OK", { requestID: msg.requestID, contactID: msg.options.contact.id });
168 this.broadcastMessage("Contact:Changed", { contactID: msg.options.contact.id, reason: msg.options.reason });
169 }.bind(this),
170 function(aErrorMsg) { mm.sendAsyncMessage("Contact:Save:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this)
171 );
172 break;
173 case "Contact:Remove":
174 if (!this.assertPermission(aMessage, "contacts-write")) {
175 return null;
176 }
177 this._db.removeContact(
178 msg.options.id,
179 function() {
180 mm.sendAsyncMessage("Contact:Remove:Return:OK", { requestID: msg.requestID, contactID: msg.options.id });
181 this.broadcastMessage("Contact:Changed", { contactID: msg.options.id, reason: "remove" });
182 }.bind(this),
183 function(aErrorMsg) { mm.sendAsyncMessage("Contact:Remove:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this)
184 );
185 break;
186 case "Contacts:Clear":
187 if (!this.assertPermission(aMessage, "contacts-write")) {
188 return null;
189 }
190 this._db.clear(
191 function() {
192 mm.sendAsyncMessage("Contacts:Clear:Return:OK", { requestID: msg.requestID });
193 this.broadcastMessage("Contact:Changed", { reason: "remove" });
194 }.bind(this),
195 function(aErrorMsg) {
196 mm.sendAsyncMessage("Contacts:Clear:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg });
197 }.bind(this)
198 );
199 break;
200 case "Contacts:GetRevision":
201 if (!this.assertPermission(aMessage, "contacts-read")) {
202 return null;
203 }
204 this._db.getRevision(
205 function(revision) {
206 mm.sendAsyncMessage("Contacts:Revision", {
207 requestID: msg.requestID,
208 revision: revision
209 });
210 },
211 function(aErrorMsg) {
212 mm.sendAsyncMessage("Contacts:GetRevision:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg });
213 }.bind(this)
214 );
215 break;
216 case "Contacts:GetCount":
217 if (!this.assertPermission(aMessage, "contacts-read")) {
218 return null;
219 }
220 this._db.getCount(
221 function(count) {
222 mm.sendAsyncMessage("Contacts:Count", {
223 requestID: msg.requestID,
224 count: count
225 });
226 },
227 function(aErrorMsg) {
228 mm.sendAsyncMessage("Contacts:Count:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg });
229 }.bind(this)
230 );
231 break;
232 case "Contacts:RegisterForMessages":
233 if (!aMessage.target.assertPermission("contacts-read")) {
234 return null;
235 }
236 if (DEBUG) debug("Register!");
237 if (this._children.indexOf(mm) == -1) {
238 this._children.push(mm);
239 }
240 break;
241 case "child-process-shutdown":
242 if (DEBUG) debug("Unregister");
243 let index = this._children.indexOf(mm);
244 if (index != -1) {
245 if (DEBUG) debug("Unregister index: " + index);
246 this._children.splice(index, 1);
247 }
248 cursorList = this._cursors.get(mm);
249 if (cursorList) {
250 for (let id of cursorList) {
251 this._db.clearDispatcher(id);
252 }
253 this._cursors.delete(mm);
254 }
255 break;
256 default:
257 if (DEBUG) debug("WRONG MESSAGE NAME: " + aMessage.name);
258 }
259 }
260 }
262 ContactService.init();