// Copyright 2014 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 "extensions/browser/api/usb/usb_api.h"

#include <algorithm>
#include <memory>
#include <numeric>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/memory/ref_counted_memory.h"
#include "base/values.h"
#include "extensions/browser/api/device_permissions_manager.h"
#include "extensions/browser/api/device_permissions_prompt.h"
#include "extensions/browser/api/extensions_api_client.h"
#include "extensions/browser/api/usb/usb_device_resource.h"
#include "extensions/browser/extension_function_constants.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/api/usb.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/permissions/usb_device_permission.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "services/device/public/cpp/usb/usb_utils.h"
#include "services/device/public/mojom/usb_device.mojom.h"
#include "services/device/public/mojom/usb_enumeration_options.mojom.h"
#include "services/device/public/mojom/usb_manager.mojom.h"

namespace usb = extensions::api::usb;
namespace BulkTransfer = usb::BulkTransfer;
namespace ClaimInterface = usb::ClaimInterface;
namespace CloseDevice = usb::CloseDevice;
namespace ControlTransfer = usb::ControlTransfer;
namespace FindDevices = usb::FindDevices;
namespace GetConfigurations = usb::GetConfigurations;
namespace GetDevices = usb::GetDevices;
namespace GetUserSelectedDevices = usb::GetUserSelectedDevices;
namespace InterruptTransfer = usb::InterruptTransfer;
namespace IsochronousTransfer = usb::IsochronousTransfer;
namespace SetConfiguration = usb::SetConfiguration;
namespace GetConfiguration = usb::GetConfiguration;
namespace ListInterfaces = usb::ListInterfaces;
namespace OpenDevice = usb::OpenDevice;
namespace ReleaseInterface = usb::ReleaseInterface;
namespace RequestAccess = usb::RequestAccess;
namespace ResetDevice = usb::ResetDevice;
namespace SetInterfaceAlternateSetting = usb::SetInterfaceAlternateSetting;

using content::BrowserThread;
using device::mojom::UsbClaimInterfaceResult;
using device::mojom::UsbControlTransferParams;
using device::mojom::UsbControlTransferRecipient;
using device::mojom::UsbControlTransferType;
using device::mojom::UsbDeviceFilterPtr;
using device::mojom::UsbIsochronousPacketPtr;
using device::mojom::UsbSynchronizationType;
using device::mojom::UsbTransferDirection;
using device::mojom::UsbTransferStatus;
using device::mojom::UsbTransferType;
using device::mojom::UsbUsageType;
using std::string;
using std::vector;
using usb::ConfigDescriptor;
using usb::ConnectionHandle;
using usb::ControlTransferInfo;
using usb::Device;
using usb::Direction;
using usb::EndpointDescriptor;
using usb::GenericTransferInfo;
using usb::InterfaceDescriptor;
using usb::IsochronousTransferInfo;
using usb::Recipient;
using usb::RequestType;
using usb::SynchronizationType;
using usb::TransferType;
using usb::UsageType;

