// Copyright 2014 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. #ifndef EXTENSIONS_DEVICE_PERMISSION_MANAGER_H_ #define EXTENSIONS_DEVICE_PERMISSION_MANAGER_H_ #include #include #include #include #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/scoped_observer.h" #include "base/strings/string16.h" #include "base/threading/thread_checker.h" #include "components/keyed_service/content/browser_context_keyed_service_factory.h" #include "components/keyed_service/core/keyed_service.h" #include "device/hid/hid_service.h" #include "device/usb/usb_service.h" namespace base { template struct DefaultSingletonTraits; class Value; } namespace content { class BrowserContext; } namespace extensions { // Stores information about a device saved with access granted. class DevicePermissionEntry : public base::RefCounted { public: enum class Type { USB, HID, }; DevicePermissionEntry(scoped_refptr device); DevicePermissionEntry(scoped_refptr device); DevicePermissionEntry(Type type, uint16_t vendor_id, uint16_t product_id, const base::string16& serial_number, const base::string16& manufacturer_string, const base::string16& 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 a null pointer if the // entry is not persistent. scoped_ptr ToValue() const; base::string16 GetPermissionMessageString() const; Type type() const { return type_; } uint16_t vendor_id() const { return vendor_id_; } uint16_t product_id() const { return product_id_; } const base::string16& serial_number() const { return serial_number_; } const base::Time& last_used() const { return last_used_; } base::string16 GetManufacturer() const; base::string16 GetProduct() const; private: friend class base::RefCounted; friend class DevicePermissionsManager; ~DevicePermissionEntry(); void set_last_used(const base::Time& last_used) { last_used_ = last_used; } // The USB device tracked by this entry. Will be nullptr if this entry was // restored from ExtensionPrefs or type_ is not Type::USB. scoped_refptr usb_device_; // The HID device tracked by this entry. Will be nullptr if this entry was // restored from ExtensionPrefs or type_ is not Type::HID. scoped_refptr hid_device_; // 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. base::string16 serial_number_; // The manufacturer string read from the device (optional). base::string16 manufacturer_string_; // The product string read from the device (optional). base::string16 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: virtual ~DevicePermissions(); // Attempts to find a permission entry matching the given device. scoped_refptr FindUsbDeviceEntry( scoped_refptr device) const; scoped_refptr FindHidDeviceEntry( scoped_refptr device) const; const std::set>& entries() const { return entries_; } private: friend class DevicePermissionsManager; // Reads permissions out of ExtensionPrefs. DevicePermissions(content::BrowserContext* context, const std::string& extension_id); std::set> entries_; std::map> ephemeral_usb_devices_; std::map> ephemeral_hid_devices_; DISALLOW_COPY_AND_ASSIGN(DevicePermissions); }; // Manages saved device permissions for all extensions. class DevicePermissionsManager : public KeyedService, public device::UsbService::Observer, public device::HidService::Observer { public: static DevicePermissionsManager* Get(content::BrowserContext* context); static base::string16 GetPermissionMessage( uint16_t vendor_id, uint16_t product_id, const base::string16& manufacturer_string, const base::string16& product_string, const base::string16& serial_number, bool always_include_manufacturer); // The DevicePermissions object for a given extension. DevicePermissions* GetForExtension(const std::string& extension_id); // Equivalent to calling GetForExtension and extracting the permission string // for each entry. std::vector GetPermissionMessageStrings( const std::string& extension_id) const; void AllowUsbDevice(const std::string& extension_id, scoped_refptr device); void AllowHidDevice(const std::string& extension_id, scoped_refptr device); // Updates the "last used" timestamp on the given device entry and writes it // out to ExtensionPrefs. void UpdateLastUsed(const std::string& extension_id, scoped_refptr entry); // Revokes permission for the extension to access the given device. void RemoveEntry(const std::string& extension_id, scoped_refptr entry); // Revokes permission for the extension to access all allowed devices. void Clear(const std::string& extension_id); private: friend class DevicePermissionsManagerFactory; FRIEND_TEST_ALL_PREFIXES(DevicePermissionsManagerTest, SuspendExtension); DevicePermissionsManager(content::BrowserContext* context); ~DevicePermissionsManager() override; DevicePermissions* GetInternal(const std::string& extension_id) const; // UsbService::Observer implementation void OnDeviceRemovedCleanup(scoped_refptr device) override; // HidService::Observer implementation void OnDeviceRemovedCleanup( scoped_refptr device) override; base::ThreadChecker thread_checker_; content::BrowserContext* context_; std::map extension_id_to_device_permissions_; ScopedObserver usb_service_observer_; ScopedObserver hid_service_observer_; DISALLOW_COPY_AND_ASSIGN(DevicePermissionsManager); }; class DevicePermissionsManagerFactory : public BrowserContextKeyedServiceFactory { public: static DevicePermissionsManager* GetForBrowserContext( content::BrowserContext* context); static DevicePermissionsManagerFactory* GetInstance(); private: friend struct base::DefaultSingletonTraits; DevicePermissionsManagerFactory(); ~DevicePermissionsManagerFactory() override; // BrowserContextKeyedServiceFactory implementation KeyedService* BuildServiceInstanceFor( content::BrowserContext* context) const override; content::BrowserContext* GetBrowserContextToUse( content::BrowserContext* context) const override; DISALLOW_COPY_AND_ASSIGN(DevicePermissionsManagerFactory); }; } // namespace extensions #endif // EXTENSIONS_DEVICE_PERMISSION_MANAGER_H_