1. はじめに
このセクションは規範的ではありません。
このAPIにより、開発者はユーザーのデバイス上のファイルシステムを介して他の(Web以外の)アプリと連携する強力なアプリを構築できます。ユーザーがこの機能を期待する主なアプリケーション例としては、IDE、写真や動画編集ソフト、テキストエディタなどがあります。 ユーザーがウェブアプリへのアクセスを許可した後、このAPIを利用することで、そのアプリはユーザーのデバイス上のファイルやフォルダーに直接読み書きできるようになります。ファイルの読み書きに加えて、このAPIはディレクトリを開いてその内容を列挙することも可能にします。さらに、ウェブアプリは利用可能になったファイルやディレクトリへの参照を保存でき、ユーザーが再度同じファイルを選択することなく、同じコンテンツへのアクセスを再取得できます。
このAPIは、<input type=file>や
<input type=file webkitdirectory>
[entries-api]
と同様に、ユーザー操作はファイルやディレクトリのピッカーダイアログを通じて行われます。
ただし、これらのAPIとは異なり、このAPIは現在純粋にJavaScript APIであり、フォームおよびinput要素とは統合されていません。
このAPIは、[FS]に記載されたAPIを拡張しています。そこでは、ウェブサイトがユーザーへ明示的なアクセス許可を求めなくても取得できるバケットファイルシステムが定義されています。
2. ファイルとディレクトリ
2.1. 概念
有効なサフィックスコードポイントとは、コードポイントのうち、ASCII英数字、 U+002B(+)、またはU+002E(.)であるものを指します。
注: これらのコードポイントは、ほとんどの既存ファイル形式をサポートするために選ばれています。
ファイル拡張子の大半は英数字のみですが、.tar.gzのような複合拡張子や、C++ソースコードのための.c++のような拡張子もよく使われるため、「+」と「.」も許容されています。
2.2. パーミッション
"file-system" 強力な機能のパーミッションに関するアルゴリズムと型は以下の通りです:
- パーミッションディスクリプタ型
-
FileSystemPermissionDescriptorは以下のように定義されます:enum {FileSystemPermissionMode ,"read" };"readwrite" dictionary :FileSystemPermissionDescriptor PermissionDescriptor {required FileSystemHandle ;handle FileSystemPermissionMode = "read"; };mode - パーミッション状態の制約
-
FileSystemPermissionDescriptordescに対するパーミッション状態の制約を決定するには、以下の手順を実行します:-
entryをdesc["
handle"]の entryとします。 -
もしentryがファイルシステムエントリであり、 バケットファイルシステム内にある場合、 このディスクリプタのパーミッション状態は常に "
granted"になります。 -
それ以外で、entryの親がnullでない場合、 このディスクリプタのパーミッション状態は、 同じ
modeで entryの親を表すhandleを持つ ディスクリプタのパーミッション状態と等しくしなければなりません。
-
これらのチェックはentryに紐付けないようにするべきです。[whatwg/fs Issue #101]
- パーミッションリクエストアルゴリズム
-
FileSystemPermissionDescriptordesc とPermissionStatusstatus が与えられた場合、以下の手順を実行します:-
desc と status で デフォルト権限クエリアルゴリズム を実行します。
-
settings を desc["
handle"] の 関連設定オブジェクト とします。 -
global を settings の グローバルオブジェクト とします。
-
global が
Windowでない場合、 "SecurityError"DOMExceptionを スロー します。 -
global が 一時的アクティベーション を持たない場合、 "
SecurityError"DOMExceptionを スロー します。 -
settings の オリジン が settings の 同一オリジン でない場合、 "
SecurityError"DOMExceptionを スロー します。 -
desc を使用する権限を リクエスト します。
-
desc と status で デフォルト権限クエリアルゴリズム を実行します。
このユーザーアクティベーションの要件は上流で定義されるのが理想的です。 [WICG/permissions-request Issue #2]
-
FileSystemHandle
handle および FileSystemPermissionMode
mode とともに実行するには、以下の手順を行います:
-
descを
FileSystemPermissionDescriptorとします。 -
desc["
name"]に "file-system"を設定します。 -
desc["
handle"] にhandleを設定します。 -
desc["
mode"] にmodeを設定します。 -
descのパーミッション状態を返します。
FileSystemHandle
handle および FileSystemPermissionMode
mode とともに実行するには、以下の手順を行います:
-
descを
FileSystemPermissionDescriptorとします。 -
desc["
name"] に "file-system"を設定します。 -
desc["
handle"] にhandleを設定します。 -
desc["
mode"] にmodeを設定します。 -
descのPermissionStatusを作成を実行し、その結果をstatusとします。
-
"
file-system"機能に対して、 パーミッションリクエストアルゴリズムを descとstatusで実行します。 -
descのパーミッション状態を返します。
現時点では
FileSystemPermissionMode
には"read"
または"readwrite"のみがあります。
将来的にはwrite専用ハンドルをサポートするため"write"モードも追加するかもしれません。
[Issue #119]
2.3. FileSystemHandle
インターフェース
dictionary {FileSystemHandlePermissionDescriptor FileSystemPermissionMode = "read"; }; [mode Exposed =(Window ,Worker ),SecureContext ,Serializable ]partial interface FileSystemHandle {Promise <PermissionState >queryPermission (optional FileSystemHandlePermissionDescriptor = {});descriptor Promise <PermissionState >requestPermission (optional FileSystemHandlePermissionDescriptor = {}); };descriptor
2.3.1. queryPermission()
メソッド
- status = await handle .
queryPermission({mode: "read" })- status = await handle .
queryPermission()- status = (await navigator.
permissions.query({name: "file-system",handle: handle })).state - status = await handle .
-
このハンドルの読み取り権限の現在の状態を照会します。 もしこれが"
prompt" を返す場合、ウェブサイトはrequestPermission()を操作前に呼び出す必要があります。 これが"denied" を返す場合、すべての操作は拒否されます。ローカルファイルシステムハンドルファクトリーから返されるハンドルは、初期状態では通常 "
granted" を返しますが、ユーザーが権限を取り消した場合や、IndexedDBから取得されたハンドルについては "prompt" を返す場合があります。 - status = await handle .
queryPermission({mode: "readwrite" })- status = (await navigator.
permissions.query({name: "file-system",handle: handle,mode: "readwrite" }).state - status = (await navigator.
-
このハンドルの書き込み権限の現在の状態を照会します。 これが"
prompt" を返す場合、このハンドルが表すファイルやディレクトリへ変更しようとする際、ユーザー操作が必要となり、ユーザーに確認プロンプトが表示されます。 ただし、もしこのハンドルの読み取り権限の状態も"prompt" の場合、ウェブサイトはrequestPermission()を呼び出す必要があります。 ファイルやディレクトリの読み取りの際、読み取りアクセスに自動的な許可プロンプトは表示されません。
permissions APIのquery()
メソッドとの統合はまだChromeには実装されていません。
queryPermission(descriptor)
メソッドを呼び出すと、以下の手順を実行します:
-
resultを新しいpromiseとする。
-
以下の手順を並列で実行する:
-
stateを、 ファイルシステム権限の照会の this と descriptor["
mode"] を与えて実行した結果とする。 -
resolve result with state。
-
-
resultを返す。
2.3.2. requestPermission()
メソッド
- status = await handle .
requestPermission({mode: "read" })- status = await handle .
requestPermission() - status = await handle .
-
このハンドルの読み取り権限の状態が"
prompt" 以外の場合、その状態をそのまま返します。 もし"prompt" の場合はユーザーのアクティベーションが必要となり、ユーザーに確認プロンプトが表示されます。 その後ユーザーの応答により新しい読み取り権限の状態が返ります。 - status = await handle .
requestPermission({mode: "readwrite" }) -
このハンドルの書き込み権限の状態が"
prompt" 以外の場合、その状態をそのまま返します。 もしこのハンドルの読み取り権限の状態が"denied" なら、それを返します。それ以外の場合で書き込み権限が"
prompt" ならユーザーに確認プロンプトが表示されます。 そしてユーザーの選択によって新しい書き込み権限の状態が返ります。
requestPermission(descriptor)
メソッドを呼び出すと、以下の手順を実行します:
-
resultを新しいpromiseとする。
-
以下の手順を並列で実行する:
-
stateを ファイルシステム権限のリクエストの thisと descriptor["
mode"] を与えて実行した結果とする。 それが例外を投げた場合はresultを拒否し中止する。 -
resolve result with state。
-
-
resultを返す。
3. ローカルファイルシステムへのアクセス
enum WellKnownDirectory {"desktop" ,"documents" ,"downloads" ,"music" ,"pictures" ,"videos" , };typedef (WellKnownDirectory or FileSystemHandle );StartInDirectory dictionary {FilePickerAcceptType USVString = "";description record <USVString , (USVString or sequence <USVString >)>; };accept dictionary {FilePickerOptions sequence <FilePickerAcceptType >;types boolean =excludeAcceptAllOption false ;DOMString ;id StartInDirectory ; };startIn dictionary :OpenFilePickerOptions FilePickerOptions {boolean =multiple false ; };dictionary :SaveFilePickerOptions FilePickerOptions {USVString ?; };suggestedName dictionary {DirectoryPickerOptions DOMString ;id StartInDirectory ;startIn FileSystemPermissionMode = "read"; }; [mode SecureContext ]partial interface Window {Promise <sequence <FileSystemFileHandle >>showOpenFilePicker (optional OpenFilePickerOptions = {});options Promise <FileSystemFileHandle >showSaveFilePicker (optional SaveFilePickerOptions = {});options Promise <FileSystemDirectoryHandle >showDirectoryPicker (optional DirectoryPickerOptions = {}); };options
showOpenFilePicker()、
showSaveFilePicker()
および showDirectoryPicker()
メソッドは
ローカルファイルシステムハンドルファクトリー
として知られています。
注: 本仕様で"ローカルファイルシステム"と呼ばれるものは、厳密にローカルデバイス上のファイルシステムである必要はありません。ここでのローカルファイルシステムは、クラウドプロバイダーをバックエンドにしてもよいです。例えばChrome OSでは、これらのファイルピッカーでGoogleドライブ上のファイルやディレクトリも選択できます。
Chrome
バージョン85以前では、これは汎用的なchooseFileSystemEntriesメソッドとして実装されていました。
3.1. ローカルファイルシステムのパーミッション
ユーザーがローカルファイルシステムハンドルファクトリーによるプロンプトで指定ファイルを選択したという事実は、ユーザーがそのファイルへの読み取り権限をウェブサイトに付与する意図であるとユーザーエージェントが扱うべきです。そのため
ローカルファイルシステムハンドルファクトリー
のいずれかによって返されたPromiseが解決された時点で、handle
を返されたハンドルに設定し、
mode
を"read"
に設定したディスクリプタのパーミッション状態は"granted"
であるべきです。
さらにshowSaveFilePicker
の呼び出しでは、返されたハンドルをhandle
に、
mode
を"readwrite"
に設定したディスクリプタのパーミッション状態は"granted"
であるべきです。
-
environment の origin が opaque origin である場合、 "
SecurityError"DOMExceptionで 拒否された約束 を返します。 -
environment の origin が environment の トップレベル origin と 同一オリジン でない場合、 "
SecurityError"DOMExceptionで 拒否された約束 を返します。 -
global を environment の グローバルオブジェクト とします。
-
global が 一時的アクティベーション を持たない場合、 "
SecurityError"DOMExceptionを スロー します。
3.2. ファイルピッカーのオプション
3.2.1. 受け入れられるファイルタイプ
showOpenFilePicker(options)
および showSaveFilePicker(options)
メソッドは、
FilePickerOptions
引数を受け入れ、これによりウェブサイトはファイルピッカーがユーザーに選択させるファイルのタイプを指定できます。
types
の各エントリは、ファイルピッカーに表示されるファイルをフィルタリングするための、ユーザーが選択可能な単一のオプションを指定します。
各オプションは、オプションの description
と、MIME タイプと拡張子の数(MIME タイプから拡張子のリストへのマッピングとして指定)で構成されます。説明が提供されない場合、説明が生成されます。
拡張子は "." で始まり、有効なサフィックスコードポイントのみを含む文字列でなければなりません。
さらに拡張子は16コードポイントの長さに制限されます。
完全な MIME タイプに加えて、MIME タイプのサブタイプとして "*" を使用して、たとえば "image/*" ですべての画像形式に一致させることができます。
ウェブサイトは常に各オプションに対して MIME タイプとファイル拡張子の両方を指定すべきです。ファイル拡張子のみを使用してファイルタイプを記述するプラットフォームでは ユーザーエージェントは拡張子で一致させることができ、拡張子を使用しないプラットフォームでは ユーザーエージェントは MIME タイプで一致させることができます。
デフォルトではファイルピッカーは、フィルタを適用しないオプションも含み、
ユーザーが任意のファイルを選択できるようにします。 excludeAcceptAllOption
を true に設定して、
ファイルピッカーにこのオプションを含めないようにします。
たとえば、次のオプションではユーザーは3つの異なるフィルタのいずれかを選択できます。 テキストファイル(プレーンテキストまたはHTML)のもの、画像のもの、そしてフィルタを適用せずユーザーが任意のファイルを選択できる3番目のもの。
const options= { types: [ { description: 'Text Files' , accept: { 'text/plain' : [ '.txt' , '.text' ], 'text/html' : [ '.html' , '.htm' ] } }, { description: 'Images' , accept: { 'image/*' : [ '.png' , '.gif' , '.jpeg' , '.jpg' ] } }, ], };
一方、次の例ではユーザーはSVGファイルのみを選択できます。ダイアログは フィルタを適用しないオプションを表示しません。
const options= { types: [ { accept: { 'image/svg+xml' : '.svg' } }, ], excludeAcceptAllOption: true };
FilePickerOptions
options を与えて、次の手順を実行します:
-
options["
types"] の各 type について繰り返します:-
type["
accept"] の各 typeString → suffixes について繰り返します:-
parsedType を、parse a MIME type を typeString で実行した結果とします。
-
parsedType の parameters が空でない場合、 throw a
TypeError. -
suffixes が文字列の場合:
-
suffixes を与えてvalidate a suffix を実行します。
-
-
それ以外の場合、suffixes の各 suffix について繰り返します:
-
suffix を与えてvalidate a suffix を実行します。
-
-
-
filter を、これらの手順(filename(string)と type(MIME type)を与えて)とします:
-
parsedType を、parse a MIME type を typeString で実行した結果とします。
-
falseを返します。
-
description を type["
description"] とします。 -
description が空の文字列の場合、 description を filter を説明するユーザー理解可能な文字列に設定します。
-
(description, filter) を accepts options に追加します。
-
-
accepts options が空であるか、 または options["
excludeAcceptAllOption"] がfalseのいずれかの場合:-
description を「すべてのファイル」を説明するユーザー理解可能な文字列とします。
-
filter を
trueを返すアルゴリズムとします。 -
(description, filter) を accepts options に追加します。
-
-
-
accepts options を返します。
3.2.2. 開始ディレクトリ
id
および startIn
フィールドを指定して、
ファイルピッカーが開くディレクトリを提案できます。
これらのオプションのいずれも指定されていない場合、ユーザーエージェントは最後にファイルまたはディレクトリが選択されたディレクトリを記憶し、新しいピッカーはそのディレクトリから開始されます。 id
を指定すると、ユーザーエージェントは異なるIDに対して異なるディレクトリを記憶できます
(ユーザーエージェントは限られた数のIDに対してのみディレクトリを記憶します)。
// このIDから以前に選択されたディレクトリへのマッピングが存在する場合、この // ディレクトリから開始します。それ以外の場合、このIDからこのファイルピッカー // 呼び出しの結果であるディレクトリへのマッピングが作成されます。 const options= { id: 'foo' , };
startIn
を FileSystemFileHandle
として指定すると、
ダイアログはそのファイルの親ディレクトリから開始されます。一方、 FileSystemDirectoryHandle
を渡すと、
ダイアログは渡されたディレクトリから開始されます。これらは、明示的な id
も渡された場合でも優先されます。
たとえば、FileSystemDirectoryHandle
project_dir が与えられた場合、次のようにして
そのディレクトリから開始するファイルピッカーを表示します:
// |project_dir| のディレクトリにピッカーが開きます。'foo' が有効なマッピング // を持っているかどうかに関係なく。 const options= { id: 'foo' , startIn: | project_dir| , };
id
および startIn
フィールドは、
ピッカーが開くディレクトリのみを制御します。上記の例では、
ファイルピッカーの操作が完了した後に、id
'foo' が project_dir と同じディレクトリにマップされることを仮定できません。
startIn
を WellKnownDirectory
として指定すると、
ダイアログは明示的な id
が渡された場合でも、
そのディレクトリから開始されますが、有効なディレクトリへのマッピングがある場合を除きます。
以下は、id
と
startIn
を WellKnownDirectory
として指定する例です。
指定されたIDから有効なパスへの既存のマッピングが存在する場合、そのマッピングが使用されます。それ以外の場合、WellKnownDirectory
経由で提案されたパスが使用されます。
// 'foo' のIDを初めて指定します。ディレクトリにマップされていません。 // ファイルピッカーはDownloadsディレクトリから開くようにフォールバックします。TODO: link this. const options= { id: 'foo' , // 未マップ。 startIn: " downloads " , // ここから開始。 }; // 後で... // 'foo' のIDはマップされている場合とされていない場合があります。例えば、このIDの // マッピングはエビクションされている可能性があります。 const options= { id: 'foo' , // マップされている可能性あり。もしそうなら、ここから開始。 startIn: " downloads " , // それ以外の場合、ここから開始。 };
startIn および id オプションは Chrome 91 で初めて導入されました。
ユーザーエージェントは、最近選択されたディレクトリマップを保持します。これは、 順序付きマップ のオリジンからパスIDマップへのものです。
パスIDマップは順序付きマップ で、有効なパスIDからパスへのものです。
有効なパスIDは文字列で、 各文字がASCII英数字または "_" または "-" です。
パスIDマップが無制限に成長しないように、 ユーザーエージェントは最近選択されたディレクトリを記憶する数を制限する 何らかのメカニズムを実装すべきです。これはたとえば、最も最近使用されていないエントリをエビクションすることで行うことができます。 ユーザーエージェントは、パスIDマップに少なくとも16エントリを格納できるようにすべきです。
WellKnownDirectory enum により、ウェブサイトは
いくつかの既知のディレクトリの中から1つを選択できます。これらの値がマップする正確なパスは実装定義
(一部の場合、これらはディスク上の実際のパスを表さない場合もあります)。
次のリストでは、各値の意味を説明し、異なるオペレーティングシステムでの可能な例のパスを示します:
"desktop"-
ユーザーのデスクトップディレクトリ(存在する場合)。たとえばこれは
C:\Documents and Settings\username\Desktop、/Users/username/Desktop、または/home/username/Desktopである可能性があります。 "documents"-
ユーザーが作成したドキュメントが通常保存されるディレクトリ。 たとえば
C:\Documents and Settings\username\My Documents、/Users/username/Documents、または/home/username/Documents。 "downloads"-
ダウンロードされたファイルが通常保存されるディレクトリ。 たとえば
C:\Documents and Settings\username\Downloads、/Users/username/Downloads、または/home/username/Downloads。 "music"-
オーディオファイルが通常保存されるディレクトリ。 たとえば
C:\Documents and Settings\username\My Documents\My Music、/Users/username/Music、または/home/username/Music。 "pictures"-
写真や他の静止画像が通常保存されるディレクトリ。 たとえば
C:\Documents and Settings\username\My Documents\My Pictures、/Users/username/Pictures、または/home/username/Pictures。 "videos"-
ビデオ/ムービーが通常保存されるディレクトリ。 たとえば
C:\Documents and Settings\username\My Documents\My Videos、/Users/username/Movies、または/home/username/Videos。 -
origin を environment のorigin とします。
-
startIn が
FileSystemHandleで、startIn が bucketファイルシステム内でない場合:-
entry を、locating an entry を startIn のlocator で実行した結果とします。
-
entry がfile entry の場合、ローカルファイルシステムで entry のparent のパスを返します。
-
entry がdirectory entry の場合、ローカルファイルシステムで entry のパスを返します。
-
-
id が空でない場合:
-
recently picked directory map[origin] が存在する場合:
-
path map をrecently picked directory map[origin] とします。
-
path map[id] が存在する場合、path map[id] を返します。
-
-
-
startIn が
WellKnownDirectoryの場合:-
startIn の
WellKnownDirectory値に対応するユーザーエージェント定義のパスを返します。
-
-
id が指定されていない、または空の文字列の場合:
-
recently picked directory map[origin] が存在する場合:
-
path map をrecently picked directory map[origin] とします。
-
path map[""] が存在する場合、path map[""] を返します。
-
-
-
ユーザーエージェント固有の方法でデフォルトパスを返します。
-
origin を environment のorigin とします。
-
recently picked directory map[origin] が存在しない場合、 recently picked directory map[origin] を空のパスIDマップに設定します。
-
id が指定されていない場合、id を空の文字列とします。
-
recently picked directory map[origin][id] を、ローカルファイルシステムで entry に対応するパスに設定します、 そのようなパスが決定できる場合。
- [ handle ] = await window .
showOpenFilePicker()- [ handle ] = await window .
showOpenFilePicker({multiple: false }) - [ handle ] = await window .
-
ユーザーが単一の既存ファイルを選択できるファイルピッカーを表示し、選択されたファイルのハンドルを返します。
- handles = await window .
showOpenFilePicker({multiple: true }) -
ユーザーが複数の既存ファイルを選択できるファイルピッカーを表示し、選択されたファイルのハンドルを返します。
showOpenFilePicker()に追加オプションを渡して、 ウェブサイトがユーザーに選択させるファイルのタイプと、 ファイルピッカーが開くディレクトリを示すことができます。詳細は§ 3.2 File picker options を参照してください。 -
environment をthisの関連設定オブジェクトとします。
-
accepts options をaccept types を処理する options で実行した結果とします。
-
starting directory を、 ピッカーが開始するディレクトリを決定する を options["
id"], options["startIn"], および environment で実行した結果とします。 -
global を environment のglobal object とします。
-
environment がファイルピッカーを表示することを許可されているかを検証します。
-
p を新しいプロミスとします。
-
次の手順を並列で実行します:
-
オプションで、このアルゴリズムの以前の実行が終了するまで待機します。
-
filePickerOptions を空の順序付きマップとします。
-
filePickerOptions["multiple"] を options["
multiple"] に設定します。 -
dismissed をWebDriver BiDi file dialog opened を null と filePickerOptions で実行した結果とします。
-
dismissed が false の場合:
-
ユーザーにいくつかのファイルをピックすることを要求するプロンプトを表示します。 filePickerOptions["multiple"] が false の場合、選択されるファイルは1つ以下でなければなりません; それ以外の場合、任意の数を選択できます。
表示されたプロンプトは、表示されるファイルのリストをフィルタリングするための accepts options のいずれかをユーザーが選択できるようにします。 これがどのように実装され、このプロンプトがどのように見えるかは実装定義です。
可能であれば、このプロンプトは starting directory を表示して開始します。
-
ユーザーが選択を行うまで待機します。
-
-
dismissed が true である、またはユーザーが選択を行わずにプロンプトを却下した場合、 reject p を "
AbortError"DOMExceptionで行い、中断します。 -
result を空のリストとします。
-
entries の各 entry について繰り返します:
-
entry がユーザーエージェントによってこのウェブサイトに公開するのがあまりにも敏感または危険と見なされる場合:
-
選択されたファイルまたはディレクトリをこのウェブサイトに公開できないことをユーザーに通知します。
-
ユーザーエージェントの裁量で、 これらの並列手順の先頭に戻るか、 reject p を "
AbortError"DOMExceptionで行い、中断します。
-
-
entry に関連付けられた新しい
FileSystemFileHandleを result に追加します。
-
-
選択されたディレクトリを記憶する を options["
id"], entries[0] および environment で実行します。 -
global のbrowsing context でactivation notification 手順を実行します。
注意: これにより、ウェブサイトはすぐに ユーザーアクティベーションを必要とする操作(追加の権限を要求するようなもの)を実行できます。
-
resolve p を result で行います。
-
-
p を返します。
- handle = await window .
showSaveFilePicker( options ) -
ユーザーが単一のファイルを選択できるファイルピッカーを表示し、選択されたファイルのハンドルを返します。選択されたファイルは既に存在する必要はありません。選択されたファイルが存在しない場合、このメソッドが返る前に新しい空のファイルが作成され、それ以外の場合は既存のファイルがこのメソッドが返る前にクリアされます。
- handle = await window .
showSaveFilePicker({suggestedName: "README.md" }) -
"README.md" という提案ファイル名がデフォルトの保存ファイル名として事前入力されたファイルピッカーを表示します。
追加options を
showSaveFilePicker()に渡して、 ウェブサイトがユーザーに選択させるファイルのタイプと、 ファイルピッカーが開くディレクトリを示すことができます。 § 3.2 File picker options を参照してください。 -
environment を this の 関連設定オブジェクト とします。
-
accepts options を accept types を処理する options で実行した結果とします。
-
starting directory を、 ピッカーが開始するディレクトリを決定する を options["
id"], options["startIn"] および environment で実行した結果とします。 -
global を environment の global object とします。
-
environment が ファイルピッカーを表示することを許可されているかを検証します。
-
p を 新しいプロミス とします。
-
次の手順を 並列で実行します:
-
オプションで、このアルゴリズムの以前の実行が終了するまで待機します。
-
ユーザーに正確に1つのファイルを選択するよう要求するプロンプトを表示します。 表示されたプロンプトは、表示されるファイルのリストをフィルタリングするための accepts options のいずれかをユーザーが選択できるようにします。 これがどのように実装され、このプロンプトがどのように見えるかは 実装定義です。 accepts options がUIに表示される場合、選択されたオプションは ユーザー提供のファイル名に追加する拡張子を提案するためにも使用されますが、これは必須ではありません。特にユーザーエージェントは ".lnk" や ".local" で終わるような潜在的に危険なサフィックスを無視する自由があります。
可能であれば、このプロンプトは starting directory を表示して開始します。
options["
suggestedName"] が 存在 し、 null でない場合、ファイルピッカープロンプトは options["suggestedName"] をデフォルトの保存名として事前入力されます。suggestedNameと accepts options の相互作用は 実装定義です。suggestedNameがあまりにも危険と見なされる場合、ユーザーエージェントは提案されたファイル名を無視またはサニタイズすべきです、ダウンロードとしてフェッチするときに行われるサニタイズと同様です。注意: ユーザーエージェントはたとえば accepts options で
suggestedNameと一致するオプションをデフォルトフィルタとして選択できます。 -
ユーザーが選択を行うまで待機します。
-
ユーザーが選択を行わずにプロンプトを却下した場合、 reject p を "
AbortError"DOMExceptionで行い、中断します。 -
entry を、選択されたファイルを表す file entry とします。
-
entry がユーザーエージェントによってこのウェブサイトに公開するのが あまりにも敏感または危険 と見なされる場合:
-
選択されたファイルまたはディレクトリをこのウェブサイトに公開できないことをユーザーに通知します。
-
ユーザーエージェントの裁量で、 これらの 並列 手順の先頭に戻るか、 reject p を "
AbortError"DOMExceptionで行い、中断します。
-
-
entry の binary data を空の byte sequence に設定します。
-
result を entry に関連付けられた新しい
FileSystemFileHandleに設定します。 -
選択されたディレクトリを記憶する を options["
id"], entry および environment で実行します。 -
global の browsing context で activation notification 手順を実行します。
注意: これにより、ウェブサイトはすぐに 返されたハンドルに対する操作(追加の権限を要求するようなもの)を実行できます。
-
Resolve p を result で行います。
-
-
p を返します。
- handle = await window .
showDirectoryPicker()- handle = await window .
showDirectoryPicker()({mode: 'read' }) - handle = await window .
-
ユーザーが単一のディレクトリを選択できるディレクトリピッカーを表示し、ユーザーが読み取り権限を付与した場合、選択されたディレクトリのハンドルを返します。
- handle = await window .
showDirectoryPicker()({mode: 'readwrite' }) -
ユーザーが単一のディレクトリを選択できるディレクトリピッカーを表示し、選択されたディレクトリのハンドルを返します。ユーザーエージェントはこのハンドルに対する読み取りと書き込み権限のリクエストを1つの後続プロンプトに組み合わせることができます。
-
environment を this の 関連設定オブジェクト とします。
-
starting directory を ピッカーが開始するディレクトリを決定する を options["
id"], options["startIn"] および environment で実行した結果とします。 -
global を environment の global object とします。
-
environment が ファイルピッカーを表示することを許可されているかを検証します。
-
p を 新しいプロミス とします。
-
次の手順を 並列で実行します:
-
オプションで、このアルゴリズムの以前の実行が終了するまで待機します。
-
filePickerOptions を空の map とします。
-
filePickerOptions["multiple"] を false に設定します。
-
dismissed を WebDriver BiDi file dialog opened を null と filePickerOptions で実行した結果とします。
-
dismissed が false の場合:
-
ユーザーにディレクトリを選択するよう要求するプロンプトを表示します。
可能であれば、このプロンプトは starting directory を表示して開始します。
-
ユーザーが選択を行うまで待機します。
-
-
dismissed が true である、またはユーザーが選択を行わずにプロンプトを却下した場合、 reject p を "
AbortError"DOMExceptionで行い、中断します。 -
entry を、選択されたディレクトリを表す directory entry とします。
-
entry がユーザーエージェントによってこのウェブサイトに公開するのが あまりにも敏感または危険 と見なされる場合:
-
選択されたファイルまたはディレクトリをこのウェブサイトに公開できないことをユーザーに通知します。
-
ユーザーエージェントの裁量で、 これらの 並列 手順の先頭に戻るか、 reject p を "
AbortError"DOMExceptionで行い、中断します。
-
-
result を entry に関連付けられた新しい
FileSystemDirectoryHandleに設定します。 -
選択されたディレクトリを記憶する を options["
id"], entry および environment で実行します。 -
desc を
FileSystemPermissionDescriptorとします。 -
desc["
name"] を "file-system" に設定します。 -
desc["
handle"] を result に設定します。 -
status を desc の create a PermissionStatus を実行した結果とします。
-
global の browsing context で activation notification 手順を実行します。
-
desc を使用する permission を要求する を実行します。
-
desc と status で default permission query algorithm を実行します。
-
status が "
granted" でない場合、 reject result を "AbortError"DOMExceptionで行い、中断します。 -
global の browsing context で activation notification 手順を実行します。
-
Resolve p を result で行います。
-
-
p を返します。
- handle = await item .
getAsFileSystemHandle() -
ドラッグされたアイテムがファイルの場合、
FileSystemFileHandleオブジェクトを返し、ドラッグされたアイテムがディレクトリの場合、FileSystemDirectoryHandleオブジェクトを返します。 -
DataTransferItemオブジェクトが読み書きモードまたは読み取り専用モードでない場合、nullで解決された約束を返します。 -
ドラッグデータアイテムの種類がFileでない場合、
nullで解決された約束を返します。 -
pを新しい約束とします。
-
以下のステップを並行して実行します:
-
entryをドラッグされたファイルまたはディレクトリを表すファイルシステムエントリとします。
-
entryがファイルエントリの場合:
-
handleをentryに関連付けられた
FileSystemFileHandleとします。
-
-
それ以外の場合は、entryがディレクトリエントリの場合:
-
handleをentryに関連付けられた
FileSystemDirectoryHandleとします。
-
-
pをentryで解決します。
-
-
pを返します。
-
ユーザーエージェント自体を含むディレクトリまたはディレクトリ。
-
ユーザーエージェントがウェブサイトストレージを保存するディレクトリ。
-
システムファイルを含むディレクトリ(Windowsの
C:\Windowsなど)。 -
Linuxの
/dev/、/sys、および/procのような低レベルデバイスへのアクセスを与えるディレクトリ。 -
ユーザーの「ホーム」ディレクトリ全体。 ホームディレクトリ内の個々のファイルとディレクトリはまだ許可されますが、 ユーザーエージェントは一般的にユーザーがディレクトリ全体への無制限アクセスを与えることを許可すべきではありません。
-
ユーザーエージェントがダウンロードのデフォルトディレクトリを持っている場合、そのディレクトリ。 ディレクトリ内の個々のファイルはまだ許可されますが、ディレクトリ全体はユーザーが認識するよりも多くのデータを漏らすリスクがあります。
-
Windowsでファイルへの書き込みを選択する場合、名前が
.lnkで終わるファイル。これらのファイルへの書き込みは、 他のオペレーティングシステムでのシンボリックリンクの作成に似ており、ユーザーが意図していないファイルへのアクセスを与えるために使用される可能性があります。 -
ファイルへの書き込みを選択する場合、名前が
.localで終わるファイル。 Windowsはこれらのファイルを使用してロードするDLLを決定し、これらのファイルへの書き込みはコードが実行される原因となる可能性があります。
StartInDirectory
startIn および環境設定オブジェクト environment を与えて、次の手順を実行します:
3.3.
showOpenFilePicker()
メソッド
showOpenFilePicker(options)
メソッドは、呼び出されたときに
これらの手順を実行します:
3.4.
showSaveFilePicker()
メソッド
suggestedName
オプションは Chrome 91 で初めて導入されました。
showSaveFilePicker(options) メソッドは、
呼び出されたときに、これらの手順を実行しなければなりません:
3.5.
showDirectoryPicker()
メソッド
id
および startIn
フィールドは、
id
および startIn
フィールドとそれぞれ同一です。
これらのフィールドを使用する方法の詳細については § 3.2.2 Starting
Directory を参照してください。
showDirectoryPicker(options)
メソッドは、呼び出されたときに、次の手順を実行しなければなりません:
3.6. ドラッグアンドドロップ
partial interface DataTransferItem {Promise <FileSystemHandle ?>getAsFileSystemHandle (); };
ドラッグアンドドロップ操作中に、ドラッグされたファイルおよび ディレクトリアイテムは、それぞれファイルエントリおよびディレクトリエントリ に関連付けられます。
getAsFileSystemHandle()
メソッドのステップは以下の通りです:
elem. addEventListener( 'dragover' , ( e) => { // ナビゲーションを防ぐ。 e. preventDefault(); }); elem. addEventListener( 'drop' , async ( e) => { e. preventDefault(); const fileHandlesPromises= [... e. dataTransfer. items] . filter( item=> item. kind=== 'file' ) . map( item=> item. getAsFileSystemHandle()); for await ( const handleof fileHandlesPromises) { if ( handle. kind=== 'directory' ) { console. log( `Directory: ${ handle. name} ` ); } else { console. log( `File: ${ handle. name} ` ); } } });
これは現在、過度に敏感または危険な ディレクトリへのアクセスをブロックしていません。 これは、ドロップされたファイルとディレクトリにアクセスを与える他のAPIとの一貫性を保つためです。しかし、これはローカルファイルシステムハンドルファクトリとは一貫性がありません。そのため、これを再検討する可能性があります。
4. アクセシビリティに関する考慮事項
このセクションは非規範的です。
この仕様がユーザーインターフェースに情報を提示する場合、 実装者はプラットフォームのOSレベルのアクセシビリティガイドラインに従うべきです。
5. プライバシーに関する考慮事項
このセクションは非規範的です。
このAPIは、既存の
<input type=file>
および<input type=file webkitdirectory>
APIがすでに持っているデータへの読み取りアクセスをウェブサイトに与える以上のものではありません。さらに、これらのAPIと同様に、
ファイルおよびディレクトリへのすべてのアクセスは、ファイルまたはディレクトリピッカーの背後に明示的にゲートされています。
しかし、この新しいAPIにはいくつかの主要なプライバシーリスクがあります:
5.1. ユーザーが意図したよりも多くの、またはより敏感なファイルへのアクセスを与える。
これはこのAPIの新しいリスクではありませんが、ユーザーがウェブサイトがアクセスしているものを正確に認識できるように、ユーザーエージェントは努めるべきです。これは、 ユーザーがディレクトリに実際にどれだけのファイルが存在するかをすぐに明確にしない場合に、ディレクトリへのアクセスを与える場合に特に重要です。
関連するリスクは、ユーザーが特に敏感なデータを与えることです。 これには、ユーザーエージェント自身の設定データ、ネットワークキャッシュやクッキーストア、 またはパスワードファイルなどのオペレーティングシステム設定データが含まれる可能性があります。これを保護するために、ユーザーエージェントはディレクトリピッカーでユーザーが選択できるディレクトリを制限することを奨励され、 潜在的にユーザーが特に敏感なデータを含むディレクトリへのアクセスを与えるのを難しくするために、選択できるファイルも制限します。正しいバランスを維持することが重要です。結局のところ、このAPIはユーザーが最もプライベートな個人データをウェブサイトとやり取りできるように意図的にしています。
ユーザーエージェントが制限することを望むディレクトリの例として、 過度に敏感または危険なディレクトリには以下が含まれます:
5.2. ウェブサイトがこのAPIを追跡に使用しようとする。
このAPIは、ブラウジングデータをクリアしてもユーザー間でユーザーを追跡するために使用される可能性があります。これは、 既存のファイルアクセスAPIとは異なり、ユーザーエージェントがファイルまたはディレクトリへの永続アクセスを許可でき、再プロンプトできるためです。 ファイルへの書き込み機能と組み合わせると、ウェブサイトはユーザーのディスク上に識別子を永続化でき、 これらの識別子はブラウジングデータをクリアしても影響を受けません。
このリスクは、ブラウジングデータをクリアしてもウェブサイトが永続化したハンドル(たとえばIndexedDBで)をクリアするという事実によってある程度軽減されます。 さらに、ユーザーエージェントはウェブサイトがアクセスしているファイルとディレクトリを明確にし、 特に信頼できる起源に対してのみ永続的な許可付与を制限するよう奨励されます。
ユーザーエージェントはまた、ユーザーが付与された許可を撤回する方法を提供することを奨励されます。 ブラウジングデータをクリアすると、すべての許可が撤回されることが期待されます。
5.3. ファーストパーティ対サードパーティのコンテキスト。
サードパーティコンテキスト(たとえば、トップレベルのフレームのオリジンと一致しないiframe内)で、
ウェブサイトはすでにアクセスしているデータにアクセスすることはできません。これには、ローカルファイルシステムハンドルファクトリを介した新しいファイルまたはディレクトリへのアクセスの取得、
および既存のハンドルへのrequestPermission
APIを介したより多くの許可のリクエストが含まれます。
ハンドルは同じオリジンの宛先にのみポストメッセージできます。ハンドルをクロスオリジン宛先に送信しようとすると、
messageerror
イベントが発生します。
6. セキュリティに関する考慮事項
このセクションは非規範的です。
このAPIは、ディスク上の既存のファイルを変更するだけでなく、新しいファイルに書き込む機能をウェブサイトに与えます。これにはいくつかの重要なセキュリティ考慮事項があります:
6.1. マルウェア
このAPIは、ウェブサイトがユーザーのシステムにマルウェアを保存または実行しようとするために使用される可能性があります。これを軽減するために、このAPIはファイルを実行可能としてマークする方法を提供しません(ただし、 すでに実行可能なファイルは、このAPIを通じて変更された後もそのようになる可能性があります)。さらに、ユーザーエージェントはこのAPIによって作成または変更されたファイルにMark-of-the-Webを適用することを奨励されます。
最後に、ユーザーエージェントはこのAPIによって変更されたファイルの内容をマルウェアスキャンおよびセーフブラウジングチェックで検証することを奨励されます、 ただし、いくつかの外部の強力な信頼関係がすでに存在する場合を除きます。もちろん、これはこのAPIのパフォーマンス特性に影響を与えます。
6.2. ランサムウェア攻撃
ランサムウェア攻撃のもう一つのリスク要因は、上記の特定の敏感なディレクトリへのアクセスをブロックするという制限によって軽減されます。さらに、ユーザーエージェントはファイルへの書き込みアクセスを適切とみなす粒度で許可できます。
6.3. ユーザーのディスクを埋める
バケットファイルシステムのファイル以外、このAPIによって書き込まれたファイルはストレージクォータの対象ではありません。その結果、ウェブサイトはクォータによって制限されることなくユーザーのディスクを埋めることができます(ただし、 ストレージクォータの対象となるストレージであっても、ユーザーのディスクを埋めたり、ほぼ埋めたりすることはまだ可能です。なぜならストレージクォータは一般的に利用可能なディスクスペースに依存しないからです)。
このAPIなしで、ウェブサイトは大規模なファイルをトリガーしてダウンロードすることで(潜在的にクライアント側で作成され、
ネットワークオーバーヘッドを発生させない)、クォータ制限の対象となるストレージにデータを書き込むことができます。truncate()
の存在とファイルの終わりを超えた非常に大きなオフセットでの書き込みにより、大規模なファイルを作成することがはるかに簡単で低コストになります。ただし、
ほとんどのファイルシステムはスパースファイルをサポートしているため、これらのファイルは実際に生成されたNULバイトを保存しない場合があります。
ウェブサイトがこのAPIを使用してディスクに書き込む場合、クォータ管理ストレージまたは既存のダウンロードメカニズムを介してウェブサイトがユーザーのディスクを埋めるのを防ぐためにユーザーエージェントが使用するあらゆる緩和策も使用されるべきです。