| <!DOCTYPE html> |
| <html> |
| <head> |
| <title>Waiting for a key.</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> |
| // For debugging timeouts, keep track of the number of the |
| // various events received. |
| var debugEncryptedEventCount = 0; |
| var debugWaitingForKeyEventCount = 0; |
| var debugTimeUpdateEventCount = 0; |
| var debugMessage = ''; |
| |
| promise_test(function(test) |
| { |
| var video = document.querySelector('video'); |
| var content = '../content/test-encrypted.webm'; |
| var initData; |
| var initDataType; |
| var mediaKeySession; |
| |
| test.timeout = function() |
| { |
| var message = 'timeout. message = ' + debugMessage |
| + ', encrypted: ' + debugEncryptedEventCount |
| + ', waitingforkey: ' + debugWaitingForKeyEventCount |
| + ', timeupdate: ' + debugTimeUpdateEventCount; |
| test.force_timeout(); |
| test.timeout_id = null; |
| test.set_status(2, message); |
| test.done(); |
| }; |
| |
| // As this code doesn't wait for the 'message' event to avoid |
| // race conditions with 'waitingforkey', specify the key ID and |
| // key used by the encrypted content. |
| var keyId = stringToUint8Array('0123456789012345'); |
| var rawKey = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, |
| 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]); |
| |
| return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getConfigurationForFile(content)).then(function(access) { |
| debugMessage = 'createMediaKeys()'; |
| return access.createMediaKeys(); |
| }).then(function(mediaKeys) { |
| debugMessage = 'setMediaKeys()'; |
| return video.setMediaKeys(mediaKeys); |
| }).then(function() { |
| video.src = content; |
| video.play(); |
| debugMessage = 'wait_for_encrypted_event()'; |
| 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. |
| initData = e.initData; |
| initDataType = e.initDataType; |
| |
| // 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_equals(video.currentTime, 0); |
| |
| // Create a session. |
| mediaKeySession = video.mediaKeys.createSession(); |
| debugMessage = 'generateRequest()'; |
| return mediaKeySession.generateRequest(initDataType, initData); |
| }).then(function() { |
| // generateRequest() will cause a 'message' event to |
| // occur specifying the keyId that is needed, but we |
| // ignore it since we already know what keyId is needed. |
| // Add the key needed to decrypt. |
| var jwkSet = stringToUint8Array(createJWKSet(createJWK(keyId, rawKey))); |
| debugMessage = 'update()'; |
| return mediaKeySession.update(jwkSet); |
| }).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); |
| }); |
| |
| // Typical test duration is 6 seconds on release builds |
| // (12 seconds on debug). Since the test is timing out anyway, |
| // make the duration 5 seconds so that the timeout function |
| // is actually called (instead of simply aborting the test). |
| }, 'Waiting for a key.', { timeout: 5000 }); |
| |
| // Wait for a pair of 'encrypted' events. Promise resolved on |
| // second event. |
| function wait_for_encrypted_event(video) |
| { |
| var encryptedEventCount = 0; |
| 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'); |
| |
| // The same decryption key is used by both the audio |
| // and the video streams so wait for the second event |
| // to ensure we see both events. |
| ++debugEncryptedEventCount; |
| if (++encryptedEventCount != 2) |
| return; |
| |
| video.removeEventListener('encrypted', listener); |
| resolve(e); |
| }); |
| }); |
| }; |
| |
| // Wait for a 'waitingforkey' event. Promise resolved when the |
| // event is received. |
| function wait_for_waitingforkey_event(video) |
| { |
| var waitingForKeyEventCount = 0; |
| return new Promise(function(resolve) { |
| video.addEventListener('waitingforkey', function listener(e) { |
| assert_equals(e.target, video); |
| assert_equals(e.type, 'waitingforkey'); |
| |
| ++debugWaitingForKeyEventCount; |
| ++waitingForKeyEventCount; |
| // TODO(jrummell): waitingforkey event should only |
| // occur once. http://crbug.com/461903 |
| // assert_equals(waitingForKeyEventCount, 1, 'Multiple waitingforkey events'); |
| |
| 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); |
| }); |
| }); |
| }; |
| </script> |
| </body> |
| </html> |