// 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/webusb/usb_device.h"

#include <algorithm>

#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
#include "third_party/blink/renderer/modules/webusb/usb_configuration.h"
#include "third_party/blink/renderer/modules/webusb/usb_control_transfer_parameters.h"
#include "third_party/blink/renderer/modules/webusb/usb_in_transfer_result.h"
#include "third_party/blink/renderer/modules/webusb/usb_isochronous_in_transfer_result.h"
#include "third_party/blink/renderer/modules/webusb/usb_isochronous_out_transfer_result.h"
#include "third_party/blink/renderer/modules/webusb/usb_out_transfer_result.h"
#include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"

using device::mojom::blink::UsbControlTransferParamsPtr;
using device::mojom::blink::UsbControlTransferType;
using device::mojom::blink::UsbControlTransferRecipient;
using device::mojom::blink::UsbDeviceInfoPtr;
using device::mojom::blink::UsbDevicePtr;
using device::mojom::blink::UsbIsochronousPacketPtr;
using device::mojom::blink::UsbOpenDeviceError;
using device::mojom::blink::UsbTransferDirection;
using device::mojom::blink::UsbTransferStatus;

namespace blink {

namespace {

const char kDeviceStateChangeInProgress[] =
    "An operation that changes the device state is in progress.";
const char kDeviceDisconnected[] = "The device was disconnected.";
const char kInterfaceNotFound[] =
    "The interface number provided is not supported by the device in its "
    "current configuration.";
const char kInterfaceStateChangeInProgress[] =
    "An operation that changes interface state is in progress.";
const char kOpenRequired[] = "The device must be opened first.";

DOMException* ConvertFatalTransferStatus(const UsbTransferStatus& status) {
  switch (status) {
    case UsbTransferStatus::TRANSFER_ERROR:
      return DOMException::Create(DOMExceptionCode::kNetworkError,
                                  "A transfer error has occurred.");
    case UsbTransferStatus::PERMISSION_DENIED:
      return DOMException::Create(DOMExceptionCode::kSecurityError,
                                  "The transfer was not allowed.");
    case UsbTransferStatus::TIMEOUT:
      return DOMException::Create(DOMExceptionCode::kTimeoutError,
                                  "The transfer timed out.");
    case UsbTransferStatus::CANCELLED:
      return DOMException::Create(DOMExceptionCode::kAbortError,
                                  "The transfer was cancelled.");
    case UsbTransferStatus::DISCONNECT:
      return DOMException::Create(DOMExceptionCode::kNotFoundError,
                                  kDeviceDisconnected);
    case UsbTransferStatus::COMPLETED:
    case UsbTransferStatus::STALLED:
    case UsbTransferStatus::BABBLE:
    case UsbTransferStatus::SHORT_PACKET:
      return nullptr;
    default:
      NOTREACHED();
      return nullptr;
  }
}

String ConvertTransferStatus(const UsbTransferStatus& status) {
  switch (status) {
    case UsbTransferStatus::COMPLETED:
    case UsbTransferStatus::SHORT_PACKET:
      return "ok";
    case UsbTransferStatus::STALLED:
      return "stall";
    case UsbTransferStatus::BABBLE:
      return "babble";
    default:
      NOTREACHED();
      return "";
  }
}

Vector<uint8_t> ConvertBufferSource(
    const ArrayBufferOrArrayBufferView& buffer) {
  DCHECK(!buffer.IsNull());
  Vector<uint8_t> vector;
  if (buffer.IsArrayBuffer()) {
    vector.Append(static_cast<uint8_t*>(buffer.GetAsArrayBuffer()->Data()),
                  buffer.GetAsArrayBuffer()->ByteLength());
  } else {
    vector.Append(static_cast<uint8_t*>(
                      buffer.GetAsArrayBufferView().View()->BaseAddress()),
                  buffer.GetAsArrayBufferView().View()->byteLength());
  }
  return vector;
}

}  // namespace

USBDevice::USBDevice(UsbDeviceInfoPtr device_info,
                     UsbDevicePtr device,
                     ExecutionContext* context)
    : ContextLifecycleObserver(context),
      device_info_(std::move(device_info)),
      device_(std::move(device)),
      opened_(false),
      device_state_change_in_progress_(false),
      configuration_index_(-1) {
  if (device_) {
    device_.set_connection_error_handler(
        WTF::Bind(&USBDevice::OnConnectionError, WrapWeakPersistent(this)));
  }
  int configuration_index = FindConfigurationIndex(Info().active_configuration);
  if (configuration_index != -1)
    OnConfigurationSelected(true /* success */, configuration_index);
}

USBDevice::~USBDevice() {
  // |m_device| may still be valid but there should be no more outstanding
  // requests because each holds a persistent handle to this object.
  DCHECK(device_requests_.IsEmpty());
}

bool USBDevice::IsInterfaceClaimed(size_t configuration_index,
                                   size_t interface_index) const {
  return configuration_index_ != -1 &&
         static_cast<size_t>(configuration_index_) == configuration_index &&
         claimed_interfaces_.Get(interface_index);
}

size_t USBDevice::SelectedAlternateInterface(size_t interface_index) const {
  return selected_alternates_[interface_index];
}

USBConfiguration* USBDevice::configuration() const {
  if (configuration_index_ != -1)
    return USBConfiguration::Create(this, configuration_index_);
  return nullptr;
}

HeapVector<Member<USBConfiguration>> USBDevice::configurations() const {
  size_t num_configurations = Info().configurations.size();
  HeapVector<Member<USBConfiguration>> configurations(num_configurations);
  for (size_t i = 0; i < num_configurations; ++i)
    configurations[i] = USBConfiguration::Create(this, i);
  return configurations;
}

ScriptPromise USBDevice::open(ScriptState* script_state) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  if (EnsureNoDeviceOrInterfaceChangeInProgress(resolver)) {
    if (opened_) {
      resolver->Resolve();
    } else {
      device_state_change_in_progress_ = true;
      device_requests_.insert(resolver);
      device_->Open(WTF::Bind(&USBDevice::AsyncOpen, WrapPersistent(this),
                              WrapPersistent(resolver)));
    }
  }
  return promise;
}

