| // 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'); |