// Copyright 2019 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_device_manager.h"

#include <functional>
#include <memory>
#include <utility>

#include "base/lazy_instance.h"
#include "base/strings/utf_string_conversions.h"
#include "build/chromeos_buildflags.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/api/extensions_api_client.h"
#include "extensions/browser/event_router_factory.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/pending_remote.h"
#include "services/device/public/mojom/usb_enumeration_options.mojom.h"

namespace usb = extensions::api::usb;

using content::BrowserThread;

namespace extensions {

namespace {

constexpr int kUsbClassMassStorage = 0x08;

bool IsMassStorageInterface(const device::mojom::UsbInterfaceInfo& interface) {
  for (auto& alternate : interface.alternates) {
    if (alternate->class_code == kUsbClassMassStorage)
      return true;
  }
  return false;
}

bool ShouldExposeDevice(const device::mojom::UsbDeviceInfo& device_info) {
  // ChromeOS always allows mass storage devices to be detached, but chrome.usb
  // only gets access when the specific vid/pid is listed in device policy.
  // This means that reloading policy can change the result of this function.
  for (auto& configuration : device_info.configurations) {
    for (auto& interface : configuration->interfaces) {
      if (!IsMassStorageInterface(*interface))
        return true;
    }
  }

#if BUILDFLAG(IS_CHROMEOS_ASH)
  if (ExtensionsAPIClient::Get()->ShouldAllowDetachingUsb(
          device_info.vendor_id, device_info.product_id)) {
    return true;
  }
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

  return false;
}

// Returns true if the given extension has permission to receive events
// regarding this device.
bool WillDispatchDeviceEvent(const device::mojom::UsbDeviceInfo& device_info,
                             content::BrowserContext* browser_context,
                             Feature::Context target_context,
                             const Extension* extension,
                             Event* event,
                             const base::DictionaryValue* listener_filter) {
  // Check install-time and optional permissions.
  std::unique_ptr<UsbDevicePermission::CheckParam> param =
      UsbDevicePermission::CheckParam::ForUsbDevice(extension, device_info);
  if (extension->permissions_data()->CheckAPIPermissionWithParam(
          APIPermission::kUsbDevice, param.get())) {
    return true;
  }

  // Check permissions granted through chrome.usb.getUserSelectedDevices.
  DevicePermissions* device_permissions =
      DevicePermissionsManager::Get(browser_context)
          ->GetForExtension(extension->id());
  if (device_permissions->FindUsbDeviceEntry(device_info).get()) {
    return true;
  }

  return false;
}

base::LazyInstance<BrowserContextKeyedAPIFactory<UsbDeviceManager>>::Leaky
    g_event_router_factory = LAZY_INSTANCE_INITIALIZER;

}  // namespace

// static
UsbDeviceManager* UsbDeviceManager::Get(
    content::BrowserContext* browser_context) {
  return BrowserContextKeyedAPIFactory<UsbDeviceManager>::Get(browser_context);
}

// static
BrowserContextKeyedAPIFactory<UsbDeviceManager>*
UsbDeviceManager::GetFactoryInstance() {
  return g_event_router_factory.Pointer();
}

void UsbDeviceManager::Observer::OnDeviceAdded(
    const device::mojom::UsbDeviceInfo& device_info) {}

void UsbDeviceManager::Observer::OnDeviceRemoved(
    const device::mojom::UsbDeviceInfo& device_info) {}

void UsbDeviceManager::Observer::OnDeviceManagerConnectionError() {}

UsbDeviceManager::UsbDeviceManager(content::BrowserContext* browser_context)
    : browser_context_(browser_context) {
  EventRouter* event_router = EventRouter::Get(browser_context_);
  if (event_router) {
    event_router->RegisterObserver(this, usb::OnDeviceAdded::kEventName);
    event_router->RegisterObserver(this, usb::OnDeviceRemoved::kEventName);
  }
}

UsbDeviceManager::~UsbDeviceManager() {}

void UsbDeviceManager::AddObserver(Observer* observer) {
  EnsureConnectionWithDeviceManager();
  observer_list_.AddObserver(observer);
}

void UsbDeviceManager::RemoveObserver(Observer* observer) {
  observer_list_.RemoveObserver(observer);
}

int UsbDeviceManager::GetIdFromGuid(const std::string& guid) {
  auto iter = guid_to_id_map_.find(guid);
  if (iter == guid_to_id_map_.end()) {
    auto result = guid_to_id_map_.insert(std::make_pair(guid, next_id_++));
    DCHECK(result.second);
    iter = result.first;
    id_to_guid_map_.insert(std::make_pair(iter->second, guid));
  }
  return iter->second;
}

bool UsbDeviceManager::GetGuidFromId(int id, std::string* guid) {
  auto iter = id_to_guid_map_.find(id);
  if (iter == id_to_guid_map_.end())
    return false;
  *guid = iter->second;
  return true;
}

void UsbDeviceManager::GetApiDevice(
    const device::mojom::UsbDeviceInfo& device_in,
    api::usb::Device* device_out) {
  device_out->device = GetIdFromGuid(device_in.guid);
  device_out->vendor_id = device_in.vendor_id;
  device_out->product_id = device_in.product_id;
  device_out->version = device_in.device_version_major << 8 |
                        device_in.device_version_minor << 4 |
                        device_in.device_version_subminor;
  device_out->product_name =
      base::UTF16ToUTF8(device_in.product_name.value_or(std::u16string()));
  device_out->manufacturer_name =
      base::UTF16ToUTF8(device_in.manufacturer_name.value_or(std::u16string()));
  device_out->serial_number =
      base::UTF16ToUTF8(device_in.serial_number.value_or(std::u16string()));
}

void UsbDeviceManager::GetDevices(
    device::mojom::UsbDeviceManager::GetDevicesCallback callback) {
  if (!is_initialized_) {
    pending_get_devices_requests_.push(std::move(callback));
    EnsureConnectionWithDeviceManager();
    return;
  }

  std::vector<device::mojom::UsbDeviceInfoPtr> device_list;
  for (const auto& pair : devices_)
    device_list.push_back(pair.second->Clone());
  base::SequencedTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(std::move(callback), std::move(device_list)));
}