namespace extensions {

namespace {

const char kDataKey[] = "data";
const char kResultCodeKey[] = "resultCode";

const char kErrorInitService[] = "Failed to initialize USB service.";

const char kErrorOpen[] = "Failed to open device.";
const char kErrorCancelled[] = "Transfer was cancelled.";
const char kErrorDisconnect[] = "Device disconnected.";
const char kErrorGeneric[] = "Transfer failed.";
const char kErrorNotSupported[] = "Not supported on this platform.";
const char kErrorNotConfigured[] = "The device is not in a configured state.";
const char kErrorOverflow[] = "Inbound transfer overflow.";
const char kErrorStalled[] = "Transfer stalled.";
const char kErrorTimeout[] = "Transfer timed out.";
const char kErrorTransferLength[] = "Transfer length is insufficient.";
const char kErrorCannotSetConfiguration[] =
    "Error setting device configuration.";
const char kErrorCannotClaimInterface[] = "Error claiming interface.";
const char kErrorCannotReleaseInterface[] = "Error releasing interface.";
const char kErrorCannotSetInterfaceAlternateSetting[] =
    "Error setting alternate interface setting.";
const char kErrorConvertDirection[] = "Invalid transfer direction.";
const char kErrorConvertRecipient[] = "Invalid transfer recipient.";
const char kErrorConvertRequestType[] = "Invalid request type.";
const char kErrorMalformedParameters[] = "Error parsing parameters.";
const char kErrorNoConnection[] = "No such connection.";
const char kErrorNoDevice[] = "No such device.";
const char kErrorPermissionDenied[] = "Permission to access device was denied";
const char kErrorInvalidTransferLength[] =
    "Transfer length must be a positive number less than 104,857,600.";
const char kErrorInvalidNumberOfPackets[] =
    "Number of packets must be a positive number less than 4,194,304.";
const char kErrorInvalidPacketLength[] =
    "Packet length must be a positive number less than 65,536.";
const char kErrorInvalidTimeout[] =
    "Transfer timeout must be greater than or equal to 0.";
const char kErrorResetDevice[] =
    "Error resetting the device. The device has been closed.";

const size_t kMaxTransferLength = 100 * 1024 * 1024;
const int kMaxPackets = 4 * 1024 * 1024;
const int kMaxPacketLength = 64 * 1024;

bool ConvertDirectionFromApi(const Direction& input,
                             UsbTransferDirection* output) {
  switch (input) {
    case usb::DIRECTION_IN:
      *output = UsbTransferDirection::INBOUND;
      return true;
    case usb::DIRECTION_OUT:
      *output = UsbTransferDirection::OUTBOUND;
      return true;
    default:
      NOTREACHED();
      return false;
  }
}

bool ConvertRequestTypeFromApi(const RequestType& input,
                               UsbControlTransferType* output) {
  switch (input) {
    case usb::REQUEST_TYPE_STANDARD:
      *output = UsbControlTransferType::STANDARD;
      return true;
    case usb::REQUEST_TYPE_CLASS:
      *output = UsbControlTransferType::CLASS;
      return true;
    case usb::REQUEST_TYPE_VENDOR:
      *output = UsbControlTransferType::VENDOR;
      return true;
    case usb::REQUEST_TYPE_RESERVED:
      *output = UsbControlTransferType::RESERVED;
      return true;
    default:
      NOTREACHED();
      return false;
  }
}

bool ConvertRecipientFromApi(const Recipient& input,
                             UsbControlTransferRecipient* output) {
  switch (input) {
    case usb::RECIPIENT_DEVICE:
      *output = UsbControlTransferRecipient::DEVICE;
      return true;
    case usb::RECIPIENT_INTERFACE:
      *output = UsbControlTransferRecipient::INTERFACE;
      return true;
    case usb::RECIPIENT_ENDPOINT:
      *output = UsbControlTransferRecipient::ENDPOINT;
      return true;
    case usb::RECIPIENT_OTHER:
      *output = UsbControlTransferRecipient::OTHER;
      return true;
    default:
      NOTREACHED();
      return false;
  }
}

template <class T>
bool GetTransferInSize(const T& input, uint32_t* output) {
  const int* length = input.length.get();
  if (length && *length >= 0 &&
      static_cast<uint32_t>(*length) < kMaxTransferLength) {
    *output = *length;
    return true;
  }
  return false;
}

const char* ConvertTransferStatusToApi(const UsbTransferStatus status) {
  switch (status) {
    case UsbTransferStatus::COMPLETED:
      return "";
    case UsbTransferStatus::TRANSFER_ERROR:
      return kErrorGeneric;
    case UsbTransferStatus::TIMEOUT:
      return kErrorTimeout;
    case UsbTransferStatus::CANCELLED:
      return kErrorCancelled;
    case UsbTransferStatus::STALLED:
      return kErrorStalled;
    case UsbTransferStatus::DISCONNECT:
      return kErrorDisconnect;
    case UsbTransferStatus::BABBLE:
      return kErrorOverflow;
    case UsbTransferStatus::SHORT_PACKET:
      return kErrorTransferLength;
    default:
      NOTREACHED();
      return "";
  }
}

std::unique_ptr<base::Value> PopulateConnectionHandle(int handle,
                                                      int vendor_id,
                                                      int product_id) {
  ConnectionHandle result;
  result.handle = handle;
  result.vendor_id = vendor_id;
  result.product_id = product_id;
  return result.ToValue();
}

TransferType ConvertTransferTypeToApi(const UsbTransferType& input) {
  switch (input) {
    case UsbTransferType::CONTROL:
      return usb::TRANSFER_TYPE_CONTROL;
    case UsbTransferType::INTERRUPT:
      return usb::TRANSFER_TYPE_INTERRUPT;
    case UsbTransferType::ISOCHRONOUS:
      return usb::TRANSFER_TYPE_ISOCHRONOUS;
    case UsbTransferType::BULK:
      return usb::TRANSFER_TYPE_BULK;
    default:
      NOTREACHED();
      return usb::TRANSFER_TYPE_NONE;
  }
}

Direction ConvertDirectionToApi(const UsbTransferDirection& input) {
  switch (input) {
    case UsbTransferDirection::INBOUND:
      return usb::DIRECTION_IN;
    case UsbTransferDirection::OUTBOUND:
      return usb::DIRECTION_OUT;
    default:
      NOTREACHED();
      return usb::DIRECTION_NONE;
  }
}

SynchronizationType ConvertSynchronizationTypeToApi(
    const UsbSynchronizationType& input) {
  switch (input) {
    case UsbSynchronizationType::NONE:
      return usb::SYNCHRONIZATION_TYPE_NONE;
    case UsbSynchronizationType::ASYNCHRONOUS:
      return usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS;
    case UsbSynchronizationType::ADAPTIVE:
      return usb::SYNCHRONIZATION_TYPE_ADAPTIVE;
    case UsbSynchronizationType::SYNCHRONOUS:
      return usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS;
    default:
      NOTREACHED();
      return usb::SYNCHRONIZATION_TYPE_NONE;
  }
}

usb::UsageType ConvertUsageTypeToApi(const UsbUsageType& input) {
  switch (input) {
    case UsbUsageType::DATA:
      return usb::USAGE_TYPE_DATA;
    case UsbUsageType::FEEDBACK:
      return usb::USAGE_TYPE_FEEDBACK;
    case UsbUsageType::EXPLICIT_FEEDBACK:
      return usb::USAGE_TYPE_EXPLICITFEEDBACK;
    case UsbUsageType::PERIODIC:
      return usb::USAGE_TYPE_PERIODIC;
    case UsbUsageType::NOTIFICATION:
      return usb::USAGE_TYPE_NOTIFICATION;
    case UsbUsageType::RESERVED:
      return usb::USAGE_TYPE_NONE;
    default:
      NOTREACHED();
      return usb::USAGE_TYPE_NONE;
  }
}

EndpointDescriptor ConvertEndpointDescriptor(
    const device::mojom::UsbEndpointInfo& input) {
  EndpointDescriptor output;
  output.address = device::ConvertEndpointNumberToAddress(input);
  output.type = ConvertTransferTypeToApi(input.type);
  output.direction = ConvertDirectionToApi(input.direction);
  output.maximum_packet_size = input.packet_size;
  output.synchronization =
      ConvertSynchronizationTypeToApi(input.synchronization_type);
  output.usage = ConvertUsageTypeToApi(input.usage_type);
  output.polling_interval = std::make_unique<int>(input.polling_interval);
  output.extra_data.assign(input.extra_data.begin(), input.extra_data.end());
  return output;
}

InterfaceDescriptor ConvertInterfaceDescriptor(
    uint8_t interface_number,
    const device::mojom::UsbAlternateInterfaceInfo& input) {
  InterfaceDescriptor output;
  output.interface_number = interface_number;
  output.alternate_setting = input.alternate_setting;
  output.interface_class = input.class_code;
  output.interface_subclass = input.subclass_code;
  output.interface_protocol = input.protocol_code;
  for (const auto& input_endpoint : input.endpoints) {
    DCHECK(input_endpoint);
    output.endpoints.push_back(ConvertEndpointDescriptor(*input_endpoint));
  }
  output.extra_data.assign(input.extra_data.begin(), input.extra_data.end());
  return output;
}

ConfigDescriptor ConvertConfigDescriptor(
    const device::mojom::UsbConfigurationInfo& input) {
  ConfigDescriptor output;
  output.configuration_value = input.configuration_value;
  output.self_powered = input.self_powered;
  output.remote_wakeup = input.remote_wakeup;
  output.max_power = input.maximum_power;
  for (const auto& input_interface : input.interfaces) {
    DCHECK(input_interface);
    // device::mojom::UsbInterfaceInfo aggregated all alternate settings
    // with the same interface number.
    for (const auto& alternate : input_interface->alternates) {
      DCHECK(alternate);
      output.interfaces.push_back(ConvertInterfaceDescriptor(
          input_interface->interface_number, *alternate));
    }
  }
  output.extra_data.assign(input.extra_data.begin(), input.extra_data.end());
  return output;
}

device::mojom::UsbDeviceFilterPtr ConvertDeviceFilter(
    const usb::DeviceFilter& input) {
  auto output = device::mojom::UsbDeviceFilter::New();
  if (input.vendor_id) {
    output->has_vendor_id = true;
    output->vendor_id = *input.vendor_id;
  }
  if (input.product_id) {
    output->has_product_id = true;
    output->product_id = *input.product_id;
  }
  if (input.interface_class) {
    output->has_class_code = true;
    output->class_code = *input.interface_class;
  }
  if (input.interface_subclass) {
    output->has_subclass_code = true;
    output->subclass_code = *input.interface_subclass;
  }
  if (input.interface_protocol) {
    output->has_protocol_code = true;
    output->protocol_code = *input.interface_protocol;
  }
  return output;
}

}  // namespace

UsbExtensionFunction::UsbExtensionFunction() = default;
UsbExtensionFunction::~UsbExtensionFunction() = default;

UsbDeviceManager* UsbExtensionFunction::usb_device_manager() {
  if (!usb_device_manager_) {
    usb_device_manager_ = UsbDeviceManager::Get(browser_context());
  }

  return usb_device_manager_;
}

UsbPermissionCheckingFunction::UsbPermissionCheckingFunction()
    : device_permissions_manager_(nullptr) {}

UsbPermissionCheckingFunction::~UsbPermissionCheckingFunction() = default;

bool UsbPermissionCheckingFunction::HasDevicePermission(
    const device::mojom::UsbDeviceInfo& device) {
  if (!device_permissions_manager_) {
    device_permissions_manager_ =
        DevicePermissionsManager::Get(browser_context());
  }

  DevicePermissions* device_permissions =
      device_permissions_manager_->GetForExtension(extension_id());
  DCHECK(device_permissions);

  permission_entry_ = device_permissions->FindUsbDeviceEntry(device);
  if (permission_entry_.get()) {
    return true;
  }

  std::unique_ptr<UsbDevicePermission::CheckParam> param =
      UsbDevicePermission::CheckParam::ForUsbDevice(extension(), device);
  if (extension()->permissions_data()->CheckAPIPermissionWithParam(
          mojom::APIPermissionID::kUsbDevice, param.get())) {
    return true;
  }

  return false;
}

void UsbPermissionCheckingFunction::RecordDeviceLastUsed() {
  if (permission_entry_.get()) {
    device_permissions_manager_->UpdateLastUsed(extension_id(),
                                                permission_entry_);
  }
}

UsbConnectionFunction::UsbConnectionFunction() = default;
UsbConnectionFunction::~UsbConnectionFunction() = default;

UsbDeviceResource* UsbConnectionFunction::GetResourceFromHandle(
    const ConnectionHandle& handle) {
  ApiResourceManager<UsbDeviceResource>* manager =
      ApiResourceManager<UsbDeviceResource>::Get(browser_context());
  if (!manager) {
    return nullptr;
  }
  return manager->Get(extension_id(), handle.handle);
}

device::mojom::UsbDevice* UsbConnectionFunction::GetDeviceFromHandle(
    const ConnectionHandle& handle) {
  UsbDeviceResource* resource = GetResourceFromHandle(handle);
  if (!resource) {
    return nullptr;
  }

  return resource->device();
}

const device::mojom::UsbDeviceInfo*
UsbConnectionFunction::GetDeviceInfoFromHandle(const ConnectionHandle& handle) {
  UsbDeviceResource* resource = GetResourceFromHandle(handle);
  if (!resource || !resource->device()) {
    return nullptr;
  }

  auto* device_manager = usb_device_manager();
  if (!device_manager) {
    return nullptr;
  }

  return device_manager->GetDeviceInfo(resource->guid());
}

void UsbConnectionFunction::ReleaseDeviceResource(
    const ConnectionHandle& handle) {
  ApiResourceManager<UsbDeviceResource>* manager =
      ApiResourceManager<UsbDeviceResource>::Get(browser_context());
  manager->Remove(extension_id(), handle.handle);
}

UsbTransferFunction::UsbTransferFunction() = default;
UsbTransferFunction::~UsbTransferFunction() = default;

void UsbTransferFunction::OnCompleted(
    UsbTransferStatus status,
    std::unique_ptr<base::DictionaryValue> transfer_info) {
  if (status == UsbTransferStatus::COMPLETED) {
    Respond(
        OneArgument(base::Value::FromUniquePtrValue(std::move(transfer_info))));
  } else {
    auto error_args = std::make_unique<base::ListValue>();
    error_args->Append(std::move(transfer_info));
    // Using ErrorWithArguments is discouraged but required to provide the
    // detailed transfer info as the transfer may have partially succeeded.
    Respond(ErrorWithArguments(std::move(error_args),
                               ConvertTransferStatusToApi(status)));
  }
}

void UsbTransferFunction::OnTransferInCompleted(
    UsbTransferStatus status,
    base::span<const uint8_t> data) {
  base::Value transfer_info(base::Value::Type::DICTIONARY);
  transfer_info.SetIntKey(kResultCodeKey, static_cast<int>(status));
  transfer_info.SetKey(kDataKey, base::Value(data));

  OnCompleted(status, base::DictionaryValue::From(base::Value::ToUniquePtrValue(
                          std::move(transfer_info))));
}

void UsbTransferFunction::OnTransferOutCompleted(UsbTransferStatus status) {
  auto transfer_info = std::make_unique<base::DictionaryValue>();
  transfer_info->SetInteger(kResultCodeKey, static_cast<int>(status));
  transfer_info->SetKey(kDataKey, base::Value(base::Value::Type::BINARY));

  OnCompleted(status, std::move(transfer_info));
}

void UsbTransferFunction::OnDisconnect() {
  const auto status = UsbTransferStatus::DISCONNECT;
  auto transfer_info = std::make_unique<base::DictionaryValue>();
  transfer_info->SetInteger(kResultCodeKey, static_cast<int>(status));
  OnCompleted(status, std::move(transfer_info));
}

UsbGenericTransferFunction::UsbGenericTransferFunction() = default;
UsbGenericTransferFunction::~UsbGenericTransferFunction() = default;

// const usb::InterruptTransfer::Params* or
// const usb::BulkTransfer::Params*
template <typename T>
ExtensionFunction::ResponseAction UsbGenericTransferFunction::DoTransfer(
    T params) {
  device::mojom::UsbDevice* device = GetDeviceFromHandle(params->handle);
  if (!device) {
    return RespondNow(Error(kErrorNoConnection));
  }

  const GenericTransferInfo& transfer = params->transfer_info;
  UsbTransferDirection direction = UsbTransferDirection::INBOUND;

  if (!ConvertDirectionFromApi(transfer.direction, &direction)) {
    return RespondNow(Error(kErrorConvertDirection));
  }

  int timeout = transfer.timeout ? *transfer.timeout : 0;
  if (timeout < 0) {
    return RespondNow(Error(kErrorInvalidTimeout));
  }

  if (direction == UsbTransferDirection::INBOUND) {
    uint32_t size = 0;
    if (!GetTransferInSize(transfer, &size)) {
      return RespondNow(Error(kErrorInvalidTransferLength));
    }

    device->GenericTransferIn(
        transfer.endpoint, size, timeout,
        mojo::WrapCallbackWithDropHandler(
            base::BindOnce(&UsbGenericTransferFunction::OnTransferInCompleted,
                           this),
            base::BindOnce(&UsbGenericTransferFunction::OnDisconnect, this)));
  } else {
    // For case direction == UsbTransferDirection::OUTBOUND.
    if (!transfer.data) {
      return RespondNow(Error(kErrorMalformedParameters));
    }

    device->GenericTransferOut(
        transfer.endpoint, *transfer.data, timeout,
        mojo::WrapCallbackWithDropHandler(
            base::BindOnce(&UsbGenericTransferFunction::OnTransferOutCompleted,
                           this),
            base::BindOnce(&UsbGenericTransferFunction::OnDisconnect, this)));
  }
  return RespondLater();
}

UsbFindDevicesFunction::UsbFindDevicesFunction() = default;
UsbFindDevicesFunction::~UsbFindDevicesFunction() = default;

ExtensionFunction::ResponseAction UsbFindDevicesFunction::Run() {
  std::unique_ptr<usb::FindDevices::Params> parameters =
      FindDevices::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());

