Chromium が出荷済みだが、他のユーザーエージェントからの コミットメント/実装がない、Web Application Manifest 拡張およびインキュベーションのための機能仕様。 これらの機能を explainer として保持する代わりに、ここでより 公式に文書化する。

これは非公式な提案である。

display_override メンバー

高度な用途では、[=manifest/display_override=] メンバーを使用して、 開発者が Web アプリケーションに対して好ましい 表示モードを選択できるように、 表示モードリスト値の カスタムフォールバック順序を指定できる。その値は [=display mode=] である。

[=application manifest=] の [=manifest/display_override=] メンバーは、 [=display mode/window-controls-overlay=] や [=display mode/unframed=] などの 拡張を含む sequence表示モードリスト値である。 このメンバーは、[=display mode=] に対する開発者の好ましい フォールバックチェーンを表す。このフィールドは [=manifest/display=] メンバーを上書きする。ユーザーエージェントがここで指定された [=display mode=] のいずれもサポートしていない場合、 [=manifest/display=] メンバーを考慮することへフォールバックする。 アルゴリズム手順については、 display メンバーの処理を参照。

次の手順は、 Web アプリの選択された表示モードを決定するにおける [=application manifest/processing extension-point=] に追加される。

  1. |manifest:ordered map|.[=manifest/display_override=] メンバーの |candidate_display_mode:DisplayModeType| それぞれについて [=list/For each=]:
    1. 表示 モードリストが |candidate_display_mode:DisplayModeType| を含む場合、 その |candidate_display_mode:DisplayModeType| を返す
    2. |candidate_display_mode:DisplayModeType| が [=display mode/window-controls-overlay=] であり、ユーザーエージェントがこれを サポートする場合、その |candidate_display_mode:DisplayModeType| を返す。
    3. |candidate_display_mode:DisplayModeType| が [=display mode/tabbed=] であり、ユーザーエージェントがこれをサポートする場合、 その |candidate_display_mode:DisplayModeType| を返す。

このメンバーは、開発者が自分の表示モードのフォールバック順序を 明示的に制御したい場合、または基本の 表示モード リストでは利用できないモードのためなど、高度な場合にのみ 使用されることを意図している。そうでない場合、ほとんどのユースケースでは [=manifest/display=] メンバーで十分である。

概念

表示モード拡張

通常の 表示モードに加えて、 [=manifest/display_override=] はそれに対する特定の拡張もサポートする。

unframed
isolated web application には、ホストネイティブのタイトルバーや [=window controls=] が表示されず、Web コンテンツがタイトルバー領域 全体へ拡張される。アプリは Web コンテンツ内に [=draggable region=] を 指定して、カスタマイズされたタイトルバーを作成できる。
[=display mode/window-controls-overlay=]
tabbed
Web アプリケーションは、複数の [=application contexts=] を単一の オペレーティングシステムレベルのウィンドウに結合できる。たとえば、 これはユーザーエージェントが、ユーザーが application contexts 間を 切り替えられるようにタブストリップ UI を表示することを意味し得る。

[=manifest/display_override=] の使用例

次は、standalone よりも minimal-ui 表示モードを優先するが、 minimal-ui がサポートされていない場合は browser ではなく standalone へフォールバックする [=manifest=] を示す。

            {
              "name": "Recipe Zone",
              "description": "All of the recipes!",
              "icons": [{
                "src": "icon/hd_hi",
                "sizes": "128x128"
              }],
              "start_url": "/index.html",
              "display_override": ["minimal-ui"],
              "display": "standalone",
              "theme_color": "yellow",
              "background_color": "red"
            }
          

ドラッグ可能な 領域の定義

[=app-region=] CSS プロパティはどのユーザーエージェントにも実装されて いないため、at risk である。なお、一部のユーザーエージェントは 同じ目的のために非標準 CSS プロパティ `-webkit-app-region` を使用する。

`app-region` プロパティは、たとえばタイトルバー内のどの領域または要素が ドラッグ可能であるかを CSS で定義するために使用できる。

manifest の処理への拡張

この仕様によって追加される新しい拡張およびインキュベーション機能 すべてを容易にするため、ユーザーエージェントは [=processing a manifest=] における 拡張 ポイントで、[=URL=] |document URL:URL|、[=URL=] |manifest URL:URL|、[=ordered map=] |json:ordered map|、および [=ordered map=] |manifest:ordered map| に アクセスして、次を実行するべきである:

  1. |json|、|manifest| および |manifest URL| を渡して [=Process the `tab_strip` member=]。
  2. |json|、|manifest| および |manifest URL| を渡して [=Process the `note_taking` member=]。
  3. |json| および |manifest| を渡して [=Process the `protocol_handlers` member=]。
  4. |json|、|manifest| および |manifest URL| を渡して [=Process the `file_handlers` member=]。
  5. |json| および |manifest| を渡して [=Process the `related_applications` member=]。
  6. |json| および |manifest| を渡して [=Process the `scope_extensions` member=]。
  7. |json|、|manifest| および |manifest URL| を渡して [=Process the `migrate_from` member=]。
  8. |json|、|manifest| および |manifest URL| を渡して [=Process the `migrate_to` member=]。

tab_strip メンバー

Web Application Manifest の `tab_strip` メンバーは、アプリケーションが [=display mode/tabbed=] 表示モードでどのように挙動することを意図しているか についての情報を含む オブジェクトである。 これは次のメンバーを持つ:

home_tab メンバー

[=tab_strip=] オブジェクトの `home_tab` メンバーは、アプリケーションの トップレベルメニューとして機能することを意図した特別な「ホームタブ」に 関する情報を含む ordered map である。これは次のメンバーを含む:

scope_patterns メンバーは、 [=manifest URL=] に相対的な [=within home tab scope|ホームタブのスコープ=] を定義する {{URLPatternInput}} のリストである。

アプリケーションの適用済み [=display mode=] が [=display mode/tabbed=] であり、 [=Document/processed manifest=] が [=tab_strip=] メンバーの非 null な [=home_tab=] メンバーを含む場合、そのアプリケーションは ホームタブを持つ

ホームタブコンテキストは、他の application contexts と比べて 特別なプロパティを持つ任意の [=application context=] である。 アプリケーションが [=has a home tab=] 場合、すべてのアプリケーション ウィンドウは [=home tab context=] を備えるべきである。そうでない場合、 アプリケーションウィンドウは [=home tab context=] を持つべきではない。

[=home tab context=] がどのように提示されるかはユーザーエージェントの 裁量に委ねられるが、通常の application contexts とは異なる外観を 持つべきである。

[=URL=] |url:URL| は、次の場合に限り ホームタブスコープ内であると言われる:

URL は [=within home tab scope=] でない場合、ホームタブスコープ外である。

すべてのウィンドウはホームタブを持つ

アプリケーションが [=has a home tab=] 場合、新しいアプリケーション ウィンドウが作成されるたびに(たとえばアプリケーションの起動時、 またはタブを新しいウィンドウへ移動するとき)、ユーザーエージェントは そのウィンドウ内に新しい [=home tab context=] を作成しなければならない。 新しく作成された [=home tab context=] は、定義上 [=within home tab scope=] である [=start URL=] へナビゲートされるべきである。

ホームタブスコープに関するナビゲーション

[=home tab context=] に関連付けられた [=top-level traversable=] を、 [=outside of home tab scope=] である [=URL=] |url:URL| へ [=navigate|ナビゲート=] するとき、次の手順が実行される:

  1. "_blank" のターゲットおよび noopener true で navigable を選択した結果を、[=top-level traversable=] |tab:toplevel traversable| とする。
  2. home-tab traversable を [=navigating=] する代わりに、 同じパラメーターで |tab| を [=navigate=] する。
  3. 現在の [=application manifest=] を |tab| の [=top-level browsing context=] に [=applied|適用=] する。
  4. ユーザーエージェントは |tab| を home-tab navigable と同じ ウィンドウに配置するべきである。
  5. |tab| をフォーカスする。

