// 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 "modules/nfc/NFC.h"

#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "bindings/core/v8/V8ArrayBuffer.h"
#include "bindings/core/v8/V8StringResource.h"
#include "core/dom/DOMArrayBuffer.h"
#include "core/dom/DOMException.h"
#include "core/dom/Document.h"
#include "core/dom/ExceptionCode.h"
#include "core/frame/LocalDOMWindow.h"
#include "modules/nfc/NFCError.h"
#include "modules/nfc/NFCMessage.h"
#include "modules/nfc/NFCPushOptions.h"
#include "modules/nfc/NFCWatchOptions.h"
#include "platform/mojo/MojoHelper.h"
#include "public/platform/InterfaceProvider.h"
#include "public/platform/Platform.h"

namespace {
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 kCharSetUTF8[] = ";charset=UTF-8";
}  // anonymous namespace

// Mojo type converters
namespace mojo {

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

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

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

  return NFCPushTarget::ANY;
}

NFCRecordType toNFCRecordType(const WTF::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 WTF::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 WTF::String& recordMediaType,
                  const WTF::String& defaultMediaType) {
  recordPtr->media_type =
      recordMediaType.isEmpty() ? defaultMediaType : recordMediaType;
}

template <>
struct TypeConverter<mojo::WTFArray<uint8_t>, WTF::String> {
  static mojo::WTFArray<uint8_t> Convert(const WTF::String& string) {
    WTF::CString utf8String = string.utf8();
    WTF::Vector<uint8_t> array;
    array.append(utf8String.data(), utf8String.length());
    return mojo::WTFArray<uint8_t>(std::move(array));
  }
};

template <>
struct TypeConverter<mojo::WTFArray<uint8_t>, blink::DOMArrayBuffer*> {
  static mojo::WTFArray<uint8_t> Convert(blink::DOMArrayBuffer* buffer) {
    WTF::Vector<uint8_t> array;
    array.append(static_cast<uint8_t*>(buffer->data()), buffer->byteLength());
    return mojo::WTFArray<uint8_t>(std::move(array));
  }
};

template <>
struct TypeConverter<NFCRecordPtr, WTF::String> {
  static NFCRecordPtr Convert(const WTF::String& string) {
    NFCRecordPtr record = NFCRecord::New();
    record->record_type = NFCRecordType::TEXT;
    record->media_type = kPlainTextMimeType;
    record->media_type.append(kCharSetUTF8);
    record->data = mojo::WTFArray<uint8_t>::From(string).PassStorage();
    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::WTFArray<uint8_t>::From(buffer).PassStorage();
    return record;
  }
};

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

