function runTest(config) { var keysystem = config.keysystem; var testname = testnamePrefix(null, config.keysystem); var initDataType = config.initDataType; var initData = config.initData; var configuration = { initDataTypes: [config.initDataType], audioCapabilities: [{contentType: config.audioType}], videoCapabilities: [{contentType: config.videoType}], sessionTypes: ['temporary'] }; var kTypeSpecificGenerateRequestExceptionsTestCases = [ // Tests in this set use a shortened parameter name due to // format_value() only returning the first 60 characters as the // result. With a longer name the first 60 characters is not // enough to determine which test failed. Even with the // shortened name, the error message for the last couple of // tests is the same. // Too few parameters. { exception: 'TypeError', func: function (mk1, type) { return mk1.createSession().generateRequest(type); } }, // Invalid parameters. { exception: 'TypeError', func: function (mk2, type) { return mk2.createSession().generateRequest(type, ''); } }, { exception: 'TypeError', func: function (mk3, type) { return mk3.createSession().generateRequest(type, null); } }, { exception: 'TypeError', func: function (mk4, type) { return mk4.createSession().generateRequest(type, undefined); } }, { exception: 'TypeError', func: function (mk5, type) { return mk5.createSession().generateRequest(type, 1); } }, // (new Uint8Array(0)) returns empty array. So 'TypeError' should // be returned. { exception: 'TypeError', func: function (mk6, type) { return mk6.createSession().generateRequest(type, new Uint8Array(0)); } } ]; function generateRequestTestExceptions(){ return new Promise(function(resolve, reject){ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { assert_true(isTypeSupported, "initDataType not supported"); return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); }).then(function (access) { return access.createMediaKeys(); }).then(function (mediaKeys) { var mp4SessionPromises = kTypeSpecificGenerateRequestExceptionsTestCases.map(function (testCase) { return test_exception(testCase, mediaKeys, initDataType, initData); }); assert_not_equals(mp4SessionPromises.length, 0); return Promise.all(mp4SessionPromises); }).then(function (result) { resolve(); }).catch(function (error) { reject(error); }); }) } promise_test(function() { return generateRequestTestExceptions(); }, testname + ' test MediaKeySession generateRequest() exceptions.'); var kLoadExceptionsTestCases = [ // Too few parameters. { exception: 'TypeError', func: function (mk1) { return mk1.createSession('temporary').load(); } }, { exception: 'TypeError', func: function (mk3) { return mk3.createSession('temporary').load(''); } }, { exception: 'TypeError', func: function (mk4) { return mk4.createSession('temporary').load(1); } }, { exception: 'TypeError', func: function (mk5) { return mk5.createSession('temporary').load('!@#$%^&*()'); } }, { exception: 'TypeError', func: function (mk6) { return mk6.createSession('temporary').load('1234'); } } ]; function loadTestExceptions(){ return new Promise(function(resolve, reject){ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { assert_true(isTypeSupported, "initDataType not supported"); return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); }).then(function (access) { return access.createMediaKeys(); }).then(function (mediaKeys) { var sessionPromises = kLoadExceptionsTestCases.map(function (testCase) { return test_exception(testCase, mediaKeys); }); assert_not_equals(sessionPromises.length, 0); return Promise.all(sessionPromises); }).then(function () { resolve(); }).catch(function (error) { reject(error); }); }) } promise_test(function() { return loadTestExceptions(); }, testname + ' test MediaKeySession load() exceptions.'); // All calls to |func| in this group are supposed to succeed. // However, the spec notes that some things are optional for // Clear Key. In particular, support for persistent sessions // is optional. Since some implementations won't support some // features, a NotSupportedError is treated as a success // if |isNotSupportedAllowed| is true. var kCreateSessionTestCases = [ // Use the default sessionType. { func: function(mk) { return mk.createSession(); }, isNotSupportedAllowed: false }, // Try variations of sessionType. { func: function(mk) { return mk.createSession('temporary'); }, isNotSupportedAllowed: false }, { func: function(mk) { return mk.createSession(undefined); }, isNotSupportedAllowed: false }, { // Since this is optional, some Clear Key implementations // will succeed, others will return a "NotSupportedError". // Both are allowed results. func: function(mk) { return mk.createSession('persistent-license'); }, isNotSupportedAllowed: true }, // Try additional parameter, which should be ignored. { func: function(mk) { return mk.createSession('temporary', 'extra'); }, isNotSupportedAllowed: false } ]; // This function checks that calling generateRequest() works for // various sessions. |testCase.func| creates a MediaKeySession // object, and then generateRequest() is called on that object. It // allows for an NotSupportedError to be generated and treated as a // success, if allowed. See comment above kCreateSessionTestCases. function test_generateRequest(testCase, mediaKeys, type, initData) { var mediaKeySession; try { mediaKeySession = testCase.func.call(null, mediaKeys); } catch (e) { assert_true(testCase.isNotSupportedAllowed); assert_equals(e.name, 'NotSupportedError'); return Promise.resolve('not supported'); } return mediaKeySession.generateRequest(type, initData); } function generateRequestForVariousSessions(){ return new Promise(function(resolve, reject){ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { assert_true(isTypeSupported, "initDataType should be supported"); return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); }).then(function (access) { return access.createMediaKeys(); }).then(function (mediaKeys) { var mp4SessionPromises = kCreateSessionTestCases.map(function (testCase) { return test_generateRequest(testCase, mediaKeys, initDataType, initData); }); assert_not_equals(mp4SessionPromises.length, 0); return Promise.all(mp4SessionPromises); }).then(function () { resolve(); }).catch(function (error) { reject(error); }); }) } promise_test(function() { return generateRequestForVariousSessions(); }, testname + ' test if MediaKeySession generateRequest() resolves for various sessions'); var kUpdateSessionExceptionsTestCases = [ // Tests in this set use a shortened parameter name due to // format_value() only returning the first 60 characters as the // result. With a longer name (mediaKeySession) the first 60 // characters is not enough to determine which test failed. // Too few parameters. { exception: 'TypeError', func: function (s) { return s.update(); } }, // Invalid parameters. { exception: 'TypeError', func: function (s) { return s.update(''); } }, { exception: 'TypeError', func: function (s) { return s.update(null); } }, { exception: 'TypeError', func: function (s) { return s.update(undefined); } }, { exception: 'TypeError', func: function (s) { return s.update(1); } }, // (new Uint8Array(0)) returns empty array. So 'TypeError' should // be returned. { exception: 'TypeError', func: function (s) { return s.update(new Uint8Array(0)); } } ]; function updateTestExceptions(){ return new Promise(function(resolve, reject){ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { assert_true(isTypeSupported, "initDataType not supported"); return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); }).then(function (access) { return access.createMediaKeys(); }).then(function (mediaKeys) { var mp4SessionPromises = kUpdateSessionExceptionsTestCases.map(function (testCase) { var mediaKeySession = mediaKeys.createSession(); return mediaKeySession.generateRequest(initDataType, initData).then(function (result) { return test_exception(testCase, mediaKeySession); }); }); assert_not_equals(mp4SessionPromises.length, 0); return Promise.all(mp4SessionPromises); }).then(function () { resolve(); }).catch(function (error) { reject(error); }); }) } promise_test(function() { return updateTestExceptions(); }, testname + ' test MediaKeySession update() exceptions.'); function create_close_exception_test(mediaKeys) { var mediaKeySession = mediaKeys.createSession(); return mediaKeySession.close().then(function (result) { assert_unreached('close() should not succeed if session uninitialized'); }).catch(function (error) { assert_equals(error.name, 'InvalidStateError'); // Return something so the promise resolves. return Promise.resolve(); }); } function closeTestExceptions(){ return new Promise(function(resolve, reject){ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { assert_true(isTypeSupported, "initDataType not supported"); return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); }).then(function (access) { return access.createMediaKeys(); }).then(function (mediaKeys) { return create_close_exception_test(mediaKeys); }).then(function () { resolve(); }).catch(function (error) { reject(error); }); }); } promise_test(function() { return closeTestExceptions(); }, testname + ' test MediaKeySession close() exceptions.'); function create_remove_exception_test(mediaKeys, type, initData) { // remove() on an uninitialized session should fail. var mediaKeySession = mediaKeys.createSession('temporary'); return mediaKeySession.remove().then(function (result) { assert_unreached('remove() should not succeed if session uninitialized'); }, function (error) { assert_equals(error.name, 'InvalidStateError'); }); } function removeTestException(){ return new Promise(function(resolve, reject){ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { assert_true(isTypeSupported, "initDataType not supported"); return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); }).then(function (access) { return access.createMediaKeys(); }).then(function (mediaKeys) { return create_remove_exception_test(mediaKeys, initDataType, initData); }).then(function () { resolve(); }).catch(function (error) { reject(error); }); }); } promise_test(function() { return removeTestException(); }, testname + ' test MediaKeySession remove() exceptions.'); // All calls to |func| in this group are supposed to succeed. // However, the spec notes that some things are optional for // Clear Key. In particular, support for persistent sessions // is optional. Since some implementations won't support some // features, a NotSupportedError is treated as a success // if |isNotSupportedAllowed| is true. var kCreateSessionTestCases = [ // Use the default sessionType. { func: function (mk) { return mk.createSession(); }, isNotSupportedAllowed: false }, // Try variations of sessionType. { func: function (mk) { return mk.createSession('temporary'); }, isNotSupportedAllowed: false }, { func: function (mk) { return mk.createSession(undefined); }, isNotSupportedAllowed: false }, { // Since this is optional, some Clear Key implementations // will succeed, others will return a "NotSupportedError". // Both are allowed results. func: function (mk) { return mk.createSession('persistent-license'); }, isNotSupportedAllowed: true }, // Try additional parameter, which should be ignored. { func: function (mk) { return mk.createSession('temporary', 'extra'); }, isNotSupportedAllowed: false } ]; // This function checks that calling |testCase.func| creates a // MediaKeySession object with some default values. It also // allows for an NotSupportedError to be generated and treated as a // success, if allowed. See comment above kCreateSessionTestCases. function test_createSession(testCase, mediaKeys) { var mediaKeySession; try { mediaKeySession = testCase.func.call(null, mediaKeys); } catch (e) { assert_true(testCase.isNotSupportedAllowed); return; } assert_equals(typeof mediaKeySession, 'object'); assert_equals(typeof mediaKeySession.addEventListener, 'function'); assert_equals(typeof mediaKeySession.sessionId, 'string'); assert_equals(typeof mediaKeySession.expiration, 'number'); assert_equals(typeof mediaKeySession.closed, 'object'); assert_equals(typeof mediaKeySession.keyStatuses, 'object'); assert_equals(typeof mediaKeySession.onkeystatuseschange, 'object'); assert_equals(typeof mediaKeySession.onmessage, 'object'); assert_equals(typeof mediaKeySession.generateRequest, 'function'); assert_equals(typeof mediaKeySession.load, 'function'); assert_equals(typeof mediaKeySession.update, 'function'); assert_equals(typeof mediaKeySession.close, 'function'); assert_equals(typeof mediaKeySession.remove, 'function'); assert_equals(mediaKeySession.sessionId, ''); } function createSessionTest(){ return new Promise(function(resolve, reject){ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { assert_true(isTypeSupported, "initDataType not supported"); return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); }).then(function (access) { return access.createMediaKeys(); }).then(function (mediaKeys) { kCreateSessionTestCases.map(function (testCase) { test_createSession(testCase, mediaKeys); }); resolve(); }).catch(function (error) { reject(error); }); }) } promise_test(function() { return createSessionTest(); }, testname + ' test MediaKeySession attribute syntax.'); }