Bug 916428 - [NFC] APIs for ISO 14443-4 tags (IsoDep Support). r=smaug, r=yoshi

This commit is contained in:
Dimi Lee 2015-01-13 14:50:24 +08:00
parent e0652c5424
commit 18e68dead8
7 changed files with 202 additions and 5 deletions

101
dom/nfc/MozIsoDepTech.cpp Normal file
View File

@ -0,0 +1,101 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=2 et sw=2 tw=80:
*
* 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/. */
#include "MozIsoDepTech.h"
#include "mozilla/dom/Promise.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_CLASS(MozIsoDepTech)
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(MozIsoDepTech)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(MozIsoDepTech)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTag)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MozIsoDepTech)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTag)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(MozIsoDepTech)
NS_IMPL_CYCLE_COLLECTING_RELEASE(MozIsoDepTech)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MozIsoDepTech)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
/* static */
already_AddRefed<MozIsoDepTech>
MozIsoDepTech::Constructor(const GlobalObject& aGlobal,
MozNFCTag& aNFCTag,
ErrorResult& aRv)
{
ErrorResult rv;
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aGlobal.GetAsSupports());
if (!win) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
Nullable<nsTArray<NFCTechType>> techList;
aNFCTag.GetTechList(techList, rv);
if (rv.Failed()) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
if (techList.IsNull() || !(techList.Value().Contains(mTechnology))) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}
nsRefPtr<MozIsoDepTech> isoDep = new MozIsoDepTech(win, aNFCTag);
return isoDep.forget();
}
MozIsoDepTech::MozIsoDepTech(nsPIDOMWindow* aWindow, MozNFCTag& aNFCTag)
: mWindow(aWindow)
, mTag(&aNFCTag)
{
}
MozIsoDepTech::~MozIsoDepTech()
{
}
already_AddRefed<Promise>
MozIsoDepTech::Transceive(const Uint8Array& aCommand, ErrorResult& aRv)
{
ErrorResult rv;
aCommand.ComputeLengthAndData();
nsRefPtr<Promise> promise = mTag->Transceive(mTechnology, aCommand, rv);
if (rv.Failed()) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
return promise.forget();
}
JSObject*
MozIsoDepTech::WrapObject(JSContext* aCx)
{
return MozIsoDepTechBinding::Wrap(aCx, this);
}
} // namespace dom
} // namespace mozilla

54
dom/nfc/MozIsoDepTech.h Normal file
View File

