2013-11-06 21:53:19 +04: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");
|
2014-11-21 12:54:04 +03:00
|
|
|
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
|
2013-11-06 21:53:19 +04:00
|
|
|
|
2013-11-25 08:40:39 +04:00
|
|
|
XPCOMUtils.defineLazyServiceGetter(this,
|
|
|
|
"appsService",
|
|
|
|
"@mozilla.org/AppsService;1",
|
|
|
|
"nsIAppsService");
|
|
|
|
|
2014-11-21 12:54:04 +03:00
|
|
|
function NfcCallback(aWindow) {
|
2015-01-15 09:55:25 +03:00
|
|
|
this._window = aWindow;
|
2014-11-21 12:54:04 +03:00
|
|
|
this.initDOMRequestHelper(aWindow, null);
|
|
|
|
this._createPromise();
|
|
|
|
}
|
|
|
|
NfcCallback.prototype = {
|
|
|
|
__proto__: DOMRequestIpcHelper.prototype,
|
|
|
|
|
2015-01-15 09:55:25 +03:00
|
|
|
_window: null,
|
2014-11-21 12:54:04 +03:00
|
|
|
promise: null,
|
|
|
|
_requestId: null,
|
|
|
|
|
|
|
|
_createPromise: function _createPromise() {
|
|
|
|
this.promise = this.createPromise((aResolve, aReject) => {
|
|
|
|
this._requestId = btoa(this.getPromiseResolverId({
|
|
|
|
resolve: aResolve,
|
|
|
|
reject: aReject
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
getCallbackId: function getCallbackId() {
|
|
|
|
return this._requestId;
|
|
|
|
},
|
|
|
|
|
|
|
|
notifySuccess: function notifySuccess() {
|
|
|
|
let resolver = this.takePromiseResolver(atob(this._requestId));
|
|
|
|
if (!resolver) {
|
|
|
|
debug("can not find promise resolver for id: " + this._requestId);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
resolver.resolve();
|
|
|
|
},
|
|
|
|
|
|
|
|
notifySuccessWithBoolean: function notifySuccessWithBoolean(aResult) {
|
|
|
|
let resolver = this.takePromiseResolver(atob(this._requestId));
|
|
|
|
if (!resolver) {
|
|
|
|
debug("can not find promise resolver for id: " + this._requestId);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
resolver.resolve(aResult);
|
|
|
|
},
|
|
|
|
|
|
|
|
notifySuccessWithNDEFRecords: function notifySuccessWithNDEFRecords(aRecords) {
|
|
|
|
let resolver = this.takePromiseResolver(atob(this._requestId));
|
|
|
|
if (!resolver) {
|
|
|
|
debug("can not find promise resolver for id: " + this._requestId);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
resolver.resolve(aRecords);
|
|
|
|
},
|
|
|
|
|
2015-01-09 05:42:48 +03:00
|
|
|
notifySuccessWithByteArray: function notifySuccessWithByteArray(aArray) {
|
|
|
|
let resolver = this.takePromiseResolver(atob(this._requestId));
|
|
|
|
if (!resolver) {
|
|
|
|
debug("can not find promise resolver for id: " + this._requestId);
|
|
|
|
return;
|
|
|
|
}
|
2015-01-15 09:55:25 +03:00
|
|
|
resolver.resolve(Cu.cloneInto(aArray, this._window));
|
2015-01-09 05:42:48 +03:00
|
|
|
},
|
|
|
|
|
2014-11-21 12:54:04 +03:00
|
|
|
notifyError: function notifyError(aErrorMsg) {
|
|
|
|
let resolver = this.takePromiseResolver(atob(this._requestId));
|
|
|
|
if (!resolver) {
|
|
|
|
debug("can not find promise resolver for id: " + this._requestId +
|
|
|
|
", errormsg: " + aErrorMsg);
|
|
|
|
return;
|
|
|
|
}
|
2015-01-15 07:17:46 +03:00
|
|
|
resolver.reject(new this._window.Error(aErrorMsg));
|
2014-11-21 12:54:04 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference,
|
|
|
|
Ci.nsIObserver,
|
|
|
|
Ci.nsINfcRequestCallback]),
|
|
|
|
};
|
|
|
|
|
2015-01-13 13:36:43 +03:00
|
|
|
// Should be mapped to the NFCTagType defined in MozNFCTag.webidl.
|
|
|
|
let TagType = {
|
|
|
|
TYPE1: "Type1",
|
|
|
|
TYPE2: "Type2",
|
|
|
|
TYPE3: "Type3",
|
|
|
|
TYPE4: "Type4",
|
|
|
|
MIFARE_CLASSIC: "MIFARE-Classic"
|
|
|
|
};
|
|
|
|
|
2013-11-06 21:53:19 +04:00
|
|
|
/**
|
2014-10-27 12:58:24 +03:00
|
|
|
* Implementation of NFCTag.
|
2014-10-22 07:48:40 +04:00
|
|
|
*
|
2014-12-26 06:50:12 +03:00
|
|
|
* @param window global window object.
|
2014-10-22 07:48:40 +04:00
|
|
|
* @param sessionToken session token received from parent process.
|
2014-12-26 06:50:12 +03:00
|
|
|
* @param tagInfo type of nsITagInfo received from parent process.
|
|
|
|
* @parem ndefInfo type of nsITagNDEFInfo received from parent process.
|
2013-11-06 21:53:19 +04:00
|
|
|
*/
|
2014-12-26 06:50:12 +03:00
|
|
|
function MozNFCTagImpl(window, sessionToken, tagInfo, ndefInfo) {
|
2014-10-27 12:58:24 +03:00
|
|
|
debug("In MozNFCTagImpl Constructor");
|
2013-11-06 21:53:19 +04:00
|
|
|
this._nfcContentHelper = Cc["@mozilla.org/nfc/content-helper;1"]
|
|
|
|
.getService(Ci.nsINfcContentHelper);
|
2014-10-22 07:48:40 +04:00
|
|
|
this._window = window;
|
|
|
|
this.session = sessionToken;
|
2014-12-26 06:50:12 +03:00
|
|
|
this.techList = tagInfo.techList;
|
2014-12-26 11:07:45 +03:00
|
|
|
this.id = Cu.cloneInto(tagInfo.tagId, window);
|
2014-12-26 06:50:12 +03:00
|
|
|
|
|
|
|
if (ndefInfo) {
|
|
|
|
this.type = ndefInfo.tagType;
|
|
|
|
this.maxNDEFSize = ndefInfo.maxNDEFSize;
|
|
|
|
this.isReadOnly = ndefInfo.isReadOnly;
|
|
|
|
this.isFormatable = ndefInfo.isFormatable;
|
2015-01-13 13:36:43 +03:00
|
|
|
this.canBeMadeReadOnly = this.type == TagType.TYPE1 ||
|
|
|
|
this.type == TagType.TYPE2 ||
|
|
|
|
this.type == TagType.MIFARE_CLASSIC;
|
2014-12-26 06:50:12 +03:00
|
|
|
}
|
2013-11-06 21:53:19 +04:00
|
|
|
}
|
2014-10-27 12:58:24 +03:00
|
|
|
MozNFCTagImpl.prototype = {
|
2013-11-06 21:53:19 +04:00
|
|
|
_nfcContentHelper: null,
|
|
|
|
_window: null,
|
2014-10-22 07:48:40 +04:00
|
|
|
session: null,
|
|
|
|
techList: null,
|
2014-12-26 11:07:45 +03:00
|
|
|
id: null,
|
2014-10-22 07:48:40 +04:00
|
|
|
type: null,
|
2014-12-26 06:50:12 +03:00
|
|
|
maxNDEFSize: null,
|
|
|
|
isReadOnly: null,
|
|
|
|
isFormatable: null,
|
|
|
|
canBeMadeReadOnly: null,
|
2014-10-29 06:15:11 +03:00
|
|
|
isLost: false,
|
2013-11-06 21:53:19 +04:00
|
|
|
|
2015-01-13 09:50:24 +03:00
|
|
|
createTech: { "ISO-DEP": (win, tag) => { return new win.MozIsoDepTech(tag); }
|
|
|
|
},
|
|
|
|
|
2013-11-06 21:53:19 +04:00
|
|
|
// NFCTag interface:
|
|
|
|
readNDEF: function readNDEF() {
|
2014-10-29 06:15:11 +03:00
|
|
|
if (this.isLost) {
|
|
|
|
throw new this._window.DOMError("InvalidStateError", "NFCTag object is invalid");
|
|
|
|
}
|
|
|
|
|
2014-11-21 12:54:04 +03:00
|
|
|
let callback = new NfcCallback(this._window);
|
|
|
|
this._nfcContentHelper.readNDEF(this.session, callback);
|
|
|
|
return callback.promise;
|
2013-11-06 21:53:19 +04:00
|
|
|
},
|
2014-10-29 06:15:11 +03:00
|
|
|
|
2013-11-06 21:53:19 +04:00
|
|
|
writeNDEF: function writeNDEF(records) {
|
2014-10-29 06:15:11 +03:00
|
|
|
if (this.isLost) {
|
|
|
|
throw new this._window.DOMError("InvalidStateError", "NFCTag object is invalid");
|
|
|
|
}
|
|
|
|
|
2014-11-05 12:43:54 +03:00
|
|
|
if (this.isReadOnly) {
|
|
|
|
throw new this._window.DOMError("InvalidAccessError", "NFCTag object is read-only");
|
|
|
|
}
|
|
|
|
|
|
|
|
let ndefLen = 0;
|
|
|
|
for (let record of records) {
|
|
|
|
ndefLen += record.size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ndefLen > this.maxNDEFSize) {
|
|
|
|
throw new this._window.DOMError("NotSupportedError", "Exceed max NDEF size");
|
|
|
|
}
|
|
|
|
|
2014-11-21 12:54:04 +03:00
|
|
|
let callback = new NfcCallback(this._window);
|
2015-03-10 11:49:08 +03:00
|
|
|
this._nfcContentHelper.writeNDEF(records, false, this.session, callback);
|
2014-11-21 12:54:04 +03:00
|
|
|
return callback.promise;
|
2013-11-06 21:53:19 +04:00
|
|
|
},
|
2014-10-29 06:15:11 +03:00
|
|
|
|
2014-10-31 09:51:41 +03:00
|
|
|
makeReadOnly: function makeReadOnly() {
|
2014-10-29 06:15:11 +03:00
|
|
|
if (this.isLost) {
|
|
|
|
throw new this._window.DOMError("InvalidStateError", "NFCTag object is invalid");
|
|
|
|
}
|
2014-11-05 12:43:54 +03:00
|
|
|
|
|
|
|
if (!this.canBeMadeReadOnly) {
|
|
|
|
throw new this._window.DOMError("InvalidAccessError",
|
|
|
|
"NFCTag object cannot be made read-only");
|
|
|
|
}
|
|
|
|
|
2014-11-21 12:54:04 +03:00
|
|
|
let callback = new NfcCallback(this._window);
|
|
|
|
this._nfcContentHelper.makeReadOnly(this.session, callback);
|
|
|
|
return callback.promise;
|
2013-11-06 21:53:19 +04:00
|
|
|
},
|
|
|
|
|
2014-11-18 04:52:39 +03:00
|
|
|
format: function format() {
|
|
|
|
if (this.isLost) {
|
|
|
|
throw new this._window.DOMError("InvalidStateError", "NFCTag object is invalid");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.isFormatable) {
|
|
|
|
throw new this._window.DOMError("InvalidAccessError",
|
|
|
|
"NFCTag object is not formatable");
|
|
|
|
}
|
|
|
|
|
2014-11-21 12:54:04 +03:00
|
|
|
let callback = new NfcCallback(this._window);
|
|
|
|
this._nfcContentHelper.format(this.session, callback);
|
|
|
|
return callback.promise;
|
2014-11-18 04:52:39 +03:00
|
|
|
},
|
|
|
|
|
2015-01-13 09:50:24 +03:00
|
|
|
selectTech: function selectTech(tech) {
|
|
|
|
if (this.isLost) {
|
|
|
|
throw new this._window.DOMError("InvalidStateError", "NFCTag object is invalid");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.techList.indexOf(tech) == -1) {
|
|
|
|
throw new this._window.DOMError("InvalidAccessError",
|
|
|
|
"NFCTag does not contain selected tag technology");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.createTech[tech] === undefined) {
|
|
|
|
throw new this._window.DOMError("InvalidAccessError",
|
|
|
|
"Technology is not supported now");
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.createTech[tech](this._window, this._contentObj);
|
|
|
|
},
|
|
|
|
|
2015-01-09 05:42:48 +03:00
|
|
|
transceive: function transceive(tech, cmd) {
|
|
|
|
if (this.isLost) {
|
|
|
|
throw new this._window.DOMError("InvalidStateError", "NFCTag object is invalid");
|
|
|
|
}
|
|
|
|
|
|
|
|
let callback = new NfcCallback(this._window);
|
|
|
|
this._nfcContentHelper.transceive(this.session, tech, cmd, callback);
|
|
|
|
return callback.promise;
|
|
|
|
},
|
|
|
|
|
2014-12-31 12:08:17 +03:00
|
|
|
notifyLost: function notifyLost() {
|
|
|
|
this.isLost = true;
|
|
|
|
},
|
|
|
|
|
2013-11-06 21:53:19 +04:00
|
|
|
classID: Components.ID("{4e1e2e90-3137-11e3-aa6e-0800200c9a66}"),
|
2014-12-26 15:57:11 +03:00
|
|
|
contractID: "@mozilla.org/nfc/tag;1",
|
2013-11-06 21:53:19 +04:00
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
|
|
|
|
Ci.nsIDOMGlobalPropertyInitializer]),
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2014-10-27 12:58:24 +03:00
|
|
|
* Implementation of NFCPeer.
|
|
|
|
*
|
|
|
|
* @param window global window object.
|
|
|
|
* @param sessionToken session token received from parent process.
|
2013-11-06 21:53:19 +04:00
|
|
|
*/
|
2014-10-27 12:58:24 +03:00
|
|
|
function MozNFCPeerImpl(aWindow, aSessionToken) {
|
|
|
|
debug("In MozNFCPeerImpl Constructor");
|
2013-11-06 21:53:19 +04:00
|
|
|
this._nfcContentHelper = Cc["@mozilla.org/nfc/content-helper;1"]
|
|
|
|
.getService(Ci.nsINfcContentHelper);
|
2014-10-23 08:19:22 +04:00
|
|
|
|
|
|
|
this._window = aWindow;
|
|
|
|
this.session = aSessionToken;
|
2013-11-06 21:53:19 +04:00
|
|
|
}
|
2014-10-27 12:58:24 +03:00
|
|
|
MozNFCPeerImpl.prototype = {
|
2013-11-06 21:53:19 +04:00
|
|
|
_nfcContentHelper: null,
|
|
|
|
_window: null,
|
2014-10-29 06:15:11 +03:00
|
|
|
isLost: false,
|
2013-11-06 21:53:19 +04:00
|
|
|
|
|
|
|
// NFCPeer interface:
|
|
|
|
sendNDEF: function sendNDEF(records) {
|
2014-10-29 06:15:11 +03:00
|
|
|
if (this.isLost) {
|
2014-07-29 07:36:58 +04:00
|
|
|
throw new this._window.DOMError("InvalidStateError", "NFCPeer object is invalid");
|
|
|
|
}
|
|
|
|
|
2013-11-06 21:53:19 +04:00
|
|
|
// Just forward sendNDEF to writeNDEF
|
2014-11-21 12:54:04 +03:00
|
|
|
let callback = new NfcCallback(this._window);
|
2015-03-10 11:49:08 +03:00
|
|
|
this._nfcContentHelper.writeNDEF(records, true, this.session, callback);
|
2014-11-21 12:54:04 +03:00
|
|
|
return callback.promise;
|
2013-11-06 21:53:19 +04:00
|
|
|
},
|
|
|
|
|
2013-12-14 11:24:02 +04:00
|
|
|
sendFile: function sendFile(blob) {
|
2014-10-29 06:15:11 +03:00
|
|
|
if (this.isLost) {
|
2014-07-29 07:36:58 +04:00
|
|
|
throw new this._window.DOMError("InvalidStateError", "NFCPeer object is invalid");
|
|
|
|
}
|
|
|
|
|
2013-12-14 11:24:02 +04:00
|
|
|
let data = {
|
2014-04-10 03:38:53 +04:00
|
|
|
"blob": blob
|
2013-12-14 11:24:02 +04:00
|
|
|
};
|
2014-11-21 12:54:04 +03:00
|
|
|
|
|
|
|
let callback = new NfcCallback(this._window);
|
|
|
|
this._nfcContentHelper.sendFile(Cu.cloneInto(data, this._window),
|
|
|
|
this.session, callback);
|
|
|
|
return callback.promise;
|
2013-12-14 11:24:02 +04:00
|
|
|
},
|
|
|
|
|
2014-12-31 12:08:17 +03:00
|
|
|
notifyLost: function notifyLost() {
|
|
|
|
this.isLost = true;
|
|
|
|
},
|
|
|
|
|
2013-11-06 21:53:19 +04:00
|
|
|
classID: Components.ID("{c1b2bcf0-35eb-11e3-aa6e-0800200c9a66}"),
|
2014-12-26 15:57:11 +03:00
|
|
|
contractID: "@mozilla.org/nfc/peer;1",
|
2013-11-06 21:53:19 +04:00
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
|
|
|
|
Ci.nsIDOMGlobalPropertyInitializer]),
|
|
|
|
};
|
|
|
|
|
2014-12-12 10:13:40 +03:00
|
|
|
// Should be mapped to the RFState defined in WebIDL.
|
|
|
|
let RFState = {
|
|
|
|
IDLE: "idle",
|
|
|
|
LISTEN: "listen",
|
|
|
|
DISCOVERY: "discovery"
|
|
|
|
};
|
|
|
|
|
2013-11-06 21:53:19 +04:00
|
|
|
/**
|
2014-10-27 12:58:24 +03:00
|
|
|
* Implementation of navigator NFC object.
|
2013-11-06 21:53:19 +04:00
|
|
|
*/
|
2014-10-27 12:58:24 +03:00
|
|
|
function MozNFCImpl() {
|
|
|
|
debug("In MozNFCImpl Constructor");
|
2013-12-11 10:04:27 +04:00
|
|
|
try {
|
|
|
|
this._nfcContentHelper = Cc["@mozilla.org/nfc/content-helper;1"]
|
|
|
|
.getService(Ci.nsINfcContentHelper);
|
|
|
|
} catch(e) {
|
2015-01-13 09:50:24 +03:00
|
|
|
debug("No NFC support.");
|
2013-12-11 10:04:27 +04:00
|
|
|
}
|
2014-07-24 08:16:02 +04:00
|
|
|
|
2014-11-19 06:00:16 +03:00
|
|
|
this.eventService = Cc["@mozilla.org/eventlistenerservice;1"]
|
|
|
|
.getService(Ci.nsIEventListenerService);
|
2013-11-06 21:53:19 +04:00
|
|
|
}
|
2014-10-27 12:58:24 +03:00
|
|
|
MozNFCImpl.prototype = {
|
2013-11-06 21:53:19 +04:00
|
|
|
_nfcContentHelper: null,
|
|
|
|
_window: null,
|
2014-11-25 10:10:34 +03:00
|
|
|
_rfState: null,
|
2015-01-13 09:50:24 +03:00
|
|
|
_contentObj: null,
|
2014-10-29 06:15:11 +03:00
|
|
|
nfcPeer: null,
|
|
|
|
nfcTag: null,
|
2014-11-19 06:00:16 +03:00
|
|
|
eventService: null,
|
2014-07-25 14:03:37 +04:00
|
|
|
|
2013-11-06 21:53:19 +04:00
|
|
|
init: function init(aWindow) {
|
2014-10-27 12:58:24 +03:00
|
|
|
debug("MozNFCImpl init called");
|
2013-11-06 21:53:19 +04:00
|
|
|
this._window = aWindow;
|
2014-10-20 13:53:39 +04:00
|
|
|
this.defineEventHandlerGetterSetter("ontagfound");
|
|
|
|
this.defineEventHandlerGetterSetter("ontaglost");
|
|
|
|
this.defineEventHandlerGetterSetter("onpeerready");
|
2014-10-30 09:08:00 +03:00
|
|
|
this.defineEventHandlerGetterSetter("onpeerfound");
|
2014-10-20 13:53:39 +04:00
|
|
|
this.defineEventHandlerGetterSetter("onpeerlost");
|
|
|
|
|
2014-10-14 12:37:50 +04:00
|
|
|
if (this._nfcContentHelper) {
|
|
|
|
this._nfcContentHelper.init(aWindow);
|
2015-01-22 12:40:17 +03:00
|
|
|
this._nfcContentHelper.addEventListener(this);
|
2014-11-25 10:10:34 +03:00
|
|
|
this._rfState = this._nfcContentHelper.queryRFState();
|
2014-10-14 12:37:50 +04:00
|
|
|
}
|
2013-11-25 08:40:39 +04:00
|
|
|
},
|
|
|
|
|
2014-04-15 10:47:42 +04:00
|
|
|
// Only apps which have nfc-manager permission can call the following interfaces
|
|
|
|
// 'checkP2PRegistration' , 'notifyUserAcceptedP2P' , 'notifySendFileStatus',
|
|
|
|
// 'startPoll', 'stopPoll', and 'powerOff'.
|
2013-11-25 08:40:39 +04:00
|
|
|
checkP2PRegistration: function checkP2PRegistration(manifestUrl) {
|
|
|
|
// Get the AppID and pass it to ContentHelper
|
|
|
|
let appID = appsService.getAppLocalIdByManifestURL(manifestUrl);
|
2014-11-21 12:54:04 +03:00
|
|
|
|
|
|
|
let callback = new NfcCallback(this._window);
|
|
|
|
this._nfcContentHelper.checkP2PRegistration(appID, callback);
|
|
|
|
return callback.promise;
|
2013-11-06 21:53:19 +04:00
|
|
|
},
|
|
|
|
|
2014-01-18 06:38:26 +04:00
|
|
|
notifyUserAcceptedP2P: function notifyUserAcceptedP2P(manifestUrl) {
|
|
|
|
let appID = appsService.getAppLocalIdByManifestURL(manifestUrl);
|
|
|
|
// Notify chrome process of user's acknowledgement
|
2014-10-30 13:46:41 +03:00
|
|
|
this._nfcContentHelper.notifyUserAcceptedP2P(appID);
|
2014-01-18 06:38:26 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
notifySendFileStatus: function notifySendFileStatus(status, requestId) {
|
2014-10-30 13:46:41 +03:00
|
|
|
this._nfcContentHelper.notifySendFileStatus(status, requestId);
|
2014-01-18 06:38:26 +04:00
|
|
|
},
|
|
|
|
|
2014-04-15 10:47:42 +04:00
|
|
|
startPoll: function startPoll() {
|
2014-11-21 12:54:04 +03:00
|
|
|
let callback = new NfcCallback(this._window);
|
2014-12-12 10:13:40 +03:00
|
|
|
this._nfcContentHelper.changeRFState(RFState.DISCOVERY, callback);
|
2014-11-21 12:54:04 +03:00
|
|
|
return callback.promise;
|
2014-04-15 10:47:42 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
stopPoll: function stopPoll() {
|
2014-11-21 12:54:04 +03:00
|
|
|
let callback = new NfcCallback(this._window);
|
2014-12-12 10:13:40 +03:00
|
|
|
this._nfcContentHelper.changeRFState(RFState.LISTEN, callback);
|
2014-11-21 12:54:04 +03:00
|
|
|
return callback.promise;
|
2014-04-15 10:47:42 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
powerOff: function powerOff() {
|
2014-11-21 12:54:04 +03:00
|
|
|
let callback = new NfcCallback(this._window);
|
2014-12-12 10:13:40 +03:00
|
|
|
this._nfcContentHelper.changeRFState(RFState.IDLE, callback);
|
2014-11-21 12:54:04 +03:00
|
|
|
return callback.promise;
|
2014-04-15 10:47:42 +04:00
|
|
|
},
|
|
|
|
|
2014-12-12 10:13:40 +03:00
|
|
|
get enabled() {
|
|
|
|
return this._rfState != RFState.IDLE;
|
|
|
|
},
|
|
|
|
|
2014-10-20 13:53:39 +04: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-25 08:40:39 +04:00
|
|
|
},
|
|
|
|
|
2014-09-09 13:56:00 +04:00
|
|
|
eventListenerWasAdded: function(eventType) {
|
|
|
|
if (eventType !== "peerready") {
|
2013-11-25 08:40:39 +04:00
|
|
|
return;
|
2014-07-24 14:11:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
let appId = this._window.document.nodePrincipal.appId;
|
2014-10-30 13:46:41 +03:00
|
|
|
this._nfcContentHelper.registerTargetForPeerReady(appId);
|
2013-11-25 08:40:39 +04:00
|
|
|
},
|
|
|
|
|
2014-09-09 13:56:00 +04:00
|
|
|
eventListenerWasRemoved: function(eventType) {
|
|
|
|
if (eventType !== "peerready") {
|
2013-11-25 08:40:39 +04:00
|
|
|
return;
|
2014-07-24 14:11:42 +04:00
|
|
|
}
|
2013-11-25 08:40:39 +04:00
|
|
|
|
|
|
|
let appId = this._window.document.nodePrincipal.appId;
|
2014-10-30 13:46:41 +03:00
|
|
|
this._nfcContentHelper.unregisterTargetForPeerReady(appId);
|
2014-07-24 08:16:02 +04:00
|
|
|
},
|
|
|
|
|
2014-12-26 06:50:12 +03:00
|
|
|
notifyTagFound: function notifyTagFound(sessionToken, tagInfo, ndefInfo, records) {
|
2014-12-11 12:42:35 +03:00
|
|
|
if (!this.handleTagFound(sessionToken, tagInfo, ndefInfo, records)) {
|
|
|
|
this._nfcContentHelper.callDefaultFoundHandler(sessionToken, false, records);
|
|
|
|
};
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles Tag Found event.
|
|
|
|
*
|
|
|
|
* returns true if the app could process this event, false otherwise.
|
|
|
|
*/
|
|
|
|
handleTagFound: function handleTagFound(sessionToken, tagInfo, ndefInfo, records) {
|
2014-10-20 13:53:39 +04:00
|
|
|
if (this.hasDeadWrapper()) {
|
|
|
|
dump("this._window or this.__DOM_IMPL__ is a dead wrapper.");
|
2014-12-11 12:42:35 +03:00
|
|
|
return false;
|
2014-10-20 13:53:39 +04:00
|
|
|
}
|
|
|
|
|
2014-11-19 06:00:16 +03:00
|
|
|
if (!this.eventService.hasListenersFor(this.__DOM_IMPL__, "tagfound")) {
|
|
|
|
debug("ontagfound is not registered.");
|
2014-12-11 12:42:35 +03:00
|
|
|
return false;
|
2014-11-19 06:00:16 +03:00
|
|
|
}
|
|
|
|
|
2014-11-06 06:12:38 +03:00
|
|
|
if (!this.checkPermissions(["nfc"])) {
|
2014-12-11 12:42:35 +03:00
|
|
|
return false;
|
2014-10-28 09:58:47 +03:00
|
|
|
}
|
|
|
|
|
2014-12-26 06:50:12 +03:00
|
|
|
let tagImpl = new MozNFCTagImpl(this._window, sessionToken, tagInfo, ndefInfo);
|
2014-10-27 12:58:24 +03:00
|
|
|
let tag = this._window.MozNFCTag._create(this._window, tagImpl);
|
2015-01-13 09:50:24 +03:00
|
|
|
|
|
|
|
tagImpl._contentObj = tag;
|
2014-10-29 06:15:11 +03:00
|
|
|
this.nfcTag = tag;
|
2014-10-20 13:53:39 +04:00
|
|
|
|
|
|
|
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 = {
|
2014-12-11 12:42:35 +03:00
|
|
|
"cancelable": true,
|
2014-10-27 12:58:24 +03:00
|
|
|
"tag": tag,
|
2014-10-20 13:53:39 +04:00
|
|
|
"ndefRecords": ndefRecords
|
|
|
|
};
|
|
|
|
|
|
|
|
debug("fire ontagfound " + sessionToken);
|
|
|
|
let tagEvent = new this._window.MozNFCTagEvent("tagfound", eventData);
|
|
|
|
this.__DOM_IMPL__.dispatchEvent(tagEvent);
|
2014-12-11 12:42:35 +03:00
|
|
|
|
|
|
|
// If defaultPrevented is false, means we need to take the default action
|
|
|
|
// for this event - redirect this event to System app. Before redirecting to
|
|
|
|
// System app, we need revoke the tag object first.
|
|
|
|
if (!tagEvent.defaultPrevented) {
|
|
|
|
this.notifyTagLost(sessionToken);
|
|
|
|
}
|
|
|
|
|
|
|
|
return tagEvent.defaultPrevented;
|
2014-10-20 13:53:39 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
notifyTagLost: function notifyTagLost(sessionToken) {
|
2015-01-28 05:48:17 +03:00
|
|
|
if (!this.handleTagLost(sessionToken)) {
|
|
|
|
this._nfcContentHelper.callDefaultLostHandler(sessionToken, false);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
handleTagLost: function handleTagLost(sessionToken) {
|
2014-10-20 13:53:39 +04:00
|
|
|
if (this.hasDeadWrapper()) {
|
|
|
|
dump("this._window or this.__DOM_IMPL__ is a dead wrapper.");
|
2015-01-28 05:48:17 +03:00
|
|
|
return false;
|
2014-10-20 13:53:39 +04:00
|
|
|
}
|
|
|
|
|
2014-11-06 06:12:38 +03:00
|
|
|
if (!this.checkPermissions(["nfc"])) {
|
2015-01-28 05:48:17 +03:00
|
|
|
return false;
|
2014-10-28 09:58:47 +03:00
|
|
|
}
|
|
|
|
|
2014-11-19 06:00:16 +03:00
|
|
|
if (!this.nfcTag) {
|
|
|
|
debug("No NFCTag object existing.");
|
2015-01-28 05:48:17 +03:00
|
|
|
return false;
|
2014-10-29 06:15:11 +03:00
|
|
|
}
|
|
|
|
|
2014-12-31 12:08:17 +03:00
|
|
|
this.nfcTag.notifyLost();
|
2014-11-19 06:00:16 +03:00
|
|
|
this.nfcTag = null;
|
|
|
|
|
2014-10-20 13:53:39 +04:00
|
|
|
debug("fire ontaglost " + sessionToken);
|
|
|
|
let event = new this._window.Event("taglost");
|
|
|
|
this.__DOM_IMPL__.dispatchEvent(event);
|
2015-01-28 05:48:17 +03:00
|
|
|
|
|
|
|
return true;
|
2014-10-20 13:53:39 +04:00
|
|
|
},
|
|
|
|
|
2014-10-30 09:08:00 +03:00
|
|
|
notifyPeerFound: function notifyPeerFound(sessionToken, isPeerReady) {
|
2014-12-11 12:42:35 +03:00
|
|
|
if (!this.handlePeerFound(sessionToken, isPeerReady)) {
|
|
|
|
this._nfcContentHelper.callDefaultFoundHandler(sessionToken, true, null);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles Peer Found/Peer Ready event.
|
|
|
|
*
|
|
|
|
* returns true if the app could process this event, false otherwise.
|
|
|
|
*/
|
|
|
|
handlePeerFound: function handlePeerFound(sessionToken, isPeerReady) {
|
2014-07-24 08:16:02 +04:00
|
|
|
if (this.hasDeadWrapper()) {
|
|
|
|
dump("this._window or this.__DOM_IMPL__ is a dead wrapper.");
|
2014-12-11 12:42:35 +03:00
|
|
|
return false;
|
2014-07-24 08:16:02 +04:00
|
|
|
}
|
|
|
|
|
2014-11-19 06:00:16 +03:00
|
|
|
if (!isPeerReady &&
|
|
|
|
!this.eventService.hasListenersFor(this.__DOM_IMPL__, "peerfound")) {
|
|
|
|
debug("onpeerfound is not registered.");
|
2014-12-11 12:42:35 +03:00
|
|
|
return false;
|
2014-11-19 06:00:16 +03:00
|
|
|
}
|
|
|
|
|
2014-11-06 06:12:38 +03:00
|
|
|
let perm = isPeerReady ? ["nfc-share"] : ["nfc"];
|
|
|
|
if (!this.checkPermissions(perm)) {
|
2014-12-11 12:42:35 +03:00
|
|
|
return false;
|
2014-10-30 09:08:00 +03:00
|
|
|
}
|
|
|
|
|
2014-11-26 10:02:36 +03:00
|
|
|
let peerImpl = new MozNFCPeerImpl(this._window, sessionToken);
|
2015-01-13 09:50:24 +03:00
|
|
|
this.nfcPeer = this._window.MozNFCPeer._create(this._window, peerImpl);
|
2014-07-24 08:16:02 +04:00
|
|
|
|
2014-12-11 12:42:35 +03:00
|
|
|
let eventType;
|
|
|
|
let eventData = {
|
|
|
|
"peer": this.nfcPeer
|
|
|
|
};
|
|
|
|
|
|
|
|
if (isPeerReady) {
|
|
|
|
eventType = "peerready";
|
|
|
|
} else {
|
|
|
|
eventData.cancelable = true;
|
|
|
|
eventType = "peerfound";
|
|
|
|
}
|
|
|
|
|
|
|
|
debug("fire on" + eventType + " " + sessionToken);
|
|
|
|
let event = new this._window.MozNFCPeerEvent(eventType, eventData);
|
2014-07-24 08:16:02 +04:00
|
|
|
this.__DOM_IMPL__.dispatchEvent(event);
|
2014-12-11 12:42:35 +03:00
|
|
|
|
|
|
|
// For peerready we don't take the default action.
|
|
|
|
if (isPeerReady) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If defaultPrevented is false, means we need to take the default action
|
|
|
|
// for this event - redirect this event to System app. Before redirecting to
|
|
|
|
// System app, we need revoke the peer object first.
|
|
|
|
if (!event.defaultPrevented) {
|
|
|
|
this.notifyPeerLost(sessionToken);
|
|
|
|
}
|
|
|
|
|
|
|
|
return event.defaultPrevented;
|
2014-07-24 08:16:02 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
notifyPeerLost: function notifyPeerLost(sessionToken) {
|
2015-01-28 05:48:17 +03:00
|
|
|
if (!this.handlePeerLost(sessionToken)) {
|
|
|
|
this._nfcContentHelper.callDefaultLostHandler(sessionToken, true);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
handlePeerLost: function handlePeerLost(sessionToken) {
|
2014-07-24 08:16:02 +04:00
|
|
|
if (this.hasDeadWrapper()) {
|
|
|
|
dump("this._window or this.__DOM_IMPL__ is a dead wrapper.");
|
2015-01-28 05:48:17 +03:00
|
|
|
return false;
|
2014-07-24 08:16:02 +04:00
|
|
|
}
|
|
|
|
|
2014-11-06 06:12:38 +03:00
|
|
|
if (!this.checkPermissions(["nfc", "nfc-share"])) {
|
2015-01-28 05:48:17 +03:00
|
|
|
return false;
|
2014-10-30 09:08:00 +03:00
|
|
|
}
|
|
|
|
|
2014-11-19 06:00:16 +03:00
|
|
|
if (!this.nfcPeer) {
|
|
|
|
debug("No NFCPeer object existing.");
|
2015-01-28 05:48:17 +03:00
|
|
|
return false;
|
2014-07-24 08:16:02 +04:00
|
|
|
}
|
|
|
|
|
2014-12-31 12:08:17 +03:00
|
|
|
this.nfcPeer.notifyLost();
|
2014-11-19 06:00:16 +03:00
|
|
|
this.nfcPeer = null;
|
2014-07-24 08:16:02 +04:00
|
|
|
|
|
|
|
debug("fire onpeerlost");
|
|
|
|
let event = new this._window.Event("peerlost");
|
|
|
|
this.__DOM_IMPL__.dispatchEvent(event);
|
2015-01-28 05:48:17 +03:00
|
|
|
|
|
|
|
return true;
|
2013-11-25 08:40:39 +04:00
|
|
|
},
|
|
|
|
|
2015-01-26 13:13:36 +03:00
|
|
|
notifyRFStateChanged: function notifyRFStateChanged(rfState) {
|
2014-11-25 10:10:34 +03:00
|
|
|
this._rfState = rfState;
|
|
|
|
},
|
|
|
|
|
2015-01-26 13:58:52 +03:00
|
|
|
notifyFocusChanged: function notifyFocusChanged(focus) {
|
|
|
|
if (focus) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.nfcTag) {
|
|
|
|
debug("losing focus, call taglost.");
|
|
|
|
this.notifyTagLost(this.nfcTag.session);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.nfcPeer) {
|
|
|
|
debug("losing focus, call peerlost.");
|
|
|
|
this.notifyPeerLost(this.nfcPeer.session);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2014-10-28 09:58:47 +03: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 11:43:45 +04:00
|
|
|
hasDeadWrapper: function hasDeadWrapper() {
|
|
|
|
return Cu.isDeadWrapper(this._window) || Cu.isDeadWrapper(this.__DOM_IMPL__);
|
|
|
|
},
|
|
|
|
|
2013-11-06 21:53:19 +04:00
|
|
|
classID: Components.ID("{6ff2b290-2573-11e3-8224-0800200c9a66}"),
|
2014-12-26 15:57:11 +03:00
|
|
|
contractID: "@mozilla.org/nfc/manager;1",
|
2013-11-06 21:53:19 +04:00
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
|
2014-07-24 08:16:02 +04:00
|
|
|
Ci.nsIDOMGlobalPropertyInitializer,
|
2015-01-26 12:27:57 +03:00
|
|
|
Ci.nsINfcEventListener]),
|
2013-11-06 21:53:19 +04:00
|
|
|
};
|
|
|
|
|
2014-11-17 12:41:18 +03:00
|
|
|
function NFCSendFileWrapper() {
|
|
|
|
}
|
|
|
|
NFCSendFileWrapper.prototype = {
|
|
|
|
// nsISystemMessagesWrapper implementation.
|
|
|
|
wrapMessage: function wrapMessage(aMessage, aWindow) {
|
|
|
|
let peerImpl = new MozNFCPeerImpl(aWindow, aMessage.sessionToken);
|
|
|
|
let peer = aWindow.MozNFCPeer._create(aWindow, peerImpl);
|
|
|
|
|
|
|
|
delete aMessage.sessionToken;
|
|
|
|
aMessage = Cu.cloneInto(aMessage, aWindow);
|
|
|
|
aMessage.peer = peer;
|
|
|
|
return aMessage;
|
|
|
|
},
|
|
|
|
|
|
|
|
classDescription: "NFCSendFileWrapper",
|
|
|
|
classID: Components.ID("{c5063a5c-8cb9-41d2-baf5-56062a2e30e9}"),
|
|
|
|
contractID: "@mozilla.org/dom/system-messages/wrapper/nfc-manager-send-file;1",
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsISystemMessagesWrapper])
|
|
|
|
};
|
|
|
|
|
2014-11-17 13:00:14 +03:00
|
|
|
function NFCTechDiscoveredWrapper() {
|
|
|
|
}
|
|
|
|
NFCTechDiscoveredWrapper.prototype = {
|
|
|
|
// nsISystemMessagesWrapper implementation.
|
|
|
|
wrapMessage: function wrapMessage(aMessage, aWindow) {
|
|
|
|
aMessage = Cu.cloneInto(aMessage, aWindow);
|
2014-12-09 13:51:29 +03:00
|
|
|
if (aMessage.isP2P) {
|
2014-11-17 13:00:14 +03:00
|
|
|
let peerImpl = new MozNFCPeerImpl(aWindow, aMessage.sessionToken);
|
|
|
|
let peer = aWindow.MozNFCPeer._create(aWindow, peerImpl);
|
|
|
|
aMessage.peer = peer;
|
|
|
|
}
|
2014-12-15 13:01:34 +03:00
|
|
|
|
|
|
|
delete aMessage.isP2P;
|
|
|
|
delete aMessage.sessionToken;
|
|
|
|
|
2014-11-17 13:00:14 +03:00
|
|
|
return aMessage;
|
|
|
|
},
|
|
|
|
|
|
|
|
classDescription: "NFCTechDiscoveredWrapper",
|
|
|
|
classID: Components.ID("{2e7f9285-3c72-4e1f-b985-141a00a23a75}"),
|
|
|
|
contractID: "@mozilla.org/dom/system-messages/wrapper/nfc-manager-tech-discovered;1",
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsISystemMessagesWrapper])
|
|
|
|
};
|
|
|
|
|
2014-10-27 12:58:24 +03:00
|
|
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MozNFCTagImpl,
|
2014-11-17 13:00:14 +03:00
|
|
|
MozNFCPeerImpl, MozNFCImpl, NFCSendFileWrapper, NFCTechDiscoveredWrapper]);
|