Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 120 additions & 6 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,138 @@ Shortname: iframe-media-pausing
Level: 1
Status: w3c/UD
Group: wicg
Repository: WICG/iframe-media-pausing
Repository: wicg/iframe-media-pausing
URL: https://github.com/WICG/iframe-media-pausing
Editor: Gabriel Santana Brito, Microsoft https://microsoft.com/, gabrielbrito@microsoft.com, https://github.com/gabrielsanbrito
Abstract: This specification defines a new permission policy that allows the
user-agent to pause media playback in iframes which are not visible to
the user.
Complain About: accidental-2119 yes, missing-example-ids yes
Markup Shorthands: markdown yes, css no
Default Biblio Status: current
Markup Shorthands: markdown yes, css no, dfn yes, markup yes
</pre>

<pre class="anchors">
spec: webaudio; urlPrefix: https://webaudio.github.io/web-audio-api/;
type: dfn; text: allowed to start; url: #allowed-to-start
spec: HTML; urlPrefix: https://html.spec.whatwg.org/multipage/;
type: dfn; text: allowed to play; url: media.html#allowed-to-play
type: dfn; text: content document; url: document-sequences.html#concept-bcc-content-document
type: dfn; text: eligible for autoplay; url: media.html#eligible-for-autoplay
type: dfn; text: internal pause steps; url: media.html#internal-pause-steps
type: dfn; text: nested browsing context; url: document-sequences.html#nested-browsing-context
</pre>

# Introduction # {#intro}

<em>This section is non-normative.</em>

Web applications that host embedded media content via iframes may wish to respond to application input by temporarily hiding the media content. These applications may not want to unload the entire iframe when it's not rendered since it could generate user-perceptible performance and experience issues when showing the media content again. At the same time, the user could have a negative experience if the media continues to play and emit audio when not rendered. This proposal aims to provide web applications with the ability to control embedded media content in such a way that guarantees their users have a good experience when the iframe's render status is changed.
Web applications that host embedded media content via iframes may wish to respond to application input by temporarily hiding the media content.
These applications may not want to unload the entire iframe when it's not rendered since it could generate user-perceptible performance and iframe state loss issues when showing the media content again.
At the same time, the user could have a negative experience if the media continues to play and emit audio when not rendered.
This proposal aims to provide web applications with the ability to control embedded media content in such a way that guarantees their users have a good experience when the iframe's render status is changed.

## Goals ## {#goals}

Propose a mechanism to allow embedder documents to limitedly control embedded iframe media playback based on whether the embedded iframe is rendered or not:
* When the iframe is not rendered, the embedder is able to pause the iframe media playback; and
* When the iframe becomes rendered again, the embedder is able to resume the iframe media playback.
Propose a mechanism to allow embedder documents to limitedly control embedded
iframe media playback based on whether the embedded iframe is rendered or not:
* When the iframe is not rendered, the embedder is able to pause the iframe's media playback; and
* When the iframe becomes rendered again, the embedder is able to resume the iframe media playback.

# API # {#api}

Control over media playback in [=child navigables=] in response to changes to their [=container=]'s visibility is relevant for user experience and performance reasons.
Although simply disposing of the [=navigable container=] when not rendered would also achieve the same result (no audible media playback), it could lead to user-perceptible performance issues when the [=navigable container=] is rendered again, since it would need to be recreated from scratch.
Moreover, disposing of the context could also lead to loss of state that the user might expect to be preserved - e.g. form data.

This specification defines a new [=policy-controlled feature=] identified by the token "<dfn export><code>media-playback-while-not-visible</code></dfn>" that controls whether a {{Document}} is allowed to play media while it is not [=being rendered=].
The [=default allowlist=] for this policy is "[=default allowlist/*=]", meaning that documents are allowed to play media while not rendered unless the policy is explicitly disabled.

To determine if a {{Document}} |document| is <dfn>allowed to play media while not rendered</dfn>, run the following steps:

1. If |document| is [=/allowed to use=] the "<a><code>media-playback-while-not-visible</code></a>" feature, then return true.
1. Return false otherwise.

## Usage example ## {#usage-example}

<div id="iframe-example" class="example">
<p>
Using the <code>media-playback-while-not-visible</code> permission policy to prevent an <{iframe}> and all of its children from playing media when the iframe is not [=being rendered=].
</p>
<pre>
&lt;iframe src="https://foo.media.com" allow="media-playback-while-not-visible 'none'"&gt;&lt;/iframe&gt;
</pre>
</div>

