summaryrefslogtreecommitdiffstats
path: root/dom/media/test/test_eme_playback.html
blob: bcfa058e3462988dc3dbb48323ffc2d4bc1f5b2d (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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
<!DOCTYPE HTML>
<html>
<head>
  <title>Test Encrypted Media Extensions</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
  <script type="text/javascript" src="manifest.js"></script>
  <script type="text/javascript" src="https://example.com:443/tests/dom/media/test/eme.js"></script>
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
/* import-globals-from eme.js */
var manager = new MediaTestManager;

function ArrayBuffersEqual(a, b) {
  if (a.byteLength != b.byteLength) {
    return false;
  }
  var ua = new Uint8Array(a);
  var ub = new Uint8Array(b);
  for (var i = 0; i < ua.length; i++) {
    if (ua[i] != ub[i]) {
      return false;
    }
  }
  return true;
}

function KeysChangeFunc(session, keys, token) {
  session.keyIdsReceived = [];
  for (var keyid in keys) {
    Log(token, "Set " + keyid + " to false in session[" + session.sessionId + "].keyIdsReceived");
    session.keyIdsReceived[keyid] = false;
  }
  return function(ev) {
    var s = ev.target;
    s.gotKeysChanged = true;

    var keyList = [];
    var valueList = [];
    var map = s.keyStatuses;

    // Test that accessing keys not known to the CDM has expected behaviour.
    var absentKey = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
                                    0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]);
    is(map.has(absentKey), false, "Shouldn't have a key that's not in the media");
    is(map.get(absentKey), undefined, "Unknown keys should undefined status");

    // Verify known keys have expected status.
    for (let [key, val] of map.entries()) {
      is(key.constructor, ArrayBuffer, "keyId should be ArrayBuffer");
      ok(map.has(key), "MediaKeyStatusMap.has() should work.");
      is(map.get(key), val, "MediaKeyStatusMap.get() should work.");
      keyList.push(key);
      valueList.push(val);
      is(val, "usable", token + ": key status should be usable");
      var kid = Base64ToHex(window.btoa(ArrayBufferToString(key)));
      ok(kid in s.keyIdsReceived, TimeStamp(token) + " session[" + s.sessionId + "].keyIdsReceived contained " + kid + " as expected.");
      s.keyIdsReceived[kid] = true;
    }

    var index = 0;
    for (var keyId of map.keys()) {
      ok(ArrayBuffersEqual(keyId, keyList[index]), "MediaKeyStatusMap.keys() should correspond to entries");
      index++;
    }
    index = 0;
    for (let val of map.values()) {
      is(val, valueList[index], "MediaKeyStatusMap.values() should correspond to entries");
      index++;
    }
  }
}

function startTest(test, token)
{
  manager.started(token);

  var sessions = [];

  function onSessionCreated(session) {
    sessions.push(session);
    session.addEventListener("keystatuseschange", KeysChangeFunc(session, test.keys, token));

    session.numKeystatuseschangeEvents = 0;
    session.numOnkeystatuseschangeEvents = 0;

    session.addEventListener("keystatuseschange", function() {
      session.numKeystatuseschangeEvents += 1;
    });
    session.onkeystatuseschange = function() {
      session.numOnkeystatuseschangeEvents += 1;
    };

    session.numMessageEvents = 0;
    session.numOnMessageEvents = 0;
    session.addEventListener("message", function() {
      session.numMessageEvents += 1;
    });
    session.onmessage = function() {
      session.numOnMessageEvents += 1;
    };
  }

  let v = document.createElement("video");
  document.body.appendChild(v);

  var gotEncrypted = 0;
  let finish = new EMEPromise;

  v.addEventListener("encrypted", function(ev) {
    gotEncrypted += 1;
  });

  v.addEventListener("loadedmetadata", function() {
    ok(SpecialPowers.do_lookupGetter(v, "isEncrypted").apply(v),
       TimeStamp(token) + " isEncrypted should be true");
    is(v.isEncrypted, undefined, "isEncrypted should not be accessible from content");
  });

  v.addEventListener("ended", function(ev) {
    ok(true, TimeStamp(token) + " got ended event");

    is(gotEncrypted, test.sessionCount,
       TimeStamp(token) + " encrypted events expected: " + test.sessionCount
       + ", actual: " + gotEncrypted);

    ok(Math.abs(test.duration - v.duration) < 0.1,
       TimeStamp(token) + " Duration of video should be corrrect");
    ok(Math.abs(test.duration - v.currentTime) < 0.1,
       TimeStamp(token) + " Current time should be same as duration");

    // Verify all sessions had all keys went sent to the CDM usable, and thus
    // that we received keystatuseschange event(s).
    is(sessions.length, test.sessionCount, TimeStamp(token) + " should have "
                        + test.sessionCount
                        + " session" + (test.sessionCount === 1 ? "" : "s"));
    var keyIdsReceived = [];
    for (var keyid in test.keys) { keyIdsReceived[keyid] = false; }
    for (var i = 0; i < sessions.length; i++) {
      var session = sessions[i];
      ok(session.gotKeysChanged,
         TimeStamp(token) + " session[" + session.sessionId
         + "] should have received at least one keychange event");
      for (let kid in session.keyIdsReceived) {
        Log(token, "session[" + session.sessionId + "] key " + kid + " = " + (session.keyIdsReceived[kid] ? "true" : "false"));
        if (session.keyIdsReceived[kid]) { keyIdsReceived[kid] = true; }
      }
      ok(session.numKeystatuseschangeEvents > 0, TimeStamp(token) + " should get key status changes");
      is(session.numKeystatuseschangeEvents, session.numOnkeystatuseschangeEvents,
         TimeStamp(token) + " should have as many keystatuseschange event listener calls as event handler calls.");

      ok(session.numMessageEvents > 0, TimeStamp(token) + " should get message events");
      is(session.numMessageEvents, session.numOnMessageEvents,
         TimeStamp(token) + " should have as many message event listener calls as event handler calls.");
    }
    for (let kid in keyIdsReceived) {
      ok(keyIdsReceived[kid], TimeStamp(token) + " key with id " + kid + " was usable as expected");
    }

    CloseSessions(v, sessions).then(finish.resolve, finish.reject);
  });

  Promise.all([
    LoadInitData(v, test, token),
    CreateAndSetMediaKeys(v, test, token),
    LoadTest(test, v, token)])
  .then(values => {
    v.play();
    let initData = values[0];
    initData.map(ev => {
      let session = v.mediaKeys.createSession();
      onSessionCreated(session);
      MakeRequest(test, token, ev, session);
    });
    return finish.promise;
  })
  .catch(reason => ok(false, reason))
  .then(() => manager.finished(token));
}

SimpleTest.waitForExplicitFinish();
manager.runTests(gEMETests, startTest);
</script>
</pre>
</body>
</html>