Web storageのlocalStorageの実体を調べる

 WebAudioを使ったスクリプトを書いていたのですが、パラメータを保存したいと思いました。で、HTML5と共にlocalStorage(を含むWeb storage)が実装されていたような気がしたので、使ってみることにしました。
 ところで、世の中的にはどんな用途でlocalStorageを使っているのか、自分のPCに格納されているlocalStorageの実体を調べてみました。
 

Web storageとは

 Web storageには永続的なlocalStorageと、セッション内でのみ有効なsessionStorageの2種類あります。一般的なcookieと異なり、localStorageを使えば永続的にデータを保持することが可能になります。

 そういえば、冒頭にも書いたようにHTML5の一部だと思っていたのですが、米Wikipediaによれば現在ではHTML5とは切り離された仕様として定義されているようです。

Web storage is being standardized by the World Wide Web Consortium (W3C). It was originally part of the HTML5 specification, but is now in a separate specification.

Web storage - Wikipedia
Web Storage (Second Edition)
 

 永続的にデータを保持されるということは、消さない限り消えないわけです。たとえ一定期間経過後に削除するようなコードが実装されていても、そのサイトをユーザが再度訪れない限りは削除ロジックは発動しません。この特性を考慮すると、開発者にとっては便利に使えても、ユーザにとってはゴミデータを貯え続けられてしまう可能性もあるわけです。

 そこで、PCのどこにどのくらいlocalStorageによってデータが格納されているか調べてみました。
 

格納場所

 WindowsGoogle Chromeを使用していると、以下のディレクトリにlocalStorageの実体が保持されているようです。

%USERPROFILE%\AppData\Local\Google\Chrome\User Data\Default\Local Storage\

 このディレクトリ内を見てみると、以下のようになっていました。

>dir
 ドライブ C のボリューム ラベルは VOLUME_LABEL です
 ボリューム シリアル番号は XXXX-XXXX です

 C:\Users\USERNAME\AppData\Local\Google\Chrome\User Data\Default\Local Storage のディレクトリ

2017/02/21  02:28    <DIR>          .
2017/02/21  02:28    <DIR>          ..
2017/02/20  01:05            10,240 chrome-devtools_devtools_0.localstorage
2017/02/20  01:05                 0 chrome-devtools_devtools_0.localstorage-journal

…中略…

            2628 個のファイル          59,284,016 バイト
               2 個のディレクトリ     808,513,536 バイトの空き領域

 サイトやChromeアプリ毎に.localstorageというファイルと.localstorage-journalというファイルのペアが作成されているようです。
 また、私のPCでは合計60MB弱になるようです。大した量ではありませんが、増設も換装も不可能な特殊形状のUltrabookのSSDを無意味なデータに占有されるのは嬉しくありません。

 永続的ということで、消えずに残っているゴミのようなlocalStorageを探してみることにします。私のPCで最も古いlocalStorageのファイルを3組例示すると、下のようなタイムスタンプで2年以上前。たぶん、このPCを使い始めたころだと思います。

2014/12/10  14:46             3,072 https_getadblock.com_0.localstorage
2014/12/10  14:46             3,608 https_getadblock.com_0.localstorage-journal
2014/12/17  17:14             3,072 https_account.asus.com_0.localstorage
2014/12/17  17:14               512 https_account.asus.com_0.localstorage-journal
2014/12/17  17:15             3,072 https_vip.asus.com_0.localstorage
2014/12/17  17:15               512 https_vip.asus.com_0.localstorage-journal

 上記のように3KB程度なら、放置しててもいいかと思えなくもありません。次に、古さではなく大きさでソートしてみると、上位10ファイルは以下の通り。

2016/06/09  18:56         8,224,768 chrome-extension_gighmmpiobklfepjocnamgkkbiglidom_0.localstorage
2017/02/20  22:59         5,734,400 https_ja.wikipedia.org_0.localstorage
2017/02/20  23:54         4,620,288 chrome-extension_nafpfdcmppffipmhcpkbplhkoiekndck_0.localstorage
2016/03/27  18:30         2,923,520 http_www.higuchi.com_0.localstorage
2017/02/21  02:17         2,555,904 https_en.wikipedia.org_0.localstorage
2017/02/12  18:14         1,933,312 https_www.wsj.com_0.localstorage
2017/02/12  18:11         1,769,472 https_commons.wikimedia.org_0.localstorage
2016/10/31  04:00         1,667,072 http_www.tp-link.jp_0.localstorage
2016/06/09  20:19         1,532,928 http_www.thevegashookup.com_0.localstorage
2016/01/18  12:08         1,222,656 https_zh.wikipedia.org_0.localstorage

 chrome-extensionから始まる、Chromeプラグインが使用しているファイルや、各国のwikipediaによって保持されたファイルが大きいようです。
 ところでこれらは具体的に一体どのようなデータを保持しているのでしょうか。私はWikipediaは参照するだけで編集したこともないですし、中身が気になるので見てみることにします。
 

