// Copyright 2015 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/nfc.h"

#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_string_resource.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.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_array_buffer.h"
#include "third_party/blink/renderer/modules/nfc/nfc_error.h"
#include "third_party/blink/renderer/modules/nfc/nfc_message.h"
#include "third_party/blink/renderer/modules/nfc/nfc_push_options.h"
#include "third_party/blink/renderer/modules/nfc/nfc_watch_options.h"
#include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"

namespace {
const char kJsonMimePostfix[] = "+json";
const char kJsonMimePrefix[] = "application/";
const char kJsonMimeType[] = "application/json";
const char kOpaqueMimeType[] = "application/octet-stream";
const char kPlainTextMimeType[] = "text/plain";
const char kPlainTextMimePrefix[] = "text/";
const char kProtocolHttps[] = "https";
const char kCharSetUTF8[] = ";charset=UTF-8";
}  // anonymous namespace

// Mojo type converters
namespace mojo {

using device::mojom::blink::NFCMessage;
using device::mojom::blink::NFCMessagePtr;
using device::mojom::blink::NFCRecord;
using device::mojom::blink::NFCRecordPtr;
using device::mojom::blink::NFCRecordType;
using device::mojom::blink::NFCRecordTypeFilter;
using device::mojom::blink::NFCPushOptions;
using device::mojom::blink::NFCPushOptionsPtr;
using device::mojom::blink::NFCPushTarget;
using device::mojom::blink::NFCWatchMode;
using device::mojom::blink::NFCWatchOptions;
using device::mojom::blink::NFCWatchOptionsPtr;

NFCPushTarget toNFCPushTarget(const String& target) {
  if (target == "tag")
    return NFCPushTarget::TAG;

  if (target == "peer")
    return NFCPushTarget::PEER;

  return NFCPushTarget::ANY;
}

NFCRecordType toNFCRecordType(const String& recordType) {
  if (recordType == "empty")
    return NFCRecordType::EMPTY;

  if (recordType == "text")
    return NFCRecordType::TEXT;

  if (recordType == "url")
    return NFCRecordType::URL;

  if (recordType == "json")
    return NFCRecordType::JSON;

  if (recordType == "opaque")
    return NFCRecordType::OPAQUE_RECORD;

  NOTREACHED();
  return NFCRecordType::EMPTY;
}

NFCWatchMode toNFCWatchMode(const String& watchMode) {
  if (watchMode == "web-nfc-only")
    return NFCWatchMode::WEBNFC_ONLY;

  if (watchMode == "any")
    return NFCWatchMode::ANY;

  NOTREACHED();
  return NFCWatchMode::WEBNFC_ONLY;
}

// https://w3c.github.io/web-nfc/#creating-web-nfc-message Step 2.1
// If NFCRecord type is not provided, deduce NFCRecord type from JS data type:
// String or Number => 'text' record
// ArrayBuffer => 'opaque' record
// JSON serializable Object => 'json' record
NFCRecordType deduceRecordTypeFromDataType(const blink::NFCRecord* record) {
  if (record->hasData()) {
    v8::Local<v8::Value> value = record->data().V8Value();

    if (value->IsString() ||
        (value->IsNumber() && !std::isnan(value.As<v8::Number>()->Value()))) {
      return NFCRecordType::TEXT;
    }

    if (value->IsObject() && !value->IsArrayBuffer()) {
      return NFCRecordType::JSON;
    }

    if (value->IsArrayBuffer()) {
      return NFCRecordType::OPAQUE_RECORD;
    }
  }

  return NFCRecordType::EMPTY;
}

void setMediaType(NFCRecordPtr& recordPtr,
                  const String& recordMediaType,
                  const String& defaultMediaType) {
  recordPtr->media_type =
      recordMediaType.IsEmpty() ? defaultMediaType : recordMediaType;
}

template <>
struct TypeConverter<Vector<uint8_t>, String> {
  static Vector<uint8_t> Convert(const String& string) {
    CString utf8String = string.Utf8();
    Vector<uint8_t> array;
    array.Append(utf8String.data(), utf8String.length());
    return array;
  }
};

template <>
struct TypeConverter<Vector<uint8_t>, blink::DOMArrayBuffer*> {
  static Vector<uint8_t> Convert(blink::DOMArrayBuffer* buffer) {
    Vector<uint8_t> array;
    array.Append(static_cast<uint8_t*>(buffer->Data()), buffer->ByteLength());
    return array;
  }
};

template <>
struct TypeConverter<NFCRecordPtr, String> {
  static NFCRecordPtr Convert(const String& string) {
    NFCRecordPtr record = NFCRecord::New();
    record->record_type = NFCRecordType::TEXT;
    record->media_type = kPlainTextMimeType;
    record->media_type.append(kCharSetUTF8);
    record->data = mojo::ConvertTo<Vector<uint8_t>>(string);
    return record;
  }
};

template <>
struct TypeConverter<NFCRecordPtr, blink::DOMArrayBuffer*> {
  static NFCRecordPtr Convert(blink::DOMArrayBuffer* buffer) {
    NFCRecordPtr record = NFCRecord::New();
    record->record_type = NFCRecordType::OPAQUE_RECORD;
    record->media_type = kOpaqueMimeType;
    record->data = mojo::ConvertTo<Vector<uint8_t>>(buffer);
    return record;
  }
};

template <>
struct TypeConverter<NFCMessagePtr, String> {
  static NFCMessagePtr Convert(const String& string) {
    NFCMessagePtr message = NFCMessage::New();
    message->data.push_back(NFCRecord::From(string));
    return message;
  }
};

template <>
struct TypeConverter<base::Optional<Vector<uint8_t>>, blink::ScriptValue> {
  static base::Optional<Vector<uint8_t>> Convert(
      const blink::ScriptValue& scriptValue) {
    v8::Local<v8::Value> value = scriptValue.V8Value();

    if (value->IsNumber()) {
      return mojo::ConvertTo<Vector<uint8_t>>(
          String::Number(value.As<v8::Number>()->Value()));
    }

    if (value->IsString()) {
      blink::V8StringResource<> stringResource = value;
      if (stringResource.Prepare()) {
        return mojo::ConvertTo<Vector<uint8_t>>(String(stringResource));
      }
    }

    if (value->IsObject() && !value->IsArray() && !value->IsArrayBuffer()) {
      v8::Local<v8::String> jsonString;
      v8::Isolate* isolate = scriptValue.GetIsolate();
      v8::TryCatch try_catch(isolate);

      // https://w3c.github.io/web-nfc/#mapping-json-to-ndef
      // If serialization throws, reject promise with a "SyntaxError" exception.
      if (!v8::JSON::Stringify(scriptValue.GetContext(), value.As<v8::Object>())
               .ToLocal(&jsonString) ||
          try_catch.HasCaught()) {
        return base::nullopt;
      }

      String string =
          blink::ToBlinkString<String>(jsonString, blink::kDoNotExternalize);
      return mojo::ConvertTo<Vector<uint8_t>>(string);
    }

    if (value->IsArrayBuffer()) {
      return mojo::ConvertTo<Vector<uint8_t>>(
          blink::V8ArrayBuffer::ToImpl(value.As<v8::Object>()));
    }

    return base::nullopt;
  }
};

template <>
struct TypeConverter<NFCRecordPtr, blink::NFCRecord*> {
  static NFCRecordPtr Convert(const blink::NFCRecord* record) {
    NFCRecordPtr recordPtr = NFCRecord::New();

    if (record->hasRecordType())
      recordPtr->record_type = toNFCRecordType(record->recordType());
    else
      recordPtr->record_type = deduceRecordTypeFromDataType(record);

    // If record type is "empty", no need to set media type or data.
    // https://w3c.github.io/web-nfc/#creating-web-nfc-message
    if (recordPtr->record_type == NFCRecordType::EMPTY)
      return recordPtr;

    switch (recordPtr->record_type) {
      case NFCRecordType::TEXT:
      case NFCRecordType::URL:
        setMediaType(recordPtr, record->mediaType(), kPlainTextMimeType);
        recordPtr->media_type.append(kCharSetUTF8);
        break;
      case NFCRecordType::JSON:
        setMediaType(recordPtr, record->mediaType(), kJsonMimeType);
        break;
      case NFCRecordType::OPAQUE_RECORD:
        setMediaType(recordPtr, record->mediaType(), kOpaqueMimeType);
        break;
      default:
        NOTREACHED();
        break;
    }

    auto recordData =
        mojo::ConvertTo<base::Optional<Vector<uint8_t>>>(record->data());
    // If JS object cannot be converted to uint8_t array, return null,
    // interrupt NFCMessage conversion algorithm and reject promise with
    // SyntaxError exception.
    if (!recordData)
      return nullptr;

    recordPtr->data = recordData.value();
    return recordPtr;
  }
};

template <>
struct TypeConverter<NFCMessagePtr, blink::NFCMessage*> {
  static NFCMessagePtr Convert(const blink::NFCMessage* message) {
    NFCMessagePtr messagePtr = NFCMessage::New();
    messagePtr->url = message->url();
    messagePtr->data.resize(message->records().size());
    for (wtf_size_t i = 0; i < message->records().size(); ++i) {
      NFCRecordPtr record = NFCRecord::From(message->records()[i].Get());
      if (record.is_null())
        return nullptr;

      messagePtr->data[i] = std::move(record);
    }
    return messagePtr;
  }
};

template <>
struct TypeConverter<NFCMessagePtr, blink::DOMArrayBuffer*> {
  static NFCMessagePtr Convert(blink::DOMArrayBuffer* buffer) {
    NFCMessagePtr message = NFCMessage::New();
    message->data.push_back(NFCRecord::From(buffer));
    return message;
  }
};

template <>
struct TypeConverter<NFCMessagePtr, blink::NFCPushMessage> {
  static NFCMessagePtr Convert(const blink::NFCPushMessage& message) {
    if (message.IsString())
      return NFCMessage::From(message.GetAsString());

    if (message.IsNFCMessage())
      return NFCMessage::From(message.GetAsNFCMessage());

    if (message.IsArrayBuffer())
      return NFCMessage::From(message.GetAsArrayBuffer());

    NOTREACHED();
    return nullptr;
  }
};

template <>
struct TypeConverter<NFCPushOptionsPtr, const blink::NFCPushOptions*> {
  static NFCPushOptionsPtr Convert(const blink::NFCPushOptions* pushOptions) {
    // https://w3c.github.io/web-nfc/#the-nfcpushoptions-dictionary
    // Default values for NFCPushOptions dictionary are:
    // target = 'any', timeout = Infinity, ignoreRead = true
    NFCPushOptionsPtr pushOptionsPtr = NFCPushOptions::New();

    if (pushOptions->hasTarget())
      pushOptionsPtr->target = toNFCPushTarget(pushOptions->target());
    else
      pushOptionsPtr->target = NFCPushTarget::ANY;

    if (pushOptions->hasTimeout())
      pushOptionsPtr->timeout = pushOptions->timeout();
    else
      pushOptionsPtr->timeout = std::numeric_limits<double>::infinity();

    if (pushOptions->hasIgnoreRead())
      pushOptionsPtr->ignore_read = pushOptions->ignoreRead();
    else
      pushOptionsPtr->ignore_read = true;

    return pushOptionsPtr;
  }
};

template <>
struct TypeConverter<NFCWatchOptionsPtr, const blink::NFCWatchOptions*> {
  static NFCWatchOptionsPtr Convert(
      const blink::NFCWatchOptions* watchOptions) {
    // https://w3c.github.io/web-nfc/#the-nfcwatchoptions-dictionary
    // Default values for NFCWatchOptions dictionary are:
    // url = "", recordType = null, mediaType = "", mode = "web-nfc-only"
    NFCWatchOptionsPtr watchOptionsPtr = NFCWatchOptions::New();
    watchOptionsPtr->url = watchOptions->url();
    watchOptionsPtr->media_type = watchOptions->mediaType();

    if (watchOptions->hasMode())
      watchOptionsPtr->mode = toNFCWatchMode(watchOptions->mode());
    else
      watchOptionsPtr->mode = NFCWatchMode::WEBNFC_ONLY;

    if (watchOptions->hasRecordType()) {
      watchOptionsPtr->record_filter = NFCRecordTypeFilter::New();
      watchOptionsPtr->record_filter->record_type =
          toNFCRecordType(watchOptions->recordType());
    }

    return watchOptionsPtr;
  }
};

}  // namespace mojo

