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>