tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

usb.https.window.js (4746B)


      1 // META: script=/resources/testdriver.js
      2 // META: script=/resources/testdriver-vendor.js
      3 // META: script=/resources/test-only-api.js
      4 // META: script=/webusb/resources/fake-devices.js
      5 // META: script=/webusb/resources/usb-helpers.js
      6 'use strict';
      7 
      8 usb_test(() => {
      9  return navigator.usb.requestDevice({ filters: [] })
     10    .then(device => {
     11      assert_unreachable('requestDevice should reject without a user gesture');
     12    })
     13    .catch(error => {
     14      assert_equals(error.code, DOMException.SECURITY_ERR);
     15    });
     16 }, 'requestDevice rejects when called without a user gesture');
     17 
     18 usb_test(() => {
     19  return callWithTrustedClick(() => navigator.usb.requestDevice({ filters: [] })
     20    .then(device => {
     21      assert_unreachable('requestDevice should reject when no device selected');
     22    })
     23    .catch(error => {
     24      assert_equals(error.code, DOMException.NOT_FOUND_ERR);
     25    })
     26  );
     27 }, 'requestDevice rejects when no device is chosen');
     28 
     29 usb_test(() => {
     30  return getFakeDevice().then(({ device, fakeDevice }) => {
     31    navigator.usb.test.onrequestdevice = event => {
     32      navigator.usb.test.onrequestdevice = undefined;
     33      event.respondWith(fakeDevice);
     34    };
     35    return callWithTrustedClick(() => {
     36      return navigator.usb.requestDevice({ filters: [] }).then(chosenDevice => {
     37        assert_equals(chosenDevice, device);
     38      });
     39    });
     40  });
     41 }, 'requestDevice returns the device chosen by the user');
     42 
     43 usb_test(() => {
     44  return getFakeDevice().then(({ device, fakeDevice }) => {
     45    navigator.usb.test.onrequestdevice = event => {
     46      navigator.usb.test.onrequestdevice = undefined;
     47      event.respondWith(fakeDevice);
     48    };
     49    return callWithTrustedClick(() => {
     50      return navigator.usb.requestDevice({ filters: [] }).then(chosenDevice => {
     51        assert_equals(chosenDevice, device);
     52        return navigator.usb.getDevices().then(devices => {
     53          assert_equals(devices.length, 1);
     54          assert_equals(devices[0], chosenDevice);
     55        });
     56      });
     57    });
     58  });
     59 }, 'getDevices returns the same object as requestDevice');
     60 
     61 usb_test(() => {
     62  const expectedFilters = [
     63    { vendorId: 1234, classCode: 0xFF, serialNumber: "123ABC" },
     64    { vendorId: 5678, productId: 0xF00F },
     65    { vendorId: 9012, classCode: 0xFF, subclassCode: 0xEE, protocolCode: 0xDD },
     66  ];
     67 
     68  navigator.usb.test.onrequestdevice = event => {
     69    navigator.usb.test.onrequestdevice = undefined;
     70 
     71    assert_equals(event.filters.length, expectedFilters.length);
     72    for (var i = 0; i < event.filters.length; ++i) {
     73      assert_object_equals(event.filters[i], expectedFilters[i]);
     74    }
     75 
     76    assert_equals(event.exclusionFilters.length, expectedFilters.length);
     77    for (var i = 0; i < event.exclusionFilters.length; ++i) {
     78      assert_object_equals(event.exclusionFilters[i], expectedFilters[i]);
     79    }
     80 
     81    event.respondWith(null);
     82  };
     83 
     84  const filters = expectedFilters;
     85  const exclusionFilters = expectedFilters;
     86  return callWithTrustedClick(() => {
     87    return navigator.usb.requestDevice({ filters, exclusionFilters })
     88      .then(device => {
     89        assert_unreached(
     90            'requestDevice should reject because no device selected');
     91      })
     92      .catch(error => {
     93        assert_equals(error.code, DOMException.NOT_FOUND_ERR);
     94      });
     95  });
     96 }, 'filters are sent correctly');
     97 
     98 usb_test(async () => {
     99  const badFilters = [
    100    { productId: 1234 },     // productId requires vendorId
    101    { subclassCode: 5678 },  // subclassCode requires classCode
    102    { protocolCode: 9012 },  // protocolCode requires subclassCode
    103  ];
    104  const badFilterOptions = ['filters', 'exclusionFilters'].flatMap(key => {
    105    return badFilters.map(filter => ({[key]: [filter]}));
    106  });
    107 
    108  for (const badFilterOption of badFilterOptions) {
    109    await callWithTrustedClick(async () => {
    110      try {
    111        await navigator.usb.requestDevice(badFilterOption);
    112        assert_unreached(
    113            'requestDevice should reject because of invalid filters');
    114      } catch (error) {
    115        assert_equals(error.name, 'TypeError');
    116      }
    117    });
    118  }
    119 }, 'requestDevice rejects on invalid filters');
    120 
    121 usb_test(() => {
    122  return getFakeDevice().then(({ device, fakeDevice }) => {
    123    navigator.usb.test.onrequestdevice = event => {
    124      event.respondWith(fakeDevice);
    125    };
    126    return callWithTrustedClick(() => {
    127      let first = navigator.usb.requestDevice({ filters: [] });
    128      let second = navigator.usb.requestDevice({ filters: [] });
    129      return Promise.all([
    130        first.then(chosenDevice => {
    131          assert_equals(chosenDevice, device);
    132        }),
    133        second.then(chosenDevice => {
    134          assert_equals(chosenDevice, device);
    135        })
    136      ]);
    137    });
    138  });
    139 }, 'multiple requestDevice calls are allowed per user activation');