バックグラウンドフェッチ

コミュニティ グループ報告書草案、

このバージョン:
https://wicg.github.io/background-fetch/
課題の追跡:
GitHub
仕様内のインライン表示
編集者:
(Google)
(Google)

概要

ユーザーに可視性を提供しつつ、バックグラウンドで大規模なアップロード/ダウンロードを処理するための API。

この文書のステータス

この仕様は、Web Platform Incubator Community Group によって公開されました。 これは W3C 標準ではなく、W3C 標準化トラック上の文書でもありません。 W3C Community Contributor License Agreement (CLA) の下では、限定的なオプトアウトが認められており、その他の条件も適用されることに注意してください。 W3C Community and Business Groups について詳しく確認してください。

1. はじめに

サービスワーカーはアセットをフェッチしてキャッシュできます。そのサイズは、オリジン ストレージによってのみ制限されます。しかし、ユーザーがサイトから移動したりブラウザーを閉じたりすると、サービスワーカーは 終了される可能性があります。これは、waitUntil() に渡された保留中の promise がある場合でも発生する可能性があります。数分以内に解決されなければ、ブラウザーはこれをサービス ワーカーの悪用とみなし、プロセスを終了する可能性があります。

これはバッテリーとプライバシーにとって非常に優れていますが、ポッドキャストや映画などの大きなアセットをダウンロードしてキャッシュしたり、動画や画像をアップロードしたりすることを困難にします。

この仕様の目的は次のとおりです。

2. レルム

特に指定されていない限り、すべてのプラットフォームオブジェクトはコンテキストオブジェクトの関連するレルムで作成されます。

3. インフラストラクチャ

ユーザーエージェントがリソースを間もなく利用可能になる可能性があると判断した場合、そのリソースは一時的に利用不可とみなされます。理由には次のものが含まれます。

バックグラウンド フェッチタスクソースはタスク ソースです。

オプションの eventLoop (イベントループ。既定では呼び出し元のコンテキストオブジェクトの関連する設定オブジェクトの担当イベントループ)上で、steps(手順)を伴うbgfetch タスクをキューに入れるには、タスクをキューに入れることにより、eventLoop 上でバックグラウンドフェッチタスク ソースを使用して steps を実行します。

3.1. サービスワーカー登録への拡張

サービスワーカー登録は、さらに次を持ちます。

3.2. バックグラウンドフェッチ

バックグラウンドフェッチ は次から構成されます。

バックグラウンド フェッチ(bgFetch)の保存済みボディバイト 総量を取得するには、次の手順を実行します。
  1. total を 0 とします。

  2. bgFetch のレコードの各 record についてそれぞれ、次を行います。

    1. record のレスポンスデータのバイトの長さだけ total を増加させます。

  3. total を返します。

3.2.1. 表示

指定された environment(環境設定オブジェクト)についてバックグラウンドフェッチ(bgFetch)を表示するには、ユーザーエージェントは次の規則に従うユーザーインターフェイスを提示しなければなりません。

PermissionDescriptor の name が "background-fetch" であり、environment を持つ場合の許可状態を permission とします。permission が "prompt" の場合、ユーザーエージェントはこのアルゴリズムの開始時に bgFetch の一時停止フラグ を設定してもかまいません。ユーザーエージェントは、ユーザーがバックグラウンドフェッチを受け入れる(bgFetch の一時停止 フラグを未設定にする)か、バックグラウンドフェッチを拒否する(bgFetch のすべて中止 フラグを設定する)かを選択できるようにするべきです。ユーザーエージェントは常に許可および常に拒否するオプションを提供してもかまいません。これらは、この許可に関するユーザーの意図に関する新しい情報として使用できます。

ユーザーが従量制接続を使用している場合、またはバックグラウンドフェッチがバックグラウンドで開始された場合、ユーザーエージェントは bgFetch の一時停止フラグ を設定することも検討してもかまいません。

3.3. バックグラウンドフェッチレコード

バックグラウンドフェッチ レコードは次から構成されます。

3.4. バックグラウンドフェッチレスポンス

バックグラウンドフェッチ レスポンスは次から構成されます。

レスポンスは、結果が 空文字列、"success"、または "bad-status" の場合、公開できます。

4. アルゴリズム

4.1. バックグラウンドフェッチを実行する

注: これは、バックグラウンドフェッチの「バックグラウンド」部分を管理するアルゴリズムです。 バックグラウンドフェッチごとに、このアルゴリズムのインスタンスは 1 つだけ実行されます。

