#ifndef EXTENSIONS_BROWSER_API_DEVICE_PERMISSIONS_MANAGER_H_
#define EXTENSIONS_BROWSER_API_DEVICE_PERMISSIONS_MANAGER_H_
#include <stdint.h>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
#include "components/keyed_service/core/keyed_service.h"
#include "services/device/public/mojom/hid.mojom.h"
#include "services/device/public/mojom/usb_device.mojom.h"
namespace base {
template <typename T>
struct DefaultSingletonTraits;
}
namespace content {
class BrowserContext;
}
namespace device {
class UsbDevice;
}
namespace extensions {
class DevicePermissionEntry : public base::RefCounted<DevicePermissionEntry> {
public:
enum class Type {
USB,
HID,
};
explicit DevicePermissionEntry(const device::mojom::UsbDeviceInfo& device);
explicit DevicePermissionEntry(const device::mojom::HidDeviceInfo& device);
DevicePermissionEntry(Type type,
uint16_t vendor_id,
uint16_t product_id,
const std::u16string& serial_number,
const std::u16string& manufacturer_string,
const std::u16string& product_string,
const base::Time& last_used);
bool IsPersistent() const;
base::Value::Dict ToValue() const;
std::u16string GetPermissionMessageString() const;
Type type() const { return type_; }
uint16_t vendor_id() const { return vendor_id_; }
uint16_t product_id() const { return product_id_; }
const std::u16string& serial_number() const { return serial_number_; }
const base::Time& last_used() const { return last_used_; }
std::u16string GetManufacturer() const;
std::u16string GetProduct() const;
private:
friend class base::RefCounted<DevicePermissionEntry>;
friend class DevicePermissionsManager;
~DevicePermissionEntry();
void set_last_used(const base::Time& last_used) { last_used_ = last_used; }
std::string device_guid_;
Type type_;
uint16_t vendor_id_;
uint16_t product_id_;
std::u16string serial_number_;
std::u16string manufacturer_string_;
std::u16string product_string_;
base::Time last_used_;
};
class DevicePermissions {
public:
DevicePermissions(const DevicePermissions&) = delete;
DevicePermissions& operator=(const DevicePermissions&) = delete;
virtual ~DevicePermissions();
scoped_refptr<DevicePermissionEntry> FindUsbDeviceEntry(
scoped_refptr<device::UsbDevice> device) const;
scoped_refptr<DevicePermissionEntry> FindUsbDeviceEntry(
const device::mojom::UsbDeviceInfo& device) const;
scoped_refptr<DevicePermissionEntry> FindHidDeviceEntry(
const device::mojom::HidDeviceInfo& device) const;
const std::set<scoped_refptr<DevicePermissionEntry>>& entries() const {
return entries_;
}
private:
friend class DevicePermissionsManager;
DevicePermissions(content::BrowserContext* context,
const std::string& extension_id);
std::set<scoped_refptr<DevicePermissionEntry>> entries_;
std::map<std::string, scoped_refptr<DevicePermissionEntry>>
ephemeral_usb_devices_;
std::map<std::string, scoped_refptr<DevicePermissionEntry>>
ephemeral_hid_devices_;
};
class DevicePermissionsManager : public KeyedService {
public:
DevicePermissionsManager(const DevicePermissionsManager&) = delete;
DevicePermissionsManager& operator=(const DevicePermissionsManager&) = delete;
static DevicePermissionsManager* Get(content::BrowserContext* context);
static std::u16string GetPermissionMessage(
uint16_t vendor_id,
uint16_t product_id,
const std::u16string& manufacturer_string,
const std::u16string& product_string,
const std::u16string& serial_number,
bool always_include_manufacturer);
DevicePermissions* GetForExtension(const std::string& extension_id);
std::vector<std::u16string> GetPermissionMessageStrings(
const std::string& extension_id) const;
void AllowUsbDevice(const std::string& extension_id,
const device::mojom::UsbDeviceInfo& device_info);
void AllowHidDevice(const std::string& extension_id,
const device::mojom::HidDeviceInfo& device);
void UpdateLastUsed(const std::string& extension_id,
scoped_refptr<DevicePermissionEntry> entry);
void RemoveEntry(const std::string& extension_id,
scoped_refptr<DevicePermissionEntry> entry);
void RemoveEntryByDeviceGUID(DevicePermissionEntry::Type type,
const std::string& guid);
void Clear(const std::string& extension_id);
private:
friend class DevicePermissionsManagerFactory;
FRIEND_TEST_ALL_PREFIXES(DevicePermissionsManagerTest, SuspendExtension);
explicit DevicePermissionsManager(content::BrowserContext* context);
~DevicePermissionsManager() override;
DevicePermissions* GetInternal(const std::string& extension_id) const;
base::ThreadChecker thread_checker_;
raw_ptr<content::BrowserContext> context_;
std::map<std::string, DevicePermissions*> extension_id_to_device_permissions_;
};
class DevicePermissionsManagerFactory
: public BrowserContextKeyedServiceFactory {
public:
DevicePermissionsManagerFactory(const DevicePermissionsManagerFactory&) =
delete;
DevicePermissionsManagerFactory& operator=(
const DevicePermissionsManagerFactory&) = delete;
static DevicePermissionsManager* GetForBrowserContext(
content::BrowserContext* context);
static DevicePermissionsManagerFactory* GetInstance();
private:
friend struct base::DefaultSingletonTraits<DevicePermissionsManagerFactory>;
DevicePermissionsManagerFactory();
~DevicePermissionsManagerFactory() override;
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
content::BrowserContext* GetBrowserContextToUse(
content::BrowserContext* context) const override;
};
}
#endif