2013-11-06 09:53:19 -08:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
/* Copyright © 2013, Deutsche Telekom, Inc. */
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
const DEBUG = false;
|
|
|
|
function debug(s) {
|
|
|
|
if (DEBUG) dump("-*- Nfc DOM: " + s + "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
const Cc = Components.classes;
|
|
|
|
const Ci = Components.interfaces;
|
|
|
|
const Cu = Components.utils;
|
|
|
|
|
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
|
|
|
2013-11-24 20:40:39 -08:00
|
|
|
XPCOMUtils.defineLazyServiceGetter(this,
|
|
|
|
"appsService",
|
|
|
|
"@mozilla.org/AppsService;1",
|
|
|
|
"nsIAppsService");
|
|
|
|
|
2013-11-06 09:53:19 -08:00
|
|
|
/**
|
|
|
|
* NFCTag
|
2014-10-21 20:48:40 -07:00
|
|
|
*
|
|
|
|
* @param window global window object.
|
|
|
|
* @param sessionToken session token received from parent process.
|
|
|
|
* @parem event type of nsINfcTagEvent received from parent process.
|
2013-11-06 09:53:19 -08:00
|
|
|
*/
|
2014-10-21 20:48:40 -07:00
|
|
|
function MozNFCTag(window, sessionToken, event) {
|
2013-11-06 09:53:19 -08:00
|
|
|
debug("In MozNFCTag Constructor");
|
|
|
|
this._nfcContentHelper = Cc["@mozilla.org/nfc/content-helper;1"]
|
|
|
|
.getService(Ci.nsINfcContentHelper);
|
2014-10-21 20:48:40 -07:00
|
|
|
this._window = window;
|
|
|
|
this.session = sessionToken;
|
|
|
|
this.techList = event.techList;
|
|
|
|
this.type = event.tagType || null;
|
|
|
|
this.maxNDEFSize = event.maxNDEFSize || null;
|
|
|
|
this.isReadOnly = event.isReadOnly || null;
|
|
|
|
this.isFormatable = event.isFormatable || null;
|
|
|
|
this.canBeMadeReadOnly = this.type ?
|
|
|
|
(this.type == "type1" || this.type == "type2" ||
|
|
|
|
this.type == "mifare_classic") :
|
|
|
|
null;
|
2013-11-06 09:53:19 -08:00
|
|
|
}
|
|
|
|
MozNFCTag.prototype = {
|
|
|
|
_nfcContentHelper: null,
|
|
|
|
_window: null,
|
2014-10-21 20:48:40 -07:00
|
|
|
session: null,
|
|
|
|
techList: null,
|
|
|
|
type: null,
|
|
|
|
maxNDEFSize: 0,
|
|
|
|
isReadOnly: false,
|
|
|
|
isFormatable: false,
|
|
|
|
canBeMadeReadOnly: false,
|
2013-11-06 09:53:19 -08:00
|
|
|
|
|
|
|
// NFCTag interface:
|
|
|
|
readNDEF: function readNDEF() {
|
2014-10-30 03:46:41 -07:00
|
|
|
return this._nfcContentHelper.readNDEF(this.session);
|
2013-11-06 09:53:19 -08:00
|
|
|
},
|
|
|
|
writeNDEF: function writeNDEF(records) {
|
2014-10-30 03:46:41 -07:00
|
|
|
return this._nfcContentHelper.writeNDEF(records, this.session);
|
2013-11-06 09:53:19 -08:00
|
|
|
},
|
|
|
|
makeReadOnlyNDEF: function makeReadOnlyNDEF() {
|
2014-10-30 03:46:41 -07:00
|
|
|
return this._nfcContentHelper.makeReadOnlyNDEF(this.session);
|
2013-11-06 09:53:19 -08:00
|
|
|
},
|
|
|
|
|
|
|
|
classID: Components.ID("{4e1e2e90-3137-11e3-aa6e-0800200c9a66}"),
|
|
|
|
contractID: "@mozilla.org/nfc/NFCTag;1",
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
|
|
|
|
Ci.nsIDOMGlobalPropertyInitializer]),
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* NFCPeer
|
|
|
|
*/
|
2014-10-22 21:19:22 -07:00
|
|
|
function MozNFCPeer(aWindow, aSessionToken) {
|
2013-11-06 09:53:19 -08:00
|
|
|
debug("In MozNFCPeer Constructor");
|
|
|
|
this._nfcContentHelper = Cc["@mozilla.org/nfc/content-helper;1"]
|
|
|
|
.getService(Ci.nsINfcContentHelper);
|
2014-10-22 21:19:22 -07:00
|
|
|
|
|
|
|
this._window = aWindow;
|
|
|
|
this.session = aSessionToken;
|
2013-11-06 09:53:19 -08:00
|
|
|
}
|
|
|
|
MozNFCPeer.prototype = {
|
|
|
|
_nfcContentHelper: null,
|
|
|
|
_window: null,
|
2014-07-28 20:36:58 -07:00
|
|
|
_isLost: false,
|
2013-11-06 09:53:19 -08:00
|
|
|
|
|
|
|
// NFCPeer interface:
|
|
|
|
sendNDEF: function sendNDEF(records) {
|
2014-07-28 20:36:58 -07:00
|
|
|
if (this._isLost) {
|
|
|
|
throw new this._window.DOMError("InvalidStateError", "NFCPeer object is invalid");
|
|
|
|
}
|
|
|
|
|
2013-11-06 09:53:19 -08:00
|
|
|
// Just forward sendNDEF to writeNDEF
|
2014-10-30 03:46:41 -07:00
|
|
|
return this._nfcContentHelper.writeNDEF(records, this.session);
|
2013-11-06 09:53:19 -08:00
|
|
|
},
|
|
|
|
|
2013-12-13 23:24:02 -08:00
|
|
|
sendFile: function sendFile(blob) {
|
2014-07-28 20:36:58 -07:00
|
|
|
if (this._isLost) {
|
|
|
|
throw new this._window.DOMError("InvalidStateError", "NFCPeer object is invalid");
|
|
|
|
}
|
|
|
|
|
2013-12-13 23:24:02 -08:00
|
|
|
let data = {
|
2014-04-09 16:38:53 -07:00
|
|
|
"blob": blob
|
2013-12-13 23:24:02 -08:00
|
|
|
};
|
2014-10-30 03:46:41 -07:00
|
|
|
return this._nfcContentHelper.sendFile(Cu.cloneInto(data, this._window),
|
2013-12-13 23:24:02 -08:00
|
|
|
this.session);
|
|
|
|
},
|
|
|
|
|
2014-07-28 20:36:58 -07:00
|
|
|
invalidate: function invalidate() {
|
|
|
|
this._isLost = true;
|
|
|
|
},
|
|
|
|
|
2013-11-06 09:53:19 -08:00
|
|
|
classID: Components.ID("{c1b2bcf0-35eb-11e3-aa6e-0800200c9a66}"),
|
|
|
|
contractID: "@mozilla.org/nfc/NFCPeer;1",
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
|
|
|
|
Ci.nsIDOMGlobalPropertyInitializer]),
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Navigator NFC object
|
|
|
|
*/
|
|
|
|
function mozNfc() {
|
|
|
|
debug("In mozNfc Constructor");
|
2013-12-10 22:04:27 -08:00
|
|
|
try {
|
|
|
|
this._nfcContentHelper = Cc["@mozilla.org/nfc/content-helper;1"]
|
|
|
|
.getService(Ci.nsINfcContentHelper);
|
|
|
|
} catch(e) {
|
|
|
|
debug("No NFC support.")
|
|
|
|
}
|
2014-07-23 21:16:02 -07:00
|
|
|
|
2014-09-23 23:52:04 -07:00
|
|
|
this._nfcContentHelper.registerEventTarget(this);
|
2013-11-06 09:53:19 -08:00
|
|
|
}
|
|
|
|
mozNfc.prototype = {
|
|
|
|
_nfcContentHelper: null,
|
|
|
|
_window: null,
|
2014-07-25 03:03:37 -07:00
|
|
|
nfcObject: null,
|
|
|
|
|
2013-11-06 09:53:19 -08:00
|
|
|
init: function init(aWindow) {
|
|
|
|
debug("mozNfc init called");
|
|
|
|
this._window = aWindow;
|
2014-10-20 02:53:39 -07:00
|
|
|
this.defineEventHandlerGetterSetter("ontagfound");
|
|
|
|
this.defineEventHandlerGetterSetter("ontaglost");
|
|
|
|
this.defineEventHandlerGetterSetter("onpeerready");
|
2014-10-29 23:08:00 -07:00
|
|
|
this.defineEventHandlerGetterSetter("onpeerfound");
|
2014-10-20 02:53:39 -07:00
|
|
|
this.defineEventHandlerGetterSetter("onpeerlost");
|
|
|
|
|
2014-10-14 01:37:50 -07:00
|
|
|
if (this._nfcContentHelper) {
|
|
|
|
this._nfcContentHelper.init(aWindow);
|
|
|
|
}
|
2013-11-24 20:40:39 -08:00
|
|
|
},
|
|
|
|
|
2014-04-14 23:47:42 -07:00
|
|
|
// Only apps which have nfc-manager permission can call the following interfaces
|
|
|
|
// 'checkP2PRegistration' , 'notifyUserAcceptedP2P' , 'notifySendFileStatus',
|
|
|
|
// 'startPoll', 'stopPoll', and 'powerOff'.
|
2013-11-24 20:40:39 -08:00
|
|
|
checkP2PRegistration: function checkP2PRegistration(manifestUrl) {
|
|
|
|
// Get the AppID and pass it to ContentHelper
|
|
|
|
let appID = appsService.getAppLocalIdByManifestURL(manifestUrl);
|
2014-10-30 03:46:41 -07:00
|
|
|
return this._nfcContentHelper.checkP2PRegistration(appID);
|
2013-11-06 09:53:19 -08:00
|
|
|
},
|
|
|
|
|
2014-01-17 18:38:26 -08:00
|
|
|
notifyUserAcceptedP2P: function notifyUserAcceptedP2P(manifestUrl) {
|
|
|
|
let appID = appsService.getAppLocalIdByManifestURL(manifestUrl);
|
|
|
|
// Notify chrome process of user's acknowledgement
|
2014-10-30 03:46:41 -07:00
|
|
|
this._nfcContentHelper.notifyUserAcceptedP2P(appID);
|
2014-01-17 18:38:26 -08:00
|
|
|
},
|
|
|
|
|
|
|
|
notifySendFileStatus: function notifySendFileStatus(status, requestId) {
|
2014-10-30 03:46:41 -07:00
|
|
|
this._nfcContentHelper.notifySendFileStatus(status, requestId);
|
2014-01-17 18:38:26 -08:00
|
|
|
},
|
|
|
|
|
2014-04-14 23:47:42 -07:00
|
|
|
startPoll: function startPoll() {
|
2014-10-30 03:46:41 -07:00
|
|
|
return this._nfcContentHelper.startPoll();
|
2014-04-14 23:47:42 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
stopPoll: function stopPoll() {
|
2014-10-30 03:46:41 -07:00
|
|
|
return this._nfcContentHelper.stopPoll();
|
2014-04-14 23:47:42 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
powerOff: function powerOff() {
|
2014-10-30 03:46:41 -07:00
|
|
|
return this._nfcContentHelper.powerOff();
|
2014-04-14 23:47:42 -07:00
|
|
|
},
|
|
|
|
|
2013-11-06 09:53:19 -08:00
|
|
|
getNFCPeer: function getNFCPeer(sessionToken) {
|
2014-08-18 02:43:28 -07:00
|
|
|
if (!sessionToken || !this._nfcContentHelper.checkSessionToken(sessionToken)) {
|
2014-08-05 02:06:00 -07:00
|
|
|
return null;
|
2013-11-06 09:53:19 -08:00
|
|
|
}
|
2014-07-25 03:03:37 -07:00
|
|
|
|
2014-08-11 02:19:11 -07:00
|
|
|
if (!this.nfcObject || this.nfcObject.session != sessionToken) {
|
2014-10-22 21:19:22 -07:00
|
|
|
let obj = new MozNFCPeer(this._window, sessionToken);
|
2014-07-25 03:03:37 -07:00
|
|
|
this.nfcObject = obj;
|
|
|
|
this.nfcObject.contentObject = this._window.MozNFCPeer._create(this._window, obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.nfcObject.contentObject;
|
2013-11-06 09:53:19 -08:00
|
|
|
},
|
|
|
|
|
2014-10-20 02:53:39 -07:00
|
|
|
defineEventHandlerGetterSetter: function defineEventHandlerGetterSetter(name) {
|
|
|
|
Object.defineProperty(this, name, {
|
|
|
|
get: function get() {
|
|
|
|
return this.__DOM_IMPL__.getEventHandler(name);
|
|
|
|
},
|
|
|
|
set: function set(handler) {
|
|
|
|
this.__DOM_IMPL__.setEventHandler(name, handler);
|
|
|
|
}
|
|
|
|
});
|
2013-11-24 20:40:39 -08:00
|
|
|
},
|
|
|
|
|
2014-09-09 02:56:00 -07:00
|
|
|
eventListenerWasAdded: function(eventType) {
|
|
|
|
if (eventType !== "peerready") {
|
2013-11-24 20:40:39 -08:00
|
|
|
return;
|
2014-07-24 03:11:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
let appId = this._window.document.nodePrincipal.appId;
|
2014-10-30 03:46:41 -07:00
|
|
|
this._nfcContentHelper.registerTargetForPeerReady(appId);
|
2013-11-24 20:40:39 -08:00
|
|
|
},
|
|
|
|
|
2014-09-09 02:56:00 -07:00
|
|
|
eventListenerWasRemoved: function(eventType) {
|
|
|
|
if (eventType !== "peerready") {
|
2013-11-24 20:40:39 -08:00
|
|
|
return;
|
2014-07-24 03:11:42 -07:00
|
|
|
}
|
2013-11-24 20:40:39 -08:00
|
|
|
|
|
|
|
let appId = this._window.document.nodePrincipal.appId;
|
2014-10-30 03:46:41 -07:00
|
|
|
this._nfcContentHelper.unregisterTargetForPeerReady(appId);
|
2014-07-23 21:16:02 -07:00
|
|
|
},
|
|
|
|
|
2014-10-20 02:53:39 -07:00
|
|
|
notifyTagFound: function notifyTagFound(sessionToken, event, records) {
|
|
|
|
if (this.hasDeadWrapper()) {
|
|
|
|
dump("this._window or this.__DOM_IMPL__ is a dead wrapper.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-27 23:58:47 -07:00
|
|
|
if (!this.checkPermissions(["nfc-read", "nfc-write"])) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-21 20:48:40 -07:00
|
|
|
let tag = new MozNFCTag(this._window, sessionToken, event);
|
2014-10-20 02:53:39 -07:00
|
|
|
let tagContentObj = this._window.MozNFCTag._create(this._window, tag);
|
|
|
|
|
|
|
|
let length = records ? records.length : 0;
|
|
|
|
let ndefRecords = records ? [] : null;
|
|
|
|
for (let i = 0; i < length; i++) {
|
|
|
|
let record = records[i];
|
|
|
|
ndefRecords.push(new this._window.MozNDEFRecord({tnf: record.tnf,
|
|
|
|
type: record.type,
|
|
|
|
id: record.id,
|
|
|
|
payload: record.payload}));
|
|
|
|
}
|
|
|
|
|
|
|
|
let eventData = {
|
|
|
|
"tag": tagContentObj,
|
|
|
|
"ndefRecords": ndefRecords
|
|
|
|
};
|
|
|
|
|
|
|
|
debug("fire ontagfound " + sessionToken);
|
|
|
|
let tagEvent = new this._window.MozNFCTagEvent("tagfound", eventData);
|
|
|
|
this.__DOM_IMPL__.dispatchEvent(tagEvent);
|
|
|
|
},
|
|
|
|
|
|
|
|
notifyTagLost: function notifyTagLost(sessionToken) {
|
|
|
|
if (this.hasDeadWrapper()) {
|
|
|
|
dump("this._window or this.__DOM_IMPL__ is a dead wrapper.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-27 23:58:47 -07:00
|
|
|
if (!this.checkPermissions(["nfc-read", "nfc-write"])) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-20 02:53:39 -07:00
|
|
|
debug("fire ontaglost " + sessionToken);
|
|
|
|
let event = new this._window.Event("taglost");
|
|
|
|
this.__DOM_IMPL__.dispatchEvent(event);
|
|
|
|
},
|
|
|
|
|
2014-10-29 23:08:00 -07:00
|
|
|
notifyPeerFound: function notifyPeerFound(sessionToken, isPeerReady) {
|
2014-07-23 21:16:02 -07:00
|
|
|
if (this.hasDeadWrapper()) {
|
|
|
|
dump("this._window or this.__DOM_IMPL__ is a dead wrapper.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-29 23:08:00 -07:00
|
|
|
if (!this.checkPermissions(["nfc-write"])) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-07-23 21:16:02 -07:00
|
|
|
this.session = sessionToken;
|
2014-10-29 23:08:00 -07:00
|
|
|
let eventData = { "peer": this.getNFCPeer(sessionToken) };
|
|
|
|
let type = (isPeerReady) ? "peerready" : "peerfound";
|
2014-07-23 21:16:02 -07:00
|
|
|
|
2014-10-29 23:08:00 -07:00
|
|
|
debug("fire on" + type + " " + sessionToken);
|
|
|
|
let event = new this._window.MozNFCPeerEvent(type, eventData);
|
2014-07-23 21:16:02 -07:00
|
|
|
this.__DOM_IMPL__.dispatchEvent(event);
|
|
|
|
},
|
|
|
|
|
|
|
|
notifyPeerLost: function notifyPeerLost(sessionToken) {
|
|
|
|
if (this.hasDeadWrapper()) {
|
|
|
|
dump("this._window or this.__DOM_IMPL__ is a dead wrapper.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-29 23:08:00 -07:00
|
|
|
if (!this.checkPermissions(["nfc-write"])) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-07-23 21:16:02 -07:00
|
|
|
if (sessionToken != this.session) {
|
|
|
|
dump("Unpaired session for notifyPeerLost." + sessionToken);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-07-25 03:03:37 -07:00
|
|
|
if (this.nfcObject && (this.nfcObject.session == sessionToken)) {
|
2014-07-28 20:36:58 -07:00
|
|
|
this.nfcObject.invalidate();
|
2014-07-25 03:03:37 -07:00
|
|
|
this.nfcObject = null;
|
|
|
|
}
|
|
|
|
|
2014-07-23 21:16:02 -07:00
|
|
|
this.session = null;
|
|
|
|
|
|
|
|
debug("fire onpeerlost");
|
|
|
|
let event = new this._window.Event("peerlost");
|
|
|
|
this.__DOM_IMPL__.dispatchEvent(event);
|
2013-11-24 20:40:39 -08:00
|
|
|
},
|
|
|
|
|
2014-10-27 23:58:47 -07:00
|
|
|
checkPermissions: function checkPermissions(perms) {
|
|
|
|
let principal = this._window.document.nodePrincipal;
|
|
|
|
for (let perm of perms) {
|
|
|
|
let permValue =
|
|
|
|
Services.perms.testExactPermissionFromPrincipal(principal, perm);
|
|
|
|
if (permValue == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
debug("doesn't have " + perm + " permission.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
2014-07-21 00:43:45 -07:00
|
|
|
hasDeadWrapper: function hasDeadWrapper() {
|
|
|
|
return Cu.isDeadWrapper(this._window) || Cu.isDeadWrapper(this.__DOM_IMPL__);
|
|
|
|
},
|
|
|
|
|
2013-11-06 09:53:19 -08:00
|
|
|
classID: Components.ID("{6ff2b290-2573-11e3-8224-0800200c9a66}"),
|
|
|
|
contractID: "@mozilla.org/navigatorNfc;1",
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
|
2014-07-23 21:16:02 -07:00
|
|
|
Ci.nsIDOMGlobalPropertyInitializer,
|
2014-09-23 23:52:04 -07:00
|
|
|
Ci.nsINfcDOMEventTarget]),
|
2013-11-06 09:53:19 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MozNFCTag, MozNFCPeer, mozNfc]);
|