<!DOCTYPE html>
<html>
    <head>
        <title>Test MediaKeySession not callable after close().</title>
        <script src="encrypted-media-utils.js"></script>
        <script src="../../resources/testharness.js"></script>
        <script src="../../resources/testharnessreport.js"></script>
    </head>
    <body>
        <script>
            // After a MediaKeySession object is closed, other operations
            // (except calling close() again) on the session are not allowed
            // and should return an InvalidStateError.

            // Create, initialize, and close a session. Returns a promise that
            // resolves with the created and closed mediaKeySession and the
            // initDataType used.
            function createClosedSession() {
                var initDataType;
                var initData;
                var mediaKeySession;

                return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) {
                    initDataType = access.getConfiguration().initDataTypes[0];
                    initData = getInitData(initDataType);
                    return access.createMediaKeys();
                }).then(function(mediaKeys) {
                    mediaKeySession = mediaKeys.createSession();
                    return mediaKeySession.generateRequest(initDataType, initData);
                }).then(function() {
                    return mediaKeySession.close();
                }).then(function(result) {
                    return Promise.resolve({ session: mediaKeySession, initDataType: initDataType} );
                });
            }

            promise_test(function()
            {
                return createClosedSession().then(function(result) {
                    var mediaKeySession = result.session;
                    var initDataType = result.initDataType;
                    var initData = getInitData(initDataType);

                    // Now try the operation that should fail.
                    return mediaKeySession.generateRequest(initDataType, initData);
                }).then(function() {
                    assert_unreached('Unexpected generateRequest() success.');
                }, function(error) {
                    assert_equals(error.name, 'InvalidStateError');
                    return Promise.resolve(null);
                });
            }, 'generateRequest() after close().');

            promise_test(function()
            {
                return createClosedSession().then(function(result) {
                    var mediaKeySession = result.session;

                    // Now try the operation that should fail.
                    return mediaKeySession.load('1234');
                }).then(function() {
                    assert_unreached('Unexpected load() success.');
                }, function(error) {
                    assert_equals(error.name, 'InvalidStateError');
                    return Promise.resolve(null);
                });
            }, 'load() after close().');

            promise_test(function()
            {
                return createClosedSession().then(function(result) {
                    var mediaKeySession = result.session;

                    // Now try the operation that should fail.
                    var validLicense = stringToUint8Array(createJWKSet(createJWK(stringToUint8Array('123'), stringToUint8Array('1234567890abcdef'))));
                    return mediaKeySession.update(validLicense);
                }).then(function() {
                    assert_unreached('Unexpected update() success.');
                }, function(error) {
                    assert_equals(error.name, 'InvalidStateError');
                    return Promise.resolve(null);
                });
            }, 'update() after close().');

            promise_test(function()
            {
                return createClosedSession().then(function(result) {
                    var mediaKeySession = result.session;

                    // Now try the operation that should fail.
                    return mediaKeySession.remove();
                }).then(function() {
                    assert_unreached('Unexpected remove() success.');
                }, function(error) {
                    assert_equals(error.name, 'InvalidStateError');
                    return Promise.resolve(null);
                });
            }, 'remove() after close().');

            promise_test(function()
            {
                return createClosedSession().then(function(result) {
                    var mediaKeySession = result.session;

                    // Now try calling close() again, which should succeed.
                    return mediaKeySession.close();
                });
            }, 'close() after close().');
        </script>
    </body>
</html>

