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
ImageResources). -
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: identityis 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
BackgroundFetchRegistrationwithin 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
BackgroundFetchManagerwithin this realm. -
If instancesMap[bgFetch] exists, then return instancesMap[bgFetch].
-
Let instance be a new
BackgroundFetchRegistrationin 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-poswhen parsed as single byte content-range, parsed as an integer. -
Let lastBytePos be the portion of contentRangeValue named
last-byte-poswhen parsed as single byte content-range, parsed as an integer. -
Let completeLength be the portion of contentRangeValue named
complete-lengthwhen 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
responseReadyto a new promise. -
Let requestObject be a new
Requestobject with the following set: -
Set recordObjectâs
requestto 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
Uint8Arraywrapping a newArrayBufferof 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 anAbortErrorDOMException. -
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
Responseobject with the following set: -
Resolve recordObjectâs
responseReadywith responseObject.
-
-
-
Otherwise, if responseDataâs result is
"aborted", then reject recordObjectâsresponseReadywith anAbortErrorDOMException. -
Otherwise, reject recordObjectâs
responseReadywith 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
BackgroundFetchRegistrationobjects. 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
Requestconstructor 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
PermissionDescriptorwithname"background-fetch", and the context object's relevant settings object. -
If permission is
"denied", then reject promise with aNotAllowedErrorDOMExceptionand abort these steps. -
Let bgFetchMap be registrationâs active background fetches.
-
If registrationâs active worker is null, then reject promise with a
TypeErrorand abort these steps. -
If bgFetchMap[id] exists, reject promise with a
TypeErrorand 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
AbortErrorDOMExceptionand 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
QuotaExceededErrorDOMExceptionand abort these steps. -
Wait for requestBodiesRemaining to be 0, or requestReadFailed to be true.
-
If requestReadFailed is true, then reject promise with a
TypeErrorand abort these steps. -
Let bgFetch be a new background fetch with:
- id
-
id.
- records
-
records.
- download total
-
optionsâ
downloadTotalmember. - upload total
-
uploadTotal.
- icons
-
optionsâ
iconsmember if present, otherwise an empty list. - title
-
optionsâ
titlemember 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
BackgroundFetchRegistrationdoesnât miss anyprogressevents.
-
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
InvalidStateErrorDOMException. -
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
isTrustedattribute is false. -
The context object's UI updated flag is set.
-
The context object is not active.
Throw an
InvalidStateErrorDOMException. -
-
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
iconsmember is present, set bgFetchâs icons to optionsâsicons. -
If optionsâs
titlemember 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
400and 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
404and 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.