クライアントサイド (すなわちローカルディスク) に何らかのデータを保存する Web 技術が、何種類かあります。ブラウザがどれだけの容量を Web データストレージに割り当てるかや、容量の上限に達したときにどのデータを削除するかのプロセスは単純ではなく、またブラウザにより異なります。この記事では、これらがどのように動作するかを説明します。
注記: 以下の情報はほとんどの最新ブラウザでおおむね正確ですが、既知の詳細情報も記載しています。Opera および Chrome は、すべての場合において同じ動作になるでしょう。Opera Mini (Presto ベースで、サーバサイドでレンダリングする) は、クライアントにデータを保存しません。
さまざまな種類のデータストレージ
同じブラウザ内で同じ保存方法を使用していても、解釈されるデータストレージの種類はさまざまです。この章では、さまざまなブラウザで見つけられる多様なストレージについて説明します。
一般的に、ストレージは以下のように大きく 2 種類に分けられます:
- 永続的: 長期間にわたって保持されることを意図するデータです。これはユーザが決断した場合にのみ削除されます (例えば Firefox では、各ページのページ情報ダイアログに "ストレージを消去" ボタンがあります)。
- 一時的: 長期間にわたって維持する必要がないデータです。ストレージの容量制限に達すると、もっとも過去に使用されたものから削除されます (LRU ポリシー)。
デフォルトでは、一時的なストレージがほとんどの使用環境 (例えば、標準的な Web アプリ) で使用され、永続的なストレージはインストールされたアプリ (例えば、Firefox OS やデスクトップ版 Firefox にインストールした Firefox アプリ、および Chrome アプリ) で使用されます。
Firefox の詳細情報
Firefox では、open()
を使用して IndexedDB データベースを作成するときに専用オプション storage
を含めれば、どのタイプのストレージを使用したいかを選択できます:
-
var request = indexedDB.open("myDatabase", { version: 1, storage: "persistent" });
-
var request = indexedDB.open("myDatabase", { version: 1, storage: "temporary" });
Firefox では永続的なストレージを使用するときに、その旨を警告して受け入れるかを問い合わせるポップアップ UI をユーザに対して表示します。
一時的なデータストレージではユーザに対して確認しませんが、ストレージの制限は存在します。
Firefox のデフォルトのストレージ
Firefox では第 3 のストレージを考慮しており、デフォルトストレージと呼びます。これは、前述の storage
パラメータを指定しない場合に使用される既定の選択肢です。デフォルトストレージのデータの振る舞いは、状況により異なります。インストール済みの Firefox OS アプリに対しては永続的なストレージ、その他の用途では一時的なストレージとして振る舞います。
データの保存先は?
それぞれのストレージタイプが別々のリポジトリに相当しており、ユーザの Firefox プロファイル内のディレクトリとは以下のように対応づけられます (ほかのブラウザでは、若干異なるでしょう):
<profile>/storage
— クォータマネージャ (後述) に管理されている、ストレージの主要なトップレベルディレクトリです。<profile>/storage/permanent
— 永続的なデータストレージのリポジトリです。<profile>/storage/temporary
— 一時的なデータストレージのリポジトリです。<profile>/storage/default
— デフォルトのデータストレージのリポジトリです。
注記: Firefox では URL バーに about:support
と入力して移動して、プロファイルフォルダ の隣にある フォルダを開く ボタン (Mac OS X では Finder で開く) を押下すると、プロファイルのフォルダを見つけることができます。
注記: プロファイルフォルダでデータを保存する場所を見ていると、第 4 のフォルダ persistent
が見つかるかもしれません。本来は更新や移行を単純化するため、少し前に persistent
フォルダを permanent
フォルダに改名しました。
注記: ユーザが <profile>/storage
の配下に、独自のディレクトリやファイルを作成すべきではありません。このようなことを行うと、ストレージの初期化が失敗します。例えば、open()
でエラーイベントが発生します。
ストレージの制限
ブラウザのストレージの最大容量は動的であり、ハードディスクドライブのサイズに応じて変わります。グローバルリミットはディスクの空き量量の 50% に決められます。Firefox では、クォータマネージャと飛ばれる内部のブラウザツールが生成元ごとにどれだけディスク容量を使用しているかを絶えず注視しており、必要に応じてデータを削除します。
従ってハードディスクドライブが 500GB であれば、ブラウザの合計ストレージサイズは 250GB になります。上限に達すると origin eviction と呼ばれる処理を実行して、ストレージの総量が再び上限を下回るまで、生成元全体に相当するデータを削除します。生成元内の一部分を削除するような縮小法はありません。生成元内のひとつのデータベースだけ削除すると、矛盾の問題が発生するおそれがあります。
また、グループリミットというもうひとつの制限もあります。これは、グローバルリミットの 20% として定義されます。それぞれの生成元は、グループ (生成元のグループ) の一部です。グループは、eTLD+1 ドメインごとに 1 つ作られます。
例:
mozilla.org
— グループ 1、生成元 1www.mozilla.org
— グループ 1、生成元 2joe.blogs.mozilla.org
— グループ 1、生成元 3firefox.com
— グループ 2、生成元 4
このグループでは mozilla.org
、www.mozilla.org
、joe.blogs.mozilla.org
が、合わせてグローバルリミットの 20% を上限としてストレージを使用できます。firefox.com
は、別に 20% の上限を持ちます。
これら 2 種類の制限は、制限に達したときの動作が異なります:
- グループリミットは "ハードリミット" とも呼ばれます。origin eviction を発生させません。
- グローバルリミットは、いくらかの領域が解放されて処理を継続できる可能性がありますので "ソフトリミット" です。
注記: グループリミットに達したとき、あるいは origin eviction で十分な空き容量を確保できないときは、ブラウザで QuotaExceededError
が発生します。
LRU ポリシー
使用可能なディスク領域がすべて埋まったときは、クォータマネージャが LRU ポリシーに基づいてデータの削除処理を始めます。もっとも過去に使用された生成元のデータが始めに削除され、上限に達しなくなるなるまで削除を繰り返します。
一時的なストレージを使用して、生成元ごとに "最終アクセス日時" を記録しています。一時的なストレージがグローバルリミットに達する (後に上限をさらに超える) と、現在使用していない (すなわち、データストアを開き続けているタブやアプリがない) 生成元をすべて発見しようとします。これらは、"最終アクセス日時" によって整列されます。origin eviction を発生させたリクエストを満たすのに十分な領域を確保するまで、もっとも過去に使用された生成元を削除し続けます。
ブラウザのデータストレージを使用する技術は何か?
Firefox では以下の技術が、必要なデータを保存するためにブラウザのデータストレージを使用します。ここではそれらの技術を "クォータクライアント" と呼びます:
生成元の "最終アクセス日時" は、これらのいずれかによってアクティブ化/非アクティブ化される origin eviction によって、すべてのクォータクライアントでデータ削除が行われたときに更新されます。
Chrome/Opera では、Quota Management API が AppCache、IndexedDB、WebSQL、File System API のクォータ管理を制御しています。
関連情報
- Working with quota on mobile browsers, by Eiji Kitamura. モバイルブラウザのクライアントサイドストレージについて詳しく分析した記事。
- Quota Management API : Fast Facts, by Eiji Kitamura. Chrome/Blink (Opera も含まれるでしょう) の Quota Management API について見ていく記事。