summaryrefslogtreecommitdiffstats
path: root/dom/media/mediasession/test/file_trigger_actionhanlder_window.html
blob: f3316d6dad6eeffd9a0dd769e00a1d4da0b2c8f9 (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
<!DOCTYPE HTML>
<html>
  <head>
    <title>Test window for triggering media session's action handler</title>
    <script src="/tests/SimpleTest/SimpleTest.js"></script>
    <script src="MediaSessionTestUtils.js"></script>
  </head>
<body>
<video id="testVideo" src="gizmo.mp4" loop></video>
<iframe id="childFrame"></iframe>
<script>

var triggeredActionNums = 0;

nextWindowMessage().then(
  async (event) => {
    const testInfo = event.data;
    await createSession(testInfo);
    // Media session would only become active if there is any media currently
    // playing. Non-active media session won't receive any actions. Therefore,
    // we start media playback before testing media session.
    await startMediaPlayback(testInfo);
    for (const action of gMediaSessionActions) {
      await waitUntilActionHandlerTriggered(action, testInfo);
    }
    endTestAndReportResult();
  });

/**
 * The following are helper functions
 */
async function startMediaPlayback({shouldCreateFrom}) {
  info(`wait until media starts playing`);
  if (shouldCreateFrom == "main-frame") {
    const video = document.getElementById("testVideo");
    await video.play();
    // As we can't observe `media-displayed-playback-changed` notification,
    // that can only be observed in the chrome process. Therefore, we use a
    // workaround instead which is to wait for a while to ensure that the
    // controller has already been created in the chrome process.
    let timeupdatecount = 0;
    await new Promise(r => video.ontimeupdate = () => {
      if (++timeupdatecount == 3) {
        video.ontimeupdate = null;
        r();
      }
    });
  } else {
    const iframe = document.getElementById("childFrame");
    iframe.contentWindow.postMessage("play", "*");
    await new Promise(r => {
      window.onmessage = event => {
        is(event.data, "played", `media started playing in child-frame`);
        r();
      };
    });
  }
}

async function createSession({shouldCreateFrom, origin}) {
  info(`create media session in ${shouldCreateFrom}`);
  if (shouldCreateFrom == "main-frame") {
    // Simply referencing media session will create media session.
    navigator.mediaSession;
    return;
  };
  const frame = document.getElementById("childFrame");
  const originURL = origin == "same-origin"
    ? "http://mochi.test:8888" : "http://example.org";
  frame.src = originURL + "/tests/dom/media/mediasession/test/file_trigger_actionhanlder_frame.html";
  await new Promise(r => frame.onload = r);
}

async function waitUntilActionHandlerTriggered(action, {shouldCreateFrom}) {
  info(`wait until '${action}' handler of media session created in ` +
       `${shouldCreateFrom} is triggered`);
  if (shouldCreateFrom == "main-frame") {
    let promise = new Promise(resolve => {
      navigator.mediaSession.setActionHandler(action, () => {
        ok(true, `Triggered ${action} handler`);
        triggeredActionNums++;
        resolve();
      });
    });
    SpecialPowers.generateMediaControlKeyTestEvent(action);
    await promise;
    return;
  }
  SpecialPowers.generateMediaControlKeyTestEvent(action);
  if ((await nextWindowMessage()).data == action) {
    info(`Triggered ${action} handler in child-frame`);
    triggeredActionNums++;
  }
}

function endTestAndReportResult() {
  const w = window.opener || window.parent;
  if (triggeredActionNums == gMediaSessionActions.length) {
    w.postMessage("success", "*");
  } else {
    w.postMessage("fail", "*");
  }
}

</script>
</body>
</html>