| Index: extensions/common/permissions/usb_device_permission_data.cc
|
| diff --git a/extensions/common/permissions/usb_device_permission_data.cc b/extensions/common/permissions/usb_device_permission_data.cc
|
| index c23b0b21c81b3968d3853977cd3a91c0e7484140..982b9e4e1f29a70e6271969ad7b5935d919aab4e 100644
|
| --- a/extensions/common/permissions/usb_device_permission_data.cc
|
| +++ b/extensions/common/permissions/usb_device_permission_data.cc
|
| @@ -4,6 +4,8 @@
|
|
|
| #include "extensions/common/permissions/usb_device_permission_data.h"
|
|
|
| +#include <stdint.h>
|
| +
|
| #include <limits>
|
| #include <memory>
|
| #include <string>
|
| @@ -16,26 +18,44 @@
|
| #include "extensions/common/permissions/api_permission.h"
|
| #include "extensions/common/permissions/usb_device_permission.h"
|
|
|
| +namespace extensions {
|
| +
|
| namespace {
|
|
|
| const char kProductIdKey[] = "productId";
|
| const char kVendorIdKey[] = "vendorId";
|
| const char kInterfaceIdKey[] = "interfaceId";
|
| +const char kInterfaceClassKey[] = "interfaceClass";
|
|
|
| -} // namespace
|
| +bool ExtractFromDict(const std::string& key,
|
| + const base::DictionaryValue* dict_value,
|
| + int max,
|
| + int* value) {
|
| + int temp;
|
| + if (!dict_value->GetInteger(key, &temp)) {
|
| + *value = UsbDevicePermissionData::SPECIAL_VALUE_ANY;
|
| + return true;
|
| + }
|
|
|
| -namespace extensions {
|
| + if (temp < UsbDevicePermissionData::SPECIAL_VALUE_ANY || temp > max)
|
| + return false;
|
|
|
| -UsbDevicePermissionData::UsbDevicePermissionData()
|
| - : vendor_id_(0), product_id_(0), interface_id_(ANY_INTERFACE) {
|
| + *value = temp;
|
| + return true;
|
| }
|
|
|
| -UsbDevicePermissionData::UsbDevicePermissionData(uint16_t vendor_id,
|
| - uint16_t product_id,
|
| - int interface_id)
|
| +} // namespace
|
| +
|
| +UsbDevicePermissionData::UsbDevicePermissionData() {}
|
| +
|
| +UsbDevicePermissionData::UsbDevicePermissionData(int vendor_id,
|
| + int product_id,
|
| + int interface_id,
|
| + int interface_class)
|
| : vendor_id_(vendor_id),
|
| product_id_(product_id),
|
| - interface_id_(interface_id) {}
|
| + interface_id_(interface_id),
|
| + interface_class_(interface_class) {}
|
|
|
| bool UsbDevicePermissionData::Check(
|
| const APIPermission::CheckParam* param) const {
|
| @@ -43,10 +63,25 @@ bool UsbDevicePermissionData::Check(
|
| return false;
|
| const UsbDevicePermission::CheckParam& specific_param =
|
| *static_cast<const UsbDevicePermission::CheckParam*>(param);
|
| - return vendor_id_ == specific_param.vendor_id &&
|
| - product_id_ == specific_param.product_id &&
|
| - (specific_param.interface_id == UNSPECIFIED_INTERFACE ||
|
| - interface_id_ == specific_param.interface_id);
|
| +
|
| + // The permission should be ignored if it filters by interface class when
|
| + // filtering by interface class is not allowed.
|
| + if (!specific_param.interface_class_allowed &&
|
| + interface_class_ != SPECIAL_VALUE_ANY) {
|
| + return false;
|
| + }
|
| + DCHECK(specific_param.interface_class_allowed ||
|
| + (vendor_id_ != SPECIAL_VALUE_ANY && product_id_ != SPECIAL_VALUE_ANY));
|
| +
|
| + return (vendor_id_ == SPECIAL_VALUE_ANY ||
|
| + vendor_id_ == specific_param.vendor_id) &&
|
| + (product_id_ == SPECIAL_VALUE_ANY ||
|
| + product_id_ == specific_param.product_id) &&
|
| + (specific_param.interface_id == SPECIAL_VALUE_UNSPECIFIED ||
|
| + interface_id_ == specific_param.interface_id) &&
|
| + (!specific_param.interface_classes ||
|
| + interface_class_ == SPECIAL_VALUE_ANY ||
|
| + specific_param.interface_classes->count(interface_class_) > 0);
|
| }
|
|
|
| std::unique_ptr<base::Value> UsbDevicePermissionData::ToValue() const {
|
| @@ -54,6 +89,7 @@ std::unique_ptr<base::Value> UsbDevicePermissionData::ToValue() const {
|
| result->SetInteger(kVendorIdKey, vendor_id_);
|
| result->SetInteger(kProductIdKey, product_id_);
|
| result->SetInteger(kInterfaceIdKey, interface_id_);
|
| + result->SetInteger(kInterfaceClassKey, interface_class_);
|
| return std::unique_ptr<base::Value>(result);
|
| }
|
|
|
| @@ -65,40 +101,61 @@ bool UsbDevicePermissionData::FromValue(const base::Value* value) {
|
| if (!value->GetAsDictionary(&dict_value))
|
| return false;
|
|
|
| - int temp;
|
| - if (!dict_value->GetInteger(kVendorIdKey, &temp))
|
| + const int kMaxId = std::numeric_limits<uint16_t>::max();
|
| + if (!ExtractFromDict(kVendorIdKey, dict_value, kMaxId, &vendor_id_))
|
| + return false;
|
| +
|
| + if (!ExtractFromDict(kProductIdKey, dict_value, kMaxId, &product_id_))
|
| return false;
|
| - if (temp < 0 || temp > std::numeric_limits<uint16_t>::max())
|
| + // If product ID is specified, so should be vendor ID.
|
| + if (product_id_ != SPECIAL_VALUE_ANY && vendor_id_ == SPECIAL_VALUE_ANY)
|
| return false;
|
| - vendor_id_ = temp;
|
|
|
| - if (!dict_value->GetInteger(kProductIdKey, &temp))
|
| + const int kMaxInterfaceData = std::numeric_limits<uint8_t>::max();
|
| + if (!ExtractFromDict(kInterfaceIdKey, dict_value, kMaxInterfaceData,
|
| + &interface_id_)) {
|
| + return false;
|
| + }
|
| + // If interface ID is specified, so should be vendor ID and product ID (note
|
| + // that product ID being set implies that vendor ID is set).
|
| + if (interface_id_ != SPECIAL_VALUE_ANY && product_id_ == SPECIAL_VALUE_ANY)
|
| return false;
|
| - if (temp < 0 || temp > std::numeric_limits<uint16_t>::max())
|
| +
|
| + if (!ExtractFromDict(kInterfaceClassKey, dict_value, kMaxInterfaceData,
|
| + &interface_class_)) {
|
| + return false;
|
| + }
|
| +
|
| + // Reject the permission if neither interface class nor vendor ID, product ID
|
| + // pair is specified in the permission.
|
| + // Note that set product ID implies that vendor ID is set as well, so only
|
| + // product ID has to be checked.
|
| + if (interface_class_ == SPECIAL_VALUE_ANY && product_id_ == SPECIAL_VALUE_ANY)
|
| return false;
|
| - product_id_ = temp;
|
|
|
| - if (!dict_value->GetInteger(kInterfaceIdKey, &temp))
|
| - interface_id_ = ANY_INTERFACE;
|
| - else if (temp < ANY_INTERFACE || temp > std::numeric_limits<uint8_t>::max())
|
| + // Interface ID is ignored, but kept for backward compatibility - don't allow
|
| + // it's usage with interface class, as interface class property was introduced
|
| + // after interface ID support was dropped.
|
| + if (interface_class_ != SPECIAL_VALUE_ANY &&
|
| + interface_id_ != SPECIAL_VALUE_ANY) {
|
| return false;
|
| - else
|
| - interface_id_ = temp;
|
| + }
|
|
|
| return true;
|
| }
|
|
|
| bool UsbDevicePermissionData::operator<(
|
| const UsbDevicePermissionData& rhs) const {
|
| - return std::tie(vendor_id_, product_id_, interface_id_) <
|
| - std::tie(rhs.vendor_id_, rhs.product_id_, rhs.interface_id_);
|
| + return std::tie(vendor_id_, product_id_, interface_id_, interface_class_) <
|
| + std::tie(rhs.vendor_id_, rhs.product_id_, rhs.interface_id_,
|
| + rhs.interface_class_);
|
| }
|
|
|
| bool UsbDevicePermissionData::operator==(
|
| const UsbDevicePermissionData& rhs) const {
|
| - return vendor_id_ == rhs.vendor_id_ &&
|
| - product_id_ == rhs.product_id_ &&
|
| - interface_id_ == rhs.interface_id_;
|
| + return vendor_id_ == rhs.vendor_id_ && product_id_ == rhs.product_id_ &&
|
| + interface_id_ == rhs.interface_id_ &&
|
| + interface_class_ == rhs.interface_class_;
|
| }
|
|
|
| } // namespace extensions
|
|
|