  vendor_id_ = parameters->options.vendor_id;
  product_id_ = parameters->options.product_id;
  int interface_id = parameters->options.interface_id.get()
                         ? *parameters->options.interface_id
                         : UsbDevicePermissionData::SPECIAL_VALUE_ANY;
  // Bail out early if there is no chance that the app has manifest permission
  // for the USB device described by vendor ID, product ID, and interface ID.
  // Note that this will match any permission filter that has only interface
  // class specified - in order to match interface class information about
  // device interfaces is needed, which is not known at this point; the
  // permission will have to be checked again when the USB device info is
  // fetched.
  std::unique_ptr<UsbDevicePermission::CheckParam> param =
      UsbDevicePermission::CheckParam::ForDeviceWithAnyInterfaceClass(
          extension(), vendor_id_, product_id_, interface_id);
  if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
          mojom::APIPermissionID::kUsbDevice, param.get())) {
    return RespondNow(Error(kErrorPermissionDenied));
  }

  auto* device_manager = usb_device_manager();
  if (!device_manager) {
    return RespondNow(Error(kErrorInitService));
  }

  device_manager->GetDevices(
      base::BindOnce(&UsbFindDevicesFunction::OnGetDevicesComplete, this));
  return RespondLater();
}

void UsbFindDevicesFunction::OnGetDevicesComplete(
    std::vector<device::mojom::UsbDeviceInfoPtr> devices) {
  result_ = std::make_unique<base::ListValue>();
  barrier_ = base::BarrierClosure(
      devices.size(),
      base::BindOnce(&UsbFindDevicesFunction::OpenComplete, this));

  for (const auto& device_info : devices) {
    // Skip the device whose vendor and product ID do not match the target one.
    if (device_info->vendor_id != vendor_id_ ||
        device_info->product_id != product_id_) {
      barrier_.Run();
      continue;
    }

    // Verify that the app has permission for the device again, this time taking
    // device's interface classes into account - in case there is a USB device
    // permission specifying only interfaceClass, permissions check in |Run|
    // might have passed even though the app did not have permission for
    // specified vendor and product ID (as actual permissions check had to be
    // deferred until device's interface classes are known).
    std::unique_ptr<UsbDevicePermission::CheckParam> param =
        UsbDevicePermission::CheckParam::ForUsbDevice(extension(),
                                                      *device_info);
    if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
            mojom::APIPermissionID::kUsbDevice, param.get())) {
      barrier_.Run();
    } else {
      mojo::Remote<device::mojom::UsbDevice> device;
      usb_device_manager()->GetDevice(device_info->guid,
                                      device.BindNewPipeAndPassReceiver());
      auto* device_raw = device.get();
      device_raw->Open(mojo::WrapCallbackWithDropHandler(
          base::BindOnce(&UsbFindDevicesFunction::OnDeviceOpened, this,
                         device_info->guid, std::move(device)),
          base::BindOnce(&UsbFindDevicesFunction::OnDisconnect, this)));
    }
  }
}

