// 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/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()->IsPageVisible())
    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->CallbackRelevantScriptStateOrReportError("NFC", "watch");
      if (!script_state)
        continue;
      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