@ -0,0 +1,54 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=2 et sw=2 tw=80:
*
* 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/. */
#ifndef mozilla_dom_nfc_MozIsoDepTech_h__
#define mozilla_dom_nfc_MozIsoDepTech_h__
#include "mozilla/dom/MozNFCTagBinding.h"
#include "mozilla/dom/MozIsoDepTechBinding.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
#include "nsISupportsImpl.h"
#include "nsPIDOMWindow.h"
namespace mozilla {
namespace dom {
class Promise;
class MozIsoDepTech : public nsISupports,
public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MozIsoDepTech)
already_AddRefed<Promise> Transceive(const Uint8Array& aCommand,
ErrorResult& aRv);
nsPIDOMWindow* GetParentObject() const { return mWindow; }
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
static already_AddRefed<MozIsoDepTech>
Constructor(const GlobalObject& aGlobal, MozNFCTag& aNFCTag,
ErrorResult& aRv);
private:
MozIsoDepTech(nsPIDOMWindow* aWindow, MozNFCTag& aNFCTag);
virtual ~MozIsoDepTech();
nsRefPtr<nsPIDOMWindow> mWindow;
nsRefPtr<MozNFCTag> mTag;
static const NFCTechType mTechnology = NFCTechType::ISO_DEP;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_nfc_MozIsoDepTech_h__

View File

@ -12,9 +12,11 @@ if CONFIG['MOZ_NFC']:
'nsINfcContentHelper.idl',
]
EXPORTS.mozilla.dom += [
'MozIsoDepTech.h',
'MozNDEFRecord.h',
]
UNIFIED_SOURCES += [
'MozIsoDepTech.cpp',
'MozNDEFRecord.cpp',
]
EXTRA_COMPONENTS += [

View File

@ -137,6 +137,9 @@ MozNFCTagImpl.prototype = {
canBeMadeReadOnly: null,
isLost: false,
createTech: { "ISO-DEP": (win, tag) => { return new win.MozIsoDepTech(tag); }
},
// NFCTag interface:
readNDEF: function readNDEF() {
if (this.isLost) {
@ -201,6 +204,24 @@ MozNFCTagImpl.prototype = {
return callback.promise;
},
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);
},
transceive: function transceive(tech, cmd) {
if (this.isLost) {
throw new this._window.DOMError("InvalidStateError", "NFCTag object is invalid");
@ -293,7 +314,7 @@ function MozNFCImpl() {
this._nfcContentHelper = Cc["@mozilla.org/nfc/content-helper;1"]
.getService(Ci.nsINfcContentHelper);
} catch(e) {
debug("No NFC support.")
debug("No NFC support.");
}
this.eventService = Cc["@mozilla.org/eventlistenerservice;1"]
@ -304,6 +325,7 @@ MozNFCImpl.prototype = {
_nfcContentHelper: null,
_window: null,
_rfState: null,
_contentObj: null,
nfcPeer: null,
nfcTag: null,
eventService: null,
@ -416,6 +438,8 @@ MozNFCImpl.prototype = {
let tagImpl = new MozNFCTagImpl(this._window, sessionToken, tagInfo, ndefInfo);
let tag = this._window.MozNFCTag._create(this._window, tagImpl);
tagImpl._contentObj = tag;
this.nfcTag = tag;
let length = records ? records.length : 0;
@ -488,7 +512,7 @@ MozNFCImpl.prototype = {
this, /* useCapture */false);
let peerImpl = new MozNFCPeerImpl(this._window, sessionToken);
this.nfcPeer = this._window.MozNFCPeer._create(this._window, peerImpl)
this.nfcPeer = this._window.MozNFCPeer._create(this._window, peerImpl);
let eventData = { "peer": this.nfcPeer };
let type = (isPeerReady) ? "peerready" : "peerfound";

View File

@ -0,0 +1,13 @@
/* 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/. */
[Func="Navigator::HasNFCSupport", AvailableIn="PrivilegedApps",
ChromeConstructor(MozNFCTag tag)]
interface MozIsoDepTech {
/**
* Send raw command to tag and receive the response.
*/
[Throws]
Promise<Uint8Array> transceive(Uint8Array command);
};

View File

@ -35,6 +35,8 @@ enum NFCTagType {
"MIFARE-Classic"
};
typedef MozIsoDepTech MozTagTech;
[JSImplementation="@mozilla.org/nfc/tag;1", AvailableIn="PrivilegedApps"]
interface MozNFCTag {
/**
@ -100,6 +102,9 @@ interface MozNFCTag {
*/
[Throws]
Promise<void> format();
[NewObject, Throws]
MozTagTech selectTech(NFCTechType tech);
};
// Mozilla Only
@ -110,9 +115,6 @@ partial interface MozNFCTag {
[ChromeOnly]
void notifyLost();
/**
* Send raw command to tag and receive the response.
*/
[ChromeOnly, Throws]
Promise<Uint8Array> transceive(NFCTechType tech, Uint8Array command);
};

View File

@ -648,6 +648,7 @@ if CONFIG['MOZ_B2G_RIL']:
if CONFIG['MOZ_NFC']:
WEBIDL_FILES += [
'MozIsoDepTech.webidl',
'MozNDEFRecord.webidl',
'MozNFC.webidl',
'MozNFCPeer.webidl',