// 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/hid/hid_device_manager.h"

#include <stdint.h>

#include <algorithm>
#include <functional>
#include <iterator>
#include <limits>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/no_destructor.h"
#include "base/task/single_thread_task_runner.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/device_service.h"
#include "extensions/browser/api/device_permissions_manager.h"
#include "extensions/browser/event_router_factory.h"
#include "extensions/common/mojom/context_type.mojom.h"
#include "extensions/common/mojom/event_dispatcher.mojom-forward.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 "mojo/public/cpp/bindings/pending_remote.h"
#include "services/device/public/cpp/hid/hid_device_filter.h"
#include "services/device/public/cpp/hid/hid_report_type.h"
#include "services/device/public/cpp/hid/hid_report_utils.h"
#include "services/device/public/mojom/hid.mojom.h"

namespace hid = extensions::api::hid;

namespace extensions {

namespace {

using ::device::HidDeviceFilter;
using ::device::HidReportType;
using ::device::IsAlwaysProtected;

// Return true if all reports in `device` with `report_id` are protected.
// Protected report IDs are not exposed in the API.
bool IsReportIdProtected(const device::mojom::HidDeviceInfo& device,
                         uint8_t report_id) {
  // `report_id` is not protected if there is any report with `report_id` that
  // is not protected.
  constexpr HidReportType report_types[] = {
      HidReportType::kInput, HidReportType::kOutput, HidReportType::kFeature};
  bool found_matching_report = false;
  for (const auto& report_type : report_types) {
    auto* collection =
        device::FindCollectionWithReport(device, report_id, report_type);
    if (collection) {
      found_matching_report = true;
      if (!IsAlwaysProtected(*collection->usage, report_type)) {
        return false;
      }
    }
  }
  if (!found_matching_report) {
    // No reports with `report_id` were found in any collection. This indicates
    // an error in the device's report descriptor, but the device may still be
    // usable. Consider the report protected if `device` has any collection with
    // a protected usage.
    return std::ranges::any_of(device.collections, [](const auto& collection) {
      return IsAlwaysProtected(*collection->usage, HidReportType::kInput) ||
             IsAlwaysProtected(*collection->usage, HidReportType::kOutput) ||
             IsAlwaysProtected(*collection->usage, HidReportType::kFeature);
    });
  }

  // All reports matching `report_id` are protected.
  return true;
}

void PopulateHidDeviceInfo(hid::HidDeviceInfo* output,
                           const device::mojom::HidDeviceInfo& input) {
  output->vendor_id = input.vendor_id;
  output->product_id = input.product_id;
  output->product_name = input.product_name;
  output->serial_number = input.serial_number;
  output->max_input_report_size = input.max_input_report_size;
  output->max_output_report_size = input.max_output_report_size;
  output->max_feature_report_size = input.max_feature_report_size;

  for (const auto& collection : input.collections) {
    // Omit a collection if all its reports are protected.
    if (!device::CollectionHasUnprotectedReports(*collection)) {
      continue;
    }

    // Omit IDs only used by protected reports.
    std::vector<int> filtered_report_ids;
    std::ranges::copy_if(collection->report_ids,
                         std::back_inserter(filtered_report_ids),
                         [&input](int report_id) {
                           return !IsReportIdProtected(input, report_id);
                         });

    hid::HidCollectionInfo api_collection;
    api_collection.usage_page = collection->usage->usage_page;
    api_collection.usage = collection->usage->usage;

    api_collection.report_ids = std::move(filtered_report_ids);

    output->collections.push_back(std::move(api_collection));
  }

  const std::vector<uint8_t>& report_descriptor = input.report_descriptor;
  if (report_descriptor.size() > 0) {
    output->report_descriptor.assign(report_descriptor.begin(),
                                     report_descriptor.end());
  }
}

bool WillDispatchDeviceEvent(
    base::WeakPtr<HidDeviceManager> device_manager,
    const device::mojom::HidDeviceInfo& device_info,
    content::BrowserContext* browser_context,
    mojom::ContextType target_context,
    const Extension* extension,
    const base::Value::Dict* listener_filter,
    std::optional<base::Value::List>& event_args_out,
    mojom::EventFilteringInfoPtr& event_filtering_info_out,
    bool* dispatch_separate_event_out) {
  if (device_manager && extension) {
    return device_manager->HasPermission(extension, device_info, false);
  }
  return false;
}

HidDeviceManager::HidManagerBinder& GetHidManagerBinderOverride() {
  static base::NoDestructor<HidDeviceManager::HidManagerBinder> binder;
  return *binder;
}

}  // namespace

struct HidDeviceManager::GetApiDevicesParams {
 public:
  GetApiDevicesParams(const Extension* extension,
                      const std::vector<HidDeviceFilter>& filters,
                      GetApiDevicesCallback callback)
      : extension(extension), filters(filters), callback(std::move(callback)) {}
  ~GetApiDevicesParams() {}

