Network Information API は、デバイスが使用中のネットワーク接続に関する情報に Web アプリケーションが アクセスできるようにする。
## 要件とユースケース この文書は、2 つの具体的な要件に対応する API について記述する。 ### ネットワークとの通信に現在使用されている [接続タイプ](https://wicg.github.io/netinfo/#dfn-connection-types) を 判定するためのインターフェースを提供する。 これはクライアントページからアドホックに照会できるべきであり、また [Service Worker](https://w3c.github.io/ServiceWorker/v1/) に 公開されるなど、他のコンテキストでも利用できるべきである。 **ユースケースの例:** * メディアのストリーミングを主目的とする Web アプリケーションは、再生前に `navigator.connection.type` を確認できる。 これが `'cellular'` に設定されている場合、モバイルネットワーク事業者が帯域幅に対して課金している可能性があることをユーザーに 知らせ、以前にキャッシュされたコンテンツのみを自動再生し始める、といったことができる。 * [インストール](https://w3c.github.io/ServiceWorker/v1/#installation-algorithm) 中にリソースを [キャッシュ](https://w3c.github.io/ServiceWorker/v1/#cache-objects) するために Service Worker を利用する Web アプリケーションは、キャッシュし得る複数の異なるアセットのバンドルを持つ場合がある。 すなわち、無条件にキャッシュされる重要なアセットの一覧と、`navigator.connection.type` が `'ethernet'` または `'wifi'` の ときにのみ事前にキャッシュされる、より大きなオプションのアセットのバンドルである。 * [バックグラウンド 同期](https://github.com/WICG/BackgroundSync/blob/master/explainer.md) ハンドラーを伴う Service Worker を使用する Web アプリケーションは、現在の `navigator.connection.type` 値を確認し、それが `'ethernet'` または `'wifi'` の場合にのみ `sync` イベントハンドラー内で データを転送する、といったことができる。 * Web アプリケーションは、ネットワーク状況に基づいてオフラインモードを有効にする判断を下す場合がある(例えば EDGE では 不十分なとき)。 ### 接続タイプが変化した場合にスクリプトへ通知する手段を提供する。 これにより開発者は、ネットワーク接続タイプが変化し、それが何らかの形で影響を及ぼす可能性があることをユーザーに知らせるため、 ユーザーインターフェースを動的に変更できる。また、大量のデータ転送を延期していたアプリケーションが、高帯域幅のネットワークが 検出され次第、自動的に転送を開始できるようにもなる。 **ユースケースの例:** * メディアのストリーミングを主目的とする Web アプリケーションは、接続タイプの更新に応じて、ユーザーインターフェースを 動的に変更できる。これは、ユーザーが再生を試み、1 回限りの照会を行うまで待つよりも、優れたユーザー体験をもたらす 可能性がある。これにより、アプリケーションはユーザーの操作に先立って、接続に関するコンテキストを提供することが できる。 * アップロードまたはダウンロードを可能にする Web アプリケーションは、`navigator.connection.type` が `'cellular'` に 設定されているときにリクエストの開始を延期し、接続の変化に対するリスナーを追加する場合がある。高帯域幅のネットワーク タイプへの変化が検出されたとき、リクエストを自動的に開始できる。
## 利用例 この API で構築できるアプリケーションの種類の例については、[Review of Apps that Use Network Information](https://github.com/w3c-webmob/netinfo) を参照のこと。
  // 接続タイプを取得する。
  var type = navigator.connection.type;

  // 最初のネットワークホップのダウンリンク速度の上限を取得する
  var max = navigator.connection.downlinkMax;

  function changeHandler(e) {
    // ここで接続の変化を処理する。
  }

  // イベントの変化を登録する。
  navigator.connection.onchange = changeHandler;

  // あるいは。
  navigator.connection.addEventListener('change', changeHandler);
  
