dom/system/gonk/Nfc.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial