Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes.html

Issue 1370723002: Include viewport visibility checks for autoplay experiment. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebased. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes-expected.txt » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 <html> 1 <html>
2 <video autoplay controls></video> 2 <video autoplay controls></video>
3 <script src=media-file.js></script> 3 <script src=media-file.js></script>
4 <script src=video-test.js></script> 4 <script src=video-test.js></script>
5 <body> 5 <body>
6 <pre> 6 <pre>
7 Check if the autoplay gesture override experiment works. There are a lot 7 Check if the autoplay gesture override experiment works. There are a lot
8 of config options, so this test just runs all of them. 8 of config options, so this test just runs all of them.
9 9
10 The "results" table contains one row per config tested. 10 The "results" table contains one row per config tested.
11 == Test Inputs == 11 == Test Inputs ==
12 # - config number, in case you'd like to run just one. 12 # - config number, in case you'd like to run just one.
13 Flags - autoplay experiment setting being tested. 13 Flags - autoplay experiment setting being tested.
14 a - "foraudio" 14 a - "foraudio"
15 v - "forvideo" 15 v - "forvideo"
16 V - "ifviewport"
17 P - "ifpagevisible"
16 M - "ifmuted" 18 M - "ifmuted"
17 p - "playmuted" 19 p - "playmuted"
18 m - "ifmobile" 20 m - "ifmobile"
19 For example, EM means "enabled-ifmuted". 21 For example, vM means '-forvideo-ifmuted".
20 Type - audio or video element? 22 Type - audio or video element?
21 audio - <audio> 23 audio - <audio>
22 video - <video> 24 video - <video>
23 Play w/- how is play requested? 25 Play w/- how is play requested?
24 none - play is not requested. 26 none - play is not requested.
25 attr - autoplay attribute is set on the element. 27 attr - autoplay attribute is set on the element.
26 play() - play() called after media is ready to play. 28 play() - play() called after media is ready to play.
27 Mute - how is media muted? 29 Mute - how is media muted?
28 no - media is not muted. 30 no - media is not muted.
29 yes - muted attribute is set on the element. 31 yes - muted attribute is set on the element.
30 Mobile - is page optimized for mobile? 32 Mobile - is page optimized for mobile?
31 no - page is not optimized for mobile. 33 no - page is not optimized for mobile.
32 yes - page is optimized for mobile. 34 yes - page is optimized for mobile.
35 View - is media in viewport?
36 onscreen - element starts out onscreen.
37 scroll - element starts offscreen, scrolled into view once
38 it is ready to play.
39 offscreen - element starts out offscreen and stays offscreen.
40 obscured - onscreen but page is not visible.
33 41
34 == Test Outputs == 42 == Test Outputs ==
43 Early? - did playback start before element was scrolled onscreen? For
44 tests in which View!=scroll, this is reported as "-".
35 Played? - did playback start by the conclusion of the test? 45 Played? - did playback start by the conclusion of the test?
36 Muted? - was the media muted? If the media didn't play, then this is 46 Muted? - was the media muted? If the media didn't play, then this is
37 reported as "-". 47 reported as "-".
38 48
39 </pre> 49 </pre>
40 <table id="results"> 50 <table id="results">
41 <tr> 51 <tr>
42 <td>#</td> 52 <td>#</td>
43 <td>Flags</td> 53 <td>Flags</td>
44 <td>Type</td> 54 <td>Type</td>
45 <td>Play w/</td> 55 <td>Play w/</td>
46 <td>Mute</td> 56 <td>Mute</td>
47 <td>Mobile</td> 57 <td>Mobile</td>
58 <td>View</td>
59 <td>Early?</td>
48 <td>Played?</td> 60 <td>Played?</td>
49 <td>Muted?</td> 61 <td>Muted?</td>
50 </tr> 62 </tr>
51 </table> 63 </table>
52 </body> 64 </body>
53 65
54 <script> 66 <script>
55 67
56 // Starting configuration number. This should be zero normally. 68 // Starting configuration number. This should be zero normally.
57 var configNumber = 0; 69 var configNumber = 0;
58 70
59 var mediaFile = findMediaFile("video", "content/test"); 71 var mediaFile = findMediaFile("video", "content/test");
60 var onscreenParent = document.createElement("div"); 72 var onscreenParent = document.createElement("div");
73 // The onscreen parent's height is also used to make sure that the off-screen
74 // parent is, in fact, off-screen.
75 onscreenParent.style.height = "1000px";
61 document.body.insertBefore(onscreenParent, document.body.firstChild); 76 document.body.insertBefore(onscreenParent, document.body.firstChild);
62 // When we remove the meta tag from the document, we put it here. 77 // Is the page optimized for mobile? We can't un-optimize it.
63 var isOptimizedForMobile = false; 78 var isOptimizedForMobile = false;
79 // Also create another root that's off the bottom of the window.
80 var offscreenParent = document.createElement("div");
81 document.body.appendChild(offscreenParent);
64 82
65 function didPlaybackStart(video) 83 function didPlaybackStart(element)
66 { 84 {
67 // We say that the video started if it's not paused or if it played and 85 return !element.paused || element.ended;
68 // already ended.
69 return !video.paused || video.ended;
70 } 86 }
71 87
72 function becomeOptimizedForMobile(enable) 88 function becomeOptimizedForMobile(enable)
73 { 89 {
74 // If we're in the right state already, then return; 90 // If we're in the right state already, then return;
75 if (enable == isOptimizedForMobile) 91 if (enable == isOptimizedForMobile)
76 return; 92 return;
77 93
78 if (!enable) { 94 if (!enable) {
79 // We can't transition out of optimized for mobile. 95 // We can't transition out of optimized for mobile.
(...skipping 14 matching lines...) Expand all
94 // Add a row to the results table. 110 // Add a row to the results table.
95 var row = document.getElementById("results").insertRow(); 111 var row = document.getElementById("results").insertRow();
96 var td = row.insertCell(); 112 var td = row.insertCell();
97 113
98 // Add experiment number 114 // Add experiment number
99 row.insertCell().innerText = (""+spec.experimentNumber); 115 row.insertCell().innerText = (""+spec.experimentNumber);
100 116
101 // Process experiment type specially. 117 // Process experiment type specially.
102 var type = spec.experimentType; 118 var type = spec.experimentType;
103 var smallType = ""; 119 var smallType = "";
104 smallType += (type.indexOf("-forvideo")>-1)?"v":""; 120 smallType += type.includes("-forvideo")?"v":"";
105 smallType += (type.indexOf("-foraudio")>-1)?"a":""; 121 smallType += type.includes("-foraudio")?"a":"";
106 smallType += (type.indexOf("-ifmuted")>-1)?"M":""; 122 smallType += type.includes("-ifviewport")?"V":"";
107 smallType += (type.indexOf("-playmuted")>-1)?"p":""; 123 smallType += type.includes("-ifpagevisible")?"P":"";
108 smallType += (type.indexOf("-ifmobile")>-1)?"m":""; 124 smallType += type.includes("-ifmuted")?"M":"";
125 smallType += type.includes("-playmuted")?"p":"";
126 smallType += type.includes("-ifmobile")?"m":"";
109 row.insertCell().innerText = smallType; 127 row.insertCell().innerText = smallType;
110 128
111 // Add remaining fields. 129 // Add remaining fields.
112 var fields = [ "elementType", "autoplayType", "mutedType", "mobileType", 130 var fields = [ "elementType", "autoplayType", "mutedType", "mobileType",
113 "played", "muted"]; 131 "visType", "playedEarly", "played", "muted"];
114 for(idx in fields) 132 for(idx in fields)
115 row.insertCell().innerText = spec[fields[idx]].substring(0,7); 133 row.insertCell().innerText = spec[fields[idx]].substring(0,7);
116 } 134 }
117 135
118 function configureElementViaScript(element, spec) 136 function configureElementViaScript(element, spec)
119 { 137 {
120 if(spec.autoplayType == "play()") 138 if(spec.autoplayType == "play()")
121 element.play(); 139 element.play();
122 } 140 }
123 141
124 function queueNextExperiment() 142 function queueNextExperiment()
125 { 143 {
126 // Start the next config, but let the event queue drain. 144 // Start the next config, but let the event queue drain.
127 setTimeout(runNextConfig, 0); 145 setTimeout(runNextConfig, 0);
128 } 146 }
129 147
130 function checkElementStatus(element) 148 function checkElementStatus(element)
131 { 149 {
132 // Update the spec with the results. 150 // Update the spec with the results.
133 var didStart = didPlaybackStart(element); 151 var didStart = didPlaybackStart(element);
134 element.spec.played = didStart ? "played" : "no"; 152 element.spec.played = didStart ? "played" : "no";
135 element.spec.muted = didStart ? (element.muted ? "muted" : "unmuted") : "-"; 153 element.spec.muted = didStart ? (element.muted ? "muted" : "unmuted") : "-";
136 154
137 addResultsRow(element.spec); 155 addResultsRow(element.spec);
138 element.remove(); 156 element.remove();
139 157
158 // Scroll back to the top, in case this was a scrolling test.
159 onscreenParent.scrollIntoView();
160
161 // Also make sure that the page is visible again. Hidden pages cause the
162 // test to proceed very slowly.
163 testRunner.setPageVisibility("visible");
164
140 queueNextExperiment(); 165 queueNextExperiment();
141 } 166 }
142 167
143 function runOneConfig(spec) 168 function runOneConfig(spec)
144 { 169 {
145 internals.settings.setAutoplayExperimentMode(spec.experimentType); 170 internals.settings.setAutoplayExperimentMode(spec.experimentType);
146 171
147 // Create, configure, and attach a media element. 172 // Create, configure, and attach a media element.
148 var element = document.createElement(spec.elementType); 173 var element = document.createElement(spec.elementType);
149 element.controls = true; 174 element.controls = true;
150 175
151 onscreenParent.appendChild(element); 176 // Hide or show the page.
177 if (spec.visType == "obscured")
178 testRunner.setPageVisibility("hidden");
179
180 // Pick whether the element will be visible when canPlayThrough.
181 if (spec.visType == "offscreen" || spec.visType == "scroll")
182 offscreenParent.appendChild(element);
183 else
184 onscreenParent.appendChild(element);
152 185
153 // Set any attributes before canPlayThrough. 186 // Set any attributes before canPlayThrough.
154 if (spec.mutedType == "yes") 187 if (spec.mutedType == "yes")
155 element.muted = true; 188 element.muted = true;
156 if (spec.autoplayType == "attr") 189 if (spec.autoplayType == "attr")
157 element.autoplay = true; 190 element.autoplay = true;
191
158 becomeOptimizedForMobile(spec.mobileType == "yes"); 192 becomeOptimizedForMobile(spec.mobileType == "yes");
159 193
194 spec.playedEarly = "-";
195
160 // Record the spec in the element, so that we can display the 196 // Record the spec in the element, so that we can display the
161 // results later. 197 // results later.
162 element.spec = spec; 198 element.spec = spec;
199 window.internals.triggerAutoplayViewportCheck(element);
163 200
164 // Wait for canplaythrough before continuing, so that the media 201 // Wait for canplaythrough before continuing, so that the media
165 // might actually be playing. 202 // might actually be playing.
166 element.addEventListener("canplaythrough", function() 203 element.addEventListener("canplaythrough", function()
167 { 204 {
168 // Now that we can play, if we're supposed to play / mute via js do so. 205 // Now that we can play, if we're supposed to play / mute via js do so.
169 configureElementViaScript(element, spec); 206 configureElementViaScript(element, spec);
170 207
171 // Record the results. 208 // If we're supposed to scroll the item onscreen after it is ready to
172 checkElementStatus(element); 209 // play, then do so now.
210 if(spec.visType == "scroll") {
211 // Record the play state here, too, before we scroll.
212 spec.playedEarly = didPlaybackStart(element) ? "yes" : "no";
213
214 // We are supposed to scroll the player into view.
215 element.scrollIntoView(true);
216 // TODO(liberato): remove once autoplay gesture override experiment concludes.
217 window.internals.triggerAutoplayViewportCheck(element);
218 // Once these two methods return, changes to the element state due
219 // to the autoplay experiment should be observable synchronously.
220 checkElementStatus(element, spec);
221 } else {
222 // Record the results immediately.
223 checkElementStatus(element, spec);
224 }
173 }); 225 });
174 226
175 // Set the source, which will eventually lead to canPlayThrough. 227 // Set the source, which will eventually lead to canPlayThrough.
176 element.src = mediaFile; 228 element.src = mediaFile;
177 } 229 }
178 230
179 var experimentTypes = [ 231 var experimentTypes = [
180 "none", 232 "none",
181 "enabled-forvideo", 233 "enabled-forvideo",
182 "enabled-forvideo-ifmuted", 234 "enabled-forvideo-ifpagevisible",
183 "enabled-forvideo-playmuted", 235 "enabled-forvideo-ifviewport",
236 "enabled-forvideo-ifviewport-ifmuted",
237 "enabled-forvideo-ifviewport-playmuted",
184 "enabled-foraudio", 238 "enabled-foraudio",
185 "enabled-forvideo-ifmobile", 239 "enabled-forvideo-ifmobile",
240 "enabled-foraudio-ifviewport",
186 ]; 241 ];
187 var elementTypes = ["video", "audio"]; 242 var elementTypes = ["video", "audio"];
188 var autoplayTypes = ["none", "attr", "play()"]; 243 var autoplayTypes = ["none", "attr", "play()"];
189 var mutedTypes = ["no", "yes"]; 244 var mutedTypes = ["no", "yes"];
245 var visTypes = ["onscreen", "scroll", "offscreen", "obscured"];
190 // mobileTypes must always start with no, since we cannot un-optimize the page. 246 // mobileTypes must always start with no, since we cannot un-optimize the page.
191 var mobileTypes = ["no", "yes"]; 247 var mobileTypes = ["no", "yes"];
192 248
193 function runNextConfig() 249 function runNextConfig()
194 { 250 {
195 // Convert configNumber into a spec, and run it. 251 // Convert configNumber into a spec, and run it.
196 var exp = configNumber; 252 var exp = configNumber;
197 253
198 // Convert this experiment number into settings. 254 // Convert this experiment number into settings.
199 var spec = {}; 255 var spec = {};
200 spec.elementType = elementTypes[exp % elementTypes.length]; 256 spec.elementType = elementTypes[exp % elementTypes.length];
201 exp = Math.floor(exp / elementTypes.length); 257 exp = Math.floor(exp / elementTypes.length);
202 spec.experimentType = experimentTypes[exp % experimentTypes.length]; 258 spec.experimentType = experimentTypes[exp % experimentTypes.length];
203 exp = Math.floor(exp / experimentTypes.length); 259 exp = Math.floor(exp / experimentTypes.length);
204 spec.autoplayType = autoplayTypes[exp % autoplayTypes.length]; 260 spec.autoplayType = autoplayTypes[exp % autoplayTypes.length];
205 exp = Math.floor(exp / autoplayTypes.length); 261 exp = Math.floor(exp / autoplayTypes.length);
206 spec.mutedType = mutedTypes[exp % mutedTypes.length]; 262 spec.mutedType = mutedTypes[exp % mutedTypes.length];
207 exp = Math.floor(exp / mutedTypes.length); 263 exp = Math.floor(exp / mutedTypes.length);
264 spec.visType = visTypes[exp % visTypes.length];
265 exp = Math.floor(exp / visTypes.length);
208 // Mobile must always change last, so that all the "no" cases precede 266 // Mobile must always change last, so that all the "no" cases precede
209 // all the "yes" cases, since we can't switch the doc back to "not 267 // all the "yes" cases, since we can't switch the doc back to "not
210 // optimized for mobile". 268 // optimized for mobile".
211 spec.mobileType = mobileTypes[exp % mobileTypes.length]; 269 spec.mobileType = mobileTypes[exp % mobileTypes.length];
212 exp = Math.floor(exp / mobileTypes.length); 270 exp = Math.floor(exp / mobileTypes.length);
213 spec.experimentNumber = configNumber; 271 spec.experimentNumber = configNumber;
214 272
215 // Return null if configNumber was larger than the highest experiment. 273 // Return null if configNumber was larger than the highest experiment.
216 if (exp > 0) 274 if (exp > 0)
217 endTest(); 275 endTest();
218 276
219 configNumber++; 277 configNumber++;
220 278
221 // To keep the test fast, skip a few combinations. 279 // To keep the test fast, skip a few combinations.
222 var skip = false; 280 var skip = false;
223 if (spec.experimentType.indexOf("-ifmuted") == -1 && spec.mutedType != "no") 281 if (!spec.experimentType.includes("-ifmuted") && spec.mutedType != "no")
224 skip = true; 282 skip = true;
225 283
226 // Only allow basic combinations for the mobile case. We just want to 284 // Only allow basic combinations for the mobile case. We just want to
227 // test video with autoplay, no mute options when testing -ifmobile. 285 // test video with autoplay, no mute options when testing -ifmobile.
228 // Similarly, if we're setting the page to be optimied for mobile, then 286 // Similarly, if we're setting the page to be optimied for mobile, then
229 // require that we're one of those tests. 287 // require that we're one of those tests.
230 if ((spec.mobileType == "yes" || spec.experimentType.indexOf("-ifmobile")>0) 288 if ((spec.mobileType == "yes" || spec.experimentType.includes("-ifmobile"))
231 && (spec.elementType != "video" || spec.autoplayType != "attr" 289 && (spec.elementType != "video" || spec.autoplayType != "attr"
232 || spec.mutedType != "no" 290 || spec.mutedType != "no"
291 || spec.visType != "onscreen"
233 || (spec.experimentType != "enabled-forvideo" 292 || (spec.experimentType != "enabled-forvideo"
234 && spec.experimentType != "enabled-forvideo-ifmobile"))) 293 && spec.experimentType != "enabled-forvideo-ifmobile")))
235 skip = true; 294 skip = true;
236 295
296 var mismatched =(spec.elementType == "video"
297 && spec.experimentType.includes("-foraudio"))
298 || (spec.elementType == "audio"
299 && spec.experimentType.includes("-forvideo"));
300
301 if (spec.autoplayType == "none" && spec.visType != 'onscreen')
302 skip = true;
303 else if (spec.experimentType.includes("-ifmuted")
304 && spec.visType != "onscreen")
305 skip = true;
306 else if (spec.visType == "offscreen"
307 && spec.autoplayType != "attr")
308 skip = true;
309 else if (!spec.experimentType.includes("-ifmuted")
310 && spec.mutedType == "yes")
311 skip = true;
312 else if (spec.elementType == "audio" && spec.mutedType == "yes")
313 skip = true;
314 else if (spec.elementType == "audio" && spec.visType != "scroll")
315 skip = true;
316 else if (mismatched && spec.visType !="onscreen")
317 skip = true;
318 else if (mismatched && spec.autoplayType != "attr")
319 skip = true;
320 else if (spec.visType == "obscured"
321 && !spec.experimentType.includes("-ifpagevisible"))
322 skip = true;
323 else if ((spec.visType == "offscreen" || spec.visType == "scroll"
324 || spec.autoplayType != "attr" || spec.elementType != "video")
325 && spec.experimentType.includes("-ifpagevisible"))
326 skip = true;
327
237 if (skip) 328 if (skip)
238 queueNextExperiment(); 329 queueNextExperiment();
239 else 330 else
240 runOneConfig(spec); 331 runOneConfig(spec);
241 } 332 }
242 333
243 window.internals.settings.setMediaPlaybackRequiresUserGesture(true); 334 window.internals.settings.setMediaPlaybackRequiresUserGesture(true);
244 runNextConfig(); 335 runNextConfig();
245 336
246 </script> 337 </script>
247 </html> 338 </html>
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes-expected.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698