ScriptPromise USBDevice::close(ScriptState* script_state) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  if (EnsureNoDeviceOrInterfaceChangeInProgress(resolver)) {
    if (!opened_) {
      resolver->Resolve();
    } else {
      device_state_change_in_progress_ = true;
      device_requests_.insert(resolver);
      device_->Close(WTF::Bind(&USBDevice::AsyncClose, WrapPersistent(this),
                               WrapPersistent(resolver)));
    }
  }
  return promise;
}

ScriptPromise USBDevice::selectConfiguration(ScriptState* script_state,
                                             uint8_t configuration_value) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  if (EnsureNoDeviceOrInterfaceChangeInProgress(resolver)) {
    if (!opened_) {
      resolver->Reject(DOMException::Create(
          DOMExceptionCode::kInvalidStateError, kOpenRequired));
    } else {
      int configuration_index = FindConfigurationIndex(configuration_value);
      if (configuration_index == -1) {
        resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
                                              "The configuration value "
                                              "provided is not supported by "
                                              "the device."));
      } else if (configuration_index_ == configuration_index) {
        resolver->Resolve();
      } else {
        device_state_change_in_progress_ = true;
        device_requests_.insert(resolver);
        device_->SetConfiguration(
            configuration_value,
            WTF::Bind(&USBDevice::AsyncSelectConfiguration,
                      WrapPersistent(this), configuration_index,
                      WrapPersistent(resolver)));
      }
    }
  }
  return promise;
}

ScriptPromise USBDevice::claimInterface(ScriptState* script_state,
                                        uint8_t interface_number) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  if (EnsureDeviceConfigured(resolver)) {
    int interface_index = FindInterfaceIndex(interface_number);
    if (interface_index == -1) {
      resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
                                            kInterfaceNotFound));
    } else if (interface_state_change_in_progress_.Get(interface_index)) {
      resolver->Reject(
          DOMException::Create(DOMExceptionCode::kInvalidStateError,
                               kInterfaceStateChangeInProgress));
    } else if (claimed_interfaces_.Get(interface_index)) {
      resolver->Resolve();
    } else if (IsProtectedInterfaceClass(interface_index)) {
      GetExecutionContext()->AddConsoleMessage(
          ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel,
                                 "An attempt to claim a USB device interface "
                                 "has been blocked because it "
                                 "implements a protected interface class."));
      resolver->Reject(DOMException::Create(
          DOMExceptionCode::kSecurityError,
          "The requested interface implements a protected class."));
    } else {
      interface_state_change_in_progress_.Set(interface_index);
      device_requests_.insert(resolver);
      device_->ClaimInterface(
          interface_number,
          WTF::Bind(&USBDevice::AsyncClaimInterface, WrapPersistent(this),
                    interface_index, WrapPersistent(resolver)));
    }
  }
  return promise;
}