[=display mode/tabbed=] の [=display mode=] を持つ [=top-level traversable=] であって [=home tab context=] に関連付けられて いないもの(すなわち非ホームタブ)を、[=within home tab scope=] である [=URL=] |url:URL| へ [=navigate|ナビゲート=] するとき、次の手順が 実行される:

  1. |hometab:toplevel traversable| を、現在のウィンドウに関連付けられた [=home tab context=] の [=top-level traversable=] とする。
  2. top-level traversable を [=navigating=] する代わりに、 同じパラメーターで |hometab| を [=navigate=] する。
  3. |hometab| をフォーカスする。

ホームタブ不変条件

上記の規則は、[=has a home tab|ホームタブを持つ=] アプリケーションについて、 次の不変条件が常に真であることを保証することを意図している:

  • すべてのアプリケーションウィンドウは正確に 1 つの [=home tab context=] を持ち、
  • すべての [=home tab context=] のアクティブ文書の [=Document/URL=] は [=within home tab scope=] であり (文書の URL が作成時以降に変更されていない限り)、
  • すべての非ホームタブ [=application context=] のアクティブ文書の [=Document/URL=] は [=outside of home tab scope=] である (文書の URL が作成時以降に変更されていない限り)。

ユーザーエージェントは、文書が [=URL/fragment=] を変更したり、 {{History}} API を使用して表示 URL をホームタブスコープ内外へ変更したり しても、ナビゲーションが発生していないため、文書をホームタブコンテキストと 非ホームタブコンテキストの間で動的に移動しない。このため、上記の不変条件は、 文書が作成された時点で持っていた [=Document/URLs=] のみを考慮する。

URL を変更することで「ナビゲートしたふり」をする single-page applications では、 これにより、上記の不変条件を破る望ましくない挙動が生じる可能性がある (例:ユーザーがホームタブ内のリンクをクリックして URL を非ホームページへ 動的に変更しても、実際にはナビゲートしていないため、ホームタブ内に 留まる)。この状況を避けるため、アプリケーションは tabbed application mode にあることを検出し、URL を変更する代わりに、ホームタブスコープの内外へ 実際のナビゲーションを行うように挙動を変更できる。

new_tab_button メンバー

[=tab_strip/new_tab_button=] メンバーは、クリック/有効化されたときに アプリケーションウィンドウ内で新しい [=application context=] を開く UI アフォーダンス(ボタンなど)の挙動を記述する ordered map である。 これは次のメンバーを持つ:

url メンバーは、 [=manifest URL=] に相対的な URL を表す文字列であり、 [=Document/processed manifest=] の [=manifest/within scope=] である。

[=Document/processed manifest=] の [=new_tab_button=] の [=new_tab_button/url=] メンバーが [=outside of home tab scope=] である場合、 アプリケーションは 新しいタブボタンを持つ。アプリケーションが [=has a new tab button|新しいタブボタンを持たない=] 場合、 ユーザーエージェントは「新しいタブ」アフォーダンスをエンドユーザーに 利用可能にするべきではない。

エンドユーザーによって新しいタブボタンが有効化されたとき、次の手順が 実行される:

  1. 現在のウィンドウ内に [=Create a new application context=] し、 それをフォーカスする。
  2. [=new_tab_button=] の [=new_tab_button/url=] メンバーの値へ ナビゲートする。

`tab_strip` メンバーの処理

[=ordered map=] |json:ordered map|、[=ordered map=] |manifest:ordered map|、 および [=URL=] |manifest URL:URL| が与えられたとき、 process the `tab_strip` member するには、 [=processing a manifest=] における 拡張ポイントで次を実行する:

  1. |manifest|["tab_strip"] を新しい [=ordered map=] に設定する。
  2. |json|["tab_strip"] が存在しない、または |json|["tab_strip"] が [=ordered map=] でない場合:
    1. |manifest|["tab_strip"]["new_tab_button"]["url"] を |manifest|["start_url"] に設定する。
    2. 戻る。
  3. |json|["tab_strip"]、 |manifest|["tab_strip"]、および |manifest URL| を渡して [=Process the `home_tab` member=]。
  4. |json|["tab_strip"]、|manifest|["tab_strip"]、|manifest URL|、および |manifest|["start_url"] を渡して [=Process the `new_tab_button` member=]。

`home_tab` メンバーの処理

[=ordered map=] |json tab strip:ordered map|、[=ordered map=] |manifest tab strip:ordered map|、および [=URL=] |manifest URL:URL| が 与えられたとき、process the `home_tab` member するには、 次を実行する:

  1. |json tab strip|["home_tab"] が存在しない、または |json tab strip|["home_tab"] が [=ordered map=] でない場合、戻る。
  2. |home tab:ordered map| を新しい [=ordered map=] とする。
  3. |json tab strip|["home_tab"]["scope_patterns"]、|home tab| および |manifest URL| を渡して [=Process the `scope_patterns` member=]。
  4. |manifest tab strip|["home_tab"] を |home tab| に設定する。

`new_tab_button` メンバーの処理

[=ordered map=] |json tab strip:ordered map|、[=ordered map=] |manifest tab strip:ordered map|、[=URL=] |manifest URL:URL|、および [=URL=] |start URL:URL| が与えられたとき、 process the `new_tab_button` member するには、次を実行する:

  1. |manifest tab strip|["new_tab_button"]["url"] を |start URL| に設定する。
  2. |json tab strip|["new_tab_button"] が存在しない、または |json tab strip|["new_tab_button"] が [=ordered map=] でない場合、戻る。
  3. |url:URL| を、|manifest URL| を基底 URL として |json tab strip|["new_tab_button"]["url"] を [=URL Parser|解析=] した結果とする。
  4. |url| が failure の場合、戻る。
  5. |url| が |manifest URL| の [=URL/within scope=] でない場合、戻る。
  6. |manifest tab strip|["new_tab_button"]["url"] を |url| に設定する。

`scope_patterns` メンバーの処理

[=ordered map=] |json home tab:ordered map|、[=ordered map=] |manifest home tab:ordered map| および [=URL=] |manifest URL:URL| が 与えられたとき、process the `scope_patterns` member するには、 次を実行する:

  1. |processed scope patterns:list| を新しい [=list=] とする。
  2. |manifest home tab|["scope_patterns"] を |processed scope patterns| に設定する。
  3. |json home tab|["scope_patterns"] が存在しない、または |json home tab|["scope_patterns"] が [=list=] でない場合、戻る。
  4. |json home tab|["scope_patterns"] の |entry:URLPatternInit| それぞれについて:
    1. |entry| と |manifest URL| を与えて [=build a URL pattern from an infra value|infra 値から URL パターンを構築=] した結果を |pattern:URL pattern| とする。この処理が例外を投げるか null を返す場合、続行する。
    2. |pattern| を |processed scope patterns| に追加する。

使用例

        {
          "name": "Tabbed App Example",
          "start_url": "/",
          "display": "standalone",
          "display_override": ["tabbed"],
          "tab_strip": {
            "home_tab": {
              "scope_patterns": [
                {"pathname": "/"},
                {"pathname": "/index.html"}
              ]
            },
            "new_tab_button": {
              "url": "/create"
            }
          }
        }
        

この例は、tabbed mode がサポートされていない場合に単一文書の standalone window へフォールバックする tabbed web app である。 メイン index ページ(/ または /index.html)へのすべてのナビゲーションは [=home tab context=] で開かれる。新しいタブボタンは /create で新しいタブを開く。

