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

草案コミュニティグループレポート,

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

概要

ユーザーが可視性を持ちながら、バックグラウンドで大容量のアップロード/ダウンロードを処理するためのAPI。

この文書のステータス

この仕様はWeb Platform Incubator Community Groupによって公開されました。 これはW3C標準ではなく、W3C標準化トラックにも載っていません。 W3C Community Contributor License Agreement (CLA)の下で限定的なオプトアウトが可能で、その他の条件も適用されることに注意してください。 W3Cコミュニティおよびビジネスグループについての詳細をご覧ください。

1. 導入

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

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

この仕様の目的は以下の通りです:

2. レルム

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

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

リソースは、ユーザーエージェントがリソースがまもなく利用可能になると考える場合、一時的に利用不可と見なされます。理由には以下が含まれる場合があります:

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

オプションのeventLoopイベントループ、デフォルトでは呼び出し元のコンテキストオブジェクト関連する設定オブジェクト責任を持つイベントループ)とsteps(ステップ)を使ってバックグラウンドフェッチタスクをキューに入れるには、eventLoop上でタスクをキューに入れバックグラウンドフェッチタスクソースを使用してstepsを実行します。

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

サービスワーカー登録には以下が追加されます:

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

バックグラウンドフェッチは以下で構成されます:

バックグラウンドフェッチ (bgFetch) の保存されたボディバイトの合計を取得するには、以下の手順を実行します:
  1. totalを0に設定します。

  2. record について、bgFetchレコード:

    1. record応答データバイト長さ分、totalを増やします。

  3. totalを返します。

3.2.1. 表示

バックグラウンドフェッチ (bgFetch) を指定されたenvironment (環境設定オブジェクト) のために表示するには、ユーザーエージェントは以下のルールに従ってUIを表示する必要があります:

permissionPermissionDescriptorとして許可状態を取得します。そのname"background-fetch"で、environmentで指定されます。もしpermission"prompt"である場合、ユーザーエージェントはこのアルゴリズムの開始時にbgFetch一時停止フラグを設定することができます。ユーザーエージェントはユーザーがバックグラウンドフェッチを受け入れる(bgFetch一時停止フラグを解除する)か、拒否する(bgFetchすべて中止フラグを設定する)ことを許可すべきです。ユーザーエージェントは常に許可または常に拒否するオプションを提供することもできます。これをこの許可に対するユーザーの意図に関する新情報として使用することができます。

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

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

バックグラウンドフェッチレコードは以下で構成されます:

3.4. バックグラウンドフェッチ応答

バックグラウンドフェッチ応答は以下で構成されます:

応答公開される場合があります。その場合結果が空文字列、"success"、または"bad-status"である必要があります。

4. アルゴリズム

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

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

バックグラウンドフェッチbgFetch (a バックグラウンドフェッチ) のために実行するには、以下の手順を実行します:
  1. swRegistrationbgFetchサービスワーカー登録とします。

  2. settledFetchesを0に設定します。

  3. immediateFailureをfalseに設定します。

  4. failureReasonを空文字列に設定します。

  5. recordについて、bgFetchレコードに対して、以下の手順を並列で実行します:

    1. レコードを完了するbgFetchrecordで実行します。

    2. resultrecord応答データ結果とします。

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

      1. アサーション: result"redundant"ではありません。

      2. failureReasonresultに設定します。

    4. settledFetchesを1増やします。

    5. もしresult"download-total-exceeded"である場合、immediateFailureをtrueに設定します。

  6. settledFetchesbgFetchレコードサイズに等しいか、またはimmediateFailureがtrueになるまで待ちます。

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

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

  8. 以下の手順をキューに追加するswRegistrationアクティブなバックグラウンドフェッチ編集キューに対して実行します:

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

    2. idbgFetchIDとします。

    3. もしactiveBgFetchesバックグラウンドフェッチを含むなら、activeBgFetches[id]を削除します。

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

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

    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. eventConstructorBackgroundFetchEventに設定します。

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

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

      2. eventConstructorBackgroundFetchUpdateUIEventに設定します。

    12. それ以外の場合:

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

      2. eventConstructorBackgroundFetchUpdateUIEventに設定します。

    13. 機能イベントを発火するeventNameを名前としてeventConstructorを使用し、swRegistrationで以下のプロパティを持つイベントを実行します:

      登録

      イベントオブジェクトの関連するレルムにおいてbgFetchBackgroundFetchRegistrationインスタンスを取得する結果。

      その後dispatchedEvent並列で以下の手順を実行します:

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

        ServiceWorker/1348

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

      3. バックグラウンドフェッチインスタンスを更新するbgFetchに対して実行します。

