// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/modules/nfc/ndef_record.h"

#include "services/device/public/mojom/nfc.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/modules/v8/string_or_array_buffer_or_array_buffer_view_or_ndef_message_init.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_ndef_record_init.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_data_view.h"
#include "third_party/blink/renderer/modules/nfc/ndef_message.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"

namespace blink {

using NDEFRecordDataSource =
    StringOrArrayBufferOrArrayBufferViewOrNDEFMessageInit;

namespace {

WTF::Vector<uint8_t> GetUTF8DataFromString(const String& string) {
  StringUTF8Adaptor utf8_string(string);
  WTF::Vector<uint8_t> data;
  data.Append(utf8_string.data(), utf8_string.size());
  return data;
}

bool IsBufferSource(const NDEFRecordDataSource& data) {
  return data.IsArrayBuffer() || data.IsArrayBufferView();
}

bool GetBytesOfBufferSource(const NDEFRecordDataSource& buffer_source,
                            WTF::Vector<uint8_t>* target,
                            ExceptionState& exception_state) {
  DCHECK(IsBufferSource(buffer_source));
  uint8_t* data;
  size_t data_length;
  if (buffer_source.IsArrayBuffer()) {
    DOMArrayBuffer* array_buffer = buffer_source.GetAsArrayBuffer();
    data = reinterpret_cast<uint8_t*>(array_buffer->Data());
    data_length = array_buffer->ByteLength();
  } else if (buffer_source.IsArrayBufferView()) {
    const DOMArrayBufferView* array_buffer_view =
        buffer_source.GetAsArrayBufferView().Get();
    data = reinterpret_cast<uint8_t*>(array_buffer_view->BaseAddress());
    data_length = array_buffer_view->byteLength();
  } else {
    NOTREACHED();
    return false;
  }
  wtf_size_t checked_length;
  if (!base::CheckedNumeric<wtf_size_t>(data_length)
           .AssignIfValid(&checked_length)) {
    exception_state.ThrowRangeError(
        "The provided buffer source exceeds the maximum supported length");
    return false;
  }
  target->Append(data, checked_length);
  return true;
}

// https://w3c.github.io/web-nfc/#dfn-validate-external-type
// Validates |input| as an external type.
bool IsValidExternalType(const String& input) {
  static const String kOtherCharsForCustomType(":!()+,-=@;$_*'.");

  // Ensure |input| is an ASCII string.
  if (!input.ContainsOnlyASCIIOrEmpty())
    return false;

  // As all characters in |input| is ASCII, limiting its length within 255 just
  // limits the length of its utf-8 encoded bytes we finally write into the
  // record payload.
  if (input.IsEmpty() || input.length() > 255)
    return false;

  // Finds the first occurrence of ':'.
  wtf_size_t colon_index = input.find(':');
  if (colon_index == kNotFound)
    return false;

  // Validates the domain (the part before ':').
  String domain = input.Left(colon_index);
  if (domain.IsEmpty())
    return false;
  // TODO(https://crbug.com/520391): Validate |domain|.

  // Validates the type (the part after ':').
  String type = input.Substring(colon_index + 1);
  if (type.IsEmpty())
    return false;
  for (wtf_size_t i = 0; i < type.length(); i++) {
    if (!IsASCIIAlphanumeric(type[i]) &&
        !kOtherCharsForCustomType.Contains(type[i])) {
      return false;
    }
  }

  return true;
}

// https://w3c.github.io/web-nfc/#dfn-validate-local-type
// Validates |input| as an local type.
bool IsValidLocalType(const String& input) {
  // Ensure |input| is an ASCII string.
  if (!input.ContainsOnlyASCIIOrEmpty())
    return false;

  // The prefix ':' will be omitted when we actually write the record type into
  // the nfc tag. We're taking it into consideration for validating the length
  // here.
  if (input.length() < 2 || input.length() > 256)
    return false;
  if (input[0] != ':')
    return false;
  if (!IsASCIILower(input[1]) && !IsASCIIDigit(input[1]))
    return false;

  // TODO(https://crbug.com/520391): Validate |input| is not equal to the record
  // type of any NDEF record defined in its containing NDEF message.

  return true;
}

String getDocumentLanguage(const ExecutionContext* execution_context) {
  String document_language;
  if (execution_context) {
    Element* document_element =
        To<LocalDOMWindow>(execution_context)->document()->documentElement();
    if (document_element) {
      document_language = document_element->getAttribute(html_names::kLangAttr);
    }
    if (document_language.IsEmpty()) {
      document_language = "en";
    }
  }
  return document_language;
}

static NDEFRecord* CreateTextRecord(const ExecutionContext* execution_context,
                                    const String& id,
                                    const NDEFRecordInit& record,
                                    ExceptionState& exception_state) {
  // https://w3c.github.io/web-nfc/#mapping-string-to-ndef
  if (!record.hasData() ||
      !(record.data().IsString() || IsBufferSource(record.data()))) {
    exception_state.ThrowTypeError(
        "The data for 'text' NDEFRecords must be a String or a BufferSource.");
    return nullptr;
  }

  // Set language to lang if it exists, or the document element's lang
  // attribute, or 'en'.
  String language;
  if (record.hasLang()) {
    language = record.lang();
  } else {
    language = getDocumentLanguage(execution_context);
  }

  // Bits 0 to 5 define the length of the language tag
  // https://w3c.github.io/web-nfc/#text-record
  if (language.length() > 63) {
    exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
                                      "Lang length cannot be stored in 6 bit.");
    return nullptr;
  }