## 定義 明確にするために、メガビット は 1,000,000 ビットであり、メガビット毎秒 は次の転送に 相当する。 * 毎秒 1,000,000 ビット * 毎秒 1,000 キロビット * 毎秒 125,000 バイト * 毎秒 125 キロバイト * など…… ## 接続タイプ ### 基盤となる接続技術 この節では、ユーザーエージェント が使用している(もしあれば)接続タイプ基盤となる接続 技術 を定義する。
bluetooth
Bluetooth 接続。
cellular
セルラー接続(例: EDGE、HSPA、LTE など)。
ethernet
イーサネット接続。
none
ネットワーク接続なし。ユーザーがリンクをたどったとき、またはスクリプトがリモートページを要求したとき(あるいは そのような試みが失敗するとわかっているとき)、ユーザーエージェントはネットワークに接続しない。すなわち、HTML における navigator.onLine === false に相当する。
mixed
ユーザーエージェントは複数の接続タイプを使用している。
other
既知の接続タイプであるが、列挙された接続タイプのいずれでもないもの。
unknown
ユーザーエージェントはネットワーク接続を確立したが、基盤となる 接続技術を判定できない、または判定しようとしないもの。
wifi
Wi-Fi 接続。
wimax
WiMAX 接続。
この API では、接続タイプConnectionType 列挙型で表される。 ### ConnectionType 列挙型
  enum ConnectionType {
    "bluetooth",
    "cellular",
    "ethernet",
    "mixed",
    "none",
    "other",
    "unknown",
    "wifi",
    "wimax"
  };
### 実効接続タイプ この節では、実効接続タイプ(ECT)を定義する。
実効接続タイプの表
ECT 最小 RTT (ms) 最大ダウンリンク (Kbps) 説明
slow-2g 2000 50 このネットワークは、テキストのみのページなど、小さな転送のみに適している。
2g 1400 70 このネットワークは、小さな画像の転送に適している。
3g 270 700 このネットワークは、高解像度画像、音声、SD 動画など、大きなアセットの転送に適している。
4g 0 このネットワークは、HD 動画やリアルタイム動画などに適している。
上記のラウンドトリップおよび帯域幅の値は、実際のユーザー測定の観測結果に基づいている。 * `slow-2g` は 2G 観測値の 66.6 パーセンタイルである * `2g` は 2G 観測値の 50 パーセンタイルである * `3g` は 3G 観測値の 50 パーセンタイルである 上記で提供される絶対値は、2017 年 4 月時点で取得された、Android 上の Chrome における実際のユーザー測定に基づいている。 ユーザーエージェントは、測定データの変化を反映するために、将来これらの値を更新してもよい。 この API では、実効接続タイプEffectiveConnectionType 列挙型で表される。 ### EffectiveConnectionType 列挙型
  enum EffectiveConnectionType {
    "2g",
    "3g",
    "4g",
    "slow-2g"
  };
## NavigatorNetworkInformation インターフェース Navigator および WorkerNavigator インターフェースは、NavigatorNetworkInformation を ミックスインすることによって、NetworkInformation インターフェースへのアクセスを公開する。
  interface mixin NavigatorNetworkInformation {
    [SameObject] readonly attribute NetworkInformation connection;
  };

  Navigator includes NavigatorNetworkInformation;
  WorkerNavigator includes NavigatorNetworkInformation;
### connection 属性 connection 属性は、取得時に、NetworkInformation インターフェースを実装するオブジェクトを 返す。
## NetworkInformation インターフェース NetworkInformation インターフェースは、ユーザーエージェントが現在使用しているネットワーク接続に関する情報に アクセスする手段を提供する。EventTarget は [[!DOM]] で定義されている。
  [Exposed=(Window,Worker)]
  interface NetworkInformation : EventTarget {
    readonly attribute ConnectionType type;
    readonly attribute EffectiveConnectionType effectiveType;
    readonly attribute Megabit downlinkMax;
    readonly attribute Megabit downlink;
    readonly attribute Millisecond rtt;
    attribute EventHandler onchange;
  };

  typedef unrestricted double Megabit;
  typedef unsigned long long Millisecond;
  