4.2. レコードを完了する

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

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

  2. downloadTotalbgFetchダウンロード合計とします。ただし0でない場合はその値を、それ以外の場合は無限大とします。

  3. bgFetch一時停止フラグが解除されるのを待ちます。

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

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

  5. requestkeepalive フラグを設定します。

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

  7. rangeStartresponseData長さとします。

  8. もしrangeStartが0でない場合は、Range ヘッダーを追加してrequestrangeStartを設定します。

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

  9. fetchAttemptCompleteを false とします。

  10. lastTransmittedSizeを 0 とします。

  11. Fetch requestを実行します。

    このステップの残りの部分では、Fetch "callbacks" を使用していますが、現在タスクをキューに入れています。これは望ましくも可能でもないため、タスクがキューに入っていないと仮定します。(issue)

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

    1. transmittedSizerequestbody送信済みバイト数とします。

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

    3. lastTransmittedSizetransmittedSizeに設定します。

    4. バックグラウンドフェッチインスタンスを更新 します。

    レスポンスを処理するには、responseに対して以下の手順を実行します:

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

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

        注: requestmethodが `GET`でない場合、リクエストを再発行することで意図しない副作用が 発生する可能性があります。リクエストを再開する標準的な方法が利用可能になった場合、 それがここで採用されます。

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

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

    2. responsestatus206の場合:

      1. もし部分レスポンスを検証するrangeStartresponse、およびresponseDataレスポンスに対して無効を返す場合、次を実行します:

        1. responseDataresult"fetch-error"に設定します。

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

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

    3. それ以外の場合:

      1. responseDataresult"redundant"に設定します。

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

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

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

      4. バックグラウンドフェッチインスタンスを更新 します。

    4. rangeStartが0であるか、responsestatus206でない場合、 responseDataresponseresponse のコピーに設定します。ただしbodyを除きます。

    5. streamresponsebodystreamとします。

    6. streamから1バイト以上が送信された場合は、bytesを送信されたバイト数 として以下の手順を実行します:

      1. bgFetch保存されたボディ バイト合計bytesのサイズを加算した値が downloadTotalを超える場合:

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

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

      2. bytesresponseDatabytesに追加します。

      3. 前の手順がクォータ制限を超えたために失敗した場合、responseDataresult"quota-exceeded" に設定し、fetchAttemptCompleteをtrueに設定してこれらの手順を中止します。

      4. バックグラウンドフェッチインスタンスを更新 します。

    7. 任意の時点でstreamのバイト送信が正常に完了した場合:

      1. responsestatus206である場合:

        1. firstBytePoslastBytePos、および completeLengthresponseからcontent-range値を抽出 した結果とします。

        2. completeLengthがnullでなく、かつresponseDatabytes長さに等しい場合、 responseDataresult"success" に設定します。

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

      2. それ以外の場合、responsestatusokステータスでない場合、 responseDataresult"bad-status" に設定します。

      3. それ以外の場合、responseDataresult"success" に設定します。

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

    8. 任意の時点でstreamエラー状態になった場合:

      1. リソースが一時的に利用できない状態であり、 requestmethodが `GET`の場合、リソースが一時的に利用できない状態でなくなるまで 待機し、fetchAttemptCompleteをtrueに設定します。

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

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

  13. 以下の手順を実行しますが、中止条件としてbgFetchpaused flagまたはabort all flagが設定された場合:

    1. fetchAttemptCompleteがtrueになるのを待ちます。

    2. resultresponseDataresultに設定します。

  14. 中止された場合

    1. bgFetchpaused flagが設定されている場合、 requestmethodが`GET`であることを確認します。

    2. bgFetchabort all flagが設定されている場合、 responseDataresult"aborted"に設定します。

    3. resultresponseDataresultに設定します。

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

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

  15. resultが空文字列の場合、レコードを完了するbgFetchおよび recordに対して実行します。

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

