Bug 1295921 - P5: Test video suspend canceling. r?jwwang draft
authorDan Glastonbury <dglastonbury@mozilla.com>
Thu, 29 Sep 2016 14:07:23 +1000
changeset 450825 5a2984a53741f19df84b4215c46dd54101b4be3b
parent 450824 35c365c257bde40bbd556bd70ec1981b292ae5ee
child 450826 7f516a0e3426d3214d71ae4697d4b456016a8504
push id38957
push userbmo:dglastonbury@mozilla.com
push dateMon, 19 Dec 2016 02:15:56 +0000
reviewersjwwang
bugs1295921
milestone53.0a1
Bug 1295921 - P5: Test video suspend canceling. r?jwwang MozReview-Commit-ID: B1zLWS9HeSG
dom/media/test/background_video.js
dom/media/test/mochitest.ini
dom/media/test/test_background_video_cancel_suspend_taint.html
dom/media/test/test_background_video_cancel_suspend_visible.html
--- a/dom/media/test/background_video.js
+++ b/dom/media/test/background_video.js
@@ -29,86 +29,100 @@ function appendVideoToDoc(url, token, wi
   v.width = width;
   v.height = height;
   v.src = url;
   return v;
 }
 
 /**
  * @param {HTMLMediaElement} video Video element under test.
- * @returns {Promise} Promise that is resolved when video 'playing' event fires and rejected on error.
+ * @returns {Promise} Promise that is resolved when video 'playing' event fires.
  */
 function waitUntilPlaying(video) {
-  var p = once(video, 'playing', () => { ok(true, video.token + " played."); });
+  var p = once(video, 'playing', () => { ok(true, `${video.token} played.`); });
   Log(video.token, "Start playing");
   video.play();
   return p;
 }
 
 /**
  * @param {HTMLMediaElement} video Video element under test.
  * @returns {Promise} Promise which is resolved when video 'ended' event fires.
  */
 function waitUntilEnded(video) {
   Log(video.token, "Waiting for ended");
   if (video.ended) {
     ok(true, video.token + " already ended");
     return Promise.success();
   }
 
-  return once(video, 'ended', () => { ok(true, video.token + " ended"); });
+  return once(video, 'ended', () => { ok(true, `${video.token} ended`); });
+}
+
+/**
+ * @param {HTMLMediaElement} video Video element under test.
+ * @returns {Promise} Promise that is resolved when video decode begins
+ *                    suspend timer.
+ */
+function testSuspendBeginsWhenHidden(video) {
+  var p = once(video, 'mozbeginvideosuspend').then(() => {
+    ok(true, `${video.token} suspend begins`)
+  });
+  Log(video.token, 'Set Hidden');
+  video.setVisible(false);
+  return p;
 }
 
 /**
  * @param {HTMLMediaElement} video Video element under test.
  * @returns {Promise} Promise that is resolved when video decode suspends.
  */
 function testVideoSuspendsWhenHidden(video) {
   let p = once(video, 'mozentervideosuspend').then(() => {
-    ok(true, video.token + " suspends");
+    ok(true, `${video.token} suspends`);
   });
   Log(video.token, "Set hidden");
   video.setVisible(false);
   return p;
 }
 
 /**
  * @param {HTMLMediaElement} video Video element under test.
  * @returns {Promise} Promise that is resolved when video decode resumes.
  */
 function testVideoResumesWhenShown(video) {
   var p  = once(video, 'mozexitvideosuspend').then(() => {
-    ok(true, video.token + " resumes");
+    ok(true, `${video.token} resumes`);
   });
   Log(video.token, "Set visible");
   video.setVisible(true);
   return p;
 }
 
 /**
  * @param {HTMLVideoElement} video Video element under test.
  * @returns {Promise} Promise that is resolved if video ends and rejects if video suspends.
  */
 function checkVideoDoesntSuspend(video) {
   let p = Promise.race([
-    waitUntilEnded(video).then(() => { ok(true, video.token + ' ended before decode was suspended')}),
-    once(video, 'mozentervideosuspend', () => { Promise.reject(new Error(video.token + ' suspended')) })
+    waitUntilEnded(video).then(() => { ok(true, `${video.token} ended before decode was suspended`)}),
+    once(video, 'mozentervideosuspend', () => { Promise.reject(new Error(`${video.token} suspended`)) })
   ]);
   Log(video.token, "Set hidden.");
   video.setVisible(false);
   return p;
 }
 
 /**
  * @param {HTMLMediaElement} video Video element under test.
  * @param {number} time video current time to wait til.
  * @returns {Promise} Promise that is resolved once currentTime passes time.
  */
 function waitTil(video, time) {
-  Log(video.token, "Waiting for time to reach " + time + "s");
+  Log(video.token, `Waiting for time to reach ${time}s`);
   return new Promise(resolve => {
     video.addEventListener('timeupdate', function timeUpdateEvent() {
       if (video.currentTime > time) {
         video.removeEventListener(name, timeUpdateEvent);
         resolve();
       }
     });
   });
--- a/dom/media/test/mochitest.ini
+++ b/dom/media/test/mochitest.ini
@@ -945,16 +945,20 @@ tags = webvtt
 
 # The tests below contain backend-specific tests. Write backend independent
 # tests rather than adding to this list.
 [test_can_play_type_webm.html]
 [test_can_play_type_wave.html]
 [test_fragment_noplay.html]
 [test_fragment_play.html]
 
+[test_background_video_cancel_suspend_taint.html]
+tags = suspend
+[test_background_video_cancel_suspend_visible.html]
+tags = suspend
 [test_background_video_no_suspend_disabled.html]
 tags = suspend
 [test_background_video_no_suspend_short_vid.html]
 tags = suspend
 [test_background_video_suspend.html]
 tags = suspend
 [test_background_video_suspend_ends.html]
 tags = suspend
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_background_video_cancel_suspend_taint.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test Background Video Suspend Cancels (Element Taint)</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="manifest.js"></script>
+<script src="background_video.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+<script type="text/javascript">
+"use strict";
+
+var manager = new MediaTestManager;
+
+/**
+ * @param {HTMLMediaElement} video Video element under test.
+ * @returns {Promise} Promise that is resolved when video decode resumes.
+ */
+function testSuspendCancelsWhenTainted(video) {
+  function ended() {
+    video.removeEventListener("mozcancelvideosuspend", canceled);
+    ok(false, `${video.token} ended before suspend cancels`);
+    this.ended_resolve();
+  }
+
+  function canceled() {
+    video.removeEventListener("ended", ended);
+    ok(true, `${video.token} suspend cancels`);
+    this.canceled_resolve();
+  }
+
+  let p = Promise.race([
+    new Promise((resolve) => {
+      video.ended_resolve = resolve;
+      video.addEventListener('ended', ended, { 'once': true });
+    }),
+    new Promise((resolve) => {
+      video.canceled_resolve = resolve;
+      video.addEventListener('mozcancelvideosuspend', canceled, { 'once': true });
+    })
+  ]);
+
+  Log(video.token, "Mark tainted");
+
+  let c = document.createElement('canvas');
+  let g = c.getContext('2d');
+  g.drawImage(video, 0, 0, c.width, c.height);
+  ok(video.hasSuspendTaint(), 'video used with drawImage is tainted.');
+
+  return p;
+}
+
+startTest({
+  desc: 'Test Background Video Suspend Cancels (Element Taint)',
+  prefs: [
+    [ "media.test.video-suspend", true ],
+    [ "media.suspend-bkgnd-video.enabled", true ],
+    [ "media.suspend-bkgnd-video.delay-ms", 10000 ]
+  ],
+  tests: gDecodeSuspendTests,
+  runTest: (test, token) => {
+    let v = appendVideoToDoc(test.name, token);
+    manager.started(token);
+
+    waitUntilPlaying(v)
+      .then(() => testSuspendBeginsWhenHidden(v))
+      .then(() => testSuspendCancelsWhenTainted(v))
+      .then(() => { manager.finished(token); });
+  }
+});
+</script>
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_background_video_cancel_suspend_visible.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test Background Video Suspend Cancels (Visibility)</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="manifest.js"></script>
+<script src="background_video.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+<script type="text/javascript">
+"use strict";
+
+var manager = new MediaTestManager;
+
+/**
+ * Check that making the element visible before suspend timer delay causes the
+ * the suspend timer to be canceled.
+ * @param {HTMLMediaElement} video Video element under test.
+ * @returns {Promise} Promise that is resolved when video decode resumes.
+ */
+function testSuspendCancelsWhenShown(video) {
+  function ended() {
+    video.removeEventListener("mozcancelvideosuspend", canceled);
+    ok(false, `${video.token} ended before suspend cancels`);
+    this.ended_resolve();
+  }
+
+  function canceled() {
+    video.removeEventListener("ended", ended);
+    ok(true, `${video.token} suspend cancels`);
+    this.canceled_resolve();
+  }
+
+  let p = Promise.race([
+    new Promise((resolve) => {
+      video.ended_resolve = resolve;
+      video.addEventListener('ended', ended, { 'once': true });
+    }),
+    new Promise((resolve) => {
+      video.canceled_resolve = resolve;
+      video.addEventListener('mozcancelvideosuspend', canceled, { 'once': true });
+    })
+  ]);
+
+  Log(video.token, "Set visible");
+  video.setVisible(true);
+
+  return p;
+}
+
+startTest({
+  desc: 'Test Background Video Suspend Cancels (Visibility)',
+  prefs: [
+    [ "media.test.video-suspend", true ],
+    [ "media.suspend-bkgnd-video.enabled", true ],
+    [ "media.suspend-bkgnd-video.delay-ms", 10000 ]
+  ],
+  tests: gDecodeSuspendTests,
+  runTest: (test, token) => {
+    let v = appendVideoToDoc(test.name, token);
+    manager.started(token);
+
+    waitUntilPlaying(v)
+      .then(() => testSuspendBeginsWhenHidden(v))
+      .then(() => testSuspendCancelsWhenShown(v))
+      .then(() => {
+        ok(true, `${v.token} finished`);
+        manager.finished(token);
+      });
+  }
+});
+</script>