ブラウザストレージ技術とプライベートブラウジング(改訂版)

4年前に

HTML5のストレージ技術とプライベートブラウジング - Nothing ventured, nothing gained.

という投稿をした。ブラウザのストレージ技術であるWeb SQL Database、Local Storage、Session Storage(いずれもWeb Storageで規定)のそれぞれが各ブラウザのプライベートブラウジングモードで使えるかを試してみたものである。

 4年が経過し、各ブラウザの実装状況も変化した。また、ストレージ技術にも変化があったので、改めて調査してみた。

対象としたブラウザは前回と同じ5種類。Internet Explorer、Firefox、Opera、Safari、Chrome。それぞれ以下のバージョンを用いた。

  • Internet Explorer - 11.0.9600.17126 (Windows 7)
  • Firefox - 30.9 (Windows 7およびMacOS X 10.9.4)
  • Opera - 22.0.1471.70 (Windows 7)
  • Safari - 7.0.5 (MacOS X 10.9.4)
  • Chrome - 35.0.1916.153 (Windows 7およびMacOS X 10.9.4)

調査対象ストレージ技術については、Web SQL Databaseが標準化の道を断念されているため対象から外した。代わりにIndexedDBを加えた。ServiceWorker*1はまだ標準化も実装も道半ばであるため取り上げていない。Filesystem APIは現状の仕様での標準化は断念し、実装しているのもChromeだけなので、取り上げていない。

また、この記事のタイトルであるが、HTML5のストレージ技術というのはもはや相応しくないため、ブラウザストレージ技術と改題した。

プライベートブラウジング

以下は前回と同じものを再掲載。 

【追記】Firefoxの動きが変更になったので、その部分を改訂。

プライベートブラウジング機能はWebの閲覧記録を一切残さない機能であり、各種ブラウザで実装されている。

同じプライベートブラウジングとは言っても、実際の動作は大きく分類して2種類になるようだ。

1つが通常モードでのブラウザはそのまま起動された状態で、プライベートモードが起動されるパターンだ。Internet Explorer、Opera、Google Chrome、Firefoxがこれに分類される*3。通常モードで起動されている各ブラウザの中からプライベートブラウジングを起動すると、別ウィンドウが開き*4、その中の操作では一切の記録が残らない。既存の通常モードのブラウザウィンドウはプライベートモードとは独立であるため、プライベートモードを終了しなくても、通常モードで起動されているブラウザウィンドウで通常の履歴の残る操作を行うことも出来る。

もう1つがモードを切り替えるパターンだ。FirefoxとSafariがこの方式だ。通常モードで起動されている各ブラウザの中からプライベートブラウジングの開始を行うと、現在の状態を一度保存し、プライベートモードへと移行する。通常モードでのブラウザウィンドウがそのままプライベートモードのブラウザに移行することになるので、通常モードとプライベートモードを共存させることは出来ない。プライベートモードが終了すると、通常モードに復帰する。

f:id:takoratta:20140713105407p:plain

 

プライベートブラウジングでのブラウザストレージの振る舞い

このプライベートブラウジング中にどのようにブラウザストレージ技術が振舞うかを調査してみた。

まず、実装状況であるが、IndexedDB以外はすべてのブラウザで実装されている。IndexedDBについても6月のWWDCで発表があったように、SafariでもYosemiteのタイミングで出る8.0よりサポートされる。リリースされたらまた試してみたい。

それぞれの動作をまとめると、以下のようになる。

  • Local StorageとSession Storageの違いはセッションをまたがって動作するのがLocal Storageでセッション終了時にデータをリセットするのがセッションストレージである。プライベートブラウジング時にはセッションを終了時にデータがリセットされることが期待されるので、この2つに期待する動作はどちらともセッション終了時にはリセットされることだ。一方、同じセッション内ではページのリロードを行ってもデータは保持されるべきである。結果はSafari以外は期待する動作となった、SafariはlocalStorage.setItem()を行うと、何故かQuotaエラーが発生する。

    "QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to add something to storage that exceeded the quota."
    f:id:takoratta:20140710215303p:plain
  • IndexedDBもLocal StorageやSession Storageと同じく、セッション終了後にはリセットされ、同じセッション内ではページのリロードを行ってもデータが保持されるのが期待される動作だろう。結果はOperaとChromeが期待する動作となったが、 Internet ExplorerとFirefoxはエラーとなった。Internet Explorerはwindow.indexedDBを実行時にundefinedとなり、FirefoxはIndexedDB.openを実行時に"InvalidStateError"となる。

    Firefoxのエラー

    f:id:takoratta:20140711122513p:plain

    Interenet Explorerのエラー

    f:id:takoratta:20140711122535p:plain