この節ではまた、ユーザーのネットワーク状況に関する詳細を公開する、いくつかの HTTP リクエストヘッダーフィールドを 定義する。これらはサーバーが受信をオプトインできるものである。サーバーは、[[CLIENT-HINTS]] で定義され、 [[CLIENT-HINTS-INFRASTRUCTURE]] で定義された処理モデルに拘束される Client Hints インフラストラクチャを介してそれを行える。 ### type 属性 type 属性は、取得時に、ユーザーエージェントが使用している 接続タイプ を返す。 ### effectiveType 属性 effectiveType 属性は、取得時に、最近観測された rttdownlink の値の組み合わせを使用して 決定される 実効接続タイプ を返す。 #### ECT リクエストヘッダーフィールド ECT リクエストヘッダーフィールドは、ユーザーエージェントがリクエストを行う時点での effectiveType を示す トークンであり、これは EffectiveConnectionType の値のいずれかである。 これは値が Token でなければならない構造化ヘッダー(Structured Header)である。[[STRUCTURED-HEADERS]] ### downlinkMax 属性 downlinkMax 属性は、最初のネットワークホップのダウンリンク速度の 上限を表す。報告される値は メガビット毎秒 単位であり、基盤となる接続技術 の プロパティによって決定される。
ユーザーエージェントは、特定のリクエストを満たすために必要なさまざまなネットワークホップの総数や性能特性を 把握していない。異なるリクエストは異なる経路をたどり、異なる性能特性を持つ場合がある。報告される 最初のネットワークホップのダウンリンク速度の上限 の値は、最初のネットワークホップの 基盤となる接続技術 のプロパティによって決定される。 いかなるリクエストのエンドツーエンド性能もこの値を超えることはできないが、これは性能を 保証するものではなく、大幅に悪化する場合もある。
### onchange 属性 onchange イベントハンドラー属性は、接続値を更新する 手順中に発火される "change" イベントを処理する。 ### downlink 属性 downlink 属性は、メガビット毎秒 単位の実効帯域幅推定値を表す。これは最も近い 25 キロビット毎秒の倍数に 丸められ、最近アクティブだった接続にわたって最近観測されたアプリケーション層のスループットに基づくが、 プライベートアドレス空間 [[!RFC1918]] への接続は除外される。最近の帯域幅測定データがない場合、属性値は 基盤となる接続 技術 のプロパティによって決定される。 #### `Downlink` リクエストヘッダーフィールド Downlink リクエストヘッダーフィールドは、ユーザーエージェントがリクエストを行う時点での downlink の値を 示す数値である。 これは値が Decimal でなければならない構造化ヘッダー(Structured Header)である。[[STRUCTURED-HEADERS]] ### rtt 属性 rtt 属性は、ミリ秒 単位の実効ラウンドトリップ時間推定値を表し、最も近い 25 ミリ秒の倍数に丸められ、 最近アクティブだった接続にわたって最近観測されたアプリケーション層の RTT 測定値に基づくが、 プライベートアドレス空間 [[!RFC1918]] への接続は除外される。最近の RTT 測定データがない場合、属性値は 基盤となる接続技術 のプロパティによって決定される。 #### `RTT` リクエストヘッダーフィールド RTT リクエストヘッダーフィールドは、ユーザーエージェントがリクエストを行う時点での rtt の値を示す 数値である。 これは値が Integer でなければならない構造化ヘッダー(Structured Header)である。[[STRUCTURED-HEADERS]] ## 基盤となる接続技術 基盤となる接続技術 とその 最初のネットワークホップのダウンリンク速度の 上限 との関係は、新しいネットワークリクエストを満たすために使用され得る利用可能なネットワーク インターフェースによって決定される。 利用可能なインターフェースに対する downlinkMax は、最大ダウンリンク速度の表 に記載された、標準化された、 または一般的に受け入れられている最大ダウンロードデータレートによって決定される。可能な場合、この値は、信号 強度、変調アルゴリズム、その他の「ネットワークの天候」変数など、インターフェースの現在のプロパティに基づいて、 より正確な上限を報告するように精緻化される場合がある。 最初のネットワークホップのダウンリンク速度の上限 は、 href="#handling-changes-to-the-underlying-connection">基盤となる接続の変化の処理 に記載された規則によって決定される。
利用可能なネットワークインターフェースとその世代およびバージョンの列挙は、スクリプトに直接公開されない。 その代わり、`downlinkMax` は、すべての利用可能なインターフェースとその現在のネットワーク状況を反映した メガビット毎秒 単位の単一の値を公開する。
### 基盤となる接続の変化の処理 異なる 接続タイプ もしくは 実効接続タイプ への切り替え、最初のネットワークホップのダウンリンク速度の 上限の変化、または実効的な downlink もしくは rtt の推定値の変化によって 基盤となる接続技術 の プロパティが変化したとき、ユーザーエージェントは 接続値を更新する手順 を実行 しなければならない: 1. new-type を、基盤となる接続 技術 を表す 接続タイプ とする。 1. new-effective-type を、現在の downlink および rtt の値によって決定される 実効接続タイプ とする。 1. new-downlink を次の結果とする。 1. downlink の値を最も近い 25 キロビット毎秒の倍数に丸める。 1. 結果の値が `connection.downlink` の値より 10% 大きいか小さい場合、new-dowlink をその結果の値に 設定する。そうでない場合、new-downlink を `connection.downlink` の値に設定する。 1. new-rtt を次の結果とする。 1. rtt の値を最も近い 25 ミリ秒の倍数に丸める。 1. 結果の値が `connection.rtt` の値より 10% 大きいか小さい場合、new-rtt をその結果の値に 設定する。そうでない場合、new-rtt を `connection.rtt` の値に設定する。 1. new-type が "none" の場合、max-value を `0` に設定する。 1. new-type が "unknown" の場合、max-value を `+Infinity` に設定する。 1. new-type が "mixed" の場合、max-value を、新しいネットワークリクエストを処理するために 使用されるインターフェース構成に適用可能な値に設定する。例えば、複数のインターフェースが使用される場合、それらの 利用可能なインターフェースに対する downlinkMax の値を合計する。 1. そうでない場合、max-value利用可能なインターフェースに対する downlinkMax に設定する。 1. max-value が `connection.downlinkMax` の値と等しくない場合、または new-type が `connection.type` の値と等しくない場合、または new-downlink が `connection.downlink` の値と等しくない場合、または new-rtt が `connection.rtt` の値と等しくない場合: 1. ネットワーキングタスクソース を使用して、次を実行する data-cite="!HTML#queue-a-task">タスクをキューに入れる: 1. `connection.downlinkMax` を max-value に設定する。 1. `connection.type` を new-type に設定する。 1. `connection.effectiveType` を new-effective-type に設定する。 1. `connection.downlink` を new-downlink に設定する。 1. `connection.rtt` を new-rtt に設定する。 1. `NetworkInformation` オブジェクトで `change` という名前の イベントを発火する
## プライバシーに関する考慮事項 Network Information API は、観測されたエンドツーエンドのネットワーク帯域幅および遅延、ならびにユーザーエージェントと サーバーの間の最初のネットワークホップに関する情報、具体的には接続のタイプとダウンリンク速度の上限、さらに この情報が変化するたびのシグナルを公開する。そのような情報は、次の目的に使用される 可能性がある: * ある時点での特定のネットワークの特性(例: タイプおよびダウンリンク推定値)に基づき、またそのような特性の 一定期間にわたる変化を観測することによって、ユーザーをフィンガープリントする。 * 1 つ以上のネットワーク間の遷移(例: タイプ、ダウンリンク推定値、時刻による遷移の順序に基づく)に基づいて、 ユーザーをフィンガープリントする。 * 上記の基準に基づいて、ユーザーの位置(例: 自宅、職場、移動中のいずれか)を推測する。 ただし、上記の考慮事項は新しいものではなく、十分な動機を持つ攻撃者は、他の技術を使用してそのような情報を すでに取得できる可能性がある: * 攻撃者は JavaScript を使用して、クライアント上の任意のネットワークフェッチ(同一オリジンまたはクロスオリジン)の 継続時間(例: フェッチ開始から `onload` イベントまでの時間)を観測でき、Resource Timing API を介して同じ フェッチに関するより詳細なタイミングデータを取得できる場合がある。 * 攻撃者は WebRTC を使用して、STUN または類似のメカニズムを介して、クライアントのパブリックおよびプライベート IP アドレスを特定できる。 * 攻撃者は、サーバー上でフェッチのクライアント IP、フェッチ継続時間、RTT、転送速度、その他の低レベルの ソケットメトリクスを観測できる。 さらに、上記の戦略の 1 つを繰り返すことによって(例: リソースの定期的なフェッチや再取得の呼び出し、定期的な SSE や WebSocket メッセージ、定期的な STUN リクエストなど)、攻撃者はクライアントの接続および IP アドレスの 性能特性の経時的な変化を観測できる。そのようなデータはその後、ユーザーフィンガープリントを精緻化し、ユーザーの 位置(例: 自宅、職場、移動中のいずれか)を推測し、さまざまな行動パターンを抽出するために 使用できる。 上記のリストは完全な概要ではない。ただし、上記の例が示すように、攻撃は送信側と受信側の 両方から可能である: * 攻撃者がクライアントから任意の種類のネットワークフェッチを開始または観測できる場合、その性能特性と それらが経時的にどのように変化するかを観測できる。 * 攻撃者がクライアントに自分のサーバーからリソースをフェッチさせることができる場合、同様にフェッチの 性能特性とそれらが経時的にどのように変化するかを観測できる。 クライアントから開始されるそのような攻撃を緩和するには、攻撃者がネットワークリクエストを観測および開始することを 防ぐ必要がある。例えば、悪意のある者による単純なコンテンツインジェクションを防ぐために HTTPS を使用する、任意の 種類のスクリプト化されたリソースフェッチを防ぐために JavaScript を無効にする、などである。送信側からの攻撃の緩和は、 VPN または HTTP プロキシの使用によって可能である。例えば、クライアントの真の IP アドレスを隠す、追加の遅延を導入する、などである。 このように、Network Information API は、ネットワークリクエストを観測または実行する必要を回避することによって、 エンドツーエンドのネットワークスループット、遅延、および最初のネットワークホップに関する情報の取得を容易にするが、 十分な動機を持つ攻撃者がすでに利用できない情報を公開することはない。 クライアントがこの種の攻撃を緩和したい場合、JavaScript を無効にし、すべての送信リクエストが信頼できるオリジンに 対して行われていることを監視し、匿名化 VPN/プロキシサービスを入念に利用すべきである。
## IANA に関する考慮事項 次の 3 つの HTTP リクエストヘッダーフィールドは、HTTP/1.1 [[!RFC7231]] が示すガイドラインを考慮した上で、メッセージ ヘッダーフィールドの恒久的なレジストリ([[!RFC3864]] を参照)に追加されるべきである。
### `ECT` リクエストヘッダーフィールドの登録 * ヘッダーフィールド名: ECT * 適用プロトコル: Hypertext Transfer Protocol (HTTP) * ステータス: Standard * 著者/変更管理者: W3C * 仕様文書: W3C TR https://www.w3.org/TR/netinfo/
### `RTT` リクエストヘッダーフィールドの登録 * ヘッダーフィールド名: RTT * 適用プロトコル: Hypertext Transfer Protocol (HTTP) * ステータス: Standard * 著者/変更管理者: W3C * 仕様文書: W3C TR https://www.w3.org/TR/netinfo/
この仕様への適合を主張できる製品のクラスは 1 つだけである。 すなわち ユーザーエージェント である。
## 謝辞 この文書は、[[!HTML]] 仕様のライセンスで許可されている範囲で、 その仕様のテキストを再利用している。