  raw_ptr<const Extension> extension;
  std::vector<HidDeviceFilter> filters;
  GetApiDevicesCallback callback;
};

HidDeviceManager::HidDeviceManager(content::BrowserContext* context)
    : browser_context_(context) {
  event_router_ = EventRouter::Get(context);
  if (event_router_) {
    event_router_->RegisterObserver(this, hid::OnDeviceAdded::kEventName);
    event_router_->RegisterObserver(this, hid::OnDeviceRemoved::kEventName);
  }
}

HidDeviceManager::~HidDeviceManager() {
  DCHECK(thread_checker_.CalledOnValidThread());
}

// static
BrowserContextKeyedAPIFactory<HidDeviceManager>*
HidDeviceManager::GetFactoryInstance() {
  static base::LazyInstance<BrowserContextKeyedAPIFactory<HidDeviceManager>>::
      DestructorAtExit factory = LAZY_INSTANCE_INITIALIZER;
  return &factory.Get();
}

template <>
void BrowserContextKeyedAPIFactory<
    HidDeviceManager>::DeclareFactoryDependencies() {
  DependsOn(EventRouterFactory::GetInstance());
}

void HidDeviceManager::GetApiDevices(
    const Extension* extension,
    const std::vector<HidDeviceFilter>& filters,
    GetApiDevicesCallback callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  LazyInitialize();

  if (enumeration_ready_) {
    base::Value::List devices = CreateApiDeviceList(extension, filters);
    base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback), std::move(devices)));
  } else {
    pending_enumerations_.push_back(std::make_unique<GetApiDevicesParams>(
        extension, filters, std::move(callback)));
  }
}

const device::mojom::HidDeviceInfo* HidDeviceManager::GetDeviceInfo(
    int resource_id) {
  DCHECK(thread_checker_.CalledOnValidThread());

  ResourceIdToDeviceInfoMap::const_iterator device_iter =
      devices_.find(resource_id);
  if (device_iter == devices_.end()) {
    return nullptr;
  }

  return device_iter->second.get();
}

void HidDeviceManager::Connect(const std::string& device_guid,
                               ConnectCallback callback) {
  DCHECK(initialized_);

  hid_manager_->Connect(device_guid, /*connection_client=*/mojo::NullRemote(),
                        /*watcher=*/mojo::NullRemote(),
                        /*allow_protected_reports=*/true,
                        /*allow_fido_reports=*/true,
                        mojo::WrapCallbackWithDefaultInvokeIfNotRun(
                            std::move(callback), mojo::NullRemote()));
}

bool HidDeviceManager::HasPermission(
    const Extension* extension,
    const device::mojom::HidDeviceInfo& device_info,
    bool update_last_used) {
  DevicePermissionsManager* permissions_manager =
      DevicePermissionsManager::Get(browser_context_);
  CHECK(permissions_manager);
  DevicePermissions* device_permissions =
      permissions_manager->GetForExtension(extension->id());
  DCHECK(device_permissions);
  scoped_refptr<DevicePermissionEntry> permission_entry =
      device_permissions->FindHidDeviceEntry(device_info);
  if (permission_entry) {
    if (update_last_used) {
      permissions_manager->UpdateLastUsed(extension->id(), permission_entry);
    }
    return true;
  }

  std::unique_ptr<UsbDevicePermission::CheckParam> usb_param =
      UsbDevicePermission::CheckParam::ForHidDevice(
          extension, device_info.vendor_id, device_info.product_id);
  if (extension->permissions_data()->CheckAPIPermissionWithParam(
          mojom::APIPermissionID::kUsbDevice, usb_param.get())) {
    return true;
  }

  if (extension->permissions_data()->HasAPIPermission(
          mojom::APIPermissionID::kU2fDevices)) {
    HidDeviceFilter u2f_filter;
    u2f_filter.SetUsagePage(0xF1D0);
    if (u2f_filter.Matches(device_info)) {
      return true;
    }
  }

  return false;
}

void HidDeviceManager::Shutdown() {
  if (event_router_) {
    event_router_->UnregisterObserver(this);
  }
}

void HidDeviceManager::OnListenerAdded(const EventListenerInfo& details) {
  LazyInitialize();
}
void HidDeviceManager::DeviceAdded(device::mojom::HidDeviceInfoPtr device) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK_LT(next_resource_id_, std::numeric_limits<int>::max());
  int new_id = next_resource_id_++;
  DCHECK(!base::Contains(resource_ids_, device->guid));
  resource_ids_[device->guid] = new_id;
  devices_[new_id] = std::move(device);

  // Don't generate events during the initial enumeration.
  if (enumeration_ready_ && event_router_) {
    api::hid::HidDeviceInfo api_device_info;
    api_device_info.device_id = new_id;

    PopulateHidDeviceInfo(&api_device_info, *devices_[new_id]);

    if (api_device_info.collections.size() > 0) {
      auto args(hid::OnDeviceAdded::Create(api_device_info));
      DispatchEvent(events::HID_ON_DEVICE_ADDED, hid::OnDeviceAdded::kEventName,
                    std::move(args), *devices_[new_id]);
    }
  }
}

