tor-browser

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

decodingInfo.any.js (14420B)


      1 // META: timeout=long
      2 'use strict';
      3 
      4 // Minimal VideoConfiguration that will be allowed per spec. All optional
      5 // properties are missing.
      6 const minimalVideoConfiguration = {
      7  contentType: 'video/webm; codecs="vp09.00.10.08"',
      8  width: 800,
      9  height: 600,
     10  bitrate: 3000,
     11  framerate: 24,
     12 };
     13 
     14 // Minimal AudioConfiguration that will be allowed per spec. All optional
     15 // properties are missing.
     16 const minimalAudioConfiguration = {
     17  contentType: 'audio/webm; codecs="opus"',
     18 };
     19 
     20 // AudioConfiguration with optional spatialRendering param.
     21 const audioConfigurationWithSpatialRendering = {
     22  contentType: 'audio/webm; codecs="opus"',
     23  spatialRendering: true,
     24 };
     25 
     26 // VideoConfiguration with optional hdrMetadataType, colorGamut, and
     27 // transferFunction properties.
     28 const videoConfigurationWithDynamicRange = {
     29  contentType: 'video/webm; codecs="vp09.00.10.08.00.09.16.09.00"',
     30  width: 800,
     31  height: 600,
     32  bitrate: 3000,
     33  framerate: 24,
     34  hdrMetadataType: 'smpteSt2086',
     35  colorGamut: 'rec2020',
     36  transferFunction: 'pq',
     37 };
     38 
     39 
     40 promise_test(t => {
     41  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo());
     42 }, "Test that decodingInfo rejects if it doesn't get a configuration");
     43 
     44 promise_test(t => {
     45  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({}));
     46 }, "Test that decodingInfo rejects if the MediaConfiguration isn't valid");
     47 
     48 promise_test(t => {
     49  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
     50    video: minimalVideoConfiguration,
     51    audio: minimalAudioConfiguration,
     52  }));
     53 }, "Test that decodingInfo rejects if the MediaConfiguration does not have a type");
     54 
     55 promise_test(t => {
     56  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
     57    type: 'file',
     58  }));
     59 }, "Test that decodingInfo rejects if the configuration doesn't have an audio or video field");
     60 
     61 promise_test(t => {
     62  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
     63    type: 'file',
     64    video: {
     65      contentType: 'video/webm; codecs="vp09.00.10.08"',
     66      width: 800,
     67      height: 600,
     68      bitrate: 3000,
     69      framerate: -1,
     70    },
     71  }));
     72 }, "Test that decodingInfo rejects if the video configuration has a negative framerate");
     73 
     74 promise_test(t => {
     75  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
     76    type: 'file',
     77    video: {
     78      contentType: 'video/webm; codecs="vp09.00.10.08"',
     79      width: 800,
     80      height: 600,
     81      bitrate: 3000,
     82      framerate: 0,
     83    },
     84  }));
     85 }, "Test that decodingInfo rejects if the video configuration has a framerate set to 0");
     86 
     87 promise_test(t => {
     88  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
     89    type: 'file',
     90    video: {
     91      contentType: 'video/webm; codecs="vp09.00.10.08"',
     92      width: 800,
     93      height: 600,
     94      bitrate: 3000,
     95      framerate: Infinity,
     96    },
     97  }));
     98 }, "Test that decodingInfo rejects if the video configuration has a framerate set to Infinity");
     99 
    100 promise_test(t => {
    101  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    102    type: 'file',
    103    video: {
    104      contentType: 'fgeoa',
    105      width: 800,
    106      height: 600,
    107      bitrate: 3000,
    108      framerate: 24,
    109    },
    110  }));
    111 }, "Test that decodingInfo rejects if the video configuration contentType doesn't parse");
    112 
    113 // See https://mimesniff.spec.whatwg.org/#example-valid-mime-type-string
    114 promise_test(t => {
    115  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    116    type: 'file',
    117    video: {
    118      contentType: 'video/webm;',
    119      width: 800,
    120      height: 600,
    121      bitrate: 3000,
    122      framerate: 24,
    123    },
    124  }));
    125 }, "Test that decodingInfo rejects if the video configuration contentType is not a valid MIME type string");
    126 
    127 promise_test(t => {
    128  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    129    type: 'file',
    130    video: {
    131      contentType: 'audio/fgeoa',
    132      width: 800,
    133      height: 600,
    134      bitrate: 3000,
    135      framerate: 24,
    136    },
    137  }));
    138 }, "Test that decodingInfo rejects if the video configuration contentType isn't of type video");
    139 
    140 promise_test(t => {
    141  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    142    type: 'file',
    143    video: {
    144      contentType: 'application/ogg; codecs=vorbis',
    145      width: 800,
    146      height: 600,
    147      bitrate: 3000,
    148      framerate: 24,
    149    },
    150  }));
    151 }, "Test that decodingInfo rejects if the video configuration contentType is of type audio");
    152 
    153 promise_test(t => {
    154  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    155    type: 'file',
    156    audio: {
    157      contentType: 'application/ogg; codecs=theora',
    158      channels: 2,
    159    },
    160  }));
    161 }, "Test that decodingInfo rejects if the audio configuration contentType is of type video");
    162 
    163 promise_test(t => {
    164  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    165    type: 'file',
    166    video: {
    167      contentType: 'video/webm; codecs="vp09.00.10.08"; foo="bar"',
    168      width: 800,
    169      height: 600,
    170      bitrate: 3000,
    171      framerate: 24,
    172    },
    173  }));
    174 }, "Test that decodingInfo rejects if the video configuration contentType has more than one parameter");
    175 
    176 promise_test(t => {
    177  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    178    type: 'file',
    179    video: {
    180      contentType: 'video/webm; foo="bar"',
    181      width: 800,
    182      height: 600,
    183      bitrate: 3000,
    184      framerate: 24,
    185    },
    186  }));
    187 }, "Test that decodingInfo rejects if the video configuration contentType has one parameter that isn't codecs");
    188 
    189 promise_test(t => {
    190  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    191    type: 'file',
    192    video: {
    193      contentType: 'video/webm',
    194      width: 800,
    195      height: 600,
    196      bitrate: 3000,
    197      framerate: 24,
    198    },
    199  }));
    200 }, "Test that decodingInfo rejects if the video configuration contentType does not imply a single media codec but has no codecs parameter");
    201 
    202 promise_test(t => {
    203  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    204    type: 'file',
    205    video: {
    206      contentType: 'video/webm; codecs="vp09.00.10.08, vp8"',
    207      width: 800,
    208      height: 600,
    209      bitrate: 3000,
    210      framerate: 24,
    211    }
    212  }));
    213 }, "Test that decodingInfo rejects if the video configuration contentType has a codecs parameter that indicates multiple video codecs");
    214 
    215 promise_test(t => {
    216  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    217    type: 'file',
    218    video: {
    219      contentType: 'video/webm; codecs="vp09.00.10.08, opus"',
    220      width: 800,
    221      height: 600,
    222      bitrate: 3000,
    223      framerate: 24,
    224    }
    225  }));
    226 }, "Test that decodingInfo rejects if the video configuration contentType has a codecs parameter that indicates both an audio and a video codec");
    227 
    228 promise_test(t => {
    229  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    230    type: 'file',
    231    audio: { contentType: 'fgeoa' },
    232  }));
    233 }, "Test that decodingInfo rejects if the audio configuration contentType doesn't parse");
    234 
    235 // See https://mimesniff.spec.whatwg.org/#example-valid-mime-type-string
    236 promise_test(t => {
    237  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    238    type: 'file',
    239    audio: { contentType: 'audio/mpeg;' },
    240  }));
    241 }, "Test that decodingInfo rejects if the audio configuration contentType is not a valid MIME type string");
    242 
    243 promise_test(t => {
    244  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    245    type: 'file',
    246    audio: { contentType: 'video/fgeoa' },
    247  }));
    248 }, "Test that decodingInfo rejects if the audio configuration contentType isn't of type audio");
    249 
    250 promise_test(t => {
    251  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    252    type: 'file',
    253    audio: { contentType: 'audio/webm; codecs="opus"; foo="bar"' },
    254  }));
    255 }, "Test that decodingInfo rejects if the audio configuration contentType has more than one parameter");
    256 
    257 promise_test(t => {
    258  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    259    type: 'file',
    260    audio: { contentType: 'audio/webm; foo="bar"' },
    261  }));
    262 }, "Test that decodingInfo rejects if the audio configuration contentType has one parameter that isn't codecs");
    263 
    264 promise_test(t => {
    265  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    266    type: 'file',
    267    audio: { contentType: 'audio/webm' },
    268  }));
    269 }, "Test that decodingInfo rejects if the audio configuration contentType does not imply a single media codec but has no codecs parameter");
    270 
    271 promise_test(t => {
    272  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    273    type: 'file',
    274    audio: { contentType: 'audio/webm; codecs="vorbis, opus"' },
    275  }));
    276 }, "Test that decodingInfo rejects if the audio configuration contentType has a codecs parameter that indicates multiple audio codecs");
    277 
    278 promise_test(t => {
    279  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    280    type: 'file',
    281    audio: { contentType: 'audio/webm; codecs="vp09.00.10.08, opus"' },
    282  }));
    283 }, "Test that decodingInfo rejects if the audio configuration contentType has a codecs parameter that indicates both an audio and a video codec");
    284 
    285 promise_test(t => {
    286  return navigator.mediaCapabilities.decodingInfo({
    287    type: 'file',
    288    video: minimalVideoConfiguration,
    289    audio: minimalAudioConfiguration,
    290  }).then(ability => {
    291    assert_equals(typeof ability.supported, "boolean");
    292    assert_equals(typeof ability.smooth, "boolean");
    293    assert_equals(typeof ability.powerEfficient, "boolean");
    294    assert_equals(typeof ability.keySystemAccess, "object");
    295  });
    296 }, "Test that decodingInfo returns a valid MediaCapabilitiesInfo objects");
    297 
    298 async_test(t => {
    299  var validTypes = [ 'file', 'media-source' ];
    300  var invalidTypes = [ undefined, null, '', 'foobar', 'mse', 'MediaSource',
    301                       'record', 'transmission' ];
    302 
    303  var validPromises = [];
    304  var invalidCaught = 0;
    305 
    306  validTypes.forEach(type => {
    307    validPromises.push(navigator.mediaCapabilities.decodingInfo({
    308      type: type,
    309      video: minimalVideoConfiguration,
    310      audio: minimalAudioConfiguration,
    311    }));
    312  });
    313 
    314  // validTypes are tested via Promise.all(validPromises) because if one of the
    315  // promises fail, Promise.all() will reject. This mechanism can't be used for
    316  // invalid types which will be tested individually and increment invalidCaught
    317  // when rejected until the amount of rejection matches the expectation.
    318  Promise.all(validPromises).then(t.step_func(() => {
    319    for (var i = 0; i < invalidTypes.length; ++i) {
    320      navigator.mediaCapabilities.decodingInfo({
    321        type: invalidTypes[i],
    322        video: minimalVideoConfiguration,
    323        audio: minimalAudioConfiguration,
    324      }).then(t.unreached_func(), t.step_func(e => {
    325        assert_equals(e.name, 'TypeError');
    326        ++invalidCaught;
    327        if (invalidCaught == invalidTypes.length)
    328          t.done();
    329      }));
    330    }
    331  }), t.unreached_func('Promise.all should not reject for valid types'));
    332 }, "Test that decodingInfo rejects if the MediaConfiguration does not have a valid type");
    333 
    334 promise_test(t => {
    335  return navigator.mediaCapabilities.decodingInfo({
    336    type: 'file',
    337    audio: audioConfigurationWithSpatialRendering,
    338  }).then(ability => {
    339    assert_equals(typeof ability.supported, "boolean");
    340    assert_equals(typeof ability.smooth, "boolean");
    341    assert_equals(typeof ability.powerEfficient, "boolean");
    342    assert_equals(typeof ability.keySystemAccess, "object");
    343  });
    344 }, "Test that decodingInfo with spatialRendering set returns a valid MediaCapabilitiesInfo objects");
    345 
    346 promise_test(t => {
    347  return navigator.mediaCapabilities.decodingInfo({
    348    type: 'file',
    349    video: videoConfigurationWithDynamicRange,
    350  }).then(ability => {
    351    assert_equals(typeof ability.supported, "boolean");
    352    assert_equals(typeof ability.smooth, "boolean");
    353    assert_equals(typeof ability.powerEfficient, "boolean");
    354    assert_equals(typeof ability.keySystemAccess, "object");
    355  });
    356 }, "Test that decodingInfo with hdrMetadataType, colorGamut, and transferFunction set returns a valid MediaCapabilitiesInfo objects");
    357 
    358 promise_test(t => {
    359  // VP9 has a default color space of BT.709 in the codec string. So this will
    360  // mismatch against the provided colorGamut and transferFunction.
    361  let bt709Config = videoConfigurationWithDynamicRange;
    362  bt709Config.contentType = 'video/webm; codecs="vp09.00.10.08"';
    363  return navigator.mediaCapabilities
    364      .decodingInfo({
    365        type: 'file',
    366        video: bt709Config,
    367      })
    368      .then(ability => {
    369        assert_equals(typeof ability.supported, 'boolean');
    370        assert_equals(typeof ability.smooth, 'boolean');
    371        assert_equals(typeof ability.powerEfficient, 'boolean');
    372        assert_equals(typeof ability.keySystemAccess, 'object');
    373        assert_false(ability.supported);
    374      });
    375 }, 'Test that decodingInfo with mismatched codec color space is unsupported');
    376 
    377 promise_test(t => {
    378  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    379    type: 'file',
    380    video: {
    381      contentType: 'video/webm; codecs="vp09.00.10.08"',
    382      width: 800,
    383      height: 600,
    384      bitrate: 3000,
    385      framerate: 24,
    386      hdrMetadataType: ""
    387    },
    388  }));
    389 }, "Test that decodingInfo rejects if the video configuration has an empty hdrMetadataType");
    390 
    391 promise_test(t => {
    392  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    393    type: 'file',
    394    video: {
    395      contentType: 'video/webm; codecs="vp09.00.10.08"',
    396      width: 800,
    397      height: 600,
    398      bitrate: 3000,
    399      framerate: 24,
    400      colorGamut: true
    401    },
    402  }));
    403 }, "Test that decodingInfo rejects if the video configuration has a colorGamut set to true");
    404 
    405 promise_test(t => {
    406  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    407    type: 'file',
    408    video: {
    409      contentType: 'video/webm; codecs="vp09.00.10.08"',
    410      width: 800,
    411      height: 600,
    412      bitrate: 3000,
    413      framerate: 24,
    414      transferFunction: 3
    415    },
    416  }));
    417 }, "Test that decodingInfo rejects if the video configuration has a transferFunction set to 3");