bgFetch(バックグラウンドフェッチ)についてバックグラウンド フェッチを実行するには、次の手順を実行します。
  1. swRegistration を bgFetch のサービスワーカー登録とします。

  2. settledFetches を 0 とします。

  3. immediateFailure を false とします。

  4. failureReason を空文字列とします。

  5. bgFetch のレコード内の各 record についてそれぞれ、次の手順を並列に実行します。

    1. bgFetch と record についてレコードを 完了する。

    2. result を record のレスポンスデータの結果とします。

    3. failureReason が空文字列でない場合:

      1. 表明: result は "redundant" ではない。

      2. failureReason を result に設定します。

    4. settledFetches を 1 増加させます。

    5. result が "download-total-exceeded" の場合、 immediateFailure を true に設定します。

  6. settledFetches が bgFetch のレコードのサイズになるか、immediateFailure が true になるまで待機します。

  7. immediateFailure が true の場合、bgFetch のすべて 中止フラグを設定します。

    注: レコードを完了するアルゴリズムはこのフラグを監視し、設定されたときにフェッチを終了します。

  8. 次の手順を swRegistration のアクティブな バックグラウンドフェッチ編集キューにエンキューします。

    1. activeBgFetches を swRegistration のアクティブなバックグラウンド フェッチとします。

    2. id を bgFetch のid とします。

    3. activeBgFetches が bgFetch というバックグラウンドフェッチを含む場合、 activeBgFetches[id] を削除します。

    4. それ以外の場合、failureReason を "aborted" に設定します。

      注: これは、abort() が正常に呼び出されたのと同時にフェッチの 1 つが失敗する競合状態を処理します。abort() から true を返した場合、これにより関連する abort イベントが確実に発火されます。

    5. failureReason が空文字列でない場合:

      1. bgFetch の結果を "failure" に設定します。

      2. bgFetch の失敗理由を failureReason に設定します。

    6. それ以外の場合、bgFetch の結果を "success" に設定します。

    7. bgFetch についてバックグラウンドフェッチインスタンスを更新する。

    8. eventName を空文字列とします。

    9. eventConstructor を null とします。

    10. failureReason が "aborted" の場合:

      1. eventName を "backgroundfetchabort" に設定します。

      2. eventConstructor を BackgroundFetchEvent に設定します。

    11. それ以外で、failureReason が空文字列でない場合:

      1. eventName を "backgroundfetchfail" に設定します。

      2. eventConstructor を BackgroundFetchUpdateUIEvent に設定します。

    12. それ以外の場合:

      1. eventName を "backgroundfetchsuccess" に設定します。

      2. eventConstructor を BackgroundFetchUpdateUIEvent に設定します。

    13. swRegistration 上で eventConstructor を使用して eventName という名前の機能イベントを発火する。次のプロパティを指定します。

      registration

      イベントオブジェクトの関連するレルム内で bgFetch についてBackgroundFetchRegistration インスタンスを取得することの結果。

      次に、dispatchedEvent を用いて次の手順を並列に実行します。

      1. dispatchedEvent がアクティブでなくなるまで待機します。

        ServiceWorker/1348。

      2. bgFetch のレコード利用可能 フラグを未設定にします。

      3. bgFetch についてバックグラウンドフェッチ インスタンスを更新する。

4.2. レコードを完了する

注: このアルゴリズムはバックグラウンドフェッチレコードのフェッチを管理します。 このアルゴリズムのインスタンスはバックグラウンドフェッチレコードごとに 1 つ開始されますが、フェッチを再試行したり、 部分レスポンスの次の部分をフェッチしたりするために再帰的に呼び出されます。

bgFetch(バックグラウンドフェッチ)および record(バックグラウンドフェッチレコード)についてレコードを完了する には、次の手順を実行します。
  1. responseData を record のレスポンスデータとします。

  2. downloadTotal を、bgFetch のダウンロード総量が 0 でなければその値、そうでなければ 無限大とします。

  3. bgFetch の一時停止フラグが未設定になるまで待機します。

  4. request を record のリクエストのコピーとします。

    注: この時点では、リクエストがストリームとして開始された場合でも、リクエスト全体が ストレージに保持されています。

  5. request のkeepalive フラグを設定します。

  6. request のサービスワーカーモードを "none" に設定します。

  7. rangeStart を responseData のバイトの長さとします。

  8. rangeStart が 0 でない場合、rangeStart を指定して request にrange ヘッダーを追加します。

    注: rangeStart が 0 の場合、通常のリクエストが行われます。 これにより、range ヘッダーを持つリクエストには Accept-Encoding: identity が追加されるため、 最初のリクエストでコンテンツエンコーディングを利用できます。

  9. fetchAttemptComplete を false とします。

  10. lastTransmittedSize を 0 とします。

  11. request をフェッチします。

    この手順の残りでは、 現在タスクをキューに入れる fetch の「コールバック」を使用します。これはここでは望ましくなく、実行もできないため、 タスクがキューに入れられないものと仮定します。(課題)

    request のリクエストボディを処理するには、次の手順を実行します。

    1. transmittedSize を request のボディの送信済み バイトとします。

    2. bgFetch のアップロード済みを、transmittedSize から lastTransmittedSize を引いた値だけ増加させます。

    3. lastTransmittedSize を transmittedSize に設定します。

    4. bgFetch についてバックグラウンドフェッチ インスタンスを更新する。

    response のレスポンスを処理するには、次の手順を実行します。

    1. response がネットワークエラーの場合:

      1. リソースが一時的に利用不可であり、 request のメソッドが `GET` の場合、 リソースが一時的に利用不可でなくなるまで待機し、 fetchAttemptComplete を true に設定してこれらの手順を中止します。

        注: request のメソッドが `GET` でない場合、 リクエストを再発行すると望ましくない副作用が生じる可能性があります。リクエストを再開する標準的な方法が 利用可能になれば、ここでも採用されます。

      2. response が中止されたネットワークエラーの場合、 responseData の結果を "aborted" に設定し、それ以外の場合は "fetch-error" に設定します。

      3. fetchAttemptComplete を true に設定し、これらの手順を中止します。

    2. response のステータスが 206 の場合:

      1. rangeStart、response、および responseData のレスポンスについて部分レスポンスを検証する結果が 無効を返す場合:

        1. responseData の結果を "fetch-error" に設定します。

        2. fetchAttemptComplete を true に設定します。

        3. 進行中のフェッチを終了し、これらの手順を中止します。

    3. それ以外の場合:

      1. responseData の結果を "redundant" に設定します。

      2. responseData を新しいバックグラウンドフェッチレスポンスに設定します。

      3. record のレスポンスデータを responseData に設定します。

        注: レコード オブジェクトを作成するアルゴリズムは、以前のバックグラウンドフェッチレスポンスへの参照を保持する場合があります。

      4. bgFetch についてバックグラウンドフェッチ インスタンスを更新する。

    4. rangeStart が 0、または response のステータスが 206 でない場合、 responseData のレスポンスを、 response のボディを除いたコピーに設定します。

    5. stream を response のボディのストリームとします。

    6. 1 バイト以上が stream から送信されるたびに、bytes を送信されたバイトとして次の手順を実行します。

      1. bgFetch の保存済みボディバイト 総量に bytes のサイズを加えた値が downloadTotal より大きい場合:

        1. stream をキャンセルします。

        2. responseData の結果を "download-total-exceeded" に、fetchAttemptComplete を true に設定し、これらの手順を中止します。

      2. bytes を responseData のバイトに追加します。

      3. 前の手順がクォータ制限の超過により失敗した場合、responseData の結果を "quota-exceeded" に、fetchAttemptComplete を true に設定し、 これらの手順を中止します。

      4. bgFetch についてバックグラウンドフェッチ インスタンスを更新する。

    7. いずれかの時点で stream のバイト送信が正常に完了した場合:

      1. response のステータスが 206 の場合:

        1. firstBytePos、lastBytePos、および completeLength を、response からcontent-range 値を抽出することの結果とします。

        2. completeLength が null でなく、かつ responseData のバイトの長さと等しい場合、 responseData の結果を "success" に設定します。

          注: リソース全体、またはリソースの残りを要求しても、 サーバーが残りを返さない場合があります。その場合は追加のリクエストを行う必要があります。

      2. それ以外で、response のステータスがok ステータスでない場合、responseData の結果を "bad-status" に設定します。

      3. それ以外の場合、responseData の結果を "success" に設定します。

      4. fetchAttemptComplete を true に設定します。

    8. いずれかの時点で stream がエラー状態になった場合:

      1. リソースが一時的に利用不可であり、 request のメソッドが `GET` の場合、 リソースが一時的に利用不可でなくなるまで待機し、 fetchAttemptComplete を true に設定します。

      2. それ以外の場合、responseData の結果を "fetch-error" に、fetchAttemptComplete を true に設定します。

  12. result を空文字列とします。

  13. 次の手順を実行しますが、bgFetch の一時停止 フラグまたはすべて中止フラグが設定された場合は中止します。

    1. fetchAttemptComplete が true になるまで待機します。

    2. result を responseData の結果に設定します。

  14. 中止された場合:

    1. bgFetch の一時停止フラグが設定されている場合、 request のメソッドが `GET` であることを表明します。

    2. bgFetch のすべて中止フラグが設定されている場合、 responseData の結果を "aborted" に設定します。

    3. result を responseData の結果に設定します。

      注: フェッチを終了すると結果が変わる可能性があるため、ここで結果を保存します。

    4. 進行中のフェッチを終了します。

  15. result が空文字列の場合、bgFetch と record についてレコードを完了する。