void UsbDeviceManager::GetDevice(
    const std::string& guid,
    mojo::PendingReceiver<device::mojom::UsbDevice> device_receiver) {
  EnsureConnectionWithDeviceManager();
  device_manager_->GetDevice(guid, /*blocked_interface_classes=*/{},
                             std::move(device_receiver),
                             /*device_client=*/mojo::NullRemote());
}

const device::mojom::UsbDeviceInfo* UsbDeviceManager::GetDeviceInfo(
    const std::string& guid) {
  DCHECK(is_initialized_);
  auto it = devices_.find(guid);
  return it == devices_.end() ? nullptr : it->second.get();
}

bool UsbDeviceManager::UpdateActiveConfig(const std::string& guid,
                                          uint8_t config_value) {
  DCHECK(is_initialized_);
  auto it = devices_.find(guid);
  if (it == devices_.end()) {
    return false;
  }
  it->second->active_configuration = config_value;
  return true;
}

#if BUILDFLAG(IS_CHROMEOS_ASH)
void UsbDeviceManager::CheckAccess(
    const std::string& guid,
    device::mojom::UsbDeviceManager::CheckAccessCallback callback) {
  EnsureConnectionWithDeviceManager();
  device_manager_->CheckAccess(guid, std::move(callback));
}
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

void UsbDeviceManager::EnsureConnectionWithDeviceManager() {
  if (device_manager_)
    return;

  // Receive mojo::Remote<UsbDeviceManager> from DeviceService.
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  content::GetDeviceService().BindUsbDeviceManager(
      device_manager_.BindNewPipeAndPassReceiver());

  SetUpDeviceManagerConnection();
}

void UsbDeviceManager::SetDeviceManagerForTesting(
    mojo::PendingRemote<device::mojom::UsbDeviceManager> fake_device_manager) {
  DCHECK(!device_manager_);
  DCHECK(fake_device_manager);
  device_manager_.Bind(std::move(fake_device_manager));
  SetUpDeviceManagerConnection();
}

void UsbDeviceManager::Shutdown() {
  EventRouter* event_router = EventRouter::Get(browser_context_);
  if (event_router) {
    event_router->UnregisterObserver(this);
  }
}

void UsbDeviceManager::OnListenerAdded(const EventListenerInfo& details) {
  EnsureConnectionWithDeviceManager();
}

