Commit 645a24e4 authored by Francois Beaufort's avatar Francois Beaufort Committed by Commit Bot

[WebNFC] Support NDEF tag with no message

This CL makes sure NDEF tags still fire an onreading Web NFC event
even if there are no messages yet. This results in a NDEFMessage with
no records as discussed in https://github.com/w3c/web-nfc/issues/367.

Bug: 520391, 1012463
Change-Id: Ib87980cfc7354561146f7854272b247fb6df5a79
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1871550
Commit-Queue: François Beaufort <beaufort.francois@gmail.com>
Reviewed-by: default avatarRijubrata Bhaumik <rijubrata.bhaumik@intel.com>
Cr-Commit-Position: refs/heads/master@{#708145}
parent cdfa1532
......@@ -29,6 +29,7 @@ import org.chromium.device.mojom.NdefErrorType;
import org.chromium.device.mojom.NdefMessage;
import org.chromium.device.mojom.NdefPushOptions;
import org.chromium.device.mojom.NdefPushTarget;
import org.chromium.device.mojom.NdefRecord;
import org.chromium.device.mojom.NdefScanOptions;
import org.chromium.device.mojom.Nfc;
import org.chromium.device.mojom.NfcClient;
......@@ -550,14 +551,21 @@ public class NfcImpl implements Nfc {
mTagHandler.connect();
message = mTagHandler.read();
if (message == null) {
Log.w(TAG, "Cannot read data from NFC tag. Tag is empty.");
// Tag is formatted to support NDEF but does not contain a message yet.
// Let's create one with no records so that watchers can be notified.
NdefMessage webNdefMessage = new NdefMessage();
webNdefMessage.data = new NdefRecord[0];
notifyMatchingWatchers(webNdefMessage);
return;
}
if (message.getByteArrayLength() > NdefMessage.MAX_SIZE) {
Log.w(TAG, "Cannot read data from NFC tag. NdefMessage exceeds allowed size.");
return;
}
notifyMatchingWatchers(message);
NdefMessage webNdefMessage = NdefMessageUtils.toNdefMessage(message);
notifyMatchingWatchers(webNdefMessage);
} catch (UnsupportedEncodingException e) {
Log.w(TAG, "Cannot read data from NFC tag. Cannot convert to NdefMessage.");
} catch (TagLostException e) {
Log.w(TAG, "Cannot read data from NFC tag. Tag is lost.");
} catch (FormatException | IllegalStateException | IOException e) {
......@@ -569,26 +577,21 @@ public class NfcImpl implements Nfc {
* Iterates through active watchers and if any of those match NdefScanOptions criteria,
* delivers NdefMessage to the client.
*/
private void notifyMatchingWatchers(android.nfc.NdefMessage message) {
try {
NdefMessage ndefMessage = NdefMessageUtils.toNdefMessage(message);
List<Integer> watchIds = new ArrayList<Integer>();
for (int i = 0; i < mWatchers.size(); i++) {
NdefScanOptions options = mWatchers.valueAt(i);
if (matchesWatchOptions(ndefMessage, options)) {
watchIds.add(mWatchers.keyAt(i));
}
private void notifyMatchingWatchers(NdefMessage message) {
List<Integer> watchIds = new ArrayList<Integer>();
for (int i = 0; i < mWatchers.size(); i++) {
NdefScanOptions options = mWatchers.valueAt(i);
if (matchesWatchOptions(message, options)) {
watchIds.add(mWatchers.keyAt(i));
}
}
if (watchIds.size() != 0) {
int[] ids = new int[watchIds.size()];
for (int i = 0; i < watchIds.size(); ++i) {
ids[i] = watchIds.get(i).intValue();
}
mClient.onWatch(ids, mTagHandler.serialNumber(), ndefMessage);
if (watchIds.size() != 0) {
int[] ids = new int[watchIds.size()];
for (int i = 0; i < watchIds.size(); ++i) {
ids[i] = watchIds.get(i).intValue();
}
} catch (UnsupportedEncodingException e) {
Log.w(TAG, "Cannot convert NdefMessage to NdefMessage.");
mClient.onWatch(ids, mTagHandler.serialNumber(), message);
}
}
......
......@@ -544,6 +544,32 @@ public class NFCTest {
assertEquals(watchId2, mOnWatchCallbackCaptor.getValue()[1]);
}
/**
* Test that Nfc.watch() notifies client when tag is not formatted.
*/
@Test
@Feature({"NFCTest"})
public void testWatchNotFormattedTag() throws IOException, FormatException {
TestNfcImpl nfc = new TestNfcImpl(mContext, mDelegate);
mDelegate.invokeCallback();
nfc.setClient(mNfcClient);
int watchId = mNextWatchId++;
WatchResponse mockWatchCallback = mock(WatchResponse.class);
nfc.watch(createNdefScanOptions(), watchId, mockWatchCallback);
verify(mockWatchCallback).call(mErrorCaptor.capture());
assertNull(mErrorCaptor.getValue());
// Returning null means tag is not formatted.
doReturn(null).when(mNfcTagHandler).read();
nfc.processPendingOperationsForTesting(mNfcTagHandler);
// Check that client was notified and correct watch id was provided.
verify(mNfcClient, times(1))
.onWatch(mOnWatchCallbackCaptor.capture(), nullable(String.class),
any(NdefMessage.class));
assertEquals(watchId, mOnWatchCallbackCaptor.getValue()[0]);
}
/**
* Test that Nfc.watch() matching function works correctly.
*/
......
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