tor-browser

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

test_getUserMedia_constraints.html (6992B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <script src="mediaStreamPlayback.js"></script>
      5  <script src="constraints.js"></script>
      6 </head>
      7 <body>
      8 <pre id="test">
      9 <script type="application/javascript">
     10 createHTML({ title: "Test getUserMedia constraints", bug: "882145" });
     11 /**
     12  Tests covering gUM constraints API for audio, video and fake video. Exercise
     13  successful parsing code and ensure that unknown required constraints and
     14  overconstraining cases produce appropriate errors.
     15 */
     16 var tests = [
     17  // Each test here tests a different constraint or codepath.
     18  { message: "unknown required constraint on video ignored",
     19    constraints: { video: { somethingUnknown: { exact: 0 } } },
     20    error: null },
     21  { message: "unknown required constraint on audio ignored",
     22    constraints: { audio: { somethingUnknown: { exact: 0 } } },
     23    error: null },
     24  { message: "audio overconstrained by facingMode ignored",
     25    constraints: { audio: { facingMode: { exact: 'left' } } },
     26    error: null },
     27  { message: "full screensharing requires permission",
     28    constraints: { video: { mediaSource: 'screen' } },
     29    error: "NotAllowedError" },
     30  { message: "application screensharing no longer exists",
     31    constraints: { video: { mediaSource: 'application' } },
     32    error: "OverconstrainedError" },
     33  { message: "window screensharing requires permission",
     34    constraints: { video: { mediaSource: 'window' } },
     35    error: "NotAllowedError" },
     36  { message: "browser screensharing requires permission",
     37    constraints: { video: { mediaSource: 'browser' } },
     38    error: "NotAllowedError" },
     39  { message: "unknown mediaSource in video fails",
     40    constraints: { video: { mediaSource: 'uncle' } },
     41    error: "OverconstrainedError",
     42    constraint: "mediaSource" },
     43  { message: "unknown mediaSource in audio fails",
     44    constraints: { audio: { mediaSource: 'uncle' } },
     45    error: "OverconstrainedError",
     46    constraint: "mediaSource" },
     47  { message: "emtpy constraint fails",
     48    constraints: { },
     49    error: "TypeError" },
     50  { message: "Triggering mock failure in default video device fails",
     51    constraints: { video: { deviceId: 'bad device' } },
     52    error: "NotReadableError" },
     53  { message: "Triggering mock failure in default audio device fails",
     54    constraints: { audio: { deviceId: 'bad device' } },
     55    error: "NotReadableError" },
     56  { message: "Success-path: optional video facingMode + audio ignoring facingMode",
     57    constraints: { audio: { mediaSource: 'microphone',
     58                            facingMode: 'left',
     59                            foo: 0,
     60                            advanced: [{ facingMode: 'environment' },
     61                                       { facingMode: 'user' },
     62                                       { bar: 0 }] },
     63                   video: { mediaSource: 'camera',
     64                            foo: 0,
     65                            advanced: [{ facingMode: 'environment' },
     66                                       { facingMode: ['user'] },
     67                                       { facingMode: ['left', 'right', 'user'] },
     68                                       { bar: 0 }] } },
     69    error: null },
     70  { message: "legacy facingMode ignored",
     71    constraints: { video: { mandatory: { facingMode: 'left' } } },
     72    error: null },
     73 ];
     74 
     75 var mustSupport = [
     76  'width', 'height', 'frameRate', 'facingMode', 'deviceId', 'groupId',
     77  'echoCancellation', 'noiseSuppression', 'autoGainControl', 'channelCount',
     78  'resizeMode',
     79 
     80  // Yet to add:
     81  //  'aspectRatio', 'volume', 'sampleRate', 'sampleSize', 'latency'
     82 
     83  // http://fluffy.github.io/w3c-screen-share/#screen-based-video-constraints
     84  // OBE by http://w3c.github.io/mediacapture-screen-share
     85  'mediaSource',
     86 
     87  // Experimental https://bugzilla.mozilla.org/show_bug.cgi?id=1131568#c3
     88  'browserWindow', 'scrollWithPage',
     89  'viewportOffsetX', 'viewportOffsetY', 'viewportWidth', 'viewportHeight',
     90 ];
     91 
     92 var mustFailWith = (msg, reason, constraint, f) =>
     93  f().then(() => ok(false, msg + " must fail"), e => {
     94    is(e.name, reason, msg + " must fail: " + e.message);
     95    if (constraint !== undefined) {
     96      is(e.constraint, constraint, msg + " must fail w/correct constraint.");
     97    }
     98  });
     99 
    100 /**
    101 * Starts the test run by running through each constraint
    102 * test by verifying that the right resolution and rejection is fired.
    103 */
    104 
    105 runTest(() => pushPrefs(
    106    // This test expects fake devices, particularly for the 'triggering mock
    107    // failure *' steps. So explicitly disable loopback and setup fakes
    108    ['media.audio_loopback_dev', ''],
    109    ['media.video_loopback_dev', ''],
    110    ['media.navigator.streams.fake', true]
    111  )
    112  .then(() => {
    113    // Check supported constraints first.
    114    var dict = navigator.mediaDevices.getSupportedConstraints();
    115    var supported = Object.keys(dict);
    116 
    117    mustSupport.forEach(key => ok(supported.includes(key) && dict[key],
    118                                  "Supports " + key));
    119 
    120    var unexpected = supported.filter(key => !mustSupport.includes(key));
    121    is(unexpected.length, 0,
    122       "Unanticipated support (please update test): " + unexpected);
    123  })
    124  .then(() => pushPrefs(["media.getusermedia.browser.enabled", false],
    125                        ["media.getusermedia.screensharing.enabled", false]))
    126  .then(() => tests.reduce((p, test) => p.then(
    127    () => {
    128      SpecialPowers.wrap(document).notifyUserGestureActivation();
    129      return getUserMedia(test.constraints);
    130    })
    131    .then(stream => {
    132      is(null, test.error, test.message);
    133      stream.getTracks().forEach(t => t.stop());
    134    }, e => {
    135      is(e.name, test.error, test.message + ": " + e.message);
    136      if (test.constraint) {
    137        is(e.constraint, test.constraint,
    138           test.message + " w/correct constraint.");
    139      }
    140    }), Promise.resolve()))
    141  .then(() => getUserMedia({video: true, audio: true}))
    142  .then(stream => stream.getVideoTracks()[0].applyConstraints({ width: 320 })
    143    .then(() => stream.getAudioTracks()[0].applyConstraints({ }))
    144    .then(() => {
    145      stream.getTracks().forEach(track => track.stop());
    146      ok(true, "applyConstraints code exercised");
    147    }))
    148  // TODO: Test outcome once fake devices support constraints (Bug 1088621)
    149  .then(() => mustFailWith("applyConstraints fails on non-Gum tracks",
    150                           "OverconstrainedError", "",
    151                           () => (new AudioContext())
    152                               .createMediaStreamDestination().stream
    153                               .getAudioTracks()[0].applyConstraints()))
    154  .then(() => mustFailWith(
    155      "getUserMedia with unsatisfied required constraint",
    156      "OverconstrainedError", "deviceId",
    157      () => getUserMedia({ audio: true,
    158                           video: { deviceId: { exact: "unheardof" } } })))
    159  .then(() => mustFailWith(
    160      "getUserMedia with unsatisfied required constraint array",
    161      "OverconstrainedError", "deviceId",
    162      () => getUserMedia({ audio: true,
    163                           video: { deviceId: { exact: ["a", "b"] } } }))));
    164 </script>
    165 </pre>
    166 </body>
    167 </html>