136 lines
4.8 KiB
HTML
136 lines
4.8 KiB
HTML
<!DOCTYPE HTML>
|
|
<html>
|
|
<head>
|
|
<title>Media Engine only test : test EME API for supported key systems</title>
|
|
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
|
<script type="text/javascript" src="manifest.js"></script>
|
|
</head>
|
|
<body>
|
|
<script class="testbody" type="text/javascript">
|
|
|
|
/**
|
|
* This test is aiming to test whether we can use EME API to generate a request
|
|
* for all supported key systems. However, we use our mock CDM (MF ClearKey) for
|
|
* external key systems like Widevine and PlayReady in order to avoid any
|
|
* possible interfering, such as returning incorrect support types (bug 1851914)
|
|
* and we can also test hardward DRM key system without being limited by
|
|
* machine capability.
|
|
*
|
|
* As this test doesn't involve any communication with the license server, that
|
|
* is why we can use our mock CDM (no decryption needed).
|
|
*/
|
|
|
|
add_task(async function setupTestingPrefs() {
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [
|
|
["media.wmf.media-engine.enabled", 2],
|
|
["media.eme.playready.enabled", true],
|
|
["media.eme.widevine.experiment.enabled", true],
|
|
// This is used to trigger Widevine CDM installation check
|
|
["media.gmp-widevinecdm-l1.enabled", true],
|
|
["media.eme.wmf.clearkey.enabled", true],
|
|
// Use the mock clearkey CDM to create cdm for all other key systems.
|
|
["media.eme.wmf.use-mock-cdm-for-external-cdms", true],
|
|
// Our mock CDM doesn't implement 'IsTypeSupportedEx()', only 'IsTypeSupported()'
|
|
["media.eme.playready.istypesupportedex", false],
|
|
],
|
|
});
|
|
});
|
|
|
|
const kKeySystems = [
|
|
"com.microsoft.playready.recommendation",
|
|
"com.microsoft.playready.recommendation.3000",
|
|
"com.microsoft.playready.recommendation.3000.clearlead",
|
|
"com.widevine.alpha.experiment",
|
|
"com.widevine.alpha.experiment2",
|
|
"org.w3.clearkey",
|
|
];
|
|
|
|
add_task(async function testKeySystemRequestForMFCDMs() {
|
|
for (let keySystem of kKeySystems) {
|
|
await testKeySystemRequest(keySystem);
|
|
info(`done testing ${keySystem}!`);
|
|
}
|
|
});
|
|
|
|
async function testKeySystemRequest(keySystem) {
|
|
// Create a Uint8Array for the key ID
|
|
const fakeKID = new Uint8Array([0xa1, 0x23, 0x45, 0x67, 0x89]);
|
|
const fakeKIDBase64 = base64UrlEncode(String.fromCharCode.apply(null, fakeKID));
|
|
|
|
// Mock CDM only supports temporary type.
|
|
const sessionType = 'temporary';
|
|
const configs = [{
|
|
initDataTypes: ['keyids'],
|
|
videoCapabilities: [{ contentType: `video/mp4;codecs="avc1.640028"` }],
|
|
sessionTypes : [sessionType],
|
|
}];
|
|
info(`requestMediaKeySystemAccess for ${keySystem}`);
|
|
let access = await navigator.requestMediaKeySystemAccess(keySystem, configs)
|
|
.catch(() => ok(false, `failed to create key system access`));
|
|
|
|
info('creating media key');
|
|
let mediaKeys = await access.createMediaKeys()
|
|
.catch(() => ok(false, `failed to create media key`));;
|
|
|
|
info(`creating a temporary media key session`);
|
|
let session = mediaKeys.createSession(sessionType);
|
|
let messagePromise = new Promise(r => {
|
|
session.addEventListener('message', async event => {
|
|
is(event.messageType, 'license-request',
|
|
'MediaKeyMessage type should be license-request');
|
|
ok(true, `created request and received message event`);
|
|
|
|
// Simulate license server response in JWK format
|
|
const mockLicenseResponse = {
|
|
keys: [{
|
|
kty: "oct",
|
|
kid: fakeKIDBase64,
|
|
k: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=" // Base64 encoded 32-byte key
|
|
}],
|
|
type: "temporary"
|
|
};
|
|
const encoder = new TextEncoder();
|
|
const licenseBuffer = encoder.encode(JSON.stringify(mockLicenseResponse));
|
|
|
|
await session.update(licenseBuffer)
|
|
.catch(e => ok(false, `Failed to update session: ${e}`));
|
|
|
|
await new Promise(resolve => {
|
|
session.addEventListener('keystatuseschange', resolve, { once: true });
|
|
});
|
|
|
|
for (let [keyId, status] of session.keyStatuses) {
|
|
const keyIdBase64 = base64UrlEncode(String.fromCharCode.apply(null, new Uint8Array(keyId)));
|
|
is(keyIdBase64, fakeKIDBase64, "Key ID should match");
|
|
is(status, 'usable', 'Key status should be usable');
|
|
}
|
|
|
|
session.close().then(() => { r(); });
|
|
});
|
|
});
|
|
|
|
const initData = {
|
|
kids: [fakeKIDBase64], // Base64 encode the KID
|
|
type: 'temporary'
|
|
};
|
|
const initDataString = JSON.stringify(initData);
|
|
await session.generateRequest(
|
|
'keyids',
|
|
new TextEncoder().encode(initDataString))
|
|
.catch(() => ok(false, `failed to generate request`));
|
|
await messagePromise;
|
|
}
|
|
|
|
// Helper function to create a web-safe Base64 encoded string
|
|
function base64UrlEncode(str) {
|
|
return btoa(str)
|
|
.replace(/\+/g, '-')
|
|
.replace(/\//g, '_')
|
|
.replace(/=+$/, '');
|
|
}
|
|
|
|
</script>
|
|
</body>
|
|
</html>
|