バックグラウンドフェッチインスタンスを更新するbgFetchバックグラウンドフェッチ)に対して実行するには、bgFetch更新処理キュー以下の手順をエンキューします:
  1. downloadedbgFetch保存されたボディバイト合計とします。

  2. uploadedbgFetchアップロード済みとします。

  3. resultbgFetch結果とします。

  4. failureReasonbgFetch失敗理由とします。

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

  6. 環境設定オブジェクトのうち、そのオリジンbgFetchサービスワーカーレジストレーションスコープURLオリジンと等しいものをそれぞれ取り出し、env責任あるイベントループバックグラウンドフェッチタスクをキューイングして以下の手順を実行します:

    1. bgFetchRegistrationを、BackgroundFetchRegistrationのうち、バックグラウンドフェッチbgFetchと等しいものとします。該当するインスタンスが存在しない場合はnullとします。

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

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

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

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

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

    5. 以下のすべてが真である場合:

      これらの手順を中止します。

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

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

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

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

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

    マウス移動イベントのデバウンスに似た方法でデバウンスを実装する必要があります。

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

バックグラウンドフェッチクリックイベントを発火するbgFetchバックグラウンドフェッチ)に対して実行するには、bgFetchサービスワーカーレジストレーションで、以下のプロパティを使用してBackgroundFetchEventという名前の "backgroundfetchclick"の機能イベントを発火する
registration

イベントオブジェクトの関連するRealmで、bgFetchBackgroundFetchRegistrationインスタンスを取得する結果。

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

注: このアルゴリズムは、BackgroundFetchRegistrationインスタンスが、BackgroundFetchManagerのライフサイクル全体で特定のバックグラウンドフェッチに対して同じインスタンスを返すことを保証します。ブラウザが最適化を行うことは問題ありませんが、特定のバックグラウンドフェッチに対して複数のインスタンスが作成されたと判別されない限り(例:等価性、拡張プロパティ、または弱い関連データを通じて)。

BackgroundFetchRegistrationインスタンスを取得するbgFetchバックグラウンドフェッチ)およびrealmRealm)に対して実行するには、以下の手順を実行します:
  1. instancesMapを、このrealm内に存在する唯一のBackgroundFetchManagerBackgroundFetchRegistrationインスタンスとします。

  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. responseFirstBytePosresponseLastBytePos、および responseCompleteLengthを、partialResponseからcontent-range値を抽出する結果とします。これが失敗した場合、invalidを返します。

  3. もしresponseFirstBytePosexpectedRangeStartと等しくない場合、invalidを返します。

  4. もしpreviousResponseがnullでない場合:

    1. 《`ETag`、`Last-Modified`》のheaderNameそれぞれに対して:

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

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

      1. previousResponseFirstBytePospreviousResponseLastBytePos、および previousResponseCompleteLengthを、previousResponseからcontent-range値を抽出した結果とします。これが失敗した場合、invalidを返します。

      2. もしpreviousResponseCompleteLengthがnullでない場合、かつ responseCompleteLengthpreviousResponseCompleteLengthと等しくない場合、invalidを返します。

  5. validを返します。

4.7. Content-Rangeの値を抽出する

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

Content-Rangeの値を抽出するresponseレスポンス)に対して実行するには、以下の手順を実行します:
  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. firstBytePoslastBytePos、およびcompleteLengthを返します。

整数としての解析について infra/189を参照。

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

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

レコードオブジェクトを作成するrecordsリスト)およびrealmRealm)に対して実行するには、以下の手順を実行します:

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

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

  2. recordrecordsから以下のように処理する:

    1. responseDatarecordレスポンスデータとします。

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

    3. recordObjectresponseReady新しいPromiseに設定します。

    4. requestObjectを以下の設定を持つ新しいRequest オブジェクトとします:

      リクエスト

      recordリクエストのコピーを設定します。その中にはボディも含みます。

      ヘッダー

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

    5. recordObjectrequestrequestObjectに設定します。

    6. transmittedBytesを0とします。

    7. stream新しいReadable Streamとし、以下の手順を並行して実行するプルアクションを持たせる:

      1. responseData長さtransmittedBytesを超えるか、またはresponseData結果が空文字列でなくなるのを待つ。

      2. bytesをnullとします。

      3. もしresponseData長さtransmittedBytesを超え、かつresponseData公開可能である場合:

        1. bytesresponseDataバイトのうち、transmittedBytesオフセットから始まるエージェントが決定するスライスとする。

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

        2. transmittedBytesbytes長さを加算する。

      4. タスクをキューに追加し、以下を実行する:

        1. もしbytesがnullでない場合:

          1. arrayを新しいUint8Arrayオブジェクトとし、ArrayBufferをラップする。

          2. arraystreamにキューに追加する。

        2. もしresponseData公開可能であり、responseData結果が空文字列でなく、かつtransmittedBytesresponseData長さと等しい場合、streamを閉じる

        3. それ以外の場合、もしresponseData結果"aborted"である場合、streamをエラー状態にする

        4. Promiseを解決する

    8. recordObjectrecordObjectsに追加する

  3. recordObjectsを返します。

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

