1. 7.9 オフラインウェブアプリケーション
      1. 7.9.1 導入
        1. 7.9.1.1 レガシーアプリケーションへのオフラインキャッシュのサポート
        2. 7.9.1.2 イベントの概要
      2. 7.9.2 キャッシュマニフェスト構文
        1. 7.9.2.1 サンプルマニフェスト
        2. 7.9.2.2 キャッシュマニフェストの記述
      3. 7.9.3 Security concerns with offline applications caches
      4. 7.9.4 アプリケーションキャッシュAPI
      5. 7.9.5 ブラウザーの状態

7.9 オフラインウェブアプリケーション

Using_the_application_cache

Support in all current engines.

Firefox3.5+Safari4+Chrome4+
Opera10.6+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android4+Safari iOS3.2+Chrome Android18+WebView Android4+Samsung Internet1.0+Opera Android11+
caniuse.com table

この機能は、ウェブプラットフォームから削除中である。(これは何年もかかる長いプロセスである。)現時点で、オフラインウェブアプリケーション機能のいずれかを使用することは、極めて勧められない。代わりにサービスワーカーを使用すること。[SW]

7.9.1 導入

ネットワーク接続が利用できない場合―たとえば、ユーザーがISPのカバレッジエリアの外に移動しているため―でも、ユーザーにウェブアプリケーションおよび文書との対話を継続できるようにするために、著者は、オフラインで作業し、オフラインで使用のためにファイルのコピーを保持するためにユーザーのブラウザーになる、ウェブアプリケーション用に必要とされるファイルの一覧を示したマニフェストを提供できる。

これを説明するために、HTMLページ"clock1.html"、CSSスタイルシート"clock.css"、およびJavaScriptスクリプト"clock.js"から成る単純な時計アプレットを考えてみる。

マニフェストを追加する前に、これらの3つのファイルは次のようになる:

<!-- clock1.html -->
<!DOCTYPE HTML>
<html lang="en">
 <head>
  <meta charset="utf-8">
  <title>Clock</title>
  <script src="clock.js"></script>
  <link rel="stylesheet" href="clock.css">
 </head>
 <body>
  <p>The time is: <output id="clock"></output></p>
 </body>
</html>
/* clock.css */
output { font: 2em sans-serif; }
/* clock.js */
setInterval(function () {
    document.getElementById('clock').value = new Date();
}, 1000);

ユーザーがオフライン時に"clock1.html"ページを開こうとする場合、しかし、(ローカルキャッシュにまだ持つ場合を除いて)ユーザーエージェントはエラーとともに失敗する。

著者は、代わりに"clock.appcache"という、3つのファイルのマニフェストを提供できる:

CACHE MANIFEST
clock2.html
clock.css
clock.js

With a small change to the HTML file, the manifest (served as text/cache-manifest) is linked to the application:

<!-- clock2.html -->
<!DOCTYPE HTML>
<html lang="en" manifest="clock.appcache">
 <head>
  <meta charset="utf-8">
  <title>Clock</title>
  <script src="clock.js"></script>
  <link rel="stylesheet" href="clock.css">
 </head>
 <body>
  <p>The time is: <output id="clock"></output></p>
 </body>
</html>

さて、ユーザーがページに行く場合、ブラウザーはファイルをキャッシュし、ユーザーがオフラインである場合でも、それらを使用できるようにする。

著者はまた、マニフェストのメインページを含めることを推奨するが、実際にマニフェストを参照されるページは、明示的に言及されない場合でも、自動的にキャッシュされる。

"no-store"ディレクティブ例外とともに、TLSで供給される(https:を使用して暗号化される)キャッシュページでのHTTPキャッシュヘッダーと制限は、マニフェストによって上書きされる。したがって、ページは、ユーザーエージェントがそれを更新する前にアプリケーションキャッシュから期限切れにならず、TLS経由で提供されるアプリケーションはオフラインで動作させることができる。