void UsbDeviceManager::OnDeviceAdded(
    device::mojom::UsbDeviceInfoPtr device_info) {
  DCHECK(device_info);
  // Update the device list.
  DCHECK(!base::Contains(devices_, device_info->guid));
  if (!ShouldExposeDevice(*device_info))
    return;
  std::string guid = device_info->guid;
  auto result =
      devices_.insert(std::make_pair(std::move(guid), std::move(device_info)));
  const device::mojom::UsbDeviceInfo& stored_info = *result.first->second;

  DispatchEvent(usb::OnDeviceAdded::kEventName, stored_info);

  // Notify all observers.
  for (auto& observer : observer_list_)
    observer.OnDeviceAdded(stored_info);
}

void UsbDeviceManager::OnDeviceRemoved(
    device::mojom::UsbDeviceInfoPtr device_info) {
  DCHECK(device_info);

  // Handle if ShouldExposeDevice() returned false when the device was added.
  if (!base::Contains(devices_, device_info->guid))
    return;

  // Update the device list.
  devices_.erase(device_info->guid);

  DispatchEvent(usb::OnDeviceRemoved::kEventName, *device_info);

  // Notify all observers for OnDeviceRemoved event.
  for (auto& observer : observer_list_)
    observer.OnDeviceRemoved(*device_info);

  auto iter = guid_to_id_map_.find(device_info->guid);
  if (iter != guid_to_id_map_.end()) {
    int id = iter->second;
    guid_to_id_map_.erase(iter);
    id_to_guid_map_.erase(id);
  }

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

void UsbDeviceManager::SetUpDeviceManagerConnection() {
  DCHECK(device_manager_);
  device_manager_.set_disconnect_handler(
      base::BindOnce(&UsbDeviceManager::OnDeviceManagerConnectionError,
                     base::Unretained(this)));

  // Listen for added/removed device events.
  DCHECK(!client_receiver_.is_bound());
  device_manager_->EnumerateDevicesAndSetClient(
      client_receiver_.BindNewEndpointAndPassRemote(),
      base::BindOnce(&UsbDeviceManager::InitDeviceList,
                     weak_factory_.GetWeakPtr()));
}

void UsbDeviceManager::InitDeviceList(
    std::vector<device::mojom::UsbDeviceInfoPtr> devices) {
  for (auto& device_info : devices) {
    DCHECK(device_info);
    if (!ShouldExposeDevice(*device_info))
      continue;
    std::string guid = device_info->guid;
    devices_.insert(std::make_pair(guid, std::move(device_info)));
  }
  is_initialized_ = true;

  while (!pending_get_devices_requests_.empty()) {
    std::vector<device::mojom::UsbDeviceInfoPtr> device_list;
    for (const auto& entry : devices_) {
      device_list.push_back(entry.second->Clone());
    }
    std::move(pending_get_devices_requests_.front())
        .Run(std::move(device_list));
    pending_get_devices_requests_.pop();
  }
}

void UsbDeviceManager::OnDeviceManagerConnectionError() {
  device_manager_.reset();
  client_receiver_.reset();
  devices_.clear();
  is_initialized_ = false;

  guid_to_id_map_.clear();
  id_to_guid_map_.clear();

  // Notify all observers.
  for (auto& observer : observer_list_)
    observer.OnDeviceManagerConnectionError();
}

void UsbDeviceManager::DispatchEvent(
    const std::string& event_name,
    const device::mojom::UsbDeviceInfo& device_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  EventRouter* event_router = EventRouter::Get(browser_context_);
  if (event_router) {
    usb::Device device_obj;
    GetApiDevice(device_info, &device_obj);

    std::unique_ptr<Event> event;
    if (event_name == usb::OnDeviceAdded::kEventName) {
      event.reset(new Event(events::USB_ON_DEVICE_ADDED,
                            usb::OnDeviceAdded::kEventName,
                            usb::OnDeviceAdded::Create(device_obj)));
    } else {
      DCHECK(event_name == usb::OnDeviceRemoved::kEventName);
      event.reset(new Event(events::USB_ON_DEVICE_REMOVED,
                            usb::OnDeviceRemoved::kEventName,
                            usb::OnDeviceRemoved::Create(device_obj)));
    }

    event->will_dispatch_callback =
        base::BindRepeating(&WillDispatchDeviceEvent, std::cref(device_info));
    event_router->BroadcastEvent(std::move(event));
  }
}

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

}  // namespace extensions
