| Index: extensions/browser/api/usb/usb_api.cc
|
| diff --git a/extensions/browser/api/usb/usb_api.cc b/extensions/browser/api/usb/usb_api.cc
|
| index a821db89b200ed5766e07d929daf692f92c00a09..389d3ce3b76481840490a1e3335ba992d98372e2 100644
|
| --- a/extensions/browser/api/usb/usb_api.cc
|
| +++ b/extensions/browser/api/usb/usb_api.cc
|
| @@ -7,6 +7,7 @@
|
| #include <algorithm>
|
| #include <memory>
|
| #include <numeric>
|
| +#include <set>
|
| #include <string>
|
| #include <utility>
|
| #include <vector>
|
| @@ -409,12 +410,10 @@ bool UsbPermissionCheckingFunction::HasDevicePermission(
|
| return true;
|
| }
|
|
|
| - UsbDevicePermission::CheckParam param(
|
| - device->vendor_id(),
|
| - device->product_id(),
|
| - UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
|
| + std::unique_ptr<UsbDevicePermission::CheckParam> param =
|
| + UsbDevicePermission::CheckParam::ForUsbDevice(extension(), device.get());
|
| if (extension()->permissions_data()->CheckAPIPermissionWithParam(
|
| - APIPermission::kUsbDevice, ¶m)) {
|
| + APIPermission::kUsbDevice, param.get())) {
|
| return true;
|
| }
|
|
|
| @@ -504,10 +503,19 @@ ExtensionFunction::ResponseAction UsbFindDevicesFunction::Run() {
|
| product_id_ = parameters->options.product_id;
|
| int interface_id = parameters->options.interface_id.get()
|
| ? *parameters->options.interface_id
|
| - : UsbDevicePermissionData::ANY_INTERFACE;
|
| - UsbDevicePermission::CheckParam param(vendor_id_, product_id_, interface_id);
|
| + : UsbDevicePermissionData::SPECIAL_VALUE_ANY;
|
| + // Bail out early if there is no chance that the app has manifest permission
|
| + // for the USB device described by vendor ID, product ID, and interface ID.
|
| + // Note that this will match any permission filter that has only interface
|
| + // class specified - in order to match interface class information about
|
| + // device interfaces is needed, which is not known at this point; the
|
| + // permission will have to be checked again when the USB device info is
|
| + // fetched.
|
| + std::unique_ptr<UsbDevicePermission::CheckParam> param =
|
| + UsbDevicePermission::CheckParam::ForDeviceWithAnyInterfaceClass(
|
| + extension(), vendor_id_, product_id_, interface_id);
|
| if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
|
| - APIPermission::kUsbDevice, ¶m)) {
|
| + APIPermission::kUsbDevice, param.get())) {
|
| return RespondNow(Error(kErrorPermissionDenied));
|
| }
|
|
|
| @@ -528,9 +536,25 @@ void UsbFindDevicesFunction::OnGetDevicesComplete(
|
| devices.size(), base::Bind(&UsbFindDevicesFunction::OpenComplete, this));
|
|
|
| for (const scoped_refptr<UsbDevice>& device : devices) {
|
| + // Skip the device whose vendor and product ID do not match the target one.
|
| if (device->vendor_id() != vendor_id_ ||
|
| device->product_id() != product_id_) {
|
| barrier_.Run();
|
| + continue;
|
| + }
|
| +
|
| + // Verify that the app has permission for the device again, this time taking
|
| + // device's interface classes into account - in case there is a USB device
|
| + // permission specifying only interfaceClass, permissions check in |Run|
|
| + // might have passed even though the app did not have permission for
|
| + // specified vendor and product ID (as actual permissions check had to be
|
| + // deferred until device's interface classes are known).
|
| + std::unique_ptr<UsbDevicePermission::CheckParam> param =
|
| + UsbDevicePermission::CheckParam::ForUsbDevice(extension(),
|
| + device.get());
|
| + if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
|
| + APIPermission::kUsbDevice, param.get())) {
|
| + barrier_.Run();
|
| } else {
|
| device->Open(base::Bind(&UsbFindDevicesFunction::OnDeviceOpened, this));
|
| }
|
|
|