4.3. バックグラウンド フェッチインスタンスを更新する

bgFetch(バックグラウンドフェッチ)についてバックグラウンド フェッチインスタンスを更新するには、次の手順を bgFetch の更新処理キューにエンキューします。
  1. downloaded を bgFetch の保存済みボディバイト総量とします。

  2. uploaded を bgFetch のアップロード済みとします。

  3. result を bgFetch の結果とします。

  4. failureReason を bgFetch の失敗理由とします。

  5. bgFetch のレコード利用可能フラグが設定されている場合は recordsAvailable を true、それ以外の場合は false とします。

  6. 環境設定オブジェクト env のうち、そのオリジンが bgFetch のサービスワーカー登録の スコープ URLのオリジンと等しいものそれぞれについて、env の担当イベントループ上でbgfetch タスクをキューに入れ、 次の手順を実行します。

    1. bgFetchRegistration を、バックグラウンドフェッチが bgFetch と等しい、関連するレルム内の BackgroundFetchRegistration インスタンスとし、存在しない場合は null とします。

      注: BackgroundFetchRegistration インスタンスを取得するアルゴリズムにより、環境ごとに最大 1 つしか存在しません。

    2. bgFetchRegistration が null の場合、これらの手順を中止します。

    3. recordsAvailable が false であり、bgFetchRegistration のレコード利用可能 フラグが設定されている場合、bgFetchRegistration のレコード利用可能 フラグを未設定にします。

    4. bgFetchRegistration の結果が空文字列でない場合、 これらの手順を中止します。

      注: これにより、バックグラウンドフェッチが確定した後に進行状況が報告されることを防ぎます。 操作が中止されたものの、一部のフェッチがまだ終了していない場合には、この状況が発生する可能性があります。

    5. 次のすべてが true の場合:

      その場合、これらの手順を中止します。

    6. bgFetchRegistration のダウンロード済みを downloaded に設定します。

    7. bgFetchRegistration のアップロード済みを uploaded に設定します。

    8. bgFetchRegistration の結果を result に設定します。

    9. bgFetchRegistration の失敗理由を failureReason に設定します。

    10. bgFetchRegistration に "progress" という名前のイベントを発火します。

    mouse move イベントがデバウンスされるのと同様に、これもデバウンスする必要があります。

4.4. バックグラウンド フェッチクリックイベントを発火する

bgFetch(バックグラウンドフェッチ)についてバックグラウンド フェッチクリックイベントを発火するには、bgFetch のサービスワーカー登録上で、BackgroundFetchEvent を使用して "backgroundfetchclick" という名前の機能イベントを発火し、次のプロパティを指定します。
registration

イベントオブジェクトの関連するレルム内で bgFetch についてBackgroundFetchRegistration インスタンスを取得することの結果。

4.5. BackgroundFetchRegistration インスタンスを取得する

注: このアルゴリズムは、BackgroundFetchManager の存続期間を通して、指定されたバックグラウンドフェッチに対して同じ BackgroundFetchRegistration インスタンスが返されることを保証します。指定されたバックグラウンドフェッチに対して複数のインスタンスが作成されたことを識別する手段がない限り (たとえば、等価性、expando、または弱く関連付けられたデータを通じて)、ブラウザーがこれを最適化しても問題ありません。

