Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
- This WPT test may be referenced by the following Test IDs:
- /media-capabilities/decodingInfoEncryptedMedia.https.html - WPT Dashboard Interop Dashboard
<!DOCTYPE html>
<title>MediaCapabilities.decodingInfo for encrypted media</title>
<meta name="timeout" content="long">
<script src=/resources/testharness.js></script>
<script src="/resources/testharnessreport.js"></script>
<script>
// Minimal VideoConfiguration that will be allowed per spec. All optional
// properties are missing.
var minimalVideoConfiguration = {
contentType: 'video/webm; codecs="vp09.00.10.08"',
width: 800,
height: 600,
bitrate: 3000,
framerate: 24,
};
// Minimal AudioConfiguration that will be allowed per spec. All optional
// properties are missing.
var minimalAudioConfiguration = {
contentType: 'audio/webm; codecs="opus"',
};
// Minimal MediaCapabilitiesKeySystemConfiguration that will be allowed per
// spec. All optional properties are missing.
var minimalKeySystemConfiguration = {
keySystem: 'org.w3.clearkey',
};
// Config with bogus name not provided by any UA.
var bogusKeySystemConfiguration = {
keySystem: 'bogus',
};
promise_test(t => {
return navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: minimalVideoConfiguration,
keySystemConfiguration: minimalKeySystemConfiguration,
});
}, "Test that decodingInfo accepts a stub key system configuration (w/video).");
promise_test(t => {
return navigator.mediaCapabilities.decodingInfo({
type: 'file',
audio: minimalAudioConfiguration,
keySystemConfiguration: minimalKeySystemConfiguration,
});
}, "Test that decodingInfo accepts a stub key system configuration (w/audio).");
promise_test(t => {
return navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: minimalVideoConfiguration,
keySystemConfiguration: {
keySystem: 'org.w3.clearkey',
video: {
robustness: '',
},
},
});
}, "Test that decodingInfo accepts a key system configuration with video info.");
promise_test(t => {
return navigator.mediaCapabilities.decodingInfo({
type: 'file',
audio: minimalAudioConfiguration,
keySystemConfiguration: {
keySystem: 'org.w3.clearkey',
audio : {
robustness: '',
},
},
});
}, "Test that decodingInfo accepts a key system configuration with audio info.");
promise_test(t => {
return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
type: 'file',
audio: minimalAudioConfiguration,
keySystemConfiguration: {
keySystem: 'org.w3.clearkey',
video: {
robustness: '',
},
},
}));
}, "Test that decodingInfo rejects if robustness and configuration do not match (1).");
promise_test(t => {
return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: minimalVideoConfiguration,
keySystemConfiguration: {
keySystem: 'org.w3.clearkey',
audio : {
robustness: '',
},
},
}));
}, "Test that decodingInfo rejects if robustness and configuration do not match (2).");
promise_test(t => {
return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: minimalVideoConfiguration,
keySystemConfiguration: {
keySystem: 'org.w3.clearkey',
audio : {
robustness: '',
},
video: {
robustness: '',
},
},
}));
}, "Test that decodingInfo rejects if robustness and configuration do not match (3).");
promise_test(t => {
return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
type: 'file',
audio: minimalAudioConfiguration,
video: minimalVideoConfiguration,
keySystemConfiguration: {
keySystem: 'org.w3.clearkey',
audio : {
robustness: '',
},
video: {
robustness: '',
},
persistentState: "foobar",
},
}));
}, "Test that decodingInfo rejects if persistentState isn't valid.");
promise_test(t => {
return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
type: 'file',
audio: minimalAudioConfiguration,
video: minimalVideoConfiguration,
keySystemConfiguration: {
keySystem: 'org.w3.clearkey',
audio : {
robustness: '',
},
video: {
robustness: '',
},
distinctiveIdentifier: "foobar",
},
}));
}, "Test that decodingInfo rejects if distinctiveIdentifier isn't valid.");
promise_test(t => {
return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
type: 'file',
audio: minimalAudioConfiguration,
video: minimalVideoConfiguration,
keySystemConfiguration: {
keySystem: 'org.w3.clearkey',
audio : {
robustness: '',
},
video: {
robustness: '',
},
sessionTypes: "foobar",
},
}));
}, "Test that decodingInfo rejects if sessionTypes isn't a sequence.");
promise_test(t => {
return navigator.mediaCapabilities.decodingInfo({
type: 'file',
audio: minimalAudioConfiguration,
video: minimalVideoConfiguration,
keySystemConfiguration: {
keySystem: {},
initDataType: {},
audio : {
robustness: '',
},
video: {
robustness: '',
},
},
});
}, "Test that decodingInfo does not reject when properties are set to unexpected values.");
promise_test(t => {
return navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: minimalVideoConfiguration,
audio: minimalAudioConfiguration,
keySystemConfiguration: minimalKeySystemConfiguration,
}).then(ability => {
assert_equals(typeof ability.supported, "boolean");
assert_equals(typeof ability.smooth, "boolean");
assert_equals(typeof ability.powerEfficient, "boolean");
assert_equals(typeof ability.keySystemAccess, "object");
});
}, "Test that decodingInfo returns a valid MediaCapabilitiesDecodingInfo objects with encrypted media");
promise_test(t => {
return navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: minimalVideoConfiguration,
keySystemConfiguration: {
keySystem: 'foobar',
video: {
robustness: '',
},
}
}).then(ability => {
assert_false(ability.supported);
assert_false(ability.smooth);
assert_false(ability.powerEfficient);
assert_equals(ability.keySystemAccess, null);
});
}, "Test that random key systems are reported as non supported.");
// TODO(mlamouri): this test could be split in two tests for which codec support
// across browsers is widely compatible: one when all browsers wouldn't support
// and one where all browsers do support. The current approach is to check that
// the answer is consistent to the spec.
promise_test(t => {
return navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: minimalVideoConfiguration,
audio: minimalAudioConfiguration,
keySystemConfiguration: minimalKeySystemConfiguration,
}).then(ability => {
if (ability.supported)
assert_not_equals(ability.keySystemAccess, null);
else
assert_equals(ability.keySystemAccess, null);
});
}, "Test that keySystemAccess is only null when not supported if keySystemConfiguration was used.");
promise_test(t => {
return navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: minimalVideoConfiguration,
audio: minimalAudioConfiguration,
// Supply bogus config to reliably result in a null keySystemAccess.
keySystemConfiguration: bogusKeySystemConfiguration,
}).then(ability => {
assert_equals(ability.keySystemAccess, null);
assert_false(ability.supported);
});
}, "Test that supported=false when keySystemConfiguration is unsupported.");
promise_test(t => {
return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
type: 'webrtc',
video: minimalVideoConfiguration,
keySystemConfiguration: minimalKeySystemConfiguration,
}));
}, "Test that decodingInfo with type webrtc rejects key system configuration.");
async function runEncryptionSchemeTest(t, scheme, expectedSupported) {
const config = {
type: 'file',
video: minimalVideoConfiguration,
audio: minimalAudioConfiguration,
keySystemConfiguration: {
keySystem: 'org.w3.clearkey',
video: {
robustness: '',
encryptionScheme: scheme
}
}
};
const info = await navigator.mediaCapabilities.decodingInfo(config);
assert_equals(info.supported, expectedSupported, `supported should be ${expectedSupported}`);
if (expectedSupported) {
assert_not_equals(info.keySystemAccess, null, "keySystemAccess should be present in the result.");
const negotiatedConfig = info.keySystemAccess.getConfiguration();
assert_true(
!!negotiatedConfig.videoCapabilities && negotiatedConfig.videoCapabilities.length > 0,
"videoCapabilities should be present in the negotiated configuration."
);
// If the encryptionScheme is not passed from mediaCapabilities.decodingInfo()
// to the EME query, the negotiated keySystemAccess configuration will not contain
// the requested encryptionScheme (it will be null/unspecified).
assert_equals(
negotiatedConfig.videoCapabilities[0].encryptionScheme,
scheme,
`negotiated encryptionScheme should match requested scheme: ${scheme}`
);
} else {
assert_equals(info.keySystemAccess, null, "keySystemAccess should be null when not supported.");
}
}
promise_test(t => {
return runEncryptionSchemeTest(t, 'cenc', true);
}, "decodingInfo() supports 'cenc' encryptionScheme and echoes it back.");
promise_test(t => {
return runEncryptionSchemeTest(t, 'cbcs', true);
}, "decodingInfo() supports 'cbcs' encryptionScheme and echoes it back.");
promise_test(t => {
return runEncryptionSchemeTest(t, 'cbcs-1-9', true);
}, "decodingInfo() supports 'cbcs-1-9' encryptionScheme and echoes it back.");
promise_test(t => {
return runEncryptionSchemeTest(t, 'foobar', false);
}, "decodingInfo() with unrecognized encryptionScheme returns supported: false.");
promise_test(t => {
return runEncryptionSchemeTest(t, null, true);
}, "decodingInfo() with null encryptionScheme returns supported: true and echoes null.");
</script>