<div id="application-example" class="example">
<p>
To disable the <code>media-playback-while-not-visible</code> permission policy for an entire web application, the application can send the HTTP response header below. Doing so will disable the permission policy for the application's top-level {{Document}} and for all of the embedded <{iframe}>'s.
</p>
<pre>
Permissions-Policy: media-playback-while-not-visible=()
</pre>
</div>

# Integration with other specifications # {#integration}

There are several ways to render audible media content on the web, which means that this specification has points of contact with other specifications.
The "<a><code>media-playback-while-not-visible</code></a>" strictly interacts with audible media content in two scenarios:

1. When the iframe is not rendered and it attempts to play audible media; and
2. When the iframe is currently playing audible media and stops [=being rendered=] during playback.

The following sections describe how the "<a><code>media-playback-while-not-visible</code></a>" permission policy integrates with other specifications.

## HTMLMediaElement ## {#html-media-element-integration}

Let |mediaElement| be an {{HTMLMediaElement}}. Let {{Document}} |document| be the |mediaElement|'s [=node document=]. Let [=/Navigable=] |navigable| be the [=node navigable=] of |mediaElement|. Let |navigableContainer| be the [=container=] of |navigable|.

Note: |navigableContainer| is null if |navigable| is a [=/top-level traversable=].

Amend the definition of [=allowed to play=] so that |mediaElement| is also not [=allowed to play=] if all the following conditions are met:
- |navigableContainer| is not null;
- |document| is not [=allowed to play media while not rendered=]; and
- |navigableContainer| is not [=being rendered=].

Note: Calling {{HTMLMediaElement/play()}} on |mediaElement| while it is not [=allowed to play=] will return a promise rejected with a "{{NotAllowedError}}" {{DOMException}}.

When |navigableContainer| is not null and stops [=being rendered=]:

1. If |document| is not [=allowed to play media while not rendered=]:
1. Run the [=internal pause steps=] on |mediaElement|.

## Web Audio ## {#web-audio-integration}

Let |audioContext| be an {{AudioContext}}. Let {{Document}} |document| be the |audioContext|'s [=relevant global object=]'s [=associated Document=]. Let |navigable| be [=/Navigable=] whose [=active document=] is |document|. Let |navigableContainer| be the [=navigable container=] whose [=content document=] is |document|.

Amend the definition of [=allowed to start=] so that |audioContext| is also not [=allowed to start=] if all the following conditions are met:
- |navigableContainer| is not null;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean that the permission policy does not apply to top level documents?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. IIUC, top-level documents do not have a navigable container and thus cannot be "not rendered".

- |document| is not [=allowed to play media while not rendered=]; and
- |navigableContainer| is not [=being rendered=].

Note: If |audioContext| is created while |navigableContainer| is not [=being rendered=], it will be initialized in the {{AudioContextState/suspended}} state. Furthermore, attempting to call {{AudioContext/resume()}} on |audioContext| while |navigableContainer| is not [=being rendered=] will return a promise rejected with {{InvalidStateError}} and transition |audioContext| to the {{AudioContextState/interrupted}} state.

When |navigableContainer| is not null and stops [=being rendered=]:

1. If |document| is not [=allowed to play media while not rendered=]:
1. If |audioContext| {{BaseAudioContext/state}} is {{AudioContextState/running}}:
1. {{AudioContext/interruption-start|Start an interruption}} on |audioContext|.

When |navigableContainer| is not null and starts [=being rendered=] again:

1. If |document| is not [=allowed to play media while not rendered=]:
1. If |audioContext| {{BaseAudioContext/state}} is {{AudioContextState/interrupted}}:
1. {{AudioContext/interruption-end|End the interruption}} on |audioContext|.

## Autoplay ## {#autoplay-integration}

Let |mediaElement| be an {{HTMLMediaElement}}. Let {{Document}} |document| be the |mediaElement|'s [=node document=]. Let [=/Navigable=] |navigable| be the [=node navigable=] of |mediaElement|. Let |navigableContainer| be the [=container=] of |navigable|.

Amend the definition of [=eligible for autoplay=] so that |mediaElement| is also not [=eligible for autoplay=] if all the following conditions are met:
- |navigableContainer| is not null;
- |document| is not [=allowed to play media while not rendered=]; and
- |navigableContainer| is not [=being rendered=].

Moreover, if |mediaElement| is currently playing because of autoplay and |navigableContainer| stops [=being rendered=], the user-agent MUST run the [=internal pause steps=] on |mediaElement|. When |navigableContainer| starts [=being rendered=] again, |mediaElement| MUST remain paused until playback is explicitly resumed.

The "<a><code>media-playback-while-not-visible</code></a>" permission policy MUST NOT affect autoplay behavior if |navigableContainer| is currently [=being rendered=].