1. Introduction
A service worker is capable of fetching and caching assets, the size of which is restricted only by origin storage. However, if the user navigates away from the site or closes the browser, the service worker is likely to be killed. This can happen even if there’s a pending promise passed to waitUntil()
- if it hasn’t resolved within a few minutes the browser may consider it an abuse of service worker and kill the process.
This is excellent for battery and privacy, but it makes it difficult to download and cache large assets such as podcasts and movies, and upload video and images.
This specification aims to:
-
Allow fetches (requests & responses) to continue even if the user closes all windows & workers to the origin.
-
Allow a single job to involve many requests, as defined by the app.
-
Allow the browser/OS to show UI to indicate the progress of that job, and allow the user to pause/abort.
-
Allow the browser/OS to deal with poor connectivity by pausing/resuming the download.
-
Allow the app to react to success/failure of the job, perhaps by caching the results.
-
Allow access to background-fetched resources as they fetch.
2. Realms
All platform objects are created in the context object's relevant Realm unless otherwise specified.
3. Infrastructure
A resource is considered temporarily unavailable if the user agent believes the resource may soon become available. Reasons may include:
-
The user agent is offline.
-
The user agent is behind a captive portal.
The background fetch task source is a task source.
3.1. Extensions to service worker registration
A service worker registration additionally has:
-
Active background fetches (a map), where each key is a DOMString, and each item is a background fetch. It is initially an empty map.
-
An active background fetches edit queue (a parallel queue), initially the result of starting a new parallel queue.
3.2. Background fetch
A background fetch consists of:
-
An id (a DOMString).
-
Records (a list of background fetch records).
-
A title (a DOMString).
-
A download total (a number).
-
An upload total (a number).
-
A uploaded (a number), initially 0.
-
A result (a
BackgroundFetchResult
), initially the empty string. -
A failure reason (a
BackgroundFetchFailureReason
), initially the empty string. -
A records available flag initially set.
-
Icons (a list of
ImageResource
s). -
A service worker registration (a service worker registration).
-
A update handling queue (a parallel queue), initially the result of starting a new parallel queue.
-
A paused flag, initially unset.
-
A abort all flag, initially unset.
-
Let total be 0.
-
For each record of bgFetch’s records:
-
Increment total by the length of record’s response data's bytes.
-
-
Return total.
3.2.1. Display
-
The UI must prominently display the bgFetch’s service worker registration's scope url's origin
-
If the bgFetch’s paused flag is unset, and bgFetch’s result is not the empty string, then the UI must indicate that bandwidth is being used.
-
The UI cannot be dismissed without aborting (e.g. swiped away) until bgFetch’s result is not the empty string.
-
The UI may display bgFetch’s title.
-
The UI may select an image resource (icon) for display from bgFetch’s icons, after successfully processing it, and fetch it using a new request with the following properties:
- URL
-
icon’s src.
- Client
-
environment.
- Keepalive flag
-
Set.
- Service-workers mode
-
"
none
". - Destination
-
"
image
". - Mode
-
"
no-cors
". - Credentials mode
-
"
include
".
-
The UI may use bgFetch’s download total, upload total, stored body bytes total, uploaded, paused flag, and result to present the progress of the fetch.
-
The UI must provide a way for the user to abort the bgFetch by setting bgFetch’s abort all flag.
-
If every request in bgFetch’s records has the method `
GET
`, the UI may provide a way to toggle bgFetch’s paused flag.Note: If a method is not `
GET
`, reissuing the request may have unwanted side effects. -
The UI may be activated (for example, by clicking), in which case fire a background fetch click event for bgFetch.
-
The UI may remain once the operation is complete, in which case it can still be activated.
Let permission be the permission state for a PermissionDescriptor
with name
"background-fetch"
and environment. If permission is "prompt"
, then the user agent may set bgFetch’s paused flag at the beginning of this algorithm. The user agent should allow the user to either accept the background fetch (unsetting bgFetch’s paused flag), or refuse the background fetch (setting bgFetch’s abort all flag). The user agent may also provide always-allow and alway-deny options, which can be used as new information about the user’s intent for this permission.
The user agent may also consider setting bgFetch’s paused flag if the user is on a metered connection, or the background fetch was started in the background.
3.3. Background fetch record
A background fetch record consists of:
-
A request (a request).
-
A response data (a background fetch response), initially a new background fetch response.
3.4. Background fetch response
A Background fetch response consists of:
-
A response (a response or null), initially null.
-
Bytes (a byte sequence), initially an empty byte sequence.
-
A result, (any
BackgroundFetchFailureReason
,"success"
, or"redundant"
), initially the empty string.
The response can be exposed if the result is the empty string, "success"
, or "bad-status"
.
4. Algorithms
4.1. Perform a background fetch
Note: This is the algorithm that manages the 'background' parts of a background fetch. Only one instance of this algorithm runs per background fetch.
-
Let swRegistration be bgFetch’s service worker registration.
-
Let settledFetches be 0.
-
Let immediateFailure be false.
-
Let failureReason be the empty string.
-
For each record in bgFetch’s records, run these steps in parallel:
-
Complete a record for bgFetch and record.
-
Let result be record’s response data's result.
-
If failureReason is not the empty string:
-
Assert: result is not
"redundant"
. -
Set failureReason to result.
-
-
Increment settledFetches by 1.
-
If result is
"download-total-exceeded"
, then set immediateFailure to true.
-
-
Wait for settledFetches to be bgFetch’s records's size, or immediateFailure to be true.
-
If immediateFailure is true, set bgFetch’s abort all flag.
Note: The complete a record algorithm listens to this flag and terminates the fetch when set.
-
Enqueue the following steps to swRegistration’s active background fetches edit queue:
-
Let activeBgFetches be swRegistration’s active background fetches.
-
Let id be bgFetch’s id.
-
If activeBgFetches contains background fetch bgFetch, then remove activeBgFetches[id].
-
Otherwise, set failureReason to
"aborted"
.Note: This handles a race condition where
abort()
was successfully called but one of the fetches failed at the same time. If we’ve returned true fromabort()
, this ensures we fire the related abort event. -
If failureReason is not the empty string, then:
-
Set bgFetch’s result to
"failure"
. -
Set bgFetch’s failure reason to failureReason.
-
-
Otherwise, set bgFetch’s result to
"success"
. -
Update background fetch instances for bgFetch.
-
Let eventName be the empty string.
-
Let eventConstructor be null.
-
If failureReason is
"aborted"
, then:-
Set eventName to "
backgroundfetchabort
". -
Set eventConstructor to
BackgroundFetchEvent
.
-
-
Otherwise, if failureReason is not the empty string, then:
-
Set eventName to "
backgroundfetchfail
". -
Set eventConstructor to
BackgroundFetchUpdateUIEvent
.
-
-
Otherwise:
-
Set eventName to "
backgroundfetchsuccess
". -
Set eventConstructor to
BackgroundFetchUpdateUIEvent
.
-
-
Fire a functional event named eventName using eventConstructor on swRegistration with the following properties:
registration
-
The result of getting a BackgroundFetchRegistration instance for bgFetch in the event object’s relevant Realm.
Then run these steps with dispatchedEvent in parallel:
-
Wait until dispatchedEvent is not active.
-
Unset bgFetch’s records available flag.
-
Update background fetch instances for bgFetch.
-
4.2. Complete a record
Note: This algorithm manages the fetching of a background fetch record. One instance of this algorithm is started per background fetch record, but it is called recursively to retry fetches or to fetch the next part of a partial response.
-
Let responseData be record’s response data.
-
Let downloadTotal be bgFetch’s download total if it is not 0, otherwise infinity.
-
Wait for bgFetch’s paused flag to be unset.
-
Let request be a copy of record’s request.
Note: At this point the request is entirely held in storage, even if it started as a stream.
-
Set request’s keepalive flag.
-
Set request’s service-workers mode to "
none
". -
If rangeStart is not 0, then add a range header to request with rangeStart.
Note: If the rangeStart is 0, a normal request is made. This allows the initial request to make use of content encoding, since
Accept-Encoding: identity
is added to requests with a range header. -
Let fetchAttemptComplete be false.
-
Let lastTransmittedSize be 0.
-
Fetch request.
The remainder of this step uses fetch "callbacks" which currently queue tasks. This isn’t desirable or possible here, so let’s pretend that tasks aren’t queued. (issue)
To process request body for request, run these steps:
-
Let transmittedSize be request’s body's transmitted bytes.
-
Increment bgFetch’s uploaded by transmittedSize minus lastTransmittedSize.
-
Set lastTransmittedSize to transmittedSize.
-
Update background fetch instances for bgFetch.
To process response for response, run these steps:
-
If response is a network error, then:
-
If the resource is temporarily unavailable and request’s method is `
GET
`, then wait until the resource is not temporarily unavailable, then set fetchAttemptComplete to true and abort these steps.Note: If request’s method is not `
GET
`, reissuing the request may have unwanted side effects. If a standard method to resume requests becomes available, it’ll be adopted here. -
If response is an aborted network error, then set responseData’s result to
"aborted"
, otherwise"fetch-error"
. -
Set fetchAttemptComplete to true, and abort these steps.
-
-
If response’s status is
206
, then:-
If validate a partial response for rangeStart, response, and responseData’s response returns invalid, then:
-
-
Otherwise:
-
Set responseData’s result to
"redundant"
. -
Set responseData to a new background fetch response.
-
Set record’s response data to responseData.
Note: The create record objects algorithm may hold a reference to the previous background fetch response.
-
Update background fetch instances for bgFetch.
-
-
If rangeStart is 0 or response’s status is not
206
, then set responseData’s response to a copy of response except for its body. -
Whenever one or more bytes are transmitted from stream, let bytes be the transmitted bytes and run these steps:
-
If bgFetch’s stored body bytes total plus the size of bytes is greater than downloadTotal, then:
-
Append bytes to responseData’s bytes.
-
If the previous step fails due to exceeding a quota limit, set responseData’s result to
"quota-exceeded"
, fetchAttemptComplete to true, and abort these steps. -
Update background fetch instances for bgFetch.
-
-
If at any point the bytes transmission for stream is done normally, then:
-
If response’s status is
206
, then:-
Let firstBytePos, lastBytePos, and completeLength be the result of extracting content-range values from response.
-
If completeLength is not null, and equal to the length of responseData’s bytes, set responseData’s result to
"success"
.Note: Although we ask for the whole resource, or the remainder of the resource, the server may not have returned the remainder, in which case we need to make an additional request.
-
-
Otherwise, if response’s status is not an ok status, set responseData’s result to
"bad-status"
. -
Otherwise, set responseData’s result to
"success"
. -
Set fetchAttemptComplete to true.
-
-
If at any point stream becomes errored, then:
-
If the resource is temporarily unavailable and request’s method is `
GET
`, then wait until the resource is not temporarily unavailable, then set fetchAttemptComplete to true. -
Otherwise, set responseData’s result to
"fetch-error"
and fetchAttemptComplete to true.
-
-
-
Let result be the empty string.
-
Run these steps, but abort when bgFetch’s paused flag or abort all flag is set:
-
Wait for fetchAttemptComplete to be true.
-
Set result to responseData’s result.
-
-
If aborted, then:
-
If bgFetch’s paused flag is set, then assert request’s method is `
GET
`. -
If bgFetch’s abort all flag is set, then set responseData’s result to
"aborted"
. -
Set result to responseData’s result.
Note: The result is stored now, as terminating the fetch may change the result.
-
Terminate the ongoing fetch.
-
-
If result is the empty string, then complete a record for bgFetch and record.
4.3. Update background fetch instances
-
Let downloaded be bgFetch’s stored body bytes total.
-
Let uploaded be bgFetch’s uploaded.
-
Let result be bgFetch’s result.
-
Let failureReason be bgFetch’s failure reason.
-
Let recordsAvailable be true if bgFetch’s records available flag is set, otherwise false.
-
For each environment settings object env whose origin is equal to bgFetch’s service worker registration's scope URL's origin, queue a bgfetch task on env’s responsible event loop to run these steps:
-
Let bgFetchRegistration be the instance of
BackgroundFetchRegistration
within the relevant realm whose background fetch is equal to bgFetch, or null if none exists.Note: There will be at most one per environment, due to the get a BackgroundFetchRegistration instance algorithm.
-
If bgFetchRegistration is null, then abort these steps.
-
If recordsAvailable is false and bgFetchRegistration’s records available flag is set, then unset bgFetchRegistration’s records available flag.
-
If bgFetchRegistration’s result is not the empty string, then abort these steps.
Note: This prevents progress being reported after the background fetch has settled. This is possible when the operation has aborted, but some fetches haven’t yet terminated.
-
If all of the following are true:
-
bgFetchRegistration’s downloaded is equal to downloaded.
-
bgFetchRegistration’s uploaded is equal to uploaded.
-
bgFetchRegistration’s result is equal to result.
-
bgFetchRegistration’s failure reason is equal to failureReason.
Then abort these steps.
-
-
Set bgFetchRegistration’s downloaded to downloaded.
-
Set bgFetchRegistration’s uploaded to uploaded.
-
Set bgFetchRegistration’s result to result.
-
Set bgFetchRegistration’s failure reason to failureReason.
-
Fire an event named "
progress
" at bgFetchRegistration.
I need to debounce this similar to how mouse move events debounce.
-
4.4. Fire a background fetch click event
backgroundfetchclick
" using BackgroundFetchEvent
on bgFetch’s service worker registration with the following properties:
registration
-
The result of getting a BackgroundFetchRegistration instance for bgFetch in the event object’s relevant Realm.
4.5. Get a BackgroundFetchRegistration instance
Note: This algorithm ensures the same BackgroundFetchRegistration
instance is returned for a given background fetch throughout the life of a BackgroundFetchManager
. It’s okay for browsers to optimise this, as long as there’s no way to tell that more than one instance has been created for a given background fetch (e.g. through equality, expandos, or weakly-associated data).
-
Let instancesMap be the BackgroundFetchRegistration instances of the only instance of
BackgroundFetchManager
within this realm. -
If instancesMap[bgFetch] exists, then return instancesMap[bgFetch].
-
Let instance be a new
BackgroundFetchRegistration
in realm, with its background fetch set to bgFetch. -
Set instancesMap[bgFetch] to instance.
-
Return instance.
4.6. Validate a partial response
Note: This algorithm checks if a partial response reasonably matches what was requested, and optionally checks if it should be combined with a previous response.
-
Assert: partialResponse’s status is
206
. -
Let responseFirstBytePos, responseLastBytePos, and responseCompleteLength be the result of extracting content-range values from partialResponse. If this fails, then return invalid.
-
If responseFirstBytePos does not equal expectedRangeStart, then return invalid.
-
If previousResponse is not null, then:
-
For headerName of « `
ETag
`, `Last-Modified
` »:-
If previousResponse’s header list contains headerName and the combined value of headerName in previousResponse’s header list does not equal the combined value of headerName in partialResponse’s header list, then return invalid.
-
-
If previousResponse’s status is
206
, then:-
Let previousResponseFirstBytePos, previousResponseLastBytePos, and previousResponseCompleteLength be the result of extracting content-range values from previousResponse. If this fails, then return invalid.
-
If previousResponseCompleteLength is not null, and responseCompleteLength does not equal previousResponseCompleteLength, then return invalid.
-
-
-
Return valid.
4.7. Extract content-range values
Note: This algorithm parses `Content-Range
` as a single byte content-range and extracts the values.
-
If response’s header list does not contain `
Content-Range
`, then return failure. -
Let contentRangeValue be the value of the first header whose name is a byte-case-insensitive match for `
Content-Range
` in response’s header list. -
If parsing contentRangeValue per single byte content-range fails, then return failure.
-
Let firstBytePos be the portion of contentRangeValue named
first-byte-pos
when parsed as single byte content-range, parsed as an integer. -
Let lastBytePos be the portion of contentRangeValue named
last-byte-pos
when parsed as single byte content-range, parsed as an integer. -
Let completeLength be the portion of contentRangeValue named
complete-length
when parsed as single byte content-range. -
If completeLength is
"*"
, then set completeLength to null, otherwise set completeLength to completeLength parsed as an integer. -
Return firstBytePos, lastBytePos, and completeLength.
Parsing as an integer infra/189.
4.8. Create record objects
Note: This algorithm creates platform objects for background fetch records. It also manages the streaming of the response from the stored bytes. The background fetch operation may still be in progress at this point.
All platform objects must be created in realm.
-
Let recordObjects be a new list.
-
For each record of records:
-
Let responseData be record’s response data.
-
Let recordObject be a new
BackgroundFetchRecord
. -
Set recordObject’s
responseReady
to a new promise. -
Let requestObject be a new
Request
object with the following set: -
Set recordObject’s
request
to requestObject. -
Let transmittedBytes be 0.
-
Let stream be a new readable stream with a pull action that returns a new promise promise and runs these steps in parallel:
-
Wait for the length of responseData’s bytes to be greater than transmittedBytes, or responseData’s result not to be the empty string.
-
Let bytes be null.
-
If the length of responseData’s bytes is greater than transmittedBytes and responseData may be exposed, then:
-
Queue a task in stream’s relevant settings object's responsible event loop using the networking task source to run these steps:
-
If bytes is not null, then:
-
Let array be a new
Uint8Array
wrapping a newArrayBuffer
of bytes. -
Enqueue array into stream.
-
-
If responseData may be exposed, responseData’s result is not the empty string, and transmittedBytes is the length of responseData’s bytes, then close stream.
-
Otherwise, if responseData’s result is
"aborted"
, then error stream with anAbortError
DOMException
. -
Otherwise, if responseData may not be exposed, then error stream with a
TypeError
. -
Resolve promise.
-
-
-
Run these steps in parallel:
-
Wait for responseData’s response to not be not-null.
-
If responseData may be exposed, then:
-
Let response be a copy of responseData’s response.
-
Delete `
Content-Range
` from response’s header list. -
Delete `
Content-Length
` from response’s header list. -
Set response’s body to body.
-
Queue a task in recordObject’s relevant settings object's responsible event loop using the networking task source to run these steps:
-
Let responseObject be a new
Response
object with the following set: -
Resolve recordObject’s
responseReady
with responseObject.
-
-
-
Otherwise, if responseData’s result is
"aborted"
, then reject recordObject’sresponseReady
with anAbortError
DOMException
. -
Otherwise, reject recordObject’s
responseReady
with aTypeError
.
-
-
Append recordObject to recordObjects.
-
-
Return recordObjects.
4.9. Contains background fetch
-
If map contains background fetch bgFetch, then return false.
-
Return true.
5. Header syntax
The following is HTTP ABNF for a single byte content-range:
"bytes=" first-byte-pos "-" last-byte-pos "/" complete-length first-byte-pos = 1*DIGIT last-byte-pos = 1*DIGIT complete-length = ( 1*DIGIT / "*" )
Note: This is a subset of what RFC 7233 allows.
The above as a railroad diagram:
6. API
6.1. Extensions to ServiceWorkerGlobalScope
partial interface ServiceWorkerGlobalScope {attribute EventHandler ;
onbackgroundfetchsuccess attribute EventHandler ;
onbackgroundfetchfail attribute EventHandler ;
onbackgroundfetchabort attribute EventHandler ; };
onbackgroundfetchclick
6.1.1. Events
The following is the event handler (and its corresponding event handler event type) that must be supported, as event handler IDL attributes, by all objects implementing ServiceWorker
interface:
event handler event type | event handler | Interface |
---|---|---|
backgroundfetchsuccess
| onbackgroundfetchsuccess
| BackgroundFetchUpdateUIEvent
|
backgroundfetchfail
| onbackgroundfetchfail
| BackgroundFetchUpdateUIEvent
|
backgroundfetchabort
| onbackgroundfetchabort
| BackgroundFetchEvent
|
backgroundfetchclick
| onbackgroundfetchclick
| BackgroundFetchEvent
|
6.2. Extensions to ServiceWorkerRegistration
partial interface ServiceWorkerRegistration {readonly attribute BackgroundFetchManager backgroundFetch ; };
A ServiceWorkerRegistration
has a background fetch manager (a BackgroundFetchManager
), initially a new BackgroundFetchManager
whose service worker registration is the context object's service worker registration.
The backgroundFetch
attribute’s getter must return the context object's background fetch manager.
6.3. BackgroundFetchManager
[Exposed =(Window ,Worker )]interface {
BackgroundFetchManager Promise <BackgroundFetchRegistration >fetch (DOMString , (
id RequestInfo or sequence <RequestInfo >),
requests optional BackgroundFetchOptions = {});
options Promise <BackgroundFetchRegistration ?>get (DOMString );
id Promise <sequence <DOMString >>getIds (); };dictionary {
BackgroundFetchUIOptions sequence <ImageResource >;
icons DOMString ; };
title dictionary :
BackgroundFetchOptions BackgroundFetchUIOptions {unsigned long long = 0; };
downloadTotal
A BackgroundFetchManager
has:
-
BackgroundFetchRegistration instances (a map), where the keys are background fetches and the values are
BackgroundFetchRegistration
objects. It is initially an empty map. -
A service worker registration (a service worker registration).
6.3.1. fetch()
fetch(id, requests, options)
method, when invoked, run these steps:
-
Let registration be the context object's service worker registration.
-
Let records be a new list.
-
Let uploadTotal be 0.
-
If requests is a
RequestInfo
, set requests to « requests ». -
If requests is empty, then return a promise rejected with a
TypeError
. -
For each request of requests:
-
Let internalRequest be the request of the result of invoking the
Request
constructor with request. If this throws an exception, return a promise rejected with the exception. -
If internalRequest’s mode is "
no-cors
", then return a promise rejected with aTypeError
. -
Set internalRequest’s client to null.
-
Let record be a new background fetch record.
-
Set record’s request to internalRequest.
-
Append record to records.
-
-
Let promise be a new promise.
-
Enqueue the following steps to registration’s active background fetches edit queue:
-
Let permission be the permission state for a
PermissionDescriptor
withname
"background-fetch"
, and the context object's relevant settings object. -
If permission is
"denied"
, then reject promise with aNotAllowedError
DOMException
and abort these steps. -
Let bgFetchMap be registration’s active background fetches.
-
If registration’s active worker is null, then reject promise with a
TypeError
and abort these steps. -
If bgFetchMap[id] exists, reject promise with a
TypeError
and abort these steps. -
Let requestBodiesRemaining be the size of requests.
-
Let requestReadFailed be false.
-
For each request of requests:
-
Run these steps in parallel:
-
Run these steps but abort when requestReadFailed is true:
Note: This ensures we have a copy of the request bytes before resolving.
-
If aborted and stream is readable, then error stream with an
AbortError
DOMException
and abort these steps. -
Increment uploadTotal by request’s body's total bytes.
-
Decrement requestBodiesRemaining by 1.
-
-
If at any point storing requests fails due to exceeding a quota limit, reject promise with a
QuotaExceededError
DOMException
and abort these steps. -
Wait for requestBodiesRemaining to be 0, or requestReadFailed to be true.
-
If requestReadFailed is true, then reject promise with a
TypeError
and abort these steps. -
Let bgFetch be a new background fetch with:
- id
-
id.
- records
-
records.
- download total
-
options’
downloadTotal
member. - upload total
-
uploadTotal.
- icons
-
options’
icons
member if present, otherwise an empty list. - title
-
options’
title
member if present, otherwise the empty string. - service worker registration
-
registration.
-
Set bgFetchMap[id] to bgFetch.
-
Queue a bgfetch task to run these steps:
-
Resolve promise with the result of getting a BackgroundFetchRegistration instance for bgFetch in the context object's relevant Realm.
-
-
In parallel, display bgFetch from the context object's relevant settings object.
-
In parallel, perform a background fetch with bgFetch.
-
-
Return promise.
6.3.2. get()
get(id)
method, when invoked, must return a new promise promise and run these steps in parallel:
-
Let registration be the context object's associated service worker registration.
-
Let bgFetch be registration’s active background fetches[id].
-
If bgFetch is undefined, then resolve promise with undefined and abort these steps.
-
Enqueue the following steps to bgFetch’s update handling queue:
-
Queue a bgfetch task task to run these steps:
-
Let bgFetchRegistration be the result of getting a BackgroundFetchRegistration instance for bgFetch in the context object's relevant Realm.
-
Resolve promise with bgFetchRegistration.
-
-
Wait for task to complete.
Note: This ensures the potential new instance of
BackgroundFetchRegistration
doesn’t miss anyprogress
events.
-
6.3.3. getIds()
getIds()
method, when invoked, must return a new promise promise and run these steps in parallel:
-
Let registration be the context object's associated service worker registration.
-
Resolve promise with the result of getting the keys of registration’s active background fetches.
6.4. BackgroundFetchRegistration
[Exposed =(Window ,Worker )]interface :
BackgroundFetchRegistration EventTarget {readonly attribute DOMString id ;readonly attribute unsigned long long uploadTotal ;readonly attribute unsigned long long uploaded ;readonly attribute unsigned long long downloadTotal ;readonly attribute unsigned long long downloaded ;readonly attribute BackgroundFetchResult result ;readonly attribute BackgroundFetchFailureReason failureReason ;readonly attribute boolean recordsAvailable ;attribute EventHandler onprogress ;Promise <boolean >abort ();Promise <BackgroundFetchRecord >match (RequestInfo ,
request optional CacheQueryOptions = {});
options Promise <sequence <BackgroundFetchRecord >>matchAll (optional RequestInfo ,
request optional CacheQueryOptions = {}); };
options enum {
BackgroundFetchResult ,
"" ,
"success" };
"failure" enum { // The background fetch has not completed yet, or was successful.
BackgroundFetchFailureReason , // The operation was aborted by the user, or abort() was called.
"" , // A response had a not-ok-status.
"aborted" , // A fetch failed for other reasons, e.g. CORS, MIX, an invalid partial response, // or a general network failure for a fetch that cannot be retried.
"bad-status" , // Storage quota was reached during the operation.
"fetch-error" , // The provided downloadTotal was exceeded.
"quota-exceeded" };
"download-total-exceeded"
A BackgroundFetchRegistration
instance has:
-
A background fetch (a background fetch).
-
A downloaded (a number), initially a copy of background fetch's stored body bytes total.
-
A uploaded (a number), initially a copy of background fetch's uploaded.
-
A result (a
BackgroundFetchResult
), initially a copy of background fetch's result. -
A failure reason (a
BackgroundFetchFailureReason
), initially a copy of background fetch's failure reason. -
An id (a number), a copy of background fetch's id.
-
An upload total (a number), a copy of background fetch's upload total.
-
A download total (a number), a copy of background fetch's download total.
-
A records available flag initially set if background fetch's records available flag is set, otherwise unset.
Note: The above values are copied so they’re available synchronously.
The id
attribute’s getter must return the context object's id.
The uploadTotal
attribute’s getter must return the context object's upload total.
The downloadTotal
attribute’s getter must return the context object's download total.
The uploaded
attribute’s getter must return the context object's uploaded.
The downloaded
attribute’s getter must return the context object's downloaded.
The result
attribute’s getter must return the context object's result.
The failureReason
attribute’s getter must return the context object's failure reason.
The recordsAvailable
attribute’s getter must return true if the context object's records available flag is set, otherwise false.
6.4.1. Events
The onprogress
event handler has the event handler event type of progress
.
The progress
event uses the Event
interface.
6.4.2. abort()
abort()
method, when invoked, must return a new promise promise and run these steps in parallel:
-
Let bgFetch be the context object's associated background fetch.
-
Let swRegistration be bgFetch’s service worker registration.
-
Enqueue the following steps to swRegistration’s active background fetches edit queue:
-
Let activeBgFetches be swRegistration’s active background fetches.
-
Let id be bgFetch’s id.
-
If activeBgFetches does not contain background fetch bgFetch, then resolve promise with false and abort these steps.
-
Remove activeBgFetches[id].
-
Resolve promise with true.
-
Set bgFetch’s abort all flag.
-
6.4.3. match()
match(request, options)
method, when invoked, must run these steps:
-
Let promise be the result of calling the algorithm
matchAll()
passing request and options. -
Return the result of reacting to promise with a fulfilment handler that, when called with argument matches, returns matches[0].
Note: User agents are encouraged to optimise the above so it’s faster than calling matchAll()
.
6.4.4. matchAll()
matchAll(request, options)
method, when invoked, must run these steps:
-
If the context object's records available flag is unset, return a promise rejected with an
InvalidStateError
DOMException
. -
Let promise be a new promise.
-
Run these steps in parallel:
-
Let matchingRecords be an empty list.
-
For each record of context object's background fetch's records:
-
If request matches cached item for request, record’s request, record’s response data's response, and options returns true, then append record to matchingRecords.
-
-
Queue a bgfetch task to resolve promise with the result of creating record objects from matchingRecords in the context object's relevant Realm.
-
-
Return promise.
6.5. BackgroundFetchRecord
[Exposed =(Window ,Worker )]interface {
BackgroundFetchRecord readonly attribute Request request ;readonly attribute Promise <Response >responseReady ; };
BackgroundFetchRecord
has:
The request
attribute’s getter must return the context object's request.
The responseReady
attribute’s getter must return the context object's response promise.
6.6. BackgroundFetchEvent
[Exposed =ServiceWorker ]interface :
BackgroundFetchEvent ExtendableEvent {(
constructor DOMString ,
type BackgroundFetchEventInit );
init readonly attribute BackgroundFetchRegistration registration ; };dictionary :
BackgroundFetchEventInit ExtendableEventInit {required BackgroundFetchRegistration ; };
registration
BackgroundFetchEvent
has a background fetch (a background fetch), initially the background fetch of the value registration
was initialized to.
The registration
attribute must return the value it was initialized to.
6.7. BackgroundFetchUpdateUIEvent
[Exposed =ServiceWorker ]interface :
BackgroundFetchUpdateUIEvent BackgroundFetchEvent {(
constructor DOMString ,
type BackgroundFetchEventInit );
init Promise <undefined >updateUI (optional BackgroundFetchUIOptions = {}); };
options
A BackgroundFetchUpdateUIEvent
has an UI updated flag which is initially unset.
6.7.1. updateUI()
updateUI(options)
method, when invoked, must return a new promise promise and run these steps in parallel:
-
If any of the following is true:
-
The context object's
isTrusted
attribute is false. -
The context object's UI updated flag is set.
-
The context object is not active.
Throw an
InvalidStateError
DOMException
. -
-
Set the context object's UI updated flag.
-
If options is null, return.
-
Let bgFetch be the context object's background fetch.
-
If options’s
icons
member is present, set bgFetch’s icons to options’sicons
. -
If options’s
title
member is present, set bgFetch’s title to options’stitle
. -
Resolve promise.
7. Automation
For the purposes of user-agent automation and application testing, this document defines the following extension command for the [WebDriver] specification.
7.1. Click
Method | URI Template |
---|---|
POST | /session/{session id}/backgroundfetch/{id}/click |
The background fetch click extension command simulates the user activating the display of a background fetch. The remote end steps are:
-
If the current top-level browsing context is no longer open, then return a WebDriver error with WebDriver error code no such window.
-
Let pageURL be the current top-level browsing context's active document's URL.
-
Let swRegistration be the matching service worker registration for pageURL.
-
If swRegistration is null, then return a WebDriver error with status
400
and JSON error code "invalid service worker state
". -
Let bgFetch be the newest background fetch with an id of url variable id and a service worker registration of swRegistration, or null if none exists.
-
If bgFetch is null, then return a WebDriver error with status
404
and JSON error code "background fetch not found
". -
Fire a background fetch click event for bgFetch.
-
Return WebDriver success.
8. Privacy and bandwidth usage
Fetches can be large and take a long time to complete. During this time the user will be fetching data from one or more servers. The user’s IP address, which may change during the operation, could be used to track the user’s location over time.
To mitigate this, the steps for displaying a background fetch require:
-
Displaying the origin of the site making the fetch.
-
The UI cannot be dismissed while the background fetch is active.
-
Allowing the operation to be easily aborted.
-
Allowing the operation to start in a paused state, requiring user interaction to begin.
The steps also allow a user agent to pause the background fetch if the user is on a metered connection.
All data stored is associated with a particular service worker registration. Clearing a service worker registration will clear all associated background fetches.