この例をオンラインで見る

7.9.1.1 レガシーアプリケーションへのオフラインキャッシュのサポート

マニフェストに記載されかつアプリケーションキャッシュに格納されたロジック(マークアップ、スクリプト、スタイルシート、画像など)とともに、アプリケーションに対する有限数の静的HTMLページとともに、およびウェブストレージまたはサーバー側にインデックス付けされたデータベースに格納されたアプリケーションおよびユーザーデーターとともに、アプリケーションロジックがアプリケーションとユーザーデータから別れる場合、アプリケーションキャッシュ機能は最も機能的に動作し、ウェブソケット、XMLHttpRequest、サーバーに送信されるイベント、または他の同様の機構を使用して動的に更新される。

このモデルはユーザーに対して高速な経験をもたらす:(おそらく古いデータを示しつつ)アプリケーション即時に読み込み、ネットワークがそれを可能にするように、新鮮なデータを高速に得られる。

しかし、レガシーアプリケーションは、サーバーから新しいHTMLページで得られた各操作とともに、ユーザーデータおよびロジックがHTMLと一緒に混合されるように設計される傾向にある。

たとえば、ニュースアプリケーションを考えてみよう。このようなアプリケーションの典型的なアーキテクチャーは、アプリケーションキャッシュ機能を使用しない場合、ユーザーはメインページをフェッチし、サーバーは現在の見出しとユーザーインタフェースロジックを一緒に混合した動的に生成されるページを返す。

しかし、アプリケーションキャッシュ機能のために設計されたニュースアプリケーションは、ロジックでのみ構成されるメインページを代わりに持つだろうし、メインページがサーバーとは別にデータをフェッチしているだろう。たとえば、XMLHttpRequestを使用して。

混合コンテンツモデルは、アプリケーションのキャッシュ機能とともにうまく動作しない:コンテンツがキャッシュされているので、常にキャッシュが更新された前回から古いデータを見て、ユーザーにもたらすだろう。

分離されたモデルと同じ速さで、従来のモデルを動作させる方法がないが、それは少なくとも好ましいオンラインアプリケーションキャッシュモードを使用してオフライン利用で使用するために改造できる。これを行うには、アプリケーションキャッシュマニフェストでオフライン作業をしたいHTMLページによって使用されるすべての静的リソースを一覧表示し、HTMLファイルからそのマニフェストを選択するmanifest属性を使用し、マニフェストの一番下に次の行を追加する:

SETTINGS:
prefer-online
NETWORK:
*

This causes the application cache to only be used for primary entries when the user is offline, and causes the application cache to be used as an atomic HTTP cache (essentially pinning resources listed in the manifest), while allowing all resources not listed in the manifest to be accessed normally when the user is online.

7.9.1.2 イベントの概要

ユーザーがマニフェストを宣言するページを訪問するときに、ブラウザーはキャッシュを更新しようとする。これは、ユーザーエージェントが最後にそれを見てからマニフェストが変更された場合、それが言及されているすべてのリソースを再ダウンロードして改めてキャッシュし、マニフェストのコピーをフェッチすることによってこれを行う。

これが起こっているように、ユーザーに適切な方法で通知できるように、イベントの数は、キャッシュの更新の状態へと更新されたスクリプトを保つためにApplicationCacheオブジェクトで発火する。イベントは次のとおり:

イベント名インターフェイス発火条件次のイベント
checkingEventユーザーエージェントは、更新をチェックする、または初回のマニフェストをダウンロードしようとしている。これは、常にシーケンスの最初のイベントである。noupdatedownloadingobsoleteerror
noupdateEventマニフェストは変更されなかった。シーケンス内の最後のイベント。
downloadingEventユーザーエージェントは更新を発見し、それをフェッチしている、または初回のマニフェストで記載されたリソースをダウンロードしている。progresserrorcachedupdateready
progressProgressEventユーザーエージェントは、マニフェストで記載されたリソースをダウンロードしている。イベントオブジェクトのtotal属性は、ダウンロードされたファイルの合計数を返す。イベントオブジェクトのloaded属性は、これまでに処理されたファイルの数を返す。progresserrorcachedupdateready
cachedEventマニフェストに記載されたリソースがダウンロードされ、アプリケーションがキャッシュされた。シーケンス内の最後のイベント。
updatereadyEventマニフェストに記載されたリソースは新しく再ダウンロードされており、スクリプトは新しいキャッシュに切り替えるためにswapCache()を使用できる。シーケンス内の最後のイベント。
obsoleteEventマニフェストは404または410ページになっていることが判明し、アプリケーションのキャッシュを削除している。シーケンス内の最後のイベント。
errorEventマニフェストが404または410ページだったので、アプリケーションをキャッシュする試みが中止された。シーケンス内の最後のイベント。
マニフェストは変更されなかったが、マニフェストを参照するページが正しくダウンロードでなかった。
マニフェストに記載されたリソースをフェッチするときに致命的なエラーが発生した。
更新されている間にマニフェストが変更された。ユーザーエージェントは、再び一時的にファイルをフェッチしようする。

これらのイベントはキャンセル可能である。それらのデフォルトアクションは、ダウンロードの進捗情報を表示するためのユーザーエージェントに対するものである。ページが独自のアップデートのUIが表示する場合、イベントのキャンセルは、冗長な進捗情報の表示からユーザーエージェントを防ぐだろう。

7.9.2 キャッシュマニフェスト構文

7.9.2.1 サンプルマニフェスト

This example manifest requires two images and a style sheet to be cached and safelists a CGI script.

CACHE MANIFEST
# the above line is required

# this is a comment
# there can be as many of these anywhere in the file
# they are all ignored
  # comments can have spaces before them
  # but must be alone on the line

# blank lines are ignored too

# these are files that need to be cached they can either be listed
# first, or a "CACHE:" header could be put before them, as is done
# lower down.
images/sound-icon.png
images/background.png
# note that each file has to be put on its own line

# here is a file for the online safelist -- it isn't cached, and
# references to this file will bypass the cache, always hitting the
# network (or trying to, if the user is offline).
NETWORK:
comm.cgi

# here is another set of files to cache, this time just the CSS file.
CACHE:
style/default.css

同様に次のように記述することができる:

CACHE MANIFEST
NETWORK:
comm.cgi
CACHE:
style/default.css
images/sound-icon.png
images/background.png

オフラインアプリケーションキャッシュマニフェストは、絶対パスまたは絶対URLを使用することができる:

CACHE MANIFEST

/main/home
/main/app.js
/settings/home
/settings/app.js
https://img.example.com/logo.png
https://img.example.com/check.png
https://img.example.com/cross.png

次のマニフェストは、ユーザーがオフラインの間にサイト上の任意のページに表示されている汎用のエラーページを定義する。これはまた、オンラインセーフリストワイルドカードフラグopenであることを指定し、他のサイト上のリソースにアクセスがブロックされないことを意味する。(汎用フォールバック名前空間なので、同じサイト上のリソースがすでにブロックされない。)

このマニフェスト上のすべてのページのように、同じページにヒットする後続はキャッシュからすぐに読み込まれるので、それらがフェッチされるようにローカルでキャッシュされるだろう。マニフェストが変更されるまで、これらのページは、再度サーバーからフェッチされることはない。マニフェストが変更されるとき、次にすべてのファイルが再ダウンロードされる。

スタイルシートや画像などのようなサブリソースは、しかし、通常のHTTPキャッシングセマンティックスを使用してのみキャッシュされる。

CACHE MANIFEST
FALLBACK:
/ /offline.html
NETWORK:
*
7.9.2.2 キャッシュマニフェストの記述