realm(レルム)内で bgFetch(バックグラウンドフェッチ)についてBackgroundFetchRegistration インスタンスを取得するには、次の手順を実行します。
  1. instancesMap を、この realm 内にある唯一の BackgroundFetchManager インスタンスのBackgroundFetchRegistration インスタンスとします。

  2. instancesMap[bgFetch] が存在する場合、 instancesMap[bgFetch] を返します。

  3. instance を realm 内の新しい BackgroundFetchRegistration とし、そのバックグラウンドフェッチを bgFetch に設定します。

  4. instancesMap[bgFetch] を instance に設定します。

  5. instance を返します。

4.6. 部分レスポンスを検証する

注: このアルゴリズムは、部分レスポンスが要求されたものと合理的に一致するかを確認し、 必要に応じて以前のレスポンスと結合すべきかどうかも確認します。

expectedRangeStart(数値)、partialResponse(レスポンス)、およびオプションの previousResponse(レスポンスまたは null。特に指定されていない限り null)について部分 レスポンスを検証するには、次の手順を実行します。
  1. 表明: partialResponse のステータスは 206 である。

  2. responseFirstBytePos、responseLastBytePos、および responseCompleteLength を、partialResponse からcontent-range 値を抽出することの結果とします。これが失敗した場合は、無効を返します。

  3. responseFirstBytePos が expectedRangeStart と等しくない場合、 無効を返します。

  4. previousResponse が null でない場合:

    1. « `ETag`, `Last-Modified` » の各 headerName について:

      1. previousResponse のヘッダーリストが headerName を含み、かつ previousResponse のヘッダーリスト内の headerName の結合された値が、 partialResponse のヘッダーリスト内の headerName の結合された値と等しくない場合、 無効を返します。

    2. previousResponse のステータスが 206 の場合:

      1. previousResponseFirstBytePos、 previousResponseLastBytePos、および previousResponseCompleteLength を、previousResponse からcontent-range 値を抽出することの結果とします。これが失敗した場合は、無効を返します。

      2. previousResponseCompleteLength が null でなく、 responseCompleteLength が previousResponseCompleteLength と等しくない場合、無効を返します。

  5. 有効を返します。

4.7. content-range 値を抽出する

注: このアルゴリズムは `Content-Range` を単一 バイト content-rangeとして解析し、その値を抽出します。

response(レスポンス)からcontent-range 値を抽出するには、次の手順を実行します。
  1. response のヘッダーリストが `Content-Range` を含まない場合、失敗を返します。

  2. contentRangeValue を、response のヘッダーリスト内で、その名前が `Content-Range` とバイト単位で大文字小文字を区別せず一致する最初のヘッダー の値とします。

  3. contentRangeValue を単一バイト content-rangeに従って解析することに失敗した場合、失敗を返します。

  4. firstBytePos を、contentRangeValue を単一バイト content-rangeとして解析したときに first-byte-pos と名付けられた部分を整数として解析したものとします。

  5. lastBytePos を、contentRangeValue を単一バイト content-rangeとして解析したときに last-byte-pos と名付けられた部分を整数として解析したものとします。

  6. completeLength を、contentRangeValue を単一バイト content-rangeとして解析したときに complete-length と名付けられた部分とします。

  7. completeLength が "*" の場合、completeLength を null に設定し、 それ以外の場合は completeLength を整数として解析した値に設定します。

  8. firstBytePos、lastBytePos、および completeLength を返します。

整数としての解析 infra/189。

4.8. レコードオブジェクトを作成する

注: このアルゴリズムはバックグラウンド フェッチレコードのプラットフォームオブジェクトを作成します。また、保存されたバイトからレスポンスをストリーミングする処理も管理します。 この時点では、バックグラウンドフェッチ操作はまだ進行中である可能性があります。

realm(レルム)内で records(バックグラウンド フェッチレコードのリスト)からレコードオブジェクトを作成するには、次の手順を実行します。

すべてのプラットフォームオブジェクトは realm 内に作成しなければなりません。

  1. recordObjects を新しいリストとします。

  2. records の各 record についてそれぞれ:

    1. responseData を record のレスポンスデータとします。

    2. recordObject を新しい BackgroundFetchRecord とします。

    3. recordObject の responseReady を新しい promise に設定します。

    4. requestObject を、次を設定した新しい Request オブジェクトとします。

      リクエスト

      record のリクエストのコピー。ボディも含みます。

      ヘッダー

      この Request の リクエストのヘッダーリストに関連付けられた新しい Headers オブジェクト。

    5. recordObject の request を requestObject に設定します。

    6. transmittedBytes を 0 とします。

    7. stream を、新しい promise promise を返し、次の手順を並列に実行する pull アクションを持つ新しい読み取り可能ストリームとします。

      1. responseData のバイトの長さが transmittedBytes より大きくなるか、responseData の結果が空文字列でなくなるまで待機します。

      2. bytes を null とします。

      3. responseData のバイトの長さが transmittedBytes より大きく、かつ responseData を公開できる場合:

        1. bytes を、transmittedBytes のオフセットから始まる、 responseData のバイトの ユーザーエージェントが決定したスライスに設定します。

          注: これにより、ユーザーエージェントは適切な速度で ストレージからリソースをストリーミングできます。

        2. transmittedBytes を bytes の長さだけ増加させます。

      4. stream の関連する設定オブジェクトの担当イベントループ内で、ネットワークタスクソースを使用してタスクをキューに入れ、次の手順を実行します。

        1. bytes が null でない場合:

          1. array を、bytes の新しい ArrayBuffer をラップする新しい Uint8Array とします。

          2. array を stream にエンキューします。

        2. responseData を公開でき、 responseData の結果が空文字列ではなく、 かつ transmittedBytes が responseData のバイトの長さである場合、 stream を閉じます。

        3. それ以外で、responseData の結果が "aborted" の場合、stream を AbortError DOMException でエラー状態にします。

        4. それ以外で、responseData を公開できない場合、 stream を TypeError でエラー状態にします。

        5. promise を解決します。

    8. 次の手順を並列に実行します。

      1. responseData のレスポンスが null でなくなるまで待機します。

      2. responseData を公開できる場合:

        1. response を responseData のレスポンスのコピーとします。

        2. response のヘッダーリストから `Content-Range` を削除します。

        3. response のヘッダーリストから `Content-Length` を削除します。

        4. body を、ストリームが stream に設定された新しいボディとします。

        5. response のボディを body に設定します。

        6. recordObject の関連する設定 オブジェクトの担当イベントループ内で、ネットワークタスクソースを使用してタスクをキューに入れ、次の手順を実行します。

          1. responseObject を、次を設定した新しい Response オブジェクトとします。

            レスポンス

            response。

            ヘッダー

            この Response のレスポンスの ヘッダー リストに関連付けられた新しい Headers オブジェクト。

          2. recordObject の responseReady を responseObject で解決します。

      3. それ以外で、responseData の結果が "aborted" の場合、recordObject の responseReady を AbortError DOMException で拒否します。

      4. それ以外の場合、recordObject の responseReady を TypeError で拒否します。

    9. recordObject を recordObjects に追加します。

  3. recordObjects を返します。

