function runTest(config) { // For debugging timeouts, keep track of the number of the // various events received. var debugEncryptedEventFired = false; var debugWaitingForKeyEventFired = false; var debugTimeUpdateEventCount = 0; var debugMessage = ''; // Set global option explicit_timeout to true and control // the timeout in the promise test below. setup({ explicit_timeout: true }); promise_test(function (test) { var video = config.video; var keysystem = config.keysystem; var configuration = { initDataTypes: [config.initDataType], audioCapabilities: [{ contentType: config.audioType }], videoCapabilities: [{ contentType: config.videoType }], sessionTypes: ['temporary'] }; var initData; var initDataType; var mediaKeySession; // As this code doesn't wait for the 'message' event for clearkey to avoid // race conditions with 'waitingforkey', specify the key ID and // key used by the encrypted content. var keyId = new Uint8Array(config.content.keys[0].kid); var rawKey = new Uint8Array(config.content.keys[0].key); // Use the message handler for non clearkey drm var handler = config.messageHandler || null; // Override timeout() to use custom message instead of default // message "Test timed out" test.timeout = function () { var message = 'timeout. message = ' + debugMessage + ', encrypted: ' + debugEncryptedEventFired + ', waitingforkey: ' + debugWaitingForKeyEventFired + ', timeupdate count: ' + debugTimeUpdateEventCount; this.timeout_id = null; this.set_status(this.TIMEOUT, message); this.phase = this.phases.HAS_RESULT; this.done(); }; return navigator.requestMediaKeySystemAccess(keysystem, [configuration]).then(function (access) { debugMessage = 'createMediaKeys()'; return access.createMediaKeys(); }).then(function (mediaKeys) { debugMessage = 'setMediaKeys()'; return video.setMediaKeys(mediaKeys); }).then(function () { return testmediasource(config); }).then(function (source) { debugMessage = 'wait_for_encrypted_event()'; mediaSource = source; video.src = URL.createObjectURL(mediaSource); video.play(); return wait_for_encrypted_event(video); }).then(function (e) { // Received the 'encrypted' event(s), so keep a copy of // the initdata for use when creating the session later. initDataType = config.initData ? config.initDataType : e.initDataType; initData = config.initData || e.initData; // Wait until the video indicates that it needs a key to // continue. debugMessage = 'wait_for_waitingforkey_event()'; return wait_for_waitingforkey_event(video); }).then(function () { // Make sure the video is NOT paused and not progressing // before a key is provided. This requires the video // to NOT have a clear lead. assert_false(video.paused); assert_less_than(video.currentTime, 0.2); // Create a session. mediaKeySession = video.mediaKeys.createSession('temporary'); debugMessage = 'generateRequest()'; return mediaKeySession.generateRequest(initDataType, initData); }).then(function () { // generateRequest() will cause a 'message' event to // occur specifying the keyId that is needed // Add the key needed to decrypt. return wait_for_message_event(mediaKeySession, handler); }).then(function () { // Video should start playing now that it can decrypt the // streams, so wait until a little bit of the video has // played. debugMessage = 'wait_for_timeupdate_event()'; return wait_for_timeupdate_event(video); }).catch(function (error) { assert_unreached('Error: ' + error.name); }); // Typical test duration is 6 seconds on release builds // (12 seconds on debug). }, 'Waiting for a key.'); // Wait for an 'encrypted' event function wait_for_encrypted_event(video) { return new Promise(function (resolve) { video.addEventListener('encrypted', function listener(e) { assert_equals(e.target, video); assert_true(e instanceof window.MediaEncryptedEvent); assert_equals(e.type, 'encrypted'); debugEncryptedEventFired = true; video.removeEventListener('encrypted', listener); resolve(e); }); }); }; // Wait for a 'waitingforkey' event. Promise resolved when the // event is received. function wait_for_waitingforkey_event(video) { return new Promise(function (resolve) { video.addEventListener('waitingforkey', function listener(e) { assert_equals(e.target, video); assert_equals(e.type, 'waitingforkey'); debugWaitingForKeyEventFired = true; video.removeEventListener('waitingforkey', listener); resolve(e); }); }); }; // Wait for a 'timeupdate' event. Promise resolved if |video| has // played for more than 0.2 seconds. function wait_for_timeupdate_event(video) { return new Promise(function (resolve) { video.addEventListener('timeupdate', function listener(e) { assert_equals(e.target, video); ++debugTimeUpdateEventCount; if (video.currentTime < 0.2) return; video.removeEventListener('timeupdate', listener); resolve(e); }); }); }; // We need to wait for the message even if for non clearkey DRMs. function wait_for_message_event(mediaKeySession, handler) { return new Promise(function (resolve, reject) { mediaKeySession.addEventListener('message', function listener(e) { assert_equals(e.target, mediaKeySession); assert_equals(e.type, 'message'); video.removeEventListener('message', listener); return handler(e.messageType, e.message).then(function (response) { return e.target.update(response) }).then(resolve, reject); }); }); } }