[=tab_strip/home_tab/scope_patterns=] と照合するとき、URL の [=URL/query=] 部分は既定で無視されることに注意 (したがって /index.html?utm_source=foo への ナビゲーションはホームタブで開かれる)。しかし、[=start URL=] と 照合するとき、[=URL/query=] は正確に一致しなければならないため、 クエリを無視したいサイトは、[=start URL=] の [=URL/path=] をスコープパターンとして明示的に含めることが推奨される。

`share_target` メンバー

`share_target` メンバーは、Web アプリケーションを共有アクション (例:テキスト、URL、またはファイルの共有)の「ターゲット」として登録する。 `share_target` メンバーは [[[web-share-target]]] 仕様の一部である。

note_taking メンバー

Web Application Manifest の `note_taking` メンバーは、ノート作成に関連する情報を 含む オブジェクトである。 これは次のメンバーを持つ:

ユーザーエージェントは、これらのメンバーを使用して、その Web アプリケーションを ノート作成機能を持つアプリケーションとして異なる扱いにしてもよい (例:オペレーティングシステムのノート作成サーフェスとの統合)。

new_note_url メンバー

[=note_taking=] `new_note_url` メンバーは、ユーザーが Web アプリケーションを 使用して新しいノートを取りたいとき(例:オペレーティングシステムの ショートカットアイコンやキーボードショートカットから)に、 ユーザーエージェントに読み込ませることを開発者が望む URL を表す [=string=] である。

`new_note_url` メンバーは純粋に助言的であり、ユーザーエージェントは それを無視してもよく、 それを使用するかどうかをエンドユーザーが選択できるようにしてもよい。 ユーザーエージェントは、エンドユーザーがそれを変更できるようにしてもよい。

使用例

次は、ノート作成アプリケーション用の [=manifest=] を示す。

          {
            "name": "My Note Taking App",
            "description": "You can take notes!",
            "icons": [{
              "src": "icon/hd_hi",
              "sizes": "128x128"
            }],
            "start_url": "/index.html",
            "display": "standalone",
            "note_taking": {
              "new_note_url": "/new_note.html"
            }
          }
        

`note_taking` メンバーの処理

[=ordered map=] |json:ordered map|、[=ordered map=] |manifest:ordered map|、 [=URL=] |manifest_URL:URL| が与えられたとき、 process the `note_taking` member するには、 [=processing a manifest=] における 拡張 ポイントで次を実行する:

  1. |json|["note_taking"] が [=map/exist=] しない場合、戻る。
  2. |json|["note_taking"] の型が [=ordered map=] でない場合、 戻る。
  3. |manifest|["note_taking"] を新しい [=ordered map=] に設定する。
  4. |json|["note_taking"], |manifest|["note_taking"], および |manifest URL| を 渡して [=process the `new_note_url` member=]。

`new_note_url` メンバーの処理

[=ordered map=] |json_note_taking:ordered map|、[=ordered map=] |manifest_note_taking:ordered map|、[=URL=] |manifest_URL:URL| が 与えられたとき、process the `new_note_url` member するには、 次を実行する:

  1. |json_note_taking|["new_note_url"] が [=map/exist=] しない場合、 戻る。
  2. |json_note_taking|["new_note_url"] の型が [=string=] でない場合、戻る。
  3. |new_note_url:URL| を、|manifest URL| を基底 URL として |json_note_taking|["new_note_url"] を [=URL Parser|解析=] した結果とする。
  4. |new_note_url| が failure の場合、戻る。
  5. |new_note_url| が |manifest URL| の [=manifest/within scope=] でない場合、戻る。
  6. manifest_note_taking["new_note_url"] を |new_note_url| に設定する。

`new_note_url` の起動

処理済み manifest |manifest:processed manifest| が与えられたとき、 launch the `new_note_url` するには、次の手順を実行する:

  1. |manifest|["note_taking"] が [=map/exist=] しない場合、戻る。
  2. |manifest|["note_taking"]["new_note_url"] が [=map/exist=] しない場合、戻る。
  3. |manifest|["note_taking"]["new_note_url"] の型が [=URL=] でない場合、戻る。
  4. |manifest| を |manifest| に、 |target URL| を |manifest|["note_taking"]["new_note_url"] に設定して、 [=launch a web application=] する手順を実行する。

ユーザーエージェントは、通常はユーザーアフォーダンスへの応答として、 任意の時点で、与えられた [=installed web application=] について [=launch the `new_note_url`=] してもよい。

`protocol_handlers` メンバー