ScriptPromise USBDevice::releaseInterface(ScriptState* script_state,
                                          uint8_t interface_number) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  if (EnsureDeviceConfigured(resolver)) {
    int interface_index = FindInterfaceIndex(interface_number);
    if (interface_index == -1) {
      resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
                                            "The interface number provided is "
                                            "not supported by the device in "
                                            "its current configuration."));
    } else if (interface_state_change_in_progress_.Get(interface_index)) {
      resolver->Reject(
          DOMException::Create(DOMExceptionCode::kInvalidStateError,
                               kInterfaceStateChangeInProgress));
    } else if (!claimed_interfaces_.Get(interface_index)) {
      resolver->Resolve();
    } else {
      // Mark this interface's endpoints unavailable while its state is
      // changing.
      SetEndpointsForInterface(interface_index, false);
      interface_state_change_in_progress_.Set(interface_index);
      device_requests_.insert(resolver);
      device_->ReleaseInterface(
          interface_number,
          WTF::Bind(&USBDevice::AsyncReleaseInterface, WrapPersistent(this),
                    interface_index, WrapPersistent(resolver)));
    }
  }
  return promise;
}

ScriptPromise USBDevice::selectAlternateInterface(ScriptState* script_state,
                                                  uint8_t interface_number,
                                                  uint8_t alternate_setting) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  if (EnsureInterfaceClaimed(interface_number, resolver)) {
    // TODO(reillyg): This is duplicated work.
    int interface_index = FindInterfaceIndex(interface_number);
    DCHECK_NE(interface_index, -1);
    int alternate_index =
        FindAlternateIndex(interface_index, alternate_setting);
    if (alternate_index == -1) {
      resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
                                            "The alternate setting provided is "
                                            "not supported by the device in "
                                            "its current configuration."));
    } else {
      // Mark this old alternate interface's endpoints unavailable while
      // the change is in progress.
      SetEndpointsForInterface(interface_index, false);
      interface_state_change_in_progress_.Set(interface_index);
      device_requests_.insert(resolver);
      device_->SetInterfaceAlternateSetting(
          interface_number, alternate_setting,
          WTF::Bind(&USBDevice::AsyncSelectAlternateInterface,
                    WrapPersistent(this), interface_number, alternate_setting,
                    WrapPersistent(resolver)));
    }
  }
  return promise;
}

ScriptPromise USBDevice::controlTransferIn(
    ScriptState* script_state,
    const USBControlTransferParameters& setup,
    unsigned length) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  if (EnsureDeviceConfigured(resolver)) {
    auto parameters = ConvertControlTransferParameters(setup, resolver);
    if (parameters) {
      device_requests_.insert(resolver);
      device_->ControlTransferIn(
          std::move(parameters), length, 0,
          WTF::Bind(&USBDevice::AsyncControlTransferIn, WrapPersistent(this),
                    WrapPersistent(resolver)));
    }
  }
  return promise;
}

ScriptPromise USBDevice::controlTransferOut(
    ScriptState* script_state,
    const USBControlTransferParameters& setup) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  if (EnsureDeviceConfigured(resolver)) {
    auto parameters = ConvertControlTransferParameters(setup, resolver);
    if (parameters) {
      device_requests_.insert(resolver);
      device_->ControlTransferOut(
          std::move(parameters), Vector<uint8_t>(), 0,
          WTF::Bind(&USBDevice::AsyncControlTransferOut, WrapPersistent(this),
                    0, WrapPersistent(resolver)));
    }
  }
  return promise;
}

ScriptPromise USBDevice::controlTransferOut(
    ScriptState* script_state,
    const USBControlTransferParameters& setup,
    const ArrayBufferOrArrayBufferView& data) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  if (EnsureDeviceConfigured(resolver)) {
    auto parameters = ConvertControlTransferParameters(setup, resolver);
    if (parameters) {
      Vector<uint8_t> buffer = ConvertBufferSource(data);
      unsigned transfer_length = buffer.size();
      device_requests_.insert(resolver);
      device_->ControlTransferOut(
          std::move(parameters), buffer, 0,
          WTF::Bind(&USBDevice::AsyncControlTransferOut, WrapPersistent(this),
                    transfer_length, WrapPersistent(resolver)));
    }
  }
  return promise;
}

