#include "chrome/browser/usb/usb_chooser_context.h"
#include <memory>
#include <string_view>
#include <utility>
#include <vector>
#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/observer_list.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/usb/web_usb_histograms.h"
#include "chrome/grit/generated_resources.h"
#include "components/content_settings/core/common/content_settings.h"
#include "content/public/browser/device_service.h"
#include "services/device/public/cpp/usb/usb_ids.h"
#include "services/device/public/mojom/usb_device.mojom.h"
#include "ui/base/l10n/l10n_util.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chromeos/ash/components/settings/cros_settings.h"
#include "chromeos/ash/components/settings/cros_settings_names.h"
#endif
#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "chromeos/crosapi/mojom/device_settings_service.mojom.h"
#include "chromeos/startup/browser_params_proxy.h"
#endif
namespace {
constexpr char kDeviceNameKey[] = …;
constexpr char kGuidKey[] = …;
constexpr char kProductIdKey[] = …;
constexpr char kSerialNumberKey[] = …;
constexpr char kVendorIdKey[] = …;
constexpr int kDeviceIdWildcard = …;
constexpr int kUsbClassMassStorage = …;
bool CanStorePersistentEntry(const device::mojom::UsbDeviceInfo& device_info) { … }
std::pair<int, int> GetDeviceIds(const base::Value::Dict& object) { … }
std::u16string GetDeviceNameFromIds(int vendor_id, int product_id) { … }
base::Value::Dict DeviceIdsToValue(int vendor_id, int product_id) { … }
#if BUILDFLAG(IS_CHROMEOS)
bool IsDetachable(int vid, int pid) {
#if BUILDFLAG(IS_CHROMEOS_ASH)
const base::Value::List* policy_list;
if (ash::CrosSettings::Get()->GetList(ash::kUsbDetachableAllowlist,
&policy_list)) {
for (const auto& entry : *policy_list) {
if (entry.GetDict().FindInt(ash::kUsbDetachableAllowlistKeyVid) == vid &&
entry.GetDict().FindInt(ash::kUsbDetachableAllowlistKeyPid) == pid) {
return true;
}
}
}
#endif
#if BUILDFLAG(IS_CHROMEOS_LACROS)
const crosapi::mojom::DeviceSettings* device_settings =
chromeos::BrowserParamsProxy::Get()->DeviceSettings().get();
if (device_settings && device_settings->usb_detachable_allow_list) {
for (const auto& entry :
device_settings->usb_detachable_allow_list->usb_device_ids) {
if (entry->has_vendor_id && entry->vendor_id == vid &&
entry->has_product_id && entry->product_id == pid) {
return true;
}
}
}
#endif
return false;
}
#endif
bool IsMassStorageInterface(const device::mojom::UsbInterfaceInfo& interface) { … }
bool ShouldExposeDevice(const device::mojom::UsbDeviceInfo& device_info) { … }
}
void UsbChooserContext::DeviceObserver::OnDeviceAdded(
const device::mojom::UsbDeviceInfo& device_info) { … }
void UsbChooserContext::DeviceObserver::OnDeviceRemoved(
const device::mojom::UsbDeviceInfo& device_info) { … }
void UsbChooserContext::DeviceObserver::OnDeviceManagerConnectionError() { … }
UsbChooserContext::UsbChooserContext(Profile* profile)
: … { … }
base::Value::Dict UsbChooserContext::DeviceInfoToValue(
const device::mojom::UsbDeviceInfo& device_info) { … }
void UsbChooserContext::InitDeviceList(
std::vector<device::mojom::UsbDeviceInfoPtr> devices) { … }
void UsbChooserContext::Shutdown() { … }
void UsbChooserContext::EnsureConnectionWithDeviceManager() { … }
void UsbChooserContext::SetUpDeviceManagerConnection() { … }
#if BUILDFLAG(IS_ANDROID)
void UsbChooserContext::OnDeviceInfoRefreshed(
device::mojom::UsbDeviceManager::RefreshDeviceInfoCallback callback,
device::mojom::UsbDeviceInfoPtr device_info) {
if (!device_info) {
std::move(callback).Run(nullptr);
return;
}
auto it = devices_.find(device_info->guid);
if (it == devices_.end()) {
std::move(callback).Run(nullptr);
return;
}
it->second = std::move(device_info);
std::move(callback).Run(it->second->Clone());
}
#endif
UsbChooserContext::~UsbChooserContext() { … }
std::vector<std::unique_ptr<permissions::ObjectPermissionContextBase::Object>>
UsbChooserContext::GetGrantedObjects(const url::Origin& origin) { … }
std::vector<std::unique_ptr<permissions::ObjectPermissionContextBase::Object>>
UsbChooserContext::GetAllGrantedObjects() { … }
void UsbChooserContext::RevokeObjectPermission(
const url::Origin& origin,
const base::Value::Dict& object) { … }
void UsbChooserContext::RevokeDevicePermissionWebInitiated(
const url::Origin& origin,
const device::mojom::UsbDeviceInfo& device) { … }
void UsbChooserContext::RevokeObjectPermissionInternal(
const url::Origin& origin,
const base::Value::Dict& object,
bool revoked_by_website = false) { … }
std::string UsbChooserContext::GetKeyForObject(
const base::Value::Dict& object) { … }
bool UsbChooserContext::IsValidObject(const base::Value::Dict& object) { … }
std::u16string UsbChooserContext::GetObjectDisplayName(
const base::Value::Dict& object) { … }
void UsbChooserContext::GrantDevicePermission(
const url::Origin& origin,
const device::mojom::UsbDeviceInfo& device_info) { … }
bool UsbChooserContext::HasDevicePermission(
const url::Origin& origin,
const device::mojom::UsbDeviceInfo& device_info) { … }
void UsbChooserContext::GetDevices(
device::mojom::UsbDeviceManager::GetDevicesCallback callback) { … }
void UsbChooserContext::GetDevice(
const std::string& guid,
base::span<const uint8_t> blocked_interface_classes,
mojo::PendingReceiver<device::mojom::UsbDevice> device_receiver,
mojo::PendingRemote<device::mojom::UsbDeviceClient> device_client) { … }
const device::mojom::UsbDeviceInfo* UsbChooserContext::GetDeviceInfo(
const std::string& guid) { … }
#if BUILDFLAG(IS_ANDROID)
void UsbChooserContext::RefreshDeviceInfo(
const std::string& guid,
device::mojom::UsbDeviceManager::RefreshDeviceInfoCallback callback) {
EnsureConnectionWithDeviceManager();
device_manager_->RefreshDeviceInfo(
guid, base::BindOnce(&UsbChooserContext::OnDeviceInfoRefreshed,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
#endif
void UsbChooserContext::AddObserver(DeviceObserver* observer) { … }
void UsbChooserContext::RemoveObserver(DeviceObserver* observer) { … }
base::WeakPtr<UsbChooserContext> UsbChooserContext::AsWeakPtr() { … }
void UsbChooserContext::OnDeviceAdded(
device::mojom::UsbDeviceInfoPtr device_info) { … }
void UsbChooserContext::OnDeviceRemoved(
device::mojom::UsbDeviceInfoPtr device_info) { … }
void UsbChooserContext::OnDeviceManagerConnectionError() { … }
void UsbChooserContext::SetDeviceManagerForTesting(
mojo::PendingRemote<device::mojom::UsbDeviceManager> fake_device_manager) { … }