Firefox に FileSystem API が無いのはなぜか?

原文: Why no FileSystem API in Firefox? (on July 5, 2012 by Jonas Sicking)

私が数多く尋ねられる質問は、なぜ Firefox は FileSystem API をサポートしないのか、です。たいてい、しかし常にではありませんが、彼らが指しているのは、Google が Chrome に実装し、W3C で標準化することを提案している FileSystemFileWriter のことです。

答えはいくらか複雑であり、質問した人が上記の 2 つの仕様の中で実際にどの能力を使いたいのか、ということに大きく依存しています。これらの仕様は、文章量が多く機能も豊富です。そのため、各自が全く違うことを望んでいても驚くにはあたりません。この投稿では、この質問に対する 私個人の 答えと、私たちが上記 2 つの仕様を実装していない理由について説明したいと思います。ただし、この投稿は私個人の意見であり、この話題について多くの議論がなされることを意図しています。

リソースをローカルに保存する

おそらく、人々が行いたい最も一般的なことは、単純にリソースのセットをローカルに保存して、ネットワークに接続されていなくても使えるようにしたい、ということでしょう。これは、リソースにすぐにアクセスする必要がある場合やユーザがオフラインでもリソースにアクセスできるようにしたい場合に役立ちます。ゲームなどは、最もこの種類のニーズがあるアプリケーションです。例えば、敵の宇宙船がいくつかの関連付けられた画像と 2 つの関連付けられた音声を持ち、敵が画面内を動き回って攻撃してくる時にそれが使われるとします。今日の人々は、一般的に、画像と音声のファイルをファイルシステムに保存することによってこの問題を解決しています。これらのファイルの名前は、敵のスピードや火力に合わせて付けられています。

しかしながら、このようにいくつかのデータを分けて保存することは、私から見るとあまり最適な方法とは思えません。特に、構造化されたデータとファイルデータの両方を保存できる解決策がある場合がそうです。IndexedDB は、ファイルデータを他の種類のデータと同じように扱えます。文字列や数値、JavaScript オブジェクトを格納するのと同じように、FileBlob を IndexedDB に書き込むことができます。これは、IndexedDB の仕様で指定されており、今のところ Firefox と IE の両方で IndexedDB の仕様どおりに実装されています。これを使って、必要なすべての情報を一カ所に格納することができ、一回のクエリで IndexedDB が必要なすべてのデータを返すことができます。コード例を見てみましょう。Web ベースのメールクライアントを構築したことがあるなら、オブジェクトを次のように格納するでしょう:

{
  subject: "Hi there",
  body: "Hi Sven,\nHow are you doing...",
  attachments: [blob1, blob2, blob3]
}

ここでのもう一つの長所は、リソースのファイルに名前を付ける必要が無いことです。File オブジェクトや Blob オブジェクトを格納するだけで、名前は必要ありません。

Firefox の IndexedDB 実装 (IE でも同じだと思います) では、ファイルは実際のデータベースの外に透過的に格納されます。これは、IndexedDB にファイルを格納するほうがファイルシステムに保存するよりもパフォーマンスが良いことを意味します。この動作により、データベースにファイルを詰め込んで他の操作が遅くなることはありません。データベースに格納したファイルの読み込みは、OS ファイルから読み込むのと同じ実装であることを意味し、ファイルシステムと同じ速さで読み込まれます。

Firefox の IndexedDB 実装は、同じ Blob の複数のファイルを IndexedDB データベースに格納する場合でさえ、ファイルのコピーを 1 個作成するだけなので十分にスマートです。同じ Blob にさらに参照を書き込んでも内部参照カウンタを追加するだけです。これは、Web ページに対して完全に透過であり、ここで気付くのは、書き込みが速く、リソースの消費が少ないということだけです。しかしながら、私は IE でも同じかどうか知りません。IE で確認してからお試しください。

写真と音楽のフォルダへのアクセス

2 番目に一般的なことは、ファイルシステムの API に関して、ユーザの写真フォルダや音楽フォルダ等にアクセスできるかということです。これは、W3C に提案された FileSystem API が実際に提供していない機能であり、多くの人々が行いたいことの一つです。この事例を満足させるために、DeviceStorage API が使えます。この API は、「ユーザのファイル」にアクセスできる完全なファイルシステムの能力があります。つまり、ファイルは Web サイト固有のものではなく、どちらかと言えばユーザにより管理され所有されるリソースであり、写真や音楽のファイルを扱うときのように、ユーザは個別のアプリを通してアクセスことを望むだろう、ということです。DeviceStorage API は、基本的にシンプルなファイルシステムの API であり、これらの種類のファイルのために最適化されています。