Manifests must be served using the text/cache-manifest MIME type. All resources served using the text/cache-manifest MIME type must follow the syntax of application cache manifests, as described in this section.

アプリケーションキャッシュマニフェストは、テキストがUTF-8を使用してエンコードされるテキストファイルである。アプリケーションキャッシュマニフェストでのデータは行ベースである。Newlines must be represented by U+000A LINE FEED (LF) characters, U+000D CARRIAGE RETURN (CR) characters, or U+000D CARRIAGE RETURN (CR) U+000A LINE FEED (LF) pairs. [ENCODING]

これは、すべてのtext/*型が唯一のCRLF改行を許可する必要がある、RFC 2046の故意の違反である。しかし、この要件は時代遅れである。CR、LFおよびCRLFの改行の使用は一般的に支持されており、実際に時にCRLFはテキストエディターでサポートされない[RFC2046]

The first line of an application cache manifest must consist of the string "CACHE", a single U+0020 SPACE character, the string "MANIFEST", and either a U+0020 SPACE character, a U+0009 CHARACTER TABULATION (tab) character, a U+000A LINE FEED (LF) character, or a U+000D CARRIAGE RETURN (CR) character. The first line may optionally be preceded by a U+FEFF BYTE ORDER MARK (BOM) character. 他のテキストが最初の行にある場合、無視される。

後続の行がもしあれば、すべて次のいずれかでなければならない:

空白行

Blank lines must consist of zero or more U+0020 SPACE and U+0009 CHARACTER TABULATION (tab) characters only.

コメント

Comment lines must consist of zero or more U+0020 SPACE and U+0009 CHARACTER TABULATION (tab) characters, followed by a single U+0023 NUMBER SIGN character (#), followed by zero or more characters other than U+000A LINE FEED (LF) and U+000D CARRIAGE RETURN (CR) characters.

Comments need to be on a line on their own. If they were to be included on a line with a URL, the "#" would be mistaken for part of a fragment.

セクションヘッダー

セクションヘッダーは、現在のセクションを変更する。可能な4つのセクションヘッダーが存在する:

CACHE:
明示的なセクションに切り替える。
FALLBACK:
代替セクションに切り替える。
NETWORK:
Switches to the online safelist section.
SETTINGS:
設定セクションに切り替える。

Section header lines must consist of zero or more U+0020 SPACE and U+0009 CHARACTER TABULATION (tab) characters, followed by one of the names above (including the U+003A COLON character (:)) followed by zero or more U+0020 SPACE and U+0009 CHARACTER TABULATION (tab) characters.

皮肉なことに、デフォルトでは、現在のセクションは、明示的なセクションである。

現在のセクションのデータ

データ行が取得しなければならない形式は、現在のセクションに依存する。

When the current section is the explicit section, data lines must consist of zero or more U+0020 SPACE and U+0009 CHARACTER TABULATION (tab) characters, a valid URL string identifying a resource other than the manifest itself, and then zero or more U+0020 SPACE and U+0009 CHARACTER TABULATION (tab) characters.

When the current section is the fallback section, data lines must consist of zero or more U+0020 SPACE and U+0009 CHARACTER TABULATION (tab) characters, a valid URL string identifying a resource other than the manifest itself, one or more U+0020 SPACE and U+0009 CHARACTER TABULATION (tab) characters, another valid URL string identifying a resource other than the manifest itself, and then zero or more U+0020 SPACE and U+0009 CHARACTER TABULATION (tab) characters.

When the current section is the online safelist section, data lines must consist of zero or more U+0020 SPACE and U+0009 CHARACTER TABULATION (tab) characters, either a single U+002A ASTERISK character (*) or a valid URL string identifying a resource other than the manifest itself, and then zero or more U+0020 SPACE and U+0009 CHARACTER TABULATION (tab) characters.

When the current section is the settings section, data lines must consist of zero or more U+0020 SPACE and U+0009 CHARACTER TABULATION (tab) characters, a setting, and then zero or more U+0020 SPACE and U+0009 CHARACTER TABULATION (tab) characters.

現在のところ1つの設定のみが定義される:

キャッシュモード設定
これは、文字列"prefer-online"で構成される。この文字列は、キャッシュモード優先オンラインに設定する。(キャッシュモードはデフォルトで高速になる。)

設定セクション内で、各設定は1回以上出現してはならない。

マニフェストは、複数回のセクションを含んでもよい。セクションは空であってもよい。

フォールバック名前空間自体に関連付けられたフォールバックページであるURL、およびそれらの名前空間は、データ行の最初のURLである名前空間、および2番目のURLであるフォールバックページ対応する、フォールバックセクションで指定されなければならない。キャッシュされる他のすべてのページは、明示的なセクションに記載されなければならない。

フォールバック名前空間およびフォールバックエントリーは、マニフェスト自身と同じ生成元を持たなければならない。Fallback namespaces must also be in the same path as the manifest's URL.

フォールバック名前空間は、複数回記載されてはならない。

ユーザーエージェントがオンラインセーフリストに入れる名前空間は、すべてオンラインセーフリストセクションで指定されなければならない。(This is needed for any URL that the page is intending to use to communicate back to the server.) To specify that all URLs are automatically safelisted in this way, a U+002A ASTERISK character (*) may be specified as one of the URLs.

Authors should not include namespaces in the online safelist for which another namespace in the online safelist is a prefix match.

相対URLはマニフェスト自身のURLを基準に指定されなければならない。マニフェスト内のすべてのURLは、(明示的または暗黙的に、相対URLを使用して)マニフェスト自身と同じschemeを持たなければならない。[URL]

URLs in manifests must not have fragments (i.e. the U+0023 NUMBER SIGN character isn't allowed in URLs in manifests).

Fallback namespaces and namespaces in the online safelist are matched by prefix match.

7.9.3 Security concerns with offline applications caches

The main risk introduced by offline application caches is that an injection attack can be elevated into persistent site-wide page replacement. This attack involves using an injection vulnerability to upload two files to the victim site. The first file is an application cache manifest consisting of just a fallback entry pointing to the second file, which is an HTML page whose manifest is declared as that first file. Once the user has been directed to that second file, all subsequent accesses to any file covered by the given fallback namespace while either the user or the site is offline will instead show that second file. Targeted denial-of-service attacks or cookie bombing attacks (where the client is made to send so many cookies that the server refuses to process the request) can be used to ensure that the site appears offline.

To mitigate this, manifests can only specify fallbacks that are in the same path as the manifest itself. This means that a content injection upload vulnerability in a particular directory on a server can only be escalated to a take-over of that directory and its subdirectories. If there is no way to inject a file into the root directory, the entire site cannot be taken over.

If a site has been attacked in this way, simply removing the offending manifest might eventually clear the problem, since the next time the manifest is updated, a 404 error will be seen, and the user agent will clear the cache. "Eventually" is the key word here, however; while the attack on the user or server is ongoing, such that connections from an affected user to the affected site are blocked, the user agent will simply assume that the user is offline and will continue to use the hostile manifest. Unfortunately, if a cookie bombing attack has also been used, merely removing the manifest is insufficient; in addition, the server has to be configured to return a 404 or 410 response instead of the 413 "Request Entity Too Large" response.

TLS does not inherently protect a site from this attack, since the attack relies on content being served from the server itself. Not using application caches also does not prevent this attack, since the attack relies on an attacker-provided manifest.

7.9.4 アプリケーションキャッシュAPI

cache = window . applicationCache

Returns the ApplicationCache object that applies to the active document of that Window.

cache . status

以下に定義された定数で与えられるように、アプリケーションキャッシュの現在のステータスを返す。

cache . update()

アプリケーションキャッシュのダウンロードプロセスを起動する。

Throws an "InvalidStateError" DOMException if there is no application cache to update.

ユーザーエージェントは通常、自動的にアプリケーションキャッシュを更新する処理をするので、通常このメソッドを呼び出す必要はない。

このメソッドは、長期のアプリケーションのような状況で役立つ。For example, a web mail application might stay open in a browser tab for weeks at a time. このようなアプリケーションは、毎日更新をテストできるだろう。

cache . abort()

アプリケーションキャッシュのダウンロード処理を中止する。

This method is intended to be used by web application showing their own caching progress UI, in case the user wants to stop the update (e.g. because bandwidth is limited).

cache . swapCache()

新しいものが存在する場合、最新のアプリケーションキャッシュに切り替わる。If there isn't, throws an "InvalidStateError" DOMException.

これは、以前にロードされたリソースが再読み込みされることはない。たとえば、画像が急にリロードされないと、スタイルシートやスクリプトが再解析または再評価されない。唯一の変更点は、キャッシュされたリソースに対する後続の要求が新しいコピーを取得することである。

このメソッドが呼び出される前にupdatereadyイベントが発火する。Once it fires, the web application can, at its leisure, call this method to switch the underlying cache to the one with the more recent updates. これを適切に使うためには、アプリケーションは動作に新しい機能をもたらすことができるようにする必要がある。たとえば、新しい機能を有効にするためにスクリプトをリロードするなど。

swapCache()の代替は、location.reload()を使用して、ユーザーに適した時点で単にページ全体をリロードすることである。

UNCACHED(数値0)

The ApplicationCache object's cache host is not associated with an application cache at this time.

IDLE(数値1)

The ApplicationCache object's cache host is associated with an application cache whose application cache group's update status is idle, and that application cache is the newest cache in its application cache group, and the application cache group is not marked as obsolete.

CHECKING(数値2)

The ApplicationCache object's cache host is associated with an application cache whose application cache group's update status is checking.

DOWNLOADING(数値3)

The ApplicationCache object's cache host is associated with an application cache whose application cache group's update status is downloading.

UPDATEREADY(数値4)

The ApplicationCache object's cache host is associated with an application cache whose application cache group's update status is idle, and whose application cache group is not marked as obsolete, but that application cache is not the newest cache in its group.

OBSOLETE(数値5)

The ApplicationCache object's cache host is associated with an application cache whose application cache group is marked as obsolete.

NavigatorOnLine

Support in all current engines.

Firefox3.5+Safari5+Chrome1+
Opera3+Edge79+
Edge (Legacy)12+Internet Explorer8+
Firefox Android4+Safari iOS4.2+Chrome Android18+WebView Android1+Samsung Internet1.0+Opera Android10.1+
caniuse.com table
self . navigator . onLine

NavigatorOnLine/onLine

Support in all current engines.

Firefox3.5+Safari5+Chrome1+
Opera3+Edge79+
Edge (Legacy)12+Internet Explorer8+
Firefox Android4+Safari iOS4.2+Chrome Android18+WebView Android1+Samsung Internet1.0+Opera Android10.1+

ユーザーエージェントが正確にオフラインである(ネットワークから切断されている)場合にfalseを返すユーザーエージェントがオンラインかもしれない場合にtrueを返す。

この属性値が変更される場合、イベントonlineおよびofflineが発火する。

この属性は、本質的に信頼できない。コンピューターは、インターネット接続がなくてもネットワークに接続できる。

この例において、ブラウザーがオンラインおよびオフラインになるように、インジケーターが更新される。

<!DOCTYPE HTML>
<html lang="en">
 <head>
  <title>Online status</title>
  <script>
   function updateIndicator() {
     document.getElementById('indicator').textContent = navigator.onLine ? 'online' : 'offline';
   }
  </script>
 </head>
 <body onload="updateIndicator()" ononline="updateIndicator()" onoffline="updateIndicator()">
  <p>The network is: <span id="indicator">(state unknown)</span>
 </body>
</html>