ScriptPromise USBDevice::clearHalt(ScriptState* script_state,
                                   String direction,
                                   uint8_t endpoint_number) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  if (EnsureEndpointAvailable(direction == "in", endpoint_number, resolver)) {
    device_requests_.insert(resolver);
    device_->ClearHalt(endpoint_number, WTF::Bind(&USBDevice::AsyncClearHalt,
                                                  WrapPersistent(this),
                                                  WrapPersistent(resolver)));
  }
  return promise;
}

ScriptPromise USBDevice::transferIn(ScriptState* script_state,
                                    uint8_t endpoint_number,
                                    unsigned length) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  if (EnsureEndpointAvailable(true /* in */, endpoint_number, resolver)) {
    device_requests_.insert(resolver);
    device_->GenericTransferIn(
        endpoint_number, length, 0,
        WTF::Bind(&USBDevice::AsyncTransferIn, WrapPersistent(this),
                  WrapPersistent(resolver)));
  }
  return promise;
}

ScriptPromise USBDevice::transferOut(ScriptState* script_state,
                                     uint8_t endpoint_number,
                                     const ArrayBufferOrArrayBufferView& data) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  if (EnsureEndpointAvailable(false /* out */, endpoint_number, resolver)) {
    Vector<uint8_t> buffer = ConvertBufferSource(data);
    unsigned transfer_length = buffer.size();
    device_requests_.insert(resolver);
    device_->GenericTransferOut(
        endpoint_number, buffer, 0,
        WTF::Bind(&USBDevice::AsyncTransferOut, WrapPersistent(this),
                  transfer_length, WrapPersistent(resolver)));
  }
  return promise;
}

ScriptPromise USBDevice::isochronousTransferIn(
    ScriptState* script_state,
    uint8_t endpoint_number,
    Vector<unsigned> packet_lengths) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  if (EnsureEndpointAvailable(true /* in */, endpoint_number, resolver)) {
    device_requests_.insert(resolver);
    device_->IsochronousTransferIn(
        endpoint_number, packet_lengths, 0,
        WTF::Bind(&USBDevice::AsyncIsochronousTransferIn, WrapPersistent(this),
                  WrapPersistent(resolver)));
  }
  return promise;
}

ScriptPromise USBDevice::isochronousTransferOut(
    ScriptState* script_state,
    uint8_t endpoint_number,
    const ArrayBufferOrArrayBufferView& data,
    Vector<unsigned> packet_lengths) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  if (EnsureEndpointAvailable(false /* out */, endpoint_number, resolver)) {
    device_requests_.insert(resolver);
    device_->IsochronousTransferOut(
        endpoint_number, ConvertBufferSource(data), packet_lengths, 0,
        WTF::Bind(&USBDevice::AsyncIsochronousTransferOut, WrapPersistent(this),
                  WrapPersistent(resolver)));
  }
  return promise;
}

ScriptPromise USBDevice::reset(ScriptState* script_state) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  if (EnsureNoDeviceOrInterfaceChangeInProgress(resolver)) {
    if (!opened_) {
      resolver->Reject(DOMException::Create(
          DOMExceptionCode::kInvalidStateError, kOpenRequired));
    } else {
      device_requests_.insert(resolver);
      device_->Reset(WTF::Bind(&USBDevice::AsyncReset, WrapPersistent(this),
                               WrapPersistent(resolver)));
    }
  }
  return promise;
}

void USBDevice::ContextDestroyed(ExecutionContext*) {
  device_.reset();
  device_requests_.clear();
}

void USBDevice::Trace(blink::Visitor* visitor) {
  visitor->Trace(device_requests_);
  ScriptWrappable::Trace(visitor);
  ContextLifecycleObserver::Trace(visitor);
}

int USBDevice::FindConfigurationIndex(uint8_t configuration_value) const {
  const auto& configurations = Info().configurations;
  for (size_t i = 0; i < configurations.size(); ++i) {
    if (configurations[i]->configuration_value == configuration_value)
      return i;
  }
  return -1;
}