void UsbFindDevicesFunction::OnDeviceOpened(
    const std::string& guid,
    mojo::Remote<device::mojom::UsbDevice> device,
    device::mojom::UsbOpenDeviceError error) {
  if (error == device::mojom::UsbOpenDeviceError::OK && device) {
    ApiResourceManager<UsbDeviceResource>* manager =
        ApiResourceManager<UsbDeviceResource>::Get(browser_context());
    UsbDeviceResource* resource =
        new UsbDeviceResource(extension_id(), guid, std::move(device));
    result_->Append(PopulateConnectionHandle(manager->Add(resource), vendor_id_,
                                             product_id_));
  }
  barrier_.Run();
}

void UsbFindDevicesFunction::OnDisconnect() {
  barrier_.Run();
}

void UsbFindDevicesFunction::OpenComplete() {
  Respond(OneArgument(base::Value::FromUniquePtrValue(std::move(result_))));
}

UsbGetDevicesFunction::UsbGetDevicesFunction() = default;
UsbGetDevicesFunction::~UsbGetDevicesFunction() = default;

ExtensionFunction::ResponseAction UsbGetDevicesFunction::Run() {
  std::unique_ptr<usb::GetDevices::Params> parameters =
      GetDevices::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());

  if (parameters->options.filters) {
    filters_.reserve(parameters->options.filters->size());
    for (const auto& filter : *parameters->options.filters)
      filters_.push_back(ConvertDeviceFilter(filter));
  }
  if (parameters->options.vendor_id) {
    auto filter = device::mojom::UsbDeviceFilter::New();
    filter->has_vendor_id = true;
    filter->vendor_id = *parameters->options.vendor_id;
    if (parameters->options.product_id) {
      filter->has_product_id = true;
      filter->product_id = *parameters->options.product_id;
    }
    filters_.push_back(std::move(filter));
  }

  auto* device_manager = usb_device_manager();
  if (!device_manager) {
    return RespondNow(Error(kErrorInitService));
  }

  device_manager->GetDevices(
      base::BindOnce(&UsbGetDevicesFunction::OnGetDevicesComplete, this));
  return RespondLater();
}

