Chromium Code Reviews| 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..774dfe30ecac60d9b6c3bb55ee7f65c0e560c959 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"; |
| + |
| +bool ExtractFromDict(const std::string& key, |
| + const base::DictionaryValue* dict_value, |
| + int max, |
| + int* value) { |
| + int temp = 0; |
|
Reilly Grant (use Gerrit)
2016/10/20 23:16:52
nit: It isn't necessary to initialize this variabl
tbarzic
2016/10/21 00:05:05
Done.
|
| + if (!dict_value->GetInteger(key, &temp)) { |
| + *value = UsbDevicePermissionData::SPECIAL_VALUE_ANY; |
| + return true; |
| + } |
| + |
| + if (temp < UsbDevicePermissionData::SPECIAL_VALUE_ANY || temp > max) |
| + return false; |
| -} // namespace |
| + *value = temp; |
| + return true; |
| +} |
| -namespace extensions { |
| +} // namespace |
| -UsbDevicePermissionData::UsbDevicePermissionData() |
| - : vendor_id_(0), product_id_(0), interface_id_(ANY_INTERFACE) { |
| -} |
| +UsbDevicePermissionData::UsbDevicePermissionData() {} |
| -UsbDevicePermissionData::UsbDevicePermissionData(uint16_t vendor_id, |
| - uint16_t product_id, |
| - int interface_id) |
| +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,53 @@ 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 (temp < 0 || temp > std::numeric_limits<uint16_t>::max()) |
| + |
| + if (!ExtractFromDict(kProductIdKey, dict_value, kMaxId, &product_id_)) |
| + return false; |
| + // 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 (temp < 0 || temp > std::numeric_limits<uint16_t>::max()) |
| + } |
| + // 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 (!ExtractFromDict(kInterfaceClassKey, dict_value, kMaxInterfaceData, |
| + &interface_class_)) { |
| 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()) |
| + // Reject the permissoin if neither interface class nor vendor ID, product ID |
|
Reilly Grant (use Gerrit)
2016/10/20 23:16:52
s/permissoin/permission/
tbarzic
2016/10/21 00:05:05
Done.
|
| + // 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; |
| - 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 |