int USBDevice::FindInterfaceIndex(uint8_t interface_number) const {
  DCHECK_NE(configuration_index_, -1);
  const auto& interfaces =
      Info().configurations[configuration_index_]->interfaces;
  for (size_t i = 0; i < interfaces.size(); ++i) {
    if (interfaces[i]->interface_number == interface_number)
      return i;
  }
  return -1;
}

int USBDevice::FindAlternateIndex(size_t interface_index,
                                  uint8_t alternate_setting) const {
  DCHECK_NE(configuration_index_, -1);
  const auto& alternates = Info()
                               .configurations[configuration_index_]
                               ->interfaces[interface_index]
                               ->alternates;
  for (size_t i = 0; i < alternates.size(); ++i) {
    if (alternates[i]->alternate_setting == alternate_setting)
      return i;
  }
  return -1;
}

bool USBDevice::IsProtectedInterfaceClass(int interface_index) const {
  DCHECK_NE(configuration_index_, -1);
  DCHECK_NE(interface_index, -1);

  // USB Class Codes are defined by the USB-IF:
  // http://www.usb.org/developers/defined_class
  const uint8_t kProtectedClasses[] = {
      0x01,  // Audio
      0x03,  // HID
      0x08,  // Mass Storage
      0x0B,  // Smart Card
      0x0E,  // Video
      0x10,  // Audio/Video
      0xE0,  // Wireless Controller (Bluetooth and Wireless USB)
  };
  DCHECK(std::is_sorted(std::begin(kProtectedClasses),
                        std::end(kProtectedClasses)));

  const auto& alternates = Info()
                               .configurations[configuration_index_]
                               ->interfaces[interface_index]
                               ->alternates;
  for (const auto& alternate : alternates) {
    if (std::binary_search(std::begin(kProtectedClasses),
                           std::end(kProtectedClasses),
                           alternate->class_code)) {
      return true;
    }
  }

  return false;
}

bool USBDevice::EnsureNoDeviceOrInterfaceChangeInProgress(
    ScriptPromiseResolver* resolver) const {
  if (!device_) {
    resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
                                          kDeviceDisconnected));
  } else if (device_state_change_in_progress_) {
    resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
                                          kDeviceStateChangeInProgress));
  } else if (AnyInterfaceChangeInProgress()) {
    resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
                                          kInterfaceStateChangeInProgress));
  } else {
    return true;
  }
  return false;
}

bool USBDevice::EnsureDeviceConfigured(ScriptPromiseResolver* resolver) const {
  if (!device_) {
    resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
                                          kDeviceDisconnected));
  } else if (device_state_change_in_progress_) {
    resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
                                          kDeviceStateChangeInProgress));
  } else if (!opened_) {
    resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
                                          kOpenRequired));
  } else if (configuration_index_ == -1) {
    resolver->Reject(
        DOMException::Create(DOMExceptionCode::kInvalidStateError,
                             "The device must have a configuration selected."));
  } else {
    return true;
  }
  return false;
}

bool USBDevice::EnsureInterfaceClaimed(uint8_t interface_number,
                                       ScriptPromiseResolver* resolver) const {
  if (!EnsureDeviceConfigured(resolver))
    return false;
  int interface_index = FindInterfaceIndex(interface_number);
  if (interface_index == -1) {
    resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
                                          kInterfaceNotFound));
  } else if (interface_state_change_in_progress_.Get(interface_index)) {
    resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
                                          kInterfaceStateChangeInProgress));
  } else if (!claimed_interfaces_.Get(interface_index)) {
    resolver->Reject(
        DOMException::Create(DOMExceptionCode::kInvalidStateError,
                             "The specified interface has not been claimed."));
  } else {
    return true;
  }
  return false;
}

bool USBDevice::EnsureEndpointAvailable(bool in_transfer,
                                        uint8_t endpoint_number,
                                        ScriptPromiseResolver* resolver) const {
  if (!EnsureDeviceConfigured(resolver))
    return false;
  if (endpoint_number == 0 || endpoint_number >= 16) {
    resolver->Reject(
        DOMException::Create(DOMExceptionCode::kIndexSizeError,
                             "The specified endpoint number is out of range."));
    return false;
  }
  auto& bit_vector = in_transfer ? in_endpoints_ : out_endpoints_;
  if (!bit_vector.Get(endpoint_number - 1)) {
    resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
                                          "The specified endpoint is not part "
                                          "of a claimed and selected alternate "
                                          "interface."));
    return false;
  }
  return true;
}