void UsbGetDevicesFunction::OnGetDevicesComplete(
    std::vector<device::mojom::UsbDeviceInfoPtr> devices) {
  std::unique_ptr<base::ListValue> result(new base::ListValue());
  for (const auto& device : devices) {
    if (device::UsbDeviceFilterMatchesAny(filters_, *device) &&
        HasDevicePermission(*device)) {
      Device api_device;
      usb_device_manager()->GetApiDevice(*device, &api_device);
      result->Append(api_device.ToValue());
    }
  }

  Respond(OneArgument(base::Value::FromUniquePtrValue(std::move(result))));
}

UsbGetUserSelectedDevicesFunction::UsbGetUserSelectedDevicesFunction() =
    default;
UsbGetUserSelectedDevicesFunction::~UsbGetUserSelectedDevicesFunction() =
    default;

ExtensionFunction::ResponseAction UsbGetUserSelectedDevicesFunction::Run() {
  std::unique_ptr<usb::GetUserSelectedDevices::Params> parameters =
      GetUserSelectedDevices::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());

  if (!user_gesture()) {
    return RespondNow(OneArgument(base::Value(base::Value::Type::LIST)));
  }

  bool multiple = false;
  if (parameters->options.multiple) {
    multiple = *parameters->options.multiple;
  }

  std::vector<UsbDeviceFilterPtr> filters;
  if (parameters->options.filters) {
    filters.reserve(parameters->options.filters->size());
    for (const auto& filter : *parameters->options.filters)
      filters.push_back(ConvertDeviceFilter(filter));
  }

  content::WebContents* web_contents = GetSenderWebContents();
  if (!web_contents) {
    return RespondNow(
        Error(function_constants::kCouldNotFindSenderWebContents));
  }

  prompt_ =
      ExtensionsAPIClient::Get()->CreateDevicePermissionsPrompt(web_contents);
  if (!prompt_) {
    return RespondNow(Error(kErrorNotSupported));
  }

  prompt_->AskForUsbDevices(
      extension(), browser_context(), multiple, std::move(filters),
      base::BindOnce(&UsbGetUserSelectedDevicesFunction::OnDevicesChosen,
                     this));
  return RespondLater();
}

void UsbGetUserSelectedDevicesFunction::OnDevicesChosen(
    std::vector<device::mojom::UsbDeviceInfoPtr> devices) {
  std::unique_ptr<base::ListValue> result(new base::ListValue());
  auto* device_manager = usb_device_manager();
  DCHECK(device_manager);

  for (const auto& device : devices) {
    Device api_device;
    device_manager->GetApiDevice(*device, &api_device);
    result->Append(api_device.ToValue());
  }

  Respond(OneArgument(base::Value::FromUniquePtrValue(std::move(result))));
}

UsbGetConfigurationsFunction::UsbGetConfigurationsFunction() = default;
UsbGetConfigurationsFunction::~UsbGetConfigurationsFunction() = default;

ExtensionFunction::ResponseAction UsbGetConfigurationsFunction::Run() {
  std::unique_ptr<usb::GetConfigurations::Params> parameters =
      GetConfigurations::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());

  auto* device_manager = usb_device_manager();
  if (!device_manager) {
    return RespondNow(Error(kErrorInitService));
  }

  std::string guid;
  if (!device_manager->GetGuidFromId(parameters->device.device, &guid)) {
    return RespondNow(Error(kErrorNoDevice));
  }

  const auto* device_info = device_manager->GetDeviceInfo(guid);
  if (!device_info) {
    return RespondNow(Error(kErrorNoDevice));
  }

  if (!HasDevicePermission(*device_info)) {
    // This function must act as if there is no such device. Otherwise it can be
    // used to fingerprint unauthorized devices.
    return RespondNow(Error(kErrorNoDevice));
  }

  std::unique_ptr<base::ListValue> configs(new base::ListValue());
  uint8_t active_config_value = device_info->active_configuration;
  for (const auto& config : device_info->configurations) {
    DCHECK(config);
    ConfigDescriptor api_config = ConvertConfigDescriptor(*config);
    if (active_config_value &&
        config->configuration_value == active_config_value) {
      api_config.active = true;
    }
    configs->Append(api_config.ToValue());
  }
  return RespondNow(
      OneArgument(base::Value::FromUniquePtrValue(std::move(configs))));
}

UsbRequestAccessFunction::UsbRequestAccessFunction() = default;
UsbRequestAccessFunction::~UsbRequestAccessFunction() = default;

ExtensionFunction::ResponseAction UsbRequestAccessFunction::Run() {
  std::unique_ptr<usb::RequestAccess::Params> parameters =
      RequestAccess::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());
  return RespondNow(OneArgument(base::Value(true)));
}

UsbOpenDeviceFunction::UsbOpenDeviceFunction() = default;
UsbOpenDeviceFunction::~UsbOpenDeviceFunction() = default;

