概要
機能ポリシーを使用すると、ウェブ デベロッパーはブラウザ内の特定の API とウェブ機能の動作を選択的に有効化、無効化、変更できます。CSP に似ていますが、セキュリティを制御するのではなく、機能を制御します。
機能ポリシー自体は、デベロッパーとブラウザの間のオプトインの契約を結ぶことはほとんどないため、高品質のウェブアプリの構築(および維持)という Google の目標を促進するのに役立ちます。
はじめに
ウェブ向けの開発は、困難な冒険です。パフォーマンスを追求し、最新のベスト プラクティスをすべて取り入れた最高水準のウェブアプリを構築するだけでは、十分ではありません。長期にわたり優れたエクスペリエンスを維持することはさらに困難です。プロジェクトが進むにつれ、デベロッパーが参加し、新機能が導入され、コードベースが拡大します。一度達成した「すばらしいエクスペリエンス」TM が悪化し始め、UX に不調をもたらす可能性があります。機能ポリシーは、作業を適切に進めるように設計されています。
機能ポリシーでは、一連の「ポリシー」をブラウザで有効にし、サイト全体で使用される特定の機能を適用します。これらのポリシーによって、サイトがアクセスできる API や、特定の機能におけるブラウザのデフォルトの動作の変更が可能な API が制限されます。
機能ポリシーでは、次のようなことができます。
- モバイル動画とサードパーティの動画の
autoplay
のデフォルトの動作を変更します。 - サイトが
camera
やmicrophone
などの機密性の高い API を使用できないようにします。 - iframe で
fullscreen
API を使用できるようにします。 - 同期 XHR や
document.write()
などの古い API の使用をブロックします。 - 画像が適切なサイズに設定されていること(レイアウトのスラッシングを防ぐことなど)と、ビューポートに対して画像が大きすぎること(ユーザーの帯域幅の無駄など)を確認します。
ポリシーはデベロッパーとブラウザ間の契約です。開発者の意図が何であるかをブラウザに通知できるため、アプリが想定外に不正な動作をしようとした場合に、誠実さを保つことができます。サイトまたはサードパーティの埋め込みコンテンツが、あらかじめ選択されたルールに違反しようとすると、ブラウザはより優れた UX で動作をオーバーライドするか、API を完全にブロックします。
機能ポリシーの使用
機能ポリシーでは、次の 2 つの方法で機能を制御できます。
Feature-Policy
HTTP ヘッダーを使用する。- iframe で
allow
属性を使用すると、
Feature-Policy
HTTP ヘッダー
機能ポリシーを使用する最も簡単な方法は、ページのレスポンスとともに Feature-Policy
HTTP ヘッダーを送信することです。このヘッダーの値には、特定のオリジンについてブラウザが尊重するポリシーまたはポリシーのセットを指定します。
Feature-Policy: <feature> <allow list origin(s)>
送信元の許可リストには、さまざまな値を指定できます。
*
: この機能は、最上位のブラウジング コンテキストとネストされたブラウジング コンテキスト(iframe)で許可されます。'self'
: この機能は、トップレベルのブラウジング コンテキストと、同一オリジンのネストされたブラウジング コンテキストで許可されます。ネストされたブラウジング コンテキストのクロスオリジン ドキュメントでは許可されません。'none'
: この機能は、最上位のブラウジング コンテキストでは許可されません。ネストされたブラウジング コンテキストでは許可されません。<origin(s)>
: ポリシーを有効にする特定のオリジン(例:https://example.com
)。
例
サイト全体ですべてのコンテンツによる Geolocation API の使用をブロックするとします。これを行うには、geolocation
機能に対して 'none'
の厳密な許可リストを送信します。
Feature-Policy: geolocation 'none'
コードや iframe が Geolocation API を使用しようとすると、ブラウザによってブロックされます。これは、ユーザーが以前に位置情報の共有を許可している場合にも当てはまります。
場合によっては、このポリシーを少し緩和した方がよい場合もあります。独自のオリジンに Geolocation API の使用を許可し、サードパーティのコンテンツによるアクセスを禁止するには、次のように許可リストで 'self'
を設定します。
Feature-Policy: geolocation 'self'
iframe allow
属性
機能ポリシーを使用する 2 つ目の方法は、iframe
内のコンテンツを制御することです。allow
属性を使用して、埋め込みコンテンツのポリシーリストを指定します。
<!-- Allow all browsing contexts within this iframe to use fullscreen. -->
<iframe src="https://example.com..." allow="fullscreen"></iframe>
<!-- Equivalent to: -->
<iframe src="https://example.com..." allow="fullscreen *"></iframe>
<!-- Allow only iframe content on a particular origin to access the user's location. -->
<iframe
src="https://another-example.com/demos/..."
allow="geolocation https://another-example.com"
></iframe>
既存の iframe 属性についてはどうですか?
機能ポリシーで制御される機能の一部には、動作を制御する既存の属性があります。たとえば、<iframe allowfullscreen>
は iframe コンテンツが HTMLElement.requestFullscreen()
API を使用できるようにする属性です。また、Payment Request API と getUserMedia()
を許可する allowpaymentrequest
属性と allowusermedia
属性もあります。
可能な限り、このような古い属性ではなく allow
属性を使用するようにしてください。後方互換性をサポートする必要がある場合は、allow
属性を同等のレガシー属性とともに使用してもまったく問題ありません(例: <iframe allowfullscreen allow="fullscreen">
)。より制限の厳しいポリシーが優先されます。たとえば、次の iframe は、allow="fullscreen 'none'"
が allowfullscreen
よりも制限的であるため、全画面表示することは許可されません。
<!-- Blocks fullscreen access if the browser supports feature policy. -->
<iframe allowfullscreen allow="fullscreen 'none'" src="..."></iframe>
複数のポリシーを一度に制御する
複数の機能を同時に制御するには、;
で区切ったポリシー ディレクティブのリストを指定して HTTP ヘッダーを送信します。
Feature-Policy: unsized-media 'none'; geolocation 'self' https://example.com; camera *;
または、ポリシーごとに個別のヘッダーを送信します。
Feature-Policy: unsized-media 'none'
Feature-Policy: geolocation 'self' https://example.com
Feature-Policy: camera *;
この例では、次のようになります。
- すべてのブラウジング コンテキストで
unsized-media
の使用を禁止します。 - ページ独自のオリジンと
https://example.com
を除くすべてのブラウジング コンテキストでgeolocation
の使用を禁止します。 - すべてのブラウジング コンテキストに対して
camera
アクセスを許可します。
例 - iframe に複数のポリシーを設定する
<!-- Blocks the iframe from using the camera and microphone
(if the browser supports feature policy). -->
<iframe allow="camera 'none'; microphone 'none'"></iframe>
JavaScript API
Chrome 60 では iframe の Feature-Policy
HTTP ヘッダーと allow
属性がサポートされるようになりましたが、Chrome 74 では JavaScript API が追加されました。
この API を使用すると、クライアントサイドのコードで、ページ、フレーム、ブラウザで許可する機能を特定できます。このファイルの特典には、メイン ドキュメント用の document.featurePolicy
または iframe 用の frame.featurePolicy
からアクセスできます。
例
以下の例は、サイト https://example.com
で Feature-Policy: geolocation 'self'
のポリシーを送信した場合の結果を示しています。
/* @return {Array<string>} List of feature policies allowed by the page. */
document.featurePolicy.allowedFeatures();
// → ["geolocation", "midi", "camera", "usb", "autoplay",...]
/* @return {boolean} True if the page allows the 'geolocation' feature. */
document.featurePolicy.allowsFeature('geolocation');
// → true
/* @return {boolean} True if the provided origin allows the 'geolocation' feature. */
document.featurePolicy.allowsFeature(
'geolocation',
'https://another-example.com/'
);
// → false
/* @return {Array<string>} List of feature policies allowed by the browser
regardless of whether they are in force. */
document.featurePolicy.features();
// → ["geolocation", "midi", "camera", "usb", "autoplay",...]
/* @return {Array<string>} List of origins (used throughout the page) that are
allowed to use the 'geolocation' feature. */
document.featurePolicy.getAllowlistForFeature('geolocation');
// → ["https://example.com"]
ポリシーのリスト
機能ポリシーで制御できる機能は何でしょうか
現時点では、実装されるポリシーとその使用方法に関するドキュメントがありません。また、さまざまなブラウザがこの仕様を採用し、さまざまなポリシーを実装しているため、リストは時間の経過とともに増えていきます。機能ポリシーは今後も変わり続けます。また、優れたリファレンス ドキュメントが必ず必要になるでしょう。
現時点では、いくつかの方法で操作可能な機能を確認できます。
- デモの機能ポリシーのキッチンシンクをご覧ください。Blink に実装されている各ポリシーの例が用意されています。
- 機能名の一覧については、Chrome のソースをご覧ください。
about:blank
に対してdocument.featurePolicy.allowedFeatures()
に対してクエリを実行してリストを探します。
["geolocation",
"midi",
"camera",
"usb",
"magnetometer",
"fullscreen",
"animations",
"payment",
"picture-in-picture",
"accelerometer",
"vr",
...
- Blink で実装済みのポリシーや検討中のポリシーについては、chromestatus.com をご覧ください。
これらのポリシーの使用方法については、仕様の GitHub リポジトリをご覧ください。一部のポリシーに関する説明がいくつか含まれています。
よくある質問
機能ポリシーを使用する状況
すべてのポリシーはオプトイン方式ですので、妥当な場合に機能ポリシーを使用してください。たとえば、アプリが画像ギャラリーの場合は、maximum-downscaling-image
ポリシーを使用することで、モバイル ビューポートに巨大な画像が送信されないようにすることができます。
document-write
や sync-xhr
などの他のポリシーは、特に慎重に使用する必要があります。有効にすると、広告などの第三者のコンテンツが破損するおそれがあります。一方、機能ポリシーは直感チェックにもなります。これにより、ページでそうした悪質な API が決して使用されないようにしてください。
機能ポリシーは開発環境と本番環境のどちらで使用するか
両方です。開発中はポリシーを有効にし、本番環境ではポリシーを有効にしておくことをおすすめします。開発中にポリシーをオンにするとこれにより、予期せぬリグレッションを未然に防ぐことができます。ユーザーに対して特定の UX が保証されるように、本番環境ではポリシーを常に有効にしてください。
ポリシー違反をサーバーに報告する方法はありますか?
Reporting API は現在開発中です。サイトで CSP 違反または非推奨に関するレポートの受信を有効にする方法と同様に、機能ポリシー違反に関するレポートを受け取ることができます。
iframe コンテンツの継承ルール
スクリプト(ファースト パーティまたはサードパーティの)は、閲覧コンテキストのポリシーを継承します。つまり、トップレベルのスクリプトはメイン ドキュメントのポリシーを継承します。
iframe
は親ページのポリシーを継承します。iframe
に allow
属性がある場合は、親ページと allow
リストの間の、より厳格なポリシーが優先されます。iframe
の使用方法について詳しくは、iframe の allow
属性をご覧ください。
ポリシーを適用した場合、ページ ナビゲーション後も維持されますか?
いいえ。ポリシーの存続期間は、単一ページ ナビゲーションのレスポンスのみです。ユーザーが新しいページに移動した場合、ポリシーを適用するには、新しいレスポンスで Feature-Policy
ヘッダーを明示的に送信する必要があります。
機能ポリシーをサポートしているブラウザ
ブラウザ サポートに関する最新情報については、caniuse.com をご覧ください。
現在、機能ポリシーをサポートするブラウザは Chrome のみです。ただし、API サーフェス全体がオプトインまたは機能検出が可能なため、機能ポリシーは段階的な拡張に適しています。
まとめ
機能ポリシーは、より良い UX とパフォーマンス向上への道筋を示すのに役立ちます。アプリの開発や保守の際には特に便利です。コードベースに侵入する前に、潜在的なフットガンを回避することができます。
その他のリソース:
- 機能ポリシーの説明
- 機能ポリシーの仕様
- キッチンシンクのデモ
- 機能ポリシーの DevTools 拡張機能 - ページの機能ポリシーを試すためのテスター。
- chromestatus.com のエントリ