// Copyright 2014 The Chromium Authors
// 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/functional/bind.h"
#include "base/values.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/api/api_resource_manager.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/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"

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::kIn:
      *output = UsbTransferDirection::INBOUND;
      return true;
    case usb::Direction::kOut:
      *output = UsbTransferDirection::OUTBOUND;
      return true;
    default:
      NOTREACHED();
  }
}

bool ConvertRequestTypeFromApi(const RequestType& input,
                               UsbControlTransferType* output) {
  switch (input) {
    case usb::RequestType::kStandard:
      *output = UsbControlTransferType::STANDARD;
      return true;
    case usb::RequestType::kClass:
      *output = UsbControlTransferType::CLASS;
      return true;
    case usb::RequestType::kVendor:
      *output = UsbControlTransferType::VENDOR;
      return true;
    case usb::RequestType::kReserved:
      *output = UsbControlTransferType::RESERVED;
      return true;
    default:
      NOTREACHED();
  }
}

bool ConvertRecipientFromApi(const Recipient& input,
                             UsbControlTransferRecipient* output) {
  switch (input) {
    case usb::Recipient::kDevice:
      *output = UsbControlTransferRecipient::DEVICE;
      return true;
    case usb::Recipient::kInterface:
      *output = UsbControlTransferRecipient::INTERFACE;
      return true;
    case usb::Recipient::kEndpoint:
      *output = UsbControlTransferRecipient::ENDPOINT;
      return true;
    case usb::Recipient::kOther:
      *output = UsbControlTransferRecipient::OTHER;
      return true;
    default:
      NOTREACHED();
  }
}

template <class T>
bool GetTransferInSize(const T& input, uint32_t* output) {
  const auto& length = input.length;
  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:
      DUMP_WILL_BE_NOTREACHED();
      return "";
  }
}

base::Value::Dict 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::TransferType::kControl;
    case UsbTransferType::INTERRUPT:
      return usb::TransferType::kInterrupt;
    case UsbTransferType::ISOCHRONOUS:
      return usb::TransferType::kIsochronous;
    case UsbTransferType::BULK:
      return usb::TransferType::kBulk;
    default:
      NOTREACHED();
  }
}

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

SynchronizationType ConvertSynchronizationTypeToApi(
    const UsbSynchronizationType& input) {
  switch (input) {
    case UsbSynchronizationType::NONE:
      return usb::SynchronizationType::kNone;
    case UsbSynchronizationType::ASYNCHRONOUS:
      return usb::SynchronizationType::kAsynchronous;
    case UsbSynchronizationType::ADAPTIVE:
      return usb::SynchronizationType::kAdaptive;
    case UsbSynchronizationType::SYNCHRONOUS:
      return usb::SynchronizationType::kSynchronous;
    default:
      NOTREACHED();
  }
}

usb::UsageType ConvertUsageTypeToApi(const UsbUsageType& input) {
  switch (input) {
    case UsbUsageType::DATA:
      return usb::UsageType::kData;
    case UsbUsageType::FEEDBACK:
      return usb::UsageType::kFeedback;
    case UsbUsageType::EXPLICIT_FEEDBACK:
      return usb::UsageType::kExplicitFeedback;
    case UsbUsageType::PERIODIC:
      return usb::UsageType::kPeriodic;
    case UsbUsageType::NOTIFICATION:
      return usb::UsageType::kNotification;
    case UsbUsageType::RESERVED:
      return usb::UsageType::kNone;
    default:
      NOTREACHED();
  }
}

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 = 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_;
}

bool UsbExtensionFunction::IsUsbDeviceAllowedByPolicy(int vendor_id,
                                                      int product_id) {
  ExtensionsBrowserClient* client = ExtensionsBrowserClient::Get();
  DCHECK(client);
  return client->IsUsbDeviceAllowedByPolicy(browser_context(), extension_id(),
                                            vendor_id, product_id);
}

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;
  }

  if (IsUsbDeviceAllowedByPolicy(device.vendor_id, device.product_id)) {
    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,
                                      base::Value::Dict transfer_info) {
  if (status == UsbTransferStatus::COMPLETED) {
    Respond(WithArguments(std::move(transfer_info)));
  } else {
    base::Value::List error_args;
    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(ErrorWithArgumentsDoNotUse(std::move(error_args),
                                       ConvertTransferStatusToApi(status)));
  }
}

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

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

