Copyright © 2019 the Contributors to the Web NFC API Specification, published by the Web NFC Community Group under the W3C Community Contributor License Agreement (CLA). A human-readable summary is available.
Near Field Communication (NFC) enables wireless communication between two devices at close proximity, usually less than a few centimeters. NFC is an international standard (ISO/IEC 18092) defining an interface and protocol for simple wireless interconnection of closely coupled devices operating at 13.56 MHz. The hardware standard is defined in NFC Forum Technical Specifications.
This document defines an API to enable selected use-cases based on NFC technology. The current scope of the specification is NDEF. Other NFC technologies may be supported in the future.
This specification was published by the Web NFC Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.
Implementers need to be aware that this specification is considered unstable. Implementers who are not taking part in the discussions will find the specification changing out from under them in incompatible ways. Vendors interested in implementing this specification before it eventually reaches the Candidate Recommendation phase should subscribe to the repository on GitHub and take part in the discussions.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY, MUST, MUST NOT, SHOULD, and SHOULD NOT in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
This document defines conformance criteria that apply to a single product: the UA (user agent) that implements the interfaces it contains.
This section is non-normative.
NFC user scenarios can be grouped as follows:
NFC works using magnetic induction, meaning that the reader (an active, powered device) will emit a small electric charge which then creates a magnetic field. This field powers the passive device which turns it into electrical impulses to communicate data. Thus, when the devices are within range, a read is always performed (see NFC Analog Specification and NFC Digital Protocol, NFC Forum, 2006). The peer-to-peer connection works in a similar way, as the device periodically switches into a so-called initiator mode in order to scan for targets, then later to fall back into target mode. If a target is found, the data is read the same way as for tags.
As NFC is based on existing RFID standards, many NFC chipsets support reading RFID tags, but some of these are only supported by single vendors and not part of the NFC standards. As such this document specifies ways to interact with the NFC Data Exchange Format (NDEF).
The Augmented Backus-Naur Form (ABNF) notation used is specified in [RFC5234].
NFC stands for Near Field Communications, short-range wireless technology operating at 13.56 MHz which enables communication between devices at a distance less than 10 cm. The NFC communications protocols and data exchange formats, and are based on existing radio-frequency identification (RFID) standards, including ISO/IEC 14443 and FeliCa. The NFC standards include ISO/IEC 18092[5] and those defined by the NFC Forum. See NFC Forum Technical Specifications for a complete listing.
An NFC adapter is the software entity in the underlying platform which provides access to NFC functionality implemented in a given hardware element (NFC chip). A device may have multiple NFC adapters, for instance a built-in one, and one or more attached via USB.
An NFC tag is a passive NFC device. The NFC tag is powered by magnetic induction when an active NFC device is in proximity range. An NFC tag contains a single NDEF message.
The way of reading the message may happen through proprietary technologies, which require the reader and the tag to be of the same manufacturer. Implementations are expected to encapsulate this.
An NFC peer is an active, powered device, which can interact with other devices in order to exchange data using NFC.
An NFC device is either an NFC peer, or an NFC tag.
NDEF is an abbreviation for NFC Forum Data Exchange Format, a lightweight binary message format that is standardized in [NFC-NDEF].
An NDEF message encapsulates one or more application-defined NDEF records. NDEF messages can be stored on an NFC tag or exchanged between NFC-enabled devices.
The term NFC content denotes all bytes sent to or received from an NFC tag or an NFC peer. In the current API it is synonym to NDEF message.
This section is non-normative.
NFC is standardized in the NFC Forum and described in [NFC-STANDARDS].
This section is non-normative.
The NFC Forum has mandated the support of five different tag types to be operable with NFC devices. The same is required on operating systems, such as Android.
In addition to that, the MIFARE Standard specifies a way for NDEF to work on top of the older MIFARE Standard, which may be optionally supported by implementors.
A note about the NDEF mapping can be found here: MIFARE Classic as NFC Type MIFARE Classic Tag
96
bytes and
2
Kbytes. Communication speed is 106
kbit/sec. In contract to all other
types, these tags have no anti-collision protection for dealing with multiple
tags within the NFC field.
48
bytes and 2
Kbytes.
Communication speed is 106
kbit/sec.
2
kbytes.
Communication speed is 212
kbit/sec or 424
kbit/s.
32
kbytes.
Supports three different communication speeds 106
or 212
or
424
kbit/s.
64
kbytes.
Communiction speed 26.48
kbit/s
320
and 4
kbytes. Communication speed is 106
kbit/sec.
MIFARE Standard is a not an NFC Forum type and can only be read by devices using NXP hardware. Support for reading and writing to tags based on the MIFARE Standard is thus non-nominative, but the type is included due to the popularity and use in legacy systems.
In addition to data types standardized for NDEF records by the NFC Forum, many commercial products such as bus cards, door openers may be based on the MIFARE Standard which require specific NFC chips (same vendor of card and reader) in order to function.
Card emulation mode capabilities also depend on the NFC chip in the device. For payments, a Secure Element is often needed.
An NDEF record is a part of an NDEF message. Each record is a binary structure that contains a data payload, as well as associated type information. In addition to this, it includes information about how the data is structured, like payload size, whether the data is chunked over multiple records etc.
A generic record looks like the following:
Only the first three bytes (lines in figure) are mandatory. First the header byte, followed by the TYPE LENGTH field and PAYLOAD LENGTH field, which may both be zero.
The TNF field (bit 0-2
, type name format) indicates the format
of the type name and is often exposed by native NFC software stacks. The
field can take binary values denoting the following NDEF record payload types:
TNF value | Description |
---|---|
0 | Empty record |
1 | NFC Forum well-known type record |
2 | MIME type record |
3 | Absolute-URL record |
4 | NFC Forum external type record |
5 | Unknown record |
6 | Unchanged record |
7 | Reserved for future use |
The IL field (bit 3
, id length) indicates whether an
ID LENGTH field is present. If the IL field is 0
, then the
ID field is not present either.
The SR field (bit 4
, short record) indicates a short record,
one with a payload length <= 255
bytes. Normal records can have payload
lengths exceeding 255
bytes up to a maximum of 4
GB. Short records only
use one byte to indicate length, whether as normal records use 4
bytes
(2
32
-1
bytes).
The CF field (bit 5
, chunk flag) indicates whether the payload
is chunked across multiple records.
Web NFC turns all received chunked records into logical records and transparently chunks sent payload when that is needed.
The ME field (bit 6
, message end) indicates whether this record
is the last in the NDEF message.
The MB field (bit 7
, message begin) indicates whether this
record is the first of the NDEF message.
The TYPE LENGTH field is an unsigned 8-bit integer that denotes the byte size of the TYPE field.
The TYPE field is a globally unique and maintained identifier that describes the type of the PAYLOAD field in a structure, encoding and format dictated by value of the TNF field.
The NFC Record Type Definition (RTD) Technical Specification requires that the TYPE field names MUST be compared in case-insensitive manner.
The ID LENGTH field is an unsigned 8-bit integer that denotes the byte size of the ID field.
The ID field is an identifier in the form of a URI reference ([RFC3986]) that is unique, and can be absolute of relative (in the latter case the application must provide a base URI). Middle and terminating chunk records MUST NOT have an ID field, other records MAY have it.
The PAYLOAD LENGTH field denotes the byte size of the
PAYLOAD field. If the SR field is 1
, its size is one byte,
otherwise 4 bytes, representing an 8-bit or 32-bit unsigned integer,
respectively.
The PAYLOAD field carries the application bytes. Any internal structure of the data is opaque to NDEF. Note that in certain cases discussed later, this field MAY contain an NDEF message as data.
An empty record's' TYPE LENGTH field,
ID LENGTH field and PAYLOAD LENGTH field MUST be 0
, thus
the TYPE field, ID field and PAYLOAD field MUST NOT
be present.
The NFC Forum has standardized a small set of useful record types in [NFC-RTD] (Resource Type Definition specifications) called well-known type records, for instance text, URL, media and opaque binary data. In addition, there are record types designed for more complex interactions, such as smart poster (containing optional embedded records for url, text, signature and actions), and handover records.
T
" for text, "U
" for URL, "Sp
" for smart poster,
"Sig
" for signature, "Hc
" for handover carrier, "Hr
" for
handover request, "Hs
" for handover select, etc.
1
and the TYPE field is "T
" (0x54
).
The first byte of the PAYLOAD field is a status byte, followed
by the ISO/IANA language code in US-ASCII encoding.
The rest of the payload is the actual text, encoded either in UTF-8 or
UTF-16, as indicated by the status byte as follows:
0
.
URI record is defined in [NDEF-URI].
The TNF field is 1
and the TYPE field is "U
" (0x55
).
The first byte of the PAYLOAD field is a URI identifier code,
in fact an index in an abbreviation table where the values are prepended
to the rest of the URI. For instance the value 0
denotes no prepending,
1
denotes "http://www.
", 0x04
denotes "https://
"" and so on.
The rest of the payload contains the rest of the URI as a UTF-8 string
(and if the first byte is 0
, then it denotes the whole URI).
The URI is defined in [RFC3987] and in fact is a UTF-8 encoded IRI that can be a URN or a URL.
Smart poster is defined in [NDEF-SMARTPOSTER] as an NDEF record that contains an NDEF message as payload, which may contain several records: a mandatory URI record that refers to a content, and additional optional records related to the content: a title record (a Text record), one or more icon records, a type record, a size record and an action record.
Icon records are MIME type records. If multiple icon records are included, readers SHOULD select only one of them to display.
The type record has NFC Forum local type "t
" specific to smart
poster and the PAYLOAD field contains a UTF-8 encoded MIME type for
the content referred to by the URI record.
The size record has NFC Forum local type "s
" specific to smart
poster and the PAYLOAD field contains a 4-byte 32 bit unsigned
integer that denotes the size of the object referred to by the URL in the
URI record.
The action record has NFC Forum local type "act
" specific to
smart poster and the PAYLOAD field contains a single byte, whose
value has the following meaning:
Value | Description |
---|---|
0 | Do the action |
1 | Save for later |
2 | Open for editing |
3..0xFF | Reserved for future use |
The action record is optional and there is no default action on the smart poster content if the action record is missing.
At the time of NDEF standardization the value 0
("do the action") was
meant for use cases like send an SMS, make a call or launch browser.
Similarly, the value 1
, ("save the content for later processing") was
meant for use cases like store the SMS in inbox, save the URL in
bookmarks, or save the phone number to contacts. Also, the value 2
("open for editing") was meant to open the smart poster content with a
default application for editing.
Implementations don't need to implement any standardized behavior for the actions defined here. In this API it's up to the applications what actions they define (that may include the use cases above). However, Web NFC just provides the values.
NDEF Signature is defined [NDEF-SIGNATURE].
Its TYPE field contains "Sig
" (0x53
, 0x69
, 0x67
) and its
PAYLOAD field contains version, signature and a certificate chain.
In this version of the API, Web NFC only provides the raw byte content
of the payload (see this
issue).
NFC handover is defined [NFC-HANDOVER] and the corresponding message structure that allows negotiation and activation of an alternative communication carrier, such as Bluetooth or WiFi. The negotiated communication carrier would then be used (separately) to perform certain activities between the two devices, such as sending photos to the other device, printing to a Bluetooth printer or streaming video to a television set. Web NFC does not support this at the moment (see this issue.
The MIME type records are records that store binary
data with associated MIME type.
Web NFC has special handling for working with JSON MIME type data.
In absolute-URL records the TYPE field contains the absolute-URL string, and not the payload.
NOTE: Some platforms, like Windows Phone have stored additional data in the payload, but any payload data in these records are ignored by other platforms such as Android. On Android, reading such a record, will attempt to load the URL in Chrome and it is as such not intended for client applications.
The NFC Forum external type records are for application specified data types and are defined in NFC Record Type Definition (RTD) Technical Specification.
The external type is a URN with the prefix "urn:nfc:ext:"
followed by
the name of the owner domain, adding a colon, then a non-zero type name,
for instance "urn:nfc:ext:w3.org:atype"
, stored as "w3.org:atype"
in the TYPE field.
The unknown records are records that store
opaque data without associated MIME type, meaning that the
application/octet-stream
default MIME type MAY be assumed.
The [NFC-NDEF] specification recommends that NDEF parsers store
or forward the payload without processing it.
0
and their
TNF field MUST be 6
(unchanged).
First record:
Intermediate record:
Last record:
Any implementation of Web NFC MUST transparently expose chunked records as single logical records.
This section is non-normative.
A few Web NFC user scenarios are described in the Use Cases document. These user scenarios can be grouped by criteria based on security, privacy and feature categories, resulting in generic flows as follows.
Document
of the top-level browsing context using the Web NFC API
is visible. For instance, a web page instructs the user
to tap an NFC tag, and then receives information from the tag.
Document
of the top-level browsing context using the
Web NFC API is visible.
Document
using the Web NFC API is
visible.
This use case is not supported in this version of the specification.
The user opens a web page which can write an NFC tag. The write operations may be one of the following:
Note that an NFC write operation to an NFC tag always involves also a read operation.
In general, pushing data to another NFC capable device requires that on the initiating device the user would first have to navigate to a web site. The user would then touch the device against another Web NFC equipped device, and data transfer would occur.
On the receiving device the UA will dispatch the content to an application
registered and eligible to handle the content, and if that application is
a browser which has a Document
of the top-level browsing context
visible with active
,
then the content is delivered to the page through the NFCReader
NFCReadingEvent
.
NFC supports handover protocols to Bluetooth or WiFi connectivity for the purpose of larger volume data transfer. The user touches another NFC capable device, and as a result configuration data is sent for a new Bluetooth or WiFi connection, which is then established between the devices.
This use case is not supported in this version of the specification.
Payment scenarios with Web NFC generally do not refer to supporting the payment process itself, but associating the payment status with a web page in order to have secondary actions. For instance, the user buys goods in a store, and payments options include contactless payment using NFC technology. In general, touching the device to the point of sales terminal receiver area will result in a transaction between the secure element from the device and the point of sales terminal. With the Web NFC API, if the user navigates to a web site before paying, there may be interaction with that site regarding the payment, e.g. the user could get points and discounts, or get delivered application or service specific data (e.g. tickets, keys, etc) to the device.
This use case is not supported in this version of the specification.
Users may attach one or more external NFC adapters to their devices, in addition to a built-in adapter. Users may use either NFC adapter.
This section is non-normative.
High level features for the Web NFC specification include the following:
This specification makes a few simplifications in what use cases and data types the Web NFC API can handle:
This section is non-normative.
This section shows how developers can make use of the various features of this specification.
Pushing a text string to any kind of device is straightforward. Options can be left out, as they default to pushing to both tags and peers.
const writer = new NFCWriter();
writer.push(
"Hello World"
).then(() => {
console.log("Message pushed.");
}).catch(error => {
console.log(`Push failed :-( try again: ${error}.`);
});
It is possible to restrict to which devices (tags or peers) data should be pushed. Below push is specified only to peers, and thus, no data is pushed when the user taps a tag.
const writer = new NFCWriter();
writer.push(
"Text meant for peers only", { target: "peer" }
).then(() => {
console.log("Message pushed.");
}).catch(_ => {
console.log("Push failed :-( try again.");
});
In order to push an NDEF record of URL type, simply use NDEFMessage.
const writer = new NFCWriter();
writer.push({
records: [{ recordType: "url", data: "https://w3c.github.io/web-nfc/" }]
}).then(() => {
console.log("Message pushed.");
}).catch(_ => {
console.log("Push failed :-( try again.");
});
This example shows reading various different kinds of data which can be stored on a tag. If the tag is unformatted or contains an empty record, a text message is written with the value "Hello World".
const writer = new NFCWriter();
const reader = new NFCReader();
reader.onreading = event => {
const message = event.message;
if (message.records.length == 0 || // unformatted tag
message.records[0].recordType == 'empty' ) { // empty record
writer.push({
records: [{ recordType: "text", data: 'Hello World' }]
});
return;
}
for (let record of message.records) {
switch (record.recordType) {
case "text":
console.log(`Text: ${record.text()}`);
break;
case "url":
console.log(`URL: ${record.text()}`);
break;
case "json":
console.log(`JSON: ${record.json().myProperty}`);
break;
case "media":
if (record.mediaType.startsWith('image/')) {
const blob = new Blob([record.arrayBuffer()], {type: record.mediaType});
const img = document.createElement("img");
img.src = URL.createObjectURL(blob);
img.onload = () => window.URL.revokeObjectURL(this.src);
document.body.appendChild(img);
}
break;
}
}
};
reader.scan();
Filtering of relevant data sources can be done by the use of
the NFCScanOptions
. Below we accept the record identifier URL with
"/mypath/mygame/
" in its path from "mygame.com
"
domain and its subdomains. When we read the data, we immediately update
the game progress by issueing a push with a custom NDEF data layout.
The example allows reading and pushing to both peers and tags, whichever one is tapped first.
const reader = new NFCReader();
reader.scan({ id: "https://mygame.com/mypath/mygame" });
reader.onreading = async event => {
console.log(`Game state: ${ JSON.stringify(event.message.records) }`);
const newMessage = {
records: [{
id: "/mypath/mygame/update",
recordType: "json",
mediaType: "application/json",
data: { level: 3, points: 4500, lives: 3 }
}]
};
const writer = new NFCWriter();
await writer.push(newMessage);
console.log("Pushed message");
};
Storing and receiving JSON data is easy with serialization and deserialization.
const reader = new NFCReader();
reader.addEventListener("reading", event => {
for (let record of event.message.records) {
if (record.recordType === 'json') {
const json = record.json();
const article =/[aeio]/.test(json.title) ? "an" : "a";
console.log(`${json.name} is ${article} ${json.title}`);
}
}
});
reader.scan({ recordType: "json" });
const writer = new NFCWriter();
writer.push({
records: [
{
recordType: "json",
mediaType: "application/json",
data: {
name: "Benny Jensen",
title: "Banker"
}
},
{
recordType: "json",
mediaType: "application/json",
data: {
name: "Zoey Braun",
title: "Engineer"
}
}]
});
Pushing data to a tag requires tapping it. If existing data should be
read during the same tap, we need to set the ignoreRead
property to false
for the NFCWriter
.
const reader = new NFCReader();
reader.onreading = event => {
for (let record of event.message.records) {
console.log("Record type: " + record.recordType);
console.log("MIME type: " + record.mediaType);
console.log("=== data ===\n" + record.text());
}
};
reader.scan();
const writer = new NFCWriter();
writer.push("Pushing data is fun!", {target: "tag", ignoreRead: false});
Read NDEF messages for 3 seconds by using signal in the NFCScanOptions
.
const reader = new NFCReader();
reader.onreading = event => {
console.log("NDEF message read.");
};
const controller = new AbortController();
controller.signal.onabort = event => {
console.log("We're done waiting for NDEF messages.");
};
reader.scan({ signal: controller.signal });
// Stop listening to NDEF messages after 3s.
setTimeout(() => controller.abort(), 3000);
const writer = new NFCWriter();
writer.push({ records: [
{
recordType: "smart-poster",
data: { records: [
{
recordType: "url",
data: "https://my.org/content/19911"
},
{
recordType: "t", // smart poster type, a local type to Sp
data: "image/gif"
},
{
recordType: "text",
data: "Funny dance"
},
{
recordType: "s", // size, a local type to Sp
data: 4096 // byte size of the content at the URL above
},
{
recordType: "act", // action, a local type to Sp
data: 0 // do the action, in this case open in the browser
}
]}
}
]}).catch(_ => {
console.log("Push failed");
});
External type records can be used to create application defined records. These records may contain an NDEF message as payload, with its own NDEF records, including local types that are used in the context of the application.
Note that the smart poster record type also contains an NDEF message as payload.
As NDEF gives no guarantee on the ordering of records, using an external type record with an NDEF message as payload, can be useful for encapsulating related data.
This example shows how to read an external record for social posts, which contains an NDEF message, containing a text record and a record with the local type "act" (action), with definition borrowed from smart poster, but used in local application context.
const reader = new NFCReader();
reader.onreading = event => {
const socialPost = event.message.records[0];
if (!socialPost) {
return;
}
let action;
let text = "";
for (let record of socialPost.toRecords()) {
switch (record.recordType) {
case "text":
text = record.text();
break;
case "act":
const buffer = record.arrayBuffer();
const view = new DataView(buffer);
action = view.getUint8(0);
break;
}
}
switch (action) {
case 0: // do the action
console.log(`Post "${text}" to timeline`);
break;
case 1: // save for later
console.log(`Save "${text}" as a draft`);
break;
case 2: // open for editing
console.log(`Show editable post with "${text}"`);
break;
}
};
reader.scan({ recordType: "example.com:sp"});
External type records can be used to create application defined records that may even contain an NDEF message as payload.
const writer = new NFCWriter();
writer.push({ records: [
{
recordType: "external",
data: {
records: [
{
recordType: "url",
data: "https://my.org/game/19911"
},
{
recordType: "text",
data: "Game context given here"
},
{
recordType: "media",
mediaType: "image/png"
data: getImageBytes(fromURL);
}
]
}
}
]}).catch(_ => {
console.log("Push failed");
});
The trust model, attacker model, threat model and possible mitigation proposals for the Web NFC API are presented in the Security and Privacy document. This section presents the chosen security and privacy model through normative requirements to implementations.
Web pages using the Web NFC API are not trusted. This means that the user needs to be aware of exactly what a web page is intending to do with NFC at any given moment. Implementations need to make sure that when the user authorizes a method of this API, then only that action is run, without side effects, and exactly in the context and the number of times the user allows the execution of NFC related operations, according to the algorithmic steps detailed in this specification.
The integrity of NFC content SHOULD NOT be trusted when used for implementing security policies, for instance the authenticity of record identifier, unless a prearranged trust relationship exists.
Security considerations for media types in general are discussed in [RFC2048] and [RFC2046].
The main threats are summarized in the Security and Privacy document.
In this specification the following threats are handled with the highest priority:
This specification attempts to minimize user prompting and uses implicit security policies to address the threats. However, this specification does not describe, nor does it mandate specific user prompting policies. The term obtain permission is used for acquiring trust for a given operation.
The Permissions API is suggested to be used by UAs for implementing NFC related Permissions in order to minimize the need for user prompting.
All expressed permissions that are preserved beyond the current browsing session MUST be revocable.
This section is non-normative.
This section summarizes the security policies which are specified as normative requirements in the respective algorithms of this specification.
Only secure contexts are allowed to access NFC content. Browsers may ignore this rule for development purposes only.
Web NFC functionality is allowed only for the Document
of the
top-level browsing context, which must be
visible.
This also means that UAs should block access to the NFC radio if the display is off or the device is locked. For backgrounded web pages, receiving and pushing NFC content must be suspended.
Making an NFC tag read-only must obtain permission, or otherwise fail.
Setting up listeners for reading NFC content should obtain permission.
The process of reading an NDEF message does not need to obtain permission.
Pushing NFC content to an NFC peer does not need to obtain permission, but the other rules in this section apply. See the § 10.10 Writing or pushing content section.
Pushing an NDEF message to an NFC tag does not need to obtain permission, if the existing NDEF message only contains NDEF records without ID fields, or with ID fields matching the registrable domain of the current settings object's origin. Otherwise the UA must obtain permission for pushing NFC content which overwrites existing information. See also the § 10.10 Writing or pushing content section.
Since all local content that a web page has access to can be shared with NFC, the user needs to be clearly aware about the permissions granted to the web page using the Web NFC API.
When pushing an NDEF message, the registrable domain, serialized, of the current settings object must be stored as the record identifier in each top-level NDEF Record.
When listening for and pushing NFC content, the UA may warn the user that the given origin may be able to infer physical location.
The payload data on NFC content is untrusted, and must not be used by the UA to do automatic handling such as opening a web page with a URL found in an NFC tag, unless the user approves that.
NDEFMessage
interface
The content of any NDEF message is exposed by the
NDEFMessage
interface:
[Exposed=Window] interfaceNDEFMessage
{constructor
(NDEFMessageInit
messageInit); readonly attribute FrozenArray<NDEFRecord
>records
; }; dictionaryNDEFMessageInit
{ required sequence<NDEFRecordInit
>records
; };
The records
property represents a list of NDEF records defining the
NDEF message.
The NDEFMessageInit
dictionary is used to initialize a
NDEF message.
NDEFRecord
interface
The content of any NDEF record is exposed by the
NDEFRecord
interface:
[Exposed=Window] interfaceNDEFRecord
{constructor
(NDEFRecordInit
recordInit); readonly attributeNDEFRecordType
recordType
; readonly attribute USVStringmediaType
; readonly attribute USVStringid
; USVString?text
(); [NewObject] ArrayBuffer?arrayBuffer
(); [NewObject] anyjson
(); sequence<NDEFRecord
>toRecords
(); }; dictionaryNDEFRecordInit
{ requiredNDEFRecordType
recordType
; USVStringmediaType
; USVStringid
; anydata
; };
A NDEFRecord
object has the following internal slots:
Internal slot | Initial value | Description (non-normative) |
---|---|---|
[[PayloadData]] | Empty byte sequence. | A byte sequence representing the whole or a subset of the PAYLOAD field data. |
The mediaType
property represents the MIME type of
the NDEF record payload.
The recordType
property represents the NDEF record types.
The id
property represents the record identifier, which is an
absolute or relative URL. The required uniqueness of the identifier is
guaranteed by the generator, as such only absolute URLs based on the origin
of the browsing content can be written using this specification.
The text()
method, when invoked, MUST return the result of
running convert NDEFRecord.[[PayloadData]] bytes with an NDEFRecord
object and text
target.
The arrayBuffer()
method, when invoked, MUST return the result of
running convert NDEFRecord.[[PayloadData]] bytes with an NDEFRecord
object and arrayBuffer
target.
The json()
method, when invoked, MUST return the result of
running convert NDEFRecord.[[PayloadData]] bytes with an NDEFRecord
object and a JSON
target.
The toRecords()
method, when invoked, MUST return the result of
running convert NDEFRecord.[[PayloadData]] bytes with an NDEFRecord
object and records
target.
The NDEFRecordInit
dictionary is used to initialize an NDEF record
with its type, optional MIME type, record identifier and payload
data via the members of
recordType
, mediaType
, id
,
and data
, respectively. The mapping from data types of an
NDEFRecordInit
to NDEF record types is presented
in the algorithmic steps which handle the data and described in the
§ 10.13 Parsing content and § 10.10 Writing or pushing content sections.
To convert NDEFRecord.[[PayloadData]] bytes, pass a record and a target, run these steps:
recordType
attribute.
empty
", return null
.
text
", then run the following sub-steps:
utf-8
" if bit 7
(MB field) of
header is equal to the value 0, or else "utf-16be
".
5
to bit 0
of the
header.
1
to the end.
utf-8
", return the result of
running UTF-8 decode on buffer.
encoding
set to "utf-16be
".
ArrayBuffer
whose contents are the bytes.
Re-throw any exceptions.
json
" or "media
", then
return the result of running parse JSON from bytes
on bytes. Re-throw any exceptions.
null
.
smart-poster
", or "media
", or
an external type, then return the result of running
parse records from bytes on bytes.
Re-throw any exceptions.
null
.
NDEFRecordType
string
This string defines the allowed types for a NDEFRecord
. The
§ 9.4 Data mapping section describes how
NDEFRecordType
is mapped to NDEF record types.
typedef DOMString NDEFRecordType
;
A set of known standardized values exists, but it is also possible for organizations to create their own custom external types.
NDEFRecord
.
DOMString
representing a custom type for the
external type record.
The type must follow the external type ABNF.
ext-type = reg-name ":" custom-type
custom-type = 1*(ALPHA / DIGIT / other)
DIGIT = %x30-39
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
other = "(" / ")" / "+" / "," / "-" / ":" / "=" /
"@" / ";" / "$" / "_" / "!" / "*" / "'" / "."
The reg-name
value is a registrable domain owned by the issuing organization, a ":
" and a type, e.g. "w3.org:member
".
And additional ABNF exists for well-known type records:
wkt-type = (ALPHA / DIGIT) *(ALPHA / DIGIT / other)
The NFC Record Type Definition (RTD) Technical Specification defines every type in the well-known type records and external type records in terms of URNs, but only a subset of the URN is actually stored in the NDEF record's TYPE field, which corresponds to the above two ABNFs.
DOMString
that MUST start with lowercase letter or a number, representing a type for a NFC Forum local type,
typically used in a record of an NDEFMessage
that is the payload
of a parent NDEFRecord
, for instance in a smart poster.
The context of the local type is the parent record whose payload
is the NDEFMessage
to which this record belongs. The value
MUST NOT be equal to any other NDEFRecordType
strings defined
in this API.
Any implementation of Web NFC MUST transparently expose chunked records as single logical records, therefore unchanged records are not explicitly represented.
Two well-known types (including any NFC Forum local type and any NFC Forum global type) MUST be compared character by character in case-sensitive manner.
Two external types MUST be compared character by character, in case-insensitive manner.
The binary representation of any well-known type and
external type MUST be written as a relative URI (RFC 3986),
omitting the namespace identifier (NID) "nfc
" and namespace specific
string (NSS) "wkt
" and "ext
", respecively, i.e. omitting the
"urn:nfc:wkt:
" and "urn:nfc:ext:
" prefixes.
For instance, "urn:nfc:ext:company.com:a" is stored as "
company.com:a`"
and the well-known type of a Text record is
"urn:nfc:wkt:T
", but it is stored as "T
".
The mapping from data types of an NDEFRecordInit
to
NDEF record types, as used in the § 10.10 Writing or pushing content
section is as follows:
NDEFRecordInit recordType | NDEFRecordInit mediaType | NDEFRecordInit data | NDEF record type |
---|---|---|---|
"empty " |
unused | unused | Empty record (TNF=0) |
"text " |
unused | DOMString |
Well-known type (TNF=1) record with TYPE="T " |
"url " |
unused | DOMString |
Well-known type (TNF=1) record with TYPE="U " |
"smart-poster " |
unused |
|
Well-known type (TNF=1) record with TYPE="Sp " |
"json " |
JSON MIME type | JSON type | MIME type record (TNF=2) with TYPE= JSON type. |
"media " |
MIME type | ArrayBuffer |
MIME type record (TNF=2) with TYPE= MIME type |
"absolute-url " |
unused | DOMString url |
Absolute-URL record (TNF=3) with TYPE=url |
external type | unused |
ArrayBuffer or anytyped array type or
|
External type record (TNF=4) with TYPE= external type |
local type | unused |
ArrayBuffer or anytyped array type |
External type record (TNF=4) with TYPE= local type inside
the NDEFMessage payload of another record |
"unknown " |
unused | ArrayBuffer |
unknown record (TNF=5) |
The mapping from NDEF record types to NDEFRecord
,
as used for incoming NDEF messages described in the
§ 10.13 Parsing content section, is as
follows. The data getters column shows the ones that should work for the
given payload type (the others may or will fail, depending on case).
NDEF record TNF field and TYPE field |
NDEFRecord recordType |
NDEFRecord mediaType |
NDEFRecord data getters |
---|---|---|---|
Empty record (TNF=0) | "empty " |
"" | none (all getters fail) |
Well-known type (TNF=1) record with TYPE="T " |
"text " |
"text/plain " |
text() or json() or arrayBuffer() |
Well-known type (TNF=1) record with TYPE="U " |
"url " |
"text/plain " |
text() or json() or arrayBuffer() |
Well-known type (TNF=1) record with TYPE="Sp " |
"smart-poster " |
"" |
toRecords() orarrayBuffer()
|
MIME type record (TNF=2) with TYPE=JSON MIME type | "json " |
The JSON MIME type used in the NDEF record |
text() orjson() orarrayBuffer()
|
MIME type record (TNF=2) with TYPE=MIME type | "media " |
The MIME type used in the NDEF record |
text() orjson() orarrayBuffer()
|
Absolute-URL record (TNF=3) with TYPE=url | "url " |
"" |
text() returning url orarrayBuffer()
|
External type record (TNF=4) with TYPE=external type | external type | "application/octet-stream " |
text() orjson() orarrayBuffer() ortoRecords()
|
Any embedded NDEF record with TYPE=local type | local type | "application/octet-stream " |
text() orjson() orarrayBuffer()
|
Unknown record (TNF=5) | "unknown " |
"application/octet-stream " |
arrayBuffer()
|
typedef (DOMString or ArrayBuffer orNDEFMessageInit
)NDEFMessageSource
; [SecureContext, Exposed=Window] interfaceNFCWriter
{constructor
(); Promise<void>push
(NDEFMessageSource
message, optionalNFCPushOptions
options={}); }; [SecureContext, Exposed=Window] interfaceNFCReader
: EventTarget {constructor
(); attribute EventHandleronreading
; attribute EventHandleronerror
; voidscan
(optionalNFCScanOptions
options={}); }; [SecureContext, Exposed=Window] interfaceNFCReadingEvent
: Event {constructor
(DOMString type,NFCReadingEventInit
readingEventInitDict); readonly attribute DOMStringserialNumber
; [SameObject] readonly attributeNDEFMessage
message
; }; dictionaryNFCReadingEventInit
: EventInit { DOMString?serialNumber
= ""; requiredNDEFMessageInit
message
; }; [SecureContext, Exposed=Window] interfaceNFCErrorEvent
: Event {constructor
(DOMString type,NFCErrorEventInit
errorEventInitDict); readonly attribute DOMExceptionerror
; }; dictionaryNFCErrorEventInit
: EventInit { required DOMExceptionerror
; };
The NDEFMessageSource
is a union type representing argument types
accepted by the push() method.
The NFCReadingEvent
is the event being dispatched on new NFC readings.
The serialNumber
property represents the serial number of
the device used for anti-collision and identification, or empty string in case none
is available. The message
is an NDEFMessage
object.
NFCReadingEventInit
is used to initialize a new event with a serial number
and the NDEFMessageInit
data via the message
member.
If serialNumber
is
not present or is null
,
empty string will be used to init the event.
Though most tags will have a stable unique identifier (UID), not all
have one and some tags even create a random number on each read.
The serial number usually consists of 4 or 7 numbers, separated by :
.
The NFCErrorEvent
is the event being dispatched on errors,
with the DOMException
object as the error
attribute.
NFCErrorEventInit
is used in order to initialize a new
event with a DOMException
data via the error
member.
The NFCWriter
is an object used for writing data to NFC devices
such as tags.
An
object has the following
internal slots:
NFCWriter
Internal Slot | Initial value | Description (non-normative) |
---|---|---|
[[PushOptions]] | null |
The value for writer.
|
[[PushMessage]] | null |
The to be written.
It is initially unset.
|
[[PushTimer]] | null |
A timer associated with the writer. |
The NFCReader
is an object used for reading data when a device,
such as a tag, is within the magnetic induction field.
An
object has the following
internal slots:
NFCReader
Internal Slot | Initial value | Description (non-normative) |
---|---|---|
[[Id]] | An empty string. |
The .id value.
|
[[RecordType]] | undefined |
The .recordType value.
|
[[MediaType]] | An empty string. |
The .mediaType value.
|
[[Signal]] | undefined |
The .signal to abort the operation.
|
Note that the internal slots of
come from the
options passed to NFCReader
NFCReader.scan()
.
Therefore there is maximum one filter associated with any given
object and successive invocations of NFCReader
NFCReader.scan()
with new options will replace existing filters.
The onreading
is an EventHandler
which is called to notify
that new reading is available.
The onerror
is an EventHandler
which is called to notify
that an error happened.
The relevant settings object of the active document of a browsing context which supports NFC has an associated NFC state record with the following internal slots:
Internal Slot | Initial value | Description (non-normative) |
---|---|---|
[[Suspended]] | false |
A boolean flag indicating whether NFC functionality is
suspended or not, initially
false .
|
[[ActivatedReaderList]] | empty set |
A set of instances.
|
[[PendingPush]] | empty |
A <promise, writer> tuple where promise
holds a pending Promise and writer holds an .
|
The activated reader objects is the value of the [[ActivatedReaderList]] internal slot.
The pending push tuple is the value of the [[PendingPush]] internal slot.
NFC is suspended if the [[Suspended]] internal slot is true
.
To suspend NFC, set the [[Suspended]] internal slot to true
.
To resume NFC, set the [[Suspended]] internal slot to false
.
Internal slots are used only as a notation in this specification, and implementations do not necessarily have to map them to explicit internal properties.
When the user agent determines that the visibility state of the responsible document of the current settings object changes, it must run these steps:
"visible"
,
resume NFC and abort these steps.
The term suspended refers to NFC
operations being suspended, which means that no NFC content is
pushed by NFCWriter
s, and no received NFC content is
presented to any
while being suspended.
NFCReader
To clear the pending push tuple on an environment settings object, perform the following steps:
To attempt to abort a pending push operation on an environment settings object, perform the following steps:
"AbortError"
DOMException
and abort these steps.
Rejecting the promise will clear the pending push tuple.
To release NFC on an environment settings object, perform the following steps:
The UA must release NFC given the document's relevant settings object as additional unloading document cleanup steps.
NFCPushOptions
dictionarydictionary NFCPushOptions
{
NFCPushTarget
target
= "any";
unrestricted double timeout
= Infinity;
boolean ignoreRead
= true;
boolean overwrite
= true;
AbortSignal? signal
;
};
The target
property
denotes the intended target for the pending
push()
operation.
The timeout
property
denotes the timeout for the pending
push()
operation expressed in milliseconds. The default value is
implementation-dependent. The value Infinity
means there is
no timeout, i.e. no timer is started. After the timeout
expires, the message set for pushing is cleared, an error is returned,
and a new NDEF message can be set for pushing.
When the value of the ignoreRead
property is
true
, the push algorithm
will skip invoking the NFC reading algorithm for an NFC tag.
When the value of the overwrite
property is
false
, the push algorithm
will read the NFC tag regardless of the ignoreRead
value
to determine if it has NDEF records on it, and if yes, it will not
execute any pending push.
The signal
property allows to abort
the push() operation.
NFCPushTarget
enumThis enum defines the set of intended target values for the push() operation.
enum NFCPushTarget
{
"tag
",
"peer
",
"any
"
};
tag
peer
any
NFCScanOptions
dictionary
To describe which messages an application is interested in, the
NFCScanOptions
dictionary is used:
dictionary NFCScanOptions
{
USVString id
= "";
NDEFRecordType
recordType
;
USVString mediaType
= "";
AbortSignal? signal
;
};
The signal
property allows to abort the
scan() operation.
The id
property
denotes the URL pattern which is used for matching the
record identifier of individual NDEF Records which are being read.
The default value ""
means that no matching is performed.
The recordType
property
denotes the enum value which is used for matching the
recordType property of each
NDEFRecord
object in an NDEF message.
If the dictionary member is not present,
then it will be ignored by the NFC listen algorithm.
The mediaType
property
denotes the match pattern which is used for matching the
mediaType property of each
NDEFRecord
object in an NDEF message.
The default value ""
means that no matching is performed.
const options = {
id: "https://www.w3.org/*", // any path from the domain is accepted
recordType: "json",
mediaType: "application/*+json" // any JSON-based MIME type
}
const options = {
id: "https://w3.org/info/restaurant/daily-menu/",
recordType: "media",
mediaType: "application/octet-stream"
}
This section describes how to write an NDEF message to an NFC tag or how to push it to an NFC peer device when it is next time in proximity range before a timer expires. At any time there is at maximum of two NDEF messages that can be set for pushing for an origin: one targeted to NFC tags and one to NFC peers, until the current message is sent, a timeout happens, or the push is aborted.
NFCWriter.push
method, when invoked, MUST run the
push a message algorithm:
Promise
object.
"NotSupportedError"
DOMException
and return p.
"NotReadableError"
DOMException
and return p.
"NotSupportedError"
DOMException
and return p.
null
otherwise.
"AbortError"
DOMException
and return p.
null
, then
add the following abort steps to signal:
"NotSupportedError"
DOMException
and abort these steps.
The UA might abort message push at this point. The reasons for termination are implementation details. For example, the user could have has set a preference to allow a given origin only to read, write, or push data to peers. Also, the implementation might be unable to support the requested operation.
A push replaces all previously configured push operations.
this
.[[PushOptions]] to options.
this
.[[PushMessage]] to output.
this
, p).
If NFC is suspended, continue waiting until timer expires (if set), or promise is aborted by the user, or until an NFC device comes within communication range.
Let p be the pending push tuple's promise.
NaN
or negative, reject
p with a TypeError
and abort these steps.
"NotSupportedError"
DOMException
and abort these steps.
Infinity
, abort these
steps.
"TimeoutError"
DOMException
.
"NotSupportedError"
DOMException
and
return p.
tag
" or "any
".
peer
" or "any
".
true
, run the NFC reading algorithm.
false
, read the tag
to check whether there are NDEF records on the tag.
If yes, then reject p with a "NotAllowedError"
DOMException
and return p.
null
, or different than the
serialized host of the current settings object's
origin, and the obtain push permission steps return
false
, then reject p with "NotAllowedError"
DOMException
and abort these steps.
If the NFC device in proximity range is an unformatted NFC tag that is NDEF-formatable, format it and write output as buffer.
Multiple adapters should be used sequentially by users. There is very small likelihood that a simultaneous tap will happen on two or multiple different and connected NFC adapters. If it happens, the user will likely need to repeat the taps until success, preferably one device at a time. The error here gives an indication that the operation needs to be repeated. Otherwise the user may think the operation succeeded on all connected NFC adapters.
"NetworkError"
DOMException
and abort these steps.
To obtain push permission, run these steps:
true
.
"granted"
(i.e. an expressed permission has been granted
to the origin and global object using
the Permissions API), return true
.
"prompt"
, then optionally
request permission
from the user for the Web NFC permission name.
If that is granted, return true
.
The request permission
steps are not yet clearly defined.
At this point the UA asks the user about the policy to be used
with the Web NFC permission name for the given
origin and global object, if the user grants permission,
return true
.
false
.
To create NDEF message given a message run these steps:
NDEFMessageSource
union, throw a TypeError
and
abort these steps.
NDEFMessageInit
type, and message's records
is empty, throw a TypeError
and abort these steps.
undefined
:
undefined
, reject promise
a TypeError
and abort these steps.
DOMString
, then set record's recordType to "text
".
ArrayBuffer
, then set record's recordType
to "media
".
json
".
empty
"text
"url
"json
"media
"NDEFMessageInit
, then
return the result of running the
create NDEF message given record's data.
NDEFMessageInit
, then
return the result of running the
create NDEF message given record's data.
NDEFMessageInit
and its
id is not null
:
1
.
To map empty record to NDEF given a record, run these steps:
0
(empty record).
0
.
0
,
and omit TYPE field and PAYLOAD field.
To map text to NDEF given a record, run these steps:
This is useful when clients specifically want to write text in a
well-known type record.
Other options would be to use the value "media
"
with an explicit MIME type text type, which allows for
better differentiation, e.g. when using "text/xml
", or
"text/vcard
".
DOMString
,
throw a TypeError
and abort these steps.
text
", and subtype is "plain
".
text
", then throw a
"SyntaxError"
DOMException
and abort these steps.
lang
"] if it
exists, or "en
".
charset
"] if it
exists, or "utf-8
".
utf-8
",
throw a TypeError
.
7
to the value 0
(meaning UTF-8 encoding).
6
to the value 0
(reserved).
SyntaxError
.
5
to bit 0
to languageLength.
1
(
well-known type record).
T
" (0x54
).
0
, set the ndefRecord's PAYLOAD field to data.
The lang=
parameter is a non-standard parameter
to MIME types, but it is used in this specification
in order to maintain compatibility with NFC Forum Technical Specifications.
To map a URL to NDEF given a record, run these steps:
DOMString
,
throw a TypeError
and abort these steps.
TypeError
and abort these steps.
0
.
1
(well-known type record).
U
" (0x55
).
0
, set the ndefRecord's PAYLOAD field to data.
To map JSON to NDEF given a record, run these steps:
application
", and subtype is "json
".
"SyntaxError"
DOMException
and abort these steps.
2
(MIME type).
0
, set the ndefRecord's PAYLOAD field to data.
To map binary data to NDEF given a record, run these steps:
ArrayBuffer
, throw a TypeError
and abort these steps.
application
", and subtype is "octet-stream
".
2
(MIME type).
0
, set the ndefRecord's PAYLOAD field to data.
To map external data to NDEF given a record, run these steps:
ArrayBuffer
, throw a TypeError
and abort these steps.
4
(external type record).
0
, set the ndefRecord's PAYLOAD field to data.
To map local type to NDEF given a record, run these steps:
ArrayBuffer
, throw a TypeError
and abort these steps.
1
(well-known type record), otherwise
set ndefRecord's TNF field to 4
(external type record).
0
, set the ndefRecord's PAYLOAD field
to data.
To create a record identifier given URL string id, run these steps:
https://
" + host as the base URL.
TypeError
and abort these steps:
"https:
".
If there are any
instances in activated reader objects
then the UA MUST listen to NDEF messages.
NFCReader
To listen for NFC content, the client MUST activate an
instance by calling NFCReader
NFCReader.scan()
. When attaching
an event listener for the "reading
" event on it, NFC content is
accessible to the client.
Each
can accept NDEF messages based on
data type, and a record identifier (URL) filters.
NFCReader
Filtering by a record identifier URL pattern, means that it will be matched against the URLs found in the NDEF records' ID field, thus the presence of such is required.
A match pattern is defined by the following ABNF:
match-pattern = top-level-type "/" [ tree "." ] subtype [ "+" suffix ] [ ";" parameters ]
top-level-type = "*" / < VCHAR except "/" and "*" >
subtype = "*" / < VCHAR except "+" >
A match pattern is a
glob used for matching MIME types,
for instance the pattern "application/*+json
" matches
"application/calendar+json
", but does not match
"application/json
". The pattern
"*/*json
", on the other hand, matches both.
https
".
A URL pattern's scheme, host and path components that are used by the URL pattern match algorithm have the following matching rules:
URL pattern component | Matching rule for record identifier |
---|---|
host |
exact match or ends with (URL pattern's
host prepended
with ". ").
|
path |
If URL pattern's path is "/* ", match any
record identifier path. Otherwise, begins with URL pattern's
path.
|
For example, 'https://mydomain.com/*
' will match
'https://service.mydomain.com/myapp/
' and
'https://info.mydomain.com/general/
', while
'https://app.mydomain.com/contacts
' will match
'https://app.mydomain.com/contacts
' and
'https://app.mydomain.com/contacts/all
'
The '*
' is a valid character for the URL path component,
therefore,
'https://www.mydomain.com/*
' pattern will match both
'https://www.mydomain.com/*
' and
'https://www.mydomain.com/service
' URLs.
true
.
false
.
false
.
.
"
to pattern's host.
false
.
/*
", return true
.
true
.
false
.
Incoming NFC content is matched using
instances.
NFCReader
When the NFCReader.scan
method is invoked, the UA
MUST run the following
NFC listen algorithm:
NFCReader
instance.
signal
" and value is not undefined
, set
reader.[[Signal]] to value.
id
", set
reader.[[Id]] to value, prepended with "https://
".
recordType
", set
reader.[[RecordType]] to value.
mediaType
", set
reader.[[MediaType]] to value.
"NotSupportedError"
DOMException
.
error
" at reader
using NFCErrorEvent
with its error attribute
initialized to e.
"NotReadableError"
DOMException
.
error
" at reader
using NFCErrorEvent
with its error attribute
initialized to e.
null
, then
add the following abort steps to reader.[[Signal]]:
NFCReader
instance from the activated reader objects.
false
, then
"NotAllowedError"
DOMException
.
error
" at reader
using NFCErrorEvent
with its error attribute
initialized to e.
"NotSupportedError"
DOMException
.
error
" at reader
using NFCErrorEvent
with its error attribute
initialized to e.
"SyntaxError"
DOMException
.
error
" at reader
using NFCErrorEvent
with its error attribute
initialized to e.
Document
of the top-level browsing context is not
visible (e.g. the user navigated
to another page), then the registered activated reader objects
still SHOULD continue to exist, but SHOULD become paused, i.e. the UA
SHOULD NOT check and use them until the Document
is
visible again.
To obtain reading permission, run these steps:
true
.
scan()
as well, then return false
.
The ask for forgiveness interaction might show choices like "block now" or "block forever", etc. If the user has chosen to "block forever" the given origin, it is the responsibility of the UA to remember these user choices for each origin, regardless of which NFC adapter is used, and consult them on later invocations.
In this step UAs are advised to notify users about that reading NFC content may indirectly reveal the physical location of the user.
true
.
This means there is no reading event generated when non-NDEF NFC technology comes in proximity range. This may change in future version of the specification.
null
if unavailable.
null
, set it to the
string of U+003A (:
) concatenating each number represented as
ASCII hex digit, in the same order.
NDEFMessage
object, with
message's records set to the empty list.
null
.
Otherwise, let input be the notation for the NDEF message
which has been received.
The UA SHOULD represent an unformatted NFC tag as an NDEF message containing no NDEF records, i.e. an empy array for its records property.
null
, append record to message's
records.
To dispatch NFC content given a serialNumber
of type serialNumber
, message
of type NDEFMessage
, run these steps:
NFCReader
instance reader in
the activated reader objects, run the following sub-steps:
""
and
it is not equal to any record's mediaType where record is
an element of message, continue.
reading
" at reader
using NFCReadingEvent
with its serialNumber
attribute
initialized to serialNumber and message
attribute
initialized to message.
3
, abort these sub-steps.
false
,
return records.
true
, let payloadLength
be the integer value of next byte (PAYLOAD LENGTH field) of bytes.
true
, let idLength be
the integer value of next byte (ID LENGTH field) of bytes,
otherwise let it be 0
.
0
bytes.
null
, append record to records.
true
, abort these sub-steps.
To parse an NDEF record given ndef into a record, run these steps:
0
(empty record), then set
record's recordType to "empty
" and set record's mediaType to ""
.
1
(well-known type record):
T
" (0x54
)U
" (0x55
)Sp
" (0x53
0x70
)2
(MIME type record), then
set record to the result of running parse an NDEF MIME type record
on ndef, or make sure that the underlying platform provides equivalent
values to the record object's properties.
3
(absolute-URL record), then
set record to the result of running parse an NDEF absolute-URL record
on ndef.
4
(external type record),
then set record to the result of running parse an NDEF external type record
on ndef, or make sure that the underlying platform provides equivalent values
to the record object's properties.
5
(unknown record)
then set record to the result of running parse an NDEF unknown record
on ndef, or make sure that the underlying platform provides equivalent values
to the record object's properties.
T
recordsTo parse an NDEF text record given a ndefRecord into a record, run these steps:
text
".
text
", subtype "plain
" and parameters
equal to an empty ordered map.
undefined
and return record.
5
to bit 0
of the header.
1
byte, inclusive.
lang
"] to language.
U
recordsTo parse an NDEF URL record given a ndefRecord into a record, run these steps:
url
".
text/plain
".
undefined
and return record.
Sp
recordsTo parse an NDEF smart-poster record given a ndefRecord into a record, run these steps:
smart-poster
".
undefined
and return record.
To parse an NDEF MIME type record given a ndefRecord into a record, run these steps:
json
".
media
".
undefined
.
To parse an NDEF absolute-URL record given a ndefRecord into a record, run these steps:
url
".
text/plain
".
To parse an NDEF external type record given a ndefRecord into a record, run these steps:
application/octet-stream
".
undefined
.
To parse an NDEF unknown record given a ndefRecord into a record, run these steps:
media
".
application/octet-stream
".
undefined
.
[Exposed=Window] interfaceNDEFMessage
{constructor
(NDEFMessageInit
messageInit); readonly attribute FrozenArray<NDEFRecord
>records
; }; dictionaryNDEFMessageInit
{ required sequence<NDEFRecordInit
>records
; }; [Exposed=Window] interfaceNDEFRecord
{constructor
(NDEFRecordInit
recordInit); readonly attributeNDEFRecordType
recordType
; readonly attribute USVStringmediaType
; readonly attribute USVStringid
; USVString?text
(); [NewObject] ArrayBuffer?arrayBuffer
(); [NewObject] anyjson
(); sequence<NDEFRecord
>toRecords
(); }; dictionaryNDEFRecordInit
{ requiredNDEFRecordType
recordType
; USVStringmediaType
; USVStringid
; anydata
; }; typedef DOMStringNDEFRecordType
; typedef (DOMString or ArrayBuffer orNDEFMessageInit
)NDEFMessageSource
; [SecureContext, Exposed=Window] interfaceNFCWriter
{constructor
(); Promise<void>push
(NDEFMessageSource
message, optionalNFCPushOptions
options={}); }; [SecureContext, Exposed=Window] interfaceNFCReader
: EventTarget {constructor
(); attribute EventHandleronreading
; attribute EventHandleronerror
; voidscan
(optionalNFCScanOptions
options={}); }; [SecureContext, Exposed=Window] interfaceNFCReadingEvent
: Event {constructor
(DOMString type,NFCReadingEventInit
readingEventInitDict); readonly attribute DOMStringserialNumber
; [SameObject] readonly attributeNDEFMessage
message
; }; dictionaryNFCReadingEventInit
: EventInit { DOMString?serialNumber
= ""; requiredNDEFMessageInit
message
; }; [SecureContext, Exposed=Window] interfaceNFCErrorEvent
: Event {constructor
(DOMString type,NFCErrorEventInit
errorEventInitDict); readonly attribute DOMExceptionerror
; }; dictionaryNFCErrorEventInit
: EventInit { required DOMExceptionerror
; }; dictionaryNFCPushOptions
{NFCPushTarget
target
= "any"; unrestricted doubletimeout
= Infinity; booleanignoreRead
= true; booleanoverwrite
= true; AbortSignal?signal
; }; enumNFCPushTarget
{ "tag
", "peer
", "any
" }; dictionaryNFCScanOptions
{ USVStringid
= "";NDEFRecordType
recordType
; USVStringmediaType
= ""; AbortSignal?signal
; };
The editors would like to thank Jeffrey Yasskin, Anne van Kesteren, Anssi Kostiainen, Domenic Denicola, Daniel Ehrenberg, Jonas Sicking, Don Coleman, Salvatore Iovene, Rijubrata Bhaumik, Wanming Lin, and François Beaufort for their contributions to this document.
Special thanks to Luc Yriarte and Samuel Ortiz for their initial work on exposing NFC to the web platform, and for their support for the current approach.