Firefox 3.6で HTML5 の オフラインキャッシュをクリアする

(追記:アドオンを作った。)
HTML5 には オフラインでwebアプリケーションを動作させるためにファイルをキャッシュする手段が指定されている. cache manifest というファイル に,「どのファイルをキャッシュするか」を記述しておき、htmlタグの manifest 属性で指定する.
例:
test.manifest

CACHE MANIFEST
test.html
a.jpeg
b.jpeg
...

test.html

<html manifest='test.manifest'>
...

このように書いておけば インターネット接続が無い環境でも test.html が閲覧できるようになり,たとえば接続が途切れやすいモバイル環境でもハッピーになれるというわけだ.
オフラインキャッシュを使ったwebアプリケーションのサンプルが hacks.mozilla.orgで公開されている. タスクリストのwebアプリで,LANケーブルを引っこ抜いてもタスクリストが管理できる.

しかしながら,各ブラウザでのHTML5の実装状況はまちまちであるような感じらしい(HTML5の策定がどのような状況なのかは知らないが).SafariHTML5を軽く試した限りでは,まともに動作しているように見えた.Appleの本気度の現れだろうか.一方でFirefoxのcache manifestは今のところ少し扱いづらい.HTML5を詳しく調べたわけではないが使っていて非常に混乱する部分がある.

そこで,Firefoxのオフラインキャッシュの機能について,さしあたり現在の挙動振る舞いについてまとめた.未だexperimentalな機能なので将来的には改善されると思うけれど,それまでのつなぎにはなるかもしれない.

キャッシュの更新

Firefoxの cache manifest について
Stackoverflow - How to properly invalidate an HTML5 Cache Manifest for online/offline web apps? で議論されている(ここにポストされている「キャッシュ更新検出スクリプト」は結構便利).いわく,

cache manifest に列挙したファイルはリロード時にもフェッチされない

ということらしい.

どうやってキャッシュを更新するか

MDCで解説されているとおり,一応,キャッシュを更新する方法はある. cache manifestを更新すれば,ページを構成する他のファイルの更新がチェックされ必要なファイルがダウンロードされるようだ.しかし 何をもって cache manifest の「更新」とするのかがかなりsensitiveで,少しのミスでページのページのリロードがされなくなってしまう.曰く,

  1. manifest ファイルにエラーがある場合にはリロードしない.ここでエラーとは
    • 構文エラー
    • manifest ファイルに記述されているファイルが存在しない
    • manifestファイルに記述されているJavaScriptファイルに構文エラーがある???(そう見えるときがある)
  2. manifest ファイルのコメントや空行は無視される.コメントが修正されてもリロードされない(MDCの説明と違う!).

…つまり,cache manifestに書いたファイルは全てサーバー上に準備しておかなければならず,さらにcache manifestに記述したエントリを増やすか削るかしないと,ページのリロードを促すことはできない.面倒である.
またFirefoxのリロードボタン(F5やCommand-R)は少なくとも2回は試したほうが良いようだ.

オフラインキャッシュをクリアする方法

いちいちcache manifestを更新するよりは,いっそのこと オフラインキャッシュをクリアしてしまうのも一手だ.普通のやり方と,私が少しググって考えたもう一つのやり方を紹介する.

方法1

メニュー Tools -> Clear Recent History から Site Preferences (Cache ではなく) にチェックを入れて Clear Now をクリックする.
…しかしこの方法では全てのサイトのオフラインキャッシュがクリアされてしまう.

方法2

次のJavaScriptをエラーコンソールで実行する.

Components.classes["@mozilla.org/network/application-cache-service;1"].getService(Components.interfaces.nsIApplicationCacheService).getActiveCache('マニフェストファイルのURL').discard();

この方法であれば目的のページのキャッシュのみをクリアできる.
適当なAdd-onの開発が待たれる.

方法3

about:cache?device=offline で表示されるディレクトリにあるindex.sqlite の中身をうまく消す。 方法はわからないがこのファイルを消してしまっても大丈夫かもしれない(試していない)

別の話

cache manifestでキャッシュされたページからXMLHttpRequestでcache manifestにないファイルを取りにいくとエラー (Error: uncaught exception: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIXMLHttpRequest.send]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" )
なぜ?