Files
tubestation/testing/web-platform/tests/webusb/usb.https.window.js
François Beaufort c693df8cd5 Bug 1838795 [wpt PR 40582] - WebUSB: Add exclusionFilters to USBRequestDeviceOptions, a=testonly
Automatic update from web-platform-tests
WebUSB: Add exclusionFilters to USBRequestDeviceOptions

This CL adds a new "exclusionFilters" option in
navigator.usb.requestDevice() options so that web developers can
exclude from the browser picker some devices that are known to not work
as expected.

Intent to Ship: https://groups.google.com/a/chromium.org/g/blink-dev/c/e1mgO-m8zvQ
Spec:
- https://github.com/WICG/webusb/pull/233
- https://github.com/WICG/webusb/pull/235
Demo: https://usb-exclusion-filters.glitch.me/

Bug: 1455392
Change-Id: I1b61d9daae3e14accedb24e493ae656316427893
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4614682
Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org>
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Commit-Queue: Fr <beaufort.francois@gmail.com>
Cr-Commit-Position: refs/heads/main@{#1161953}

--

wpt-commits: b7727490c96a87eb3f40fe43f266ad05368ab2b0
wpt-pr: 40582
2023-07-06 08:21:04 +00:00

140 lines
4.6 KiB
JavaScript

// META: script=/resources/testdriver.js
// META: script=/resources/testdriver-vendor.js
// META: script=/resources/test-only-api.js
// META: script=/webusb/resources/fake-devices.js
// META: script=/webusb/resources/usb-helpers.js
'use strict';
usb_test(() => {
return navigator.usb.requestDevice({ filters: [] })
.then(device => {
assert_unreachable('requestDevice should reject without a user gesture');
})
.catch(error => {
assert_equals(error.code, DOMException.SECURITY_ERR);
});
}, 'requestDevice rejects when called without a user gesture');
usb_test(() => {
return callWithTrustedClick(() => navigator.usb.requestDevice({ filters: [] })
.then(device => {
assert_unreachable('requestDevice should reject when no device selected');
})
.catch(error => {
assert_equals(error.code, DOMException.NOT_FOUND_ERR);
})
);
}, 'requestDevice rejects when no device is chosen');
usb_test(() => {
return getFakeDevice().then(({ device, fakeDevice }) => {
navigator.usb.test.onrequestdevice = event => {
navigator.usb.test.onrequestdevice = undefined;
event.respondWith(fakeDevice);
};
return callWithTrustedClick(() => {
return navigator.usb.requestDevice({ filters: [] }).then(chosenDevice => {
assert_equals(chosenDevice, device);
});
});
});
}, 'requestDevice returns the device chosen by the user');
usb_test(() => {
return getFakeDevice().then(({ device, fakeDevice }) => {
navigator.usb.test.onrequestdevice = event => {
navigator.usb.test.onrequestdevice = undefined;
event.respondWith(fakeDevice);
};
return callWithTrustedClick(() => {
return navigator.usb.requestDevice({ filters: [] }).then(chosenDevice => {
assert_equals(chosenDevice, device);
return navigator.usb.getDevices().then(devices => {
assert_equals(devices.length, 1);
assert_equals(devices[0], chosenDevice);
});
});
});
});
}, 'getDevices returns the same object as requestDevice');
usb_test(() => {
const expectedFilters = [
{ vendorId: 1234, classCode: 0xFF, serialNumber: "123ABC" },
{ vendorId: 5678, productId: 0xF00F },
{ vendorId: 9012, classCode: 0xFF, subclassCode: 0xEE, protocolCode: 0xDD },
];
navigator.usb.test.onrequestdevice = event => {
navigator.usb.test.onrequestdevice = undefined;
assert_equals(event.filters.length, expectedFilters.length);
for (var i = 0; i < event.filters.length; ++i) {
assert_object_equals(event.filters[i], expectedFilters[i]);
}
assert_equals(event.exclusionFilters.length, expectedFilters.length);
for (var i = 0; i < event.exclusionFilters.length; ++i) {
assert_object_equals(event.exclusionFilters[i], expectedFilters[i]);
}
event.respondWith(null);
};
const filters = expectedFilters;
const exclusionFilters = expectedFilters;
return callWithTrustedClick(() => {
return navigator.usb.requestDevice({ filters, exclusionFilters })
.then(device => {
assert_unreached(
'requestDevice should reject because no device selected');
})
.catch(error => {
assert_equals(error.code, DOMException.NOT_FOUND_ERR);
});
});
}, 'filters are sent correctly');
usb_test(async () => {
const badFilters = [
{ productId: 1234 }, // productId requires vendorId
{ subclassCode: 5678 }, // subclassCode requires classCode
{ protocolCode: 9012 }, // protocolCode requires subclassCode
];
const badFilterOptions = ['filters', 'exclusionFilters'].flatMap(key => {
return badFilters.map(filter => ({[key]: [filter]}));
});
for (const badFilterOption of badFilterOptions) {
await callWithTrustedClick(async () => {
try {
await navigator.usb.requestDevice(badFilterOption);
assert_unreached(
'requestDevice should reject because of invalid filters');
} catch (error) {
assert_equals(error.name, 'TypeError');
}
});
}
}, 'requestDevice rejects on invalid filters');
usb_test(() => {
return getFakeDevice().then(({ device, fakeDevice }) => {
navigator.usb.test.onrequestdevice = event => {
event.respondWith(fakeDevice);
};
return callWithTrustedClick(() => {
let first = navigator.usb.requestDevice({ filters: [] });
let second = navigator.usb.requestDevice({ filters: [] });
return Promise.all([
first.then(chosenDevice => {
assert_equals(chosenDevice, device);
}),
second.then(chosenDevice => {
assert_equals(chosenDevice, device);
})
]);
});
});
}, 'multiple requestDevice calls are allowed per user activation');