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; ...@@ -29,6 +29,7 @@ import org.chromium.device.mojom.NdefErrorType;
import org.chromium.device.mojom.NdefMessage; import org.chromium.device.mojom.NdefMessage;
import org.chromium.device.mojom.NdefPushOptions; import org.chromium.device.mojom.NdefPushOptions;
import org.chromium.device.mojom.NdefPushTarget; import org.chromium.device.mojom.NdefPushTarget;
import org.chromium.device.mojom.NdefRecord;
import org.chromium.device.mojom.NdefScanOptions; import org.chromium.device.mojom.NdefScanOptions;
import org.chromium.device.mojom.Nfc; import org.chromium.device.mojom.Nfc;
import org.chromium.device.mojom.NfcClient; import org.chromium.device.mojom.NfcClient;
...@@ -550,14 +551,21 @@ public class NfcImpl implements Nfc { ...@@ -550,14 +551,21 @@ public class NfcImpl implements Nfc {
mTagHandler.connect(); mTagHandler.connect();
message = mTagHandler.read(); message = mTagHandler.read();
if (message == null) { 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; return;
} }
if (message.getByteArrayLength() > NdefMessage.MAX_SIZE) { if (message.getByteArrayLength() > NdefMessage.MAX_SIZE) {
Log.w(TAG, "Cannot read data from NFC tag. NdefMessage exceeds allowed size."); Log.w(TAG, "Cannot read data from NFC tag. NdefMessage exceeds allowed size.");
return; 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) { } catch (TagLostException e) {
Log.w(TAG, "Cannot read data from NFC tag. Tag is lost."); Log.w(TAG, "Cannot read data from NFC tag. Tag is lost.");
} catch (FormatException | IllegalStateException | IOException e) { } catch (FormatException | IllegalStateException | IOException e) {
...@@ -569,26 +577,21 @@ public class NfcImpl implements Nfc { ...@@ -569,26 +577,21 @@ public class NfcImpl implements Nfc {
* Iterates through active watchers and if any of those match NdefScanOptions criteria, * Iterates through active watchers and if any of those match NdefScanOptions criteria,
* delivers NdefMessage to the client. * delivers NdefMessage to the client.
*/ */
private void notifyMatchingWatchers(android.nfc.NdefMessage message) { private void notifyMatchingWatchers(NdefMessage message) {
try { List<Integer> watchIds = new ArrayList<Integer>();
NdefMessage ndefMessage = NdefMessageUtils.toNdefMessage(message); for (int i = 0; i < mWatchers.size(); i++) {
List<Integer> watchIds = new ArrayList<Integer>(); NdefScanOptions options = mWatchers.valueAt(i);
for (int i = 0; i < mWatchers.size(); i++) { if (matchesWatchOptions(message, options)) {
NdefScanOptions options = mWatchers.valueAt(i); watchIds.add(mWatchers.keyAt(i));
if (matchesWatchOptions(ndefMessage, options)) {
watchIds.add(mWatchers.keyAt(i));
}
} }
}
if (watchIds.size() != 0) { if (watchIds.size() != 0) {
int[] ids = new int[watchIds.size()]; int[] ids = new int[watchIds.size()];
for (int i = 0; i < watchIds.size(); ++i) { for (int i = 0; i < watchIds.size(); ++i) {
ids[i] = watchIds.get(i).intValue(); ids[i] = watchIds.get(i).intValue();
}
mClient.onWatch(ids, mTagHandler.serialNumber(), ndefMessage);
} }
} catch (UnsupportedEncodingException e) { mClient.onWatch(ids, mTagHandler.serialNumber(), message);
Log.w(TAG, "Cannot convert NdefMessage to NdefMessage.");
} }
} }
......
...@@ -544,6 +544,32 @@ public class NFCTest { ...@@ -544,6 +544,32 @@ public class NFCTest {
assertEquals(watchId2, mOnWatchCallbackCaptor.getValue()[1]); 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. * 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