mapマップ)がバックグラウンドフェッチを含むか bgFetchバックグラウンドフェッチ)を判定するには、以下の手順を実行します:
  1. idbgFetchIDとします。

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

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

  4. trueを返します。

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

  2. trueを返します。

5. ヘッダー構文

以下はHTTP ABNFで定義された単一バイトの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 / "*" )

注: これは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. もしrequestsRequestInfoの場合、requestsを« requests »に設定します。

  5. もしrequestsの場合、 Promiseを以下で拒否された状態で返します: TypeError

  6. requestrequestsから以下のように処理します:

    1. internalRequestを、以下を実行した結果のリクエストとします: Request コンストラクタをrequestと共に呼び出します。これが例外をスローした場合、Promiseを例外で拒否された状態で返します。

    2. もしinternalRequestモードが"no-cors"の場合、 Promiseを以下で拒否された状態で返します: TypeError

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

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

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

    6. リストに追加としてrecordrecordsに追加します。

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

  8. 以下の手順をエンキューとして registrationアクティブなバックグラウンドフェッチ編集キューに追加します:

    1. permissionを、以下を満たす権限状態とします: PermissionDescriptorname"background-fetch"であり、コンテキストオブジェクト関連設定オブジェクトです。

    2. もしpermission"denied"である場合、promiseを以下で拒否して手順を中止します: NotAllowedError DOMException

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

    4. もしregistrationアクティブワーカーがnullである場合、promiseを以下で拒否して手順を中止します: TypeError

    5. もしbgFetchMap[id]が存在する場合、promiseを以下で拒否して手順を中止します: TypeError

    6. 以下のプロパティを持つ新しいbgFetchを作成し、bgFetchMap[id]に設定します:

      id

      id

      records

      records

      download total

      optionsdownloadTotalメンバー。

      upload total

      uploadTotal

      icons

      optionsiconsメンバーが存在する場合それを使用し、存在しない場合は空のリスト

      title

      optionstitleメンバーが存在する場合それを使用し、存在しない場合は空文字列。

      service worker registration

      registration

    7. Bgfetchタスクをキューに追加して以下を実行:

      1. Promiseを解決し、BackgroundFetchRegistrationインスタンスを取得bgFetchコンテキストオブジェクト関連するRealmで返します。

    8. 並行してbgFetchを表示します。

    9. 並行してバックグラウンドフェッチを実行します。

  9. promiseを返します。

6.3.2. get()

get(id) メソッドを呼び出すと、新しいPromise promiseを返し、以下の手順を並行して実行します:
  1. registrationコンテキストオブジェクトに関連付けられたサービスワーカーレジストレーションとします。

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

  3. もしbgFetchが未定義の場合、Promiseを解決してpromiseに未定義を設定し、これらの手順を中止します。

  4. 以下の手順をエンキューとしてbgFetch更新処理キューに追加します:

    1. Bgfetchタスクをキューに追加としてtaskを実行し、以下の手順を実行します:

      1. bgFetchRegistrationを、BackgroundFetchRegistrationインスタンスを取得してbgFetchコンテキストオブジェクト関連するRealmに設定した結果とします。

      2. Promiseを解決してpromisebgFetchRegistrationを設定します。

    2. taskが完了するのを待ちます。

      注: これにより、新しいBackgroundFetchRegistrationインスタンスが progressイベントを見逃さないことを保証します。

6.3.3. getIds()

getIds() メソッドを呼び出すと、新しいPromise promiseを返し、以下の手順を並行して実行します:
  1. registrationコンテキストオブジェクトに関連付けられたサービスワーカーレジストレーションとします。

  2. Promiseを解決して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. swRegistrationbgFetchサービスワーカーレジストレーションとします。

  3. 以下の手順をエンキューとして swRegistrationアクティブなバックグラウンドフェッチ編集キューに追加します:

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

    2. idbgFetchIDとします。

    3. もしactiveBgFetchesバックグラウンドフェッチを含まない bgFetchである場合、 Promiseを解決してpromiseにfalseを設定し、これらの手順を中止します。

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

    5. Promiseを解決してpromiseにtrueを設定します。

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

6.4.3. match()

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

  2. Promiseが解決された時に実行する手順の結果を返します。 その結果、promisematchesを渡し、matches[0]を返します。

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

