summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/encrypted-media/scripts/waiting-for-a-key.js
blob: fdfb855677f384472668abb5d70b55158406f256 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
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);
            });
        });
    }
}