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

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

Issue 1329853004: Include viewport visibility checks for autoplay experiment. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@autoplay_step1
Patch Set: Created 5 years, 3 months 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
OLDNEW
1 <video autoplay controls></video> 1 <video autoplay controls></video>
2 <script src=media-file.js></script> 2 <script src=media-file.js></script>
3 <script src=video-test.js></script> 3 <script src=video-test.js></script>
4 <body> 4 <body>
5 <pre> 5 <pre>
6 Check if the autoplay gesture override experiment works. There are a lot 6 Check if the autoplay gesture override experiment works. There are a lot
7 of config options, so this test just runs all of them. 7 of config options, so this test just runs all of them.
8 8
9 The "results" table contains one row per config tested. 9 The "results" table contains one row per config tested.
10 == Test Inputs == 10 == Test Inputs ==
11 # - config number, in case you'd like to run just one. 11 # - config number, in case you'd like to run just one.
12 Flags - autoplay experiment setting being tested. 12 Flags - autoplay experiment setting being tested.
13 a - "foraudio" 13 a - "foraudio"
14 v - "forvideo" 14 v - "forvideo"
15 V - "ifviewport"
15 M - "ifmuted" 16 M - "ifmuted"
16 p - "playmuted" 17 p - "playmuted"
17 For example, EM means "enabled-ifmuted". 18 For example, vM means '-forvideo-ifmuted".
18 This test does not check -ifmobile since that check always 19 This test does not check -ifmobile since that check always
19 fails outside of android. 20 fails outside of android.
20 Type - audio or video element? 21 Type - audio or video element?
21 audio - <audio> 22 audio - <audio>
22 video - <video> 23 video - <video>
23 Play w/- how is play requested? 24 Play w/- how is play requested?
24 none - play is not requested. 25 none - play is not requested.
25 attr - autoplay attribute is set on the element. 26 attr - autoplay attribute is set on the element.
26 play() - play() called after media is ready to play. 27 play() - play() called after media is ready to play.
27 Mute - how is media muted? 28 Mute - how is media muted?
28 none - media is not muted. 29 none - media is not muted.
29 attr - muted attribute is set on the element. 30 attr - muted attribute is set on the element.
30 js - muted property is set after media is ready to play. 31 js - muted property is set after media is ready to play.
32 View - is media in viewport?
33 onscreen - element starts out onscreen.
34 scroll - element starts offscreen, scrolled into view once
35 it is ready to play.
36 offscreen - element starts out offscreen and stays offscreen.
31 37
32 == Test Outputs == 38 == Test Outputs ==
39 Early? - did playback start before element was scrolled onscreen? For
40 tests in which View!=scroll, this is reported as "-".
33 Played? - did playback start by the conclusion of the test? 41 Played? - did playback start by the conclusion of the test?
34 Muted? - was the media muted? If the media didn't play, then this is 42 Muted? - was the media muted? If the media didn't play, then this is
35 reported as "-". 43 reported as "-".
36 44
37 </pre> 45 </pre>
38 <table id="results"> 46 <table id="results">
39 <tr> 47 <tr>
40 <td>#</td> 48 <td>#</td>
41 <td>Flags</td> 49 <td>Flags</td>
42 <td>Type</td> 50 <td>Type</td>
43 <td>Play w/</td> 51 <td>Play w/</td>
44 <td>Mute</td> 52 <td>Mute</td>
53 <td>View</td>
54 <td>Early?</td>
45 <td>Played?</td> 55 <td>Played?</td>
46 <td>Muted?</td> 56 <td>Muted?</td>
47 </tr> 57 </tr>
48 </table> 58 </table>
49 </body> 59 </body>
50 60
51 <script> 61 <script>
52 62
53 // Starting configuration number. This should be zero normally. 63 // Starting configuration number. This should be zero normally.
54 var configNumber = 0; 64 var configNumber = 0;
55 65
56 var mediaFile = findMediaFile("video", "content/test"); 66 var mediaFile = findMediaFile("video", "content/test");
57 var onscreenParent = document.createElement("div"); 67 var onscreenParent = document.createElement("div");
68 // The onscreen parent's height is also used to make sure that the off-screen
69 // parent is, in fact, off-screen.
70 onscreenParent.style.height="1000px";
58 document.body.insertBefore(onscreenParent, document.body.firstChild); 71 document.body.insertBefore(onscreenParent, document.body.firstChild);
72 // Also create another root that's off the bottom of the window.
73 var offscreenParent = document.createElement("div");
74 document.body.appendChild(offscreenParent);
59 75
60 function didPlaybackStart(video) 76 function didPlaybackStart(element)
61 { 77 {
62 // We say that the video started if it's not paused or if it played and 78 // We say that the element started if it's not paused or if it played and
63 // already ended. 79 // already ended.
64 return !video.paused || video.ended; 80 return !element.paused || element.ended;
65 } 81 }
66 82
67 function addResultsRow(spec) 83 function addResultsRow(spec)
68 { 84 {
69 // Add a row to the results table. 85 // Add a row to the results table.
70 var row = document.getElementById("results").insertRow(-1); 86 var row = document.getElementById("results").insertRow(-1);
71 var td = row.insertCell(0); 87 var td = row.insertCell(0);
72 88
73 // Add experiment number 89 // Add experiment number
74 row.insertCell(-1).innerText = (""+spec["experimentNumber"]); 90 row.insertCell(-1).innerText = (""+spec["experimentNumber"]);
75 91
76 // Process experiment type specially. 92 // Process experiment type specially.
77 var type = spec["experimentType"]; 93 var type = spec["experimentType"];
78 var smallType = ""; 94 var smallType = "";
79 smallType += (type.indexOf("-forvideo")>-1)?"v":""; 95 smallType += (type.indexOf("-forvideo")>-1)?"v":"";
80 smallType += (type.indexOf("-foraudio")>-1)?"a":""; 96 smallType += (type.indexOf("-foraudio")>-1)?"a":"";
97 smallType += (type.indexOf("-ifviewport")>-1)?"V":"";
81 smallType += (type.indexOf("-ifmuted")>-1)?"M":""; 98 smallType += (type.indexOf("-ifmuted")>-1)?"M":"";
82 smallType += (type.indexOf("-playmuted")>-1)?"p":""; 99 smallType += (type.indexOf("-playmuted")>-1)?"p":"";
83 row.insertCell(-1).innerText = smallType; 100 row.insertCell(-1).innerText = smallType;
84 101
85 // Add remaining fields. 102 // Add remaining fields.
86 var fields = [ "elementType", "autoplayType", "mutedType", "played", 103 var fields = [ "elementType", "autoplayType", "mutedType", "visType",
87 "muted"]; 104 "playedEarly", "played", "muted"];
88 for(idx in fields) 105 for(idx in fields)
89 row.insertCell(-1).innerText = spec[fields[idx]].substring(0,7); 106 row.insertCell(-1).innerText = spec[fields[idx]].substring(0,7);
90 } 107 }
91 108
92 function configureVideoViaScript(element, spec) 109 function configureElementViaScript(element, spec)
93 { 110 {
94 if (spec.mutedType == "js") 111 if (spec.mutedType == "js")
95 element.muted = true; 112 element.muted = true;
96 if(spec.autoplayType == "play()") 113 if(spec.autoplayType == "play()")
97 element.play(); 114 element.play();
98 } 115 }
99 116
100 function queueNextExperiment() 117 function queueNextExperiment()
101 { 118 {
102 // Start the next config, but let the event queue drain. 119 // Start the next config, but let the event queue drain.
103 setTimeout(runNextConfig, 0); 120 setTimeout(runNextConfig, 0);
104 } 121 }
105 122
106 function checkElementStatus(element) 123 function checkElementStatus(element)
107 { 124 {
108 // Update the spec with the results. 125 // Update the spec with the results.
109 var didStart = didPlaybackStart(element); 126 var didStart = didPlaybackStart(element);
110 element.spec.played = didStart ? "played" : "no"; 127 element.spec.played = didStart ? "played" : "no";
111 element.spec.muted = didStart ? (element.muted ? "muted" : "unmuted") : "-"; 128 element.spec.muted = didStart ? (element.muted ? "muted" : "unmuted") : "-";
112 129
113 addResultsRow(element.spec); 130 addResultsRow(element.spec);
114 element.parentElement.removeChild(element); 131 element.parentElement.removeChild(element);
115 132
133 // Scroll back to the top, in case this was a scrolling test.
134 onscreenParent.scrollIntoView();
135
116 queueNextExperiment(); 136 queueNextExperiment();
117 } 137 }
118 138
119 function runOneConfig(spec) 139 function runOneConfig(spec)
120 { 140 {
121 internals.settings.setAutoplayExperimentMode(spec.experimentType); 141 internals.settings.setAutoplayExperimentMode(spec.experimentType);
122 142
123 // Create, configure, and attach a media element. 143 // Create, configure, and attach a media element.
124 var element = document.createElement(spec.elementType); 144 var element = document.createElement(spec.elementType);
145 element.setAttribute("controls", "true");
125 146
126 onscreenParent.appendChild(element); 147 // Pick whether the element will be visible when canPlayThrough.
148 if (spec.visType == "onscreen")
149 onscreenParent.appendChild(element);
150 else
151 offscreenParent.appendChild(element);
127 152
128 // Set any attributes before canPlayThrough. 153 // Set any attributes before canPlayThrough.
129 if (spec.mutedType == "attr") 154 if (spec.mutedType == "attr")
130 element.setAttribute("muted", "true"); 155 element.setAttribute("muted", "true");
131 if (spec.autoplayType == "attr") 156 if (spec.autoplayType == "attr")
132 element.setAttribute("autoplay", "true"); 157 element.setAttribute("autoplay", "true");
133 158
159 spec.playedEarly = "-";
160
134 // Record the spec in the element, so that we can display the 161 // Record the spec in the element, so that we can display the
135 // results later. 162 // results later.
136 element.spec = spec; 163 element.spec = spec;
137 164
138 // Wait for canplaythrough before continuing, so that the media 165 // Wait for canplaythrough before continuing, so that the media
139 // might actually be playing. 166 // might actually be playing.
140 element.addEventListener("canplaythrough", function() 167 element.addEventListener("canplaythrough", function()
141 { 168 {
142 // Now that we can play, if we're supposed to play / mute via js do so. 169 // Now that we can play, if we're supposed to play / mute via js do so.
143 configureVideoViaScript(element, spec); 170 configureElementViaScript(element, spec);
144 171
145 // Record the results. 172 // If we're supposed to scroll the item onscreen after it is ready to
146 checkElementStatus(element); 173 // play, then do so now.
174 if(spec.visType == "scroll") {
175 // Record the play state here, too, before we scroll.
176 spec.playedEarly = didPlaybackStart(element) ? "yes" : "no";
177
178 // We are supposed to scroll the player into view.
179 element.scrollIntoView(true);
180 // We cause two visibility checks. The first notices the scroll,
181 // while the second notices that scrolling has stopped.
182 // It would be nicer to trigger location polling here, but that
183 // can take ~second to notice that scrolling is stopped.
184 window.internals.triggerAutoplayViewportCheck(element);
185 window.internals.triggerAutoplayViewportCheck(element);
186 // Once those are return, the state should be correct.
187 checkElementStatus(element, spec);
188 } else {
189 // Record the results immediately.
190 checkElementStatus(element, spec);
191 }
147 }); 192 });
148 193
149 // Set the source, which will eventually lead to canPlayThrough. 194 // Set the source, which will eventually lead to canPlayThrough.
150 element.src=mediaFile; 195 element.src=mediaFile;
151 } 196 }
152 197
153 var experimentTypes = [ 198 var experimentTypes = [
154 "none", 199 "none",
155 "enabled-forvideo", 200 "enabled-forvideo",
156 "enabled-forvideo-ifmuted", 201 "enabled-forvideo-ifviewport",
157 "enabled-forvideo-playmuted", 202 "enabled-forvideo-ifviewport-ifmuted",
203 "enabled-forvideo-ifviewport-playmuted",
158 "enabled-foraudio", 204 "enabled-foraudio",
205 "enabled-foraudio-ifviewport",
159 ]; 206 ];
160 var elementTypes = ["video", "audio"]; 207 var elementTypes = ["video", "audio"];
161 var autoplayTypes = ["none", "attr", "play()"]; 208 var autoplayTypes = ["none", "attr", "play()"];
162 var mutedTypes = ["none", "attr", "js"]; 209 var mutedTypes = ["none", "attr", "js"];
210 var visTypes = ["onscreen", "scroll", "offscreen"];
163 211
164 function runNextConfig() 212 function runNextConfig()
165 { 213 {
166 // Convert configNumber into a spec, and run it. 214 // Convert configNumber into a spec, and run it.
167 var exp = configNumber; 215 var exp = configNumber;
168 216
169 // Convert this experiment number into settings. 217 // Convert this experiment number into settings.
170 var spec = {}; 218 var spec = {};
171 spec.elementType = elementTypes[exp % elementTypes.length]; 219 spec.elementType = elementTypes[exp % elementTypes.length];
172 exp = Math.floor(exp / elementTypes.length); 220 exp = Math.floor(exp / elementTypes.length);
173 spec.experimentType = experimentTypes[exp % experimentTypes.length]; 221 spec.experimentType = experimentTypes[exp % experimentTypes.length];
174 exp = Math.floor(exp / experimentTypes.length); 222 exp = Math.floor(exp / experimentTypes.length);
175 spec.autoplayType = autoplayTypes[exp % autoplayTypes.length]; 223 spec.autoplayType = autoplayTypes[exp % autoplayTypes.length];
176 exp = Math.floor(exp / autoplayTypes.length); 224 exp = Math.floor(exp / autoplayTypes.length);
177 spec.mutedType = mutedTypes[exp % mutedTypes.length]; 225 spec.mutedType = mutedTypes[exp % mutedTypes.length];
178 exp = Math.floor(exp / mutedTypes.length); 226 exp = Math.floor(exp / mutedTypes.length);
227 spec.visType = visTypes[exp % visTypes.length];
228 exp = Math.floor(exp / visTypes.length);
179 spec.experimentNumber = configNumber; 229 spec.experimentNumber = configNumber;
180 230
181 // exp>0 here indicates that we've wrapped around. 231 // exp>0 here indicates that we've wrapped around.
182 if (exp > 0) { 232 if (exp > 0) {
183 endTest(); 233 endTest();
184 } 234 }
185 235
186 configNumber++; 236 configNumber++;
187 237
188 // To keep the test fast, skip a few combinations. 238 // To keep the test fast, skip a few combinations.
189 var skip = false; 239 var skip = false;
190 if (spec.experimentType.indexOf("-ifmuted") == -1 && spec.mutedType != "none ") 240 var mismatched =(spec.elementType == "video"
241 && spec.experimentType.indexOf("-foraudio") > -1)
242 || (spec.elementType == "audio"
243 && spec.experimentType.indexOf("-forvideo") > -1);
244
245 if (spec.autoplayType == "none" && spec.visType != 'onscreen')
246 skip = true;
247 else if (spec.experimentType.indexOf("-ifmuted") > -1 && spec.visType != "on screen")
248 skip = true;
249 else if (spec.visType == "offscreen" && spec.autoplayType != "attr")
250 skip = true;
251 else if (spec.experimentType.indexOf("-ifmuted") == -1 && spec.mutedType != "none")
252 skip = true;
253 else if (spec.elementType == "audio" && spec.mutedType != "none")
254 skip = true;
255 else if (spec.elementType == "audio" && spec.visType != "scroll")
256 skip = true;
257 else if (mismatched && spec.visType !="onscreen")
258 skip = true;
259 else if (mismatched && spec.autoplayType != "attr")
191 skip = true; 260 skip = true;
192 261
193 if (skip) 262 if (skip)
194 queueNextExperiment(); 263 queueNextExperiment();
195 else 264 else
196 runOneConfig(spec); 265 runOneConfig(spec);
197 } 266 }
198 267
199 window.internals.settings.setMediaPlaybackRequiresUserGesture(true); 268 window.internals.settings.setMediaPlaybackRequiresUserGesture(true);
200 runNextConfig(); 269 runNextConfig();
201 270
202 </script> 271 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698