6.4.4. matchAll()

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

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

  3. 以下の手順を並行して実行します:

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

    2. recordについて、以下をコンテキストオブジェクトバックグラウンドフェッチレコードから実行します:

      1. もしリクエストがキャッシュされたアイテムに一致する ためのrequestrecordリクエストrecordレスポンスデータレスポンス、 およびoptionsがtrueを返す場合、 リストに追加としてrecordmatchingRecordsに追加します。

    3. Bgfetchタスクをキューに追加して、 Promiseを解決し、 promiseレコードオブジェクトを作成してmatchingRecordsコンテキストオブジェクト関連するRealmで設定します。

  4. promiseを返します。

6.5. BackgroundFetchRecord

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

BackgroundFetchRecord には以下が含まれます:

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

responseReady 属性のgetterはコンテキストオブジェクトレスポンスプロミスを返さなければなりません。

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. もしoptionsicons メンバーが存在する場合、bgFetchアイコンoptionsicons に設定します。

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

  7. Promiseを解決します。

7. 自動化

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

7.1. クリック

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

バックグラウンドフェッチクリック 拡張コマンドは、表示バックグラウンドフェッチをユーザーがアクティブにすることをシミュレートします。リモートエンドステップは以下の通りです:

  1. もし現在のトップレベルブラウジングコンテキスト既に閉じられている場合、WebDriverエラーWebDriverエラーコード no such windowと共に返します。

  2. pageURL現在のトップレベルブラウジングコンテキストアクティブドキュメントURLとします。

  3. swRegistrationpageURLに対する一致するサービスワーカーレジストレーションとします。

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

  5. bgFetchを、バックグラウンドフェッチの中で、idurl変数 idで、サービスワーカーレジストレーションswRegistrationの最新のものとし、それが存在しない場合はnullとします。

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

  7. バックグラウンドフェッチクリックイベントを発火 します。

  8. WebDriver成功を返します。

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

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

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

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

保存されるすべてのデータは、特定のサービスワーカーレジストレーションに関連付けられています。サービスワーカーレジストレーションをクリアすると、関連付けられたすべてのバックグラウンドフェッチがクリアされます。

適合性

文書の規約

適合性の要件は、記述的な断言とRFC 2119の用語を組み合わせて表現されています。 重要な単語である「MUST」、「MUST NOT」、「REQUIRED」、「SHALL」、「SHALL NOT」、「SHOULD」、「SHOULD NOT」、「RECOMMENDED」、 「MAY」、「OPTIONAL」は、本書の規範的な部分において、RFC 2119で説明されているとおりに解釈されます。 ただし、可読性のため、これらの単語は本仕様ではすべて大文字では表示されていません。

本仕様のテキストは、非規範的と明記されたセクション、例、および注意書きを除き、すべて規範的です。[RFC2119]

本仕様における例は、「例えば」という言葉で導入されるか、 またはclass="example"で設定されることで、規範的なテキストから区別されます。 次のように:

これは情報例の一例です。

情報提供のための注意書きは「注意」という言葉で始まり、 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. フェッチ標準. 現行標準. 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日. 作業草案. URL: https://www.w3.org/TR/image-resource/
[INFRA]
Anne van Kesteren; Domenic Denicola. インフラ標準. 現行標準. URL: https://infra.spec.whatwg.org/
[PERMISSIONS]
Mounir Lamouri; Marcos Caceres; Jeffrey Yasskin. 権限. 2020年7月20日. 作業草案. 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. サービスワーカー 1. 2019年11月19日. 勧告候補. URL: https://www.w3.org/TR/service-workers-1/
[STREAMS]
Adam Rice; Domenic Denicola; 吉野剛史 (Takeshi Yoshino). ストリーム標準. 現行標準. 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日. 勧告. URL: https://www.w3.org/TR/webdriver1/
[WebIDL]
Boris Zbarsky. Web IDL. 2016年12月15日. 編集草案. 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 {
  // The background fetch has not completed yet, or was successful.
  "",
  // The operation was aborted by the user, or abort() was called.
  "aborted",
  // A response had a not-ok-status.
  "bad-status",
  // 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.
  "fetch-error",
  // Storage quota was reached during the operation.
  "quota-exceeded",
  // The provided downloadTotal was exceeded.
  "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 の「コールバック」を使用していますが、これらは現在タスクをキューに追加します。ここではそれが望ましくも可能でもないため、タスクがキューに追加されないふりをしましょう。 (問題)
マウス移動イベントと同様にデバウンスする必要があります。
整数として解析 infra/189.
ServiceWorker/1348.