namespace blink {
namespace {

ScriptPromise RejectWithTypeError(ScriptState* script_state,
                                  const String& message) {
  return ScriptPromise::Reject(
      script_state,
      V8ThrowException::CreateTypeError(script_state->GetIsolate(), message));
}

ScriptPromise RejectWithDOMException(ScriptState* script_state,
                                     DOMExceptionCode exception_code,
                                     const String& message) {
  return ScriptPromise::RejectWithDOMException(
      script_state, DOMException::Create(exception_code, message));
}

ScriptPromise RejectIfInvalidTextRecord(ScriptState* script_state,
                                        const NFCRecord* record) {
  v8::Local<v8::Value> value = record->data().V8Value();
  if (!value->IsString() &&
      !(value->IsNumber() && !std::isnan(value.As<v8::Number>()->Value()))) {
    return RejectWithTypeError(script_state,
                               "The data for 'text' NFCRecords must be of "
                               "String or UnrestrctedDouble type.");
  }

  if (record->hasMediaType() &&
      !record->mediaType().StartsWithIgnoringASCIICase(kPlainTextMimePrefix)) {
    return RejectWithDOMException(script_state, DOMExceptionCode::kSyntaxError,
                                  "Invalid media type for 'text' record.");
  }

  return ScriptPromise();
}

ScriptPromise RejectIfInvalidURLRecord(ScriptState* script_state,
                                       const NFCRecord* record) {
  if (!record->data().V8Value()->IsString()) {
    return RejectWithTypeError(
        script_state, "The data for 'url' NFCRecord must be of String type.");
  }

  blink::V8StringResource<> string_resource = record->data().V8Value();
  if (!string_resource.Prepare() ||
      !KURL(NullURL(), string_resource).IsValid()) {
    return RejectWithDOMException(script_state, DOMExceptionCode::kSyntaxError,
                                  "Cannot parse data for 'url' record.");
  }

  return ScriptPromise();
}

ScriptPromise RejectIfInvalidJSONRecord(ScriptState* script_state,
                                        const NFCRecord* record) {
  v8::Local<v8::Value> value = record->data().V8Value();
  if (!value->IsObject() || value->IsArrayBuffer()) {
    return RejectWithTypeError(
        script_state, "The data for 'json' NFCRecord must be of Object type.");
  }

  // If JSON record has media type, it must be equal to "application/json" or
  // start with "application/" and end with "+json".
  if (record->hasMediaType() &&
      (record->mediaType() != kJsonMimeType &&
       !(record->mediaType().StartsWithIgnoringASCIICase(kJsonMimePrefix) &&
         record->mediaType().EndsWithIgnoringASCIICase(kJsonMimePostfix)))) {
    return RejectWithDOMException(script_state, DOMExceptionCode::kSyntaxError,
                                  "Invalid media type for 'json' record.");
  }

  return ScriptPromise();
}

ScriptPromise RejectIfInvalidOpaqueRecord(ScriptState* script_state,
                                          const NFCRecord* record) {
  if (!record->data().V8Value()->IsArrayBuffer()) {
    return RejectWithTypeError(
        script_state,
        "The data for 'opaque' NFCRecord must be of ArrayBuffer type.");
  }

  return ScriptPromise();
}

ScriptPromise RejectIfInvalidNFCRecord(ScriptState* script_state,
                                       const NFCRecord* record) {
  device::mojom::blink::NFCRecordType type;
  if (record->hasRecordType()) {
    type = mojo::toNFCRecordType(record->recordType());
  } else {
    type = mojo::deduceRecordTypeFromDataType(record);

    // https://w3c.github.io/web-nfc/#creating-web-nfc-message
    // If NFCRecord.recordType is not set and record type cannot be deduced
    // from NFCRecord.data, reject promise with TypeError.
    if (type == device::mojom::blink::NFCRecordType::EMPTY)
      return RejectWithTypeError(script_state, "Unknown NFCRecord type.");
  }

  // Non-empty records must have data.
  if (!record->hasData() &&
      (type != device::mojom::blink::NFCRecordType::EMPTY)) {
    return RejectWithTypeError(script_state,
                               "Nonempty NFCRecord must have data.");
  }

  switch (type) {
    case device::mojom::blink::NFCRecordType::TEXT:
      return RejectIfInvalidTextRecord(script_state, record);
    case device::mojom::blink::NFCRecordType::URL:
      return RejectIfInvalidURLRecord(script_state, record);
    case device::mojom::blink::NFCRecordType::JSON:
      return RejectIfInvalidJSONRecord(script_state, record);
    case device::mojom::blink::NFCRecordType::OPAQUE_RECORD:
      return RejectIfInvalidOpaqueRecord(script_state, record);
    case device::mojom::blink::NFCRecordType::EMPTY:
      return ScriptPromise();
  }

  NOTREACHED();
  return RejectWithTypeError(script_state,
                             "Invalid NFCRecordType was provided.");
}

ScriptPromise RejectIfInvalidNFCRecordArray(
    ScriptState* script_state,
    const HeapVector<Member<NFCRecord>>& records) {
  for (const auto& record : records) {
    ScriptPromise isValidRecord =
        RejectIfInvalidNFCRecord(script_state, record);
    if (!isValidRecord.IsEmpty())
      return isValidRecord;
  }

  return ScriptPromise();
}

ScriptPromise RejectIfInvalidNFCPushMessage(
    ScriptState* script_state,
    const NFCPushMessage& push_message) {
  // If NFCPushMessage of invalid type, reject promise with TypeError
  if (!push_message.IsNFCMessage() && !push_message.IsString() &&
      !push_message.IsArrayBuffer()) {
    return RejectWithTypeError(script_state,
                               "Invalid NFCPushMessage type was provided.");
  }

  if (push_message.IsNFCMessage()) {
    // https://w3c.github.io/web-nfc/#the-push-method
    // If NFCMessage.records is empty, reject promise with TypeError
    const NFCMessage* message = push_message.GetAsNFCMessage();
    if (!message->hasRecords() || message->records().IsEmpty()) {
      return RejectWithTypeError(script_state,
                                 "Empty NFCMessage was provided.");
    }

    return RejectIfInvalidNFCRecordArray(script_state, message->records());
  }

  return ScriptPromise();
}

bool SetURL(const String& origin,
            device::mojom::blink::NFCMessagePtr& message) {
  KURL origin_url(origin);

  if (!message->url.IsEmpty() && origin_url.CanSetPathname()) {
    origin_url.SetPath(message->url);
  }

  message->url = origin_url;
  return origin_url.IsValid();
}

String ToNFCRecordType(const device::mojom::blink::NFCRecordType& type) {
  switch (type) {
    case device::mojom::blink::NFCRecordType::TEXT:
      return "text";
    case device::mojom::blink::NFCRecordType::URL:
      return "url";
    case device::mojom::blink::NFCRecordType::JSON:
      return "json";
    case device::mojom::blink::NFCRecordType::OPAQUE_RECORD:
      return "opaque";
    case device::mojom::blink::NFCRecordType::EMPTY:
      return "empty";
  }

  NOTREACHED();
  return String();
}

v8::Local<v8::Value> ToV8(ScriptState* script_state,
                          const device::mojom::blink::NFCRecordPtr& record) {
  switch (record->record_type) {
    case device::mojom::blink::NFCRecordType::TEXT:
    case device::mojom::blink::NFCRecordType::URL:
    case device::mojom::blink::NFCRecordType::JSON: {
      String string_data;
      if (!record->data.IsEmpty()) {
        string_data = String::FromUTF8WithLatin1Fallback(
            static_cast<unsigned char*>(&record->data.front()),
            record->data.size());
      }

      v8::Isolate* isolate = script_state->GetIsolate();
      v8::Local<v8::String> string = V8String(isolate, string_data);

      // Stringified JSON must be converted back to an Object.
      if (record->record_type == device::mojom::blink::NFCRecordType::JSON) {
        v8::Local<v8::Value> json_object;
        v8::TryCatch try_catch(isolate);
        if (!v8::JSON::Parse(script_state->GetContext(), string)
                 .ToLocal(&json_object)) {
          return v8::Null(isolate);
        }

        return json_object;
      }

      return string;
    }

    case device::mojom::blink::NFCRecordType::OPAQUE_RECORD: {
      if (!record->data.IsEmpty()) {
        DOMArrayBuffer* buffer = DOMArrayBuffer::Create(
            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());
    }

    case device::mojom::blink::NFCRecordType::EMPTY:
      return v8::Null(script_state->GetIsolate());
  }

  NOTREACHED();
  return v8::Local<v8::Value>();
}

NFCRecord* ToNFCRecord(ScriptState* script_state,
                       const device::mojom::blink::NFCRecordPtr& record) {
  NFCRecord* nfc_record = NFCRecord::Create();
  nfc_record->setMediaType(record->media_type);
  nfc_record->setRecordType(ToNFCRecordType(record->record_type));
  nfc_record->setData(ScriptValue(script_state, ToV8(script_state, record)));
  return nfc_record;
}

NFCMessage* ToNFCMessage(ScriptState* script_state,
                         const device::mojom::blink::NFCMessagePtr& message) {
  NFCMessage* nfc_message = NFCMessage::Create();
  nfc_message->setURL(message->url);
  blink::HeapVector<Member<NFCRecord>> records;
  for (wtf_size_t i = 0; i < message->data.size(); ++i)
    records.push_back(ToNFCRecord(script_state, message->data[i]));
  nfc_message->setRecords(records);
  return nfc_message;
}

size_t GetNFCMessageSize(const device::mojom::blink::NFCMessagePtr& message) {
  size_t message_size = message->url.CharactersSizeInBytes();
  for (wtf_size_t i = 0; i < message->data.size(); ++i) {
    message_size += message->data[i]->media_type.CharactersSizeInBytes();
    message_size += message->data[i]->data.size();
  }
  return message_size;
}

}  // namespace

NFC::NFC(LocalFrame* frame)
    : PageVisibilityObserver(frame->GetPage()),
      ContextLifecycleObserver(frame->GetDocument()),
      client_binding_(this) {
  String error_message;

  // Only connect to NFC if we are in a context that supports it.
  if (!IsSupportedInContext(GetExecutionContext(), error_message))
    return;

  frame->GetInterfaceProvider().GetInterface(mojo::MakeRequest(&nfc_));
  nfc_.set_connection_error_handler(
      WTF::Bind(&NFC::OnConnectionError, WrapWeakPersistent(this)));
  device::mojom::blink::NFCClientPtr client;
  client_binding_.Bind(mojo::MakeRequest(&client));
  nfc_->SetClient(std::move(client));
}

NFC* NFC::Create(LocalFrame* frame) {
  NFC* nfc = MakeGarbageCollected<NFC>(frame);
  return nfc;
}

NFC::~NFC() {
  // |m_nfc| may hold persistent handle to |this| object, therefore, there
  // should be no more outstanding requests when NFC object is destructed.
  DCHECK(requests_.IsEmpty());
}

void NFC::Dispose() {
  client_binding_.Close();
}

void NFC::ContextDestroyed(ExecutionContext*) {
  nfc_.reset();
  requests_.clear();
  callbacks_.clear();
}

// https://w3c.github.io/web-nfc/#writing-or-pushing-content
// https://w3c.github.io/web-nfc/#dom-nfc-push
ScriptPromise NFC::push(ScriptState* script_state,
                        const NFCPushMessage& push_message,
                        const NFCPushOptions* options) {
  ScriptPromise promise = RejectIfNotSupported(script_state);
  if (!promise.IsEmpty())
    return promise;

  ScriptPromise isValidMessage =
      RejectIfInvalidNFCPushMessage(script_state, push_message);
  if (!isValidMessage.IsEmpty())
    return isValidMessage;

  // https://w3c.github.io/web-nfc/#dom-nfc-push
  // 9. If timeout value is NaN or negative, reject promise with "TypeError"
  // and abort these steps.
  if (options->hasTimeout() &&
      (std::isnan(options->timeout()) || options->timeout() < 0)) {
    return RejectWithTypeError(
        script_state, "Invalid NFCPushOptions.timeout value was provided.");
  }

  device::mojom::blink::NFCMessagePtr message =
      device::mojom::blink::NFCMessage::From(push_message);
  if (!message) {
    return RejectWithDOMException(script_state, DOMExceptionCode::kSyntaxError,
                                  "Cannot convert NFCMessage.");
  }

  if (!SetURL(
          ExecutionContext::From(script_state)->GetSecurityOrigin()->ToString(),
          message)) {
    return RejectWithDOMException(script_state, DOMExceptionCode::kSyntaxError,
                                  "Cannot set WebNFC Id.");
  }

  if (GetNFCMessageSize(message) > device::mojom::blink::NFCMessage::kMaxSize) {
    return RejectWithDOMException(script_state,
                                  DOMExceptionCode::kNotSupportedError,
                                  "NFCMessage exceeds maximum supported size.");
  }

  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  requests_.insert(resolver);
  auto callback = WTF::Bind(&NFC::OnRequestCompleted, WrapPersistent(this),
                            WrapPersistent(resolver));
  nfc_->Push(std::move(message),
             device::mojom::blink::NFCPushOptions::From(options),
             std::move(callback));

  return resolver->Promise();
}

// https://w3c.github.io/web-nfc/#dom-nfc-cancelpush
ScriptPromise NFC::cancelPush(ScriptState* script_state, const String& target) {
  ScriptPromise promise = RejectIfNotSupported(script_state);
  if (!promise.IsEmpty())
    return promise;

  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  requests_.insert(resolver);
  auto callback = WTF::Bind(&NFC::OnRequestCompleted, WrapPersistent(this),
                            WrapPersistent(resolver));
  nfc_->CancelPush(mojo::toNFCPushTarget(target), std::move(callback));

  return resolver->Promise();
}

// https://w3c.github.io/web-nfc/#watching-for-content
// https://w3c.github.io/web-nfc/#dom-nfc-watch
ScriptPromise NFC::watch(ScriptState* script_state,
                         V8MessageCallback* callback,
                         const NFCWatchOptions* options) {
  ScriptPromise promise = RejectIfNotSupported(script_state);
  if (!promise.IsEmpty())
    return promise;

  // https://w3c.github.io/web-nfc/#dom-nfc-watch (Step 9)
  if (options->hasURL() && !options->url().IsEmpty()) {
    KURL pattern_url(options->url());
    if (!pattern_url.IsValid() || pattern_url.Protocol() != kProtocolHttps) {
      return RejectWithDOMException(script_state,
                                    DOMExceptionCode::kSyntaxError,
                                    "Invalid URL pattern was provided.");
    }
  }

  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  requests_.insert(resolver);
  auto watch_callback =
      WTF::Bind(&NFC::OnWatchRegistered, WrapPersistent(this),
                WrapPersistent(ToV8PersistentCallbackFunction(callback)),
                WrapPersistent(resolver));
  nfc_->Watch(device::mojom::blink::NFCWatchOptions::From(options),
              std::move(watch_callback));
  return resolver->Promise();
}

// https://w3c.github.io/web-nfc/#dom-nfc-cancelwatch
ScriptPromise NFC::cancelWatch(ScriptState* script_state, int32_t id) {
  ScriptPromise promise = RejectIfNotSupported(script_state);
  if (!promise.IsEmpty())
    return promise;

  if (id) {
    callbacks_.erase(id);
  } else {
    return RejectWithDOMException(script_state,
                                  DOMExceptionCode::kNotFoundError,
                                  "Provided watch id cannot be found.");
  }

  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  requests_.insert(resolver);
  nfc_->CancelWatch(id,
                    WTF::Bind(&NFC::OnRequestCompleted, WrapPersistent(this),
                              WrapPersistent(resolver)));
  return resolver->Promise();
}

// https://w3c.github.io/web-nfc/#dom-nfc-cancelwatch
// If watchId is not provided to nfc.cancelWatch, cancel all watch operations.
ScriptPromise NFC::cancelWatch(ScriptState* script_state) {
  ScriptPromise promise = RejectIfNotSupported(script_state);
  if (!promise.IsEmpty())
    return promise;

  callbacks_.clear();
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  requests_.insert(resolver);
  nfc_->CancelAllWatches(WTF::Bind(&NFC::OnRequestCompleted,
                                   WrapPersistent(this),
                                   WrapPersistent(resolver)));
  return resolver->Promise();
}

void NFC::PageVisibilityChanged() {
  // If service is not initialized, there cannot be any pending NFC activities
  if (!nfc_)
    return;

  // NFC operations should be suspended.
  // https://w3c.github.io/web-nfc/#nfc-suspended
  if (GetPage()->VisibilityState() == mojom::PageVisibilityState::kVisible)
    nfc_->ResumeNFCOperations();
  else
    nfc_->SuspendNFCOperations();
}

void NFC::OnRequestCompleted(ScriptPromiseResolver* resolver,
                             device::mojom::blink::NFCErrorPtr error) {
  if (!requests_.Contains(resolver))
    return;

  requests_.erase(resolver);
  if (error.is_null())
    resolver->Resolve();
  else
    resolver->Reject(NFCError::Take(resolver, error->error_type));
}

void NFC::OnConnectionError() {
  nfc_.reset();
  callbacks_.clear();

  // If NFCService is not available or disappears when NFC hardware is
  // disabled, reject promise with NotSupportedError exception.
  for (ScriptPromiseResolver* resolver : requests_)
    resolver->Reject(NFCError::Take(
        resolver, device::mojom::blink::NFCErrorType::NOT_SUPPORTED));

  requests_.clear();
}

void NFC::OnWatch(const Vector<uint32_t>& ids,
                  device::mojom::blink::NFCMessagePtr message) {
  if (!GetExecutionContext())
    return;

  for (const auto& id : ids) {
    auto it = callbacks_.find(id);
    if (it != callbacks_.end()) {
      V8MessageCallback* callback = it->value;
      ScriptState* script_state = callback->CallbackRelevantScriptState();
      DCHECK(script_state);
      ScriptState::Scope scope(script_state);
      const NFCMessage* nfc_message = ToNFCMessage(script_state, message);
      callback->InvokeAndReportException(nullptr, nfc_message);
    }
  }
}

bool NFC::IsSupportedInContext(ExecutionContext* context,
                               String& error_message) {
  // https://w3c.github.io/web-nfc/#security-policies
  // WebNFC API must be only accessible from top level browsing context.
  if (!To<Document>(context)->domWindow()->GetFrame() ||
      !To<Document>(context)->GetFrame()->IsMainFrame()) {
    error_message = "Must be in a top-level browsing context";
    return false;
  }

  return true;
}

ScriptPromise NFC::RejectIfNotSupported(ScriptState* script_state) {
  String error_message;
  if (!IsSupportedInContext(ExecutionContext::From(script_state),
                            error_message)) {
    return RejectWithDOMException(
        script_state, DOMExceptionCode::kSecurityError, error_message);
  }

  if (!nfc_) {
    return RejectWithDOMException(script_state,
                                  DOMExceptionCode::kNotSupportedError,
                                  "WebNFC is not supported.");
  }

  return ScriptPromise();
}

void NFC::OnWatchRegistered(
    V8PersistentCallbackFunction<V8MessageCallback>* callback,
    ScriptPromiseResolver* resolver,
    uint32_t id,
    device::mojom::blink::NFCErrorPtr error) {
  requests_.erase(resolver);

  // Invalid id was returned.
  // https://w3c.github.io/web-nfc/#dom-nfc-watch
  // 8. If the request fails, reject promise with "NotSupportedError"
  // and abort these steps.
  if (!id) {
    resolver->Reject(NFCError::Take(
        resolver, device::mojom::blink::NFCErrorType::NOT_SUPPORTED));
    return;
  }

  if (error.is_null()) {
    callbacks_.insert(id, callback->ToNonV8Persistent());
    resolver->Resolve(id);
  } else {
    resolver->Reject(NFCError::Take(resolver, error->error_type));
  }
}

void NFC::Trace(blink::Visitor* visitor) {
  visitor->Trace(requests_);
  visitor->Trace(callbacks_);
  ScriptWrappable::Trace(visitor);
  PageVisibilityObserver::Trace(visitor);
  ContextLifecycleObserver::Trace(visitor);
}

}  // namespace blink
