1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/system/gonk/Nfc.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,637 @@ 1.4 +/* Copyright 2012 Mozilla Foundation and Mozilla contributors 1.5 + * 1.6 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.7 + * you may not use this file except in compliance with the License. 1.8 + * You may obtain a copy of the License at 1.9 + * 1.10 + * http://www.apache.org/licenses/LICENSE-2.0 1.11 + * 1.12 + * Unless required by applicable law or agreed to in writing, software 1.13 + * distributed under the License is distributed on an "AS IS" BASIS, 1.14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.15 + * See the License for the specific language governing permissions and 1.16 + * limitations under the License. 1.17 + */ 1.18 + 1.19 +/* Copyright © 2013, Deutsche Telekom, Inc. */ 1.20 + 1.21 +"use strict"; 1.22 + 1.23 +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; 1.24 + 1.25 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.26 +Cu.import("resource://gre/modules/Services.jsm"); 1.27 + 1.28 +let NFC = {}; 1.29 +Cu.import("resource://gre/modules/nfc_consts.js", NFC); 1.30 + 1.31 +Cu.import("resource://gre/modules/systemlibs.js"); 1.32 +const NFC_ENABLED = libcutils.property_get("ro.moz.nfc.enabled", "false") === "true"; 1.33 + 1.34 +// set to true in nfc_consts.js to see debug messages 1.35 +let DEBUG = NFC.DEBUG_NFC; 1.36 + 1.37 +let debug; 1.38 +if (DEBUG) { 1.39 + debug = function (s) { 1.40 + dump("-*- Nfc: " + s + "\n"); 1.41 + }; 1.42 +} else { 1.43 + debug = function (s) {}; 1.44 +} 1.45 + 1.46 +const NFC_CONTRACTID = "@mozilla.org/nfc;1"; 1.47 +const NFC_CID = 1.48 + Components.ID("{2ff24790-5e74-11e1-b86c-0800200c9a66}"); 1.49 + 1.50 +const NFC_IPC_MSG_NAMES = [ 1.51 + "NFC:SetSessionToken" 1.52 +]; 1.53 + 1.54 +const NFC_IPC_READ_PERM_MSG_NAMES = [ 1.55 + "NFC:ReadNDEF", 1.56 + "NFC:GetDetailsNDEF", 1.57 + "NFC:Connect", 1.58 + "NFC:Close", 1.59 +]; 1.60 + 1.61 +const NFC_IPC_WRITE_PERM_MSG_NAMES = [ 1.62 + "NFC:WriteNDEF", 1.63 + "NFC:MakeReadOnlyNDEF", 1.64 + "NFC:SendFile", 1.65 + "NFC:RegisterPeerTarget", 1.66 + "NFC:UnregisterPeerTarget" 1.67 +]; 1.68 + 1.69 +const NFC_IPC_MANAGER_PERM_MSG_NAMES = [ 1.70 + "NFC:CheckP2PRegistration", 1.71 + "NFC:NotifyUserAcceptedP2P", 1.72 + "NFC:NotifySendFileStatus", 1.73 + "NFC:StartPoll", 1.74 + "NFC:StopPoll", 1.75 + "NFC:PowerOff" 1.76 +]; 1.77 + 1.78 +XPCOMUtils.defineLazyServiceGetter(this, "ppmm", 1.79 + "@mozilla.org/parentprocessmessagemanager;1", 1.80 + "nsIMessageBroadcaster"); 1.81 +XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger", 1.82 + "@mozilla.org/system-message-internal;1", 1.83 + "nsISystemMessagesInternal"); 1.84 +XPCOMUtils.defineLazyServiceGetter(this, "gSystemWorkerManager", 1.85 + "@mozilla.org/telephony/system-worker-manager;1", 1.86 + "nsISystemWorkerManager"); 1.87 +XPCOMUtils.defineLazyServiceGetter(this, "UUIDGenerator", 1.88 + "@mozilla.org/uuid-generator;1", 1.89 + "nsIUUIDGenerator"); 1.90 +XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () { 1.91 + return { 1.92 + QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener, 1.93 + Ci.nsIObserver]), 1.94 + 1.95 + nfc: null, 1.96 + 1.97 + // Manage message targets in terms of sessionToken. Only the authorized and 1.98 + // registered contents can receive related messages. 1.99 + targetsBySessionTokens: {}, 1.100 + sessionTokens: [], 1.101 + 1.102 + // Manage registered Peer Targets 1.103 + peerTargetsMap: {}, 1.104 + currentPeerAppId: null, 1.105 + 1.106 + init: function init(nfc) { 1.107 + this.nfc = nfc; 1.108 + 1.109 + Services.obs.addObserver(this, NFC.TOPIC_XPCOM_SHUTDOWN, false); 1.110 + this._registerMessageListeners(); 1.111 + }, 1.112 + 1.113 + _shutdown: function _shutdown() { 1.114 + this.nfc = null; 1.115 + 1.116 + Services.obs.removeObserver(this, NFC.TOPIC_XPCOM_SHUTDOWN); 1.117 + this._unregisterMessageListeners(); 1.118 + }, 1.119 + 1.120 + _registerMessageListeners: function _registerMessageListeners() { 1.121 + ppmm.addMessageListener("child-process-shutdown", this); 1.122 + 1.123 + for (let msgname of NFC_IPC_MSG_NAMES) { 1.124 + ppmm.addMessageListener(msgname, this); 1.125 + } 1.126 + 1.127 + for (let msgname of NFC_IPC_READ_PERM_MSG_NAMES) { 1.128 + ppmm.addMessageListener(msgname, this); 1.129 + } 1.130 + 1.131 + for (let msgname of NFC_IPC_WRITE_PERM_MSG_NAMES) { 1.132 + ppmm.addMessageListener(msgname, this); 1.133 + } 1.134 + 1.135 + for (let msgname of NFC_IPC_MANAGER_PERM_MSG_NAMES) { 1.136 + ppmm.addMessageListener(msgname, this); 1.137 + } 1.138 + }, 1.139 + 1.140 + _unregisterMessageListeners: function _unregisterMessageListeners() { 1.141 + ppmm.removeMessageListener("child-process-shutdown", this); 1.142 + 1.143 + for (let msgname of NFC_IPC_MSG_NAMES) { 1.144 + ppmm.removeMessageListener(msgname, this); 1.145 + } 1.146 + 1.147 + for (let msgname of NFC_IPC_READ_PERM_MSG_NAMES) { 1.148 + ppmm.removeMessageListener(msgname, this); 1.149 + } 1.150 + 1.151 + for (let msgname of NFC_IPC_WRITE_PERM_MSG_NAMES) { 1.152 + ppmm.removeMessageListener(msgname, this); 1.153 + } 1.154 + 1.155 + for (let msgname of NFC_IPC_MANAGER_PERM_MSG_NAMES) { 1.156 + ppmm.removeMessageListener(msgname, this); 1.157 + } 1.158 + 1.159 + ppmm = null; 1.160 + }, 1.161 + 1.162 + _registerMessageTarget: function _registerMessageTarget(sessionToken, target) { 1.163 + let targets = this.targetsBySessionTokens[sessionToken]; 1.164 + if (!targets) { 1.165 + targets = this.targetsBySessionTokens[sessionToken] = []; 1.166 + let list = this.sessionTokens; 1.167 + if (list.indexOf(sessionToken) == -1) { 1.168 + list.push(sessionToken); 1.169 + } 1.170 + } 1.171 + 1.172 + if (targets.indexOf(target) != -1) { 1.173 + debug("Already registered this target!"); 1.174 + return; 1.175 + } 1.176 + 1.177 + targets.push(target); 1.178 + debug("Registered :" + sessionToken + " target: " + target); 1.179 + }, 1.180 + 1.181 + _unregisterMessageTarget: function _unregisterMessageTarget(sessionToken, target) { 1.182 + if (sessionToken == null) { 1.183 + // Unregister the target for every sessionToken when no sessionToken is specified. 1.184 + for (let session of this.sessionTokens) { 1.185 + this._unregisterMessageTarget(session, target); 1.186 + } 1.187 + return; 1.188 + } 1.189 + 1.190 + // Unregister the target for a specified sessionToken. 1.191 + let targets = this.targetsBySessionTokens[sessionToken]; 1.192 + if (!targets) { 1.193 + return; 1.194 + } 1.195 + 1.196 + if (target == null) { 1.197 + debug("Unregistered all targets for the " + sessionToken + " targets: " + targets); 1.198 + targets = []; 1.199 + let list = this.sessionTokens; 1.200 + if (sessionToken !== null) { 1.201 + let index = list.indexOf(sessionToken); 1.202 + if (index > -1) { 1.203 + list.splice(index, 1); 1.204 + } 1.205 + } 1.206 + return; 1.207 + } 1.208 + 1.209 + let index = targets.indexOf(target); 1.210 + if (index != -1) { 1.211 + targets.splice(index, 1); 1.212 + } 1.213 + }, 1.214 + 1.215 + _sendTargetMessage: function _sendTargetMessage(sessionToken, message, options) { 1.216 + let targets = this.targetsBySessionTokens[sessionToken]; 1.217 + if (!targets) { 1.218 + return; 1.219 + } 1.220 + 1.221 + for (let target of targets) { 1.222 + target.sendAsyncMessage(message, options); 1.223 + } 1.224 + }, 1.225 + 1.226 + registerPeerTarget: function registerPeerTarget(msg) { 1.227 + let appInfo = msg.json; 1.228 + // Sanity check on PeerEvent 1.229 + if (!this.isValidPeerEvent(appInfo.event)) { 1.230 + return; 1.231 + } 1.232 + let targets = this.peerTargetsMap; 1.233 + let targetInfo = targets[appInfo.appId]; 1.234 + // If the application Id is already registered 1.235 + if (targetInfo) { 1.236 + // If the event is not registered 1.237 + if (targetInfo.event !== appInfo.event) { 1.238 + // Update the event field ONLY 1.239 + targetInfo.event |= appInfo.event; 1.240 + } 1.241 + // Otherwise event is already registered, return! 1.242 + return; 1.243 + } 1.244 + // Target not registered yet! Add to the target map 1.245 + 1.246 + // Registered targetInfo target consists of 2 fields (values) 1.247 + // target : Target to notify the right content for peer notifications 1.248 + // event : NFC_PEER_EVENT_READY (0x01) Or NFC_PEER_EVENT_LOST (0x02) 1.249 + let newTargetInfo = { target : msg.target, 1.250 + event : appInfo.event }; 1.251 + targets[appInfo.appId] = newTargetInfo; 1.252 + }, 1.253 + 1.254 + unregisterPeerTarget: function unregisterPeerTarget(msg) { 1.255 + let appInfo = msg.json; 1.256 + // Sanity check on PeerEvent 1.257 + if (!this.isValidPeerEvent(appInfo.event)) { 1.258 + return; 1.259 + } 1.260 + let targets = this.peerTargetsMap; 1.261 + let targetInfo = targets[appInfo.appId]; 1.262 + if (targetInfo) { 1.263 + // Application Id registered and the event exactly matches. 1.264 + if (targetInfo.event === appInfo.event) { 1.265 + // Remove the target from the list of registered targets 1.266 + delete targets[appInfo.appId] 1.267 + } 1.268 + else { 1.269 + // Otherwise, update the event field ONLY, by removing the event flag 1.270 + targetInfo.event &= ~appInfo.event; 1.271 + } 1.272 + } 1.273 + }, 1.274 + 1.275 + removePeerTarget: function removePeerTarget(target) { 1.276 + let targets = this.peerTargetsMap; 1.277 + Object.keys(targets).forEach((appId) => { 1.278 + let targetInfo = targets[appId]; 1.279 + if (targetInfo && targetInfo.target === target) { 1.280 + // Remove the target from the list of registered targets 1.281 + delete targets[appId]; 1.282 + } 1.283 + }); 1.284 + }, 1.285 + 1.286 + isRegisteredP2PTarget: function isRegisteredP2PTarget(appId, event) { 1.287 + let targetInfo = this.peerTargetsMap[appId]; 1.288 + // Check if it is a registered target for the 'event' 1.289 + return ((targetInfo != null) && (targetInfo.event & event !== 0)); 1.290 + }, 1.291 + 1.292 + notifyPeerEvent: function notifyPeerEvent(appId, event) { 1.293 + let targetInfo = this.peerTargetsMap[appId]; 1.294 + // Check if the application id is a registeredP2PTarget 1.295 + if (this.isRegisteredP2PTarget(appId, event)) { 1.296 + targetInfo.target.sendAsyncMessage("NFC:PeerEvent", { 1.297 + event: event, 1.298 + sessionToken: this.nfc.sessionTokenMap[this.nfc._currentSessionId] 1.299 + }); 1.300 + return; 1.301 + } 1.302 + debug("Application ID : " + appId + " is not a registered target" + 1.303 + "for the event " + event + " notification"); 1.304 + }, 1.305 + 1.306 + isValidPeerEvent: function isValidPeerEvent(event) { 1.307 + // Valid values : 0x01, 0x02 Or 0x03 1.308 + return ((event === NFC.NFC_PEER_EVENT_READY) || 1.309 + (event === NFC.NFC_PEER_EVENT_LOST) || 1.310 + (event === (NFC.NFC_PEER_EVENT_READY | NFC.NFC_PEER_EVENT_LOST))); 1.311 + }, 1.312 + 1.313 + /** 1.314 + * nsIMessageListener interface methods. 1.315 + */ 1.316 + 1.317 + receiveMessage: function receiveMessage(msg) { 1.318 + debug("Received '" + msg.name + "' message from content process"); 1.319 + if (msg.name == "child-process-shutdown") { 1.320 + // By the time we receive child-process-shutdown, the child process has 1.321 + // already forgotten its permissions so we need to unregister the target 1.322 + // for every permission. 1.323 + this._unregisterMessageTarget(null, msg.target); 1.324 + this.removePeerTarget(msg.target); 1.325 + return null; 1.326 + } 1.327 + 1.328 + if (NFC_IPC_MSG_NAMES.indexOf(msg.name) != -1) { 1.329 + // Do nothing. 1.330 + } else if (NFC_IPC_READ_PERM_MSG_NAMES.indexOf(msg.name) != -1) { 1.331 + if (!msg.target.assertPermission("nfc-read")) { 1.332 + debug("Nfc message " + msg.name + 1.333 + " from a content process with no 'nfc-read' privileges."); 1.334 + return null; 1.335 + } 1.336 + } else if (NFC_IPC_WRITE_PERM_MSG_NAMES.indexOf(msg.name) != -1) { 1.337 + if (!msg.target.assertPermission("nfc-write")) { 1.338 + debug("Nfc Peer message " + msg.name + 1.339 + " from a content process with no 'nfc-write' privileges."); 1.340 + return null; 1.341 + } 1.342 + } else if (NFC_IPC_MANAGER_PERM_MSG_NAMES.indexOf(msg.name) != -1) { 1.343 + if (!msg.target.assertPermission("nfc-manager")) { 1.344 + debug("NFC message " + message.name + 1.345 + " from a content process with no 'nfc-manager' privileges."); 1.346 + return null; 1.347 + } 1.348 + } else { 1.349 + debug("Ignoring unknown message type: " + msg.name); 1.350 + return null; 1.351 + } 1.352 + 1.353 + switch (msg.name) { 1.354 + case "NFC:SetSessionToken": 1.355 + this._registerMessageTarget(this.nfc.sessionTokenMap[this.nfc._currentSessionId], msg.target); 1.356 + debug("Registering target for this SessionToken : " + 1.357 + this.nfc.sessionTokenMap[this.nfc._currentSessionId]); 1.358 + return null; 1.359 + case "NFC:RegisterPeerTarget": 1.360 + this.registerPeerTarget(msg); 1.361 + return null; 1.362 + case "NFC:UnregisterPeerTarget": 1.363 + this.unregisterPeerTarget(msg); 1.364 + return null; 1.365 + case "NFC:CheckP2PRegistration": 1.366 + // Check if the application id is a valid registered target. 1.367 + // (It should have registered for NFC_PEER_EVENT_READY). 1.368 + let isRegistered = this.isRegisteredP2PTarget(msg.json.appId, 1.369 + NFC.NFC_PEER_EVENT_READY); 1.370 + // Remember the current AppId if registered. 1.371 + this.currentPeerAppId = (isRegistered) ? msg.json.appId : null; 1.372 + let status = (isRegistered) ? NFC.GECKO_NFC_ERROR_SUCCESS : 1.373 + NFC.GECKO_NFC_ERROR_GENERIC_FAILURE; 1.374 + // Notify the content process immediately of the status 1.375 + msg.target.sendAsyncMessage(msg.name + "Response", { 1.376 + status: status, 1.377 + requestId: msg.json.requestId 1.378 + }); 1.379 + return null; 1.380 + case "NFC:NotifyUserAcceptedP2P": 1.381 + // Notify the 'NFC_PEER_EVENT_READY' since user has acknowledged 1.382 + this.notifyPeerEvent(msg.json.appId, NFC.NFC_PEER_EVENT_READY); 1.383 + return null; 1.384 + case "NFC:NotifySendFileStatus": 1.385 + // Upon receiving the status of sendFile operation, send the response 1.386 + // to appropriate content process. 1.387 + this.sendNfcResponseMessage(msg.name + "Response", msg.json); 1.388 + return null; 1.389 + default: 1.390 + return this.nfc.receiveMessage(msg); 1.391 + } 1.392 + }, 1.393 + 1.394 + /** 1.395 + * nsIObserver interface methods. 1.396 + */ 1.397 + 1.398 + observe: function observe(subject, topic, data) { 1.399 + switch (topic) { 1.400 + case NFC.TOPIC_XPCOM_SHUTDOWN: 1.401 + this._shutdown(); 1.402 + break; 1.403 + } 1.404 + }, 1.405 + 1.406 + sendNfcResponseMessage: function sendNfcResponseMessage(message, data) { 1.407 + this._sendTargetMessage(this.nfc.sessionTokenMap[this.nfc._currentSessionId], message, data); 1.408 + }, 1.409 + }; 1.410 +}); 1.411 + 1.412 +function Nfc() { 1.413 + debug("Starting Worker"); 1.414 + this.worker = new ChromeWorker("resource://gre/modules/nfc_worker.js"); 1.415 + this.worker.onerror = this.onerror.bind(this); 1.416 + this.worker.onmessage = this.onmessage.bind(this); 1.417 + 1.418 + gMessageManager.init(this); 1.419 + 1.420 + // Maps sessionId (that are generated from nfcd) with a unique guid : 'SessionToken' 1.421 + this.sessionTokenMap = {}; 1.422 + this.targetsByRequestId = {}; 1.423 + 1.424 + gSystemWorkerManager.registerNfcWorker(this.worker); 1.425 +} 1.426 + 1.427 +Nfc.prototype = { 1.428 + 1.429 + classID: NFC_CID, 1.430 + classInfo: XPCOMUtils.generateCI({classID: NFC_CID, 1.431 + classDescription: "Nfc", 1.432 + interfaces: [Ci.nsIWorkerHolder]}), 1.433 + 1.434 + QueryInterface: XPCOMUtils.generateQI([Ci.nsIWorkerHolder]), 1.435 + 1.436 + _currentSessionId: null, 1.437 + 1.438 + powerLevel: NFC.NFC_POWER_LEVEL_UNKNOWN, 1.439 + 1.440 + onerror: function onerror(event) { 1.441 + debug("Got an error: " + event.filename + ":" + 1.442 + event.lineno + ": " + event.message + "\n"); 1.443 + event.preventDefault(); 1.444 + }, 1.445 + 1.446 + /** 1.447 + * Send arbitrary message to worker. 1.448 + * 1.449 + * @param nfcMessageType 1.450 + * A text message type. 1.451 + * @param message [optional] 1.452 + * An optional message object to send. 1.453 + */ 1.454 + sendToWorker: function sendToWorker(nfcMessageType, message) { 1.455 + message = message || {}; 1.456 + message.type = nfcMessageType; 1.457 + this.worker.postMessage(message); 1.458 + }, 1.459 + 1.460 + /** 1.461 + * Send Error response to content. 1.462 + * 1.463 + * @param message 1.464 + * An nsIMessageListener's message parameter. 1.465 + */ 1.466 + sendNfcErrorResponse: function sendNfcErrorResponse(message) { 1.467 + if (!message.target) { 1.468 + return; 1.469 + } 1.470 + 1.471 + let nfcMsgType = message.name + "Response"; 1.472 + message.target.sendAsyncMessage(nfcMsgType, { 1.473 + sessionId: message.json.sessionToken, 1.474 + requestId: message.json.requestId, 1.475 + status: NFC.GECKO_NFC_ERROR_GENERIC_FAILURE 1.476 + }); 1.477 + }, 1.478 + 1.479 + /** 1.480 + * Process the incoming message from the NFC worker 1.481 + */ 1.482 + onmessage: function onmessage(event) { 1.483 + let message = event.data; 1.484 + debug("Received message from NFC worker: " + JSON.stringify(message)); 1.485 + 1.486 + switch (message.type) { 1.487 + case "techDiscovered": 1.488 + this._currentSessionId = message.sessionId; 1.489 + 1.490 + // Check if the session token already exists. If exists, continue to use the same one. 1.491 + // If not, generate a new token. 1.492 + if (!this.sessionTokenMap[this._currentSessionId]) { 1.493 + this.sessionTokenMap[this._currentSessionId] = UUIDGenerator.generateUUID().toString(); 1.494 + } 1.495 + // Update the upper layers with a session token (alias) 1.496 + message.sessionToken = this.sessionTokenMap[this._currentSessionId]; 1.497 + // Do not expose the actual session to the content 1.498 + delete message.sessionId; 1.499 + 1.500 + gSystemMessenger.broadcastMessage("nfc-manager-tech-discovered", message); 1.501 + break; 1.502 + case "techLost": 1.503 + gMessageManager._unregisterMessageTarget(this.sessionTokenMap[this._currentSessionId], null); 1.504 + 1.505 + // Update the upper layers with a session token (alias) 1.506 + message.sessionToken = this.sessionTokenMap[this._currentSessionId]; 1.507 + // Do not expose the actual session to the content 1.508 + delete message.sessionId; 1.509 + 1.510 + gSystemMessenger.broadcastMessage("nfc-manager-tech-lost", message); 1.511 + // Notify 'PeerLost' to appropriate registered target, if any 1.512 + gMessageManager.notifyPeerEvent(this.currentPeerAppId, NFC.NFC_PEER_EVENT_LOST); 1.513 + delete this.sessionTokenMap[this._currentSessionId]; 1.514 + this._currentSessionId = null; 1.515 + this.currentPeerAppId = null; 1.516 + break; 1.517 + case "ConfigResponse": 1.518 + let target = this.targetsByRequestId[message.requestId]; 1.519 + if (!target) { 1.520 + debug("No target for requestId: " + message.requestId); 1.521 + return; 1.522 + } 1.523 + delete this.targetsByRequestId[message.requestId]; 1.524 + 1.525 + if (message.status == NFC.GECKO_NFC_ERROR_SUCCESS) { 1.526 + this.powerLevel = message.powerLevel; 1.527 + } 1.528 + 1.529 + target.sendAsyncMessage("NFC:ConfigResponse", message); 1.530 + break; 1.531 + case "ConnectResponse": // Fall through. 1.532 + case "CloseResponse": 1.533 + case "GetDetailsNDEFResponse": 1.534 + case "ReadNDEFResponse": 1.535 + case "MakeReadOnlyNDEFResponse": 1.536 + case "WriteNDEFResponse": 1.537 + message.sessionToken = this.sessionTokenMap[this._currentSessionId]; 1.538 + // Do not expose the actual session to the content 1.539 + delete message.sessionId; 1.540 + gMessageManager.sendNfcResponseMessage("NFC:" + message.type, message); 1.541 + break; 1.542 + default: 1.543 + throw new Error("Don't know about this message type: " + message.type); 1.544 + } 1.545 + }, 1.546 + 1.547 + // nsINfcWorker 1.548 + worker: null, 1.549 + 1.550 + sessionTokenMap: null, 1.551 + 1.552 + targetsByRequestId: null, 1.553 + 1.554 + /** 1.555 + * Process a message from the content process. 1.556 + */ 1.557 + receiveMessage: function receiveMessage(message) { 1.558 + debug("Received '" + JSON.stringify(message) + "' message from content process"); 1.559 + 1.560 + // Handle messages without sessionToken. 1.561 + if (message.name == "NFC:StartPoll") { 1.562 + this.targetsByRequestId[message.json.requestId] = message.target; 1.563 + this.setConfig({powerLevel: NFC.NFC_POWER_LEVEL_ENABLED, 1.564 + requestId: message.json.requestId}); 1.565 + return null; 1.566 + } else if (message.name == "NFC:StopPoll") { 1.567 + this.targetsByRequestId[message.json.requestId] = message.target; 1.568 + this.setConfig({powerLevel: NFC.NFC_POWER_LEVEL_LOW, 1.569 + requestId: message.json.requestId}); 1.570 + return null; 1.571 + } else if (message.name == "NFC:PowerOff") { 1.572 + this.targetsByRequestId[message.json.requestId] = message.target; 1.573 + this.setConfig({powerLevel: NFC.NFC_POWER_LEVEL_DISABLED, 1.574 + requestId: message.json.requestId}); 1.575 + return null; 1.576 + } 1.577 + 1.578 + if (this.powerLevel != NFC.NFC_POWER_LEVEL_ENABLED) { 1.579 + debug("NFC is not enabled. current powerLevel:" + this.powerLevel); 1.580 + this.sendNfcErrorResponse(message); 1.581 + return null; 1.582 + } 1.583 + 1.584 + // Sanity check on sessionId 1.585 + if (message.json.sessionToken !== this.sessionTokenMap[this._currentSessionId]) { 1.586 + debug("Invalid Session Token: " + message.json.sessionToken + 1.587 + " Expected Session Token: " + this.sessionTokenMap[this._currentSessionId]); 1.588 + this.sendNfcErrorResponse(message); 1.589 + return null; 1.590 + } 1.591 + 1.592 + // Update the current sessionId before sending to the worker 1.593 + message.json.sessionId = this._currentSessionId; 1.594 + 1.595 + switch (message.name) { 1.596 + case "NFC:GetDetailsNDEF": 1.597 + this.sendToWorker("getDetailsNDEF", message.json); 1.598 + break; 1.599 + case "NFC:ReadNDEF": 1.600 + this.sendToWorker("readNDEF", message.json); 1.601 + break; 1.602 + case "NFC:WriteNDEF": 1.603 + this.sendToWorker("writeNDEF", message.json); 1.604 + break; 1.605 + case "NFC:MakeReadOnlyNDEF": 1.606 + this.sendToWorker("makeReadOnlyNDEF", message.json); 1.607 + break; 1.608 + case "NFC:Connect": 1.609 + this.sendToWorker("connect", message.json); 1.610 + break; 1.611 + case "NFC:Close": 1.612 + this.sendToWorker("close", message.json); 1.613 + break; 1.614 + case "NFC:SendFile": 1.615 + // Chrome process is the arbitrator / mediator between 1.616 + // system app (content process) that issued nfc 'sendFile' operation 1.617 + // and system app that handles the system message : 1.618 + // 'nfc-manager-send-file'. System app subsequently handover's 1.619 + // the data to alternate carrier's (BT / WiFi) 'sendFile' interface. 1.620 + 1.621 + // Notify system app to initiate BT send file operation 1.622 + gSystemMessenger.broadcastMessage("nfc-manager-send-file", 1.623 + message.json); 1.624 + break; 1.625 + default: 1.626 + debug("UnSupported : Message Name " + message.name); 1.627 + return null; 1.628 + } 1.629 + 1.630 + return null; 1.631 + }, 1.632 + 1.633 + setConfig: function setConfig(prop) { 1.634 + this.sendToWorker("config", prop); 1.635 + } 1.636 +}; 1.637 + 1.638 +if (NFC_ENABLED) { 1.639 + this.NSGetFactory = XPCOMUtils.generateNSGetFactory([Nfc]); 1.640 +}