WebAPI/WebNFC: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
Line 1: Line 1:
= Introduction =
= Introduction =
== Current Status (As to Firefox OS v1.4) ==
== Current Status (As to Firefox OS v2.0) ==
* b2g-NFC-2.0, {{bug|949293}}
* Gecko meta bug, {{bug|860906}}
* Gecko meta bug, {{bug|860906}}
* Gaia meta bug,  {{bug|933640}}
* Gaia meta bug,  {{bug|933640}}
Line 6: Line 7:
** Use a native daemon nfcd which links to native NFC library. [https://github.com/mozilla-b2g/platform_system_nfcd nfcd github]
** Use a native daemon nfcd which links to native NFC library. [https://github.com/mozilla-b2g/platform_system_nfcd nfcd github]
* Hardware
* Hardware
** Using Nexus-4, which uses Broadcom NFC chipset with libnfc-nci library.
** Using Nexus-4/Nexus-5, which uses Broadcom NFC chipset with libnfc-nci library.
** Flame, NXP chipsets with libnfc-nci library.


== Security Review (By Paul Theriault) ==
== Security Review (By Paul Theriault) ==

Revision as of 03:02, 12 June 2014

Introduction

Current Status (As to Firefox OS v2.0)

  • b2g-NFC-2.0, bug 949293
  • Gecko meta bug, bug 860906
  • Gaia meta bug, bug 933640
  • Gonk
    • Use a native daemon nfcd which links to native NFC library. nfcd github
  • Hardware
    • Using Nexus-4/Nexus-5, which uses Broadcom NFC chipset with libnfc-nci library.
    • Flame, NXP chipsets with libnfc-nci library.

Security Review (By Paul Theriault)

Contributors

  • Gecko Engineers: Arno Puder, Garner Lee, Siddartha Pothapragada, Yoshi Huang, Dimi Lee
  • Early Contributors: Markus Neubrand, Philipp von Weitershausen

Roadmap

First iteration: NDEF (Firefox OS v1.3)

  • meta bug, bug 959692 - (b2g-NFC-1.3) [meta] FxOS v1.3 NFC feature
  • Technologies:
    • Focus on NDEF standard only for now
    • Others (e.g. proprietary MIFARE) to be investigated later.
  • Capabilities:
    • Read/write NDEF records on tags
    • bug 933136 - [Gecko] NFC onpeerready, onpeerlost callbacks
  • Implementation:
    • See bug 674741
    • NDEF-only API is available on MozNFCTag object.
    • Discovered NDEF tags are automatically parsed and dispatched to content in the "nfc-manager-tech-discovered" system message.
    • navigator.mozNfc only available to a specific privileged content page (cf. WebTelephony, WebSMS).
    • For now, content is expected to do filtering and dispatching to handlers e.g. via WebActivity.
  • Gonk
    • bug 906579 - B2G NFC: NFC Daemon for supporting libnfc-nci
  • Hardware
    • Using Nexus-4, which uses Broadcom NFC chipset with libnfc-nci library.

Second iteration: Handover and other bug fixes (Firefox OS v1.4)

  • meta bug : bug 949293 - (b2g-NFC-1.4) [meta] FxOS v1.4 NFC feature
  • Technologies:
  • Capabilities:
    • bug 933093 NFC handover.
    • bug 916863 - [NFC] NFC support in emulator
    • NFC Manager API
      • bug 952217 - [B2G][NFC] Have a separate NFC application API and NFC Manager API
      • bug 959437 - Refactor NfcManager APIs and implementation details to support sendFile , notifyUserAcceptedP2P and other privileged Nfc operations

Third iteration: Secure Element (Firefox OS v1.5 >)

Current API

MozNFCTag.webidl

 enum NFCTechType {
   "NFC_A",
   "NFC_B",
   "NFC_ISO_DEP",
   "NFC_F",
   "NFC_V",
   "NDEF",
   "NDEF_FORMATABLE",
   "MIFARE_CLASSIC",
   "MIFARE_ULTRALIGHT",
   "NFC_BARCODE",
   "P2P",
   "UNKNOWN_TECH"
 };

 interface MozNFCTag : EventTarget {
   DOMRequest getDetailsNDEF();
   DOMRequest readNDEF();
   DOMRequest writeNDEF(sequence<MozNDEFRecord> records);
   DOMRequest makeReadOnlyNDEF();

   DOMRequest connect(NFCTechType techType);
   DOMRequest close();
 };

MozNFCPeer.webidl

sendNDEF does a P2P send of an NDEF formatted message to another NFC enabled device. NFCPeer will also handle send a generic blob in handover requests where a NDEF formatted "handover" message will conditionally trigger pairing with another device over an available Bluetooth or Wifi connection.

 interface MozNFCPeer : EventTarget {
   DOMRequest sendNDEF(sequence<MozNDEFRecord> records);
   DOMRequest sendFile(Blob blob);
 };

MozNDEFRecord.webidl

NDEF records contain a bunch of metadata and a payload that is exposed as a Uint8Array.

 interface MozNDEFRecord {
   /**
    * Type Name Field (3-bits) - Specifies the NDEF record type in general.
    * tnf_empty: 0x00
    * tnf_well_known: 0x01
    * tnf_mime_media: 0x02
    * tnf_absolute_uri: 0x03
    * tnf_external type: 0x04
    * tnf_unknown: 0x05
    * tnf_unchanged: 0x06
    * tnf_reserved: 0x07
    */
   readonly attribute octet tnf;

   /**
    * type - Describes the content of the payload. This can be a mime type.
    */
   readonly attribute Uint8Array type;

   /**
    * id - Identifer is application dependent.
    */
   readonly attribute Uint8Array id;

   /**
    * payload - Binary data blob. The meaning of this field is application dependent.
    */
   readonly attribute Uint8Array payload;
 };

MozNfc.webidl

interface MozNfc : EventTarget {
  MozNFCTag getNFCTag(DOMString sessionId);
  MozNFCPeer getNFCPeer(DOMString sessionId);

  [Func="Navigator::HasNfcPeerSupport"]
  attribute EventHandler onpeerready;
  [Func="Navigator::HasNfcPeerSupport"]
  attribute EventHandler onpeerlost;
};

Check bug 933136, or onpeerready for how onpeerready is called.

Usage of APIs

Receiving NDEF messages, via MozActivity

Setup an Activity handler for incoming NDEF messages. The web activity chooser UI will route the messsage to the user selected application if there is more than one match. Currently, only NDEF is supported, although individual nfc tags can actually be compatible with multiple legacy and proprietary technology types.

Applications that do not have "nfc" read or write permissions can still get NDEF events via activities, and act on the data. The raw NDEF data is included with the activity, should the application wish to process any special properties of more complex NDEF data structures.

If the NFC NDEF tag type is well known, such as URIs, the activity will be delievered with some extra fields already parsed.

In the application manifest, declare the following in the activities block to get nfc ndef discovered events.

 "nfc-ndef-discovered": {
   "filters": {
     "type": "uri",
     "uri": { "required":true, "regexp":"/^https?:.{1,16384}$/i" }
   }
 },

Then implement an activity handler in the application:

 navigator.mozSetMessageHandler('activity', NfcActivityHandler);
 
 function NfcActivityHandler(activity) {
   var activityName = activity.source.name;
   var data = activity.source.data;
 
   switch (activityName) {
     case 'nfc-ndef-discovered':
       console.log('nfc ndef message records(s): ' + JSON.stringify(data.records));
       console.log('Session Token: ' + JSON.stringify(data.sessionToken));
       console.log('Technology Detected: ' + JSON.stringify(data.tech));
       handleNdefDiscovered(data);
       break;
 }

Note: Gaia applications, in order to read NDEF messages from a passive tag (or) P2P phone, should declare 'nfc-ndef-discovered' in their manifest file as stated above.This implies that the Gaia application that registered the 'nfc-ndef-discovered' activity shall be listed in activity picker whenever an NDEF message is about to be read.

Sending/Writing NDEF messages in P2P mode

In P2P mode, there are two event listeners that can be registered by the applications. Applications should have 'nfc-write' permissions in order to register for 'onpeerready' and 'onpeerlost'.

1. onpeerready : Fired when there is another nfc peer phone is close proximity (in its near-field) and if the registered Nfc application is top-most (visible) application.

 Ex:- var nfcdom = window.navigator.mozNfc;
 nfcdom.onpeerready = function(event) {
  // perform write ndef operation
  .
 }

2. onpeerlost : Fired when the fellow nfc peer has been taken away from its proximity (from its near-field) and if the registered Nfc application is top-most (visible) application.

 Ex:- var nfcdom = window.navigator.mozNfc;
 nfcdom.onpeerlost = function(event) {
  // If necessary, show an UI indication that device is lost.
  .
 }

Note: These above APIs 'onpeerready' and 'onpeerlost' should be used if the application wants to bypass the normal activity picker. As you may also have noted , for these event handlers to be fired, the Nfc Gaia application should be the top-visible / foreground application.(There is no need to declare 'nfc-ndef-discovered' in the application's manifest file)

Sending/Writing NDEF messages in Passive Tag mode

TBD: Similar API needs to be added for a passive Tag scenario. foreground dispatch is still under discussion. bug 937430

Gaia application that wants to perform write operation in a 'Passive Tag' mode, can still perform the action only after 'reading the ndef message via MozActivity' as stated in the above section.

Application Permissions

NFC API can currently be used only by certified applications.

To use general reading NDEF API, at least nfc-read permission is required. To write NDEF or to use NFCPeer, nfc-write is required.

Application Usage Example:

 "permissions": {
   "nfc": { "access": "readwrite" }
 }

** Only for internal user ** For those APIs used by the nfc_manager in System app, nfc-manager permission is required. It must not be used in any other application besides System App.

NFC example

NFC Utility function for parsing / constructing NDEF records

Gaia Application developers can use a helper library (<$GAIA_HOME>/shared/js/nfc_utils.js> to perform routine tasks such as parse incoming NDEF records or construct NDEF records.

NfcUtils in bug 963556 will provide some basic constants and utility functions to create and parse NDEF messages that follow NFCForum-TS-NDEF_1.0 specifications.

The helper-utility exposes the following public functions:

- parseNDEF            : Parse a NDEF message
- parseHandoverNDEF    : Parse a NDEF message that represents a handover request
                         or a handover select message
- searchForBluetoothAC : Search for a Bluetooth Alternate Carrier in a
                         handover NDEF message
- parseBluetoothSSP    : Parses a Carrier Data Record that contains a
                         Bluetooth Secure Simple Pairing record
- encodeHandoverRequest: Returns a NDEF message that contains a handover
                         request message
- encodeHandoverSelect:  Returns a NDEF message that contains a handover
                         select message

Sample example to demonstrate the construction of an url as an NDEF Message:
  var tnf     = NDEF.TNF_WELL_KNOWN;
  var type    = NDEF.RTD_URI;
  var id      = new Uint8Array();
  // Short Record, 0x3 or "http://"
  var payload = new Uint8Array(NfcUtils.fromUTF8('\u0003mozilla.org'));
  var  urlNDEFMsg = [new MozNDEFRecord(tnf, type, id, payload)];
  // Call writeNdef() API with urlNDEFMsg

NDEF Connect Example

To establish an NFC application session, all NFCTag operations require an initial connect. It also selects the technology to use for subsequent operations until close/disconnect.

 nfctag = window.navigator.mozNfc.getNFCTag(sessionToken);

 var connectreq = nfctag.connect("NDEF");
 connectreq.onsuccess = function() {
   console.log('Connect success!');
 };
 connectreq.onerror = function() {
   console.log('ERROR: Failed to connect.');
 };

NFC Close Example

Applications should close() the tag when done to release resources.

 var closereq = nfctag.close();
 closereq.onsuccess = function() {
   console.log('NFC tag close success!');
 };
 closereq.onerror = function() {
   console.log('ERROR: Failed to close.');
 };

NDEF Details Example

 var detailreq = nfctag.getDetailsNDEF();
 detailreq.onsuccess = function() {
   console.log('Max NDEF Message Length: ' + detailreq.result.maxNdefMsgLen);
 };
 detailreq.onerror = function() {
   console.log('ERROR: Failed to get NDEF details.');
 };

NDEF Read Example

The array of ndef records should be passed along in the web activity already read, but applications can still directly read the tag. The session token arrives from a MozActivity. NdefRecord fields are in Uint8Array format, they must first be unpacked in order to be read by applications.

 var conn = nfctag.connect("NDEF");
 conn.onsuccess = function() {
   var req = nfctag.readNDEF();
   req.onsuccess = function() {
     var records = req.result;
     showRecords(records);
     nfctag.close(); // This is a DOMRequest call, truncated code here.
   };
   req.onerror = function() {
     nfctag.close(); // This is a DOMRequest call, truncated code here.
   };
 };
 
 function showRecords(records) {
   records.forEach(function (record) {
     console.log("Found a " + record.tnf + " record" +
                 " of type " + record.type +
                 " with ID " + record.id +
                 " and payload " + record.payload);
   });
 };

NDEF Write Tag Example

 var tnf     = 1;                                                      // NFC Forum Well Known type
 var type    = new Uint8Array(NfcUtils.fromUTF8("U"));                 // URL type
 var id      = new Uint8Array(NfcUtils.fromUTF8(""));                  // id
 var payload = new Uint8Array(NfcUtils.fromUTF8("\u0003mozilla.org")); // URL data, with a short record prefix 0x3 replacing http://
 
 var ndefRecords = [new MozNDEFRecord(tnf, type, id, payload)];
 
 var writereq = nfctag.writeNDEF(ndefRecords);
 writereq.onsuccess = function(e) {
   console.log("Successfully wrote records to tag");
 };
 writereq.onerror = function(e) {
   console.log("Write failed!");
 };

NDEF P2P Send Example

Peer to Peer communications to another NFC enabled device does not need a connect, as it will automatically connect implicitly. It also only supports NDEF, which is a common standard data format across different NFC devices.

 var tnf     = 1;                                                      // NFC Forum Well Known type
 var type    = new Uint8Array(NfcUtils.fromUTF8("U"));                 // URL type
 var id      = new Uint8Array(NfcUtils.fromUTF8(""));                  // id
 var payload = new Uint8Array(NfcUtils.fromUTF8("\u0003mozilla.org")); // URL data, with a short record prefix 0x3 replacing http://
 
 var ndefRecords = [new MozNDEFRecord(tnf, type, id, payload)];
 var nfcdom = window.navigator.mozNfc;
  nfcdom.onpeerready = function(event) {
   var nfcPeer = nfcdom.getNFCPeer(event.detail);  // 'event.detail' has sessionToken.
   var req = nfcpeer.sendNDEF(ndefRecords); // push NDEF message to other NFC device.
   req.onsuccess = function(e) {
     console.log("Successfully pushed P2P message");
   };
   req.onerror = function(e) {
     console.log("P2P push failed!");
   };
 };

NDEF P2P SendFile Example

During handover scenarios, in order to send a file

 var nfcdom = window.navigator.mozNfc;
 nfcdom.onpeerready = function(event) {
   var nfcPeer = nfcdom.getNFCPeer(event.detail);
   var blob = ... // construct a 'blob' that is of type 'file'.
   // This 'blob' will be passed onto / handover to Bluetooth interface for the actual file transfer. (Wifi handover is not yet supported)
   var req = nfcPeer.sendFile(blob);
   req.onsuccess = function(e) {
     console.log("Successfully sent file");
   };
   req.onerror = function(e) {
     console.log("Send file failed!");
   };
 }; 

In order to use this api, applications should have the nfc permission 'nfc-write'

Handover Support

Only Bluetooth Handover is supported currently

Refer to this bug bug 903305 for 'sendFile' api, and for implementation details, refer bug 933093.

Application Dispatch Order

Dispatch priority is handled by the NFC Manager. In the numbered list below, a low number indicates higher priority. It generally dispatches according to the NFC technology type, and then the NDEF NDEF.TNF field, and the NDEF Record type field. If an activity is to be launched, it will display a activity list if there is more than one match.

1) Foreground App, if the callback onforegrounddispatch is set.
2) P2P Handover Types (BT transfers, WiFi direct connection, etc.)
3) All other matches.

In #3, unknown tags are dispatched as a "nfc-tag-discovered" activity.

NFC Resources

Reference

Similar APIs