| OLD | NEW | 
|---|
| 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> | 
| OLD | NEW | 
|---|