template <>
struct TypeConverter<mojo::WTFArray<uint8_t>, blink::ScriptValue> {
  static mojo::WTFArray<uint8_t> Convert(
      const blink::ScriptValue& scriptValue) {
    v8::Local<v8::Value> value = scriptValue.v8Value();

    if (value->IsNumber())
      return mojo::WTFArray<uint8_t>::From(
          WTF::String::number(value.As<v8::Number>()->Value()));

    if (value->IsString()) {
      blink::V8StringResource<> stringResource = value;
      if (stringResource.prepare())
        return mojo::WTFArray<uint8_t>::From<WTF::String>(stringResource);
    }

    if (value->IsObject() && !value->IsArray() && !value->IsArrayBuffer()) {
      v8::Local<v8::String> jsonString;
      if (v8::JSON::Stringify(scriptValue.context(), value.As<v8::Object>())
              .ToLocal(&jsonString)) {
        WTF::String wtfString = blink::v8StringToWebCoreString<WTF::String>(
            jsonString, blink::DoNotExternalize);
        return mojo::WTFArray<uint8_t>::From(wtfString);
      }
    }

    if (value->IsArrayBuffer())
      return mojo::WTFArray<uint8_t>::From(
          blink::V8ArrayBuffer::toImpl(value.As<v8::Object>()));

    return nullptr;
  }
};

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::WTFArray<uint8_t>::From(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.is_null())
      return nullptr;

    recordPtr->data = recordData.PassStorage();
    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.data().size());
    for (size_t i = 0; i < message.data().size(); ++i) {
      NFCRecordPtr record = NFCRecord::From(message.data()[i]);
      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.append(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, 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, 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 {

bool isValidTextRecord(const NFCRecord& record) {
  v8::Local<v8::Value> value = record.data().v8Value();
  if (!value->IsString() &&
      !(value->IsNumber() && !std::isnan(value.As<v8::Number>()->Value())))
    return false;

  if (record.hasMediaType() &&
      !record.mediaType().startsWith(kPlainTextMimePrefix,
                                     TextCaseUnicodeInsensitive))
    return false;

  return true;
}

bool isValidURLRecord(const NFCRecord& record) {
  if (!record.data().v8Value()->IsString())
    return false;

  blink::V8StringResource<> stringResource = record.data().v8Value();
  if (!stringResource.prepare())
    return false;

  return KURL(KURL(), stringResource).isValid();
}

bool isValidJSONRecord(const NFCRecord& record) {
  v8::Local<v8::Value> value = record.data().v8Value();
  if (!value->IsObject() || value->IsArrayBuffer())
    return false;

  if (record.hasMediaType() &&
      !record.mediaType().startsWith(kJsonMimePrefix, TextCaseASCIIInsensitive))
    return false;

  return true;
}

bool isValidOpaqueRecord(const NFCRecord& record) {
  return record.data().v8Value()->IsArrayBuffer();
}

bool isValidNFCRecord(const NFCRecord& record) {
  device::nfc::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 SyntaxError.
    if (type == device::nfc::mojom::blink::NFCRecordType::EMPTY)
      return false;
  }

  // Non-empty records must have data.
  if (!record.hasData() &&
      (type != device::nfc::mojom::blink::NFCRecordType::EMPTY)) {
    return false;
  }

  switch (type) {
    case device::nfc::mojom::blink::NFCRecordType::TEXT:
      return isValidTextRecord(record);
    case device::nfc::mojom::blink::NFCRecordType::URL:
      return isValidURLRecord(record);
    case device::nfc::mojom::blink::NFCRecordType::JSON:
      return isValidJSONRecord(record);
    case device::nfc::mojom::blink::NFCRecordType::OPAQUE_RECORD:
      return isValidOpaqueRecord(record);
    case device::nfc::mojom::blink::NFCRecordType::EMPTY:
      return !record.hasData() && record.mediaType().isEmpty();
  }

  NOTREACHED();
  return false;
}

DOMException* isValidNFCRecordArray(const HeapVector<NFCRecord>& records) {
  // https://w3c.github.io/web-nfc/#the-push-method
  // If NFCMessage.data is empty, reject promise with SyntaxError
  if (records.isEmpty())
    return DOMException::create(SyntaxError);

  for (const auto& record : records) {
    if (!isValidNFCRecord(record))
      return DOMException::create(SyntaxError);
  }

  return nullptr;
}

DOMException* isValidNFCPushMessage(const NFCPushMessage& message) {
  if (!message.isNFCMessage() && !message.isString() &&
      !message.isArrayBuffer())
    return DOMException::create(TypeMismatchError);

  if (message.isNFCMessage()) {
    if (!message.getAsNFCMessage().hasData())
      return DOMException::create(TypeMismatchError);

    return isValidNFCRecordArray(message.getAsNFCMessage().data());
  }

  return nullptr;
}

bool setURL(const String& origin,
            device::nfc::mojom::blink::NFCMessagePtr& message) {
  KURL originURL(ParsedURLString, origin);

  if (!message->url.isEmpty() && originURL.canSetPathname()) {
    originURL.setPath(message->url);
  }

  message->url = originURL;
  return originURL.isValid();
}

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

  NOTREACHED();
  return String();
}

v8::Local<v8::Value> toV8(
    ScriptState* scriptState,
    const device::nfc::mojom::blink::NFCRecordPtr& record) {
  switch (record->record_type) {
    case device::nfc::mojom::blink::NFCRecordType::TEXT:
    case device::nfc::mojom::blink::NFCRecordType::URL:
    case device::nfc::mojom::blink::NFCRecordType::JSON: {
      String stringData;
      if (!record->data.isEmpty()) {
        stringData = String::fromUTF8WithLatin1Fallback(
            static_cast<unsigned char*>(&record->data.first()),
            record->data.size());
      }

      v8::Isolate* isolate = scriptState->isolate();
      v8::Local<v8::String> string = v8String(isolate, stringData);

      // Stringified JSON must be converted back to an Object.
      if (record->record_type ==
          device::nfc::mojom::blink::NFCRecordType::JSON) {
        v8::Local<v8::Value> jsonObject;
        v8::TryCatch tryCatch(isolate);
        if (!v8Call(v8::JSON::Parse(isolate, string), jsonObject, tryCatch)) {
          return v8::Null(isolate);
        }

        return jsonObject;
      }

      return string;
    }

    case device::nfc::mojom::blink::NFCRecordType::OPAQUE_RECORD: {
      if (!record->data.isEmpty()) {
        DOMArrayBuffer* buffer = DOMArrayBuffer::create(
            static_cast<void*>(&record->data.first()), record->data.size());
        return toV8(buffer, scriptState->context()->Global(),
                    scriptState->isolate());
      }

      return v8::Null(scriptState->isolate());
    }

    case device::nfc::mojom::blink::NFCRecordType::EMPTY:
      return v8::Null(scriptState->isolate());
  }

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

NFCRecord toNFCRecord(ScriptState* scriptState,
                      const device::nfc::mojom::blink::NFCRecordPtr& record) {
  NFCRecord nfcRecord;
  nfcRecord.setMediaType(record->media_type);
  nfcRecord.setRecordType(toNFCRecordType(record->record_type));
  nfcRecord.setData(ScriptValue(scriptState, toV8(scriptState, record)));
  return nfcRecord;
}

NFCMessage toNFCMessage(
    ScriptState* scriptState,
    const device::nfc::mojom::blink::NFCMessagePtr& message) {
  NFCMessage nfcMessage;
  nfcMessage.setURL(message->url);
  blink::HeapVector<NFCRecord> records;
  for (size_t i = 0; i < message->data.size(); ++i)
    records.append(toNFCRecord(scriptState, message->data[i]));
  nfcMessage.setData(records);
  return nfcMessage;
}

size_t getNFCMessageSize(
    const device::nfc::mojom::blink::NFCMessagePtr& message) {
  size_t messageSize = message->url.charactersSizeInBytes();
  for (size_t i = 0; i < message->data.size(); ++i) {
    messageSize += message->data[i]->media_type.charactersSizeInBytes();
    messageSize += message->data[i]->data.size();
  }
  return messageSize;
}

}  // namespace

NFC::NFC(LocalFrame* frame)
    : PageVisibilityObserver(frame->page()),
      ContextLifecycleObserver(frame->document()),
      m_client(this) {
  ThreadState::current()->registerPreFinalizer(this);
  frame->interfaceProvider()->getInterface(mojo::GetProxy(&m_nfc));
  m_nfc.set_connection_error_handler(convertToBaseCallback(
      WTF::bind(&NFC::OnConnectionError, wrapWeakPersistent(this))));
  m_nfc->SetClient(m_client.CreateInterfacePtrAndBind());
}

NFC* NFC::create(LocalFrame* frame) {
  NFC* nfc = new 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(m_requests.isEmpty());
}

void NFC::dispose() {
  m_client.Close();
}

void NFC::contextDestroyed() {
  m_nfc.reset();
  m_requests.clear();
  m_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* scriptState,
                        const NFCPushMessage& pushMessage,
                        const NFCPushOptions& options) {
  ScriptPromise promise = rejectIfNotSupported(scriptState);
  if (!promise.isEmpty())
    return promise;

  DOMException* exception = isValidNFCPushMessage(pushMessage);
  if (exception)
    return ScriptPromise::rejectWithDOMException(scriptState, exception);

  device::nfc::mojom::blink::NFCMessagePtr message =
      device::nfc::mojom::blink::NFCMessage::From(pushMessage);
  if (!message)
    return ScriptPromise::rejectWithDOMException(
        scriptState, DOMException::create(SyntaxError));

  if (!setURL(
          scriptState->getExecutionContext()->getSecurityOrigin()->toString(),
          message))
    return ScriptPromise::rejectWithDOMException(
        scriptState, DOMException::create(SyntaxError));

  if (getNFCMessageSize(message) >
      device::nfc::mojom::blink::NFCMessage::kMaxSize) {
    return ScriptPromise::rejectWithDOMException(
        scriptState, DOMException::create(NotSupportedError));
  }

  ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
  m_requests.add(resolver);
  auto callback = convertToBaseCallback(WTF::bind(&NFC::OnRequestCompleted,
                                                  wrapPersistent(this),
                                                  wrapPersistent(resolver)));
  m_nfc->Push(std::move(message),
              device::nfc::mojom::blink::NFCPushOptions::From(options),
              callback);

  return resolver->promise();
}

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

  ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
  m_requests.add(resolver);
  auto callback = convertToBaseCallback(WTF::bind(&NFC::OnRequestCompleted,
                                                  wrapPersistent(this),
                                                  wrapPersistent(resolver)));
  m_nfc->CancelPush(mojo::toNFCPushTarget(target), 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* scriptState,
                         MessageCallback* callback,
                         const NFCWatchOptions& options) {
  ScriptPromise promise = rejectIfNotSupported(scriptState);
  if (!promise.isEmpty())
    return promise;

  callback->setScriptState(scriptState);
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
  m_requests.add(resolver);
  auto watchCallback = convertToBaseCallback(
      WTF::bind(&NFC::OnWatchRegistered, wrapPersistent(this),
                wrapPersistent(callback), wrapPersistent(resolver)));
  m_nfc->Watch(device::nfc::mojom::blink::NFCWatchOptions::From(options),
               watchCallback);
  return resolver->promise();
}

// https://w3c.github.io/web-nfc/#dom-nfc-cancelwatch
ScriptPromise NFC::cancelWatch(ScriptState* scriptState, long id) {
  ScriptPromise promise = rejectIfNotSupported(scriptState);
  if (!promise.isEmpty())
    return promise;

  if (id) {
    m_callbacks.remove(id);
  } else {
    return ScriptPromise::rejectWithDOMException(
        scriptState, DOMException::create(NotFoundError));
  }

  ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
  m_requests.add(resolver);
  m_nfc->CancelWatch(id, convertToBaseCallback(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* scriptState) {
  ScriptPromise promise = rejectIfNotSupported(scriptState);
  if (!promise.isEmpty())
    return promise;

  m_callbacks.clear();
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
  m_requests.add(resolver);
  m_nfc->CancelAllWatches(convertToBaseCallback(
      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 (!m_nfc)
    return;

  // NFC operations should be suspended.
  // https://w3c.github.io/web-nfc/#nfc-suspended
  if (page()->visibilityState() == PageVisibilityStateVisible)
    m_nfc->ResumeNFCOperations();
  else
    m_nfc->SuspendNFCOperations();
}

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

  m_requests.remove(resolver);
  if (error.is_null())
    resolver->resolve();
  else
    resolver->reject(NFCError::take(resolver, error->error_type));
}

void NFC::OnConnectionError() {
  if (!Platform::current()) {
    // TODO(rockot): Clean this up once renderer shutdown sequence is fixed.
    return;
  }

  m_nfc.reset();
  m_callbacks.clear();

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

  m_requests.clear();
}

void NFC::OnWatch(const WTF::Vector<uint32_t>& ids,
                  device::nfc::mojom::blink::NFCMessagePtr message) {
  for (const auto& id : ids) {
    auto it = m_callbacks.find(id);
    if (it != m_callbacks.end()) {
      MessageCallback* callback = it->value;
      ScriptState* scriptState = callback->getScriptState();
      DCHECK(scriptState);
      ScriptState::Scope scope(scriptState);
      NFCMessage nfcMessage = toNFCMessage(scriptState, message);
      callback->handleMessage(nfcMessage);
    }
  }
}

ScriptPromise NFC::rejectIfNotSupported(ScriptState* scriptState) {
  String errorMessage;
  if (!scriptState->getExecutionContext()->isSecureContext(errorMessage)) {
    return ScriptPromise::rejectWithDOMException(
        scriptState, DOMException::create(SecurityError, errorMessage));
  }

  if (!m_nfc) {
    return ScriptPromise::rejectWithDOMException(
        scriptState, DOMException::create(NotSupportedError));
  }

  return ScriptPromise();
}

void NFC::OnWatchRegistered(MessageCallback* callback,
                            ScriptPromiseResolver* resolver,
                            uint32_t id,
                            device::nfc::mojom::blink::NFCErrorPtr error) {
  m_requests.remove(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::nfc::mojom::blink::NFCErrorType::NOT_SUPPORTED));
    return;
  }

  if (error.is_null()) {
    m_callbacks.add(id, callback);
    resolver->resolve(id);
  } else {
    resolver->reject(NFCError::take(resolver, error->error_type));
  }
}

DEFINE_TRACE(NFC) {
  PageVisibilityObserver::trace(visitor);
  ContextLifecycleObserver::trace(visitor);
  visitor->trace(m_requests);
  visitor->trace(m_callbacks);
}

}  // namespace blink