4.9. バックグラウンドフェッチを含む

map(マップ)が bgFetch(バックグラウンドフェッチ)をバックグラウンド フェッチとして含むかどうかを判定するには、次の手順を実行します。
  1. id を bgFetch のid とします。

  2. map[id] が存在しない場合、 false を返します。

  3. map[id] が bgFetch と等しくない場合、false を返します。

  4. true を返します。

map(マップ)が bgFetch(バックグラウンドフェッチ)をバックグラウンド フェッチとして含まないかどうかを判定するには、次の手順を実行します。
  1. map が bgFetch というバックグラウンドフェッチを含む場合、 false を返します。

  2. true を返します。

5. ヘッダー構文

次は、単一バイト content-rangeに対するHTTP ABNF です。

"bytes=" first-byte-pos "-" last-byte-pos "/" complete-length
first-byte-pos = 1*DIGIT
last-byte-pos  = 1*DIGIT
complete-length = ( 1*DIGIT / "*" )

注: これは RFC 7233 が許可するもののサブセットです。

上記をレールロードダイアグラムで表すと次のとおりです。

"bytes=" first-byte-pos digit /first-byte-pos "/" last-byte-pos digit /last-byte-pos "/" complete-length "*" digit /complete-length

6. API

6.1. ServiceWorkerGlobalScope への拡張

partial interface ServiceWorkerGlobalScope {
  attribute EventHandler onbackgroundfetchsuccess;
  attribute EventHandler onbackgroundfetchfail;
  attribute EventHandler onbackgroundfetchabort;
  attribute EventHandler onbackgroundfetchclick;
};

6.1.1. イベント

次は、ServiceWorker インターフェイスを実装するすべてのオブジェクトが、イベントハンドラー IDL 属性としてサポートしなければならないイベントハンドラー(および対応するイベントハンドラーイベント型)です。

イベントハンドラーイベント型 イベントハンドラー インターフェイス
backgroundfetchsuccess onbackgroundfetchsuccess BackgroundFetchUpdateUIEvent
backgroundfetchfail onbackgroundfetchfail BackgroundFetchUpdateUIEvent
backgroundfetchabort onbackgroundfetchabort BackgroundFetchEvent
backgroundfetchclick onbackgroundfetchclick BackgroundFetchEvent

6.2. ServiceWorkerRegistration への拡張

partial interface ServiceWorkerRegistration {
  readonly attribute BackgroundFetchManager backgroundFetch;
};

ServiceWorkerRegistration はバックグラウンドフェッチマネージャー (BackgroundFetchManager)を持ちます。 初期状態では、サービスワーカー登録が コンテキストオブジェクトのサービスワーカー登録である新しい BackgroundFetchManager です。

backgroundFetch 属性の getter は、コンテキストオブジェクトのバックグラウンドフェッチマネージャーを返さなければなりません。

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 downloadTotal = 0;
};

BackgroundFetchManager は次を持ちます。

6.3.1. fetch()