ExtensionFunction::ResponseAction UsbOpenDeviceFunction::Run() {
  std::unique_ptr<usb::OpenDevice::Params> parameters =
      OpenDevice::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());

  auto* device_manager = usb_device_manager();
  if (!device_manager) {
    return RespondNow(Error(kErrorInitService));
  }

  std::string guid;
  if (!device_manager->GetGuidFromId(parameters->device.device, &guid)) {
    return RespondNow(Error(kErrorNoDevice));
  }

  const device::mojom::UsbDeviceInfo* device_info =
      device_manager->GetDeviceInfo(guid);
  if (!device_info) {
    return RespondNow(Error(kErrorNoDevice));
  }

  if (!HasDevicePermission(*device_info)) {
    // This function must act as if there is no such device. Otherwise it can be
    // used to fingerprint unauthorized devices.
    return RespondNow(Error(kErrorNoDevice));
  }

  mojo::Remote<device::mojom::UsbDevice> device;
  device_manager->GetDevice(device_info->guid,
                            device.BindNewPipeAndPassReceiver());
  auto* device_raw = device.get();
  device_raw->Open(mojo::WrapCallbackWithDropHandler(
      base::BindOnce(&UsbOpenDeviceFunction::OnDeviceOpened, this,
                     device_info->guid, std::move(device)),
      base::BindOnce(&UsbOpenDeviceFunction::OnDisconnect, this)));
  return RespondLater();
}

void UsbOpenDeviceFunction::OnDeviceOpened(
    std::string guid,
    mojo::Remote<device::mojom::UsbDevice> device,
    device::mojom::UsbOpenDeviceError error) {
  if (error != device::mojom::UsbOpenDeviceError::OK || !device) {
    Respond(Error(kErrorOpen));
    return;
  }

  RecordDeviceLastUsed();

  ApiResourceManager<UsbDeviceResource>* manager =
      ApiResourceManager<UsbDeviceResource>::Get(browser_context());
  const device::mojom::UsbDeviceInfo* device_info =
      usb_device_manager()->GetDeviceInfo(guid);
  DCHECK(device_info);
  UsbDeviceResource* resource = new UsbDeviceResource(
      extension_id(), device_info->guid, std::move(device));
  Respond(OneArgument(base::Value::FromUniquePtrValue(
      PopulateConnectionHandle(manager->Add(resource), device_info->vendor_id,
                               device_info->product_id))));
}

void UsbOpenDeviceFunction::OnDisconnect() {
  Respond(Error(kErrorDisconnect));
}

UsbSetConfigurationFunction::UsbSetConfigurationFunction() = default;
UsbSetConfigurationFunction::~UsbSetConfigurationFunction() = default;

ExtensionFunction::ResponseAction UsbSetConfigurationFunction::Run() {
  std::unique_ptr<usb::SetConfiguration::Params> parameters =
      SetConfiguration::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());

  UsbDeviceResource* resource = GetResourceFromHandle(parameters->handle);
  if (!resource || !resource->device()) {
    return RespondNow(Error(kErrorNoConnection));
  }

  if (parameters->configuration_value < 0) {
    return RespondNow(Error(kErrorMalformedParameters));
  }

  uint8_t config_value = parameters->configuration_value;
  resource->device()->SetConfiguration(
      config_value, mojo::WrapCallbackWithDefaultInvokeIfNotRun(
                        base::BindOnce(&UsbSetConfigurationFunction::OnComplete,
                                       this, resource->guid(), config_value),
                        false));
  return RespondLater();
}

void UsbSetConfigurationFunction::OnComplete(const std::string& guid,
                                             uint8_t config_value,
                                             bool success) {
  if (success) {
    bool updated_config =
        usb_device_manager()->UpdateActiveConfig(guid, config_value);
    DCHECK(updated_config);
    Respond(NoArguments());
  } else {
    Respond(Error(kErrorCannotSetConfiguration));
  }
}

UsbGetConfigurationFunction::UsbGetConfigurationFunction() = default;
UsbGetConfigurationFunction::~UsbGetConfigurationFunction() = default;

ExtensionFunction::ResponseAction UsbGetConfigurationFunction::Run() {
  std::unique_ptr<usb::GetConfiguration::Params> parameters =
      GetConfiguration::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());

  const device::mojom::UsbDeviceInfo* device_info =
      GetDeviceInfoFromHandle(parameters->handle);
  if (!device_info) {
    return RespondNow(Error(kErrorNoConnection));
  }

  uint8_t active_config_value = device_info->active_configuration;
  if (active_config_value) {
    for (const auto& config : device_info->configurations) {
      DCHECK(config);
      if (config->configuration_value == active_config_value) {
        ConfigDescriptor api_config = ConvertConfigDescriptor(*config);
        return RespondNow(
            OneArgument(base::Value::FromUniquePtrValue(api_config.ToValue())));
      }
    }
  }
  // Respond with an error if there is no active config or the config object
  // can't be found according to |active_config_value|.
  return RespondNow(Error(kErrorNotConfigured));
}

UsbListInterfacesFunction::UsbListInterfacesFunction() = default;
UsbListInterfacesFunction::~UsbListInterfacesFunction() = default;

ExtensionFunction::ResponseAction UsbListInterfacesFunction::Run() {
  std::unique_ptr<usb::ListInterfaces::Params> parameters =
      ListInterfaces::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());

  const device::mojom::UsbDeviceInfo* device_info =
      GetDeviceInfoFromHandle(parameters->handle);
  if (!device_info) {
    return RespondNow(Error(kErrorNoConnection));
  }

  uint8_t active_config_value = device_info->active_configuration;
  if (!active_config_value) {
    return RespondNow(Error(kErrorNotConfigured));
  }

  for (const auto& config : device_info->configurations) {
    DCHECK(config);
    if (config->configuration_value == active_config_value) {
      ConfigDescriptor api_config = ConvertConfigDescriptor(*config);
      std::unique_ptr<base::ListValue> result(new base::ListValue);
      for (size_t i = 0; i < api_config.interfaces.size(); ++i) {
        result->Append(api_config.interfaces[i].ToValue());
      }
      return RespondNow(
          OneArgument(base::Value::FromUniquePtrValue(std::move(result))));
    }
  }
  // Respond with an error if the config object can't be found according to
  // |active_config_value|.
  return RespondNow(Error(kErrorNotConfigured));
}

UsbCloseDeviceFunction::UsbCloseDeviceFunction() = default;
UsbCloseDeviceFunction::~UsbCloseDeviceFunction() = default;