  auto& data = record.data();
  // TODO(crbug.com/1070871): Use encodingOr("utf-8").
  String encoding_label = record.hasEncoding() ? record.encoding() : "utf-8";
  WTF::Vector<uint8_t> bytes;
  if (data.IsString()) {
    if (encoding_label != "utf-8") {
      exception_state.ThrowTypeError(
          "A DOMString data source is always encoded as \"utf-8\" so other "
          "encodings are not allowed.");
      return nullptr;
    }
    StringUTF8Adaptor utf8_string(data.GetAsString());
    bytes.Append(utf8_string.data(), utf8_string.size());
  } else {
    DCHECK(IsBufferSource(data));
    if (encoding_label != "utf-8" && encoding_label != "utf-16" &&
        encoding_label != "utf-16be" && encoding_label != "utf-16le") {
      exception_state.ThrowTypeError(
          "Encoding must be either \"utf-8\", \"utf-16\", \"utf-16be\", or "
          "\"utf-16le\".");
      return nullptr;
    }
    if (!GetBytesOfBufferSource(data, &bytes, exception_state)) {
      return nullptr;
    }
  }

  return MakeGarbageCollected<NDEFRecord>(id, encoding_label, language,
                                          std::move(bytes));
}

// Create a 'url' record or an 'absolute-url' record.
static NDEFRecord* CreateUrlRecord(const String& id,
                                   const NDEFRecordInit& record,
                                   ExceptionState& exception_state) {
  // https://w3c.github.io/web-nfc/#mapping-url-to-ndef
  if (!record.hasData() || !record.data().IsString()) {
    exception_state.ThrowTypeError(
        "The data for url NDEFRecord must be a String.");
    return nullptr;
  }

  // No need to check mediaType according to the spec.
  String url = record.data().GetAsString();
  if (!KURL(NullURL(), url).IsValid()) {
    exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
                                      "Cannot parse data for url record.");
    return nullptr;
  }

  return MakeGarbageCollected<NDEFRecord>(
      device::mojom::blink::NDEFRecordTypeCategory::kStandardized,
      record.recordType(), id, GetUTF8DataFromString(url));
}

