|
1 /* Copyright 2012 Mozilla Foundation and Mozilla contributors |
|
2 * |
|
3 * Licensed under the Apache License, Version 2.0 (the "License"); |
|
4 * you may not use this file except in compliance with the License. |
|
5 * You may obtain a copy of the License at |
|
6 * |
|
7 * http://www.apache.org/licenses/LICENSE-2.0 |
|
8 * |
|
9 * Unless required by applicable law or agreed to in writing, software |
|
10 * distributed under the License is distributed on an "AS IS" BASIS, |
|
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
12 * See the License for the specific language governing permissions and |
|
13 * limitations under the License. |
|
14 */ |
|
15 |
|
16 /* Copyright © 2013, Deutsche Telekom, Inc. */ |
|
17 |
|
18 "use strict"; |
|
19 |
|
20 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; |
|
21 |
|
22 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
23 Cu.import("resource://gre/modules/Services.jsm"); |
|
24 |
|
25 let NFC = {}; |
|
26 Cu.import("resource://gre/modules/nfc_consts.js", NFC); |
|
27 |
|
28 Cu.import("resource://gre/modules/systemlibs.js"); |
|
29 const NFC_ENABLED = libcutils.property_get("ro.moz.nfc.enabled", "false") === "true"; |
|
30 |
|
31 // set to true in nfc_consts.js to see debug messages |
|
32 let DEBUG = NFC.DEBUG_NFC; |
|
33 |
|
34 let debug; |
|
35 if (DEBUG) { |
|
36 debug = function (s) { |
|
37 dump("-*- Nfc: " + s + "\n"); |
|
38 }; |
|
39 } else { |
|
40 debug = function (s) {}; |
|
41 } |
|
42 |
|
43 const NFC_CONTRACTID = "@mozilla.org/nfc;1"; |
|
44 const NFC_CID = |
|
45 Components.ID("{2ff24790-5e74-11e1-b86c-0800200c9a66}"); |
|
46 |
|
47 const NFC_IPC_MSG_NAMES = [ |
|
48 "NFC:SetSessionToken" |
|
49 ]; |
|
50 |
|
51 const NFC_IPC_READ_PERM_MSG_NAMES = [ |
|
52 "NFC:ReadNDEF", |
|
53 "NFC:GetDetailsNDEF", |
|
54 "NFC:Connect", |
|
55 "NFC:Close", |
|
56 ]; |
|
57 |
|
58 const NFC_IPC_WRITE_PERM_MSG_NAMES = [ |
|
59 "NFC:WriteNDEF", |
|
60 "NFC:MakeReadOnlyNDEF", |
|
61 "NFC:SendFile", |
|
62 "NFC:RegisterPeerTarget", |
|
63 "NFC:UnregisterPeerTarget" |
|
64 ]; |
|
65 |
|
66 const NFC_IPC_MANAGER_PERM_MSG_NAMES = [ |
|
67 "NFC:CheckP2PRegistration", |
|
68 "NFC:NotifyUserAcceptedP2P", |
|
69 "NFC:NotifySendFileStatus", |
|
70 "NFC:StartPoll", |
|
71 "NFC:StopPoll", |
|
72 "NFC:PowerOff" |
|
73 ]; |
|
74 |
|
75 XPCOMUtils.defineLazyServiceGetter(this, "ppmm", |
|
76 "@mozilla.org/parentprocessmessagemanager;1", |
|
77 "nsIMessageBroadcaster"); |
|
78 XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger", |
|
79 "@mozilla.org/system-message-internal;1", |
|
80 "nsISystemMessagesInternal"); |
|
81 XPCOMUtils.defineLazyServiceGetter(this, "gSystemWorkerManager", |
|
82 "@mozilla.org/telephony/system-worker-manager;1", |
|
83 "nsISystemWorkerManager"); |
|
84 XPCOMUtils.defineLazyServiceGetter(this, "UUIDGenerator", |
|
85 "@mozilla.org/uuid-generator;1", |
|
86 "nsIUUIDGenerator"); |
|
87 XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () { |
|
88 return { |
|
89 QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener, |
|
90 Ci.nsIObserver]), |
|
91 |
|
92 nfc: null, |
|
93 |
|
94 // Manage message targets in terms of sessionToken. Only the authorized and |
|
95 // registered contents can receive related messages. |
|
96 targetsBySessionTokens: {}, |
|
97 sessionTokens: [], |
|
98 |
|
99 // Manage registered Peer Targets |
|
100 peerTargetsMap: {}, |
|
101 currentPeerAppId: null, |
|
102 |
|
103 init: function init(nfc) { |
|
104 this.nfc = nfc; |
|
105 |
|
106 Services.obs.addObserver(this, NFC.TOPIC_XPCOM_SHUTDOWN, false); |
|
107 this._registerMessageListeners(); |
|
108 }, |
|
109 |
|
110 _shutdown: function _shutdown() { |
|
111 this.nfc = null; |
|
112 |
|
113 Services.obs.removeObserver(this, NFC.TOPIC_XPCOM_SHUTDOWN); |
|
114 this._unregisterMessageListeners(); |
|
115 }, |
|
116 |
|
117 _registerMessageListeners: function _registerMessageListeners() { |
|
118 ppmm.addMessageListener("child-process-shutdown", this); |
|
119 |
|
120 for (let msgname of NFC_IPC_MSG_NAMES) { |
|
121 ppmm.addMessageListener(msgname, this); |
|
122 } |
|
123 |
|
124 for (let msgname of NFC_IPC_READ_PERM_MSG_NAMES) { |
|
125 ppmm.addMessageListener(msgname, this); |
|
126 } |
|
127 |
|
128 for (let msgname of NFC_IPC_WRITE_PERM_MSG_NAMES) { |
|
129 ppmm.addMessageListener(msgname, this); |
|
130 } |
|
131 |
|
132 for (let msgname of NFC_IPC_MANAGER_PERM_MSG_NAMES) { |
|
133 ppmm.addMessageListener(msgname, this); |
|
134 } |
|
135 }, |
|
136 |
|
137 _unregisterMessageListeners: function _unregisterMessageListeners() { |
|
138 ppmm.removeMessageListener("child-process-shutdown", this); |
|
139 |
|
140 for (let msgname of NFC_IPC_MSG_NAMES) { |
|
141 ppmm.removeMessageListener(msgname, this); |
|
142 } |
|
143 |
|
144 for (let msgname of NFC_IPC_READ_PERM_MSG_NAMES) { |
|
145 ppmm.removeMessageListener(msgname, this); |
|
146 } |
|
147 |
|
148 for (let msgname of NFC_IPC_WRITE_PERM_MSG_NAMES) { |
|
149 ppmm.removeMessageListener(msgname, this); |
|
150 } |
|
151 |
|
152 for (let msgname of NFC_IPC_MANAGER_PERM_MSG_NAMES) { |
|
153 ppmm.removeMessageListener(msgname, this); |
|
154 } |
|
155 |
|
156 ppmm = null; |
|
157 }, |
|
158 |
|
159 _registerMessageTarget: function _registerMessageTarget(sessionToken, target) { |
|
160 let targets = this.targetsBySessionTokens[sessionToken]; |
|
161 if (!targets) { |
|
162 targets = this.targetsBySessionTokens[sessionToken] = []; |
|
163 let list = this.sessionTokens; |
|
164 if (list.indexOf(sessionToken) == -1) { |
|
165 list.push(sessionToken); |
|
166 } |
|
167 } |
|
168 |
|
169 if (targets.indexOf(target) != -1) { |
|
170 debug("Already registered this target!"); |
|
171 return; |
|
172 } |
|
173 |
|
174 targets.push(target); |
|
175 debug("Registered :" + sessionToken + " target: " + target); |
|
176 }, |
|
177 |
|
178 _unregisterMessageTarget: function _unregisterMessageTarget(sessionToken, target) { |
|
179 if (sessionToken == null) { |
|
180 // Unregister the target for every sessionToken when no sessionToken is specified. |
|
181 for (let session of this.sessionTokens) { |
|
182 this._unregisterMessageTarget(session, target); |
|
183 } |
|
184 return; |
|
185 } |
|
186 |
|
187 // Unregister the target for a specified sessionToken. |
|
188 let targets = this.targetsBySessionTokens[sessionToken]; |
|
189 if (!targets) { |
|
190 return; |
|
191 } |
|
192 |
|
193 if (target == null) { |
|
194 debug("Unregistered all targets for the " + sessionToken + " targets: " + targets); |
|
195 targets = []; |
|
196 let list = this.sessionTokens; |
|
197 if (sessionToken !== null) { |
|
198 let index = list.indexOf(sessionToken); |
|
199 if (index > -1) { |
|
200 list.splice(index, 1); |
|
201 } |
|
202 } |
|
203 return; |
|
204 } |
|
205 |
|
206 let index = targets.indexOf(target); |
|
207 if (index != -1) { |
|
208 targets.splice(index, 1); |
|
209 } |
|
210 }, |
|
211 |
|
212 _sendTargetMessage: function _sendTargetMessage(sessionToken, message, options) { |
|
213 let targets = this.targetsBySessionTokens[sessionToken]; |
|
214 if (!targets) { |
|
215 return; |
|
216 } |
|
217 |
|
218 for (let target of targets) { |
|
219 target.sendAsyncMessage(message, options); |
|
220 } |
|
221 }, |
|
222 |
|
223 registerPeerTarget: function registerPeerTarget(msg) { |
|
224 let appInfo = msg.json; |
|
225 // Sanity check on PeerEvent |
|
226 if (!this.isValidPeerEvent(appInfo.event)) { |
|
227 return; |
|
228 } |
|
229 let targets = this.peerTargetsMap; |
|
230 let targetInfo = targets[appInfo.appId]; |
|
231 // If the application Id is already registered |
|
232 if (targetInfo) { |
|
233 // If the event is not registered |
|
234 if (targetInfo.event !== appInfo.event) { |
|
235 // Update the event field ONLY |
|
236 targetInfo.event |= appInfo.event; |
|
237 } |
|
238 // Otherwise event is already registered, return! |
|
239 return; |
|
240 } |
|
241 // Target not registered yet! Add to the target map |
|
242 |
|
243 // Registered targetInfo target consists of 2 fields (values) |
|
244 // target : Target to notify the right content for peer notifications |
|
245 // event : NFC_PEER_EVENT_READY (0x01) Or NFC_PEER_EVENT_LOST (0x02) |
|
246 let newTargetInfo = { target : msg.target, |
|
247 event : appInfo.event }; |
|
248 targets[appInfo.appId] = newTargetInfo; |
|
249 }, |
|
250 |
|
251 unregisterPeerTarget: function unregisterPeerTarget(msg) { |
|
252 let appInfo = msg.json; |
|
253 // Sanity check on PeerEvent |
|
254 if (!this.isValidPeerEvent(appInfo.event)) { |
|
255 return; |
|
256 } |
|
257 let targets = this.peerTargetsMap; |
|
258 let targetInfo = targets[appInfo.appId]; |
|
259 if (targetInfo) { |
|
260 // Application Id registered and the event exactly matches. |
|
261 if (targetInfo.event === appInfo.event) { |
|
262 // Remove the target from the list of registered targets |
|
263 delete targets[appInfo.appId] |
|
264 } |
|
265 else { |
|
266 // Otherwise, update the event field ONLY, by removing the event flag |
|
267 targetInfo.event &= ~appInfo.event; |
|
268 } |
|
269 } |
|
270 }, |
|
271 |
|
272 removePeerTarget: function removePeerTarget(target) { |
|
273 let targets = this.peerTargetsMap; |
|
274 Object.keys(targets).forEach((appId) => { |
|
275 let targetInfo = targets[appId]; |
|
276 if (targetInfo && targetInfo.target === target) { |
|
277 // Remove the target from the list of registered targets |
|
278 delete targets[appId]; |
|
279 } |
|
280 }); |
|
281 }, |
|
282 |
|
283 isRegisteredP2PTarget: function isRegisteredP2PTarget(appId, event) { |
|
284 let targetInfo = this.peerTargetsMap[appId]; |
|
285 // Check if it is a registered target for the 'event' |
|
286 return ((targetInfo != null) && (targetInfo.event & event !== 0)); |
|
287 }, |
|
288 |
|
289 notifyPeerEvent: function notifyPeerEvent(appId, event) { |
|
290 let targetInfo = this.peerTargetsMap[appId]; |
|
291 // Check if the application id is a registeredP2PTarget |
|
292 if (this.isRegisteredP2PTarget(appId, event)) { |
|
293 targetInfo.target.sendAsyncMessage("NFC:PeerEvent", { |
|
294 event: event, |
|
295 sessionToken: this.nfc.sessionTokenMap[this.nfc._currentSessionId] |
|
296 }); |
|
297 return; |
|
298 } |
|
299 debug("Application ID : " + appId + " is not a registered target" + |
|
300 "for the event " + event + " notification"); |
|
301 }, |
|
302 |
|
303 isValidPeerEvent: function isValidPeerEvent(event) { |
|
304 // Valid values : 0x01, 0x02 Or 0x03 |
|
305 return ((event === NFC.NFC_PEER_EVENT_READY) || |
|
306 (event === NFC.NFC_PEER_EVENT_LOST) || |
|
307 (event === (NFC.NFC_PEER_EVENT_READY | NFC.NFC_PEER_EVENT_LOST))); |
|
308 }, |
|
309 |
|
310 /** |
|
311 * nsIMessageListener interface methods. |
|
312 */ |
|
313 |
|
314 receiveMessage: function receiveMessage(msg) { |
|
315 debug("Received '" + msg.name + "' message from content process"); |
|
316 if (msg.name == "child-process-shutdown") { |
|
317 // By the time we receive child-process-shutdown, the child process has |
|
318 // already forgotten its permissions so we need to unregister the target |
|
319 // for every permission. |
|
320 this._unregisterMessageTarget(null, msg.target); |
|
321 this.removePeerTarget(msg.target); |
|
322 return null; |
|
323 } |
|
324 |
|
325 if (NFC_IPC_MSG_NAMES.indexOf(msg.name) != -1) { |
|
326 // Do nothing. |
|
327 } else if (NFC_IPC_READ_PERM_MSG_NAMES.indexOf(msg.name) != -1) { |
|
328 if (!msg.target.assertPermission("nfc-read")) { |
|
329 debug("Nfc message " + msg.name + |
|
330 " from a content process with no 'nfc-read' privileges."); |
|
331 return null; |
|
332 } |
|
333 } else if (NFC_IPC_WRITE_PERM_MSG_NAMES.indexOf(msg.name) != -1) { |
|
334 if (!msg.target.assertPermission("nfc-write")) { |
|
335 debug("Nfc Peer message " + msg.name + |
|
336 " from a content process with no 'nfc-write' privileges."); |
|
337 return null; |
|
338 } |
|
339 } else if (NFC_IPC_MANAGER_PERM_MSG_NAMES.indexOf(msg.name) != -1) { |
|
340 if (!msg.target.assertPermission("nfc-manager")) { |
|
341 debug("NFC message " + message.name + |
|
342 " from a content process with no 'nfc-manager' privileges."); |
|
343 return null; |
|
344 } |
|
345 } else { |
|
346 debug("Ignoring unknown message type: " + msg.name); |
|
347 return null; |
|
348 } |
|
349 |
|
350 switch (msg.name) { |
|
351 case "NFC:SetSessionToken": |
|
352 this._registerMessageTarget(this.nfc.sessionTokenMap[this.nfc._currentSessionId], msg.target); |
|
353 debug("Registering target for this SessionToken : " + |
|
354 this.nfc.sessionTokenMap[this.nfc._currentSessionId]); |
|
355 return null; |
|
356 case "NFC:RegisterPeerTarget": |
|
357 this.registerPeerTarget(msg); |
|
358 return null; |
|
359 case "NFC:UnregisterPeerTarget": |
|
360 this.unregisterPeerTarget(msg); |
|
361 return null; |
|
362 case "NFC:CheckP2PRegistration": |
|
363 // Check if the application id is a valid registered target. |
|
364 // (It should have registered for NFC_PEER_EVENT_READY). |
|
365 let isRegistered = this.isRegisteredP2PTarget(msg.json.appId, |
|
366 NFC.NFC_PEER_EVENT_READY); |
|
367 // Remember the current AppId if registered. |
|
368 this.currentPeerAppId = (isRegistered) ? msg.json.appId : null; |
|
369 let status = (isRegistered) ? NFC.GECKO_NFC_ERROR_SUCCESS : |
|
370 NFC.GECKO_NFC_ERROR_GENERIC_FAILURE; |
|
371 // Notify the content process immediately of the status |
|
372 msg.target.sendAsyncMessage(msg.name + "Response", { |
|
373 status: status, |
|
374 requestId: msg.json.requestId |
|
375 }); |
|
376 return null; |
|
377 case "NFC:NotifyUserAcceptedP2P": |
|
378 // Notify the 'NFC_PEER_EVENT_READY' since user has acknowledged |
|
379 this.notifyPeerEvent(msg.json.appId, NFC.NFC_PEER_EVENT_READY); |
|
380 return null; |
|
381 case "NFC:NotifySendFileStatus": |
|
382 // Upon receiving the status of sendFile operation, send the response |
|
383 // to appropriate content process. |
|
384 this.sendNfcResponseMessage(msg.name + "Response", msg.json); |
|
385 return null; |
|
386 default: |
|
387 return this.nfc.receiveMessage(msg); |
|
388 } |
|
389 }, |
|
390 |
|
391 /** |
|
392 * nsIObserver interface methods. |
|
393 */ |
|
394 |
|
395 observe: function observe(subject, topic, data) { |
|
396 switch (topic) { |
|
397 case NFC.TOPIC_XPCOM_SHUTDOWN: |
|
398 this._shutdown(); |
|
399 break; |
|
400 } |
|
401 }, |
|
402 |
|
403 sendNfcResponseMessage: function sendNfcResponseMessage(message, data) { |
|
404 this._sendTargetMessage(this.nfc.sessionTokenMap[this.nfc._currentSessionId], message, data); |
|
405 }, |
|
406 }; |
|
407 }); |
|
408 |
|
409 function Nfc() { |
|
410 debug("Starting Worker"); |
|
411 this.worker = new ChromeWorker("resource://gre/modules/nfc_worker.js"); |
|
412 this.worker.onerror = this.onerror.bind(this); |
|
413 this.worker.onmessage = this.onmessage.bind(this); |
|
414 |
|
415 gMessageManager.init(this); |
|
416 |
|
417 // Maps sessionId (that are generated from nfcd) with a unique guid : 'SessionToken' |
|
418 this.sessionTokenMap = {}; |
|
419 this.targetsByRequestId = {}; |
|
420 |
|
421 gSystemWorkerManager.registerNfcWorker(this.worker); |
|
422 } |
|
423 |
|
424 Nfc.prototype = { |
|
425 |
|
426 classID: NFC_CID, |
|
427 classInfo: XPCOMUtils.generateCI({classID: NFC_CID, |
|
428 classDescription: "Nfc", |
|
429 interfaces: [Ci.nsIWorkerHolder]}), |
|
430 |
|
431 QueryInterface: XPCOMUtils.generateQI([Ci.nsIWorkerHolder]), |
|
432 |
|
433 _currentSessionId: null, |
|
434 |
|
435 powerLevel: NFC.NFC_POWER_LEVEL_UNKNOWN, |
|
436 |
|
437 onerror: function onerror(event) { |
|
438 debug("Got an error: " + event.filename + ":" + |
|
439 event.lineno + ": " + event.message + "\n"); |
|
440 event.preventDefault(); |
|
441 }, |
|
442 |
|
443 /** |
|
444 * Send arbitrary message to worker. |
|
445 * |
|
446 * @param nfcMessageType |
|
447 * A text message type. |
|
448 * @param message [optional] |
|
449 * An optional message object to send. |
|
450 */ |
|
451 sendToWorker: function sendToWorker(nfcMessageType, message) { |
|
452 message = message || {}; |
|
453 message.type = nfcMessageType; |
|
454 this.worker.postMessage(message); |
|
455 }, |
|
456 |
|
457 /** |
|
458 * Send Error response to content. |
|
459 * |
|
460 * @param message |
|
461 * An nsIMessageListener's message parameter. |
|
462 */ |
|
463 sendNfcErrorResponse: function sendNfcErrorResponse(message) { |
|
464 if (!message.target) { |
|
465 return; |
|
466 } |
|
467 |
|
468 let nfcMsgType = message.name + "Response"; |
|
469 message.target.sendAsyncMessage(nfcMsgType, { |
|
470 sessionId: message.json.sessionToken, |
|
471 requestId: message.json.requestId, |
|
472 status: NFC.GECKO_NFC_ERROR_GENERIC_FAILURE |
|
473 }); |
|
474 }, |
|
475 |
|
476 /** |
|
477 * Process the incoming message from the NFC worker |
|
478 */ |
|
479 onmessage: function onmessage(event) { |
|
480 let message = event.data; |
|
481 debug("Received message from NFC worker: " + JSON.stringify(message)); |
|
482 |
|
483 switch (message.type) { |
|
484 case "techDiscovered": |
|
485 this._currentSessionId = message.sessionId; |
|
486 |
|
487 // Check if the session token already exists. If exists, continue to use the same one. |
|
488 // If not, generate a new token. |
|
489 if (!this.sessionTokenMap[this._currentSessionId]) { |
|
490 this.sessionTokenMap[this._currentSessionId] = UUIDGenerator.generateUUID().toString(); |
|
491 } |
|
492 // Update the upper layers with a session token (alias) |
|
493 message.sessionToken = this.sessionTokenMap[this._currentSessionId]; |
|
494 // Do not expose the actual session to the content |
|
495 delete message.sessionId; |
|
496 |
|
497 gSystemMessenger.broadcastMessage("nfc-manager-tech-discovered", message); |
|
498 break; |
|
499 case "techLost": |
|
500 gMessageManager._unregisterMessageTarget(this.sessionTokenMap[this._currentSessionId], null); |
|
501 |
|
502 // Update the upper layers with a session token (alias) |
|
503 message.sessionToken = this.sessionTokenMap[this._currentSessionId]; |
|
504 // Do not expose the actual session to the content |
|
505 delete message.sessionId; |
|
506 |
|
507 gSystemMessenger.broadcastMessage("nfc-manager-tech-lost", message); |
|
508 // Notify 'PeerLost' to appropriate registered target, if any |
|
509 gMessageManager.notifyPeerEvent(this.currentPeerAppId, NFC.NFC_PEER_EVENT_LOST); |
|
510 delete this.sessionTokenMap[this._currentSessionId]; |
|
511 this._currentSessionId = null; |
|
512 this.currentPeerAppId = null; |
|
513 break; |
|
514 case "ConfigResponse": |
|
515 let target = this.targetsByRequestId[message.requestId]; |
|
516 if (!target) { |
|
517 debug("No target for requestId: " + message.requestId); |
|
518 return; |
|
519 } |
|
520 delete this.targetsByRequestId[message.requestId]; |
|
521 |
|
522 if (message.status == NFC.GECKO_NFC_ERROR_SUCCESS) { |
|
523 this.powerLevel = message.powerLevel; |
|
524 } |
|
525 |
|
526 target.sendAsyncMessage("NFC:ConfigResponse", message); |
|
527 break; |
|
528 case "ConnectResponse": // Fall through. |
|
529 case "CloseResponse": |
|
530 case "GetDetailsNDEFResponse": |
|
531 case "ReadNDEFResponse": |
|
532 case "MakeReadOnlyNDEFResponse": |
|
533 case "WriteNDEFResponse": |
|
534 message.sessionToken = this.sessionTokenMap[this._currentSessionId]; |
|
535 // Do not expose the actual session to the content |
|
536 delete message.sessionId; |
|
537 gMessageManager.sendNfcResponseMessage("NFC:" + message.type, message); |
|
538 break; |
|
539 default: |
|
540 throw new Error("Don't know about this message type: " + message.type); |
|
541 } |
|
542 }, |
|
543 |
|
544 // nsINfcWorker |
|
545 worker: null, |
|
546 |
|
547 sessionTokenMap: null, |
|
548 |
|
549 targetsByRequestId: null, |
|
550 |
|
551 /** |
|
552 * Process a message from the content process. |
|
553 */ |
|
554 receiveMessage: function receiveMessage(message) { |
|
555 debug("Received '" + JSON.stringify(message) + "' message from content process"); |
|
556 |
|
557 // Handle messages without sessionToken. |
|
558 if (message.name == "NFC:StartPoll") { |
|
559 this.targetsByRequestId[message.json.requestId] = message.target; |
|
560 this.setConfig({powerLevel: NFC.NFC_POWER_LEVEL_ENABLED, |
|
561 requestId: message.json.requestId}); |
|
562 return null; |
|
563 } else if (message.name == "NFC:StopPoll") { |
|
564 this.targetsByRequestId[message.json.requestId] = message.target; |
|
565 this.setConfig({powerLevel: NFC.NFC_POWER_LEVEL_LOW, |
|
566 requestId: message.json.requestId}); |
|
567 return null; |
|
568 } else if (message.name == "NFC:PowerOff") { |
|
569 this.targetsByRequestId[message.json.requestId] = message.target; |
|
570 this.setConfig({powerLevel: NFC.NFC_POWER_LEVEL_DISABLED, |
|
571 requestId: message.json.requestId}); |
|
572 return null; |
|
573 } |
|
574 |
|
575 if (this.powerLevel != NFC.NFC_POWER_LEVEL_ENABLED) { |
|
576 debug("NFC is not enabled. current powerLevel:" + this.powerLevel); |
|
577 this.sendNfcErrorResponse(message); |
|
578 return null; |
|
579 } |
|
580 |
|
581 // Sanity check on sessionId |
|
582 if (message.json.sessionToken !== this.sessionTokenMap[this._currentSessionId]) { |
|
583 debug("Invalid Session Token: " + message.json.sessionToken + |
|
584 " Expected Session Token: " + this.sessionTokenMap[this._currentSessionId]); |
|
585 this.sendNfcErrorResponse(message); |
|
586 return null; |
|
587 } |
|
588 |
|
589 // Update the current sessionId before sending to the worker |
|
590 message.json.sessionId = this._currentSessionId; |
|
591 |
|
592 switch (message.name) { |
|
593 case "NFC:GetDetailsNDEF": |
|
594 this.sendToWorker("getDetailsNDEF", message.json); |
|
595 break; |
|
596 case "NFC:ReadNDEF": |
|
597 this.sendToWorker("readNDEF", message.json); |
|
598 break; |
|
599 case "NFC:WriteNDEF": |
|
600 this.sendToWorker("writeNDEF", message.json); |
|
601 break; |
|
602 case "NFC:MakeReadOnlyNDEF": |
|
603 this.sendToWorker("makeReadOnlyNDEF", message.json); |
|
604 break; |
|
605 case "NFC:Connect": |
|
606 this.sendToWorker("connect", message.json); |
|
607 break; |
|
608 case "NFC:Close": |
|
609 this.sendToWorker("close", message.json); |
|
610 break; |
|
611 case "NFC:SendFile": |
|
612 // Chrome process is the arbitrator / mediator between |
|
613 // system app (content process) that issued nfc 'sendFile' operation |
|
614 // and system app that handles the system message : |
|
615 // 'nfc-manager-send-file'. System app subsequently handover's |
|
616 // the data to alternate carrier's (BT / WiFi) 'sendFile' interface. |
|
617 |
|
618 // Notify system app to initiate BT send file operation |
|
619 gSystemMessenger.broadcastMessage("nfc-manager-send-file", |
|
620 message.json); |
|
621 break; |
|
622 default: |
|
623 debug("UnSupported : Message Name " + message.name); |
|
624 return null; |
|
625 } |
|
626 |
|
627 return null; |
|
628 }, |
|
629 |
|
630 setConfig: function setConfig(prop) { |
|
631 this.sendToWorker("config", prop); |
|
632 } |
|
633 }; |
|
634 |
|
635 if (NFC_ENABLED) { |
|
636 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([Nfc]); |
|
637 } |