bool USBDevice::AnyInterfaceChangeInProgress() const {
  for (size_t i = 0; i < interface_state_change_in_progress_.size(); ++i) {
    if (interface_state_change_in_progress_.QuickGet(i))
      return true;
  }
  return false;
}

UsbControlTransferParamsPtr USBDevice::ConvertControlTransferParameters(
    const USBControlTransferParameters& parameters,
    ScriptPromiseResolver* resolver) const {
  auto mojo_parameters = device::mojom::blink::UsbControlTransferParams::New();

  if (parameters.requestType() == "standard") {
    mojo_parameters->type = UsbControlTransferType::STANDARD;
  } else if (parameters.requestType() == "class") {
    mojo_parameters->type = UsbControlTransferType::CLASS;
  } else if (parameters.requestType() == "vendor") {
    mojo_parameters->type = UsbControlTransferType::VENDOR;
  } else {
    resolver->Reject(DOMException::Create(
        DOMExceptionCode::kTypeMismatchError,
        "The control transfer requestType parameter is invalid."));
    return nullptr;
  }

  if (parameters.recipient() == "device") {
    mojo_parameters->recipient = UsbControlTransferRecipient::DEVICE;
  } else if (parameters.recipient() == "interface") {
    size_t interface_number = parameters.index() & 0xff;
    if (!EnsureInterfaceClaimed(interface_number, resolver))
      return nullptr;
    mojo_parameters->recipient = UsbControlTransferRecipient::INTERFACE;
  } else if (parameters.recipient() == "endpoint") {
    bool in_transfer = parameters.index() & 0x80;
    size_t endpoint_number = parameters.index() & 0x0f;
    if (!EnsureEndpointAvailable(in_transfer, endpoint_number, resolver))
      return nullptr;
    mojo_parameters->recipient = UsbControlTransferRecipient::ENDPOINT;
  } else if (parameters.recipient() == "other") {
    mojo_parameters->recipient = UsbControlTransferRecipient::OTHER;
  } else {
    resolver->Reject(DOMException::Create(
        DOMExceptionCode::kTypeMismatchError,
        "The control transfer recipient parameter is invalid."));
    return nullptr;
  }

  mojo_parameters->request = parameters.request();
  mojo_parameters->value = parameters.value();
  mojo_parameters->index = parameters.index();
  return mojo_parameters;
}

void USBDevice::SetEndpointsForInterface(size_t interface_index, bool set) {
  const auto& configuration = *Info().configurations[configuration_index_];
  const auto& interface = *configuration.interfaces[interface_index];
  const auto& alternate =
      *interface.alternates[selected_alternates_[interface_index]];
  for (const auto& endpoint : alternate.endpoints) {
    uint8_t endpoint_number = endpoint->endpoint_number;
    if (endpoint_number == 0 || endpoint_number >= 16)
      continue;  // Ignore endpoints with invalid indices.
    auto& bit_vector = endpoint->direction == UsbTransferDirection::INBOUND
                           ? in_endpoints_
                           : out_endpoints_;
    if (set)
      bit_vector.Set(endpoint_number - 1);
    else
      bit_vector.Clear(endpoint_number - 1);
  }
}

void USBDevice::AsyncOpen(ScriptPromiseResolver* resolver,
                          UsbOpenDeviceError error) {
  if (!MarkRequestComplete(resolver))
    return;

  switch (error) {
    case UsbOpenDeviceError::ALREADY_OPEN:
      NOTREACHED();
      FALLTHROUGH;
    case UsbOpenDeviceError::OK:
      OnDeviceOpenedOrClosed(true /* opened */);
      resolver->Resolve();
      return;
    case UsbOpenDeviceError::ACCESS_DENIED:
      OnDeviceOpenedOrClosed(false /* not opened */);
      resolver->Reject(DOMException::Create(DOMExceptionCode::kSecurityError,
                                            "Access denied."));
      return;
  }
}

void USBDevice::AsyncClose(ScriptPromiseResolver* resolver) {
  if (!MarkRequestComplete(resolver))
    return;

  OnDeviceOpenedOrClosed(false /* closed */);
  resolver->Resolve();
}

