tor-browser

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

test_eme_mfcdm_generate_request.html (4735B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <title>Media Engine only test : test EME API for supported key systems</title>
      5  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      6  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
      7  <script type="text/javascript" src="manifest.js"></script>
      8 </head>
      9 <body>
     10 <script class="testbody" type="text/javascript">
     11 
     12 /**
     13 * This test is aiming to test whether we can use EME API to generate a request
     14 * for all supported key systems. However, we use our mock CDM (MF ClearKey) for
     15 * external key systems like Widevine and PlayReady in order to avoid any
     16 * possible interfering, such as returning incorrect support types (bug 1851914)
     17 * and we can also test hardward DRM key system without being limited by
     18 * machine capability.
     19 *
     20 * As this test doesn't involve any communication with the license server, that
     21 * is why we can use our mock CDM (no decryption needed).
     22 */
     23 
     24 add_task(async function setupTestingPrefs() {
     25  await SpecialPowers.pushPrefEnv({
     26    set: [
     27      ["media.wmf.media-engine.enabled", 2],
     28      ["media.eme.playready.enabled", true],
     29      ["media.eme.widevine.experiment.enabled", true],
     30      // This is used to trigger Widevine CDM installation check
     31      ["media.gmp-widevinecdm-l1.enabled", true],
     32      ["media.eme.wmf.clearkey.enabled", true],
     33      // Use the mock clearkey CDM to create cdm for all other key systems.
     34      ["media.eme.wmf.use-mock-cdm-for-external-cdms", true],
     35    ],
     36  });
     37 });
     38 
     39 const kKeySystems = [
     40  "com.microsoft.playready.recommendation",
     41  "com.microsoft.playready.recommendation.3000",
     42  "com.microsoft.playready.recommendation.3000.clearlead",
     43  "com.widevine.alpha.experiment",
     44  "com.widevine.alpha.experiment2",
     45  "org.w3.clearkey",
     46 ];
     47 
     48 add_task(async function testKeySystemRequestForMFCDMs() {
     49  for (let keySystem of kKeySystems) {
     50    await testKeySystemRequest(keySystem);
     51    info(`done testing ${keySystem}!`);
     52  }
     53 });
     54 
     55 async function testKeySystemRequest(keySystem) {
     56  // Create a Uint8Array for the key ID
     57  const fakeKID = new Uint8Array([0xa1, 0x23, 0x45, 0x67, 0x89]);
     58  const fakeKIDBase64 = base64UrlEncode(String.fromCharCode.apply(null, fakeKID));
     59 
     60  // Mock CDM only supports temporary type.
     61  const sessionType = 'temporary';
     62  const configs = [{
     63    initDataTypes: ['keyids'],
     64    videoCapabilities: [{ contentType: `video/mp4;codecs="avc1.640028"` }],
     65    sessionTypes : [sessionType],
     66  }];
     67  info(`requestMediaKeySystemAccess for ${keySystem}`);
     68  let access = await navigator.requestMediaKeySystemAccess(keySystem, configs)
     69      .catch(() => ok(false, `failed to create key system access`));
     70 
     71  info('creating media key');
     72  let mediaKeys = await access.createMediaKeys()
     73    .catch(() => ok(false, `failed to create media key`));;
     74 
     75  info(`creating a temporary media key session`);
     76  let session = mediaKeys.createSession(sessionType);
     77  let messagePromise = new Promise(r => {
     78    session.addEventListener('message', async event => {
     79      is(event.messageType, 'license-request',
     80          'MediaKeyMessage type should be license-request');
     81      ok(true, `created request and received message event`);
     82 
     83      // Simulate license server response in JWK format
     84      const mockLicenseResponse = {
     85          keys: [{
     86            kty: "oct",
     87            kid: fakeKIDBase64,
     88            k: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa="  // Base64 encoded 32-byte key
     89          }],
     90          type: "temporary"
     91        };
     92      const encoder = new TextEncoder();
     93      const licenseBuffer = encoder.encode(JSON.stringify(mockLicenseResponse));
     94 
     95      await session.update(licenseBuffer)
     96        .catch(e => ok(false, `Failed to update session: ${e}`));
     97 
     98      await new Promise(resolve => {
     99        session.addEventListener('keystatuseschange', resolve, { once: true });
    100      });
    101 
    102      for (let [keyId, status] of session.keyStatuses) {
    103        const keyIdBase64 = base64UrlEncode(String.fromCharCode.apply(null, new Uint8Array(keyId)));
    104        is(keyIdBase64, fakeKIDBase64, "Key ID should match");
    105        is(status, 'usable', 'Key status should be usable');
    106      }
    107 
    108      session.close().then(() => { r(); });
    109    });
    110  });
    111 
    112  const initData = {
    113    kids: [fakeKIDBase64],  // Base64 encode the KID
    114    type: 'temporary'
    115  };
    116  const initDataString = JSON.stringify(initData);
    117  await session.generateRequest(
    118      'keyids',
    119      new TextEncoder().encode(initDataString))
    120        .catch(() => ok(false, `failed to generate request`));
    121  await messagePromise;
    122 }
    123 
    124 // Helper function to create a web-safe Base64 encoded string
    125 function base64UrlEncode(str) {
    126  return btoa(str)
    127    .replace(/\+/g, '-')
    128    .replace(/\//g, '_')
    129    .replace(/=+$/, '');
    130 }
    131 
    132 </script>
    133 </body>
    134 </html>