Skip to content

Commit f495c02

Browse files
authored
Specify range fetching for media elements
See #2814, especially #2814 (comment), for some background. The strategy taken here is that multiple opaque range responses are OK as long as they're from the same origin. (They don't have to be the same URL.) Programmatic service worker responses are considered a null origin for these purposes. This matches implemented behaviors.
1 parent 89f9bcb commit f495c02

File tree

1 file changed

+156
-37
lines changed

1 file changed

+156
-37
lines changed

source

Lines changed: 156 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2539,6 +2539,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
25392539
<li><dfn data-x-href="https://fetch.spec.whatwg.org/#finalize-and-report-timing">finalize and report timing</dfn></li>
25402540
<li><dfn data-x="serialize-a-response-url-for-reporting" data-x-href="https://fetch.spec.whatwg.org/#serialize-a-response-url-for-reporting">serialize a response URL for reporting</dfn></li>
25412541
<li><dfn data-x="body safely extract" data-x-href="https://fetch.spec.whatwg.org/#bodyinit-safely-extract">safely extracting a body</dfn></li>
2542+
<li><dfn data-x="body-incrementally-read" data-x-href="https://fetch.spec.whatwg.org/#body-incrementally-read">incrementally reading a body</dfn></li>
25422543
<li><dfn data-x-href="https://fetch.spec.whatwg.org/#process-response-end-of-body">processResponseConsumeBody</dfn></li>
25432544
<li><dfn data-x-href="https://fetch.spec.whatwg.org/#fetch-processresponseendofbody">processResponseEndOfBody</dfn></li>
25442545
<li>
@@ -2556,6 +2557,10 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
25562557
<li><dfn data-x="concept-response-location-url" data-x-href="https://fetch.spec.whatwg.org/#concept-response-location-url">location URL</dfn></li>
25572558
<li><dfn data-x="concept-response-timing-info" data-x-href="https://fetch.spec.whatwg.org/#concept-response-timing-info">timing info</dfn></li>
25582559
<li><dfn data-x="concept-response-service-worker-timing-info" data-x-href="https://fetch.spec.whatwg.org/#response-service-worker-timing-info">service worker timing info</dfn></li>
2560+
<li>
2561+
<dfn data-x-href="https://wicg.github.io/background-fetch/#extract-content-range-values">extract content-range values</dfn>
2562+
<!-- TODO: move this to FETCH -->
2563+
</li>
25592564
</ul>
25602565
</li>
25612566
<li>
@@ -2595,6 +2600,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
25952600
<li><dfn data-x="concept-request-reload-navigation-flag" data-x-href="https://fetch.spec.whatwg.org/#concept-request-reload-navigation-flag">reload-navigation flag</dfn></li>
25962601
<li><dfn data-x="concept-request-history-navigation-flag" data-x-href="https://fetch.spec.whatwg.org/#concept-request-history-navigation-flag">history-navigation flag</dfn></li>
25972602
<li><dfn data-x="concept-request-user-activation" data-x-href="https://fetch.spec.whatwg.org/#request-user-activation">user-activation</dfn></li>
2603+
<li><dfn data-x-href="https://fetch.spec.whatwg.org/#concept-request-add-range-header">add a range header</dfn></li>
25982604
</ul>
25992605
</li>
26002606
</ul>
@@ -33857,6 +33863,11 @@ interface <dfn interface>HTMLMediaElement</dfn> : <span>HTMLElement</span> {
3385733863

3385833864
</p>
3385933865

33866+
<p>A <span>media resource</span> has an associated
33867+
<dfn data-x="media-resource-origin">origin</dfn>, which is either "<code data-x="">none</code>",
33868+
"<code data-x="">multiple</code>", "<code data-x="">rewritten</code>", or an
33869+
<span>origin</span>. It is initially set to "<code data-x="">none</code>".</p>
33870+
3386033871
<p>A <span>media resource</span> can have multiple audio and video tracks. For the purposes of a
3386133872
<span>media element</span>, the video data of the <span>media resource</span> is only that of the
3386233873
currently selected track (if any) as given by the element's <code
@@ -34673,6 +34684,66 @@ interface <dfn interface>MediaError</dfn> {
3467334684
</li>
3467434685
</ol>
3467534686

34687+
<p>To <dfn>verify a media response</dfn> given a <span data-x="concept-response">response</span>
34688+
<var>response</var>, a <span>media resource</span> <var>resource</var>, and
34689+
"<code data-x="">entire resource</code>" or a
34690+
(number, number or "<code data-x="">until end</code>") tuple <var>byteRange</var>:</p>
34691+
34692+
<ol>
34693+
<li><p>If <var>response</var> is a <span>network error</span>, then return false.</p></li>
34694+
34695+
<li><p>If <var>byteRange</var> is "<code data-x="">entire resource</code>", then return
34696+
true.</p></li>
34697+
34698+
<li><p>Let <var>internalResponse</var> be <var>response</var>'s
34699+
<span>unsafe response</span>.</p></li>
34700+
34701+
<li><p>If <var>internalResponse</var>'s <span data-x="concept-response-status">status</span> is
34702+
not 206, then return false.</p></li>
34703+
34704+
<li><p>Let <var>origin</var> be "<code data-x="">rewritten</code>" if
34705+
<var>internalResponse</var>'s <span data-x="concept-response-url">URL</span> is null; otherwise
34706+
<var>internalResponse</var>'s <span data-x="concept-response-url">URL</span>'s
34707+
<span data-x="concept-url-origin">origin</span>.</p></li>
34708+
34709+
<li><p>Let <var>previousOrigin</var> be <var>resource</var>'s
34710+
<span data-x="media-resource-origin">origin</span>.</p></li>
34711+
34712+
<li>
34713+
<p>If any of the following conditions are true:</p>
34714+
<ul>
34715+
<li><var>previousOrigin</var> is "<code data-x="">none</code>";</li>
34716+
34717+
<li><var>origin</var> and <var>previousOrigin</var> are "<code data-x="">rewritten</code>";
34718+
or</li>
34719+
34720+
<li><var>origin</var> and <var>previousOrigin</var> are <span data-x="origin">origins</span>,
34721+
and <var>origin</var> is <span>same origin</span> with <var>previousOrigin</var></li>
34722+
</ul>
34723+
34724+
<p>then set <var>resource</var>'s <span data-x="media-resource-origin">origin</span> to
34725+
<var>origin</var>.</p>
34726+
34727+
<p>Otherwise, if <var>response</var> is <span>CORS-cross-origin</span>, then return false.</p>
34728+
34729+
<p>Otherwise, set <var>resource</var>'s <span data-x="media-resource-origin">origin</span> to
34730+
"<code data-x="">multiple</code>".</p>
34731+
34732+
<p class="note">This ensures that opaque responses with range headers do not leak information
34733+
by being patched together with other responses from different origins.</p>
34734+
</li>
34735+
34736+
<li><p>Let (<var>start</var>, <var>end</var>) be the result of
34737+
<span data-x="extract content-range values">extracting content-range values</span> from
34738+
<var>internalResponse</var>.</p></li>
34739+
34740+
<li><p>If <var>start</var> is not <var>byteRange</var>[0], or if
34741+
<var>byteRange</var>[1] is neither "<code data-x="">until end</code>" or <var>end</var>,
34742+
return false.</p></li>
34743+
34744+
<li><p>Return true.</p></li>
34745+
</ol>
34746+
3467634747
<p>The <dfn data-x="concept-media-load-resource" export>resource fetch algorithm</dfn> for a
3467734748
<span>media element</span> and a given <span>URL record</span> or <span>media provider
3467834749
object</span> is as follows:</p>
@@ -34736,28 +34807,91 @@ interface <dfn interface>MediaError</dfn> {
3473634807
</ol>
3473734808
</li>
3473834809

34810+
<li><p>Let <var>destination</var> be "<code data-x="">audio</code>" if the <span>media
34811+
element</span> is an <code>audio</code> element, or "<code data-x="">video</code>"
34812+
otherwise.</p>
34813+
34814+
<li><p>Let <var>request</var> be the result of <span
34815+
data-x="create a potential-CORS request">creating a potential-CORS request</span> given
34816+
<var>current media resource</var>'s <span>URL record</span>, <var>destination</var>, and the
34817+
current state of <span>media element</span>'s
34818+
<code data-x="attr-script-crossorigin">crossorigin</code> content attribute.</p></li>
34819+
34820+
<li><p>Set <var>request</var>'s <span data-x="concept-request-client">client</span> to the
34821+
<span>media element</span>'s <span>node document</span>'s <span>relevant settings
34822+
object</span>.</p></li>
34823+
34824+
<li><p>Let <var>byteRange</var>, which is "<code data-x="">entire resource</code>" or a
34825+
(number, number or "<code data-x="">until end</code>") tuple, be the byte range required to satisfy
34826+
missing data in <span>media data</span>. This value is <span>implementation-defined</span>
34827+
and may rely on codec, network conditions or other heuristics. The user-agent may determine
34828+
to fetch the resource in full, in which case <var>byteRange</var> would be
34829+
"<code data-x="">entire resource</code>", to fetch from a byte offset until the end,
34830+
in which case <var>byteRange</var> would be
34831+
(number, "<code data-x="">until end</code>"), or to fetch a range between two byte offsets,
34832+
im which case <var>byteRange</var> would be a (number, number) tuple representing the two
34833+
offsets.</p></li>
34834+
3473934835
<li>
34740-
<p>Let <var>destination</var> be "<code data-x="">audio</code>" if the <span>media
34741-
element</span> is an <code>audio</code> element and to "<code data-x="">video</code>"
34742-
otherwise.</p>
34836+
<p>If <var>byteRange</var> is not "<code data-x="">entire resource</code>", then:</p>
34837+
<ol>
34838+
<li><p>If <var>byteRange</var>[1] is "<code data-x="">until end</code>" then
34839+
<span>add a range header</span> to <var>request</var> given
34840+
<var>byteRange</var>[0].</p></li>
3474334841

34744-
<p>Let <var>request</var> be the result of <span
34745-
data-x="create a potential-CORS request">creating a potential-CORS request</span> given
34746-
<var>current media resource</var>'s <span>URL record</span>, <var>destination</var>, and the
34747-
<span>media element</span>'s <code data-x="attr-media-crossorigin">crossorigin</code>
34748-
content attribute value.
34842+
<li><p>Otherwise, <span>add a range header</span> to <var>request</var> given
34843+
<var>byteRange</var>[0] and <var>byteRange</var>[1].</p></li>
34844+
</ol>
34845+
</li>
3474934846

34750-
<p>Set <var>request</var>'s <span data-x="concept-request-client">client</span> to the
34751-
<span>media element</span>'s <span>node document</span>'s <span>relevant settings
34752-
object</span>.</p>
34847+
<li>
34848+
<!--FETCH--><p><span data-x="concept-fetch">Fetch</span> <var>request</var>, with
34849+
<i data-x="process response">processResponse</i> set to the following steps given
34850+
<span data-x="concept-response">response</span> <var>response</var>:</p>
3475334851

34754-
<!--FETCH--><p><span data-x="concept-fetch">Fetch</span> <var>request</var>.</p>
34852+
<ol>
34853+
<li><p>Let <var>global</var> be the <span>media element</span>'s
34854+
<span>node document</span>'s <span>relevant global object</span>.</p></li>
34855+
34856+
<li><p>Let <var>updateMedia</var> be to <span>queue a media element task</span> given
34857+
the <span>media element</span> to run the first appropriate steps from the
34858+
<span>media data processing steps list</span> below. (A new task is used for
34859+
this so that the work described below occurs relative to the appropriate
34860+
<span>media element event task source</span> rather than using the
34861+
<span>networking task source</span>.)</p>
34862+
34863+
<li><p>Let <var>finalize</var> be to <span>finalize and report timing</span> with
34864+
<var>response</var>, <var>global</var>, and <var>destination</var>, and call
34865+
<var>updateMedia</var>.</p></li>
34866+
34867+
<li>
34868+
<p>Let <var>processEndOfMedia</var> be the following steps:</p>
34869+
34870+
<ol>
34871+
<li><p>Call <var>finalize</var>.</p>
34872+
34873+
<li><p>If the fetching process has completes without errors, including decoding the
34874+
media data, and if all of the data is available to the user agent without network
34875+
access, then, the user agent must move on to the <i>final step</i> below.
34876+
This might never happen, e.g. when streaming an infinite resource such as web radio, or
34877+
if the resource is longer than the user agent's ability to cache data.</p>
34878+
</ol>
34879+
</li>
3475534880

34756-
<p>The <var>response</var>'s <span>unsafe response</span> obtained in this fashion, if any,
34757-
contains the <span>media data</span>. It can be <span>CORS-same-origin</span> or
34758-
<span>CORS-cross-origin</span>; this affects whether subtitles referenced in the <span>media
34759-
data</span> are exposed in the API and, for <code>video</code> elements, whether a
34760-
<code>canvas</code> gets tainted when the video is drawn on it.</p>
34881+
<li><p>If the result of <span data-x="verify a media response">verifying</span>
34882+
<var>response</var> given the <var>current media resource</var> and
34883+
<var>byteRange</var> is false, then call <var>finalize</var>. Otherwise,
34884+
<span data-x="body-incrementally-read">incrementally read</span> <var>response</var>'s
34885+
<span data-x="concept-response-body">body</span> given <var>updateMedia</var>,
34886+
<var>processEndOfMedia</var>, <var>finalize</var>, and <var>global</var>.</p></li>
34887+
34888+
<li><p>Update the <span>media data</span> with the contents of <var>response</var>'s
34889+
<span>unsafe response</span> obtained in this fashion. <var>response</var> can be
34890+
<span>CORS-same-origin</span> or <span>CORS-cross-origin</span>; this affects whether
34891+
subtitles referenced in the <span>media data</span> are exposed in the API and, for
34892+
<code>video</code> elements, whether a<code>canvas</code> gets tainted when the video is
34893+
drawn on it.</p></li>
34894+
</ol>
3476134895

3476234896
<p>The <dfn export id="stall-timeout">media element stall timeout</dfn> is an
3476334897
<span>implementation-defined</span> length of time, which should be about three seconds.
@@ -34800,11 +34934,11 @@ interface <dfn interface>MediaError</dfn> {
3480034934
element's <span>delaying-the-load-event flag</span> to false. This stops <span data-x="delay
3480134935
the load event">delaying the load event</span>.</p>
3480234936

34803-
<p>The user agent may use whatever means necessary to fetch the resource (within the constraints
34804-
put forward by this and other specifications); for example, reconnecting to the server in the
34805-
face of network errors, using HTTP range retrieval requests, or switching to a streaming
34806-
protocol. The user agent must consider a resource erroneous only if it has given up trying to
34807-
fetch it.</p>
34937+
<p>Although the above steps give an algorithm for issuing requests, the user agent may use
34938+
other means besides those exact ones, especially in the face of error conditions. For
34939+
example, the user agent may reconnect to the server or switch to a streaming protocol. The
34940+
user agent must only consider the resource erroneous, and proceed into the error branches
34941+
of the above steps, if the user agent has given up trying to fetch the resource.</p>
3480834942

3480934943
<p>To determine the format of the <span>media resource</span>, the user agent must use the
3481034944
<span data-x="Content-Type sniffing: video">rules for sniffing audio and video specifically</span>.</p>
@@ -34814,21 +34948,6 @@ interface <dfn interface>MediaError</dfn> {
3481434948
given the <span>media element</span> to <span data-x="concept-event-fire">fire an
3481534949
event</span> named <code data-x="event-media-progress">progress</code> at the element.</p>
3481634950

34817-
<p>The <span>networking task source</span> <span data-x="concept-task">tasks</span> to
34818-
process the data as it is being fetched must each <span>immediately</span> <span>queue a
34819-
media element task</span> given the <span>media element</span> to run the first appropriate
34820-
steps from the <span>media data processing steps list</span> below. (A new task is used for
34821-
this so that the work described below occurs relative to the appropriate <span>media element
34822-
event task source</span> rather than using the <span>networking task source</span>.)</p>
34823-
34824-
<p>When the <span>networking task source</span> has <span data-x="queue a
34825-
task">queued</span> the last <span data-x="concept-task">task</span> as part of fetching the
34826-
<span>media resource</span> (i.e. once the download has completed), if the fetching process
34827-
completes without errors, including decoding the media data, and if all of the data is available
34828-
to the user agent without network access, then, the user agent must move on to the <i>final step</i> below.
34829-
This might never happen, e.g. when streaming an infinite resource such as web radio, or if the
34830-
resource is longer than the user agent's ability to cache data.</p>
34831-
3483234951
<p>While the user agent might still need network access to obtain parts of the <span>media
3483334952
resource</span>, the user agent must remain on this step.</p>
3483434953

0 commit comments

Comments
 (0)