1. はじめに
サブアプリ API を使用すると、親アプリケーションは、次の条件を満たす補助 アプリケーション(サブアプリ)をプログラムによってインストール、一覧表示、および削除できます。
-
オペレーティングシステムおよびユーザーには、完全に独立したアプリケーションとして表示されます(個別のランチャーアイコン、 独立したタスクバー/シェルフウィンドウ、および個別の OS 統合)。
-
基盤となるリソース、オリジン、ストレージ、権限、および更新ライフサイクルを親 アプリケーションと共有します。
この API は、セキュリティとデータ整合性を確保するため、分離コンテキストに制限されています。
2. 概念
インストール済みウェブアプリケーションには、関連付けられた親アプリがあり、その値は null、またはインストール済みウェブアプリケーションです。
インストール済みウェブアプリケーションには、関連付けられたサブアプリ集合があり、これは集合であり、インストール済みウェブアプリケーションを要素として持ちます。
Document
には、関連付けられたインストール済みウェブアプリケーションがあり、これは
その Document
が一部として提示されるインストール済みウェブアプリケーションです。この関連付けの正確な機構は実装定義です。
Document
は、関連付けられたインストール済みウェブアプリケーションを持ち、かつ
その関連付けられたインストール済みウェブアプリケーションの
親アプリが null でない場合、サブアプリ文書です。
3. Window
インターフェイスの拡張
[Exposed =Window ,SecureContext ,IsolatedContext ]partial interface Window { [SameObject ]readonly attribute SubApps subApps ; };
3.1. subApps
属性
各 Window
オブジェクトには、関連付けられた subApps があり、これは SubApps インスタンスであり、
Window
とともに作成されます。
4. SubApps
インターフェイス
// https://w3c.github.io/manifest/#id-member を表しますtypedef USVString ;ManifestId dictionary {SubAppsAddResponse record <USVString ,ManifestId >;installedApps record <USVString ,DOMException >; };failedApps dictionary {SubAppsRemoveResponse sequence <ManifestId >;removedApps record <USVString ,DOMException >; };failedApps dictionary {SubAppsListResult required DOMString ; }; [appName Exposed =Window ,SecureContext ,IsolatedContext ]interface {SubApps Promise <SubAppsAddResponse >(add sequence <USVString >);install_paths Promise <SubAppsRemoveResponse >(remove sequence <ManifestId >);manifest_ids Promise <record <USVString ,SubAppsListResult >>(); };list
文字列 path は、次のすべての条件を満たす場合、Document
document に対する有効な相対パスです。
-
path は有効な絶対 URL ではありません。
-
path は
"/"で始まります。 -
path は空ではありません。
-
path は
"//"で始まりません。
4.1. add()
メソッド
add(install_paths)
メソッドの手順は、次のとおりです。
install_paths
引数は、サブアプリの開始 HTML ページを指す相対パスのリストです。
-
promise を新しい プロミスとする。
-
document を、関連するグローバルオブジェクトの関連付けられた Documentとする。
-
document が、"sub-apps" という名前のポリシー制御対象機能を使用することを許可されていない場合、promise を "
SecurityError"DOMExceptionで拒否し、promise を返す。 -
document がサブアプリ文書である場合、promise を "
NotSupportedError"DOMExceptionで拒否し、promise を返す。 -
parsedUrls を空のリストとする。
-
install_paths内の各 installPath に対して、以下を反復する:-
installPath が document に対する有効な相対パスでない場合、promise を "
TypeError"DOMExceptionで拒否し、promise を返す。 -
absoluteUrl を、document の文書基底 URLを基底 URL として installPath を構文解析した結果とする。
-
absoluteUrl が失敗である場合、promise を "
TypeError"DOMExceptionで拒否し、 promise を返す。 -
absoluteUrl を parsedUrls に付加する。
-
-
parentApp を、document の関連付けられたインストール済みウェブ アプリケーションとする。
-
install_pathsの サイズが 20 より大きい場合、promise を "QuotaExceededError"DOMExceptionで拒否し、promise を返す。 -
currentSubAppsCount +
install_pathsの サイズが 50 より大きい場合、promise を "QuotaExceededError"DOMExceptionで拒否し、promise を返す。 -
subApps をthisとする。
-
以下の手順を並列に実行する:
-
userConsent を、
install_paths内のサブアプリをインストールするためのユーザーの同意を要求した結果とする (例えば、統合されたインストールダイアログを提示することによる)。 -
userConsent が拒否された場合、subApps の関連するグローバルオブジェクト上でグローバルタスクをキューに入れ、promise を "
NotAllowedError"DOMExceptionで拒否させ、 これらの手順を中止する。 -
installedApps を空のマップとする。
-
failedApps を空のマップとする。
-
parsedUrls 内の各 absoluteUrl に対して、以下を反復する:
-
installPath を、absoluteUrl のパスとする。
-
manifest を、absoluteUrl を与えてマニフェストをフェッチして処理する 結果とする。
-
manifest が失敗である場合、以下の手順を実行する:
-
failedApps[installPath] を新しい "
DataError"DOMExceptionに設定する。 -
継続する。
-
-
manifestId を manifest のidとする。それが 定義されていない場合、manifest のstart_url(参照/ハッシュフラグメントを除く)にフォールバックする。
-
parentApp に manifestId を持つサブアプリがすでにインストールされている場合、 以下の手順を実行する:
-
failedApps[installPath] を新しい "
InvalidStateError"DOMExceptionに設定する。 -
継続する。
-
-
parentApp のマニフェストのscopeが manifest のscopeの接頭辞であるか、manifest のscopeが、parentApp のサブアプリセット内の 現在インストールされているいずれかのサブアプリのscopeの接頭辞であるか、parentApp のサブアプリセット内の 現在インストールされているいずれかのサブアプリのscopeが manifest のscopeの接頭辞であるか、または absoluteUrl が parentApp のマニフェスト自体を指している場合、以下の手順を実行する:
-
failedApps[installPath] を新しい "
ConstraintError"DOMExceptionに設定する。 -
継続する。
-
-
プラットフォームのアプリケーションランチャーにサブアプリをインストールすることを試みる。
-
システムまたはデータベースのエラーが原因でインストールに失敗した場合:
-
failedApps[installPath] を新しい "
OperationError"DOMExceptionに設定する。 -
継続する。
-
-
installedApps[installPath] を manifestId に設定する。
-
-
response を、以下を持つ新しい
SubAppsAddResponse辞書とする:-
installedAppsを installedApps に設定する。 -
failedAppsを failedApps に設定する。
-
-
グローバルタスクをキューに入れ、subApps の関連するグローバルオブジェクト上で、 promise を response で解決させる。
-
-
promise を返す。
4.2. remove()
メソッド
manifest_ids
引数は、削除するサブアプリの id のリストです。
remove(manifest_ids)
メソッドの手順は、次のとおりです。
-
promise を新しい プロミスとする。
-
document を、関連するグローバルオブジェクトの関連付けられた Documentとする。
-
document が、"sub-apps" という名前のポリシー制御対象機能を使用することを許可されていない場合、promise を "
SecurityError"DOMExceptionで拒否し、promise を返す。 -
document がサブアプリ文書である場合、promise を "
NotSupportedError"DOMExceptionで拒否し、promise を返す。 -
parentApp を、document の関連付けられたインストール済みウェブ アプリケーションとする。
-
parsedManifestIds を空のリストとする。
-
manifest_ids内の各 manifestId に対して、以下を反復する:-
manifestId が document に対する有効な相対パスでない場合、promise を "
TypeError"DOMExceptionで拒否し、promise を返す。 -
parsedUrl を、document の文書基底 URLを基底 URL として manifestId を構文解析した結果とする。
-
parsedUrl が失敗である場合、promise を "
TypeError"DOMExceptionで拒否し、 promise を返す。 -
parsedUrl を parsedManifestIds に付加する。
-
-
subApps をthisとする。
-
以下の手順を並列に実行する:
-
removedApps を空のシーケンスとする。
-
failedApps を空のマップとする。
-
parsedManifestIds 内の各 parsedUrl に対して、以下を反復する:
-
manifestId を、parsedUrl のパスとする。
-
parentApp のサブアプリセット内に、id が manifestId であるインストール済みウェブアプリケーションが存在しない場合、以下の 手順を実行する:
-
failedApps[manifestId] を新しい "
NotFoundError"DOMExceptionに設定する。 -
継続する。
-
-
ID manifestId を持つサブアプリを、システムのランチャーおよびレジストリから アンインストールすることを試みる。
-
システムエラーが原因でアンインストールに失敗した場合、以下の手順を実行する:
-
failedApps[manifestId] を新しい "
OperationError"DOMExceptionに設定する。 -
継続する。
-
-
manifestId を removedApps に付加する。
-
-
response を、以下を持つ新しい
SubAppsRemoveResponse辞書とする:-
removedAppsを removedApps に設定する。 -
failedAppsを failedApps に設定する。
-
-
グローバルタスクをキューに入れ、subApps の関連するグローバルオブジェクト上で、 promise を response で解決させる。
-
-
promise を返す。
4.3. list()
メソッド
list()
メソッドの手順は、次のとおりです。
-
promise を新しい プロミスとする。
-
document を、関連するグローバルオブジェクトの関連付けられた Documentとする。
-
document が、"sub-apps" という名前のポリシー制御対象機能を使用することを許可されていない場合、promise を "
SecurityError"DOMExceptionで拒否し、 promise を返す。 -
document がサブアプリ文書である場合、promise を "
NotSupportedError"DOMExceptionで拒否し、 promise を返す。 -
parentApp を、document の関連付けられたインストール済みウェブ アプリケーションとする。
-
subApps をthisとする。
-
以下の手順を並列に実行する:
-
listResult を空のマップとする。
-
parentApp に対して現在インストールされているすべてのサブアプリのリストを、 プラットフォームのレジストリから取得する。
-
プラットフォームエラーが原因でリストの取得に失敗した場合、subApps の関連するグローバルオブジェクト上でグローバルタスクをキューに入れ、promise を "
OperationError"DOMExceptionで拒否させ、 これらの手順を中止する。 -
インストール済みの各サブアプリ subApp に対して、以下を反復する:
-
manifestId を、subApp のidとする。
-
appName を、サブアプリのウェブマニフェストから抽出された名前 とする。
-
resultEntry を、
appNameが appName に設定された新しいSubAppsListResult辞書とする。 -
listResult[manifestId] を resultEntry に設定する。
-
-
グローバルタスクをキューに入れ、subApps の関連するグローバルオブジェクト上で、 promise を listResult で解決させる。
-
-
promise を返す。
4.4. マニフェストをフェッチして処理する
「マニフェストをフェッチして 処理する」アルゴリズムを記述する。 [課題 #2]
url(URL)を与えてマニフェストをフェッチして 処理するには、次の 手順を実行します。
-
失敗を返します。
5. セキュリティおよびプライバシーに関する考慮事項
補助アプリケーションのインストールと管理は強力な機能です。ユーザーエージェントは、明示的な許可なしに、ウェブアプリケーションが サブアプリをインストールまたは管理することを許可してはなりません。
この節では、考慮される脅威と、それらを軽減するためのユーザーエージェントに対する規範的要件を概説します。
5.1. 共有オリジンのアイデンティティ
サブアプリは、個別のセキュリティオリジンを持ちません。親アプリと完全に同じオリジンおよびローカルデータストア(Cookie、IndexedDB、LocalStorage、 Cache Storage など)を共有します。標準的なウェブセキュリティ境界(同一オリジンポリシーなど)は、 親アプリとそのすべてのサブアプリを単一のエンティティとして扱います。5.2. 権限の継承
すべての権限は、親アプリとそのサブアプリの間で共有されます。サブアプリに権限(たとえば、カメラ、ファイル システムアクセス、USB)を付与すると、その権限は親にも自動的に付与され、その逆も同様です。サブアプリ API にアクセスするには、親アプリの文書が権限ポリシー
sub-apps を明示的に宣言する必要があります。サブアプリに対して宣言された権限ポリシーは効果を持ちません。
5.3. 明示的なユーザー同意
特定のオリジンについて、ユーザーの同意を得なければなりません。add()
が呼び出された場合、ユーザーエージェントは、要求されたすべての
サブアプリを表示する統合インストールダイアログをユーザーに提示しなければなりません。複数のサブアプリを一度に追加する場合、ダイアログの乱発を避けるため、
それらを単一のプロンプト内に提示するべきです。
ユーザーエージェントは、どのオリジンがアクセスを要求しているかを明確に示し、 ユーザーが十分な情報に基づいて判断できるだけの情報(たとえば、インストールされるサブアプリの名前 およびアイコン)を提供する権限プロンプトを表示しなければなりません。
5.4. アイデンティティ偽装のリスク
開発者はサブアプリの名前とアイコンをカスタマイズできるため、悪意のあるアプリケーションが システムダイアログや信頼されたサードパーティアプリケーションを模倣するサブアプリを作成するリスクがあります。 このリスクを軽減するため、サブアプリ API は、整合性および署名検証を保証する分離コンテキストに制限されています。5.5. OS 統合拡張のリスク
サブアプリは、独自の OS 統合(プロトコルハンドラーやファイルタイプの 関連付けなど)を登録できます。これは、アプリケーションが親アプリの主要マニフェストで 宣言された範囲をはるかに超えて、OS 内での影響範囲を拡張する可能性があることを意味します。 この問題は、ほとんどのオペレーティングシステム統合が有効になる前に、明示的なユーザー承認(たとえば、 あるファイルタイプの既定のアプリケーションとしてサブアプリを選択すること)を必要とするという事実によって軽減されます。5.6. クォータおよび制限
ホストオペレーティングシステムおよびユーザーのアプリケーションランチャーを、潜在的なリソース枯渇や悪用から保護するため、 プラットフォームは次の 2 つの制限を適用する:-
親アプリケーションごとにインストール済みサブアプリを 50 個とする厳格な上限。
-
1 回の権限プロンプトでインストールできるサブアプリを 20 個とする制限。
一括インストール呼び出しがプラットフォームの制限を超える場合、add()
呼び出し全体が "QuotaExceededError"
DOMException
で拒否される。
6. 統合
6.1. 権限ポリシー
この仕様は、Window
オブジェクト上の subApps
属性によって公開されるメソッドを使用できるかどうかを制御する機能を定義します。
この機能の機能名は、"sub-apps" です。
この機能の既定の許可リストは
'none' です。ユーザーエージェントは、特定のオリジンについて
これを 'self' に上書きしても構いません(たとえば、ユーザーの判断に基づく場合)。