この API は仕様策定と実装の段階にあります。最近の nightly ビルドでテストできますが、まだデフォルトで有効になっていません。この機能が Web にもたらす主な問題はセキュリティです。Web サイトに、あなたの画像を読み込ませたり変更させたりはしたくないでしょう。この API は過去 10 年分の写真を削除する能力のある API なので、GeoLocation API で行っているように確認のダイアログを置かなければなりません。おそらく、さらに何かする必要があるでしょう。これは、私たちが現在取り組んでいることです。しかし、低レベルのファイル操作を実装していない部分では明らかにセキュリティが困難です。

低レベルのファイル操作

あまり一般的でない要求は、低レベルのファイル操作である作成、読み込み、更新、削除 (CRUD; create, read, update, delete の頭文字をとったもの) です。例えば、10MB のファイルの中間に 10 byte の書き込みをしたい場合です。IndexedDB は、まだこれをサポートしておらず、ファイル全体の追加と削除しかできません。これは、FileWriter 仕様のドラフト版でサポートされています。しかしながら、この部分の API はとても根本的な問題を抱えています。特に、この仕様にはファイルをロックする能力が無いため、複数のファイル操作が同時にできず、これらの操作をしている間、別のタブでファイルの変更や読み込みが無いようにしなければなりません。また、fsync する手段も無いため、データベースなどの ACID タイプのアプリケーションを FileWriter の上に実装できません。

私たちは代わりに、同じ目標を持ち、ファイルのロックや同時に複数の操作を行う能力のある API を作成しました。これは、ページがファイルのロック解除を忘れたりデッドロックが発生する危険性がない方法で行われます。この API は fsync 操作も受け入れ、FileHandle 上のデータベースが行うようなことも可能にします。しかしながら、最も重要なことは、この API が FileWriter のように非同期コールバックを入れ子にしなくてもよい方法で実装されていることです。言い換えれば、作者にとって使いやすい API であるということです。FileHandle についての詳細は、
https://wiki.mozilla.org/WebAPI/FileHandleAPI をお読みください。

filesystem URL スキーム

上記の FileSystem API がカバーしていないもう一つの能力があります。この仕様は、新しい filesystem: URL スキームを導入します。URL を filesystem: から読み込む時、FileSystem API を使用して格納されたファイルのコンテンツを返します。これは、次の 2 つの理由でとても素敵な機能と言えます。第一に、これらすべての URL を予想できることです。ファイルシステム内のファイルに一度格納すれば、それを読み出すために使用する URL を常に知っていることになります。また、その URL は、ファイルがファイルシステムに格納されている限り Web ページが再読み込みされても続けて使用することができます。第二に、相対 URL が filesystem: スキームで使用できます。そのため、あるファイルシステムに格納されたリソースから別のファイルシステムに格納されたりソースまで、あらゆる <img> リンクを作成できます。

Firefox は blob: URL スキームをサポートしません。これは、URL が使われるどこの Blob からでもデータを読み込めます。しかしながら、上述の能力はありません。これは、解決策を見つけたいと思っているものです。より良い解決策が見つけられないときは、Google の仕様を実装するしかないでしょう。

結論

Web プラットフォームに追加される機能について話す時はいつもそうであるように、事例と能力について話し、特定の解決策に直接飛躍しないのは重要なことです。多くの FileSystem API で解決しようとする問題は、他の方法でも解決できます。私の意見では、そういった改善が何度もあります。

これが、私たちが FileSystem API を優先的に実装しない理由です。代わりに、IndexedDB の実装を良くしたり、低レベルのファイル操作のための API に取り組むことに焦点を当てています。

IndexedDB に焦点を当てることは、基本的なファイルストレージのための良い API が 3 つのブラウザ (IE10, Firefox, Chrome) ですぐに使えるようになることを意味します。

関連事項として、最近、私たちの IndexedDB 実装の仕様準拠についての最後の問題を解決したところです。Firefox 16 では、プレフィックス無しの仕様に準拠した IndexedDB が使えるようになります!

いつもそうであるように、私たちは他の人々、特に Web 開発者からのフィードバックにとても興味があります。FileSystem API を優先的に扱うべきだと思いますか? その理由は?