[=manifest's=] protocol_handlers メンバーは、 Web アプリケーションが URL プロトコルを処理できるようにする protocol handler description の配列である。

インストール時、ユーザーエージェントは次と整合する対話を通じて、 オペレーティングシステムに protocol handler を登録するべきである:

`protocol_handlers` メンバーの処理

[=object=] |json:JSON|、|manifest:ordered map| が与えられたとき、 process the `protocol_handlers` member するには:

  1. |json:JSON|["|protocol_handlers|"] の新しい [=list=] を |processedProtocolHandlers| とする。
  2. manifest["|protocol_handlers|"] を |processedProtocolHandlers| に設定する。
  3. |protocol_handler|(protocol handler description)それぞれについて [=list/For each=]:
    1. |protocol_handler|["protocol"] または |protocol_handler|["url"] が undefined の場合、[=iteration/continue=]。
    2. |protocol_handler|["protocol"]、| protocol_handler|["url"] を、 |manifest URL| を基底 URL として、かつ [=this=] の関連する [=environment settings object=] を使用して、 [=normalize protocol handler parameters=] を実行した結果を (|normalizedProtocol:string|, |normalizedUrl:URL|) とする。 結果が failure の場合、[=iteration/continue=]。
    3. |normalizedUrl| が |manifest| の [=manifest/within scope=] でない場合、 [=iteration/continue=]。
    4. |processedProtocolHandlers| が |normalizedUrl| を [=list/contains=] する場合、[=iteration/continue=]。
    5. |protocol_handler| を |processedProtocolHandlers| に [=List/Append=] する。
  4. |processedProtocolHandlers| それぞれについて [=list/For each=]、 ユーザーエージェントは [=register a protocol handler=] するべきである。

ユーザーエージェントは、ホストオペレーティングシステムでプロトコルの 既定 handler として [=protocol handler description=] protocol_handlers を登録する前に、ユーザーに許可を求めるべきである。 ユーザーエージェントは、ホストオペレーティングシステムの慣例または制限との 一貫性を保つため、提示される [=protocol handler description=] protocol_handlers のリストを切り詰めてもよい。

Protocol handler 項目

protocol handler description は、Web アプリケーションが 処理したいプロトコルを表す [=object=] であり、 [=manifest/protocol_handlers=] メンバーに対応する。 これは次のメンバーを持つ:

ユーザーエージェントは、これらの値を使用して、Web アプリケーションを operating system の handler として登録するべきである。 ユーザーが protocol handler URL を有効化したとき、ユーザーエージェントは handling a protocol launch を実行するべきである。

[[HTML]] の {{NavigatorContentUtils/registerProtocolHandler()}} は、 Web サイトが特定のプロトコルの可能な handler として自分自身を登録することを 可能にする。protocol handler description に対する 有効な [=protocol handler description/protocol=] および [=protocol handler description/url=] の値を構成するものは、その API で定義される。 なお、[[HTML]] API は、ここで [=protocol handler description/protocol=] を 使用する場所で scheme を使用するが、同じ制限が適用される。

`protocol` メンバー

protocol handler descriptionprotocol メンバーは、 処理されるプロトコル(`mailto` または `web+auth` など)を表す string である。

protocol handler description の [=protocol handler description/protocol=] メンバーは、 [[HTML]] で定義される {{NavigatorContentUtils/registerProtocolHandler()}} の scheme 引数と同等である。

`url` メンバー

protocol handler descriptionurl メンバーは、 関連付けられたプロトコルが有効化されたときに開かれる、 アプリケーションの [=manifest/within scope=] である URL である。

protocol handler description の [=protocol handler description/url=] メンバーは、 [[HTML]] で定義される {{NavigatorContentUtils/registerProtocolHandler()}} の url 引数と同等である。

プロトコル起動の処理

[=manifest=] manifest を持つ protocol handler description protocol_handler が呼び出されたとき、 それは [=invoke a protocol handler=] に使用される同じ手順を通る。 その際、ユーザーエージェントは resultURL へ [=navigating=] する代わりに、manifestresultURL を渡して [=launch a web application=] するべきである。

これはこのように [=invoke a protocol handler=] を呼び出して変更するべきではない。 resultURL の計算は、汎用の別個のアルゴリズムへ 抽出されるべきである。

プライバシー上の考慮事項:既定の protocol handler

オペレーティングシステムの機能によっては、protocol handler は、ユーザーが 明示的に知ることなく、与えられたプロトコルの「既定」handler (例:与えられたプロトコルの起動を自動的に処理する)になる可能性がある。 起こり得る悪用を防ぐため、ユーザーエージェントは次のような保護を 採用してもよい:

ユーザーエージェントが protocol handler entity の登録を削除する場合、 ユーザーが Web アプリおよびプロトコルをオペレーティングシステムに 再登録できる UX を提供するべきである。

`file_handlers` メンバー

[=manifest's=] file_handlers メンバーは、 アプリ自体の外部から発生するファイルを開くアクションをアプリがどのように 処理するかについての指示を提供する [=list=] である。

登録済み file-handling applications の管理、提示、および選択は、 オペレーティングシステムの裁量に委ねられる。

[=ordered map=] |json:ordered map|、[=ordered map=] |manifest:ordered map|、 [=URL=] |manifest_url:URL| が与えられたとき、 process the `file_handlers` member するには:

  1. |processedFileHandlers:list| を新しい [=list=] とする。
  2. |manifest|["file_handlers"] を |processedFileHandlers| に設定する。
  3. |json|["file_handlers"] が [=map/exist=] しない、または |json|["file_handlers"] が [=list=] でない場合、戻る。
  4. |json|["file_handlers"] の |entry:ordered map| それぞれについて [=list/For each=]:
    1. |entry|、[=manifest/start_url=]、[=manifest/scope=]、 および |manifest_url| を用いて [=process a file handler item=] した結果を |file_handler:ordered map| とする。
    2. |file_handler| が failure の場合、[=iteration/continue=]。
    3. |file_handler| を |processedFileHandlers| に [=list/Append=] する。

[=installation=] 時に、ユーザーエージェントは [=register file handlers=] する処理を実行するべきである。

File Handler 項目

file handler は、 アプリケーションのスコープ内の URL であって、それが受け入れる [=file types=] を伴う起動を処理できるものを表す。 これは次のメンバーを持つ:

ユーザーエージェントは、これらのメンバーを使用して Web アプリケーションを オペレーティングシステム上の [=file type=] と関連付けることができる。

file type は [=MIME type=] および/または [=file extension=] によって定義できる。OS がそのファイルに [=MIME type=] があると判断する場合、またはその名前が特定の [=file extension=] で終わる場合、そのファイルは file type に属する。 file extension は "." で始まり、 有効な suffix code pointsのみを含む文字列である。さらに、[=file extensions=] は 16 コードポイントの長さに制限される。

`action` メンバー

[=file handler=] の action メンバーは、 manifest URL に 相対的な URL を表す string であり、 処理済み manifest の [=manifest/within scope=] である。 この URL は [=execute a file handler launch=] する手順でナビゲートされる。

`name` メンバー

[=file handler=] の name メンバーは、 ユーザーに対して file type を識別する string である。 [=User agents=] は、file handler の登録中にこの情報を オペレーティングシステムへ渡してもよい。

`icons` メンバー

file handlericons メンバーは、 [=file type=] のグラフィカルな表現として機能するアイコンを列挙する。 ユーザーエージェントは、file handler の登録中にこの情報を オペレーティングシステムへ渡してもよい。

`accept` メンバー

[=file handler=] の accept メンバーは、 [=MIME types=] を [=file extensions=] のリストに対応付ける dictionary である。

[=User agents=] は、[=file handler/accept=] エントリが一致する拡張子を 持つファイルにのみ適用されることを強制しなければならない。

[=register file handlers=] するために、一部のオペレーティングシステムは [=MIME types=] を必要とし、一部は [=file extensions=] を必要とする。 したがって manifest は、各 [=file handler/accept=] エントリについて常に両方を提供しなければならない。

完全な [=MIME types=] に加えて、たとえば "image/*" ですべての画像形式を(提供された [=file extensions=] のリストにも適用されるものとして)照合するために、 [=MIME type=] の subtype として "*" を使用できる。

`launch_type` メンバー

[=file handler=] の launch_type メンバーは、 この handler にルーティングされたファイルに対してアプリがどのように 起動されるかを決定する string である。可能な値は `"single-client"` と `"multiple-clients"` である。提供されない場合、 既定で `"single-client"` になる。

[=file handler=] が一連のファイルに一致すると判断された場合、 [=user agent=] は [=file handler/launch_type=] を使用して、アプリが 各ファイルに対して 1 回ずつ起動されるか (`"multiple-clients"`)、すべてのファイルに対して 1 回だけ起動されるか (`"single-client"`)を制御するべきである。{{LaunchParams/files}} を参照。 ユーザーエージェントは、異なる [=file handlers=] からのファイルを 1 つの起動イベントに結合してはならない。

file handler 項目の処理

[=ordered map=] |item:ordered map|、[=URL=] |start_url:URL|、 [=URL=] |scope:URL|、および [=URL=] |manifest URL:URL| が与えられたとき、 process a file handler item するには:

  1. 次のいずれかが true の場合、failure を返す:
    • |item|["action"] が [=map/exist=] しない、または [=string=] でない。
    • |item|["accept"] が [=map/exist=] しない。
    • |item|["accept"] が [=dictionary=] でない。
    • |item|["accept"] が [=map/is empty=] である。
  2. |url:URL| を、|manifest_url URL| を基底 URL として |item|["action"] を [=URL Parser|解析=] した結果とする。
  3. |url| が failure の場合、failure を返す。
  4. |url| が |scope| の [=manifest/within scope=] でない場合、 failure を返す。
  5. |launch_type:string| を、"single-client" で初期化された 新しい [=string=] とする。
  6. |item|["launch_type"] が [=map/exists=] し、 "multiple-clients" である場合、|launch_type| を |item|["launch_type"] に設定する。
  7. |accept:ordered map| を新しい [=ordered map=] とする。
  8. |item|["accept"] の |mime_type_string:string| → |extensions| について [=map/for each=]
    1. |extensions| が [=list=] でない場合、[=iteration/continue=]。
    2. |extensions| が [=list/empty=] の場合、[=iteration/continue=]。
    3. |extensions| が [=string=] でない項目を [=list/contains=] する場合、 [=iteration/continue=]。
    4. |extensions| が文字 `.` で始まらない文字列を [=list/contains=] する場合、 [=iteration/continue=]。
    5. |extensions| が 16 文字より長い文字列を [=list/contains=] する場合、 [=iteration/continue=]。
    6. |mime_type_string| に対して [=parse a mime type=] の手順を実行した結果を |mime_type_parsed:mime type| とする。
    7. |mime_type_parsed:mime type| が failure の場合、 [=iteration/continue=]。
    8. |mime_type_parsed/type| が [[IANA-MEDIA-TYPES]] における top-level type として列挙されていない場合、[=iteration/continue=]。
    9. |accept|[|mime_type_string|] を |extensions| に設定する。
  9. |accept:ordered map| が空の場合、failure を返す。
  10. |file_handler:ordered map| を |ordered map| «[ "action" → |url|, "name" → |item|["name"], "launch_type" → |launch_type|, "accept" → |accept| ]» とする。
  11. |item|["icons"]、|file_handler|、 |manifest URL|、および "icons" を渡して、 画像リソースを 処理する
  12. |file_handler| を返す。

file handler 起動の実行

execute a file handler launch する手順は、 次のアルゴリズムで与えられる。このアルゴリズムは [=list=] |files:list| と、 [=processing a manifest=] からの結果を保持する [=ordered map=] |manifest:ordered_map| を取る。

  1. |file_handlers:list| を |manifest|["file_handlers"] とする。
  2. |file_handlers:list| が null の場合、戻る。
  3. |launches:ordered map| を [=ordered map=] とする。
  4. |files| の |filename:string| それぞれについて [=list/for each=]
    1. |file_handlers:list| の |file_handler:ordered_map| それぞれについて [=list/for each=]:
      1. |file_handler|["accept"] の |mime_type_string:string| → |extensions:list| について [=map/for each=]
        1. |extensions| の |extension:string| それぞれについて [=list/for each=]:
          1. |filename| が |extension| で終わらない場合、 [=iteration/continue=]。
          2. |launches|[|file_handler|] が [=map/exists=] する場合、 |filename| を |launches|[|file_handler|] に [=list/append=] する。
          3. そうでない場合、|launches|[|file_handler|] を 単一要素 |filename| を持つ [=list=] に設定する。
          4. |files| の次の要素へ [=iteration/Continue=] する。
  5. |launches| の |file_handler| → |files:list| について [=map/for each=]
    1. |file_handler|["launch_type"] が "multiple-clients" に等しい場合
      1. |files| の |file| それぞれについて [=list/for each=]
        1. {{LaunchParams/targetURL}} を |file_handler|["action"] に設定し、{{LaunchParams/files}} を |file| に対応する単一の {{FileSystemHandle}} 要素を持つ {{FrozenArray}} に設定した、新しい {{LaunchParams}} |params:LaunchParams| とする。
        2. |manifest| と |params| を渡して [=Launch a web application with handling=]。
    2. そうでない場合、
      1. {{LaunchParams/targetURL}} を |file_handler|["action"] に設定し、 {{LaunchParams/files}} を |files| によって名付けられたファイルパスに 対応する {{FileSystemHandle}} の {{FrozenArray}} に設定した、 新しい {{LaunchParams}} |params:LaunchParams| とする。
      2. |manifest| と |params| を渡して [=Launch a web application with handling=]。

file handler の登録

ユーザーエージェントは、次と整合するように、ホスト オペレーティングシステムに register file handlers するべきである:

ユーザーエージェントは、機能を維持し乱用を防ぐため、 [=file extensions=] の総集合を切り詰めてもよい。 ユーザーエージェントは、特定の filetypes との関連付けを防いでもよい。

プライバシー上の考慮事項:既定の file handler。

オペレーティングシステムの機能によっては、[=file handler=] はユーザーが 明示的に知ることなく、与えられた [=file type=] の既定 handler となり、 与えられた file type の起動を自動的に処理する可能性がある。 起こり得る悪用を防ぐため、[=user agents=] は [=execute a file handler launch=] する処理を開始するために、 明示的なユーザー同意を要求してもよい。同意が求められる場合、 ユーザーエージェントは、その決定が永続的であることをユーザーが指定できるように するべきであり、そのように指定された場合は、Web アプリケーションの OS 登録を file handling entity として削除するべきである。

プライバシー上の考慮事項:名前とアイコン。

各 file handler の名前とアイコンは、ユーザーがそれらを確認するための 指定された方法がないため、プライバシーおよびセキュリティ上センシティブで あり得る。このため、[=user agents=] は、代替の文字列やアイコンを優先して これらを無視する、または OS の既定値へフォールバックすることを選択してもよい。

file handler を持つ manifest の例

次の例では、Web アプリケーションは 3 つの異なる file handler を持つ。

`related_applications` メンバー

related application は、基盤となるアプリケーションプラットフォームから アクセス可能であり、Web アプリケーションと関係を持つアプリケーションである。

[=manifest's=] related_applications メンバーは related applications を列挙し、Web アプリケーションと related applications の間のそのような関係を示すものとして機能する。 この関係は一方向であり、列挙されたアプリケーションが同じ関係を主張しない限り、 user agent は双方向の endorsement を仮定してはならない。

`related_applications` の使用例としては、その情報を使用して Web アプリケーションに 関する詳細情報を収集する crawler、またはユーザーが Web アプリケーションを インストールしたい場合に、列挙されたアプリケーションを代替として提案する ブラウザーなどが考えられる。

[=ordered map=] |json:ordered map| および [=ordered map=] |manifest:ordered map| が与えられたとき、 process the `related_applications` member するには:

  1. |relatedApplications:list| を新しい [=list=] とする。
  2. |manifest|["related_applications"] を |relatedApplications| に設定する。
  3. |json|["related_applications"] が [=map/exist=] しない、または |json|["related_applications"] が [=list=] でない場合、戻る。
  4. |json|["related_applications"] の app それぞれについて [=list/For each=]:
    1. app["id"] も app["url"] も 欠落していない場合:
      1. app["url"] を、 app["url"] が与えられたときに process the `url` member of an application を実行した結果に 設定する。
      2. apprelatedApplications に [=list/append=] する。
  5. relatedApplications を設定する。

`prefer_related_applications` メンバー

[=manifest's=] `prefer_related_applications` メンバーは、 related applications が Web アプリケーションより優先されるべきであると ユーザーエージェントに伝えるヒントとして使用される [=boolean=] である。 `prefer_related_applications` メンバーが `true` に設定されており、 ユーザーエージェントが Web アプリケーションのインストールを提案したい場合、 代わりに related applications の 1 つのインストールを提案したいと 考えるかもしれない。

`scope_extensions` メンバー

[=manifest's=] scope_extensions メンバーは、アプリケーションが望む [=scope extensions=] のリストを表す。

scope extension は、[=within extended scope=] として扱われるべき 追加の [=URLs=] を記述することで、[=manifest/navigation scope of a manifest=] を拡張する。

ユーザーエージェントは、追加の [=URLs=] を [=within extended scope=] と できるように [=apply extended scope=] する前に、 [=process the scope_extensions member=] および [=validate scope extensions=] しなければならない。

[=URL=] |target:URL| は、|target| が manifest の [=manifest/within scope=] である、または [=matches a validated scope extension=] である場合、 |manifest:processed manifest| の extended scope 内である。

[=URL=] |target:URL| は、[=URL=] |target:URL| と [=list=] |validated_scope_extensions:list| が与えられたときに 次のアルゴリズムが `true` を返す場合、検証済み scope extension に一致する

  1. |validated_scope_extensions:list| の |entry:ordered map| それぞれについて [=list/For each=]:
    1. |entry| が [=ordered map=] でない、または |entry|["scope"] が [=map/exist=] しない、または [=URL=] でない場合、続行する。
    2. [=URL=] |resolved_scope:URL| を |entry:ordered map|["scope"] とする。
    3. |target| が |resolved_scope| の [=URL/within scope=] である場合、 `true` を返す。
  2. `false` を返す。

使用例

次の例は、`scope_extensions` メンバーを使用するアプリケーションの [=manifest=] を示す。

          {
            "id": "https://example.com/app",
            "name": "My App",
            "icons": [{
              "src": "icon/hd_hi",
              "sizes": "128x128"
            }],
            "start_url": "/app/index.html",
            "scope": "/app",
            "display": "standalone",
            "scope_extensions": [
              { "type": "origin", "origin": "https://example.co.uk" },
              { "type": "origin", "origin": "https://help.example.com" }]
          }
        

次は、`scope_extensions` メンバーに列挙された [=origins=] の `.well-known` パスからダウンロードできる 2 つの [=web-app-origin-association=] ファイルを示す。

          {
            "https://example.com/app": {
              "scope": "/app"   
            }
          }
        
          {
            "https://example.com/app": {
              "scope": "/"   
            }
          }
        

このアプリの navigation scope は、次の [=URLs=] のいずれかの [=URL/within scope=] である URL から成る: `https://example.com/app`, `https://example.co.uk/app`, および `https://help.example.com`。

`scope_extensions` メンバーの処理

[=ordered map=] |json:ordered map|、[=ordered map=] |manifest:ordered map|、 および [=URL=] |manifest_id:URL| が与えられたとき、 process the `scope_extensions` member するには:

  1. |processedScopeExtensions:list| を新しい [=list=] とする。
  2. |manifest|["scope_extensions"] を |processedScopeExtensions| に設定する。
  3. |json|["scope_extensions"] が [=map/exist=] しない、または [=list=] でない場合、戻る。
  4. |json|["scope_extensions"] の |entry:ordered map| それぞれについて [=list/For each=]:
    1. |entry|["type"] または |entry|["origin"] が [=map/exist=] しない場合、 [=iteration/continue=]。
    2. |entry|["type"] が "origin" でない場合、[=iteration/continue=]。
    3. |entry|["origin"] が [=string=] でない場合、 [=iteration/continue=]。
    4. |entry|["origin"] を [=URL Parser|解析=] した結果を [=URL=] |origin_url:URL| とする。
    5. |origin_url| が [=URL/scheme=] "https" を持つ有効な |URL| である場合、 |entry|["origin"] を |origin_url| の [=URL/origin=] に設定する。
    6. そうでなければ [=iteration/continue=]。
    7. [=ordered map=] |entry:ordered map| および [=URL=] |manifest_id:URL| が与えられたとして、 [=validate scope extensions=] のアルゴリズムを用いて |entry| を検証する。
    8. 直前の手順が error を返した場合、 [=iteration/continue=]。
    9. そうでない場合、|entry|["scope"] を返された [=URL=] に設定する。
    10. |entry| を |processedScopeExtensions| に [=list/Append=] する。

scope extensions の検証

[=ordered map=] |extension:ordered map| および [=URL=] |manifest_id:URL| が 与えられたとき、validate scope extensions するには:

  1. |extension|["origin"] の [=URL/origin=] の [=URL=] を [=URL=] |origin_url:URL| とする。
  2. |origin_url| を基底 [=URL=] として "/.well-known/web-app-origin-association" を [=URL Parser|解析=] した結果を [=URL=] |download_url:URL| とする。
  3. |download_url| を与えて [=fetch=] した結果を [=ordered map=] |json:ordered map| とする。
  4. [=fetch=] が失敗した場合、error を返す。
  5. |json|[|manifest_id|] が [=map/exist=] しない、または [=ordered map=] でない場合、error を返す。
  6. |scope:string| を [=string=] "/" とする。
  7. |json|[|manifest_id|]["scope"] が [=map/exists=] し、 [=string=] である場合、|scope| を |json|[|manifest_id|]["scope"] に設定する。
  8. |extension|["origin"] を基底 [=URL=] として |scope| を [=URL Parser|解析=] した結果を [=URL=] |resolved_scope:URL| とする。
  9. |resolved_scope| を返す。

scope extensions の適用

ユーザーエージェントは、シナリオによって apply extended scope を 適用し、別のシナリオでは [=manifest/scope=] を適用することを選択してもよい。

[=application context=] の [=navigable/active document=] の [=URL=] が [=manifest/within scope=] ではないが [=within extended scope=] である場合、ユーザーエージェントは、ユーザーがその [=URL=] または 少なくともその [=origin=] を判断できる UI を提供するべきであり、 それが安全な接続で提供されているかどうかも含めるべきである。 この UI は、[=URL=] が [=application context=] の [=Document/processed manifest=] の [=manifest/within scope=] でない場合に 使用される UI とは異なるべきである。これは、ユーザーがアプリケーションの 意図された内容をナビゲートしていることを明確にしつつ、異なる [=origin=] へナビゲートすることのプライバシーおよびセキュリティ上の 影響についてユーザーに情報を与え続けるためである。

web-app-origin-association ファイル

web-app-origin-association ファイルは、[=validate scope extensions=] または [=validate origin migration=] に使用できる JSON ファイルである。それは、自身が存在する origin と 1 つ以上の Web アプリケーションとの関連付けを確認する。 これは manifest [=manifest/ids=] を参照することによってアプリを一意に識別する。

[=origin=] |origin:origin| が与えられた場合、 [=web-app-origin-association=] ファイルは [origin]/.well-known/web-app-origin-association からダウンロード可能であることが期待される。

Web Application Origin Migration

Web Application Origin Migration は、Web アプリケーションがユーザーエージェントに対して、 ある origin から別の origin(同じ site 内)へ移動したことを示せるようにする。 これにより、ユーザーエージェントは、ユーザーのインストールおよび場合によっては その設定を保持しながら、インストール済み Web アプリケーションを移行できる。

使用例

次の例は、https://old.example.com でホストされていた Web アプリケーションを https://new.example.com へ移行する方法を示す。 両方の origins は [=same site=] でなければならず、移行に明示的に 同意しなければならない。

まず、古いアプリケーションの manifest は、ユーザーエージェントに移動する 意図を知らせるために、任意で `migrate_to` メンバーを含めることができる (あるいは古いアプリケーションが新しいアプリケーションへリダイレクトできる):

          {
            "name": "My App",
            "id": "/",
            "migrate_to": {
              "id": "https://new.example.com/",
              "install_url": "https://new.example.com/install"
            }
          }
        

次に、新しいアプリケーションの manifest は、古いアプリケーションからの 移行を主張するために `migrate_from` メンバーを含める:

          {
            "name": "My New App",
            "id": "/",
            "migrate_from": [
              {
                "id": "https://old.example.com/",
                "install_url": "https://old.example.com/install",
                "behavior": "force"
              }
            ]
          }
        

最後に、古い origin は、新しいアプリケーションによる引き継ぎを許可することを 確定的に検証するために、`web-app-origin-association` ファイルをホストしなければ ならない。このファイルがないと、悪意ある新しいアプリケーションが許可なく 古いアプリケーションからの移行を主張できる。

          {
            "https://new.example.com/": {
              "allow_migration": true
            }
          }
        

migrate_from メンバー

[=manifest/migrate_from=] メンバーは、移行元である古い Web アプリケーションを識別する [=strings=] または [=ordered maps=] の [=list=] である。

エントリが [=string=] である場合、それは古いアプリケーションの [=manifest/id=] として扱われる。

エントリが [=ordered map=] である場合、次のメンバーを持つことができる:

ユーザーエージェントが [=manifest/migrate_from=] メンバーを処理するには、 manifest はその JSON 内に有効で明示的な id メンバーも含む必要がある。

migrate_to メンバー

[=manifest/migrate_to=] メンバーは、新しいアプリケーションへの移行を 先回りして通知する任意の [=ordered map=] である。これは次のメンバーを持つ:

origin migration の検証

[=URL=] |old_manifest_id:URL| および [=URL=] |new_manifest_id:URL| が 与えられたとき、validate origin migration するには:

  1. |old_manifest_id| の [=URL/origin=] と |new_manifest_id| の [=URL/origin=] が [=same site=] でない場合、error を返す。
  2. |old_manifest_id| の [=URL/origin=] が |new_manifest_id| の [=URL/origin=] と [=same origin=] である場合、success を返す。
  3. |old_manifest_id| の [=URL/origin=] の [=URL=] を [=URL=] |origin_url:URL| とする。
  4. |origin_url| を基底 [=URL=] として "/.well-known/web-app-origin-association" を [=URL Parser|解析=] した結果を [=URL=] |download_url:URL| とする。
  5. |download_url| を与えて [=fetch=] した結果を [=ordered map=] |json:ordered map| とする。
  6. [=fetch=] が失敗した場合、error を返す。
  7. |json|[|new_manifest_id|] が [=map/exist=] しない、または [=ordered map=] でない場合、error を返す。
  8. |json|[|new_manifest_id|]["allow_migration"] が `true` でない場合、 error を返す。
  9. success を返す。

`migrate_from` メンバーの処理

[=ordered map=] |json:ordered map|、[=ordered map=] |manifest:ordered map|、 および [=URL=] |manifest URL:URL| が与えられたとき、 process the `migrate_from` member するには:

  1. |json|["id"] が [=map/exist=] しない、または [=string=] でない場合、 戻る。
  2. |json|["id"] が空文字列の場合、戻る。
  3. |base_origin:origin| を |manifest|["start_url"] の [=URL/origin=] とする。
  4. |id_url:URL| を、|base_origin| を基底 URL として |json|["id"] を [=URL Parser|解析=] した結果とする。
  5. |id_url| が failure の場合、戻る。
  6. |id_url| が |manifest|["start_url"] と [=same origin=] でない場合、 戻る。
  7. |processed_migrate_from:list| を新しい [=list=] とする。
  8. |manifest|["migrate_from"] を |processed_migrate_from| に設定する。
  9. |json|["migrate_from"] が [=map/exist=] しない、または [=list=] でない場合、戻る。
  10. |json|["migrate_from"] の |entry| それぞれについて [=list/For each=]:
    1. |processed_entry:ordered map| を新しい [=ordered map=] とする。
    2. |entry| が [=string=] の場合:
      1. |manifest URL| を基底 URL として |entry| を [=URL Parser|解析=] した結果を |id:URL| とする。
      2. |id| が failure の場合、[=iteration/continue=]。
      3. |processed_entry|["id"] を |id| に設定する。
    3. そうでなく、|entry| が [=ordered map=] の場合:
      1. |entry|["id"] が [=map/exist=] しない、または [=string=] でない場合、[=iteration/continue=]。
      2. |manifest URL| を基底 URL として |entry|["id"] を [=URL Parser|解析=] した結果を |id:URL| とする。
      3. |id| が failure の場合、[=iteration/continue=]。
      4. |processed_entry|["id"] を |id| に設定する。
      5. |entry|["install_url"] が [=map/exists=] し、 [=string=] である場合:
        1. |manifest URL| を基底 URL として |entry|["install_url"] を [=URL Parser|解析=] した結果を |install_url:URL| とする。
        2. |install_url| が failure でない場合、 |processed_entry|["install_url"] を |install_url| に設定する。
      6. |entry|["behavior"] が [=map/exists=] し、 [=string=] である場合:
        1. |entry|["behavior"] が "suggest" または "force" である場合、 |processed_entry|["behavior"] を |entry|["behavior"] に設定する。
    4. そうでなければ、[=iteration/continue=]。
    5. [=URL=] |processed_entry|["id"] および [=URL=] |id_url| が 与えられたとして、[=validate origin migration=] のアルゴリズムを 用いて |processed_entry|["id"] を検証する。
    6. 直前の手順が error を返した場合、 [=iteration/continue=]。
    7. |processed_entry| を |processed_migrate_from| に [=list/Append=] する。

`migrate_to` メンバーの処理

[=ordered map=] |json:ordered map|、[=ordered map=] |manifest:ordered map|、 および [=URL=] |manifest URL:URL| が与えられたとき、 process the `migrate_to` member するには:

  1. |json|["migrate_to"] が [=map/exist=] しない、または [=ordered map=] でない場合、戻る。
  2. |entry:ordered map| を |json|["migrate_to"] とする。
  3. |entry|["id"] が [=map/exist=] しない、または [=string=] でない場合、 戻る。
  4. |manifest URL| を基底 URL として |entry|["id"] を [=URL Parser|解析=] した結果を |id:URL| とする。
  5. |id| が failure の場合、戻る。
  6. |processed_migrate_to:ordered map| を新しい [=ordered map=] とする。
  7. |processed_migrate_to|["id"] を |id| に設定する。
  8. |entry|["install_url"] が [=map/exists=] し、[=string=] である場合:
    1. |manifest URL| を 基底 URL として |entry|["install_url"] を [=URL Parser|解析=] した結果を |install_url:URL| とする。
    2. |install_url| が failure でない場合、 |processed_migrate_to|["install_url"] を |install_url| に設定する。
  9. |manifest|["migrate_to"] を |processed_migrate_to| に設定する。

プライバシーおよびセキュリティの考慮事項

悪意ある主体がアプリケーションを密かに乗っ取ること(例:単純な電卓が自身を更新して 銀行アプリを模倣すること)を防ぐため、[=validate origin migration=] アルゴリズムは 双方向のハンドシェイクを強制する。新旧両方のアプリケーション origin は、 [=web-app-origin-association=] ファイルを介して移行に明示的に同意しなければならない。

さらに、移行は [=same site=] であることに制限され、未検証の第三者へ所有権を移すのではなく、 組織の管理下での正当なリブランディングおよびアーキテクチャ変更に使用されることを保証する。

ユーザーエージェントは、特にセキュリティ上センシティブなフィールド (アプリ名やアイコンなど)の更新が含まれる場合、移行フローの一部として 明示的なユーザー確認ダイアログを含めることを検討するべきである。

外部アプリケーションリソース

外部 アプリケーションリソースは、Web アプリケーションに関連する アプリケーションを表す。

[=external application resource=] は次のメンバーを持つことができ、 その一部は [=valid external application resource=] であるために必須である:

valid external application resource は、 [=external application resource/platform=] メンバー、および [=external application resource/url=] または [=external application resource/id=] メンバー(またはその両方)を持たなければならない。

`platform` メンバー

platform メンバーは、 この [=external application resource=] が関連付けられている [=platform=] を表す。platform は、 ソフトウェア配布エコシステム、または場合によってはオペレーティングシステムを 表す。この仕様は platform メンバーの特定の値を定義しない。

`url` メンバー

[=external application resource's=] url メンバーは、 アプリケーションを見つけることができる URL である。

process the `url` member of an application するには:

  1. application URL が欠落している場合、null を返す。
  2. そうでなければ、application URL を [=URL Parser|解析=] し、 結果が failure でない場合、その結果を返す。そうでなければ null を返す。

`id` メンバー

[=external application resource's=] id メンバーは、 プラットフォーム上でアプリケーションを表すために使用される id を表す。

`min_version` メンバー

[=external application resource's=] min_version メンバーは、 この Web アプリに関連すると見なされるアプリケーションの最小バージョンを表す。 このバージョンは、プラットフォーム固有の構文および意味を持つ string である。

`fingerprints` メンバー

[=external application resource's=] fingerprints メンバーは、 [=fingerprints=] の [=list=] を表す。

fingerprint は、 アプリケーションの検証に使用される暗号学的 fingerprint の集合を表す。 fingerprint は次の 2 つのメンバーを持つ:typevalue。これらはいずれも string であるが、その構文と意味はプラットフォーム定義である。

インストールプロンプト

インストール処理は、複数の方法でトリガーされ得る:

いずれの場合も、文書が installable でない場合、ユーザーエージェントは present an install prompt してはならない。

ユーザーエージェントは、文書が installable である場合に限り、任意の時点で steps to notify that an install prompt is available を 任意の時点で実行してもよく、サイトに、ユーザーがユーザーエージェント UI と 対話する必要なく site-triggered install prompt を表示する機会を与える。

インストールプロンプトを 提示するには:

  1. ユーザーエージェント固有の UI を表示し、アプリのインストールを進めるかどうかを ユーザーに尋ねる。この選択の result は、 {{AppBannerPromptOutcome/"accepted"}} または {{AppBannerPromptOutcome/"dismissed"}} のいずれかである。
  2. result を返し、in parallel で:
    1. result が {{AppBannerPromptOutcome/"accepted"}} の場合、 steps to install the web application を実行する。

steps to notify that an install prompt is available は、 次のアルゴリズムで与えられる:

  1. top-level browsing context の {{Document}} が 完全に 読み込まれるまで待つ。
  2. 提示中の install prompt がすでに 存在する場合、または steps to install the web application が現在 実行中である場合、この手順を中止する。
  3. 次を行うために、application life-cycle task source 上で Queue a task する:
    1. {{Event/cancelable}} 属性を `true` に初期化する手順を伴い、 {{BeforeInstallPromptEvent}} インターフェイスを使用して、 [=top-level browsing context=] の [=relevant global object=] で `"beforeinstallprompt"` という名前の [=fire an event=] をした結果を |mayShowPrompt| とする。
    2. |mayShowPrompt| が true の場合、ユーザーエージェントは in parallel で、|event| とともに request to present an install prompt してもよい。

Installable web applications

Installation 処理

steps to install the web application は次のアルゴリズムで与えられる:

  1. manifest を、installable document の manifest とする。
  2. ユーザーのオペレーティングシステムに Web アプリケーションを登録しようとするため、 未指定の一連のアクションを実行する(例:Web アプリケーションを起動する ショートカットを作成する、システムのアンインストールメニューに アプリケーションを登録する、など)。インストールが失敗した場合 (これは任意の理由で起こり得る。たとえば、OS がユーザーエージェントに デバイスのホーム画面へアイコンを追加する許可を拒否する場合など)、 これらの手順を中止する。
  3. インストールが行われた [=top-level browsing context=] の [=relevant global object=] で `"appinstalled"` という名前の fire an event をするために、 application life-cycle task source 上で Queue a task する。

インストール可能性シグナル

設計上、この仕様は、Web アプリケーションを「インストール」するための 明示的な API を開発者に提供しない。代わりに、 manifest は、Web アプリケーションがインストール可能であることを ユーザーエージェントに示す installability signal として機能できる。 これらのシグナルはユーザーエージェントごとに異なる。各ユーザーエージェントは、 Web サイトがインストールプロンプトに適格であるかどうかを判断するための 独自のヒューリスティックを持つためである。実装者は一般に、 特定の installabilty signals や、Web アプリケーションが installable と見なされるために 満たす必要があるその他の関連基準を説明する文書を提供する。

ユーザーエージェントが実装する可能性のある Web アプリケーションの installability signals の例:

このリストは網羅的ではなく、一部の installability signals は すべてのユーザーエージェントに適用されない場合がある。ユーザーエージェントが これらの installability signals をどのように使用して Web アプリケーションがインストール可能かを判断するかは、実装者に委ねられる。

インストールイベント

この仕様の [=event|イベント=] は、application life-cycle task source に依存する。

BeforeInstallPromptEvent インターフェイス

beforeinstallprompt イベントは、必ずしも manual installation が続くことを示すわけではないため、 やや誤った名前である(ユーザーエージェントによっては、サイトに インストールプロンプトをトリガーする能力を与えるだけの場合がある)。 歴史的な理由からこの名前になっている。
          [Exposed=Window]
          interface BeforeInstallPromptEvent : Event {
            constructor(DOMString type, optional EventInit eventInitDict = {});
            Promise<PromptResponseObject> prompt();
          };

          dictionary PromptResponseObject {
            AppBannerPromptOutcome userChoice;
          };

          enum AppBannerPromptOutcome {
            "accepted",
            "dismissed"
          };
        

{{BeforeInstallPromptEvent}} は、サイトが site-triggered install prompt を提示することを許可されたとき、 またはユーザーエージェントが automated install prompt を提示する前に dispatch される。これは、サイトが automated install prompt を cancel できるようにし、さらに site-triggered install prompt を 手動で提示できるようにする。

{{BeforeInstallPromptEvent}} が cancel されない場合、 ユーザーエージェントはエンドユーザーに対して present an install prompt することが許可される (具体的には automated install prompt)。 既定動作を cancel すること({{Event/preventDefault()}} による)は、 ユーザーエージェントが presenting an install prompt することを防ぐ。 ユーザーエージェントは、後で再び steps to notify that an install prompt is available を自由に実行できる。

PromptResponseObject は {{BeforeInstallPromptEvent/prompt()}} を呼び出した結果を含む。 それは 1 つのメンバー、 userChoice を含み、 ユーザーが選択した結果を表す。

{{BeforeInstallPromptEvent}} のインスタンスは、次の内部スロットを持つ:

[[\didPrompt]]
初期値 `false` の boolean。このイベントがエンドユーザーに present an install prompt するために使用されたかどうかを表す。
[[\userResponsePromise]]
presenting an install prompt の結果を表す promise。

prompt() メソッド

prompt メソッドは、呼び出されたときに次の手順を実行する:

  1. {{BeforeInstallPromptEvent/[[userResponsePromise]]}} を |userResponsePromise| とする。
  2. |userResponsePromise| が pending の場合:
    1. [=this=].{{BeforeInstallPromptEvent/[[didPrompt]]}} が `true` の場合、このアルゴリズムを終了する。
    2. このイベントの {{Event/isTrusted}} 属性が `false` の場合、 |userResponsePromise| を {{"NotAllowedError"}} で reject し、 このアルゴリズムを終了する。
    3. [=this=].{{BeforeInstallPromptEvent/[[didPrompt]]}} を `true` に設定する。
    4. In parallel で、[=this=] とともに request to present an install prompt する。エンドユーザーが選択するまで、 場合によっては無期限に待つ。
  3. |userResponsePromise| を返す。

{{BeforeInstallPromptEvent}} event とともに request to present an install prompt するには:

  1. Present an install prompt し、その結果を |outcome| とする。
  2. |response| を、新しく作成された {{PromptResponseObject}} とし、 その {{PromptResponseObject/userChoice}} を |outcome| に初期化する。
  3. |event|.{{BeforeInstallPromptEvent/[[userResponsePromise]]}} を |response| で [=Resolve=] する。

使用例

この例は、ユーザーがボタンをクリックして site-triggered install prompt を表示するまで、 automated install prompt が表示されないようにする方法を示す。 このようにして、サイトは、任意の時点でプロンプトするのではなく、 インストールをユーザーの裁量に任せつつ、そのための目立つ UI を提供できる。

              window.addEventListener("beforeinstallprompt", event => {
                // Suppress automatic prompting.
                event.preventDefault();

                // Show the (disabled-by-default) install button. This button
                // resolves the installButtonClicked promise when clicked.
                installButton.disabled = false;

                // Wait for the user to click the button.
                installButton.addEventListener("click", async e => {
                  // The prompt() method can only be used once.
                  installButton.disabled = true;

                  // Show the prompt.
                  const userChoice = await event.prompt();
                  console.info(`user choice was: ${userChoice}`);
                });
              });
            

AppBannerPromptOutcome enum

AppBannerPromptOutcome enum の値は、 presenting an install prompt からの結果を表す。

"accepted":
エンドユーザーは、ユーザーエージェントに Web アプリケーションを インストールしてほしいことを示した。
"dismissed":
エンドユーザーは install prompt を退けた。

`Window` オブジェクトへの拡張

          partial interface Window {
            attribute EventHandler onappinstalled;
            attribute EventHandler onbeforeinstallprompt;
          };
        

onappinstalled 属性

onappinstalled event handler IDL attribute は "appinstalled" イベントを処理する。

onbeforeinstallprompt 属性

onbeforeinstallprompt event handler IDL attribute は "beforeinstallprompt" イベントを処理する。