void UsbTransferFunction::OnTransferOutCompleted(UsbTransferStatus status) {
  base::Value::Dict transfer_info;
  transfer_info.Set(kResultCodeKey, static_cast<int>(status));
  transfer_info.Set(kDataKey, base::Value(base::Value::Type::BINARY));

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

void UsbTransferFunction::OnDisconnect() {
  const auto status = UsbTransferStatus::DISCONNECT;
  base::Value::Dict transfer_info;
  transfer_info.Set(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(
    const 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::optional<usb::FindDevices::Params> parameters =
      FindDevices::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters);

  vendor_id_ = parameters->options.vendor_id;
  product_id_ = parameters->options.product_id;
  int interface_id = parameters->options.interface_id.value_or(
      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()) &&
      !IsUsbDeviceAllowedByPolicy(vendor_id_, product_id_)) {
    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) {
  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()) &&
        !IsUsbDeviceAllowedByPolicy(vendor_id_, product_id_)) {
      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::UsbOpenDeviceResultPtr result) {
  if (result->is_success() && 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(WithArguments(std::move(result_)));
}

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

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

  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) {
  base::Value::List result;
  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(WithArguments(std::move(result)));
}

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

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

  if (!user_gesture()) {
    return RespondNow(WithArguments(base::Value::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) {
  base::Value::List result;
  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(WithArguments(std::move(result)));
}

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

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

  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));
  }

  base::Value::List configs;
  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(WithArguments(std::move(configs)));
}

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

ExtensionFunction::ResponseAction UsbRequestAccessFunction::Run() {
  std::optional<usb::RequestAccess::Params> parameters =
      RequestAccess::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters);
  return RespondNow(WithArguments(true));
}

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

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

  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::UsbOpenDeviceResultPtr result) {
  if (result->is_error() || !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(WithArguments(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::optional<usb::SetConfiguration::Params> parameters =
      SetConfiguration::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters);

  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::optional<usb::GetConfiguration::Params> parameters =
      GetConfiguration::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters);

  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(WithArguments(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::optional<usb::ListInterfaces::Params> parameters =
      ListInterfaces::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters);

  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);
      base::Value::List result;
      for (const auto& interface : api_config.interfaces) {
        result.Append(interface.ToValue());
      }
      return RespondNow(WithArguments(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::optional<usb::CloseDevice::Params> parameters =
      CloseDevice::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters);

  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::optional<usb::ClaimInterface::Params> parameters =
      ClaimInterface::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters);

  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::optional<usb::ReleaseInterface::Params> parameters =
      ReleaseInterface::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters);

  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::optional<usb::SetInterfaceAlternateSetting::Params> parameters =
      SetInterfaceAlternateSetting::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters);

  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::optional<usb::ControlTransfer::Params> parameters =
      ControlTransfer::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters);

  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::optional<usb::BulkTransfer::Params> parameters =
      BulkTransfer::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parameters);

  return DoTransfer<const std::optional<usb::BulkTransfer::Params>>(parameters);
}

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

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

  return DoTransfer<const std::optional<usb::InterruptTransfer::Params>>(
      parameters);
}

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

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

  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;
  size_t index = 0;
  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(), reinterpret_cast<const char*>(&data[index]),
                  reinterpret_cast<const char*>(
                      &data[index + packet->transferred_length]));
    index += packet->transferred_length;
  }

  base::Value::Dict transfer_info;
  transfer_info.Set(kResultCodeKey, base::Value(static_cast<int>(status)));
  transfer_info.Set(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;
    }
  }
  base::Value::Dict transfer_info;
  transfer_info.Set(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_);

  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(WithArguments(true));
  } else {
    ReleaseDeviceResource(parameters_->handle);

    base::Value::List error_args;
    error_args.Append(false);
    // Using ErrorWithArguments is discouraged but required to maintain
    // compatibility with existing applications.
    Respond(
        ErrorWithArgumentsDoNotUse(std::move(error_args), kErrorResetDevice));
  }
}

}  // namespace extensions
