From 7f048c2410dab3f21b5f76b63ee4d7cb8facacb3 Mon Sep 17 00:00:00 2001 From: Matt Wolenetz Date: Fri, 18 Mar 2022 14:02:31 -0700 Subject: [PATCH] Simplify text for many conditional cross-context operations (#304) Following one of the suggested alternatives by @mwatson2 on previous pull request review [1], this change introduces a "mirror if necessary" algorithm and uses it to simplfiy multiple places in the spec text where the attached MediaSource needs to update the state of the attached HTMLMediaElement. Note, there are several other cross-context pieces of text left unchanged, since they are specific to either setting up the conditionally cross-context communication ports, conditionally tearing them down, or describe how the extended media element buffering or seekable attributes behave relative to the potentially cross-context and asynchronous communication of the state used in those extensions. Note, upcoming PR for privacy and security section addition will also update (restrict) the flexibility for optimizing cross-context communication to help mitigate related timing attacks in implementations. [1] https://github.com/w3c/media-source/pull/282#pullrequestreview-729154906 --- media-source-respec.html | 264 +++++++++++++++++---------------------- 1 file changed, 114 insertions(+), 150 deletions(-) diff --git a/media-source-respec.html b/media-source-respec.html index c04fcb7..8d340a2 100644 --- a/media-source-respec.html +++ b/media-source-respec.html @@ -449,34 +449,27 @@

Attributes

-
  • -
    -
    If the {{MediaSource}} was constructed in a {{DedicatedWorkerGlobalScope}}:
    -
    Post an internal remove track mirror message to {{MediaSource/[[port to - main]]}} whose implicit handler in {{Window}} runs the steps in the following "otherwise" case - for the {{Window}} {{AudioTrack}} mirror of the {{DedicatedWorkerGlobalScope}} {{AudioTrack}} - object created previously by the implicit handler for the internal create track - mirror message.
    -
    Otherwise, run the following steps:
    -
    -
      -
    1. Let |HTMLMediaElement audioTracks list:AudioTrackList| equal the {{AudioTrackList}} object - returned by the {{HTMLMediaElement/audioTracks}} attribute on the HTMLMediaElement.
    2. -
    3. Remove the {{AudioTrack}} object from the |HTMLMediaElement audioTracks list|. -

      - This should trigger {{AudioTrackList}} [[HTML]] logic to [=queue a task=] to - [=fire an event=] named [=AudioTrackList/removetrack=] using {{TrackEvent}} with the - {{TrackEvent/track}} attribute initialized to the {{AudioTrack}} object, at the - |HTMLMediaElement audioTracks list|. If the {{AudioTrack/enabled}} attribute on the - {{AudioTrack}} object was true at the beginning of this removal step, then this should - also trigger {{AudioTrackList}} [[HTML]] logic to [=queue a task=] to [=fire an event=] - named [=AudioTrackList/change=] at the |HTMLMediaElement audioTracks list|. -

      -
    4. -
    -
    -
    +
  • Use the [=mirror if necessary=] algorithm to run the following steps in {{Window}}, to + remove the {{AudioTrack}} object (or instead, the {{Window}} mirror of it if the {{MediaSource}} + object was constructed in a {{DedicatedWorkerGlobalScope}}) from the media element: +
      +
    1. Let |HTMLMediaElement audioTracks list:AudioTrackList| equal the {{AudioTrackList}} object + returned by the {{HTMLMediaElement/audioTracks}} attribute on the HTMLMediaElement.
    2. +
    3. Remove the {{AudioTrack}} object from the |HTMLMediaElement audioTracks list|. +

      + This should trigger {{AudioTrackList}} [[HTML]] logic to [=queue a task=] to + [=fire an event=] named [=AudioTrackList/removetrack=] using {{TrackEvent}} with the + {{TrackEvent/track}} attribute initialized to the {{AudioTrack}} object, at the + |HTMLMediaElement audioTracks list|. If the {{AudioTrack/enabled}} attribute on the + {{AudioTrack}} object was true at the beginning of this removal step, then this should + also trigger {{AudioTrackList}} [[HTML]] logic to [=queue a task=] to [=fire an event=] + named [=AudioTrackList/change=] at the |HTMLMediaElement audioTracks list|. +

      +
    4. +
  • + + @@ -502,34 +495,24 @@

    Attributes

    -
  • -
    -
    If the {{MediaSource}} was constructed in a {{DedicatedWorkerGlobalScope}}:
    -
    Post an internal remove track mirror message to {{MediaSource/[[port to - main]]}} whose implicit handler in {{Window}} runs the steps in the following "otherwise" case - for the {{Window}} {{VideoTrack}} mirror of the {{DedicatedWorkerGlobalScope}} {{VideoTrack}} - object created previously by the implicit handler for the internal create track - mirror message.
    -
    Otherwise, run the following steps:
    -
    -
      -
    1. Let |HTMLMediaElement videoTracks list:VideoTrackList| equal the {{VideoTrackList}} object - returned by the {{HTMLMediaElement/videoTracks}} attribute on the HTMLMediaElement.
    2. -
    3. Remove the {{VideoTrack}} object from the |HTMLMediaElement videoTracks list|. -

      - This should trigger {{VideoTrackList}} [[HTML]] logic to [=queue a task=] to [=fire an event=] - named [=VideoTrackList/removetrack=] using {{TrackEvent}} with the {{TrackEvent/track}} - attribute initialized to the {{VideoTrack}} object, at the |HTMLMediaElement videoTracks list|. - If the - {{VideoTrack/selected}} attribute on the {{VideoTrack}} object was true at the beginning - of this removal step, then this should also trigger {{VideoTrackList}} [[HTML]] logic to - [=queue a task=] to [=fire an event=] named [=VideoTrackList/change=] at the - |HTMLMediaElement videoTracks list|. -

      -
    4. -
    -
    -
    +
  • Use the [=mirror if necessary=] algorithm to run the following steps in {{Window}}, to + remove the {{VideoTrack}} object (or instead, the {{Window}} mirror of it if the {{MediaSource}} + object was constructed in a {{DedicatedWorkerGlobalScope}}) from the media element: +
      +
    1. Let |HTMLMediaElement videoTracks list:VideoTrackList| equal the {{VideoTrackList}} object + returned by the {{HTMLMediaElement/videoTracks}} attribute on the HTMLMediaElement.
    2. +
    3. Remove the {{VideoTrack}} object from the |HTMLMediaElement videoTracks list|. +

      + This should trigger {{VideoTrackList}} [[HTML]] logic to [=queue a task=] to [=fire an + event=] named [=VideoTrackList/removetrack=] using {{TrackEvent}} with the + {{TrackEvent/track}} attribute initialized to the {{VideoTrack}} object, at the + |HTMLMediaElement videoTracks list|. If the {{VideoTrack/selected}} attribute on the + {{VideoTrack}} object was true at the beginning of this removal step, then this should also + trigger {{VideoTrackList}} [[HTML]] logic to [=queue a task=] to [=fire an event=] named + [=VideoTrackList/change=] at the |HTMLMediaElement videoTracks list|. +

      +
    4. +
  • @@ -557,35 +540,25 @@

    Attributes

    -
  • -
    -
    If the {{MediaSource}} was constructed in a {{DedicatedWorkerGlobalScope}}:
    -
    Post an internal remove track mirror message to {{MediaSource/[[port to - main]]}} whose implicit handler in {{Window}} runs the steps in the following "otherwise" case - for the {{Window}} {{TextTrack}} mirror of the {{DedicatedWorkerGlobalScope}} {{TextTrack}} - object created previously by the implicit handler for the internal create track - mirror message.
    -
    Otherwise, run the following steps:
    -
    -
      -
    1. Let |HTMLMediaElement textTracks list:TextTrackList| equal the {{TextTrackList}} object - returned by the {{HTMLMediaElement/textTracks}} attribute on the HTMLMediaElement.
    2. -
    3. Remove the {{TextTrack}} object from the |HTMLMediaElement textTracks list|. -

      - This should trigger {{TextTrackList}} [[HTML]] logic to [=queue a task=] to [=fire an event=] - named [=TextTrackList/removetrack=] using {{TrackEvent}} with the {{TrackEvent/track}} - attribute initialized to the {{TextTrack}} object, at the |HTMLMediaElement textTracks list|. - If the - {{TextTrack/mode}} attribute on the {{TextTrack}} object was - or at the - beginning of this removal step, then this should also trigger {{TextTrackList}} [[HTML]] - logic to [=queue a task=] to [=fire an event=] named [=TextTrackList/change=] - at the |HTMLMediaElement textTracks list|. -

      -
    4. -
    -
    -
    +
  • Use the [=mirror if necessary=] algorithm to run the following steps in {{Window}}, to + remove the {{TextTrack}} object (or instead, the {{Window}} mirror of it if the {{MediaSource}} + object was constructed in a {{DedicatedWorkerGlobalScope}}) from the media element: +
      +
    1. Let |HTMLMediaElement textTracks list:TextTrackList| equal the {{TextTrackList}} object + returned by the {{HTMLMediaElement/textTracks}} attribute on the HTMLMediaElement.
    2. +
    3. Remove the {{TextTrack}} object from the |HTMLMediaElement textTracks list|. +

      + This should trigger {{TextTrackList}} [[HTML]] logic to [=queue a task=] to [=fire an + event=] named [=TextTrackList/removetrack=] using {{TrackEvent}} with the + {{TrackEvent/track}} attribute initialized to the {{TextTrack}} object, at the + |HTMLMediaElement textTracks list|. If the {{TextTrack/mode}} attribute on the + {{TextTrack}} object was or + at the beginning of this removal step, then this + should also trigger {{TextTrackList}} [[HTML]] logic to [=queue a task=] to [=fire an + event=] named [=TextTrackList/change=] at the |HTMLMediaElement textTracks list|. +

      +
    4. +
  • @@ -1042,15 +1015,12 @@

    Duration change

  • Update {{MediaSource/duration}} to |new duration|.
  • -
  • Update the {{HTMLMediaElement/duration}} to |new duration|.
  • -
  • -
    -
    If the {{MediaSource}} was constructed in a {{DedicatedWorkerGlobalScope}}:
    -
    Post an internal duration change message to {{MediaSource//[[port to main]]}} whose - implicit handler in {{Window}} runs the .
    -
    Otherwise:
    -
    Run the .
    -
    +
  • Use the [=mirror if necessary=] algorithm to run the following steps in {{Window}} to update the media + element's duration: +
      +
    1. Update the media element's {{HTMLMediaElement/duration}} to |new duration|.
    2. +
    3. Run the .
    4. +
  • @@ -1076,13 +1046,7 @@

    End of stream

    If |error| is set to {{EndOfStreamError/""network""}}
    -
    -
    -
    If the {{MediaSource}} was constructed in a {{DedicatedWorkerGlobalScope}}:
    -
    Post an internal network error message to {{MediaSource//[[port to main]]}} whose - implicit handler in {{Window}} runs the steps in the following "otherwise" case.
    -
    Otherwise:
    -
    +
    Use the [=mirror if necessary=] algorithm to run the following steps in {{Window}}:
    If the {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} attribute equals {{HTMLMediaElement/HAVE_NOTHING}}
    @@ -1091,18 +1055,10 @@

    End of stream

    {{HTMLMediaElement/HAVE_NOTHING}}
    Run the "If the connection is interrupted after some media data has been received, causing the user agent to give up trying to fetch the resource" steps of the 's .
    -
    -
    If |error| is set to {{EndOfStreamError/""decode""}}
    -
    -
    -
    If the {{MediaSource}} was constructed in a {{DedicatedWorkerGlobalScope}}:
    -
    Post an internal decode error message to {{MediaSource/[[port to main]]}} whose - implicit handler in {{Window}} runs the steps in the following "otherwise" case.
    -
    Otherwise:
    -
    +
    Use the [=mirror if necessary=] algorithm to run the following steps in {{Window}}:
    If the {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} attribute equals {{HTMLMediaElement/HAVE_NOTHING}}
    @@ -1111,13 +1067,36 @@

    End of stream

    {{HTMLMediaElement/HAVE_NOTHING}}
    Run the steps of the 's .
    -
    -
    + +
    +

    Mirror if necessary

    +

    This algorithm is used to run steps on {{Window}} from a {{MediaSource}} attached from either the same + {{Window}} or from a {{DedicatedWorkerGlobalScope}}, usually to update the state of the attached + {{HTMLMediaElement}}. This algorithm takes a |steps| parameter that lists the steps to run on {{Window}}.

    +
    +
    If the {{MediaSource}} was constructed in a {{DedicatedWorkerGlobalScope}}:
    +
    Post an internal mirror on window message to {{MediaSource/[[port to main]]}} whose + implicit handler in {{Window}} will run |steps|. Return control to the caller without awaiting that + handler's receipt of the message. +
    + The purpose of the mirror message mechanism is to ensure that: +
      +
    1. |steps| run asynchronously as their own task on {{Window}} rather than these |steps| somehow + happening in the middle of some other {{Window}} task's execution, and
    2. +
    3. |steps| are run without blocking the synchronous execution and return of this algorithm on + {{DedicatedWorkerGlobalScope}}. +
    +
    +
    +
    Otherwise:
    +
    Run |steps|.
    +
    +
    @@ -2014,52 +1993,37 @@

    Initialization Segment Received

  • Set {{SourceBuffer/[[pending initialization segment for changeType flag]]}} to false.
  • If the |active track flag| equals true, then run the following steps: -
    -
    If the [=parent media source=] was constructed in a {{DedicatedWorkerGlobalScope}}:
    -
    Post an internal active track added message to {{MediaSource/[[port to main]]}} whose - implicit handler in {{Window}} runs the following step: +
  • Use the [=parent media source=]'s [=mirror if necessary=] algorithm to run the following step in + {{Window}}:
    1. If the {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} attribute is greater than {{HTMLMediaElement/HAVE_CURRENT_DATA}}, then set the {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} attribute to {{HTMLMediaElement/HAVE_METADATA}}. -
    2. -
  • -
    Otherwise:
    -
    If the {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} attribute is greater than - {{HTMLMediaElement/HAVE_CURRENT_DATA}}, then set the - {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} attribute to - {{HTMLMediaElement/HAVE_METADATA}}.
    -
    -

    - Per [[HTML]] logic, {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} - changes may trigger events on the HTMLMediaElement. -

    +

    + Per [[HTML]] logic, {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} + changes may trigger events on the HTMLMediaElement. +

    + +
  • If each object in {{MediaSource/sourceBuffers}} of the [=parent media source=] has - {{SourceBuffer/[[first initialization segment received flag]]}} equal to true, then run the following - steps: -
    -
    If the [=parent media source=] was constructed in a {{DedicatedWorkerGlobalScope}}:
    -
    Post an internal sourcebuffers ready message to {{MediaSource/[[port to main]]}} whose - implicit handler in {{Window}} runs the following step: -
      -
    1. If the {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} attribute is - {{HTMLMediaElement/HAVE_NOTHING}}, then set the {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} - attribute to {{HTMLMediaElement/HAVE_METADATA}}. -
    2. -
    -
    Otherwise:
    -
    If the {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} attribute is - {{HTMLMediaElement/HAVE_NOTHING}}, then set the {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} - attribute to {{HTMLMediaElement/HAVE_METADATA}}.
    -
    -

    - Per [[HTML]] logic, {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} - changes may trigger events on the HTMLMediaElement. If transition from {{HTMLMediaElement/HAVE_NOTHING}} - to {{HTMLMediaElement/HAVE_METADATA}} occurs, it should trigger HTMLMediaElement logic to [=queue a - task=] to [=fire an event=] named [=HTMLMediaElement/loadedmetadata=] at the media element. -

    + {{SourceBuffer/[[first initialization segment received flag]]}} equal to true, then + use the [=parent media source=]'s [=mirror if necessary=] algorithm to run the following step in + {{Window}}: +
      +
    1. If the {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} attribute is + {{HTMLMediaElement/HAVE_NOTHING}}, then set the {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} + attribute to {{HTMLMediaElement/HAVE_METADATA}}. +

      + Per [[HTML]] logic, + {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} changes may trigger events on the + HTMLMediaElement. If transition from {{HTMLMediaElement/HAVE_NOTHING}} to + {{HTMLMediaElement/HAVE_METADATA}} occurs, it should trigger HTMLMediaElement logic to [=queue a + task=] to [=fire an event=] named [=HTMLMediaElement/loadedmetadata=] at the media element. +

      +
    2. +