diff --git a/index.html b/index.html index 9a9686a..0e2892b 100644 --- a/index.html +++ b/index.html @@ -46,7 +46,22 @@ } ] }, - ] + ], + localBiblio: { + "NFC_SECURITY": { + href: "https://github.com/w3c/web-nfc/security-privacy.html", + title: "Web NFC Security and Privacy", + publisher: "W3C", + date: "25 April 2015", + }, + "NFC_USECASES": { + href: "https://github.com/w3c/web-nfc/use-cases.html", + title: "Web NFC Use Cases", + publisher: "W3C", + date: "25 April 2015", + }, + }, + }; @@ -93,17 +108,6 @@ product: the user agent that implements the interfaces it contains.
- -Implementations that use ECMAScript to implement the APIs defined in this specification MUST implement them in a manner consistent with the @@ -174,6 +178,15 @@ via user interface or host device platform features, via which the user approves the permission of a web app to access the Web NFC API.
++ The term obtain permission for a certain operation refers to + obtain expressed permission or to ensure the existence of a + prearranged trust relationship. +
+
+ URL
+
is defined in [[!URL]].
+
Blob
is defined in [[!FILEAPI]].
@@ -190,7 +203,7 @@
are defined in [[!WEBIDL]].
- NFC stands for Near Field Communications, short-range wireless + 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 @@ -201,13 +214,13 @@
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 contain multiple NFC - adapters. + given hardware element (NFC chip). A device may have multiple NFC + adapters, for instance a built-in one, and one attached via USB.
An NFC tag is a passive, unpowered NFC device. The NFC tag is powered by magnetic induction when an active NFC - device is in proximity range. A NFC tag contains a single + device is in proximity range. An NFC tag contains a single NDEF message.
The way of reading the message may happen through proprietary @@ -281,6 +294,16 @@ URI, Smart Poster (containing a URI or other data and possible actions).
++ A Web NFC message is an NDEF message which contains at + least one Web NFC record. +
+
+ A Web NFC record is an NDEF record with TNF=4
+ (External Type Record), and the type field set to
+ "urn:nfc:ext:w3.org:webnfc"
. Further formatting details are
+ described Data Types.
+
An NFC handover defines NFC Forum Well Known Types and the corresponding message structure that allows negotiation and activation of an alternative communication carrier, such as Bluetooth or WiFi. @@ -294,6 +317,8 @@ web app which is invoking the methods of this API has been checked to comply with the security policies set by the underlying platform and API implementation in the moment and context of invoking the API method. + Further details are described in + Security and Privacy.
The term @@ -304,8 +329,6 @@ The term URL scope is introduced in this document for NFC operations as a sub-domain match to the web app's document URL, which includes the domain of the calling web app. - The URL scope is stored in the identifier field of an - NDEF record.
@@ -317,12 +340,14 @@NFC works using magnetic induction, meaning that the reader will emit a small electric charge which then creates a magnetic field. This field powers - the passive device which turns it in to electrical impulses to communicate + 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, for then to fall back into target mode. If a target is found, the + 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 legacy RFIDs tags, but many of these are only supported by single + As NFC is based on existing RFID standards, many NFC chipsets support + reading RFIDs tags, but many of these are only supported by single vendors and not part of the NFC standards. Though certain devices support reading and writing to these, it is not a goal of this specification to support proprietary tags or support interoperability with legacy systems. @@ -419,38 +444,30 @@ that tag. If multiple websites can handle the tag, a choice is presented to the user to pick the preferred web site for handling the tag. - Web sites have a programmatic means to tell the user agent - they are able and interested to handle NFC tags of certain - type. + Optionally, web sites have a programmatic means to tell the + user agent they are able and interested to handle + NFC tags of certain type.
The following high level technical requirements result from the - enumerated use cases and high level features: + enumerated use cases and high level features. With this version of the + API, web pages should be able to:
The following types can be used when writing NFC tags, sending - data to NFC peers, and when reading NDEF messages. -
-
- NdefData
denotes the data types
- supported as NDEF record payload in read and write operations in
- this API.
-
- The mapping from supported NdefData
to
- NDEF record types is as follows:
-
NdefData | -NDEF record type | -
---|---|
DOMString | -NFC Forum Well Known Type (TNF=1) with type Text | -
URL | -- |
JSON | -Media-type as defined in RFC 2046 (TNF=2) with associated
- MIME type "application/webnfc+json"
- |
-
Blob | -
-
|
-
- This section shows how developers can make use of the various features of - this specification. -
-- navigator.nfc.findAdapters().then(function(adapters) { - var adapter = adapters[0]; - var scope = "example.com/tag/updater"; - - adapter.onread = (msg) => { - var timesRead = (msg.data.length > 0) ? msg.data[0].json().timesRead : 0; - if (msg.writeable) - adapter.write([{ timesRead: (timesRead + 1) % 1000 }], scope); - else - console.log("Read-only tag; value = " + timesRead); - }; - - var watchOptions = { - scope: scope, - watchType: "tag-only" - }; - adapter.watch(watchOptions).then(function() { - console.log("We are now watching tags via NFC"); - }); - }).catch(function(err) { - console.log("No NFC adapters found"); - }); --
- navigator.nfc.findAdapters().then(function(adapters) { - var adapter = adapters[0]; - var scope = "/example.com/mygame"; - - adapter.onread = (event) => { - console.log("Game state received from: " + event.scope); - console.log("Game state: " + event.data.json()); - }; - - adapter.onpush = (event) => { // update values - console.log("Successfully pushed a message to: " + event.scope); - updateGameState(); - } - - // fetch game state and update push message - function updateGameState() { - var msg = [ { level: 3, points: 4500, lives: 3 } ]; - adapter.setPushMessage(msg, scope).then(function() { - console.log("Game state updated for push"); - }); - }; - - var withOptions = { - scope: scope, - watchType: "peer-only" - }; - adapter.watch(withOptions).then(function() { - console.log("We are now watching game progress via NFC"); - }); - }); --
- User agents MUST NOT provide Web NFC API access
- to web apps without the
- expressed permission of the user. User agents must acquire consent
- for permission through a user interface for each call to the methods of this
- API, unless a prearranged trust relationship applies.
+ The Permissions API SHOULD
+ be supported by user agents for implementing NFC related
+ [[permissions]]. The required
+
+ permission name is "nfc"
.
- User agents may support prearranged trust relationships that do not require - such per-request user interfaces. + User agents MUST NOT provide Web NFC API access + to web apps without the expressed permission of the user. + User agents must acquire consent for [[permissions]] for each call to the + methods of this API, unless a prearranged trust relationship applies.
Considering adding the following: @@ -702,11 +592,180 @@ for development purposes only.
- Permissions that are preserved beyond the current browsing session must be + Permissions that are preserved beyond the current browsing session MUST be revocable.
++ The Permissions API does + not yet address the issue of revoking permissions. When it will be + addressed, this section will be updated. +
++ User agents MUST implement the following policies: +
"https://"
SHOULD be able to read NFC tags that is
+ not empty or does not contain a Web NFC messages.
+ + Web NFC implementations SHOULD use Web NFC messages, which SHOULD + be sufficiently differentiated in order to avoid accidental matching with + a generic NDEF message used in regular NFC tags or between + NFC peers. This is achieved by using an additional + Web NFC record, and in rest using normal NDEF records in + order to compose the NDEF message. +
++ The format of a Web NFC record is the following. +
urn:nfc:ext:w3.org:webnfc
.
+ + The payload of a Web NFC message is represented by using normal + NDEF records. + The following types can be used as payload, i.e. when writing to + NFC tags, sending data to NFC peers, and when reading + NDEF messages. +
++ NfcData denotes the data types + supported as NDEF record payload in read and send operations in + this API. +
+
+ The mapping from supported NfcData
to
+ NDEF record types, as used in the send()
+ method is as follows:
+
NfcData | +NDEF record type | +
---|---|
DOMString | +NFC Forum Well Known Type (TNF=1) with type Text | +
URL | ++ |
JSON | +Media-type as defined in [[RFC2046]] (TNF=2) with associated
+ MIME type "application/json"
+ |
+
Blob with MIME type | +Media-type as defined in [[RFC2046]] (TNF=2) | +
Blob without MIME type | +NFC Forum External Type (TNF=4) | +
+ The mapping from NDEF record types to NfcData
,
+ as used for incoming NDEF messages exposed by the
+ NfcMessageEvent
, is as follows:
+
NDEF record type | +NfcData | +
---|---|
NFC Forum Well Known Type (TNF=1) with type Text | +DOMString | +
NFC Forum Well Known Type (TNF=1) with type URI | +URL object | +
NFC Forum Well Known Type (TNF=1) with type + Smart Poster | +URL object | +
Absolute URI as defined in [[RFC3986]] (TNF=3) | +URL object | +
Media-type as defined in [[RFC2046]] (TNF=2) with associated
+ MIME type "application/json"
+ |
+ JSON object | +
Media-type as defined in [[RFC2046]] (TNF=2) | +Blob object | +
NFC Forum External Type (TNF=4) with type other than
+ urn:nfc:ext:w3.org:webnfc |
+ Blob object | +
Any other NDEF record type | +Blob object | +
+ Note that Web NFC records are not exposed to client web apps. +
+@@ -716,31 +775,30 @@ extends.
When getting the nfc attribute, the - user agent MUST return the NFC object, which provides + user agent MUST return the Nfc object, which provides NFC related functionality.
- Implementations might expose multiple NFC adapters. By using the + Implementations MAY expose multiple NFC adapters. By using the - findAdapters() method, web apps can obtain adapter objects - providing NFC functionality, - in a similar way to that of service worker extensions [[SERVICE-WORKERS]]. + requestAdapter() method, web apps can obtain an adapter object + providing NFC functionality. When this method is invoked, the user agent MUST run the following steps: -
Promise
object.
DOMException
object whose name property
- is set to "SecurityError"
, and terminate these
- steps.
+ then reject promise with "SecurityError"
,
+ and terminate these steps.
DOMException
object whose name property
- is set to "NotSupportedError"
, and terminate
- these steps.
+ then reject promise with
+ "NotSupportedError"
, and terminate these steps.
DOMException
object whose name
- property is set to "NotSupportedError"
,
- and terminate these steps.
+ then reject promise with
+ "NotSupportedError"
, and terminate these steps.
+ null
."NotFoundError"
, and terminate these steps.
+ NfcAdapter
objects. Implementations SHOULD
- maintain a default adapter, which SHOULD be exposed as the first
- element in the returned array.
+ Resolve promise with adapter.
The NfcAdapter
interface handles incoming NDEF messages,
- exposed by the NdefReadEvent
event, both from
- NFC tags and NFC peers. By default, listening to this event
- SHOULD be disabled. Applications can subscribe to NDEF messages
- originating from a given URL scope by using the watch()
- method. Applications can write to an NFC tag, and set up push
- messages to NFC peers.
+ exposed by the NfcMessageEvent
event, either from an
+ NFC tag or an NFC peer. By default, listening to this event
+ SHOULD be disabled.
onread
read
NdefReadEvent
onpush
push
NdefPushEvent
onmessage
message
NfcMessageEvent
- The read
event is used for notifying the adapter
- object about a message dispatched to the web app via NFC.
+ The message
event is used for notifying the adapter
+ object about an NDEF message dispatched to the web app.
- As messages are not automatically pushed to peers when they detect each
- other, but most often requires some kind of user interaction, the
- push
event is used for notifying the adapter object about a
- message successfully pushed to an NFC peer with a matching
- URL scope in range via NFC.
-
- The scope
property
- represents the URL scope of the NDEF message.
-
- When the
- readAsMessageBuffer
method is invoked, the
- user agent MUST run the following steps:
-
ArrayBuffer
- object.
- In this specification, NDEF message content is delivered by an - NdefReadEvent event. + NfcMessageEvent event.
- The NdefReadEvent
has all properties and methods of the
- NdefPushEvent
interface, and the following additional
- properties:
-
- The passive
- property MUST return true
if the source of the NFC data is
- a passive NFC tag, and false
otherwise.
-
- The writeable
- property MUST return true
if the source of the NFC data is
- a passive NFC tag which is writeable, and false
- otherwise.
+ The message
+ property MUST return the NfcMessage
representing the
+ payload data of the NDEF message.
- The data
- property represents the array of NdefRecordData
- content corresponding to the array of NDEF records payload data of
- the NDEF message.
-
The content of the NDEF message is exposed by the following interface:
-
- NdefRecordData objects have associated data read by the NFC chip
- upon creation.
+ The scope
+ property MUST return the URL scope which has written the message.
The
- contentType
- attribute describes the type of data such as MIME type and additional
- information for text messages, e.g.
- "text/plain;charset=UTF-8;"
+ data property MUST return the
+ payload data of the NDEF message as an array of either
+ DOMString
, or URL
object, or Blob
+ object, or serializable JSON object as a generic Object
.
- The url()
- method, when invoked, MUST return a DOMString
- representing any URL stored in the NDEF message or
- undefined
.
-
- The blob()
- method, when invoked, MUST return a Blob
whose
- contents are bytes.
-
- The json()
- method, when invoked, MUST return the result of invoking the initial
- value of JSON.parse
with the result of running
- utf-8 decode on bytes as argument.
- Re-throw any exceptions thrown by JSON.parse
.
-
- The text()
-
method, when invoked, MUST return the result of running
- utf-8 decode onbytes.
-
- The
- arrayBuffer()
method, when invoked, MUST return an
- ArrayBuffer
whose contents are bytes.
-
The
-
- watch()
method enables listening to incoming
- NDEF messages.
-
- As web apps might not be interested in all peer and tag messages, - filtering is possible for watched messages: -
- Future versions may add additional filtering criteria, e.g. based on - NFC Forum Tag types (such as Type 1 to 4), and NFC technologies (such as - NFC-A, NFC-B, etc). -
-- When writing to tags or pushing messages to peers, the - document base URL serves as the default scope, though another - URL scope can be set with the restriction that it MUST include the - document domain (e.g. http://www.w3.org). -
-- To describe which messages an application is interested in, the following - dictionary is used: -
- -
- The scope property
- denotes the URL scope for which all messages MUST belong to.
- If the value is null
or undefined
,
- then implementations SHOULD use the web app's
- document base URL.
-
- The - - acceptedContentTypes property denotes the list of MIME types, that - the registrations wants to handle. -
-- The watchType property - tells whether to watch: -
'tag-only'
.
- 'peer-only'
.
- 'all'
.
- - var watchOptions = { - scope: "http://www.w3.org", - acceptedContentTypes: ["application/manifest+json", "application/json", "text/json"] - } --
- var watchOptions = { - scope: "https://01.org/registration", - acceptedContentTypes: ["application/json"], - watchType: 'tag-only' - } --
- Inputs: -
Output: true
or false
- When filtering NDEF messages with identifiers associated with - url, based on URL scope, run the following steps - atomically. -
undefined
, then let
- scope be the calling web app's
- document base URL.
- "/*"
, then
- return true
.
- true
.
- false
.
-
- When the
-
- watch()
method is invoked, the user agent MUST run
- the following steps:
-
Promise
object.
- DOMException
object whose name property
- is set to "SecurityError"
,
- and terminate these steps.
- DOMException
object whose name property
- is set to "SyntaxError"
, and terminate these steps.
- read
events only for
- messages, whose URL scope is within-scope for any of the
- elements of the list of URL scopes registered during successive
- calls of the watch()
method,
- and for which the content type matches the list of accepted content
- types.
- DOMException
object whose name property
- is set to "NotSupportedError"
, and terminate these steps.
- clearWatch()
method to remove the listener.
- "read"
event at
- the adapter object.
-
- When the
- clearWatch()
method is invoked, the user agent
- MUST run the following steps:
-
Promise
object.
+ Let promise be a new Promise
object.
DOMException
object whose name property
- is set to "SecurityError"
,
- and terminate these steps.
- undefined
, then make
- a request to the underlying platform to remove all listeners and
- filters set by successive calls of the watch()
- method.
- "SecurityError"
, and terminate these steps.
DOMException
object whose name property
- is set to "NotSupportedError"
, and terminate these steps.
-
- The
- write()
method is used for writing an NFC tag, if
- possible. When this method is invoked, the user agent MUST run the
- following steps:
-
Promise
object.
- DOMException
object
- whose name property is set to
- "SecurityError"
, and terminate these steps.
+ If there is no support for the functionality of sending data to an
+ NFC peer in proximity range, or to write data to an
+ NFC tag, then reject promise with
+ "NotSupportedError"
, and terminate these steps.
DOMException
object whose name
- property is set to "NotSupportedError"
, and
- terminate these steps.
+ Parse the argument options. If it is undefined
+ or null
, then use the default values.
+ Otherwise if invalid, then reject promise with
+ "SyntaxError"
, and terminate these steps.
DOMException
- object whose name property is set
- to "SyntaxError"
, and terminate these steps.
- If the value is undefined
, then attribute to
- scope the DOMString
describing the
- document base URL.
+ Parse the argument message.scope.
+ If the value is undefined
, then set scope to
+ the DOMString
describing the document base URL.
+ If it is invalid in the given platform, or if it is not a
+ sub-domain match of the document base URL, then reject
+ promise with "SyntaxError"
, and terminate
+ these steps.
NdefData
.
+ For each element in the array message.data,
+ check the type
+ to be one of the supported types.
If the value is invalid on the given platform, then reject
- promise with a new DOMException
- object whose name property is set to
- "SyntaxError"
, and terminate these steps.
+ promise with "SyntaxError"
, and
+ terminate these steps.
For each valid element create an NDEF record.
The implementation choose the best suitable NDEF record format
for the given platform.
- Each element in the input array given in data SHOULD
- map to a separate NDEF record in the NDEF message to be
- sent.
- Assemble an NDEF message from the NDEF records and
- referred to as output.
+ Each element in the input array given in message.data
+ SHOULD map to a separate NDEF record in the NDEF message
+ to be sent.
DOMException
- object whose name property is set to
- "NotSupportedError"
, and terminate these steps.
-
- The
-
- setPushMessage()
method is used for setting the messages
- which the user can push to another peer when it gets into proximity range.
- When this method is invoked, the user agent MUST run the following
- steps:
-
Promise
object.
+ Assemble an NDEF message from the NDEF records and an
+ additional Web NFC record, referred to as output.
DOMException
object
- whose name property is set to
- "SecurityError"
, and terminate these steps.
+ If options.target has the value "tag"
, then
+ the sending should only happen if an NFC tag is tapped within
+ a platform specific timeout, otherwise reject promise with
+ a "TimeoutError"
in the case of timeout, or
+ "InvalidAccessError"
if an NFC peer is
+ tapped instead of a tag.
DOMException
object whose
- name property is set to
- "NotSupportedError"
, and terminate these steps.
+ If options.target has the value "peer"
, then
+ the sending should only happen if an NFC peer is tapped within
+ a platform specific timeout, otherwise reject promise with
+ a "TimeoutError"
in the case of timeout, or
+ "InvalidAccessError"
if an NFC tag is
+ tapped instead of a peer.
DOMException
- object whose name property is set
- to "SyntaxError"
, and terminate these steps.
- If the value is undefined
, then attribute to
- scope the DOMString
describing the
- document base URL.
- NdefData
.
- If the value is invalid on the given platform, then reject
- promise with a new DOMException
- object whose name property is set to
- "SyntaxError"
, and terminate these steps.
- For each valid element create an NDEF record.
- The implementation choose the best suitable NDEF record format
- for the given platform.
- Each element in the input array given in data SHOULD
- map to a separate NDEF record in the NDEF message to be
- sent.
- Assemble an NDEF message from the NDEF records and
- referred to as output.
- DOMException
- object whose name property is set to
- "NotSupportedError"
, and terminate these steps.
+ If options.target has the value "any"
(which
+ is the default value), then the sending should happen if either an
+ NFC peer or an NFC tag is tapped within a platform
+ specific timeout, otherwise reject promise with
+ "TimeoutError"
.
+ The target property
+ denotes the intended target for the pending send()
+ operation. The default value is "any"
.
+
- When the
-
- clearPushMessage()
method is invoked, the
- user agent MUST run the following steps:
-
Promise
object.
- DOMException
object whose name property
- is set to "SecurityError"
,
- and terminate these steps.
- undefined
, then make
- a request to the underlying platform to remove and cancel pushing any
- previously set messages to NFC peer devices in range or coming
- into range.
- DOMException
object whose name property
- is set to "NotSupportedError"
, and terminate these steps.
- + navigator.permissions.query({name: 'nfc'}).then((result) => { + if (result.status == 'granted') { + enableNfcUseCase(); // Do things here. + } else if (result.status == 'prompt') { + // The user agent will prompt. + } + // Otherwise don't do anything since it will fail. + }); ++
+ var adapter = null; + navigator.nfc.requestAdapter().then((nfcAdapter) => { + adapter = nfcAdapter; + adapter.onmessage = onMessage; + }; + + function onMessage(event) { + console.log("NDEF message received from scope " + event.message.scope); + var data = event.message.data; + + if (!data) { // empty tag + writeMessageOnTag({data: “Initializing a passive tag”}); + } + + if (typeof data == ‘string’) { + console.log(“Data is string: “ + data); + } else if (data instanceof Blob) { + processBlob(data); + } else if (data instanceof URL) { + console.log(“Data is URL: “ + data.toString()); + } else if (typeof data == ‘object’) { + processJson(data); + } + }; + + function writeMessageOnTag(msg) { + adapter.send(msg, {target: "tag"}) + .then(() => { console.log("Send was successful")}) + .catch(() => { console.log("Send failed")}); + }; + + function processBlob(data) { + console.log(“Blob size: ” + data.size + “ bytes”); + console.log(“Blob type: ” + data.type); + var reader = new FileReader(); + reader.addEventListener(“loadend”, function() { + console.log(“Blob data: ” + reader.result); + // Now send a response based on the data. + adapter.send({data: “Response to blob” }) + .then(() => { console.log("Send was successful")}) + .catch(() => { console.log("Send failed")}); + }); + reader.readAsText(data); + }; + + function processJson(data) { + if (myCondition(data.myKnownProperty)) { + adapter.send({data: “Custom data”}); + }; ++
+ navigator.nfc.requestAdapter().then((adapter) => { + console.log("Waiting for game state"); + adapter.onmessage = (event) => { + console.log("Game state received from: " + event.message.scope); + console.log("Game state: " + event.message.data); + // Now do some calculations and update the state. + adapter.send({ scope: event.message.scope, + data: [ { level: 3, points: 4500, lives: 3 } ] }) + .then(() => { console.log("Send was successful")}) + .catch(() => { console.log("Send failed")}); + }; + }); ++
+ The following problems are being discussed and need most attention: +
+ +The editors would like to express their gratitude to the former editors - Luc Yriarte and Samuel Ortiz, and also to Don Coleman, Salvatore Iovene and - Jeffrey Yasskin for their technical guidance, implementation feedback and - support. + Luc Yriarte and Samuel Ortiz, and also to Don Coleman, Jeffrey Yasskin, + Salvatore Iovene, and Alexander Shalamov for their technical guidance, + implementation feedback and support.
The encoded JSON format for Web NFC data and metadata is useful for abstracting away NFC Forum types, and for supporting implementations where @@ -367,6 +364,7 @@
diff --git a/use-cases.html b/use-cases.html index 7b43d3d..16cca8e 100644 --- a/use-cases.html +++ b/use-cases.html @@ -140,6 +140,7 @@ and other data.