background_video.js (6024B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 // This file expects manager to be defined in the global scope. 6 /* global manager */ 7 /* import-globals-from manifest.js */ 8 9 "use strict"; 10 11 function startTest(test) { 12 info(test.desc); 13 SimpleTest.waitForExplicitFinish(); 14 SpecialPowers.pushPrefEnv({ set: test.prefs }, () => { 15 manager.runTests(test.tests, test.runTest); 16 }); 17 } 18 19 function nextVideoEnded(video) { 20 return nextEvent(video, "ended"); 21 } 22 23 function nextVideoPlaying(video) { 24 return nextEvent(video, "playing"); 25 } 26 27 function nextVideoResumes(video) { 28 return nextEvent(video, "mozexitvideosuspend"); 29 } 30 31 function nextVideoSuspends(video) { 32 return nextEvent(video, "mozentervideosuspend"); 33 } 34 35 /** 36 * @param {string} url video src. 37 * @returns {HTMLMediaElement} The created video element. 38 */ 39 function appendVideoToDoc(url, token, width, height) { 40 // Default size of (160, 120) is used by other media tests. 41 if (width === undefined) { 42 width = 160; 43 } 44 if (height === undefined) { 45 height = (3 * width) / 4; 46 } 47 48 let v = document.createElement("video"); 49 v.token = token; 50 v.width = width; 51 v.height = height; 52 v.src = url; 53 document.body.appendChild(v); 54 return v; 55 } 56 57 function appendVideoToDocWithoutLoad(token, width, height) { 58 // Default size of (160, 120) is used by other media tests. 59 if (width === undefined) { 60 width = 160; 61 } 62 if (height === undefined) { 63 height = (3 * width) / 4; 64 } 65 66 let v = document.createElement("video"); 67 v.token = token; 68 document.body.appendChild(v); 69 v.width = width; 70 v.height = height; 71 return v; 72 } 73 74 function loadAndWaitUntilLoadedmetadata(video, url, preloadType = "metadata") { 75 return new Promise(resolve => { 76 video.preload = preloadType; 77 video.addEventListener( 78 "loadedmetadata", 79 () => { 80 resolve(); 81 }, 82 true 83 ); 84 video.src = url; 85 }); 86 } 87 88 /** 89 * @param {HTMLMediaElement} video Video element with under test. 90 * @returns {Promise} Promise that is resolved when video 'visibilitychanged' event fires. 91 */ 92 function waitUntilVisible(video) { 93 let videoChrome = SpecialPowers.wrap(video); 94 if (videoChrome.isInViewPort) { 95 return Promise.resolve(); 96 } 97 98 return new Promise(resolve => { 99 videoChrome.addEventListener("visibilitychanged", () => { 100 if (videoChrome.isInViewPort) { 101 ok(true, `${video.token} is visible.`); 102 videoChrome.removeEventListener("visibilitychanged", this); 103 resolve(); 104 } 105 }); 106 }); 107 } 108 109 /** 110 * @param {HTMLMediaElement} video Video element under test. 111 * @returns {Promise} Promise that is resolved when video 'playing' event fires. 112 */ 113 function waitUntilPlaying(video) { 114 var p = once(video, "playing", () => { 115 ok(true, `${video.token} played.`); 116 }); 117 Log(video.token, "Start playing"); 118 video.play(); 119 return p; 120 } 121 122 /** 123 * @param {HTMLMediaElement} video Video element under test. 124 * @returns {Promise} Promise which is resolved when video 'ended' event fires. 125 */ 126 function waitUntilEnded(video) { 127 Log(video.token, "Waiting for ended"); 128 if (video.ended) { 129 ok(true, video.token + " already ended"); 130 return Promise.resolve(); 131 } 132 133 return once(video, "ended", () => { 134 ok(true, `${video.token} ended`); 135 }); 136 } 137 138 /** 139 * @param {HTMLMediaElement} video Video element under test. 140 * @returns {Promise} Promise that is resolved when video decode starts 141 * suspend timer. 142 */ 143 function testSuspendTimerStartedWhenHidden(video) { 144 var p = once(video, "mozstartvideosuspendtimer").then(() => { 145 ok(true, `${video.token} suspend begins`); 146 }); 147 Log(video.token, "Set Hidden"); 148 video.setVisible(false); 149 return p; 150 } 151 152 /** 153 * @param {HTMLMediaElement} video Video element under test. 154 * @returns {Promise} Promise that is resolved when video decode suspends. 155 */ 156 function testVideoSuspendsWhenHidden(video) { 157 let p = once(video, "mozentervideosuspend").then(() => { 158 ok(true, `${video.token} suspends`); 159 }); 160 Log(video.token, "Set hidden"); 161 video.setVisible(false); 162 return p; 163 } 164 165 /** 166 * @param {HTMLMediaElement} video Video element under test. 167 * @returns {Promise} Promise that is resolved when video decode resumes. 168 */ 169 function testVideoResumesWhenShown(video) { 170 var p = once(video, "mozexitvideosuspend").then(() => { 171 ok(true, `${video.token} resumes`); 172 }); 173 Log(video.token, "Set visible"); 174 video.setVisible(true); 175 return p; 176 } 177 178 /** 179 * @param {HTMLMediaElement} video Video element under test. 180 * @returns {Promise} Promise that is resolved when video decode resumes. 181 */ 182 function testVideoOnlySeekCompletedWhenShown(video) { 183 var p = once(video, "mozvideoonlyseekcompleted").then(() => { 184 ok(true, `${video.token} resumes`); 185 }); 186 Log(video.token, "Set visible"); 187 video.setVisible(true); 188 return p; 189 } 190 191 /** 192 * @param {HTMLVideoElement} video Video element under test. 193 * @returns {Promise} Promise that is resolved if video ends and rejects if video suspends. 194 */ 195 function checkVideoDoesntSuspend(video) { 196 let p = Promise.race([ 197 waitUntilEnded(video).then(() => { 198 ok(true, `${video.token} ended before decode was suspended`); 199 }), 200 once(video, "mozentervideosuspend", () => { 201 Promise.reject(new Error(`${video.token} suspended`)); 202 }), 203 ]); 204 Log(video.token, "Set hidden."); 205 video.setVisible(false); 206 return p; 207 } 208 209 /** 210 * @param {HTMLMediaElement} video Video element under test. 211 * @param {number} time video current time to wait til. 212 * @returns {Promise} Promise that is resolved once currentTime passes time. 213 */ 214 function waitTil(video, time) { 215 Log(video.token, `Waiting for time to reach ${time}s`); 216 return new Promise(resolve => { 217 video.addEventListener("timeupdate", function timeUpdateEvent() { 218 if (video.currentTime > time) { 219 video.removeEventListener(name, timeUpdateEvent); 220 resolve(); 221 } 222 }); 223 }); 224 }