static NDEFRecord* CreateMimeRecord(const String& id,
                                    const NDEFRecordInit& record,
                                    ExceptionState& exception_state) {
  // https://w3c.github.io/web-nfc/#mapping-binary-data-to-ndef
  if (!record.hasData() || !IsBufferSource(record.data())) {
    exception_state.ThrowTypeError(
        "The data for 'mime' NDEFRecord must be a BufferSource.");
    return nullptr;
  }

  // ExtractMIMETypeFromMediaType() ignores parameters of the MIME type.
  String mime_type;
  if (record.hasMediaType() && !record.mediaType().IsEmpty()) {
    mime_type = ExtractMIMETypeFromMediaType(AtomicString(record.mediaType()));
  } else {
    mime_type = "application/octet-stream";
  }

  WTF::Vector<uint8_t> bytes;
  if (!GetBytesOfBufferSource(record.data(), &bytes, exception_state)) {
    return nullptr;
  }

  return MakeGarbageCollected<NDEFRecord>(id, mime_type, bytes);
}

static NDEFRecord* CreateUnknownRecord(const String& id,
                                       const NDEFRecordInit& record,
                                       ExceptionState& exception_state) {
  if (!record.hasData() || !IsBufferSource(record.data())) {
    exception_state.ThrowTypeError(
        "The data for 'unknown' NDEFRecord must be a BufferSource.");
    return nullptr;
  }

  WTF::Vector<uint8_t> bytes;
  if (!GetBytesOfBufferSource(record.data(), &bytes, exception_state)) {
    return nullptr;
  }

  return MakeGarbageCollected<NDEFRecord>(
      device::mojom::blink::NDEFRecordTypeCategory::kStandardized, "unknown",
      id, bytes);
}

