Bug 1345403 part 5 - Test video suspend canceling; r?jwwang draft
authorKaku Kuo <kaku@mozilla.com>
Wed, 08 Mar 2017 21:18:13 +0800
changeset 497393 c5c4911b892f0125f1a5621ae327b044b960d83d
parent 497392 c83c34d4b9b8984628b7df5af0e0bf58d80e947e
child 497394 4ea126c513aadef2dee78f820550ca002e8d77b6
push id48886
push userbmo:kaku@mozilla.com
push dateMon, 13 Mar 2017 08:40:05 +0000
reviewersjwwang
bugs1345403
milestone55.0a1
Bug 1345403 part 5 - Test video suspend canceling; r?jwwang MozReview-Commit-ID: 99IDqpwuRIf
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.resolve();
   }
 
-  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 starts
+ *                    suspend timer.
+ */
+function testSuspendTimerStartedWhenHidden(video) {
+  var p = once(video, 'mozstartvideosuspendtimer').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
@@ -1123,16 +1123,22 @@ tags = webvtt
 skip-if = toolkit == 'android' # android(bug 1232305)
 [test_can_play_type_wave.html]
 skip-if = android_version == '15' || android_version == '17' # android(bug 1232305)
 [test_fragment_noplay.html]
 skip-if = android_version == '15' || android_version == '17' # android(bug 1232305)
 [test_fragment_play.html]
 skip-if = android_version == '15' || android_version == '17' # bug 1335520, bug 1209318, android(bug 1232305)
 
+[test_background_video_cancel_suspend_taint.html]
+skip-if = toolkit == 'android' # bug 1346705
+tags = suspend
+[test_background_video_cancel_suspend_visible.html]
+skip-if = toolkit == 'android' # bug 1346705
+tags = suspend
 [test_background_video_no_suspend_disabled.html]
 skip-if = toolkit == 'android' # android(bug 1304480)
 tags = suspend
 [test_background_video_no_suspend_short_vid.html]
 skip-if = toolkit == 'android' # android(bug 1304480)
 tags = suspend
 [test_background_video_suspend.html]
 skip-if = toolkit == 'android' # android(bug 1304480)
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 testSuspendTimerCanceledWhenTainted(video) {
+  function ended() {
+    video.removeEventListener("mozcancelvideosuspendtimer", 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('mozcancelvideosuspendtimer', 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(() => testSuspendTimerStartedWhenHidden(v))
+      .then(() => testSuspendTimerCanceledWhenTainted(v))
+      .then(() => { manager.finished(token); });
+  }
+});
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_background_video_cancel_suspend_visible.html
@@ -0,0 +1,69 @@
+<!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 testSuspendTimerCanceledWhenShown(video) {
+  function ended() {
+    video.removeEventListener("mozcancelvideosuspendtimer", 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('mozcancelvideosuspendtimer', 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(() => testSuspendTimerStartedWhenHidden(v))
+      .then(() => testSuspendTimerCanceledWhenShown(v))
+      .then(() => {
+        ok(true, `${v.token} finished`);
+        manager.finished(token);
+      });
+  }
+});