void USBDevice::OnDeviceOpenedOrClosed(bool opened) {
  opened_ = opened;
  if (!opened_) {
    claimed_interfaces_.ClearAll();
    selected_alternates_.Fill(0);
    in_endpoints_.ClearAll();
    out_endpoints_.ClearAll();
  }
  device_state_change_in_progress_ = false;
}

void USBDevice::AsyncSelectConfiguration(size_t configuration_index,
                                         ScriptPromiseResolver* resolver,
                                         bool success) {
  if (!MarkRequestComplete(resolver))
    return;

  OnConfigurationSelected(success, configuration_index);
  if (success) {
    resolver->Resolve();
  } else {
    resolver->Reject(
        DOMException::Create(DOMExceptionCode::kNetworkError,
                             "Unable to set device configuration."));
  }
}

void USBDevice::OnConfigurationSelected(bool success,
                                        size_t configuration_index) {
  if (success) {
    configuration_index_ = configuration_index;
    size_t num_interfaces =
        Info().configurations[configuration_index_]->interfaces.size();
    claimed_interfaces_.ClearAll();
    claimed_interfaces_.Resize(num_interfaces);
    interface_state_change_in_progress_.ClearAll();
    interface_state_change_in_progress_.Resize(num_interfaces);
    selected_alternates_.resize(num_interfaces);
    selected_alternates_.Fill(0);
    in_endpoints_.ClearAll();
    out_endpoints_.ClearAll();
  }
  device_state_change_in_progress_ = false;
}

void USBDevice::AsyncClaimInterface(size_t interface_index,
                                    ScriptPromiseResolver* resolver,
                                    bool success) {
  if (!MarkRequestComplete(resolver))
    return;

  OnInterfaceClaimedOrUnclaimed(success, interface_index);
  if (success) {
    resolver->Resolve();
  } else {
    resolver->Reject(DOMException::Create(DOMExceptionCode::kNetworkError,
                                          "Unable to claim interface."));
  }
}

void USBDevice::AsyncReleaseInterface(size_t interface_index,
                                      ScriptPromiseResolver* resolver,
                                      bool success) {
  if (!MarkRequestComplete(resolver))
    return;

  OnInterfaceClaimedOrUnclaimed(!success, interface_index);
  if (success) {
    resolver->Resolve();
  } else {
    resolver->Reject(DOMException::Create(DOMExceptionCode::kNetworkError,
                                          "Unable to release interface."));
  }
}

void USBDevice::OnInterfaceClaimedOrUnclaimed(bool claimed,
                                              size_t interface_index) {
  if (claimed) {
    claimed_interfaces_.Set(interface_index);
  } else {
    claimed_interfaces_.Clear(interface_index);
    selected_alternates_[interface_index] = 0;
  }
  SetEndpointsForInterface(interface_index, claimed);
  interface_state_change_in_progress_.Clear(interface_index);
}

void USBDevice::AsyncSelectAlternateInterface(size_t interface_index,
                                              size_t alternate_index,
                                              ScriptPromiseResolver* resolver,
                                              bool success) {
  if (!MarkRequestComplete(resolver))
    return;

  if (success)
    selected_alternates_[interface_index] = alternate_index;
  SetEndpointsForInterface(interface_index, success);
  interface_state_change_in_progress_.Clear(interface_index);

  if (success) {
    resolver->Resolve();
  } else {
    resolver->Reject(DOMException::Create(DOMExceptionCode::kNetworkError,
                                          "Unable to set device interface."));
  }
}

void USBDevice::AsyncControlTransferIn(ScriptPromiseResolver* resolver,
                                       UsbTransferStatus status,
                                       const Vector<uint8_t>& data) {
  if (!MarkRequestComplete(resolver))
    return;

  DOMException* error = ConvertFatalTransferStatus(status);
  if (error) {
    resolver->Reject(error);
  } else {
    resolver->Resolve(
        USBInTransferResult::Create(ConvertTransferStatus(status), data));
  }
}

void USBDevice::AsyncControlTransferOut(unsigned transfer_length,
                                        ScriptPromiseResolver* resolver,
                                        UsbTransferStatus status) {
  if (!MarkRequestComplete(resolver))
    return;

  DOMException* error = ConvertFatalTransferStatus(status);
  if (error) {
    resolver->Reject(error);
  } else {
    resolver->Resolve(USBOutTransferResult::Create(
        ConvertTransferStatus(status), transfer_length));
  }
}

