blob: 299109b5f5eb816a3fc82c9c41aa78fb48cec348 [file] [log] [blame]
// 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 <stdint.h>
#include <map>
#include <memory>
#include <set>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.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 <typename T>
struct DefaultSingletonTraits;
class Value;
}
namespace content {
class BrowserContext;
}
namespace extensions {
// Stores information about a device saved with access granted.
class DevicePermissionEntry : public base::RefCounted<DevicePermissionEntry> {
public:
enum class Type {
USB,
HID,
};
DevicePermissionEntry(scoped_refptr<device::UsbDevice> device);
DevicePermissionEntry(scoped_refptr<device::HidDeviceInfo> 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.
std::unique_ptr<base::Value> 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<DevicePermissionEntry>;
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<device::UsbDevice> 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<device::HidDeviceInfo> 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<DevicePermissionEntry> FindUsbDeviceEntry(
scoped_refptr<device::UsbDevice> device) const;
scoped_refptr<DevicePermissionEntry> FindHidDeviceEntry(
scoped_refptr<device::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 std::string& extension_id);
std::set<scoped_refptr<DevicePermissionEntry>> entries_;
std::map<device::UsbDevice*, scoped_refptr<DevicePermissionEntry>>
ephemeral_usb_devices_;
std::map<device::HidDeviceInfo*, scoped_refptr<DevicePermissionEntry>>
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<base::string16> GetPermissionMessageStrings(
const std::string& extension_id) const;
void AllowUsbDevice(const std::string& extension_id,
scoped_refptr<device::UsbDevice> device);
void AllowHidDevice(const std::string& extension_id,
scoped_refptr<device::HidDeviceInfo> 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<DevicePermissionEntry> entry);
// Revokes permission for the extension to access the given device.
void RemoveEntry(const std::string& extension_id,
scoped_refptr<DevicePermissionEntry> 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::UsbDevice> device) override;
// HidService::Observer implementation
void OnDeviceRemovedCleanup(
scoped_refptr<device::HidDeviceInfo> device) override;
base::ThreadChecker thread_checker_;
content::BrowserContext* context_;
std::map<std::string, DevicePermissions*> extension_id_to_device_permissions_;
ScopedObserver<device::UsbService, device::UsbService::Observer>
usb_service_observer_;
ScopedObserver<device::HidService, device::HidService::Observer>
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();
~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_