You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We propose creating a new "media-playback-while-not-visible" [Permission Policy](https://www.w3.org/TR/permissions-policy/) that would pause any media being played by iframes which are not currently rendered. For example, this would apply whenever the iframe’s `"display"` CSS property is set to `"none"` or when the the `"visibility"` property is set to `"hidden"` or `"collapse"`.
30
+
We propose creating a new "media-playback-while-not-visible" [permission policy] that would pause any media being played by iframes which are not currently rendered. For example, this would apply whenever the iframe’s `"display"` CSS property is set to `"none"` or when the the `"visibility"` property is set to `"hidden"` or `"collapse"`.
31
31
32
32
This policy will have a default value of '*', meaning that all of the nested iframes are allowed to play media when not rendered. The example below show how this permission policy could be used to prevent all the nested iframes from playing media. By doing it this way, even other iframes embedded by "foo.media.com" shouldn’t be allowed to play media if not rendered.
In this case, `example.com` serves a document that embeds an iframe with a document from `https://foo.media.com`. Since the HTTP header only allows documents from `https://example.com` to inherit `media-playback-while-not-visible`, the iframe will not be able to use the feature.
60
60
61
-
In the past, the ["execution-while-not-rendered" and "execution-while-out-of-viewport"](https://wicg.github.io/page-lifecycle/#feature-policies) permission policies have been proposed as additions to the Page Lifecycle draft specification. However, these policies freeze all iframe JavaScript execution when not rendered, which is not desirable for the featured use case. Moreover, this proposal has not been adopted or standardized.
61
+
In the past, the `"execution-while-not-rendered"` and `"execution-while-out-of-viewport"` permission policies have been proposed as additions to the [Page Lifecycle API] draft specification. However, these policies freeze all iframe JavaScript execution when not rendered, which is not desirable for the featured use case. Moreover, this proposal has not been adopted or standardized.
62
62
63
63
## Interoperability with other Web API's
64
64
65
65
Given that there exists many ways for a website to render audio in the broader web platform, this proposal has points of contact with many API's. To be more specific, there are two scenarios where this interaction might happen. Let's consider an iframe, which is not allowed to play `media-playback-while-not-visible`:
66
66
- Scenario 1: When the iframe is not rendered and it attempts to play audio; and
67
-
- Callers should treat this scenario as if they weren't allowed to start media playback. Like when the [`autoplay` permission policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy/autoplay) is set to `'none'` for an iframe.
67
+
- Callers should treat this scenario as if they weren't allowed to start media playback. Like when the [`autoplay` permission policy] is set to `'none'` for an iframe.
68
68
- Scenario 2: When the iframe is already playing audio and stops being rendered during media playback.
69
69
- Callers should treat this scenario as if the user had paused media playback.
70
70
71
71
The following subsections covers how this proposal could interact with Web APIs that render audio.
72
72
73
73
### HTMLMediaElements
74
74
75
-
HTMLMediaElement media playback is started and paused, respectively, with the [`play`](https://html.spec.whatwg.org/multipage/media.html#dom-media-play) and [`pause`](https://html.spec.whatwg.org/multipage/media.html#dom-media-pause) methods. For scenario 1, the media element shouldn't be [allowed to play](https://html.spec.whatwg.org/multipage/media.html#allowed-to-play) and `play` should return a promise rejected with `"NotAllowedError"`. In this case, the website could easily handle this like shown below.
75
+
HTMLMediaElement media playback is started and paused, respectively, with the [`play()`] and [`pause()`] methods. For scenario 1, the media element shouldn't be [allowed to play] and `play()` should return a promise rejected with `"NotAllowedError"`. In this case, the website could easily handle this like shown below.
_This Web Audio API integration is dependent on the successful specification and implementation of the new AudioContextState `"interrupted"` proposed in this [explainer][`"interrupted"`]._
113
+
112
114
The Web Audio API renders audio through an [AudioContext](https://webaudio.github.io/web-audio-api/#AudioContext) object. We propose that the `AudioContext` shouldn't be [allowed to start](https://webaudio.github.io/web-audio-api/#allowed-to-start) whenever it is not rendered and disallowed by the `media-playback-while-not-visible` policy.
113
115
114
-
For scenario 1, if the iframe is not rendered, any `AudioContext` will not be [allowed to start](https://webaudio.github.io/web-audio-api/#allowed-to-start). Therefore, attempting to [create](https://webaudio.github.io/web-audio-api/#dom-audiocontext-audiocontext)a new `AudioContext`or start playback by calling [`resume()`](https://webaudio.github.io/web-audio-api/#dom-audiocontext-resume) shouldn't output any audio and put the `AudioContext`into a[`"suspended"`](https://webaudio.github.io/web-audio-api/#dom-audiocontextstate-suspended) state. It would be recommended for the iframe to wait for a new user interaction event before calling [`resume()`](https://webaudio.github.io/web-audio-api/#dom-audiocontext-resume) - e.g., `click`.
116
+
For scenario 1, if the iframe is not rendered, any `AudioContext` will not be [allowed to start]. Therefore, [creating][AudioContext constructor]a new `AudioContext`should initially put it into the [`"suspended"`] state. Consequently, attempting to start playback by calling [`resume()`] shouldn't output any audio and move the `AudioContext`to the[`"interrupted"`] state. In this case, the webpage can then listen to [`statechange`] events to determine when the interruption is over.
115
117
116
118
```js
117
119
// AudioContext being created in a not rendered iframe, where
@@ -120,62 +122,72 @@ let audioCtx = new AudioContext();
// `audioCtx.onStateChange` should print 'interrupted'
135
133
```
136
134
137
-
Similarly, for scenario 2, when the iframe becomes not rendered during audio playback, the user agent should run the [`suspend()`](https://webaudio.github.io/web-audio-api/#dom-audiocontext-suspend) steps. The audio context state should change to `'suspended'` and the website can monitor this by listening to the [`statechange`](https://webaudio.github.io/web-audio-api/#eventdef-baseaudiocontext-statechange) event.
135
+
Similarly, for scenario 2, when the iframe becomes not rendered during audio playback, the user agent should interrupt the `AudioContext` by moving it to the [`"interrupted"`] state. Likewise, when the interruption is over, the UA should move the `AudioContext` back to the [`"running"`] state. Webpages can monitor these transitions by listening to the [`statechange`] event.
138
136
139
-
```js
140
-
let audioCtx =newAudioContext();
141
-
let oscillator =audioCtx.createOscillator();
142
-
oscillator.connect(audioCtx.destination);
137
+
The snippet below show this could work for scenario 2. Let's assume that the `AudioContext` in the iframe is [allowed to start]. When the web page is initialized, the `AudioContext` will be able to play audio and will transition to the [`"running"`] state. If the user clicks on the `"iframe_visibility_btn"`, the frame will get hidden and the `AudioContext` should be put in the [`"interrupted"`] state. Likewise, pressing again the button will show the iframe again and audio playback will be resumed.
let display_btn =document.getElementById(iframe_visibility_btn);
171
+
display_btn.innerHTML=BTN_HIDE_DISPLAY_NONE_STR;
172
+
display_btn.addEventListener('click', () => {
173
+
if (display_btn.innerHTML==BTN_HIDE_DISPLAY_NONE_STR){
174
+
iframe.style.setProperty('display', 'none')
175
+
display_btn.innerHTML=BTN_SHOW_DISPLAY_NONE_STR
176
+
} else {
177
+
iframe.style.setProperty('display', 'block')
178
+
display_btn.innerHTML=BTN_HIDE_DISPLAY_NONE_STR
179
+
}
180
+
});
181
+
</script>
182
+
</body>
183
+
</html>
172
184
```
173
185
174
186
### Web Speech API
175
187
176
-
The [Web Speech API](https://wicg.github.io/speech-api/) proposes a [SpeechSynthesis interface](https://wicg.github.io/speech-api/#tts-section). The latter interface allows websites to create text-to-speech output by calling [`window.speechSynthesis.speak`](https://wicg.github.io/speech-api/#dom-speechsynthesis-speak) with a [`SpeechSynthesisUtterance`](https://wicg.github.io/speech-api/#speechsynthesisutterance), which represents the text-to-be-said.
188
+
The [Web Speech API] proposes a [SpeechSynthesis interface]. The latter interface allows websites to create text-to-speech output by calling [`window.speechSynthesis.speak`] with a [`SpeechSynthesisUtterance`], which represents the text-to-be-said.
177
189
178
-
For both scenarios, the iframe should listen for utterance errors when calling `window.speechSynthesis.speak()`. For scenario 1 it should fail with a [`"not-allowed"`](https://wicg.github.io/speech-api/#dom-speechsynthesiserrorcode-not-allowed) SpeechSyntesis error; and, for scenario 2, it should fail with an [`"interrupted"`](https://wicg.github.io/speech-api/#dom-speechsynthesiserrorcode-interrupted) error.
190
+
For both scenarios, the iframe should listen for utterance errors when calling `window.speechSynthesis.speak()`. For scenario 1 it should fail with a [`"not-allowed"` SpeechSynthesisErrorCode]; and, for scenario 2, it should fail with an [`"interrupted"` SpeechSynthesisErrorCode].
179
191
180
192
```js
181
193
let utterance =newSpeechSynthesisUtterance('blabla');
@@ -199,12 +211,12 @@ This proposal does not affect autoplay behavior unless the media-playing iframe
199
211
200
212
Both `execution-while-not-rendered` and `execution-while-out-of-viewport` permission policies should take precedence over `media-playback-while-not-visible`. Therefore, in the case that we have an iframe with colliding permissions for the same origin, `media-playback-while-not-visible` should only be considered if the iframe is allowed to execute. The user agent should perform the following checks:
201
213
202
-
1. If the origin is not [allowed to use](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#allowed-to-use) the [`"execution-while-not-rendered"`](https://wicg.github.io/page-lifecycle/#execution-while-not-rendered) feature, then:
203
-
1. If the iframe is not [being rendered](https://html.spec.whatwg.org/multipage/rendering.html#being-rendered), freeze execution of the iframe context and return.
204
-
2. If the origin is not [allowed to use](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#allowed-to-use) the [`"execution-while-out-of-viewport"`](https://wicg.github.io/page-lifecycle/#execution-while-out-of-viewport) feature, then:
205
-
1. If the iframe does not intersect the [viewport](https://www.w3.org/TR/CSS2/visuren.html#viewport), freeze execution of the iframe context and return.
206
-
3. If the origin is not [allowed to use](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#allowed-to-use) the [`"media-playback-while-not-visible"`](#proposed-solution-media-playback-while-not-visible-permission-policy) feature, then:
207
-
1. If the iframe is not [being rendered](https://html.spec.whatwg.org/multipage/rendering.html#being-rendered), pause all media playback from the iframe context and return.
214
+
1. If the origin is not [allowed to use] the [`"execution-while-not-rendered"`] feature, then:
215
+
1. If the iframe is not [being rendered], freeze execution of the iframe context and return.
216
+
2. If the origin is not [allowed to use] the [`"execution-while-out-of-viewport"`] feature, then:
217
+
1. If the iframe does not intersect the [viewport], freeze execution of the iframe context and return.
218
+
3. If the origin is not [allowed to use] the [`"media-playback-while-not-visible"`](#proposed-solution-media-playback-while-not-visible-permission-policy) feature, then:
219
+
1. If the iframe is not [being rendered], pause all media playback from the iframe context and return.
208
220
209
221
## Alternative Solutions
210
222
@@ -244,4 +256,34 @@ Similarly to the [HTMLMediaElement.muted](https://html.spec.whatwg.org/multipage
244
256
</html>
245
257
```
246
258
247
-
This alternative was not selected as the preferred one, because we think that pausing media playback is preferable to just muting it.
259
+
This alternative was not selected as the preferred one, because we think that pausing media playback is preferable to just muting it.
The [Web Speech API](https://wicg.github.io/speech-api/) proposes a [SpeechSynthesis interface](https://wicg.github.io/speech-api/#tts-section). The latter interface allows websites to create text-to-speech output by calling [`window.speechSynthesis.speak`](https://wicg.github.io/speech-api/#dom-speechsynthesis-speak) with a [`SpeechSynthesisUtterance`](https://wicg.github.io/speech-api/#speechsynthesisutterance), which represents the text-to-be-said.
288
+
289
+
For both scenarios, the iframe should listen for utterance errors when calling `window.speechSynthesis.speak()`. For scenario 1 it should fail with a [`"not-allowed" SpeechSynthesisErrorCode`](https://wicg.github.io/speech-api/#dom-speechsynthesiserrorcode-not-allowed) SpeechSyntesis error; and, for scenario 2, it should fail with an [`"interrupted" SpeechSynthesisErrorCode`](https://wicg.github.io/speech-api/#dom-speechsynthesiserrorcode-interrupted) error.
0 commit comments