Commit f0bb4f52 authored by Leon Han's avatar Leon Han Committed by Commit Bot

[webnfc] Support reading/writing smart-poster records

The spec changes:
https://github.com/w3c/web-nfc/pull/361
https://github.com/w3c/web-nfc/pull/495
https://github.com/w3c/web-nfc/pull/536

BUG=520391

Change-Id: I00a363aba07d1f9f2f8e40212dca7650e26047a2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2038492
Commit-Queue: Leon Han <leon.han@intel.com>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Reviewed-by: default avatarFrançois Beaufort <beaufort.francois@gmail.com>
Cr-Commit-Position: refs/heads/master@{#743864}
parent 422366b5
...@@ -149,8 +149,7 @@ public final class NdefMessageUtils { ...@@ -149,8 +149,7 @@ public final class NdefMessageUtils {
return new android.nfc.NdefRecord(android.nfc.NdefRecord.TNF_EMPTY, return new android.nfc.NdefRecord(android.nfc.NdefRecord.TNF_EMPTY,
null /* type */, null /* id */, null /* payload */); null /* type */, null /* id */, null /* payload */);
case RECORD_TYPE_SMART_POSTER: case RECORD_TYPE_SMART_POSTER:
// TODO(https://crbug.com/520391): Support 'smart-poster' type records. return createPlatformSmartPosterRecord(record.id, record.payloadMessage);
throw new InvalidNdefMessageException();
} }
throw new InvalidNdefMessageException(); throw new InvalidNdefMessageException();
} }
...@@ -294,6 +293,18 @@ public final class NdefMessageUtils { ...@@ -294,6 +293,18 @@ public final class NdefMessageUtils {
return nfcRecord; return nfcRecord;
} }
/**
* Constructs smart-poster NdefRecord
*/
private static NdefRecord createSmartPosterRecord(byte[] payload) {
NdefRecord nfcRecord = new NdefRecord();
nfcRecord.category = NdefRecordTypeCategory.STANDARDIZED;
nfcRecord.recordType = RECORD_TYPE_SMART_POSTER;
nfcRecord.data = payload;
nfcRecord.payloadMessage = getNdefMessageFromPayloadBytes(payload);
return nfcRecord;
}
/** /**
* Constructs local type NdefRecord * Constructs local type NdefRecord
*/ */
...@@ -319,7 +330,9 @@ public final class NdefMessageUtils { ...@@ -319,7 +330,9 @@ public final class NdefMessageUtils {
return createTextRecord(record.getPayload()); return createTextRecord(record.getPayload());
} }
// TODO(https://crbug.com/520391): Support RTD_SMART_POSTER type records. if (Arrays.equals(record.getType(), android.nfc.NdefRecord.RTD_SMART_POSTER)) {
return createSmartPosterRecord(record.getPayload());
}
// Prefix the raw local type with ':' to differentiate from other type names in WebNFC APIs, // Prefix the raw local type with ':' to differentiate from other type names in WebNFC APIs,
// e.g. |localType| being "text" will become ":text" to differentiate from the standardized // e.g. |localType| being "text" will become ":text" to differentiate from the standardized
...@@ -474,6 +487,75 @@ public final class NdefMessageUtils { ...@@ -474,6 +487,75 @@ public final class NdefMessageUtils {
id == null ? null : ApiCompatibilityUtils.getBytesUtf8(id), payload); id == null ? null : ApiCompatibilityUtils.getBytesUtf8(id), payload);
} }
/**
* Creates a TNF_WELL_KNOWN + RTD_SMART_POSTER android.nfc.NdefRecord.
*/
public static android.nfc.NdefRecord createPlatformSmartPosterRecord(
String id, NdefMessage payloadMessage) throws InvalidNdefMessageException {
if (payloadMessage == null) {
throw new InvalidNdefMessageException();
}
List<android.nfc.NdefRecord> records = new ArrayList<android.nfc.NdefRecord>();
boolean hasUrlRecord = false;
boolean hasSizeRecord = false;
boolean hasTypeRecord = false;
boolean hasActionRecord = false;
for (int i = 0; i < payloadMessage.data.length; ++i) {
NdefRecord record = payloadMessage.data[i];
if (record.recordType.equals("url")) {
// The single mandatory url record.
if (hasUrlRecord) {
throw new InvalidNdefMessageException();
}
hasUrlRecord = true;
} else if (record.recordType.equals(":s")) {
// Zero or one size record.
// Size record must contain a 4-byte 32 bit unsigned integer.
if (hasSizeRecord || record.data.length != 4) {
throw new InvalidNdefMessageException();
}
hasSizeRecord = true;
} else if (record.recordType.equals(":t")) {
// Zero or one type record.
if (hasTypeRecord) {
throw new InvalidNdefMessageException();
}
hasTypeRecord = true;
} else if (record.recordType.equals(":act")) {
// Zero or one action record.
// Action record must contain only a single byte.
if (hasActionRecord || record.data.length != 1) {
throw new InvalidNdefMessageException();
}
hasActionRecord = true;
} else {
// No restriction on other record types.
}
try {
records.add(toNdefRecord(payloadMessage.data[i]));
} catch (UnsupportedEncodingException | InvalidNdefMessageException
| IllegalArgumentException e) {
throw new InvalidNdefMessageException();
}
}
// The single url record is mandatory.
if (!hasUrlRecord) {
throw new InvalidNdefMessageException();
}
android.nfc.NdefRecord[] ndefRecords = new android.nfc.NdefRecord[records.size()];
records.toArray(ndefRecords);
android.nfc.NdefMessage ndefMessage = new android.nfc.NdefMessage(ndefRecords);
return new android.nfc.NdefRecord(android.nfc.NdefRecord.TNF_WELL_KNOWN,
android.nfc.NdefRecord.RTD_SMART_POSTER,
id == null ? null : ApiCompatibilityUtils.getBytesUtf8(id),
ndefMessage.toByteArray());
}
/** /**
* Creates a TNF_WELL_KNOWN + |recordType| android.nfc.NdefRecord. * Creates a TNF_WELL_KNOWN + |recordType| android.nfc.NdefRecord.
*/ */
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_ndef_message_init.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_ndef_message_init.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/nfc/ndef_record.h" #include "third_party/blink/renderer/modules/nfc/ndef_record.h"
#include "third_party/blink/renderer/modules/nfc/ndef_record_init.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink { namespace blink {
...@@ -99,6 +100,88 @@ NDEFMessage* NDEFMessage::Create(const ExecutionContext* execution_context, ...@@ -99,6 +100,88 @@ NDEFMessage* NDEFMessage::Create(const ExecutionContext* execution_context,
return nullptr; return nullptr;
} }
// static
NDEFMessage* NDEFMessage::CreateAsPayloadOfSmartPoster(
const ExecutionContext* execution_context,
const NDEFMessageInit* init,
ExceptionState& exception_state) {
// NDEFMessageInit#records is a required field.
DCHECK(init->hasRecords());
NDEFMessage* payload_message = MakeGarbageCollected<NDEFMessage>();
bool has_url_record = false;
bool has_size_record = false;
bool has_type_record = false;
bool has_action_record = false;
for (const NDEFRecordInit* record_init : init->records()) {
const String& record_type = record_init->recordType();
if (record_type == "url") {
// The single mandatory url record.
if (has_url_record) {
exception_state.ThrowTypeError(
"'smart-poster' NDEFRecord contains more than one url record.");
return nullptr;
}
has_url_record = true;
} else if (record_type == ":s") {
// Zero or one size record.
if (has_size_record) {
exception_state.ThrowTypeError(
"'smart-poster' NDEFRecord contains more than one size record.");
return nullptr;
}
has_size_record = true;
} else if (record_type == ":t") {
// Zero or one type record.
if (has_type_record) {
exception_state.ThrowTypeError(
"'smart-poster' NDEFRecord contains more than one type record.");
return nullptr;
}
has_type_record = true;
} else if (record_type == ":act") {
// Zero or one action record.
if (has_action_record) {
exception_state.ThrowTypeError(
"'smart-poster' NDEFRecord contains more than one action record.");
return nullptr;
}
has_action_record = true;
} else {
// No restriction on other record types.
}
NDEFRecord* record = NDEFRecord::Create(
execution_context, record_init, exception_state, /*is_embedded=*/true);
if (exception_state.HadException())
return nullptr;
DCHECK(record);
if (record->recordType() == ":s" && record->payloadData().size() != 4) {
exception_state.ThrowTypeError(
"Size record of smart-poster must contain a 4-byte 32 bit unsigned "
"integer.");
return nullptr;
}
if (record->recordType() == ":act" && record->payloadData().size() != 1) {
exception_state.ThrowTypeError(
"Action record of smart-poster must contain only a single byte.");
return nullptr;
}
payload_message->records_.push_back(record);
}
if (!has_url_record) {
exception_state.ThrowTypeError(
"'smart-poster' NDEFRecord is missing the single mandatory url "
"record.");
return nullptr;
}
return payload_message;
}
NDEFMessage::NDEFMessage() = default; NDEFMessage::NDEFMessage() = default;
NDEFMessage::NDEFMessage(const device::mojom::blink::NDEFMessage& message) { NDEFMessage::NDEFMessage(const device::mojom::blink::NDEFMessage& message) {
......
...@@ -33,6 +33,9 @@ class MODULES_EXPORT NDEFMessage final : public ScriptWrappable { ...@@ -33,6 +33,9 @@ class MODULES_EXPORT NDEFMessage final : public ScriptWrappable {
static NDEFMessage* Create(const ExecutionContext*, static NDEFMessage* Create(const ExecutionContext*,
const NDEFMessageSource&, const NDEFMessageSource&,
ExceptionState&); ExceptionState&);
static NDEFMessage* CreateAsPayloadOfSmartPoster(const ExecutionContext*,
const NDEFMessageInit*,
ExceptionState&);
NDEFMessage(); NDEFMessage();
explicit NDEFMessage(const device::mojom::blink::NDEFMessage&); explicit NDEFMessage(const device::mojom::blink::NDEFMessage&);
......
...@@ -270,6 +270,29 @@ static NDEFRecord* CreateUnknownRecord(const String& id, ...@@ -270,6 +270,29 @@ static NDEFRecord* CreateUnknownRecord(const String& id,
id, bytes); id, bytes);
} }
static NDEFRecord* CreateSmartPosterRecord(
const ExecutionContext* execution_context,
const String& id,
const NDEFRecordDataSource& data,
ExceptionState& exception_state) {
// https://w3c.github.io/web-nfc/#dfn-map-smart-poster-to-ndef
if (!data.IsNDEFMessageInit()) {
exception_state.ThrowTypeError(
"The data for 'smart-poster' NDEFRecord must be an NDEFMessageInit.");
return nullptr;
}
NDEFMessage* payload_message = NDEFMessage::CreateAsPayloadOfSmartPoster(
execution_context, data.GetAsNDEFMessageInit(), exception_state);
if (exception_state.HadException())
return nullptr;
DCHECK(payload_message);
return MakeGarbageCollected<NDEFRecord>(
device::mojom::blink::NDEFRecordTypeCategory::kStandardized,
"smart-poster", id, payload_message);
}
static NDEFRecord* CreateExternalRecord( static NDEFRecord* CreateExternalRecord(
const ExecutionContext* execution_context, const ExecutionContext* execution_context,
const String& record_type, const String& record_type,
...@@ -379,9 +402,8 @@ NDEFRecord* NDEFRecord::Create(const ExecutionContext* execution_context, ...@@ -379,9 +402,8 @@ NDEFRecord* NDEFRecord::Create(const ExecutionContext* execution_context,
} else if (record_type == "unknown") { } else if (record_type == "unknown") {
return CreateUnknownRecord(init->id(), init->data(), exception_state); return CreateUnknownRecord(init->id(), init->data(), exception_state);
} else if (record_type == "smart-poster") { } else if (record_type == "smart-poster") {
// TODO(https://crbug.com/520391): Support creating smart-poster records. return CreateSmartPosterRecord(execution_context, init->id(), init->data(),
exception_state.ThrowTypeError("smart-poster type is not supported yet"); exception_state);
return nullptr;
} else if (IsValidExternalType(record_type)) { } else if (IsValidExternalType(record_type)) {
return CreateExternalRecord(execution_context, record_type, init->id(), return CreateExternalRecord(execution_context, record_type, init->id(),
init->data(), exception_state); init->data(), exception_state);
......
This is a testharness.js-based test.
PASS NDEFRecord constructor without init dict
PASS NDEFRecord constructor with null init dict
PASS NDEFRecord constructor without NDEFRecordInit#recordType field
PASS NDEFRecord constructor with empty record type and id
PASS NDEFRecord constructor should only accept mediaType for mime record type
PASS NDEFRecord constructor with custom record ids
PASS NDEFRecord constructor with empty record type
PASS NDEFRecord constructor with text record type and string data
PASS NDEFRecord constructor with text record type and arrayBuffer data
PASS NDEFRecord constructor with text record type and arrayBufferView data
PASS NDEFRecord constructor with text record type, encoding, and lang
PASS NDEFRecord constructor with text record type and custom document language
PASS NDEFRecord constructor with url record type
PASS NDEFRecord constructor with absolute-url record type
PASS NDEFRecord constructor with mime record type and stream data
PASS NDEFRecord constructor with mime record type and json data
PASS NDEFRecord constructor with unknown record type
PASS NDEFRecord constructor with external record type
PASS NDEFRecord constructor with local record type
FAIL NDEFRecord constructor with smart-poster record type Failed to construct 'NDEFRecord': smart-poster type is not supported yet
FAIL NDEFRecord constructor with smart-poster record type that contains only a mandatory uri record Failed to construct 'NDEFRecord': smart-poster type is not supported yet
PASS NDEFRecord constructor with record type string being treated as case sensitive
PASS NDEFRecord constructor with invalid external record type
PASS NDEFRecord constructor for smart-poster record with invalid embedded records.
PASS NDEFRecord constructor with various local record types
Harness: the test ran to completion.
...@@ -406,10 +406,10 @@ ...@@ -406,10 +406,10 @@
new Uint8Array(buffer).set([1, 2, 3, 4]); new Uint8Array(buffer).set([1, 2, 3, 4]);
const encoder = new TextEncoder(); const encoder = new TextEncoder();
const uri_record = createUrlRecord(test_url_data); const uri_record = createUrlRecord(test_url_data);
const title_record = createTextRecord(test_text_data); const title_record = createTextRecord(test_text_data, 'utf-8', 'en');
const type_record = createRecord(":t", encoder.encode("image/gif")); const type_record = createRecord(':t', encoder.encode("image/gif"));
const size_record = createRecord(":s", new Uint32Array([4096])); const size_record = createRecord(':s', new Uint32Array([4096]));
const action_record = createRecord(":act", new Uint8Array([0])); const action_record = createRecord(':act', new Uint8Array([3]));
const icon_record = createRecord("mime", buffer, test_record_id, 'image/gif'); const icon_record = createRecord("mime", buffer, test_record_id, 'image/gif');
const payload_message = createMessage([ const payload_message = createMessage([
uri_record, title_record, type_record, size_record, action_record, icon_record]); uri_record, title_record, type_record, size_record, action_record, icon_record]);
...@@ -438,6 +438,7 @@ ...@@ -438,6 +438,7 @@
assert_equals(record.encoding, 'utf-8', 'title record\'s encoding'); assert_equals(record.encoding, 'utf-8', 'title record\'s encoding');
assert_equals(record.lang, 'en', 'title record\'s lang'); assert_equals(record.lang, 'en', 'title record\'s lang');
assert_equals(decoder.decode(record.data), test_text_data, 'title record\'s data'); assert_equals(decoder.decode(record.data), test_text_data, 'title record\'s data');
break;
case ':t': case ':t':
assert_equals(record.mediaType, null, 'type record\'s mediaType'); assert_equals(record.mediaType, null, 'type record\'s mediaType');
assert_equals(record.id, null, 'type record\'s id'); assert_equals(record.id, null, 'type record\'s id');
...@@ -447,16 +448,16 @@ ...@@ -447,16 +448,16 @@
assert_equals(record.mediaType, null, 'size record\'s mediaType'); assert_equals(record.mediaType, null, 'size record\'s mediaType');
assert_equals(record.id, null, 'size record\'s id'); assert_equals(record.id, null, 'size record\'s id');
assert_equals(record.data.byteLength, 4, 'byteLength of size record\'s data'); assert_equals(record.data.byteLength, 4, 'byteLength of size record\'s data');
assert_equals(record.data.getUint32(0), 4096, 'value of size record\'s data'); assert_equals(new Uint32Array(record.data.buffer)[0], 4096, 'value of size record\'s data');
break; break;
case ':act': case ':act':
assert_equals(record.mediaType, null, 'action record\'s mediaType'); assert_equals(record.mediaType, null, 'action record\'s mediaType');
assert_equals(record.id, null, 'action record\'s id'); assert_equals(record.id, null, 'action record\'s id');
assert_equals(record.data.byteLength, 1, 'byteLength of action record\'s data'); assert_equals(record.data.byteLength, 1, 'byteLength of action record\'s data');
assert_equals(record.data.getUint8(0), 0, 'value of action record\'s data'); assert_equals(new Uint8Array(record.data.buffer)[0], 3, 'value of action record\'s data');
break; break;
case 'mime': case 'mime':
assert_equals(record.mediaType, image/gif, 'icon record\'s mediaType'); assert_equals(record.mediaType, 'image/gif', 'icon record\'s mediaType');
assert_equals(record.id, test_record_id, 'icon record\'s id'); assert_equals(record.id, test_record_id, 'icon record\'s id');
assert_array_equals(new Uint8Array(record.data.buffer), [1, 2, 3, 4], assert_array_equals(new Uint8Array(record.data.buffer), [1, 2, 3, 4],
'icon record\'s mediaType'); 'icon record\'s mediaType');
...@@ -473,20 +474,20 @@ ...@@ -473,20 +474,20 @@
test(() => { test(() => {
const uri_record = createUrlRecord(test_url_data); const uri_record = createUrlRecord(test_url_data);
const smart_poster_record = createRecord( const smart_poster_record = createRecord(
'smart-poster', createMessage([uri_record]), "dummy_record_id"); 'smart-poster', createMessage([uri_record]), 'dummy_record_id');
const record = new NDEFRecord(smart_poster_record); const record = new NDEFRecord(smart_poster_record);
assert_equals(record.recordType, 'smart-poster', 'recordType'); assert_equals(record.recordType, 'smart-poster', 'recordType');
assert_equals(record.mediaType, null, 'mediaType'); assert_equals(record.mediaType, null, 'mediaType');
assert_equals(record.id, 'dummy_record_id', 'id'); assert_equals(record.id, 'dummy_record_id', 'id');
const embedded_record = record.toRecords(); const embedded_records = record.toRecords();
// smart-poster record only contains a uri record. // smart-poster record only contains a uri record.
assert_equals(embedded_record.length, 1, 'length'); assert_equals(embedded_records.length, 1, 'length');
const decoder = new TextDecoder(); const decoder = new TextDecoder();
assert_equals(embedded_record.recordType, 'url', 'uri record\'s recordType'); assert_equals(embedded_records[0].recordType, 'url', 'uri record\'s recordType');
assert_equals(embedded_record.mediaType, null, 'uri record\'s mediaType'); assert_equals(embedded_records[0].mediaType, null, 'uri record\'s mediaType');
assert_equals(embedded_record.id, test_record_id, 'uri record\'s id'); assert_equals(embedded_records[0].id, test_record_id, 'uri record\'s id');
assert_equals(decoder.decode(embedded_record.data), test_url_data, 'uri record\'s data'); assert_equals(decoder.decode(embedded_records[0].data), test_url_data, 'uri record\'s data');
}, 'NDEFRecord constructor with smart-poster record type that contains only a mandatory uri record'); }, 'NDEFRecord constructor with smart-poster record type that contains only a mandatory uri record');
test(() => { test(() => {
...@@ -532,61 +533,41 @@ ...@@ -532,61 +533,41 @@
test(() => { test(() => {
const encoder = new TextEncoder(); const encoder = new TextEncoder();
const uri_record = createUrlRecord(test_url_data); const uri_record = createUrlRecord(test_url_data);
const title_record = createTextRecord(test_text_data); const title_record = createTextRecord(test_text_data, 'utf-8', 'en');
const type_record = createRecord(":t", encoder.encode("image/gif")); const type_record = createRecord(':t', encoder.encode("image/gif"));
const size_record = createRecord(":s", new Uint32Array([4096])); const size_record = createRecord(':s', new Uint32Array([4096]));
const action_record = createRecord(":act", new Uint8Array([0])); const action_record = createRecord(':act', new Uint8Array([0]));
const icon_record = createRecord( const icon_record = createRecord(
"mime", test_buffer_data, test_record_id, 'image/gif'); "mime", test_buffer_data, test_record_id, 'image/gif');
const invalid_datas = [ const invalid_data_list = [
// NDEFRecord.data for smart-poster record must be a NDEFMessageInit. {data: 'A string is not a NDEFMessageInit', message: 'A string is not allowed.'},
"A string is not a NDEFMessageInit", {data: test_buffer_data, message: 'An ArrayBuffer is not allowed.'},
test_buffer_data, {data: createMessage([title_record, type_record, size_record, action_record, icon_record]),
// NDEFRecord.data for smart-poster record must contain a URI record. message: 'Must contain a URI record.'},
createMessage([title_record, type_record, size_record, {data: createMessage([uri_record, title_record, type_record, size_record,
action_record, icon_record]),
// NDEFRecord.data for smart-poster record must not contain more than
// one uri record, type record, size record or action record.
createMessage([uri_record, title_record, type_record, size_record,
action_record, icon_record, uri_record]), action_record, icon_record, uri_record]),
createMessage([uri_record, title_record, type_record, size_record, message: 'Must not contain more than one uri record.'},
{data: createMessage([uri_record, title_record, type_record, size_record,
action_record, icon_record, type_record]), action_record, icon_record, type_record]),
createMessage([uri_record, title_record, type_record, size_record, message: 'Must not contain more than one type record.'},
{data: createMessage([uri_record, title_record, type_record, size_record,
action_record, icon_record, size_record]), action_record, icon_record, size_record]),
createMessage([uri_record, title_record, type_record, size_record, message: 'Must not contain more than one size record.'},
{data: createMessage([uri_record, title_record, type_record, size_record,
action_record, icon_record, action_record]), action_record, icon_record, action_record]),
// NDEFRecord.data for smart-poster record contains a size record must message: 'Must not contain more than one action record.'},
// have a data of type 4-byte 32 bit unsigned integer. {data: createMessage([uri_record, title_record, type_record, action_record,
createMessage([uri_record, title_record, type_record, action_record,
icon_record, createRecord(":s", new Uint8Array([1]))]), icon_record, createRecord(":s", new Uint8Array([1]))]),
// NDEFRecord.data for smart-poster record contains an action record must message: 'Size record must have payload as 4-byte 32 bit unsigned integer.'},
// have a data of type 1-byte 8 bit unsigned integer. {data: createMessage([uri_record, title_record, type_record, size_record,
createMessage([uri_record, title_record, type_record, size_record,
icon_record, createRecord(":act", new Uint32Array([0]))]), icon_record, createRecord(":act", new Uint32Array([0]))]),
// NDEFRecord.data for smart-poster record contains an icon record must message: 'Action record must have payload as 1-byte 8 bit unsigned integer.'}
// have a data starts with 'image' or 'video'.
createMessage([uri_record, title_record, type_record, size_record,
action_record, createMimeRecord(test_buffer_data)]),
// NDEFRecord.data for smart-poster record must not contain empty record.
createMessage([uri_record, title_record, type_record, size_record,
action_record, icon_record, createRecord('empty')]),
// NDEFRecord.data for smart-poster record must not contain absolute-url record.
createMessage([uri_record, title_record, type_record, size_record,
action_record, icon_record, createUrlRecord(test_url_data, true)]),
// NDEFRecord.data for smart-poster record must not contain external record.
createMessage([uri_record, title_record, type_record, size_record,
action_record, icon_record, createRecord('example.com:foo', test_buffer_data)]),
// NDEFRecord.data for smart-poster record must not contain unknown record.
createMessage([uri_record, title_record, type_record, size_record,
action_record, icon_record, createUnknownRecord(test_buffer_data)]),
// NDEFRecord.data for smart-poster record must contain only well-known local type.
createMessage([uri_record, title_record, type_record, size_record,
action_record, icon_record, createRecord(':notWellknownLocalType', test_buffer_data)])
]; ];
invalid_datas.forEach(data => { invalid_data_list.forEach(entry => {
assert_throws_js(TypeError, () => new NDEFRecord(createRecord('smart-poster', data))); assert_throws_js(TypeError, () => new NDEFRecord(createRecord('smart-poster', entry.data)),
entry.message);
}); });
}, "NDEFRecord constructor for smart-poster record with invalid embedded records."); }, "NDEFRecord constructor for smart-poster record with invalid embedded records.");
......
This is a testharness.js-based test.
PASS Test that promise is rejected with TypeError if NDEFMessageSource is invalid.
PASS Test that promise is rejected with SyntaxError if NDEFMessageSource contains invalid records.
PASS NDEFWriter.write should fail if user permission is not granted.
PASS NDEFWriter.write should fail if no implementation for NFC Mojo interface is available.
PASS NDEFWriter.write should fail if abort write request before write happends.
PASS NDEFWriter.write should fail if signal's aborted flag is set.
PASS NDEFWriter.write should fail if signal is not an AbortSignal.
PASS Synchronously signaled abort.
PASS NDEFWriter.write should fail when NFC HW is disabled.
PASS NDEFWriter.write should fail when NFC HW is not supported.
PASS Test that WebNFC API is not accessible from iframe context.
PASS NDEFWriter.write should succeed when NFC HW is enabled
PASS NDEFWriter.write NDEFMessage containing text, mime, unknown, url, absolute-url and external records with default NDEFWriteOptions.
PASS NDEFWriter.write NDEFMessage containing embedded records.
FAIL NDEFWriter.write NDEFMessage containing smart-poster record. promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'write' on 'NDEFWriter': smart-poster type is not supported yet"
PASS Test that NDEFWriter.write succeeds when message is DOMString.
PASS Test that NDEFWriter.write succeeds when message is ArrayBuffer.
PASS Test that NDEFWriter.write succeeds when message is ArrayBufferView.
PASS NDEFWriter.write with 'empty' record should succeed.
PASS Check that default NDEFWriteOptions values are correctly set.
PASS Check that provided NDEFWriteOptions values are correctly converted.
PASS NDEFWriter.write should read data when ignoreRead is false.
PASS NDEFWriter.write should ignore reading data when ignoreRead is true.
PASS NDEFWriter.write should replace all previously configured write operations.
PASS Test that mediaType should be set to 'application/octet-stream' if NDEFRecordInit.record's recordType is 'mime' and NDEFRecordInit.record's mediaType is undefined.
PASS NDEFWriter.write should fail when the NFC device coming up does not expose NDEF technology.
PASS NDEFWriter.write should succeed to write data to an unformatted NFC device when the NDEFWriteOptions.overwrite is false.
PASS NDEFWriter.write should succeed to overwrite the existing data when the NDEFWriteOptions.overwrite is true.
PASS NDEFWriter.write should fail when there are NDEF records on the NFC device and NDEFWriteOptions.overwrite is false.
PASS NDEFWriter.write should fail with NetworkError when NFC data transfer fails.
Harness: the test ran to completion.
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