ExtensionFunction::ResponseAction UsbCloseDeviceFunction::Run() {
  std::unique_ptr<usb::CloseDevice::Params> parameters =
      CloseDevice::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());

  device::mojom::UsbDevice* device = GetDeviceFromHandle(parameters->handle);
  if (!device) {
    return RespondNow(Error(kErrorNoConnection));
  }

  // The device handle is closed when the resource is destroyed.
  ReleaseDeviceResource(parameters->handle);
  return RespondNow(NoArguments());
}

UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() = default;
UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() = default;

ExtensionFunction::ResponseAction UsbClaimInterfaceFunction::Run() {
  std::unique_ptr<usb::ClaimInterface::Params> parameters =
      ClaimInterface::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());

  device::mojom::UsbDevice* device = GetDeviceFromHandle(parameters->handle);
  if (!device) {
    return RespondNow(Error(kErrorNoConnection));
  }

  device->ClaimInterface(
      parameters->interface_number,
      mojo::WrapCallbackWithDefaultInvokeIfNotRun(
          base::BindOnce(&UsbClaimInterfaceFunction::OnComplete, this),
          UsbClaimInterfaceResult::kFailure));
  return RespondLater();
}

void UsbClaimInterfaceFunction::OnComplete(UsbClaimInterfaceResult result) {
  if (result == UsbClaimInterfaceResult::kSuccess) {
    Respond(NoArguments());
  } else {
    Respond(Error(kErrorCannotClaimInterface));
  }
}

UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() = default;
UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() = default;

ExtensionFunction::ResponseAction UsbReleaseInterfaceFunction::Run() {
  std::unique_ptr<usb::ReleaseInterface::Params> parameters =
      ReleaseInterface::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());

  device::mojom::UsbDevice* device = GetDeviceFromHandle(parameters->handle);
  if (!device) {
    return RespondNow(Error(kErrorNoConnection));
  }

  device->ReleaseInterface(
      parameters->interface_number,
      mojo::WrapCallbackWithDefaultInvokeIfNotRun(
          base::BindOnce(&UsbReleaseInterfaceFunction::OnComplete, this),
          false));
  return RespondLater();
}

void UsbReleaseInterfaceFunction::OnComplete(bool success) {
  if (success)
    Respond(NoArguments());
  else
    Respond(Error(kErrorCannotReleaseInterface));
}

UsbSetInterfaceAlternateSettingFunction::
    UsbSetInterfaceAlternateSettingFunction() = default;

UsbSetInterfaceAlternateSettingFunction::
    ~UsbSetInterfaceAlternateSettingFunction() = default;

ExtensionFunction::ResponseAction
UsbSetInterfaceAlternateSettingFunction::Run() {
  std::unique_ptr<usb::SetInterfaceAlternateSetting::Params> parameters =
      SetInterfaceAlternateSetting::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());

  device::mojom::UsbDevice* device = GetDeviceFromHandle(parameters->handle);
  if (!device) {
    return RespondNow(Error(kErrorNoConnection));
  }

  device->SetInterfaceAlternateSetting(
      parameters->interface_number, parameters->alternate_setting,
      mojo::WrapCallbackWithDefaultInvokeIfNotRun(
          base::BindOnce(&UsbSetInterfaceAlternateSettingFunction::OnComplete,
                         this),
          false));
  return RespondLater();
}

void UsbSetInterfaceAlternateSettingFunction::OnComplete(bool success) {
  if (success) {
    Respond(NoArguments());
  } else {
    Respond(Error(kErrorCannotSetInterfaceAlternateSetting));
  }
}

UsbControlTransferFunction::UsbControlTransferFunction() = default;
UsbControlTransferFunction::~UsbControlTransferFunction() = default;

ExtensionFunction::ResponseAction UsbControlTransferFunction::Run() {
  std::unique_ptr<usb::ControlTransfer::Params> parameters =
      ControlTransfer::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());

  device::mojom::UsbDevice* device = GetDeviceFromHandle(parameters->handle);
  if (!device) {
    return RespondNow(Error(kErrorNoConnection));
  }

  const ControlTransferInfo& transfer = parameters->transfer_info;
  UsbTransferDirection direction = UsbTransferDirection::INBOUND;
  UsbControlTransferType request_type;
  UsbControlTransferRecipient recipient;

  if (!ConvertDirectionFromApi(transfer.direction, &direction)) {
    return RespondNow(Error(kErrorConvertDirection));
  }

  if (!ConvertRequestTypeFromApi(transfer.request_type, &request_type)) {
    return RespondNow(Error(kErrorConvertRequestType));
  }

  if (!ConvertRecipientFromApi(transfer.recipient, &recipient)) {
    return RespondNow(Error(kErrorConvertRecipient));
  }

  int timeout = transfer.timeout ? *transfer.timeout : 0;
  if (timeout < 0) {
    return RespondNow(Error(kErrorInvalidTimeout));
  }

  auto mojo_parameters =
      UsbControlTransferParams::New(request_type, recipient, transfer.request,
                                    transfer.value, transfer.index);

  if (direction == UsbTransferDirection::INBOUND) {
    uint32_t size = 0;
    if (!GetTransferInSize(transfer, &size)) {
      return RespondNow(Error(kErrorInvalidTransferLength));
    }

    device->ControlTransferIn(
        std::move(mojo_parameters), size, timeout,
        mojo::WrapCallbackWithDropHandler(
            base::BindOnce(&UsbControlTransferFunction::OnTransferInCompleted,
                           this),
            base::BindOnce(&UsbControlTransferFunction::OnDisconnect, this)));
  } else {
    // For case direction == UsbTransferDirection::OUTBOUND.
    if (!transfer.data) {
      return RespondNow(Error(kErrorMalformedParameters));
    }

    device->ControlTransferOut(
        std::move(mojo_parameters), *transfer.data, timeout,
        mojo::WrapCallbackWithDropHandler(
            base::BindOnce(&UsbControlTransferFunction::OnTransferOutCompleted,
                           this),
            base::BindOnce(&UsbControlTransferFunction::OnDisconnect, this)));
  }
  return RespondLater();
}

UsbBulkTransferFunction::UsbBulkTransferFunction() = default;
UsbBulkTransferFunction::~UsbBulkTransferFunction() = default;

ExtensionFunction::ResponseAction UsbBulkTransferFunction::Run() {
  std::unique_ptr<usb::BulkTransfer::Params> parameters =
      BulkTransfer::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());

  return DoTransfer<const usb::BulkTransfer::Params*>(parameters.get());
}