表にすると次のようになる。ここでの表記は上に説明したように、プライベートブラウジングとしての期待する動作かどうかを示すようにし、前回の表記から変更した。

 Local StorageSession StorageIndexedDB
Internet Explorer 期待通りの動作(ブラウザ再起動すると値がリセットする) 期待通りの動作(ブラウザ再起動すると値がリセットする) window.indexedDBを実行時にundefinedとなる。
Firefox 期待通りの動作(ブラウザ再起動すると値がリセットする) 期待通りの動作(ブラウザ再起動すると値がリセットする) IndexedDB.openが"InvalidStateError"となる。
Opera 期待通りの動作(ブラウザ再起動すると値がリセットする) 期待通りの動作(ブラウザ再起動すると値がリセットする) 期待通りの動作(ブラウザ再起動すると値がリセットする)
Safari Quotaエラー Quotaエラー IndexedDBが未サポート
Google Chrome 期待通りの動作(ブラウザ再起動すると値がリセットする) 期待通りの動作(ブラウザ再起動すると値がリセットする) 期待通りの動作(ブラウザ再起動すると値がリセットする)

 

Webアプリケーション側での対応

以下は前回と同じものを再掲載。 

プライベートブラウジングにおいてストレージ技術が機能しないのがプライベートブラウジングの目的にあっているとはいえ、そのままではWebアプリケーションでストレージ技術を使っている場合、ユーザーがプライベートブラウジングモードでアクセスしてきた際に適切に動作しないことになる。プライベートブラウジングの場合にはストレージ技術を使わないようにしたり、ユーザーに警告を出すようにする方が親切だ。

ただ、プライベートブラウジングかどうかはユーザーエージェントなどで簡単に分かるようにはなっていない。プライバシーを最大限に尊重して欲しいというモードにしているので、不必要な情報はWebサーバー/アプリケーション側には渡さない。

1つ比較的簡単に利用出来るのが、Stanford Web Security Research/Detecting Incognito*5で紹介されている方法だ。これは、あるユニークなURLにアクセスし、CSSの:visitedセレクタを確認することにより、ブラウザがプライベートブラウジングモードかどうかを判定する方法だ。:visitedセレクタが変更されていなかったら、プライベートブラウジング中だと判断出来る。

ただし、この方法がいつまで有効かわからない。CSS :visitedセレクタはウェブの閲覧履歴を取得することが出来る*6ため、プライバシー強化にむけてこの振る舞いを変えようという動きがある(例: modest / Mozilla Hacks (hacks.mozilla.org) / CSS の :visited に行われるプライバシー対策Safari Realized/Safari 5 で :visited の挙動が変更に)。行動ターゲッティング広告などに利用されているため、その是非をめぐって議論が続いていたものだ。FirefoxとWebKit系ブラウザでは早晩この方法は使えなくなる。

したがって、現在では将来に渡って確実にプライベートブラウジング中かどうかを判別する方法は無さそうだ。もしご存知の方がいたら教えて欲しい。

【以下、今回追記分】

:visitedセレクタについては対応がされた*7ので、プライベートブラウジングの判別には使えない。

方法としては、ここで述べたプライベートブラウジングの各ブラウザでの挙動の違いを利用するというのが現状の唯一の策のようだ。これだとどっちが先だかわからないが。

本件については以下のブログ記事に詳しい。というか、この記事ですべて書かれていたように思う (^^;;;

プライベートブラウジングモードの判定 - Please Sleep

なお、Firefoxに関して言えば、Supporting private browsing mode | MDNの方法が使える模様だ。

 【更新】 FirefoxはSupporting per-window private browsing | MDNがあるが、これは拡張権限のみ。FirefoxでIndexedDBが使えないのは、781982 – IndexedDB does not function in private browsing mode にあるように、プライベートブラウジング中には使わせたくないという理由。というのをmala (bulkneets) on Twitterさんに教えていただいた。

徹底解説HTML5 APIガイドブック オフライン系API編

徹底解説HTML5 APIガイドブック オフライン系API編

 

 

*1:W3Cでの標準化の名称はService Workers

*2:463027 – (PBnGen) Implement per-window Private Browsing

*3:コメントとTwitterで指摘されたが、Firefoxはバージョン20からこちらの形式になった。

*4:Operaの場合はプライベートウィンドウとプライベートタブの2つのプライベートモードがあり、プライベートタブの場合は既存のブラウザウィンドウの中にプライベートモードでのタブが生成される。

*5:リンク切れとなっている。

*6:だから、上のようにプライベートブラウジングかどうかの判定に使えるのだが。

*7::visited - CSS | MDN