| // 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. |
| |
| #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 "extensions/common/extension_id.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 { |
| |
| // Stores information about a device saved with access granted. |
| 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); |
| |
| // A persistent device is one that can be recognized when it is reconnected |
| // and can therefore be remembered persistently by writing information about |
| // it to ExtensionPrefs. Currently this means it has a serial number string. |
| bool IsPersistent() const; |
| |
| // Convert the device to a serializable value, returns an is_none() value |
| // if the entry is not persistent. |
| 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; } |
| |
| // The device guid of a hid/USB device tracked by this entry. |
| std::string device_guid_; |
| // The type of device this entry represents. |
| Type type_; |
| // The vendor ID of this device. |
| uint16_t vendor_id_; |
| // The product ID of this device. |
| uint16_t product_id_; |
| // The serial number (possibly alphanumeric) of this device. |
| std::u16string serial_number_; |
| // The manufacturer string read from the device (optional). |
| std::u16string manufacturer_string_; |
| // The product string read from the device (optional). |
| std::u16string product_string_; |
| // The last time this device was used by the extension. |
| base::Time last_used_; |
| }; |
| |
| // Stores device permissions associated with a particular extension. |
| class DevicePermissions { |
| public: |
| DevicePermissions(const DevicePermissions&) = delete; |
| DevicePermissions& operator=(const DevicePermissions&) = delete; |
| |
| virtual ~DevicePermissions(); |
| |
| // Attempts to find a permission entry matching the given device. |
| 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; |
| |
| // Reads permissions out of ExtensionPrefs. |
| DevicePermissions(content::BrowserContext* context, |
| const ExtensionId& 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_; |
| }; |
| |
| // Manages saved device permissions for all extensions. |
| class DevicePermissionsManager : public KeyedService { |
| public: |
| explicit DevicePermissionsManager(content::BrowserContext* context); |
| ~DevicePermissionsManager() override; |
| |
| 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); |
| |
| // The DevicePermissions object for a given extension. |
| DevicePermissions* GetForExtension(const ExtensionId& extension_id); |
| |
| // Equivalent to calling GetForExtension and extracting the permission string |
| // for each entry. |
| std::vector<std::u16string> GetPermissionMessageStrings( |
| const ExtensionId& extension_id) const; |
| |
| void AllowUsbDevice(const ExtensionId& extension_id, |
| const device::mojom::UsbDeviceInfo& device_info); |
| void AllowHidDevice(const ExtensionId& extension_id, |
| const device::mojom::HidDeviceInfo& device); |
| |
| // Updates the "last used" timestamp on the given device entry and writes it |
| // out to ExtensionPrefs. |
| void UpdateLastUsed(const ExtensionId& extension_id, |
| scoped_refptr<DevicePermissionEntry> entry); |
| |
| // Revokes permission for the extension to access the given device. |
| void RemoveEntry(const ExtensionId& extension_id, |
| scoped_refptr<DevicePermissionEntry> entry); |
| |
| // Revokes permission for an ephemeral hid/USB device by its guid. |
| void RemoveEntryByDeviceGUID(DevicePermissionEntry::Type type, |
| const std::string& guid); |
| |
| // Revokes permission for the extension to access all allowed devices. |
| void Clear(const ExtensionId& extension_id); |
| |
| private: |
| friend class DevicePermissionsManagerFactory; |
| FRIEND_TEST_ALL_PREFIXES(DevicePermissionsManagerTest, SuspendExtension); |
| |
| DevicePermissions* GetInternal(const ExtensionId& 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; |
| |
| // BrowserContextKeyedServiceFactory implementation |
| std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext( |
| content::BrowserContext* context) const override; |
| content::BrowserContext* GetBrowserContextToUse( |
| content::BrowserContext* context) const override; |
| }; |
| |
| } // namespace extensions |
| |
| #endif // EXTENSIONS_BROWSER_API_DEVICE_PERMISSIONS_MANAGER_H_ |