Web NFC
W3C Web NFC API implementation in Chromium
Rijubrata Bhaumik <rijubrata.bhaumik@intel.com>
Leon Han <leon.han@intel.com>
Donna Wu <donna.wu@intel.com>
Former: Alexander Shalamov <alexander.shalamov@intel.com>
Last updated: 22 Dec 2020
Objective
This document explains how W3C Web NFC API is implemented in Chromium on both renderer and browser process sides. Future work and implementation challenges are described in “Future work” section of this document.
ED Spec (8 Dec 2020):
W3C Web NFC API https://w3c.github.io/web-nfc/
Background
The Web NFC API enables wireless communication in close proximity between active and passive NFC devices. The means of communication are based on NDEF message exchange specification. The API provides simple, yet powerful interfaces to create, read (receive) or write (send) NDEF compliant messages. The NDEF format was chosen to hide low level complexity and laborious handling of various NFC technology types. The NFC APIs are available on Android, Windows (UWP), iOS, Chrome OS and Linux platforms.
High level overview
The implementation of Web NFC in Chromium consists of two main parts:
The NFC module in Blink located at third_party/blink/renderer/modules/nfc/ which contains Blink JS bindings for Web NFC, and the browser side platform level adaptation that is located at services/device/nfc. The Blink NFC module communicates with the browser adaptation through NFC mojo interface defined in nfc.mojom file and implemented by the services/device/nfc module. The browser communicates with the android NFC implementation also through nfc_provider.mojom, in order to get the NFC object associated with which either resumes or suspends NFC operation in case of webpage visibility status change. At the time of writing, only Android platform is supported.
Other platforms provide NFC interfaces and can be supported in the future.
NDEFReader is the primary interface of the Web NFC. The NDEFReader interface has both, write and scan methods:
- The write method is for writing data to an NFC tag. This method returns a promise, which will be resolved when the message is successfully written to an NFC tag, or rejected either when errors happened or process is aborted by setting the AbortSignal in the NDEFWriteOptions.
- The scan method tries to read data from any NFC tag that comes within proximity. Once there is some data found, an NDEFReadingEvent carrying the data is dispatched to the NDEFReader.
Detailed design
Blink module
Details:
# **NFCProxy will be the mojo interface proxy for NDEFReader(s).**
# **There will be one NFCProxy instance per Document, and its lifecycle
is bound with the document which will align with the Spec’s description
“per ExecutionContext”**
# **NDEFReader Read:**
# **NFCProxy will have a <reader, watch_id> map to keep all active
readers.**
# **NDEFReader::scan() will call NFCProxy::StartReading(reader), which
will assign a |watch_id| for the |reader| and add it into NFCProxy’s
active reader list then call device::mojom::blink::NFC::Watch() to make
a request to DeviceService.**
# **The promise returned by scan() being resolved means DeviceService
has already started the scanning process.**
# **The scanning can be aborted anytime by setting the corresponding
AbortSignal in NDEFScanOptions, NDEFReader will call
NFCProxy::StopReading(reader) to remove itself from NFCProxy’s active
reader list and make a request to DeviceService to cancel.**
# **Stop itself when document is destroyed or it is destroyed itself.**
# **This will be an EventTarget and an ActiveScriptWrappable. If the
reader is in the middle of scanning and there are event listeners
registered, then it should remain alive until all pending activities get
done.**
# **NDEFReader Write:**
# **It will implement ContextClient for a valid Document to get NFCProxy
and pass the write request to the NFCProxy for push() method.**
# **The push() can be aborted anytime by setting the corresponding
AbortSignal.**
Android adaptation
The most important classes for Android adaptation are NfcImpl, NfcTagHandler and NdefMessageUtils.
NfcImpl class implements mojo NFC interface and uses Android platform NFC APIs to access NFC functionality. NfcTagHandler wraps android.nfc.Tag object and provides a unified interface for reading / writing NDEF messages. NdefMessageUtils has few static methods for conversion between android.nfc.NdefMessage and mojom.NdefMessage objects.
At runtime, the latest NFC.push operation is stored in PendingPushOperation object and as soon as the NFC tag appears within close proximity, write operation is performed. Same pattern is applicable for NFC.watch operations.
Runtime view
NDEFReader#write()
NDEFReader::write() will resolve the promise if there is no error occurred and the message is written to a matched target successfully. In other cases, any errors, or the AbortSignal is set during the process, it will reject the promise.
NDEFReader#scan()
NDEFReader#scan() may trigger NDEFReader#{onreading,onreadingerror}() events during the whole process. NDEFReader::scan() can be called multiple times on the same reader object but there is maximum only one active at any time point.
Future work
# **Support for ISO-DEP. The ISO-DEP (ISO 14443-4) protocol provides low
level I/O operations on a NFC tag. This functionality might be required by
developers who would like to communicate with smart cards or implement
custom communication mechanisms.**
# **Support for HCE.[ Host-based Card Emulation
(HCE)](https://developer.android.com/guide/topics/connectivity/nfc/hce.html)
would allow web developers to emulate secure element component. This feature
would enable ticketing, payments, and other complex use-cases.**
# **Bootstrapping WebVR. HMD enclosure can have NFC tag that contains
information about lens configuration (dual / single element), FOV, magnet
button, URL to be opened and other features.**
# **Support for: Chrome OS, Linux and Windows (UWP) platforms.**
# **Support for: NFC assisted WebBluetooth handover / pairing.**
# **Research whether[ iOS Core
NFC](https://developer.apple.com/documentation/corenfc) can be used to
implement Web NFC support in Chromium on iOS platform.**