summaryrefslogtreecommitdiffstats
path: root/dom/media/test/test_periodic_timeupdate.html
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/media/test/test_periodic_timeupdate.html100
1 files changed, 100 insertions, 0 deletions
diff --git a/dom/media/test/test_periodic_timeupdate.html b/dom/media/test/test_periodic_timeupdate.html
new file mode 100644
index 0000000000..5d40c7e38a
--- /dev/null
+++ b/dom/media/test/test_periodic_timeupdate.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Periodic timeupdate test</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<script type="application/javascript">
+
+/**
+ * To ensure that when dispatching periodic `timeupdate` event, we would only
+ * dispatch that once within 250ms according to the spec. This test would end
+ * after receiving certain number of timeupdate` event.
+ */
+const sNumPeriodicTimeupdatesToEndTestAfter = 5;
+const sTimeThreshold = 250;
+
+add_task(async function testPeriodicTimeupdateShouldOnlyBeDispatchedOnceWithin250Ms() {
+ const video = document.createElement('video');
+ video.src = "gizmo.mp4";
+ video.loop = true;
+ video._timeupdateCount = 0;
+ document.body.appendChild(video);
+ ok(await video.play().then(_=>true,_=>false), "video started playing");
+ const culprit = createCulpritToMakeMainThreadBusy();
+ await new Promise(r => {
+ function endTest() {
+ video.removeEventListener("timeupdate", checkTimeupdate);
+ culprit.shutdown();
+ r();
+ }
+ video.onseeking = () => {
+ info(`seeking starts (looping back to the head)`);
+ video._ignoreEvents = true;
+ }
+ video.onseeked = () => {
+ info(`seeking ends`);
+ video._ignoreEvents = false;
+ }
+ function checkTimeupdate(event) {
+ // When reaching to the end, video would perform a seek to the start
+ // position where one mandatory `timeupdate` would be dispatched.
+ if (video._ignoreEvents) {
+ info(`ignore non-periodic timeupdate because that is allowed to be dispatched within ${sTimeThreshold}ms`);
+ return;
+ }
+
+ const now = performance.now();
+ if (video._prevTime === undefined) {
+ info(`recevied the first 'timeupdate'`);
+ video._prevTime = now;
+ return;
+ }
+
+ const timeDiff = now - video._prevTime;
+ if (timeDiff < sTimeThreshold) {
+ ok(false, `Time diff ${timeDiff} is smaller than ${sTimeThreshold}ms!`);
+ endTest();
+ return;
+ }
+
+ ok(true, `Time diff ${timeDiff} since last time received 'timeupdate'`);
+ video._prevTime = now;
+ info(`check timeupdate ${++video._timeupdateCount} time`);
+ if (video._timeupdateCount == sNumPeriodicTimeupdatesToEndTestAfter) {
+ endTest();
+ }
+ };
+ video.addEventListener("timeupdate", checkTimeupdate);
+ });
+});
+
+window.onmessage = _ => blockMainThreadForMilliseconds(1);
+
+/**
+ * Following are helper functions
+ */
+function blockMainThreadForMilliseconds(ms) {
+ const lastTime = performance.now();
+ while (lastTime + ms > performance.now());
+}
+
+function createCulpritToMakeMainThreadBusy() {
+ let culprit = {};
+ culprit._id = setInterval(_ => {
+ blockMainThreadForMilliseconds(1000);
+ }, 0);
+ culprit.shutdown = _ => {
+ clearInterval(culprit._id);
+ }
+ for (let i = 0; i < 5000; ++i) {
+ window.postMessage("foo", "*");
+ }
+ return culprit;
+}
+
+</script>
+</head>
+<body>
+</body>
+</html>