Commit 5b152f15 authored by Leon Han's avatar Leon Han Committed by Commit Bot

[webnfc] Introduce NDEFCompatibility to replace NFCWatchMode

This CL switches the existing enum NFCWatchMode to NDEFCompatibility
which is newly defined at
http://w3c.github.io/web-nfc/#dom-ndefcompatibility
and updated the behaviors implemented in Device Service accordingly.

Now we just use it for watch operations, in the future we'll be using it
for push operations as well.

BUG=520391

Change-Id: I82cf736d1a57044e9fd59a350b748b99548f9a82
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1628537
Commit-Queue: Leon Han <leon.han@intel.com>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#666621}
parent 7c7006f2
......@@ -23,6 +23,7 @@ import android.util.SparseArray;
import org.chromium.base.Callback;
import org.chromium.base.ContextUtils;
import org.chromium.base.Log;
import org.chromium.device.mojom.NdefCompatibility;
import org.chromium.device.mojom.NdefMessage;
import org.chromium.device.mojom.Nfc;
import org.chromium.device.mojom.NfcClient;
......@@ -30,7 +31,6 @@ import org.chromium.device.mojom.NfcError;
import org.chromium.device.mojom.NfcErrorType;
import org.chromium.device.mojom.NfcPushOptions;
import org.chromium.device.mojom.NfcPushTarget;
import org.chromium.device.mojom.NfcWatchMode;
import org.chromium.device.mojom.NfcWatchOptions;
import org.chromium.mojo.bindings.Callbacks;
import org.chromium.mojo.system.MojoException;
......@@ -544,20 +544,21 @@ public class NfcImpl implements Nfc {
Log.w(TAG, "Cannot read data from NFC tag. IO_ERROR.");
}
if (message != null) notifyMatchingWatchers(message);
if (message != null) notifyMatchingWatchers(message, mTagHandler.compatibility());
}
/**
* Iterates through active watchers and if any of those match NfcWatchOptions criteria,
* delivers NdefMessage to the client.
*/
private void notifyMatchingWatchers(android.nfc.NdefMessage message) {
private void notifyMatchingWatchers(android.nfc.NdefMessage message, int compatibility) {
try {
NdefMessage ndefMessage = NfcTypeConverter.toNdefMessage(message);
List<Integer> watchIds = new ArrayList<Integer>();
for (int i = 0; i < mWatchers.size(); i++) {
NfcWatchOptions options = mWatchers.valueAt(i);
if (matchesWatchOptions(ndefMessage, options)) watchIds.add(mWatchers.keyAt(i));
if (matchesWatchOptions(ndefMessage, compatibility, options))
watchIds.add(mWatchers.keyAt(i));
}
if (watchIds.size() != 0) {
......@@ -575,10 +576,12 @@ public class NfcImpl implements Nfc {
/**
* Implements matching algorithm.
*/
private boolean matchesWatchOptions(NdefMessage message, NfcWatchOptions options) {
// Valid WebNFC message must have non-empty url.
if (options.mode == NfcWatchMode.WEBNFC_ONLY
&& (message.url == null || message.url.isEmpty())) {
private boolean matchesWatchOptions(
NdefMessage message, int compatibility, NfcWatchOptions options) {
// 'nfc-forum' option can only read messages from NFC standard devices and 'vendor' option
// can only read from vendor specific ones.
if (options.compatibility != NdefCompatibility.ANY
&& options.compatibility != compatibility) {
return false;
}
......
......@@ -12,12 +12,15 @@ import android.nfc.tech.Ndef;
import android.nfc.tech.NdefFormatable;
import android.nfc.tech.TagTechnology;
import org.chromium.device.mojom.NdefCompatibility;
import java.io.IOException;
/**
* Utility class that provides I/O operations for NFC tags.
*/
public class NfcTagHandler {
private final int mCompatibility;
private final TagTechnology mTech;
private final TagTechnologyHandler mTechHandler;
private boolean mWasConnected;
......@@ -32,11 +35,20 @@ public class NfcTagHandler {
if (tag == null) return null;
Ndef ndef = Ndef.get(tag);
if (ndef != null) return new NfcTagHandler(ndef, new NdefHandler(ndef));
if (ndef != null) {
int compatibility = NdefCompatibility.VENDOR;
String type = ndef.getType();
if (type.equals(Ndef.NFC_FORUM_TYPE_1) || type.equals(Ndef.NFC_FORUM_TYPE_2)
|| type.equals(Ndef.NFC_FORUM_TYPE_3) || type.equals(Ndef.NFC_FORUM_TYPE_4)) {
compatibility = NdefCompatibility.NFC_FORUM;
}
return new NfcTagHandler(compatibility, ndef, new NdefHandler(ndef));
}
NdefFormatable formattable = NdefFormatable.get(tag);
if (formattable != null) {
return new NfcTagHandler(formattable, new NdefFormattableHandler(formattable));
return new NfcTagHandler(
NdefCompatibility.VENDOR, formattable, new NdefFormattableHandler(formattable));
}
return null;
......@@ -100,7 +112,8 @@ public class NfcTagHandler {
}
}
protected NfcTagHandler(TagTechnology tech, TagTechnologyHandler handler) {
protected NfcTagHandler(int compatibility, TagTechnology tech, TagTechnologyHandler handler) {
mCompatibility = compatibility;
mTech = tech;
mTechHandler = handler;
}
......@@ -154,4 +167,12 @@ public class NfcTagHandler {
}
return false;
}
/**
* Returns NdefCompatibility.NFC_FORUM if the tag has a NFC standard type, otherwise returns
* NdefCompatibility.VENDOR.
*/
public int compatibility() {
return mCompatibility;
}
}
......@@ -33,12 +33,13 @@ enum NFCPushTarget {
ANY
};
enum NFCWatchMode {
// Restricts scope of the watch operation. Only Web NFC messages must be
// used by matching algorithm.
WEBNFC_ONLY,
// Allows performing watch operation for all NFC messages. For example, NFC
// tags with valid NDEF messages.
enum NDEFCompatibility {
// Allows all active and passive NFC devices, supported by the NFC standard.
NFC_FORUM,
// Allows vendor specific NFC tags (passive device) that require specific
// reader chips.
VENDOR,
// Allows all NDEF compatible devices that the reader chip can read.
ANY
};
......@@ -96,8 +97,8 @@ struct NFCWatchOptions {
// Defines media type filtering constraint.
string? media_type;
// Defines mode of watch operation.
NFCWatchMode mode;
// Defines the accepted kind of NFC devices.
NDEFCompatibility compatibility;
};
interface NFC {
......
......@@ -38,6 +38,7 @@ const char kCharSetUTF8[] = ";charset=UTF-8";
// Mojo type converters
namespace mojo {
using device::mojom::blink::NDEFCompatibility;
using device::mojom::blink::NDEFMessage;
using device::mojom::blink::NDEFMessagePtr;
using device::mojom::blink::NDEFRecord;
......@@ -47,11 +48,10 @@ using device::mojom::blink::NDEFRecordTypeFilter;
using device::mojom::blink::NFCPushOptions;
using device::mojom::blink::NFCPushOptionsPtr;
using device::mojom::blink::NFCPushTarget;
using device::mojom::blink::NFCWatchMode;
using device::mojom::blink::NFCWatchOptions;
using device::mojom::blink::NFCWatchOptionsPtr;
NFCPushTarget toNFCPushTarget(const String& target) {
NFCPushTarget ToNFCPushTarget(const String& target) {
if (target == "tag")
return NFCPushTarget::TAG;
......@@ -61,7 +61,7 @@ NFCPushTarget toNFCPushTarget(const String& target) {
return NFCPushTarget::ANY;
}
NDEFRecordType toNDEFRecordType(const String& recordType) {
NDEFRecordType ToNDEFRecordType(const String& recordType) {
if (recordType == "empty")
return NDEFRecordType::EMPTY;
......@@ -81,15 +81,18 @@ NDEFRecordType toNDEFRecordType(const String& recordType) {
return NDEFRecordType::EMPTY;
}
NFCWatchMode toNFCWatchMode(const String& watchMode) {
if (watchMode == "web-nfc-only")
return NFCWatchMode::WEBNFC_ONLY;
NDEFCompatibility ToNDEFCompatibility(const String& compatibility) {
if (compatibility == "nfc-forum")
return NDEFCompatibility::NFC_FORUM;
if (watchMode == "any")
return NFCWatchMode::ANY;
if (compatibility == "vendor")
return NDEFCompatibility::VENDOR;
if (compatibility == "any")
return NDEFCompatibility::ANY;
NOTREACHED();
return NFCWatchMode::WEBNFC_ONLY;
return NDEFCompatibility::NFC_FORUM;
}
// https://w3c.github.io/web-nfc/#creating-web-nfc-message Step 2.1
......@@ -221,7 +224,7 @@ struct TypeConverter<NDEFRecordPtr, blink::NDEFRecord*> {
NDEFRecordPtr recordPtr = NDEFRecord::New();
if (record->hasRecordType())
recordPtr->record_type = toNDEFRecordType(record->recordType());
recordPtr->record_type = ToNDEFRecordType(record->recordType());
else
recordPtr->record_type = deduceRecordTypeFromDataType(record);
......@@ -312,7 +315,7 @@ struct TypeConverter<NFCPushOptionsPtr, const blink::NFCPushOptions*> {
NFCPushOptionsPtr pushOptionsPtr = NFCPushOptions::New();
if (pushOptions->hasTarget())
pushOptionsPtr->target = toNFCPushTarget(pushOptions->target());
pushOptionsPtr->target = ToNFCPushTarget(pushOptions->target());
else
pushOptionsPtr->target = NFCPushTarget::ANY;
......@@ -336,20 +339,17 @@ struct TypeConverter<NFCWatchOptionsPtr, const blink::NFCWatchOptions*> {
const blink::NFCWatchOptions* watchOptions) {
// https://w3c.github.io/web-nfc/#the-nfcwatchoptions-dictionary
// Default values for NFCWatchOptions dictionary are:
// url = "", recordType = null, mediaType = "", mode = "web-nfc-only"
// url = "", recordType = null, mediaType = "", compatibility = "nfc-forum"
NFCWatchOptionsPtr watchOptionsPtr = NFCWatchOptions::New();
watchOptionsPtr->url = watchOptions->url();
watchOptionsPtr->media_type = watchOptions->mediaType();
if (watchOptions->hasMode())
watchOptionsPtr->mode = toNFCWatchMode(watchOptions->mode());
else
watchOptionsPtr->mode = NFCWatchMode::WEBNFC_ONLY;
watchOptionsPtr->compatibility =
ToNDEFCompatibility(watchOptions->compatibility());
if (watchOptions->hasRecordType()) {
watchOptionsPtr->record_filter = NDEFRecordTypeFilter::New();
watchOptionsPtr->record_filter->record_type =
toNDEFRecordType(watchOptions->recordType());
ToNDEFRecordType(watchOptions->recordType());
}
return watchOptionsPtr;
......@@ -446,7 +446,7 @@ ScriptPromise RejectIfInvalidNDEFRecord(ScriptState* script_state,
const NDEFRecord* record) {
device::mojom::blink::NDEFRecordType type;
if (record->hasRecordType()) {
type = mojo::toNDEFRecordType(record->recordType());
type = mojo::ToNDEFRecordType(record->recordType());
} else {
type = mojo::deduceRecordTypeFromDataType(record);
......@@ -751,7 +751,7 @@ ScriptPromise NFC::cancelPush(ScriptState* script_state, const String& target) {
requests_.insert(resolver);
auto callback = WTF::Bind(&NFC::OnRequestCompleted, WrapPersistent(this),
WrapPersistent(resolver));
nfc_->CancelPush(mojo::toNFCPushTarget(target), std::move(callback));
nfc_->CancelPush(mojo::ToNFCPushTarget(target), std::move(callback));
return resolver->Promise();
}
......
......@@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// https://w3c.github.io/web-nfc/#the-nfcwatchoptions-dictionary
enum NFCWatchMode { "web-nfc-only", "any" };
// http://w3c.github.io/web-nfc/#dom-ndefcompatibility
enum NDEFCompatibility { "nfc-forum", "vendor", "any" };
// https://w3c.github.io/web-nfc/#the-nfcwatchoptions-dictionary
dictionary NFCWatchOptions {
USVString url = "";
NDEFRecordType? recordType;
USVString mediaType = "";
NFCWatchMode mode = "web-nfc-only";
NDEFCompatibility compatibility = "nfc-forum";
};
......@@ -47,8 +47,8 @@ function createNFCPushOptions(target, timeout, ignoreRead) {
return { target, timeout, ignoreRead };
}
function createNFCWatchOptions(url, recordType, mediaType, mode) {
return { url, recordType, mediaType, mode};
function createNFCWatchOptions(url, recordType, mediaType, compatibility) {
return { url, recordType, mediaType, compatibility };
}
function createTextRecord(text) {
......@@ -95,10 +95,12 @@ function toMojoNFCPushTarget(target) {
return device.mojom.NFCPushTarget.ANY;
}
function toMojoNFCWatchMode(mode) {
if (mode === 'web-nfc-only')
return device.mojom.NFCWatchMode.WEBNFC_ONLY;
return device.mojom.NFCWatchMode.ANY;
function toMojoNDEFCompatibility(compatibility) {
if (compatibility === 'nfc-forum')
return device.mojom.NDEFCompatibility.NFC_FORUM;
if (compatibility === 'vendor')
return device.mojom.NDEFCompatibility.VENDOR;
return device.mojom.NDEFCompatibility.ANY;
}
// Converts between NDEFMessage https://w3c.github.io/web-nfc/#dom-ndefmessage
......@@ -233,10 +235,10 @@ function assertNFCWatchOptionsEqual(provided, received) {
else
assert_equals(received.mediaType, '');
if (provided.mode !== undefined)
assert_equals(toMojoNFCWatchMode(provided.mode), received.mode);
if (provided.compatibility !== undefined)
assert_equals(toMojoNDEFCompatibility(provided.compatibility), received.compatibility);
else
assert_equals(received.mode, device.mojom.NFCWatchMode.WEBNFC_ONLY);
assert_equals(received.compatibility, device.mojom.NDEFCompatibility.NFC_FORUM);
if (provided.recordType !== undefined) {
assert_equals(!+received.record_filter, true);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment