'use strict'; // These tests rely on the User Agent providing an implementation of the // WebUSB Testing API (https://wicg.github.io/webusb/test/). // // In Chromium-based browsers this implementation is provided by a polyfill // in order to reduce the amount of test-only code shipped to users. To enable // these tests the browser must be run with these options: // // --enable-blink-features=MojoJS,MojoJSTest let loadChromiumResources = Promise.resolve().then(() => { if (!MojoInterfaceInterceptor) { // Do nothing on non-Chromium-based browsers or when the Mojo bindings are // not present in the global namespace. return; } let chain = Promise.resolve(); [ '/resources/chromium/mojo_bindings.js', '/resources/chromium/string16.mojom.js', '/resources/chromium/device.mojom.js', '/resources/chromium/device_manager.mojom.js', '/resources/chromium/chooser_service.mojom.js', '/resources/chromium/webusb-test.js', ].forEach(path => { // Use importScripts for workers. if (typeof document === 'undefined') { chain = chain.then(() => importScripts(path)); return; } let script = document.createElement('script'); script.src = path; script.async = false; chain = chain.then(() => new Promise(resolve => { script.onload = () => resolve(); })); document.head.appendChild(script); }); return chain; }); function usb_test(func, name, properties) { promise_test(async () => { if (navigator.usb.test === undefined) { // Try loading a polyfill for the WebUSB Testing API. await loadChromiumResources; } await navigator.usb.test.initialize(); try { await func(); } finally { await navigator.usb.test.reset(); } }, name, properties); } // Returns a promise that is resolved when the next USBConnectionEvent of the // given type is received. function connectionEventPromise(eventType) { return new Promise(resolve => { let eventHandler = e => { assert_true(e instanceof USBConnectionEvent); navigator.usb.removeEventListener(eventType, eventHandler); resolve(e.device); }; navigator.usb.addEventListener(eventType, eventHandler); }); } // Creates a fake device and returns a promise that resolves once the // 'connect' event is fired for the fake device. The promise is resolved with // an object containing the fake USB device and the corresponding USBDevice. function getFakeDevice() { let promise = connectionEventPromise('connect'); let fakeDevice = navigator.usb.test.addFakeDevice(fakeDeviceInit); return promise.then(device => { return { device: device, fakeDevice: fakeDevice }; }); } // Disconnects the given device and returns a promise that is resolved when it // is done. function waitForDisconnect(fakeDevice) { let promise = connectionEventPromise('disconnect'); fakeDevice.disconnect(); return promise; } function assertRejectsWithError(promise, name, message) { return promise.then(() => { assert_unreached('expected promise to reject with ' + name); }, error => { assert_equals(error.name, name); if (message !== undefined) assert_equals(error.message, message); }); } function assertDeviceInfoEquals(usbDevice, deviceInit) { for (var property in deviceInit) { if (property == 'activeConfigurationValue') { if (deviceInit.activeConfigurationValue == 0) { assert_equals(usbDevice.configuration, null); } else { assert_equals(usbDevice.configuration.configurationValue, deviceInit.activeConfigurationValue); } } else if (Array.isArray(deviceInit[property])) { assert_equals(usbDevice[property].length, deviceInit[property].length); for (var i = 0; i < usbDevice[property].length; ++i) assertDeviceInfoEquals(usbDevice[property][i], deviceInit[property][i]); } else { assert_equals(usbDevice[property], deviceInit[property], property); } } } function callWithTrustedClick(callback) { return new Promise(resolve => { let button = document.createElement('button'); button.textContent = 'click to continue test'; button.style.display = 'block'; button.style.fontSize = '20px'; button.style.padding = '10px'; button.onclick = () => { resolve(callback()); document.body.removeChild(button); }; document.body.appendChild(button); test_driver.click(button); }); }