fetch(id, requests, options) メソッドは、呼び出されたときに次の手順を実行します。
  1. registration をコンテキストオブジェクトのサービスワーカー 登録とします。

  2. records を新しいリストとします。

  3. uploadTotal を 0 とします。

  4. requests が RequestInfo の場合、requests を « requests » に設定します。

  5. requests が空の場合、 TypeError で拒否された promiseを返します。

  6. requests の各 request についてそれぞれ:

    1. internalRequest を、request を指定して Request コンストラクターを呼び出した結果のリクエストとします。これが例外をスローした場合、その例外で拒否された promiseを返します。

    2. internalRequest のモードが "no-cors" の場合、 TypeError で拒否された promiseを返します。

    3. internalRequest のクライアントを null に設定します。

    4. record を新しいバックグラウンド フェッチレコードとします。

    5. record のリクエストを internalRequest に設定します。

    6. record を records に追加します。

  7. promise を新しい promise とします。

  8. 次の手順を registration のアクティブな バックグラウンドフェッチ編集キューにエンキューします。

    1. PermissionDescriptor の name が "background-fetch" で、コンテキスト オブジェクトの関連する設定オブジェクトを持つ場合の許可状態を permission とします。

    2. permission が "denied" の場合、promise を NotAllowedError DOMException で拒否し、これらの手順を中止します。

    3. bgFetchMap を registration のアクティブな バックグラウンドフェッチとします。

    4. registration のアクティブワーカーが null の場合、 promise を TypeError で拒否し、これらの手順を中止します。

    5. bgFetchMap[id] が存在する場合、promise を TypeError で拒否し、 これらの手順を中止します。

    6. requestBodiesRemaining を requests のサイズ とします。

    7. requestReadFailed を false とします。

    8. requests の各 request についてそれぞれ:

      1. request のボディが null の場合、 続行します。

      2. stream を request のボディのストリームとします。

      3. 次の手順を並列に実行します。

        1. 次の手順を実行しますが、requestReadFailed が true の場合は中止します。

          1. request のボディを待機します。

          2. stream がエラー状態になった場合、 requestReadFailed を true に設定します。

          注: これにより、解決する前に リクエストバイトのコピーを確実に保持します。

        2. 中止された場合で、stream が読み取り可能なら、 stream を AbortError DOMException でエラー状態にし、 これらの手順を中止します。

        3. uploadTotal を request のボディの総バイト数だけ増加させます。

        4. requestBodiesRemaining を 1 減少させます。

    9. いずれかの時点で requests の保存がクォータ制限の超過により失敗した場合、 promise を QuotaExceededError DOMException で拒否し、これらの手順を中止します。

    10. requestBodiesRemaining が 0 になるか、requestReadFailed が true になるまで待機します。

    11. requestReadFailed が true の場合、promise を TypeError で拒否し、 これらの手順を中止します。

    12. bgFetch を、次を持つ新しいバックグラウンドフェッチとします。

      id

      id。

      レコード

      records。

      ダウンロード総量

      options の downloadTotal メンバー。

      アップロード総量

      uploadTotal。

      アイコン

      options の icons メンバーが存在する場合はそれを使用し、 それ以外の場合は空のリスト。

      タイトル

      options の title メンバーが存在する場合はそれを使用し、 それ以外の場合は空文字列。

      サービスワーカー 登録

      registration。

    13. bgFetchMap[id] を bgFetch に設定します。

    14. 次の手順を実行するようbgfetch タスクをキューに入れます。

      1. promise を、コンテキストオブジェクトの関連するレルム内で bgFetch についてBackgroundFetchRegistration インスタンスを取得することの結果で解決します。

    15. 並列に、コンテキストオブジェクトの関連する設定オブジェクトから bgFetch を表示します。

    16. 並列に、bgFetch についてバックグラウンドフェッチを実行します。

  9. promise を返します。

6.3.2. get()

get(id) メソッドは、 呼び出されたとき、新しい promise promise を返し、次の手順を並列に実行しなければなりません。
  1. registration を、コンテキストオブジェクトに関連付けられたサービスワーカー 登録とします。

  2. bgFetch を registration のアクティブなバックグラウンド フェッチ[id] とします。

  3. bgFetch が undefined の場合、promise を undefined で解決し、 これらの手順を中止します。

  4. 次の手順を bgFetch の更新処理キューにエンキューします。

    1. 次の手順を実行する task というbgfetch タスクをキューに入れます。

      1. bgFetchRegistration を、コンテキストオブジェクトの関連するレルム内で bgFetch についてBackgroundFetchRegistration インスタンスを取得することの結果とします。

      2. promise を bgFetchRegistration で解決します。

    2. task が完了するまで待機します。

      注: これにより、新しく作成される可能性のある BackgroundFetchRegistration が progress イベントを見逃さないようにします。

6.3.3. getIds()

getIds() メソッドは、呼び出されたとき、 新しい promise promise を返し、次の手順を並列に実行しなければなりません。
  1. registration を、コンテキストオブジェクトに関連付けられたサービスワーカー 登録とします。

  2. promise を、registration のアクティブなバックグラウンド フェッチのキーを取得することの結果で解決します。

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 BackgroundFetchFailureReason {
  // バックグラウンドフェッチはまだ完了していないか、正常に完了した。
  "",
  // 操作はユーザーによって中止されたか、abort() が呼び出された。
  "aborted",
  // レスポンスが not-ok-status だった。
  "bad-status",
  // CORS、MIX、無効な部分レスポンスなどの他の理由、
  // または再試行できないフェッチの一般的なネットワーク障害によってフェッチが失敗した。
  "fetch-error",
  // 操作中にストレージクォータに達した。
  "quota-exceeded",
  // 指定された downloadTotal を超過した。
  "download-total-exceeded"
};

BackgroundFetchRegistration インスタンスは次を持ちます。

注: 上記の値は同期的に利用できるようにコピーされます。

id 属性の getter は、コンテキストオブジェクトのid を返さなければなりません。

uploadTotal 属性の getter は、コンテキストオブジェクトのアップロード総量を返さなければなりません。

downloadTotal 属性の getter は、コンテキストオブジェクトのダウンロード総量を返さなければなりません。

uploaded 属性の getter は、 コンテキストオブジェクトのアップロード済みを返さなければなりません。

downloaded 属性の getter は、コンテキストオブジェクトのダウンロード済みを返さなければなりません。

result 属性の getter は、 コンテキストオブジェクトの結果を返さなければなりません。

failureReason 属性の getter は、コンテキストオブジェクトの失敗理由を返さなければなりません。

recordsAvailable 属性の getter は、コンテキストオブジェクトのレコード利用可能フラグが設定されている場合は true、それ以外の場合は false を返さなければなりません。

6.4.1. イベント

onprogress イベントハンドラーは、progress というイベントハンドラーイベント型を持ちます。

progress イベントは Event インターフェイスを使用します。

6.4.2. abort()