void HidDeviceManager::DeviceRemoved(device::mojom::HidDeviceInfoPtr device) {
  DCHECK(thread_checker_.CalledOnValidThread());
  const auto& resource_entry = resource_ids_.find(device->guid);
  CHECK(resource_entry != resource_ids_.end());
  int resource_id = resource_entry->second;
  const auto& device_entry = devices_.find(resource_id);
  CHECK(device_entry != devices_.end());
  resource_ids_.erase(resource_entry);
  devices_.erase(device_entry);

  if (event_router_) {
    DCHECK(enumeration_ready_);
    auto args(hid::OnDeviceRemoved::Create(resource_id));
    DispatchEvent(events::HID_ON_DEVICE_REMOVED,
                  hid::OnDeviceRemoved::kEventName, std::move(args), *device);
  }

  // Remove permission entry for ephemeral hid device.
  DevicePermissionsManager* permissions_manager =
      DevicePermissionsManager::Get(browser_context_);
  DCHECK(permissions_manager);
  permissions_manager->RemoveEntryByDeviceGUID(DevicePermissionEntry::Type::HID,
                                               device->guid);
}

void HidDeviceManager::DeviceChanged(device::mojom::HidDeviceInfoPtr device) {
  // Find |device| in |devices_|.
  DCHECK(thread_checker_.CalledOnValidThread());
  const auto& resource_entry = resource_ids_.find(device->guid);
  CHECK(resource_entry != resource_ids_.end());
  int resource_id = resource_entry->second;
  DCHECK(base::Contains(devices_, resource_id));

  // Update the device information.
  devices_[resource_id] = std::move(device);
}

void HidDeviceManager::LazyInitialize() {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (initialized_) {
    return;
  }
  // |hid_manager_| may already be initialized in tests.
  if (!hid_manager_) {
    // |hid_manager_| is initialized and safe to use whether or not the
    // connection is successful.

    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
    auto receiver = hid_manager_.BindNewPipeAndPassReceiver();
    const auto& binder = GetHidManagerBinderOverride();
    if (binder) {
      binder.Run(std::move(receiver));
    } else {
      content::GetDeviceService().BindHidManager(std::move(receiver));
    }
  }
  // Enumerate HID devices and set client.
  std::vector<device::mojom::HidDeviceInfoPtr> empty_devices;
  hid_manager_->GetDevicesAndSetClient(
      receiver_.BindNewEndpointAndPassRemote(),
      mojo::WrapCallbackWithDefaultInvokeIfNotRun(
          base::BindOnce(&HidDeviceManager::OnEnumerationComplete,
                         weak_factory_.GetWeakPtr()),
          std::move(empty_devices)));

  initialized_ = true;
}

// static
void HidDeviceManager::OverrideHidManagerBinderForTesting(
    HidManagerBinder binder) {
  GetHidManagerBinderOverride() = std::move(binder);
}

base::Value::List HidDeviceManager::CreateApiDeviceList(
    const Extension* extension,
    const std::vector<HidDeviceFilter>& filters) {
  base::Value::List api_devices;
  for (const ResourceIdToDeviceInfoMap::value_type& map_entry : devices_) {
    int resource_id = map_entry.first;
    auto& device_info = map_entry.second;

    if (!filters.empty() &&
        !HidDeviceFilter::MatchesAny(*device_info, filters)) {
      continue;
    }

    if (!HasPermission(extension, *device_info, false)) {
      continue;
    }

    hid::HidDeviceInfo api_device_info;
    api_device_info.device_id = resource_id;
    PopulateHidDeviceInfo(&api_device_info, *device_info);

    // Expose devices with which user can communicate.
    if (api_device_info.collections.size() > 0) {
      api_devices.Append(api_device_info.ToValue());
    }
  }

  return api_devices;
}

void HidDeviceManager::OnEnumerationComplete(
    std::vector<device::mojom::HidDeviceInfoPtr> devices) {
  DCHECK(resource_ids_.empty());
  DCHECK(devices_.empty());

  for (auto& device_info : devices) {
    DeviceAdded(std::move(device_info));
  }
  enumeration_ready_ = true;

  for (const auto& params : pending_enumerations_) {
    base::Value::List devices_list =
        CreateApiDeviceList(params->extension, params->filters);
    std::move(params->callback).Run(std::move(devices_list));
  }
  pending_enumerations_.clear();
}

void HidDeviceManager::DispatchEvent(
    events::HistogramValue histogram_value,
    const std::string& event_name,
    base::Value::List event_args,
    const device::mojom::HidDeviceInfo& device_info) {
  std::unique_ptr<Event> event(
      new Event(histogram_value, event_name, std::move(event_args)));
  // The |event->will_dispatch_callback| will be called synchronously, it is
  // safe to pass |device_info| by reference.
  event->will_dispatch_callback =
      base::BindRepeating(&WillDispatchDeviceEvent, weak_factory_.GetWeakPtr(),
                          std::cref(device_info));
  event_router_->BroadcastEvent(std::move(event));
}

}  // namespace extensions