void USBDevice::AsyncClearHalt(ScriptPromiseResolver* resolver, bool success) {
  if (!MarkRequestComplete(resolver))
    return;

  if (success) {
    resolver->Resolve();
  } else {
    resolver->Reject(DOMException::Create(DOMExceptionCode::kNetworkError,
                                          "Unable to clear endpoint."));
  }
}

void USBDevice::AsyncTransferIn(ScriptPromiseResolver* resolver,
                                UsbTransferStatus status,
                                const Vector<uint8_t>& data) {
  if (!MarkRequestComplete(resolver))
    return;

  DOMException* error = ConvertFatalTransferStatus(status);
  if (error) {
    resolver->Reject(error);
  } else {
    resolver->Resolve(
        USBInTransferResult::Create(ConvertTransferStatus(status), data));
  }
}

void USBDevice::AsyncTransferOut(unsigned transfer_length,
                                 ScriptPromiseResolver* resolver,
                                 UsbTransferStatus status) {
  if (!MarkRequestComplete(resolver))
    return;

  DOMException* error = ConvertFatalTransferStatus(status);
  if (error) {
    resolver->Reject(error);
  } else {
    resolver->Resolve(USBOutTransferResult::Create(
        ConvertTransferStatus(status), transfer_length));
  }
}

void USBDevice::AsyncIsochronousTransferIn(
    ScriptPromiseResolver* resolver,
    const Vector<uint8_t>& data,
    Vector<UsbIsochronousPacketPtr> mojo_packets) {
  if (!MarkRequestComplete(resolver))
    return;

  DOMArrayBuffer* buffer = DOMArrayBuffer::Create(data.data(), data.size());
  HeapVector<Member<USBIsochronousInTransferPacket>> packets;
  packets.ReserveCapacity(mojo_packets.size());
  size_t byte_offset = 0;
  for (const auto& packet : mojo_packets) {
    DOMException* error = ConvertFatalTransferStatus(packet->status);
    if (error) {
      resolver->Reject(error);
      return;
    }
    DOMDataView* data_view = nullptr;
    if (buffer) {
      data_view =
          DOMDataView::Create(buffer, byte_offset, packet->transferred_length);
    }
    packets.push_back(USBIsochronousInTransferPacket::Create(
        ConvertTransferStatus(packet->status), data_view));
    byte_offset += packet->length;
  }
  resolver->Resolve(USBIsochronousInTransferResult::Create(buffer, packets));
}

void USBDevice::AsyncIsochronousTransferOut(
    ScriptPromiseResolver* resolver,
    Vector<UsbIsochronousPacketPtr> mojo_packets) {
  if (!MarkRequestComplete(resolver))
    return;

  HeapVector<Member<USBIsochronousOutTransferPacket>> packets;
  packets.ReserveCapacity(mojo_packets.size());
  for (const auto& packet : mojo_packets) {
    DOMException* error = ConvertFatalTransferStatus(packet->status);
    if (error) {
      resolver->Reject(error);
      return;
    }
    packets.push_back(USBIsochronousOutTransferPacket::Create(
        ConvertTransferStatus(packet->status), packet->transferred_length));
  }
  resolver->Resolve(USBIsochronousOutTransferResult::Create(packets));
}

void USBDevice::AsyncReset(ScriptPromiseResolver* resolver, bool success) {
  if (!MarkRequestComplete(resolver))
    return;

  if (success) {
    resolver->Resolve();
  } else {
    resolver->Reject(DOMException::Create(DOMExceptionCode::kNetworkError,
                                          "Unable to reset the device."));
  }
}

void USBDevice::OnConnectionError() {
  device_.reset();
  opened_ = false;
  for (ScriptPromiseResolver* resolver : device_requests_) {
    resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
                                          kDeviceDisconnected));
  }
  device_requests_.clear();
}

bool USBDevice::MarkRequestComplete(ScriptPromiseResolver* resolver) {
  auto request_entry = device_requests_.find(resolver);
  if (request_entry == device_requests_.end())
    return false;
  device_requests_.erase(request_entry);
  return true;
}

}  // namespace blink