UsbInterruptTransferFunction::UsbInterruptTransferFunction() = default;
UsbInterruptTransferFunction::~UsbInterruptTransferFunction() = default;

ExtensionFunction::ResponseAction UsbInterruptTransferFunction::Run() {
  std::unique_ptr<usb::InterruptTransfer::Params> parameters =
      InterruptTransfer::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());

  return DoTransfer<const usb::InterruptTransfer::Params*>(parameters.get());
}

UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() = default;
UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() = default;

ExtensionFunction::ResponseAction UsbIsochronousTransferFunction::Run() {
  std::unique_ptr<usb::IsochronousTransfer::Params> parameters =
      IsochronousTransfer::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters.get());

  device::mojom::UsbDevice* device = GetDeviceFromHandle(parameters->handle);
  if (!device) {
    return RespondNow(Error(kErrorNoConnection));
  }

  const IsochronousTransferInfo& transfer = parameters->transfer_info;
  const GenericTransferInfo& generic_transfer = transfer.transfer_info;
  UsbTransferDirection direction = UsbTransferDirection::INBOUND;

  if (!ConvertDirectionFromApi(generic_transfer.direction, &direction))
    return RespondNow(Error(kErrorConvertDirection));

  uint32_t size = 0;
  if (direction == UsbTransferDirection::INBOUND) {
    if (!GetTransferInSize(generic_transfer, &size))
      return RespondNow(Error(kErrorInvalidTransferLength));
  } else {
    if (!generic_transfer.data)
      return RespondNow(Error(kErrorMalformedParameters));

    size = generic_transfer.data->size();
  }

  if (transfer.packets < 0 || transfer.packets >= kMaxPackets)
    return RespondNow(Error(kErrorInvalidNumberOfPackets));
  size_t packets = transfer.packets;

  if (transfer.packet_length < 0 ||
      transfer.packet_length >= kMaxPacketLength) {
    return RespondNow(Error(kErrorInvalidPacketLength));
  }

  size_t total_length = packets * transfer.packet_length;
  if (packets > size || total_length > size)
    return RespondNow(Error(kErrorTransferLength));

  std::vector<uint32_t> packet_lengths(packets, transfer.packet_length);

  int timeout = generic_transfer.timeout ? *generic_transfer.timeout : 0;
  if (timeout < 0)
    return RespondNow(Error(kErrorInvalidTimeout));

  if (direction == UsbTransferDirection::INBOUND) {
    device->IsochronousTransferIn(
        generic_transfer.endpoint, packet_lengths, timeout,
        mojo::WrapCallbackWithDropHandler(
            base::BindOnce(
                &UsbIsochronousTransferFunction::OnTransferInCompleted, this),
            base::BindOnce(&UsbIsochronousTransferFunction::OnDisconnect,
                           this)));
  } else {
    device->IsochronousTransferOut(
        generic_transfer.endpoint, *generic_transfer.data, packet_lengths,
        timeout,
        mojo::WrapCallbackWithDropHandler(
            base::BindOnce(
                &UsbIsochronousTransferFunction::OnTransferOutCompleted, this),
            base::BindOnce(&UsbIsochronousTransferFunction::OnDisconnect,
                           this)));
  }
  return RespondLater();
}

void UsbIsochronousTransferFunction::OnTransferInCompleted(
    base::span<const uint8_t> data,
    std::vector<UsbIsochronousPacketPtr> packets) {
  size_t length = std::accumulate(packets.begin(), packets.end(), 0,
                                  [](const size_t& a, const auto& packet) {
                                    return a + packet->transferred_length;
                                  });
  std::vector<char> buffer;
  buffer.reserve(length);

  UsbTransferStatus status = UsbTransferStatus::COMPLETED;
  const char* data_ptr = reinterpret_cast<const char*>(data.data());
  for (const auto& packet : packets) {
    // Capture the error status of the first unsuccessful packet.
    if (status == UsbTransferStatus::COMPLETED &&
        packet->status != UsbTransferStatus::COMPLETED) {
      status = packet->status;
    }

    buffer.insert(buffer.end(), data_ptr,
                  data_ptr + packet->transferred_length);
    data_ptr += packet->length;
  }

  auto transfer_info = std::make_unique<base::DictionaryValue>();
  transfer_info->SetKey(kResultCodeKey, base::Value(static_cast<int>(status)));
  transfer_info->SetKey(kDataKey, base::Value(std::move(buffer)));
  OnCompleted(status, std::move(transfer_info));
}

void UsbIsochronousTransferFunction::OnTransferOutCompleted(
    std::vector<UsbIsochronousPacketPtr> packets) {
  UsbTransferStatus status = UsbTransferStatus::COMPLETED;
  for (const auto& packet : packets) {
    // Capture the error status of the first unsuccessful packet.
    if (status == UsbTransferStatus::COMPLETED &&
        packet->status != UsbTransferStatus::COMPLETED) {
      status = packet->status;
    }
  }
  auto transfer_info = std::make_unique<base::DictionaryValue>();
  transfer_info->SetKey(kResultCodeKey, base::Value(static_cast<int>(status)));
  OnCompleted(status, std::move(transfer_info));
}

UsbResetDeviceFunction::UsbResetDeviceFunction() = default;
UsbResetDeviceFunction::~UsbResetDeviceFunction() = default;

ExtensionFunction::ResponseAction UsbResetDeviceFunction::Run() {
  parameters_ = ResetDevice::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters_.get());

  device::mojom::UsbDevice* device = GetDeviceFromHandle(parameters_->handle);
  if (!device) {
    return RespondNow(Error(kErrorNoConnection));
  }

  device->Reset(mojo::WrapCallbackWithDefaultInvokeIfNotRun(
      base::BindOnce(&UsbResetDeviceFunction::OnComplete, this), false));
  return RespondLater();
}

void UsbResetDeviceFunction::OnComplete(bool success) {
  if (success) {
    Respond(OneArgument(base::Value(true)));
  } else {
    ReleaseDeviceResource(parameters_->handle);

    std::unique_ptr<base::ListValue> error_args(new base::ListValue());
    error_args->Append(false);
    // Using ErrorWithArguments is discouraged but required to maintain
    // compatibility with existing applications.
    Respond(ErrorWithArguments(std::move(error_args), kErrorResetDevice));
  }
}

}  // namespace extensions
