summaryrefslogtreecommitdiffstats
path: root/dom/media/test/browser/head.js
blob: 489d107be541fcf88b6ef40beaa149bb6bc6f50a (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
"use strict";

/* import-globals-from ../eme_standalone.js */

// Opens a tab containing a blank page, returns a promise that will resolve
// to that tab.
function openTab() {
  const emptyPageUri =
    "https://example.com/browser/dom/media/test/browser/file_empty_page.html";
  return BrowserTestUtils.openNewForegroundTab(window.gBrowser, emptyPageUri);
}

// Creates and configures a video element for non-MSE playback in `tab`. Does not
// start playback for the element. Returns a promise that will resolve once
// the element is setup and ready for playback.
function loadVideo(tab, extraEvent = undefined) {
  return SpecialPowers.spawn(
    tab.linkedBrowser,
    [extraEvent],
    async _extraEvent => {
      let video = content.document.createElement("video");
      video.id = "media";
      content.document.body.appendChild(video);

      video.src = "gizmo.mp4";
      video.load();

      info(`waiting 'loadeddata' event to ensure playback is ready`);
      let promises = [];
      promises.push(new Promise(r => (video.onloadeddata = r)));
      if (_extraEvent != undefined) {
        info(
          `waiting '${_extraEvent}' event to ensure the probe has been recorded`
        );
        promises.push(
          new Promise(r =>
            video.addEventListener(_extraEvent, r, { once: true })
          )
        );
      }
      await Promise.allSettled(promises);
    }
  );
}

// Creates and configures a video element for MSE playback in `tab`. Does not
// start playback for the element. Returns a promise that will resolve once
// the element is setup and ready for playback.
function loadMseVideo(tab, extraEvent = undefined) {
  return SpecialPowers.spawn(
    tab.linkedBrowser,
    [extraEvent],
    async _extraEvent => {
      async function once(target, name) {
        return new Promise(r =>
          target.addEventListener(name, r, { once: true })
        );
      }

      let video = content.document.createElement("video");
      video.id = "media";
      content.document.body.appendChild(video);

      info(`starting setup MSE`);
      const ms = new content.wrappedJSObject.MediaSource();
      video.src = content.wrappedJSObject.URL.createObjectURL(ms);
      await once(ms, "sourceopen");
      const sb = ms.addSourceBuffer("video/mp4");
      const videoFile = "bipbop2s.mp4";
      let fetchResponse = await content.fetch(videoFile);
      sb.appendBuffer(await fetchResponse.arrayBuffer());
      await once(sb, "updateend");
      ms.endOfStream();
      await once(ms, "sourceended");

      info(`waiting 'loadeddata' event to ensure playback is ready`);
      let promises = [];
      promises.push(once(video, "loadeddata"));
      if (_extraEvent != undefined) {
        info(
          `waiting '${_extraEvent}' event to ensure the probe has been recorded`
        );
        promises.push(
          new Promise(r =>
            video.addEventListener(_extraEvent, r, { once: true })
          )
        );
      }
      await Promise.allSettled(promises);
    }
  );
}

// Creates and configures a video element for EME playback in `tab`. Does not
// start playback for the element. Returns a promise that will resolve once
// the element is setup and ready for playback.
function loadEmeVideo(tab, extraEvent = undefined) {
  const emeHelperUri =
    gTestPath.substr(0, gTestPath.lastIndexOf("/")) + "/eme_standalone.js";
  return SpecialPowers.spawn(
    tab.linkedBrowser,
    [emeHelperUri, extraEvent],
    async (_emeHelperUri, _extraEvent) => {
      async function once(target, name) {
        return new Promise(r =>
          target.addEventListener(name, r, { once: true })
        );
      }

      // Helper to clone data into content so the EME helper can use the data.
      function cloneIntoContent(data) {
        return Cu.cloneInto(data, content.wrappedJSObject);
      }

      info(`starting setup EME`);
      Services.scriptloader.loadSubScript(_emeHelperUri, content);
      let video = content.document.createElement("video");
      video.id = "media";
      content.document.body.appendChild(video);
      let emeHelper = new content.wrappedJSObject.EmeHelper();
      emeHelper.SetKeySystem(
        content.wrappedJSObject.EmeHelper.GetClearkeyKeySystemString()
      );
      emeHelper.SetInitDataTypes(cloneIntoContent(["webm"]));
      emeHelper.SetVideoCapabilities(
        cloneIntoContent([{ contentType: 'video/webm; codecs="vp9"' }])
      );
      emeHelper.AddKeyIdAndKey(
        "2cdb0ed6119853e7850671c3e9906c3c",
        "808b9adac384de1e4f56140f4ad76194"
      );
      emeHelper.onerror = error => {
        is(false, `Got unexpected error from EME helper: ${error}`);
      };
      await emeHelper.ConfigureEme(video);

      info(`starting setup MSE`);
      const ms = new content.wrappedJSObject.MediaSource();
      video.src = content.wrappedJSObject.URL.createObjectURL(ms);
      await once(ms, "sourceopen");
      const sb = ms.addSourceBuffer("video/webm");
      const videoFile = "sintel-short-clearkey-subsample-encrypted-video.webm";
      let fetchResponse = await content.fetch(videoFile);
      sb.appendBuffer(await fetchResponse.arrayBuffer());
      await once(sb, "updateend");
      ms.endOfStream();
      await once(ms, "sourceended");

      info(`waiting 'loadeddata' event to ensure playback is ready`);
      let promises = [];
      promises.push(once(video, "loadeddata"));
      if (_extraEvent != undefined) {
        info(
          `waiting '${_extraEvent}' event to ensure the probe has been recorded`
        );
        promises.push(
          new Promise(r =>
            video.addEventListener(_extraEvent, r, { once: true })
          )
        );
      }
      await Promise.allSettled(promises);
    }
  );
}