static NDEFRecord* CreateSmartPosterRecord(
    const ExecutionContext* execution_context,
    const String& id,
    const NDEFRecordInit& record,
    ExceptionState& exception_state) {
  // https://w3c.github.io/web-nfc/#dfn-map-smart-poster-to-ndef
  if (!record.hasData() || !record.data().IsNDEFMessageInit()) {
    exception_state.ThrowTypeError(
        "The data for 'smart-poster' NDEFRecord must be an NDEFMessageInit.");
    return nullptr;
  }

  NDEFMessage* payload_message = NDEFMessage::CreateAsPayloadOfSmartPoster(
      execution_context, record.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(
    const ExecutionContext* execution_context,
    const String& id,
    const NDEFRecordInit& record,
    ExceptionState& exception_state) {
  const String& record_type = record.recordType();

  // https://w3c.github.io/web-nfc/#dfn-map-external-data-to-ndef
  if (record.hasData() && IsBufferSource(record.data())) {
    WTF::Vector<uint8_t> bytes;
    if (!GetBytesOfBufferSource(record.data(), &bytes, exception_state)) {
      return nullptr;
    }
    return MakeGarbageCollected<NDEFRecord>(
        device::mojom::blink::NDEFRecordTypeCategory::kExternal, record_type,
        id, bytes);
  } else if (record.hasData() && record.data().IsNDEFMessageInit()) {
    NDEFMessage* payload_message = NDEFMessage::Create(
        execution_context, record.data().GetAsNDEFMessageInit(),
        exception_state, /*is_embedded=*/true);
    if (exception_state.HadException())
      return nullptr;
    DCHECK(payload_message);
    return MakeGarbageCollected<NDEFRecord>(
        device::mojom::blink::NDEFRecordTypeCategory::kExternal, record_type,
        id, payload_message);
  }

  exception_state.ThrowTypeError(
      "The data for external type NDEFRecord must be a BufferSource or an "
      "NDEFMessageInit.");
  return nullptr;
}

static NDEFRecord* CreateLocalRecord(const ExecutionContext* execution_context,
                                     const String& id,
                                     const NDEFRecordInit& record,
                                     ExceptionState& exception_state) {
  const String& record_type = record.recordType();

  // https://w3c.github.io/web-nfc/#dfn-map-local-type-to-ndef
  if (record.hasData() && IsBufferSource(record.data())) {
    WTF::Vector<uint8_t> bytes;
    if (!GetBytesOfBufferSource(record.data(), &bytes, exception_state)) {
      return nullptr;
    }
    return MakeGarbageCollected<NDEFRecord>(
        device::mojom::blink::NDEFRecordTypeCategory::kLocal, record_type, id,
        bytes);
  } else if (record.hasData() && record.data().IsNDEFMessageInit()) {
    NDEFMessage* payload_message = NDEFMessage::Create(
        execution_context, record.data().GetAsNDEFMessageInit(),
        exception_state, /*is_embedded=*/true);
    if (exception_state.HadException())
      return nullptr;
    DCHECK(payload_message);
    return MakeGarbageCollected<NDEFRecord>(
        device::mojom::blink::NDEFRecordTypeCategory::kLocal, record_type, id,
        payload_message);
  }

  exception_state.ThrowTypeError(
      "The data for local type NDEFRecord must be a BufferSource or an "
      "NDEFMessageInit.");
  return nullptr;
}

}  // namespace

// static
NDEFRecord* NDEFRecord::Create(const ExecutionContext* execution_context,
                               const NDEFRecordInit* record,
                               ExceptionState& exception_state,
                               bool is_embedded) {
  // https://w3c.github.io/web-nfc/#creating-ndef-record
  const String& record_type = record->recordType();

  // https://w3c.github.io/web-nfc/#dom-ndefrecordinit-mediatype
  if (record->hasMediaType() && record_type != "mime") {
    exception_state.ThrowTypeError(
        "NDEFRecordInit#mediaType is only applicable for 'mime' records.");
    return nullptr;
  }

  // https://w3c.github.io/web-nfc/#dfn-map-empty-record-to-ndef
  if (record->hasId() && record_type == "empty") {
    exception_state.ThrowTypeError(
        "NDEFRecordInit#id is not applicable for 'empty' records.");
    return nullptr;
  }

  // TODO(crbug.com/1070871): Use IdOr(String()).
  String id;
  if (record->hasId())
    id = record->id();

  if (record_type == "empty") {
    // https://w3c.github.io/web-nfc/#mapping-empty-record-to-ndef
    return MakeGarbageCollected<NDEFRecord>(
        device::mojom::blink::NDEFRecordTypeCategory::kStandardized,
        record_type, /*id=*/String(), WTF::Vector<uint8_t>());
  } else if (record_type == "text") {
    return CreateTextRecord(execution_context, id, *record, exception_state);
  } else if (record_type == "url" || record_type == "absolute-url") {
    return CreateUrlRecord(id, *record, exception_state);
  } else if (record_type == "mime") {
    return CreateMimeRecord(id, *record, exception_state);
  } else if (record_type == "unknown") {
    return CreateUnknownRecord(id, *record, exception_state);
  } else if (record_type == "smart-poster") {
    return CreateSmartPosterRecord(execution_context, id, *record,
                                   exception_state);
  } else if (IsValidExternalType(record_type)) {
    return CreateExternalRecord(execution_context, id, *record,
                                exception_state);
  } else if (IsValidLocalType(record_type)) {
    if (!is_embedded) {
      exception_state.ThrowTypeError(
          "Local type records are only supposed to be embedded in the payload "
          "of another record (smart-poster, external, or local).");
      return nullptr;
    }
    return CreateLocalRecord(execution_context, id, *record, exception_state);
  }

  exception_state.ThrowTypeError("Invalid NDEFRecord type.");
  return nullptr;
}

NDEFRecord::NDEFRecord(device::mojom::blink::NDEFRecordTypeCategory category,
                       const String& record_type,
                       const String& id,
                       WTF::Vector<uint8_t> data)
    : category_(category),
      record_type_(record_type),
      id_(id),
      payload_data_(std::move(data)) {
  DCHECK_EQ(
      category_ == device::mojom::blink::NDEFRecordTypeCategory::kExternal,
      IsValidExternalType(record_type_));
  DCHECK_EQ(category_ == device::mojom::blink::NDEFRecordTypeCategory::kLocal,
            IsValidLocalType(record_type_));
}

NDEFRecord::NDEFRecord(device::mojom::blink::NDEFRecordTypeCategory category,
                       const String& record_type,
                       const String& id,
                       NDEFMessage* payload_message)
    : category_(category),
      record_type_(record_type),
      id_(id),
      payload_message_(payload_message) {
  DCHECK(record_type_ == "smart-poster" ||
         category_ == device::mojom::blink::NDEFRecordTypeCategory::kExternal ||
         category_ == device::mojom::blink::NDEFRecordTypeCategory::kLocal);
  DCHECK_EQ(
      category_ == device::mojom::blink::NDEFRecordTypeCategory::kExternal,
      IsValidExternalType(record_type_));
  DCHECK_EQ(category_ == device::mojom::blink::NDEFRecordTypeCategory::kLocal,
            IsValidLocalType(record_type_));
}

NDEFRecord::NDEFRecord(const String& id,
                       const String& encoding,
                       const String& lang,
                       WTF::Vector<uint8_t> data)
    : category_(device::mojom::blink::NDEFRecordTypeCategory::kStandardized),
      record_type_("text"),
      id_(id),
      encoding_(encoding),
      lang_(lang),
      payload_data_(std::move(data)) {}

NDEFRecord::NDEFRecord(const ExecutionContext* execution_context,
                       const String& text)
    : category_(device::mojom::blink::NDEFRecordTypeCategory::kStandardized),
      record_type_("text"),
      encoding_("utf-8"),
      lang_(getDocumentLanguage(execution_context)),
      payload_data_(GetUTF8DataFromString(text)) {}

NDEFRecord::NDEFRecord(const String& id,
                       const String& media_type,
                       WTF::Vector<uint8_t> data)
    : category_(device::mojom::blink::NDEFRecordTypeCategory::kStandardized),
      record_type_("mime"),
      id_(id),
      media_type_(media_type),
      payload_data_(std::move(data)) {}

// Even if |record| is for a local type record, here we do not validate if it's
// in the context of a parent record but just expose to JS as is.
NDEFRecord::NDEFRecord(const device::mojom::blink::NDEFRecord& record)
    : category_(record.category),
      record_type_(record.record_type),
      id_(record.id),
      media_type_(record.media_type),
      encoding_(record.encoding),
      lang_(record.lang),
      payload_data_(record.data),
      payload_message_(
          record.payload_message
              ? MakeGarbageCollected<NDEFMessage>(*record.payload_message)
              : nullptr) {
  DCHECK_NE(record_type_ == "mime", media_type_.IsNull());
  DCHECK_EQ(
      category_ == device::mojom::blink::NDEFRecordTypeCategory::kExternal,
      IsValidExternalType(record_type_));
  DCHECK_EQ(category_ == device::mojom::blink::NDEFRecordTypeCategory::kLocal,
            IsValidLocalType(record_type_));
}

const String& NDEFRecord::mediaType() const {
  DCHECK_NE(record_type_ == "mime", media_type_.IsNull());
  return media_type_;
}

DOMDataView* NDEFRecord::data() const {
  // Step 4 in https://w3c.github.io/web-nfc/#dfn-parse-an-ndef-record
  if (record_type_ == "empty") {
    DCHECK(payload_data_.IsEmpty());
    return nullptr;
  }
  DOMArrayBuffer* dom_buffer =
      DOMArrayBuffer::Create(payload_data_.data(), payload_data_.size());
  return DOMDataView::Create(dom_buffer, 0, payload_data_.size());
}

// https://w3c.github.io/web-nfc/#dfn-convert-ndefrecord-data-bytes
base::Optional<HeapVector<Member<NDEFRecord>>> NDEFRecord::toRecords(
    ExceptionState& exception_state) const {
  if (record_type_ != "smart-poster" &&
      category_ != device::mojom::blink::NDEFRecordTypeCategory::kExternal &&
      category_ != device::mojom::blink::NDEFRecordTypeCategory::kLocal) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kNotSupportedError,
        "Only {smart-poster, external, local} type records could have a ndef "
        "message as payload.");
    return base::nullopt;
  }

  if (!payload_message_)
    return base::nullopt;

  return payload_message_->records();
}

void NDEFRecord::Trace(Visitor* visitor) const {
  visitor->Trace(payload_message_);
  ScriptWrappable::Trace(visitor);
}

}  // namespace blink