abort() メソッドは、 呼び出されたとき、新しい promise promise を返し、次の手順を並列に実行しなければなりません。
  1. bgFetch を、コンテキストオブジェクトに関連付けられたバックグラウンドフェッチとします。

  2. swRegistration を bgFetch のサービスワーカー 登録とします。

  3. 次の手順を swRegistration のアクティブな バックグラウンドフェッチ編集キューにエンキューします。

    1. activeBgFetches を swRegistration のアクティブな バックグラウンドフェッチとします。

    2. id を bgFetch のid とします。

    3. activeBgFetches が bgFetch というバックグラウンドフェッチを 含まない場合、promise を false で解決し、これらの手順を中止します。

    4. activeBgFetches[id] を削除します。

    5. promise を true で解決します。

    6. bgFetch のすべて中止フラグを設定します。

6.4.3. match()

match(request, options) メソッドは、呼び出されたとき、次の手順を実行しなければなりません。
  1. promise を、request と options を渡して matchAll() アルゴリズムを呼び出した結果とします。

  2. promise に、引数 matches で呼び出されたときに matches[0] を返す履行ハンドラーを指定して反応した結果を返します。

注: ユーザーエージェントには、上記を matchAll() の呼び出しよりも高速になるよう最適化することが推奨されます。

6.4.4. matchAll()

matchAll(request, options) メソッドは、呼び出されたとき、次の手順を実行しなければなりません。
  1. コンテキストオブジェクトのレコード利用可能 フラグが未設定の場合、InvalidStateError DOMException で拒否された promiseを返します。

  2. promise を新しい promise とします。

  3. 次の手順を並列に実行します。

    1. matchingRecords を空のリストとします。

    2. コンテキストオブジェクトのバックグラウンド フェッチのレコード内の各 record について:

      1. request、record のリクエスト、 record のレスポンスデータの レスポンス、 および options についてリクエストがキャッシュ済み項目に一致する が true を返す場合、record を matchingRecords に追加します。

    3. コンテキストオブジェクトの関連するレルム内で matchingRecords からレコードオブジェクトを作成することの結果で promise を解決するようbgfetch タスクをキューに入れます。

  4. promise を返します。

6.5. BackgroundFetchRecord

[Exposed=(Window,Worker)]
interface BackgroundFetchRecord {
  readonly attribute Request request;
  readonly attribute Promise<Response> responseReady;
};
BackgroundFetchRecord は次を持ちます。

request 属性の getter は、コンテキストオブジェクトのリクエストを返さなければなりません。

responseReady 属性の getter は、コンテキストオブジェクトのレスポンス 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 はバックグラウンドフェッチ(バックグラウンドフェッチ)を持ちます。初期値は、 registration が初期化された値のバックグラウンドフェッチです。

registration 属性は、 初期化された値を返さなければなりません。

6.7. BackgroundFetchUpdateUIEvent

[Exposed=ServiceWorker]
interface BackgroundFetchUpdateUIEvent : BackgroundFetchEvent {
  constructor(DOMString type, BackgroundFetchEventInit init);
  Promise<undefined> updateUI(optional BackgroundFetchUIOptions options = {});
};

BackgroundFetchUpdateUIEvent は、初期状態では未設定のUI 更新済みフラグを持ちます。

6.7.1. updateUI()

updateUI(options) メソッドは、呼び出されたとき、新しい promise promise を返し、次の手順を並列に実行しなければなりません。
  1. 次のいずれかが true の場合:

    InvalidStateError DOMException をスローします。

  2. コンテキストオブジェクトのUI 更新済みフラグを設定します。

  3. options が null の場合、返ります。

  4. bgFetch をコンテキストオブジェクトのバックグラウンドフェッチとします。

  5. options の icons メンバーが存在する場合、bgFetch のアイコンを options の icons に設定します。

  6. options の title メンバーが存在する場合、bgFetch のタイトルを options の title に設定します。

  7. promise を解決します。

7. 自動化

ユーザーエージェントの自動化およびアプリケーションテストの目的で、この文書は [WebDriver] 仕様向けに次の拡張コマンドを定義します。

7.1. クリック

メソッド URI テンプレート
POST /session/{session id}/backgroundfetch/{id}/click

バックグラウンド フェッチクリック拡張コマンドは、ユーザーがバックグラウンドフェッチの表示をアクティブ化する動作をシミュレートします。リモートエンド手順は次のとおりです。

  1. 現在のトップレベル閲覧コンテキスト がすでに開かれていない場合、WebDriver エラーコード no such window を持つWebDriver エラーを返します。

  2. pageURL を、現在のトップレベル閲覧 コンテキストのアクティブな文書のURL とします。

  3. swRegistration を pageURL に対する一致するサービスワーカー登録とします。

  4. swRegistration が null の場合、ステータス 400 および JSON エラーコード "invalid service worker state" を持つWebDriver エラーを返します。

  5. bgFetch を、URL 変数 id と同じid、および swRegistration と同じサービスワーカー登録 を持つ最新のバックグラウンドフェッチとし、存在しない場合は null とします。

  6. bgFetch が null の場合、ステータス 404 および JSON エラーコード "background fetch not found" を持つWebDriver エラーを返します。

  7. bgFetch についてバックグラウンドフェッチクリックイベントを発火する。

  8. WebDriver 成功を返します。

8. プライバシーと帯域幅の使用

フェッチは大規模になり、完了までに長い時間がかかる場合があります。この間、ユーザーは 1 台以上のサーバーからデータをフェッチします。 操作中に変化する可能性のあるユーザーの IP アドレスが、時間の経過に伴うユーザーの位置追跡に使用される可能性があります。

これを軽減するため、バックグラウンドフェッチを表示する手順では、次を要求します。

また、この手順では、ユーザーが従量制接続を使用している場合、ユーザーエージェントがバックグラウンドフェッチを一時停止することも許可しています。

