chromium/third_party/blink/web_tests/media/encrypted-media/encrypted-media-playback-multiple-sessions.html

<!DOCTYPE html>
<html>
    <head>
        <title>Clear Key Playback with Multiple Sessions</title>
        <script src="encrypted-media-utils.js"></script>
        <script src="../../resources/testharness.js"></script>
        <script src="../../resources/testharnessreport.js"></script>
    </head>
    <body>
        <video></video>
        <script>
            async_test(function(test)
            {
                var video = document.querySelector('video');
                var content = '../content/test-encrypted-different-av-keys.webm';
                var audioMediaKeySession = null;
                var videoMediaKeySession = null;
                var audioInitDataType = null;
                var videoInitDataType = null;
                var audioInitData = null;
                var videoInitData = null;
                var audioKeyProvided = false;
                var videoKeyProvided = false;

                // The 2 streams use different key ids and different keys.
                var audioKeyId = '1234567890123456';
                var audioKey = new Uint8Array([0x30, 0x30, 0x62, 0xF1, 0x68, 0x14, 0xD2, 0x7B,
                                               0x68, 0xEF, 0x12, 0x2A, 0xFC, 0xE4, 0xAE, 0x0A]);
                var videoKeyId = '0123456789012345';
                var videoKey = new Uint8Array([0x7A, 0x7A, 0x62, 0xF1, 0x68, 0x14, 0xD2, 0x7B,
                                               0x68, 0xEF, 0x12, 0x2A, 0xFC, 0xE4, 0xAE, 0x0A]);

                function onEncrypted(event)
                {
                    var keyId = String.fromCharCode.apply(null, new Uint8Array(event.initData));

                    // To avoid issues when comparing the expected.txt file
                    // (which logs the events in the order they occur), save
                    // the initData and make the calls to generateRequest()
                    // only after both "onencrypted" events are received.
                    // This prevents a "message" event from occurring before
                    // both "onencrypted" events are received.
                    var mediaKeySession = video.mediaKeys.createSession();
                    if (keyId == videoKeyId) {
                        assert_equals(videoMediaKeySession, null);
                        videoMediaKeySession = mediaKeySession;
                        videoInitDataType = event.initDataType;
                        videoInitData = event.initData;
                        // Return if audio "onencrypted" event not yet received.
                        if (audioMediaKeySession == null)
                            return;
                    } else {
                        assert_equals(keyId, audioKeyId);
                        assert_equals(audioMediaKeySession, null);
                        audioMediaKeySession = mediaKeySession;
                        audioInitDataType = event.initDataType;
                        audioInitData = event.initData;
                        // Return if video "onencrypted" event not yet received.
                        if (videoMediaKeySession == null)
                            return;
                    }

                    // Both sessions have been created.
                    assert_not_equals(videoMediaKeySession, null);
                    assert_not_equals(audioMediaKeySession, null);

                    var promises = [];
                    waitForEventAndRunStep('message', videoMediaKeySession, onMessage, test);
                    promises.push(videoMediaKeySession.generateRequest(videoInitDataType, videoInitData));

                    waitForEventAndRunStep('message', audioMediaKeySession, onMessage, test);
                    promises.push(audioMediaKeySession.generateRequest(audioInitDataType, audioInitData));

                    Promise.all(promises).catch(function(error) {
                        forceTestFailureFromPromise(test, error);
                    });
                }

                function onMessage(event)
                {
                    assert_equals(event.messageType, 'license-request');
                    var keyId = extractSingleKeyIdFromMessage(event.message);
                    if (event.target == videoMediaKeySession) {
                        assert_equals(String.fromCharCode.apply(null, keyId), videoKeyId);
                        var jwkSet = stringToUint8Array(createJWKSet(createJWK(keyId, videoKey)));
                        videoMediaKeySession.update(jwkSet).then(function(result) {
                            videoKeyProvided = true;
                        }).catch(function(error) {
                            forceTestFailureFromPromise(test, error);
                        });
                    } else {
                        assert_equals(event.target, audioMediaKeySession);
                        assert_equals(String.fromCharCode.apply(null, keyId), audioKeyId);
                        var jwkSet = stringToUint8Array(createJWKSet(createJWK(keyId, audioKey)));
                        audioMediaKeySession.update(jwkSet).then(function(result) {
                            audioKeyProvided = true;
                        }).catch(function(error) {
                            forceTestFailureFromPromise(test, error);
                        });
                    }
                }

                function onPlaying(event)
                {
                    // Video should not start playing until both keys have been
                    // provided.
                    assert_true(videoKeyProvided);
                    assert_true(audioKeyProvided);

                    // Not using waitForEventAndRunStep() to avoid too many
                    // EVENT(onTimeUpdate) logs.
                    video.addEventListener('timeupdate', onTimeUpdate, true);
                }

                function onTimeUpdate(event)
                {
                    if (event.target.currentTime < 0.2)
                        return;

                    test.done();
                }

                navigator.requestMediaKeySystemAccess('org.w3.clearkey', getConfigurationForFile(content)).then(function(access) {
                    return access.createMediaKeys();
                }).then(function(mediaKeys) {
                    waitForEventAndRunStep('encrypted', video, onEncrypted, test);
                    waitForEventAndRunStep('playing', video, onPlaying, test);
                    video.src = content;
                    return video.setMediaKeys(mediaKeys);
                }).then(function(result) {
                    video.play();
                }).catch(function(error) {
                    forceTestFailureFromPromise(test, error);
                });
            }, 'Playback using Clear Key key system with multiple sessions.');
        </script>
    </body>
</html>