Commit 79d34d57 authored by Donna Wu's avatar Donna Wu Committed by Commit Bot

[webnfc] Modify NDEFRecordData type according to the Spec.

Now that dictionary can be used as a member of a union type, so this
CL changed NDEFRecordData type from "any" to the Spec defined union.

Bug: 935912, 520391
Change-Id: Ib6ab361fa6a4087a2e14f4e9eb20b4a949155c7b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1628587Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Reviewed-by: default avatarRijubrata Bhaumik <rijubrata.bhaumik@intel.com>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Donna Wu <donna.wu@intel.com>
Cr-Commit-Position: refs/heads/master@{#666117}
parent 069edaba
...@@ -82,6 +82,8 @@ bindings_modules_generated_union_type_files = [ ...@@ -82,6 +82,8 @@ bindings_modules_generated_union_type_files = [
"$bindings_modules_v8_output_dir/string_or_canvas_gradient_or_canvas_pattern.h", "$bindings_modules_v8_output_dir/string_or_canvas_gradient_or_canvas_pattern.h",
"$bindings_modules_v8_output_dir/string_or_string_sequence_or_constrain_dom_string_parameters.cc", "$bindings_modules_v8_output_dir/string_or_string_sequence_or_constrain_dom_string_parameters.cc",
"$bindings_modules_v8_output_dir/string_or_string_sequence_or_constrain_dom_string_parameters.h", "$bindings_modules_v8_output_dir/string_or_string_sequence_or_constrain_dom_string_parameters.h",
"$bindings_modules_v8_output_dir/string_or_unrestricted_double_or_array_buffer_or_dictionary.cc",
"$bindings_modules_v8_output_dir/string_or_unrestricted_double_or_array_buffer_or_dictionary.h",
"$bindings_modules_v8_output_dir/string_or_unsigned_long.cc", "$bindings_modules_v8_output_dir/string_or_unsigned_long.cc",
"$bindings_modules_v8_output_dir/string_or_unsigned_long.h", "$bindings_modules_v8_output_dir/string_or_unsigned_long.h",
"$bindings_modules_v8_output_dir/unsigned_long_or_unsigned_long_sequence.cc", "$bindings_modules_v8_output_dir/unsigned_long_or_unsigned_long_sequence.cc",
......
...@@ -6,9 +6,7 @@ ...@@ -6,9 +6,7 @@
enum NDEFRecordType { "empty", "text", "url", "json", "opaque" }; enum NDEFRecordType { "empty", "text", "url", "json", "opaque" };
// TODO(riju): Fix http://crbug.com/935912 typedef (DOMString or unrestricted double or ArrayBuffer or Dictionary) NDEFRecordData;
// typedef (DOMString or unrestricted double or ArrayBuffer or Dictionary) NDEFRecordData;
typedef any NDEFRecordData;
dictionary NDEFRecord { dictionary NDEFRecord {
NDEFRecordType recordType; NDEFRecordType recordType;
......
...@@ -96,21 +96,21 @@ NFCWatchMode toNFCWatchMode(const String& watchMode) { ...@@ -96,21 +96,21 @@ NFCWatchMode toNFCWatchMode(const String& watchMode) {
// If NDEFRecord type is not provided, deduce NDEFRecord type from JS data type: // If NDEFRecord type is not provided, deduce NDEFRecord type from JS data type:
// String or Number => 'text' record // String or Number => 'text' record
// ArrayBuffer => 'opaque' record // ArrayBuffer => 'opaque' record
// JSON serializable Object => 'json' record // Dictionary, JSON serializable Object => 'json' record
NDEFRecordType deduceRecordTypeFromDataType(const blink::NDEFRecord* record) { NDEFRecordType deduceRecordTypeFromDataType(const blink::NDEFRecord* record) {
if (record->hasData()) { if (record->hasData()) {
v8::Local<v8::Value> value = record->data().V8Value(); const blink::NDEFRecordData& value = record->data();
if (value->IsString() || if (value.IsString() || (value.IsUnrestrictedDouble() &&
(value->IsNumber() && !std::isnan(value.As<v8::Number>()->Value()))) { !std::isnan(value.GetAsUnrestrictedDouble()))) {
return NDEFRecordType::TEXT; return NDEFRecordType::TEXT;
} }
if (value->IsObject() && !value->IsArrayBuffer()) { if (value.IsDictionary()) {
return NDEFRecordType::JSON; return NDEFRecordType::JSON;
} }
if (value->IsArrayBuffer()) { if (value.IsArrayBuffer()) {
return NDEFRecordType::OPAQUE_RECORD; return NDEFRecordType::OPAQUE_RECORD;
} }
} }
...@@ -176,31 +176,27 @@ struct TypeConverter<NDEFMessagePtr, String> { ...@@ -176,31 +176,27 @@ struct TypeConverter<NDEFMessagePtr, String> {
}; };
template <> template <>
struct TypeConverter<base::Optional<Vector<uint8_t>>, blink::ScriptValue> { struct TypeConverter<base::Optional<Vector<uint8_t>>, blink::NDEFRecordData> {
static base::Optional<Vector<uint8_t>> Convert( static base::Optional<Vector<uint8_t>> Convert(
const blink::ScriptValue& scriptValue) { const blink::NDEFRecordData& value) {
v8::Local<v8::Value> value = scriptValue.V8Value(); if (value.IsUnrestrictedDouble()) {
if (value->IsNumber()) {
return mojo::ConvertTo<Vector<uint8_t>>( return mojo::ConvertTo<Vector<uint8_t>>(
String::Number(value.As<v8::Number>()->Value())); String::Number(value.GetAsUnrestrictedDouble()));
} }
if (value->IsString()) { if (value.IsString()) {
blink::V8StringResource<> stringResource = value; return mojo::ConvertTo<Vector<uint8_t>>(value.GetAsString());
if (stringResource.Prepare()) {
return mojo::ConvertTo<Vector<uint8_t>>(String(stringResource));
}
} }
if (value->IsObject() && !value->IsArray() && !value->IsArrayBuffer()) { if (value.IsDictionary()) {
v8::Local<v8::String> jsonString; v8::Local<v8::String> jsonString;
v8::Isolate* isolate = scriptValue.GetIsolate(); blink::Dictionary dictionary = value.GetAsDictionary();
v8::Isolate* isolate = dictionary.GetIsolate();
v8::TryCatch try_catch(isolate); v8::TryCatch try_catch(isolate);
// https://w3c.github.io/web-nfc/#mapping-json-to-ndef // https://w3c.github.io/web-nfc/#mapping-json-to-ndef
// If serialization throws, reject promise with a "SyntaxError" exception. // If serialization throws, reject promise with a "SyntaxError" exception.
if (!v8::JSON::Stringify(scriptValue.GetContext(), value.As<v8::Object>()) if (!v8::JSON::Stringify(dictionary.V8Context(), dictionary.V8Value())
.ToLocal(&jsonString) || .ToLocal(&jsonString) ||
try_catch.HasCaught()) { try_catch.HasCaught()) {
return base::nullopt; return base::nullopt;
...@@ -211,9 +207,8 @@ struct TypeConverter<base::Optional<Vector<uint8_t>>, blink::ScriptValue> { ...@@ -211,9 +207,8 @@ struct TypeConverter<base::Optional<Vector<uint8_t>>, blink::ScriptValue> {
return mojo::ConvertTo<Vector<uint8_t>>(string); return mojo::ConvertTo<Vector<uint8_t>>(string);
} }
if (value->IsArrayBuffer()) { if (value.IsArrayBuffer()) {
return mojo::ConvertTo<Vector<uint8_t>>( return mojo::ConvertTo<Vector<uint8_t>>(value.GetAsArrayBuffer());
blink::V8ArrayBuffer::ToImpl(value.As<v8::Object>()));
} }
return base::nullopt; return base::nullopt;
...@@ -383,9 +378,10 @@ ScriptPromise RejectWithDOMException(ScriptState* script_state, ...@@ -383,9 +378,10 @@ ScriptPromise RejectWithDOMException(ScriptState* script_state,
ScriptPromise RejectIfInvalidTextRecord(ScriptState* script_state, ScriptPromise RejectIfInvalidTextRecord(ScriptState* script_state,
const NDEFRecord* record) { const NDEFRecord* record) {
v8::Local<v8::Value> value = record->data().V8Value(); const NDEFRecordData& value = record->data();
if (!value->IsString() &&
!(value->IsNumber() && !std::isnan(value.As<v8::Number>()->Value()))) { if (!value.IsString() && !(value.IsUnrestrictedDouble() &&
!std::isnan(value.GetAsUnrestrictedDouble()))) {
return RejectWithTypeError(script_state, return RejectWithTypeError(script_state,
"The data for 'text' NDEFRecords must be of " "The data for 'text' NDEFRecords must be of "
"String or UnrestrctedDouble type."); "String or UnrestrctedDouble type.");
...@@ -402,14 +398,12 @@ ScriptPromise RejectIfInvalidTextRecord(ScriptState* script_state, ...@@ -402,14 +398,12 @@ ScriptPromise RejectIfInvalidTextRecord(ScriptState* script_state,
ScriptPromise RejectIfInvalidURLRecord(ScriptState* script_state, ScriptPromise RejectIfInvalidURLRecord(ScriptState* script_state,
const NDEFRecord* record) { const NDEFRecord* record) {
if (!record->data().V8Value()->IsString()) { if (!record->data().IsString()) {
return RejectWithTypeError( return RejectWithTypeError(
script_state, "The data for 'url' NDEFRecord must be of String type."); script_state, "The data for 'url' NDEFRecord must be of String type.");
} }
blink::V8StringResource<> string_resource = record->data().V8Value(); if (!KURL(NullURL(), record->data().GetAsString()).IsValid()) {
if (!string_resource.Prepare() ||
!KURL(NullURL(), string_resource).IsValid()) {
return RejectWithDOMException(script_state, DOMExceptionCode::kSyntaxError, return RejectWithDOMException(script_state, DOMExceptionCode::kSyntaxError,
"Cannot parse data for 'url' record."); "Cannot parse data for 'url' record.");
} }
...@@ -419,8 +413,7 @@ ScriptPromise RejectIfInvalidURLRecord(ScriptState* script_state, ...@@ -419,8 +413,7 @@ ScriptPromise RejectIfInvalidURLRecord(ScriptState* script_state,
ScriptPromise RejectIfInvalidJSONRecord(ScriptState* script_state, ScriptPromise RejectIfInvalidJSONRecord(ScriptState* script_state,
const NDEFRecord* record) { const NDEFRecord* record) {
v8::Local<v8::Value> value = record->data().V8Value(); if (!record->data().IsDictionary()) {
if (!value->IsObject() || value->IsArrayBuffer()) {
return RejectWithTypeError( return RejectWithTypeError(
script_state, "The data for 'json' NDEFRecord must be of Object type."); script_state, "The data for 'json' NDEFRecord must be of Object type.");
} }
...@@ -440,7 +433,7 @@ ScriptPromise RejectIfInvalidJSONRecord(ScriptState* script_state, ...@@ -440,7 +433,7 @@ ScriptPromise RejectIfInvalidJSONRecord(ScriptState* script_state,
ScriptPromise RejectIfInvalidOpaqueRecord(ScriptState* script_state, ScriptPromise RejectIfInvalidOpaqueRecord(ScriptState* script_state,
const NDEFRecord* record) { const NDEFRecord* record) {
if (!record->data().V8Value()->IsArrayBuffer()) { if (!record->data().IsArrayBuffer()) {
return RejectWithTypeError( return RejectWithTypeError(
script_state, script_state,
"The data for 'opaque' NDEFRecord must be of ArrayBuffer type."); "The data for 'opaque' NDEFRecord must be of ArrayBuffer type.");
...@@ -557,8 +550,10 @@ String ToNDEFRecordType(const device::mojom::blink::NDEFRecordType& type) { ...@@ -557,8 +550,10 @@ String ToNDEFRecordType(const device::mojom::blink::NDEFRecordType& type) {
return String(); return String();
} }
v8::Local<v8::Value> ToV8(ScriptState* script_state, NDEFRecordData BuildRecordData(
const device::mojom::blink::NDEFRecordPtr& record) { ScriptState* script_state,
const device::mojom::blink::NDEFRecordPtr& record) {
NDEFRecordData result = NDEFRecordData();
switch (record->record_type) { switch (record->record_type) {
case device::mojom::blink::NDEFRecordType::TEXT: case device::mojom::blink::NDEFRecordType::TEXT:
case device::mojom::blink::NDEFRecordType::URL: case device::mojom::blink::NDEFRecordType::URL:
...@@ -570,41 +565,51 @@ v8::Local<v8::Value> ToV8(ScriptState* script_state, ...@@ -570,41 +565,51 @@ v8::Local<v8::Value> ToV8(ScriptState* script_state,
record->data.size()); record->data.size());
} }
v8::Isolate* isolate = script_state->GetIsolate(); // Convert back the stringified double.
v8::Local<v8::String> string = V8String(isolate, string_data); if (record->record_type == device::mojom::blink::NDEFRecordType::TEXT) {
bool can_convert = false;
double number = string_data.ToDouble(&can_convert);
if (can_convert) {
result.SetUnrestrictedDouble(number);
return result;
}
}
// Stringified JSON must be converted back to an Object. // Stringified JSON must be converted back to an Object.
if (record->record_type == device::mojom::blink::NDEFRecordType::JSON) { if (record->record_type == device::mojom::blink::NDEFRecordType::JSON) {
v8::Isolate* isolate = script_state->GetIsolate();
v8::Local<v8::String> string = V8String(isolate, string_data);
v8::Local<v8::Value> json_object; v8::Local<v8::Value> json_object;
v8::TryCatch try_catch(isolate); v8::TryCatch try_catch(isolate);
if (!v8::JSON::Parse(script_state->GetContext(), string) NonThrowableExceptionState exception_state;
.ToLocal(&json_object)) {
return v8::Null(isolate);
}
return json_object; if (v8::JSON::Parse(script_state->GetContext(), string)
.ToLocal(&json_object)) {
result.SetDictionary(
Dictionary(isolate, json_object, exception_state));
return result;
}
} }
return string; result.SetString(string_data);
return result;
} }
case device::mojom::blink::NDEFRecordType::OPAQUE_RECORD: { case device::mojom::blink::NDEFRecordType::OPAQUE_RECORD: {
if (!record->data.IsEmpty()) { if (!record->data.IsEmpty()) {
DOMArrayBuffer* buffer = DOMArrayBuffer::Create( result.SetArrayBuffer(DOMArrayBuffer::Create(
static_cast<void*>(&record->data.front()), record->data.size()); static_cast<void*>(&record->data.front()), record->data.size()));
return ToV8(buffer, script_state->GetContext()->Global(),
script_state->GetIsolate());
} }
return v8::Null(script_state->GetIsolate()); return result;
} }
case device::mojom::blink::NDEFRecordType::EMPTY: case device::mojom::blink::NDEFRecordType::EMPTY:
return v8::Null(script_state->GetIsolate()); return result;
} }
NOTREACHED(); NOTREACHED();
return v8::Local<v8::Value>(); return result;
} }
NDEFRecord* ToNDEFRecord(ScriptState* script_state, NDEFRecord* ToNDEFRecord(ScriptState* script_state,
...@@ -612,7 +617,7 @@ NDEFRecord* ToNDEFRecord(ScriptState* script_state, ...@@ -612,7 +617,7 @@ NDEFRecord* ToNDEFRecord(ScriptState* script_state,
NDEFRecord* nfc_record = NDEFRecord::Create(); NDEFRecord* nfc_record = NDEFRecord::Create();
nfc_record->setMediaType(record->media_type); nfc_record->setMediaType(record->media_type);
nfc_record->setRecordType(ToNDEFRecordType(record->record_type)); nfc_record->setRecordType(ToNDEFRecordType(record->record_type));
nfc_record->setData(ScriptValue(script_state, ToV8(script_state, record))); nfc_record->setData(BuildRecordData(script_state, record));
return nfc_record; return nfc_record;
} }
......
...@@ -19,6 +19,7 @@ namespace blink { ...@@ -19,6 +19,7 @@ namespace blink {
class NFCPushOptions; class NFCPushOptions;
using NDEFMessageSource = StringOrArrayBufferOrNDEFMessage; using NDEFMessageSource = StringOrArrayBufferOrNDEFMessage;
using NDEFRecordData = StringOrUnrestrictedDoubleOrArrayBufferOrDictionary;
class NFCWatchOptions; class NFCWatchOptions;
class ScriptPromiseResolver; class ScriptPromiseResolver;
......
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