保存されるすべてのデータは、特定のサービスワーカー登録に関連付けられます。サービスワーカー登録を消去すると、関連するすべての バックグラウンドフェッチが消去されます。

適合性

文書の 規約

適合要件は、説明的な表明 と RFC 2119 の用語を組み合わせて表現されます。 この文書の規範的な部分におけるキーワード “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, および “OPTIONAL” は、RFC 2119 に記載されているとおりに 解釈されるものとします。 ただし、読みやすさのため、 この仕様ではこれらの単語がすべて大文字で表記されるとは限りません。

この仕様のすべてのテキストは、 明示的に非規範的と記されている節、例、および注記を除き、規範的です。 [RFC2119]

この仕様の例は、“for example” という語で導入されるか、 class="example" によって 規範的なテキストから区別されます。 次のようになります。

これは参考情報としての例の一例です。

参考情報としての注記は “Note” という語で始まり、 class="note" によって 規範的なテキストから区別されます。 次のようになります。

注: これは参考情報としての注記です。

適合する アルゴリズム

アルゴリズムの一部として命令形で表現される要件 (たとえば "先頭の空白文字をすべて除去する" または "false を返してこれらの手順を中止する") は、そのアルゴリズムを導入する際に使用されたキーワード ("must", "should", "may" など) の意味で解釈されるものとします。

アルゴリズムまたは特定の手順として表現された適合要件は、 最終結果が同等である限り、 どのような方法でも実装できます。 特に、この仕様で定義されるアルゴリズムは 理解しやすいことを意図しており、 高性能であることを意図していません。 実装者には最適化することが推奨されます。

索引

この仕様で定義される 用語

参照により定義される 用語

参考文献

規範的参考文献

[DOM]
Anne van Kesteren. DOM 標準. 現行標準. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript 言語仕様. URL: https://tc39.es/ecma262/
[FETCH]
Anne van Kesteren. Fetch 標準. 現行標準. URL: https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML 標準. 現行 標準. URL: https://html.spec.whatwg.org/multipage/
[IMAGE-RESOURCE]
Aaron Gustafson; Rayan Kanso; Marcos Caceres. 画像 リソース. 2021年3月29日. WD. URL: https://www.w3.org/TR/image-resource/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 標準. 現行 標準. URL: https://infra.spec.whatwg.org/
[PERMISSIONS]
Mounir Lamouri; Marcos Caceres; Jeffrey Yasskin. Permissions. 2020年7月20日. WD. URL: https://www.w3.org/TR/permissions/
[RFC2119]
S. Bradner. 要件レベルを示すために RFC で使用する キーワード. 1997年3月. 現在のベストプラクティス. URL: https://tools.ietf.org/html/rfc2119
[SERVICE-WORKERS-1]
Alex Russell; et al. Service Workers 1. 2019年11月 19日. CR. URL: https://www.w3.org/TR/service-workers-1/
[STREAMS]
Adam Rice; Domenic Denicola; 吉野剛史 (Takeshi Yoshino). Streams 標準. 現行標準. URL: https://streams.spec.whatwg.org/
[URL]
Anne van Kesteren. URL 標準. 現行標準. URL: https://url.spec.whatwg.org/
[WebDriver]
Simon Stewart; David Burns. WebDriver. 2018年6月5日. REC. URL: https://www.w3.org/TR/webdriver1/
[WebIDL]
Boris Zbarsky. Web IDL. 2016年12月15日. ED. URL: https://heycam.github.io/webidl/

IDL 索引

partial interface ServiceWorkerGlobalScope {
  attribute EventHandler onbackgroundfetchsuccess;
  attribute EventHandler onbackgroundfetchfail;
  attribute EventHandler onbackgroundfetchabort;
  attribute EventHandler onbackgroundfetchclick;
};

partial interface ServiceWorkerRegistration {
  readonly attribute BackgroundFetchManager backgroundFetch;
};

[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 downloadTotal = 0;
};

[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 BackgroundFetchFailureReason {
  // バックグラウンドフェッチはまだ完了していないか、正常に完了した。
  "",
  // 操作はユーザーによって中止されたか、abort() が呼び出された。
  "aborted",
  // レスポンスが not-ok-status だった。
  "bad-status",
  // CORS、MIX、無効な部分レスポンスなど、その他の理由でフェッチが失敗した、
  // または再試行できないフェッチで一般的なネットワーク障害が発生した。
  "fetch-error",
  // 操作中にストレージクォータに達した。
  "quota-exceeded",
  // 指定された downloadTotal を超過した。
  "download-total-exceeded"
};

[Exposed=(Window,Worker)]
interface BackgroundFetchRecord {
  readonly attribute Request request;
  readonly attribute Promise<Response> responseReady;
};

[Exposed=ServiceWorker]
interface BackgroundFetchEvent : ExtendableEvent {
  constructor(DOMString type, BackgroundFetchEventInit init);
  readonly attribute BackgroundFetchRegistration registration;
};

dictionary BackgroundFetchEventInit : ExtendableEventInit {
  required BackgroundFetchRegistration registration;
};

[Exposed=ServiceWorker]
interface BackgroundFetchUpdateUIEvent : BackgroundFetchEvent {
  constructor(DOMString type, BackgroundFetchEventInit init);
  Promise<undefined> updateUI(optional BackgroundFetchUIOptions options = {});
};

課題索引

manifest/pull/710。 ↵
ServiceWorker/1348。 ↵
この手順の残りでは、現在タスクをキューに入れる fetch の「コールバック」を使用します。これは ここでは望ましくなく、実行もできないため、タスクがキューに入れられないものと仮定します。(課題) ↵
mouse move イベントがデバウンスされるのと同様に、これもデバウンスする必要があります。 ↵
整数としての解析 infra/189。 ↵
ServiceWorker/1348。 ↵