03 December 2013

Web Storage の仕様を読む

W3C の Web Storage の仕様を読む。

Web Storage とは

Abstract には

This specification defines an API for persistent data storage of key-value pair data in Web clients.

とあるように、キーバリュー型データの永続的なストレージを提供する API。sessionStorage、localStorage を総称して Web Storage。ドキュメントのステータスは Recomendation なので、W3C の文章のステータスとしては最終段階だ。

Cookie との違い

window を超えて一貫したデータにアクセスできる点が異なる。Cookie はリクエストごとに送受信される。ブラウザのウィンドウ (タブ) を複数開いている場合、あるウィンドウでのデータ操作の結果を他のウィンドウにも反映させるにはリロード (サーバと通信) するしかない。あくまでクライアント側の状態変化でしかないはずなのに、いちいちサーバに問い合わせるのも変な感じだ。

Web Storage はウィンドウを超えてデータの操作ができる。window.localStorage などのオブジェクトが提供されるが、ちょうどこれがシングルトンになっているイメージ。セッションごとにクリアされる sessionStorage とセッションを越えて保持される localStorage の二種類がある。

現在はタブ型ブラウザが一般的になっているため、同一サイトでタブを複数開いてブラウジングすることは珍しくない。EC サイトの購入トランザクションなどは、ウィンドウを超えて一貫したデータを操作できないとクリティカルだ。

API

基本的な使い方は省略。Tips をいくつか。

  • ストレージがいっぱいで setItem に失敗した場合は QuotaExceededError という例外になる。
  • setItem, removeItem, clear はアトミックな操作
  • setItem, removeItem, clear を呼び出すと、Document に対してイベントも発火する (後述)
  • 各メソッド呼び出しはディスクへの物理書き込みを待つ必要は (仕様上は) ない。複数 script からの読み書きの一貫性がとれればそれでよい。
  • sessionStorage の生存期間について。top-level browsing context (通常は window オブジェクト) が破棄されると同時に sessionStorage もクリアされると仕様上は定義されている。一方で top-level browsing context の生存期間はクライアントの実装依存で、仕様では厳密に定義していないようだ。
  • localStorage への各操作は mutex で排他制御をしている。

Event

こちらも割愛。ポイントは以下。

  • ストレージに変化があったタイミングで storage イベントが発火する
  • その際は key, oldValue, newValue, url, storageArea という情報が取得できる

Threads

mutex を使っていることからもわかるように、複数のブラウジングコンテキストが同時にストレージにアクセスするが、各スクリプトは並列性を意識しない。よってあるスクリプトの実行中に length などのプロパティは変更されない (そのスクリプトが set/remove して length が変わるケースは除く)。

よってあるスクリプトの実行中はその origin の storage にロックがかかっていて、別のスクリプトからの書き込み・更新はそれを待つ必要があるということだろうか。このセクションは自信がないので要調査。

Disk Space

以下の内容が "SHOULD" (RECOMENDED) で定義されている。

  • サイズのリミットを設ける
  • リミットはオリジンごとに設ける
  • ストレージがいっぱいになったことをユーザーに通知する
  • ドメインごとの使用量をユーザーが参照できるようにする
  • オリジンごとに 5MB の制限を推奨。この数値は将来的にアップデートするので実装側からのフィードバックは歓迎。

Privacy

User tracking

いくつかの項目が "MAY" (OPTIONAL) で定義されている。広告のためのユーザートラッキングによるリスクを緩和する対策例として、明確に記載されている。考えようによっては広告のトラッキングはユーザーエージェントのユースケースのひとつでしかないが、その対策が (オプショナルとはいえ) 仕様に明記されていることには驚いた。

  • サードパーティストレージをブロックする。iframe に別ドメインのドキュメントを読み込んで storage に何かを保存することを防ぐ。
  • データの expire。ユーザーがそう設定していた場合、一定期間でストレージのデータをクリアする。例えば、サードパーティのストレージはセッションストレージとして扱うなど。
  • クッキーをクリアするのと同様にストレージもクリアするよう、ヘルプなどでわかりやすくユーザーに示す。
  • ストレージへのアクセスをサイトごとにホワイトリスト化する。
  • オリジン毎の利用状況を記録しユーザーに提示する。ブラックリストとの組み合わせも可。
  • ブラックリストの共有

Sensitivity of data

ユーザーエージェントはストレージのデータを極めてセンシティブに扱うべきである。ストレージにはメール、カレンダー、アポイント、健康状態などの重要な個人情報が入る可能性がある。よってユーザーがストレージの削除を支持した場合、ユーザーエージェントは即座にバックエンドのストレージからデータを削除しなくてはいけない。

Security

割愛。あとで。