├── .gitattributes ├── .pr-preview.yml ├── w3c.json ├── LICENSE.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── .github └── workflows │ └── auto-publish.yml ├── security-privacy-questionnaire.md ├── README.md └── index.bs /.gitattributes: -------------------------------------------------------------------------------- 1 | *.bs linguist-language=HTML -------------------------------------------------------------------------------- /.pr-preview.yml: -------------------------------------------------------------------------------- 1 | { 2 | "src_file": "index.bs", 3 | "type": "bikeshed", 4 | "params": { 5 | "force": 1 6 | } 7 | } -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": 115198 3 | , "contacts": ["tidoust", "chrisn", "marcoscaceres"] 4 | , "repo-type": "rec-track" 5 | } 6 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All documents in this Repository are licensed by contributors under the [W3C 2 | Software and Document License](http://www.w3.org/Consortium/Legal/copyright-software). 3 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions to this repository are intended to become part of Recommendation-track documents governed by the 4 | [W3C Patent Policy](https://www.w3.org/policies/patent-policy/) and 5 | [Software and Document License](https://www.w3.org/copyright/software-license/). To make substantive contributions to specifications, you must either participate 6 | in the relevant W3C Working Group or make a non-member patent licensing commitment. 7 | 8 | If you are not the sole contributor to a contribution (pull request), please identify all 9 | contributors in the pull request comment. 10 | 11 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 12 | 13 | ``` 14 | +@github_username 15 | ``` 16 | 17 | If you added a contributor by mistake, you can remove them in a comment with: 18 | 19 | ``` 20 | -@github_username 21 | ``` 22 | 23 | If you are making a pull request on behalf of someone else but you had no part in designing the 24 | feature, you can remove yourself with the above syntax. 25 | -------------------------------------------------------------------------------- /.github/workflows/auto-publish.yml: -------------------------------------------------------------------------------- 1 | # Workflow based on the main w3c/spec-prod action example: 2 | # https://github.com/w3c/spec-prod/#basic-usage 3 | 4 | name: Build, Validate, Deploy and Publish 5 | 6 | on: 7 | # Workflow runs on pull requests where it makes sure that the spec can still 8 | # be generated, that markup is valid and that there are no broken links, as 9 | # well as on pushes to the default branch where it also deploys the generated 10 | # spec to the gh-pages branch and publishes the result to /TR. 11 | # The "workflow_dispatch" hook allows admins to also trigger the workflow 12 | # manually from GitHub's UI. 13 | pull_request: {} 14 | push: 15 | branches: [main] 16 | workflow_dispatch: 17 | 18 | jobs: 19 | main: 20 | runs-on: ubuntu-latest 21 | steps: 22 | # See doc at https://github.com/actions/checkout#checkout-v2 23 | - name: Checkout repository 24 | uses: actions/checkout@v4 25 | 26 | # See doc at https://github.com/w3c/spec-prod/#spec-prod 27 | # The action only deploys the generated spec to the gh-pages branch when 28 | # the workflow was triggered by a push to the default branch. 29 | - name: Build and validate index.html, push to gh-pages branch if needed 30 | uses: w3c/spec-prod@v2 31 | with: 32 | GH_PAGES_BRANCH: gh-pages 33 | W3C_ECHIDNA_TOKEN: ${{ secrets.ECHIDNA_TOKEN }} 34 | W3C_WG_DECISION_URL: https://github.com/w3c/media-wg/issues/27 35 | W3C_BUILD_OVERRIDE: | 36 | status: WD 37 | -------------------------------------------------------------------------------- /security-privacy-questionnaire.md: -------------------------------------------------------------------------------- 1 | # Autoplay Policy Detection - Security and Privacy Questionnaire 2 | 3 | This document answers the [W3C Security and Privacy 4 | Questionnaire](https://w3ctag.github.io/security-questionnaire/) for the 5 | Autoplay Policy Detection specification. 6 | 7 | Last Update: 2022-09-12 8 | 9 | **What information might this feature expose to Web sites or other parties, and 10 | for what purposes is that exposure necessary?** 11 | 12 | This API exposes information to allow websites detect if autoplaying media is 13 | allowed, which help them make actions, such as selecting alternate content or 14 | improving the user experience while media is not allowed to autoplay. 15 | 16 | Example query: 17 | Is this media element allowed to autoplay? 18 | 19 | Example answer: 20 | The queried media element is not allowed to autoplay. 21 | 22 | If the user agent does not allow any autoplay media, then websites could stop 23 | loading media resources and related tasks to save the bandwidth and CPU usage 24 | for users. 25 | 26 | **Do features in your specification expose the minimum amount of information 27 | necessary to enable their intended uses?** 28 | 29 | Yes. The API will return different results, such as `allowed`, `allowed-muted` 30 | and `disallowed`, to answer websites' question. 31 | 32 | **How do the features in your specification deal with personal information, 33 | personally-identifiable information (PII), or information derived from them?** 34 | 35 | This specification does not deal with PII. 36 | 37 | **How do the features in your specification deal with sensitive information?** 38 | 39 | This specification does not deal with sensitive information. 40 | 41 | **Do the features in your specification introduce new state for an origin that 42 | persists across browsing sessions?** 43 | 44 | No. 45 | 46 | **Do the features in your specification expose information about the underlying 47 | platform to origins?** 48 | 49 | No. The information about whether autoplay is not allowed is not platform 50 | specific. The result doesn't describe anything which can be used to deduce the 51 | underlying platform. 52 | 53 | **Do features in this specification allow an origin access to sensors on a 54 | user’s device?** 55 | 56 | No. 57 | 58 | **What data do the features in this specification expose to an origin? Please 59 | also document what data is identical to data exposed by other features, in the 60 | same or different contexts.** 61 | 62 | 3 enums, "allowed", "allowed-muted" and "disallowed", which are used to answer 63 | the question for knowing the status for autoplay. 64 | 65 | There is no other API can directly answer the status of whether autoplay is 66 | allowed. However, for media element, there is a API could answer the question 67 | indirectly. But for the audio context, there is no way to know the status. 68 | 69 | Eg. `HTMLMediaElement.play()`, will return a promise. If autoplay is not 70 | allowed, the play promise will be rejected, and the element will receive an 71 | unsupported error. 72 | 73 | **Do features in this specification enable new script execution/loading 74 | mechanisms?** 75 | 76 | No. 77 | 78 | **Do features in this specification allow an origin to access other devices?** 79 | 80 | No. 81 | 82 | **Do features in this specification allow an origin some measure of control over 83 | a user agent’s native UI?** 84 | 85 | No. 86 | 87 | **What temporary identifiers do the features in this specification create or 88 | expose to the web?** 89 | 90 | No. 91 | 92 | **How does this specification distinguish between behavior in first-party and 93 | third-party contexts?** 94 | 95 | It does not distinguish. 96 | 97 | **How do the features in this specification work in the context of a browser’s 98 | Private Browsing or Incognito mode?** 99 | 100 | This specification does not treat Private Browsing and Incognito mode in a 101 | special way. They should all work the same as normal browsing mode. 102 | 103 | Unless the user agent implements something specially which would return 104 | different answers for the same origin under the same situation. 105 | 106 | **Does this specification have both "Security Considerations" and "Privacy 107 | Considerations" sections?** 108 | 109 | Yes, this specification has a [Security and Privacy Considerations](https://w3c.github.io/autoplay/#security-and-privacy) 110 | section already. 111 | 112 | **Do features in your specification enable downgrading default security 113 | characteristics?** 114 | 115 | No. 116 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Autoplay Policy Detection 2 | 3 | This repository contains the Autoplay Policy Detection specification that is being worked on in the W3C [Media Working Group](https://www.w3.org/media-wg/). 4 | 5 | ## Editor 6 | 7 | - Alastor Wu 8 | 9 | ## Participate 10 | 11 | - https://github.com/w3c/autoplay/issues/ 12 | 13 | ## Introduction 14 | 15 | Most user agents have their own mechanisms to block autoplaying media, and those mechanisms are implementation-specific. Web developers need to have a way to detect if autoplaying media is allowed or not in order to make actions, such as selecting alternate content or improving the user experience while media is not allowed to autoplay. For instance, if a user agent only blocks audible autoplay, then web developers can replace audible media with inaudible media to keep media playing, instead of showing a blocked media which looks like a still image to users. If the user agent does not allow any autoplay media, then web developers could stop loading media resources and related tasks to save the bandwidth and CPU usage for users. 16 | 17 | Currently, this specification only handles HTMLMediaElement (video and audio) and Web Audio API. This specification does not handle Web Speech API and animated image (GIF animation). 18 | 19 | ## Goal 20 | 21 | To allow web developers detect whether they're allowed to play media via HTMLMediaElement API and Web Audio API easily without using any complicated workaround. 22 | 23 | ## API 24 | 25 | Autoplay detection can be performed through the Navigator object. The result can either allow authors to know if media, which have the same type of the given media type and exist in the document contained in the Window object associated with the queried Navigator object, are allowed to autoplay, or to know if a specific element is allowed to autoplay. 26 | 27 | ```js 28 | enum AutoplayPolicy { 29 | "allowed", 30 | "allowed-muted", 31 | "disallowed" 32 | }; 33 | 34 | enum AutoplayPolicyMediaType { "mediaelement", "audiocontext" }; 35 | 36 | [Exposed=Window] 37 | partial interface Navigator { 38 | AutoplayPolicy getAutoplayPolicy(AutoplayPolicyMediaType type); 39 | AutoplayPolicy getAutoplayPolicy(HTMLMediaElement element); 40 | AutoplayPolicy getAutoplayPolicy(AudioContext context); 41 | }; 42 | ``` 43 | 44 | ## Key scenarios 45 | 46 | ### Checking whether authors can autoplay any media element. 47 | 48 | ```js 49 | if (navigator.getAutoplayPolicy("mediaelement") === "allowed") { 50 | // Create and play a new media element. 51 | } else if (navigator.getAutoplayPolicy("mediaelement") === "allowed-muted") { 52 | // Create a new media element, and play it in muted. 53 | } else { 54 | // Autoplay is disallowed, maybe show a poster instead. 55 | } 56 | ``` 57 | 58 | ### Checking whether authors can start any audio context. 59 | 60 | Web Audio uses sticky activation to determine if AudioContext can be allowed to start. 61 | 62 | ```js 63 | if (navigator.getAutoplayPolicy("audiocontext") === "allowed") { 64 | let ac = new AudioContext(); 65 | ac.onstatechange = function () { 66 | if (ac.state === "running") { 67 | // Start running audio app. 68 | } 69 | }; 70 | } else { 71 | // Audio context is not allowed to start. Display a bit of UI to ask 72 | // users to start the audio app. Audio starts via calling ac.resume() 73 | // from a handler, and 'onstatechange' allows knowing when the audio 74 | // stack is ready. 75 | } 76 | ``` 77 | 78 | ### Checking whether authors can autoplay on a specific media element. 79 | 80 | ```js 81 | function handlePlaySucceeded() { 82 | // Update the control UI to playing. 83 | } 84 | function handlePlayFailed() { 85 | // Show a button to allow users to explicitly start the video and 86 | // display an image element as poster to replace the video. 87 | } 88 | 89 | let video = document.getElementById("video"); 90 | switch (navigator.getAutoplayPolicy(video)) { 91 | case "allowed": 92 | video.src = "video.webm"; 93 | video.play().then(handlePlaySucceeded, handlePlayFailed); 94 | break; 95 | case "allowed-muted": 96 | video.src = "video.webm"; 97 | video.muted = true; 98 | video.play().then(handlePlaySucceeded, handlePlayFailed); 99 | break; 100 | default: 101 | // Autoplay is not allowed, no need to download the resource. 102 | handlePlayFailed(); 103 | break; 104 | } 105 | ``` 106 | 107 | ### Checking whether authors can autoplay on a specific audio context. 108 | 109 | Web Audio uses sticky activation to determine if AudioContext can be allowed to start. 110 | 111 | ```js 112 | let ac = new AudioContext(); 113 | if (navigator.getAutoplayPolicy(ac) === "allowed") { 114 | ac.onstatechange = function () { 115 | if (ac.state === "running") { 116 | // Start running audio app. 117 | } 118 | }; 119 | } else { 120 | // Display a bit of UI to ask users to start the audio app. 121 | // Audio starts via calling ac.resume() from a handler, and 122 | // 'onstatechange' allows knowing when the audio stack is ready. 123 | } 124 | ``` 125 | 126 | ## Stakeholder Feedback / Opposition 127 | 128 | - Chrome : Positive 129 | - Edge : No public signal 130 | - Firefox : Shipping on Nightly 131 | - Safari : [Positive](https://github.com/WebKit/standards-positions/issues/113) 132 | 133 | ## References & acknowledgements 134 | 135 | Many thanks for valuable feedback and advice from 136 | 137 | - Alastor Wu 138 | - Becca Hughes 139 | - Christoph Guttandin 140 | - Chris Needham 141 | - Chris Pearce 142 | - Dale Curtis 143 | - Eric Carlson 144 | - François Daoust 145 | - Frank Liberato 146 | - Gary Katsevman 147 | - Jean-Yves Avenard 148 | - Jer Noble 149 | - Mattias Buelens 150 | - Mounir Lamouri 151 | - Paul Adenot 152 | - Tom Jenkinson 153 | -------------------------------------------------------------------------------- /index.bs: -------------------------------------------------------------------------------- 1 |
2 | Title: Autoplay Policy Detection 3 | Shortname: autoplay-detection 4 | Level: None 5 | Status: w3c/ED 6 | Group: mediawg 7 | Repository: https://github.com/w3c/autoplay 8 | URL: https://w3c.github.io/autoplay/ 9 | TR: https://www.w3.org/TR/autoplay-detection/ 10 | Editor: Alastor Wu, Mozilla https://www.mozilla.org, alwu@mozilla.com, w3cid 92198 11 | Abstract: This specification provides web developers the ability to detect if automatically starting the playback of a media file is allowed in different situations. 12 | Markup Shorthands: markdown on 13 |14 | 15 |
16 | spec:html; type:attribute; text:document 17 |18 | 19 | 50 | 51 |
76 | enum AutoplayPolicy {
77 | "allowed",
78 | "allowed-muted",
79 | "disallowed"
80 | };
81 |
82 | | Enum Value | 87 |Description | 88 |
|---|---|
| 93 | "allowed" 94 | | 95 | Media are allowed to autoplay. 96 | |
| 98 | "allowed-muted" 99 | |
100 | Inaudible media are allowed to autoplay.
101 |
102 | Note: Currently, this attribute will only be returned when the
103 | given media type or element is a type of {{HTMLMediaElement}}
104 | or its extensions, such as {{HTMLVideoElement}} or
105 | {{HTMLAudioElement}}.
106 |
107 | An inaudible media element is an {{HTMLMediaElement}}
108 | that has any of the following conditions:
109 |
|
| 116 | "disallowed" 117 | | 118 | No media is allowed to autoplay. 119 | |
140 | enum AutoplayPolicyMediaType { "mediaelement", "audiocontext" };
141 |
142 | [Exposed=Window]
143 | partial interface Navigator {
144 | AutoplayPolicy getAutoplayPolicy(AutoplayPolicyMediaType type);
145 | AutoplayPolicy getAutoplayPolicy(HTMLMediaElement element);
146 | AutoplayPolicy getAutoplayPolicy(AudioContext context);
147 | };
148 |
149 |
150 | | Enum Value | 155 |Description | 156 |
|---|---|
| 161 | mediaelement 162 | | 163 | It's used to query a status for {{HTMLMediaElement}} and its 164 | extensions, such as {{HTMLVideoElement}} and {{HTMLAudioElement}}. 165 | |
| 167 | audiocontext 168 | | 169 | It's used to query a status for {{AudioContext}}. 170 | |
323 |
324 | if (navigator.getAutoplayPolicy("mediaelement") === "allowed") {
325 | // Create and play a new media element.
326 | } else if (navigator.getAutoplayPolicy("mediaelement") === "allowed-muted") {
327 | // Create a new media element, and play it in muted.
328 | } else {
329 | // Autoplay is disallowed, maybe show a poster instead.
330 | }
331 |
332 |
340 | if (navigator.getAutoplayPolicy("audiocontext") === "allowed") {
341 | let ac = new AudioContext();
342 | ac.onstatechange = function() {
343 | if (ac.state === "running") {
344 | // Start running audio app.
345 | }
346 | }
347 | } else {
348 | // Audio context is not allowed to start. Display a bit of UI to ask
349 | // users to start the audio app. Audio starts via calling ac.resume()
350 | // from a handler, and 'onstatechange' allows knowing when the audio
351 | // stack is ready.
352 | }
353 |
354 |
359 | function handlePlaySucceeded() {
360 | // Update the control UI to playing.
361 | }
362 | function handlePlayFailed() {
363 | // Show a button to allow users to explicitly start the video and
364 | // display an image element as poster to replace the video.
365 | }
366 |
367 | let video = document.getElementById("video");
368 | switch (navigator.getAutoplayPolicy(video)) {
369 | case "allowed":
370 | video.src = "video.webm";
371 | video.play().then(handlePlaySucceeded, handlePlayFailed);
372 | break;
373 | case "allowed-muted":
374 | video.src = "video.webm";
375 | video.muted = true;
376 | video.play().then(handlePlaySucceeded, handlePlayFailed);
377 | break;
378 | default:
379 | // Autoplay is not allowed, no need to download the resource.
380 | handlePlayFailed();
381 | break;
382 | }
383 |
384 |
392 | let ac = new AudioContext();
393 | if (navigator.getAutoplayPolicy(ac) === "allowed") {
394 | ac.onstatechange = function() {
395 | if (ac.state === "running") {
396 | // Start running audio app.
397 | }
398 | }
399 | } else {
400 | // Display a bit of UI to ask users to start the audio app.
401 | // Audio starts via calling ac.resume() from a handler, and
402 | // 'onstatechange' allows knowing when the audio stack is ready.
403 | }
404 |
405 |