.localstorageを開く

 バイナリエディタで開いてみると、"SQLite format 3"という文字列から始まっていることが判ります。ということで、これはSQLiteのデータファイルのようです。

 SQLite公式から"A bundle of command-line tools for managing SQLite database files, including the command-line shell program, the sqldiff.exe program, and the sqlite3_analyzer.exe program."をダウンロードします。
SQLite Download Page

 展開したファイル中の"sqlite3.exe"がSQLiteコマンドラインクライアント(Oracleで言うところのSQL*Plus)なので、これを使うことで内部のデータにアクセスできます。
 

sqlite3で.localstorageにアクセス

 sqlite3を起動すると以下のようなバナー表示に続いて、SQLiteのプロンプト表示となります。

SQLite version 3.17.0 2017-02-13 16:02:40
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite>

 .openコマンドでデータファイルを開きます。この際ディレクトリ指定の\マークは\\とする必要があります(\で指定してもエラーメッセージは表示されませんが、意図したファイルも開かれません)。

sqlite> .open "C:\\Users\\USERNAME\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Local Storage\\chrome-extension_gighmmpiobklfepjocnamgkkbiglidom_0.localstorage"

 データファイルが開けても、内部のテーブル名が判らなければSQLを叩けません。Oracleで言うところのDBA_TABLES等のディクショナリやQL*Plusで言うところの"show tables"コマンドに相当するコマンドが、SQLiteでは".table"になるようです。

sqlite> .table
ItemTable

 テーブル名がItemTableだと判ったので、とりあえず参照してみます。

sqlite> select * from ItemTable;
…結果略…

 ごっそりとコンソールに出力が流れました。そりゃそうですね、8MB以上もあるデータファイルで単一テーブルなのだから、何も考えずに全件表示したらこうなります。

 ということで、SQL*Plusで言うところの"spool"コマンドに相当するのが、SQLiteでは".out"になるようです。

sqlite> .out out.txt
sqlite> select * from ItemTable;
sqlite> .out stdout

 これでselect結果をout.txtに落とし込めました。
 
 具体的なデータ内容はここには掲載しませんが、所謂Adblockプラグインのブロック対象リストがデータ量の9割以上を占めていました。過去にAdblock系のプラグインを使用していたことがありますが、1年以上前にアンインストールしています。それでもlocalstorageは消えずに残っていることになります。

 ついでに、このItemTableのテーブル構造を知りたいと思いましたが、SQL*Plusで言うところの"desc"コマンドに相当するものは見当たらないので、スキーマ内オブジェクトのDDLを表示する".schema"を叩いてみます。

sqlite> .schema
CREATE TABLE ItemTable (key TEXT UNIQUE ON CONFLICT REPLACE, value BLOB NOT NULL ON CONFLICT FAIL);

 ということで、ItemTableはkey, valueの2カラムからなるテーブルのようです。で、keyは文字列でユニーク、valueはBLOBでNULL不可と。
 これがそのままlocalStorageのkey, valueのペアに相当しているようですね。

 データ構造が判ったので、他の巨大なファイルも同様に内部を確認してみました。
 WikipediaのlocalStorageには巨大なJavaScriptが保持されていたり、TP-LINKのlocalStorageにはWOFF形式のWeb Fontがbase64エンコードされた文字列が格納されていたり、ExifViewerプラグインのlocalStorageには最近表示された画像のURLとそのEXIFデータのJSON文字列がキャッシュとして保持されていたり、それぞれのデカさに相当するデータが保持されていました。

 それって、単なるブラウザキャッシュじゃダメなのかとか、sessionStorageではなくlocalStorageとして永続的に保持する必要があるのか等、疑問に感じる使われ方も多く見当たりました。
 



以上。