diff --git a/index.bs b/index.bs index f3ca41c..fbaaf11 100644 --- a/index.bs +++ b/index.bs @@ -39,6 +39,7 @@ spec:dom; type:dfn; text:origin spec:dom; type:interface; text:Document spec:html; type:attribute; for:HTMLMediaElement; text:readyState spec:html; type:dfn; for:/; text:browsing context +spec:html; type:dfn; text:allowed to use spec:infra; type:dfn; text:user agent spec:infra; type:dfn; for:list; text:item @@ -167,53 +168,31 @@ to initiate and control this behavior by exposing the following sets of properti # Concepts # {#concepts} -## Internal Slot Definitions ## {#defines} +## Definitions ## {#defines} + +A Picture-in-Picture window is a window displaying the <{video}> element. + +A {{DocumentOrShadowRoot}} has: + +1. A Picture-in-Picture element, which is an {{Element}} or `null`, initially `null`. + +A traversable navigable has: +1. A picture-in-picture parallel queue, which is a [=parallel queue=] created by + [=starting a new parallel queue=]. + A user agent has: 1. An initiators of active Picture-in-Picture sessions list of zero or more origins, which is initially empty. -Note: In case a user agent supports multiple Picture-in-Picture - windows, the list allows duplicates. + Note: In case a user agent supports multiple Picture-in-Picture windows, the list allows duplicates. An origin is said to have an active Picture-in-Picture session if any of the origins in initiators of active Picture-in-Picture sessions are same origin-domain with origin. -## Request Picture-in-Picture ## {#request-pip} - -When the request Picture-in-Picture algorithm with |video| is invoked, -the user agent MUST run the following steps: - -1. If Picture-in-Picture support is `false`, throw a - {{NotSupportedError}} and abort these steps. -2. If the document is not allowed to use the policy-controlled feature - named `"picture-in-picture"`, throw a {{SecurityError}} and abort these - steps. -3. If |video|'s {{readyState}} attribute is {{HAVE_NOTHING}}, throw a - {{InvalidStateError}} and abort these steps. -4. If |video| has no video track, throw a {{InvalidStateError}} and abort - these steps. -5. If |video|'s {{HTMLVideoElement/disablePictureInPicture}} is true, - the user agent MAY throw an {{InvalidStateError}} and abort these steps. -6. If {{pictureInPictureElement}} is `null`: - 1. If this's relevant global object does not have - transient activation, throw a {{NotAllowedError}} and abort these steps. - 2. [=Consume user activation=] given this's relevant global object. -7. If |video| is {{pictureInPictureElement}}, abort these steps. -8. Set {{pictureInPictureElement}} to |video|. -9. Let Picture-in-Picture window be a new instance of - {{PictureInPictureWindow}} associated with {{pictureInPictureElement}}. -10. Append relevant settings object's origin to - initiators of active Picture-in-Picture sessions. -11. Queue a task to fire an event named - {{enterpictureinpicture}} using {{PictureInPictureEvent}} at the - |video| with its {{bubbles}} attribute initialized to `true` and its - {{PictureInPictureEvent/pictureInPictureWindow}} attribute initialized to - Picture-in-Picture window. -12. If {{pictureInPictureElement}} is fullscreenElement, it is - RECOMMENDED to exit fullscreen. +## Picture-in-Picture ## {#pip} It is RECOMMENDED that video frames are not rendered in the page and in the Picture-in-Picture window at the same time but if they are, they MUST be kept @@ -233,7 +212,7 @@ It is also RECOMMENDED that the Picture-in-Picture window has a maximum and minimum size. For example, it could be restricted to be between a quarter and a half of one dimension of the screen. -When a {{DocumentOrShadowRoot}}'s {{pictureInPictureElement}} attribute is set, +When a {{DocumentOrShadowRoot}}'s Picture-in-Picture element is set, the [=Picture-in-Picture window=] MUST be visible, even when the {{DocumentOrShadowRoot}}'s [=relevant global object=]'s [=associated Document=]'s [=Document/visibility state=] is "hidden". @@ -332,16 +311,48 @@ partial interface HTMLVideoElement { }; -The {{requestPictureInPicture()}} method, when invoked, MUST -return a new promise |promise| and run the following steps in -parallel: +The {{requestPictureInPicture()}} method steps request Picture-in-Picture: + +1. If [=Picture-in-Picture support=] is `false`, return [=a promise rejected with=] {{NotSupportedError}} {{DOMException}}. +2. Let |doc| be [=this=]'s [=node document=]. +3. If |doc| is not [=allowed to use=] the [=policy-controlled feature=] + named `"picture-in-picture"`, return [=a promise rejected with=] {{NotAllowedError}} {{DOMException}}. +4. If [=this=]'s {{readyState}} attribute is {{HAVE_NOTHING}}, return [=a promise rejected with=] {{InvalidStateError}} {{DOMException}}. +5. If [=this=] has no video track, return [=a promise rejected with=] {{InvalidStateError}} {{DOMException}}. +6. If [=this=]'s {{HTMLVideoElement/disablePictureInPicture}} is true, user agent may return [=a promise rejected with=] {{InvalidStateError}} {{DOMException}}. +7. If |doc|'s [=Picture-in-Picture element=] is `null`: + 1. If [=this=]'s [=relevant global object=] does not have a [=transient activation=], then return [=a + promise rejected with=] {{NotAllowedError}} {{DOMException}}. + 2. [=Consume user activation=] given [=this=]'s [=relevant global object=]. +8. If [=this=] is |doc|'s [=Picture-in-Picture element=]: + 1. Return [=a promise resolved with=] the [=Picture-in-Picture window=] associated with |doc|'s [=Picture-in-Picture element=]. +9. Let |global| be [=this=]'s [=relevant global object=]. +10. Let |p| be [=a new promise=] created in [=this=]'s [=relevant realm=]. +11. Return |p|, and [=enqueue the following steps=] to |doc|'s [=picture-in-picture parallel queue=]: + 1. If [=this=] is |doc|'s [=Picture-in-Picture element=]: + 1. [=Queue a global task=] on the [=media element event task source=] given |global| to + [=/resolve=] |p| with the [=Picture-in-Picture window=] associated with + [=this=]. + 2. Abort these steps. + 2. Attempt to associate a [=Picture-in-Picture window=] with [=this=]. + 3. If the previous step failed: + 1. [=Queue a global task=] on the [=media element event task source=] given |global| to + [=/reject=] |p| with {{InvalidStateError}} {{DOMException}}. + 2. Abort these steps. + 4. Let |pipWindow| be a new instance of {{PictureInPictureWindow}} that represents [=this=]'s associated [=Picture-in-Picture window=]. + 5. [=Queue a global task=] on the [=media element event task source=] given |global|, to perform + the following steps: + 1. If {{pictureInPictureElement}} is not `null`, run the [=exit Picture-in-Picture algorithm=]. + 2. Set |doc|'s [=Picture-in-Picture element=] to [=this=]. + 3. [=list/Append=] [=relevant settings object=]'s [=origin=] to [=initiators of active + Picture-in-Picture sessions=]. + 4. If [=this=] is [=fullscreenElement=], [=exit fullscreen=]. + 5. [=Fire an event=] named {{enterpictureinpicture}} using {{PictureInPictureEvent}} at + [=this=] with its {{bubbles}} attribute initialized to `true` and its + {{PictureInPictureEvent/pictureInPictureWindow}} attribute initialized to + [=Picture-in-Picture window=]. + 6. [=/Resolve=] |p| with |pipWindow|. -1. Let |video| be the video element on which the method was invoked. -2. Run the request Picture-in-Picture algorithm with |video|. -3. If the previous step threw an exception, reject |promise| with that - exception and abort these steps. -4. [=/Resolve=] |promise| with the Picture-in-Picture window associated with - {{pictureInPictureElement}}. ## Extensions to Document ## {#document-extensions} @@ -382,8 +393,7 @@ The {{pictureInPictureElement}} attribute's getter must run these steps: 1. If this is a shadow root and its host is not connected, return `null` and abort these steps. -2. Let |candidate| be the result of retargeting Picture-in-Picture - element against this. +2. Let |candidate| be the result of [=retargeting=] [=Picture-in-Picture element=] against [=this=]. 3. If |candidate| and this are in the same tree, return |candidate| and abort these steps. 4. Return `null`. @@ -468,8 +478,8 @@ regardless of the browsing context. ## Permissions Policy ## {#permissions-policy} This specification defines a policy-controlled feature named -`"picture-in-picture"` that controls whether the request Picture-in-Picture -algorithm may return a {{SecurityError}} and whether +`"picture-in-picture"` that controls whether [=request Picture-in-Picture=] +returns a {{SecurityError}} and whether {{pictureInPictureEnabled}} is `true` or `false`. The default allowlist for this feature is `*`.