まとめ
機能ポリシーを使用すると、ウェブ デベロッパーは、ブラウザで特定の API とウェブ機能の動作を選択的に有効化、無効化、変更できます。これは CSP と似ていますが、セキュリティを制御するのではなく、機能を制御します。
機能ポリシー自体は、デベロッパーとブラウザ間の小さなオプトイン契約にすぎず、高品質のウェブアプリを構築(および維持)するという Google の目標を促進するうえで役立ちます。
はじめに
ウェブ向けの開発は、難しい仕事です。パフォーマンスに優れ、最新のベスト プラクティスをすべて取り入れた高品質のウェブアプリを構築するだけでも十分です。使い続けていくうちに、こうしたエクスペリエンスを維持するのはさらに困難です。プロジェクトが進化するにつれ、デベロッパーが関与し、新機能を導入し、コードベースを拡大していきます。一度達成した素晴らしいエクスペリエンス TM が劣化し、UX も低下し始める可能性があります。機能ポリシーは、順調に進んでいくことを目的としています。
機能ポリシーでは、ブラウザに対して一連の「ポリシー」をオプトインして、サイト全体で使用される特定の機能に適用します。このポリシーでは、サイトがアクセスできる API を制限したり、一部の機能に関するブラウザのデフォルトの動作を変更したりできます。
機能ポリシーでできることの例:
- モバイルとサードパーティの動画に対する
autoplay
のデフォルトの動作を変更します。 - サイトによる
camera
やmicrophone
などの機密性の高い API の使用を制限します。 - iframe で
fullscreen
API を使用できるようにします。 - 同期 XHR や
document.write()
などの古い API の使用をブロックする。 - 画像のサイズを適切に設定し(レイアウトのスラッシングを防ぐなど)、ビューポートに対して大きすぎる画像にならないようにします(ユーザーの帯域幅を浪費するなど)。
ポリシーはデベロッパーとブラウザ間の契約です。開発者の意図をブラウザに通知することで、アプリが枠組みを突破して不適切な動作をしようとした場合に、Google が率直さを保てるようにします。サイトまたは埋め込みサードパーティのコンテンツが、デベロッパーが事前に選択したルールのいずれかに違反しようとした場合、ブラウザはより優れた UX で動作をオーバーライドするか、API 全体をブロックします。
機能ポリシーの使用
機能ポリシーでは、次の 2 つの方法で機能を制御できます。
Feature-Policy
HTTP ヘッダーを使用する。- iframe で
allow
属性を使用する場合。
Feature-Policy
HTTP ヘッダー
機能ポリシーを使用する最も簡単な方法は、ページのレスポンスで Feature-Policy
HTTP ヘッダーを送信することです。このヘッダーの値は、ブラウザが特定の生成元を尊重する 1 つまたは複数のポリシーです。
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 を使用しようとすると、ブラウザによってブロックされます。これは、ユーザーが以前に現在地を共有する権限を付与している場合にも当てはまります。
場合によっては、このポリシーを少し緩和した方がよいこともあります。許可リストで 'self'
を設定することで、独自のオリジンに Geolocation API の使用を許可し、サードパーティのコンテンツによるアクセスを防ぐことができます。
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 を使用できるようにする属性です。また、allowpaymentrequest
属性と allowusermedia
属性もあり、それぞれ Payment Request API を許可し、getUserMedia()
を許可しています。
可能であれば、これらの古い属性ではなく 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",
...
- chromestatus.com で、Blink で実装済みまたは検討中のポリシーを確認します。
これらのポリシーの使用方法については、仕様の GitHub リポジトリをご覧ください。いくつかのポリシーについて解説します。
よくある質問
機能ポリシーを使用する状況
すべてのポリシーはオプトイン方式であるため、適切な状況で機能ポリシーを使用してください。たとえば、画像ギャラリーのアプリの場合、maximum-downscaling-image
ポリシーにより、モバイルのビューポートに巨大な画像が送信されないようにできます。
document-write
や sync-xhr
などの他のポリシーは慎重に使用してください。オンにすると、広告などのサードパーティのコンテンツが破損する場合があります。一方、機能ポリシーは、ページでこうした悪質な API が使用されないようにするための大前提となります。
機能ポリシーは開発環境と本番環境のどちらで使用できますか?
両方です。開発中はポリシーを有効にし、本番環境ではポリシーを有効にしておくことをおすすめします。開発中にポリシーを有効にすると 適切な方法で開始できます予期しない回帰を発生前に検出できます。ユーザーに対して特定の UX を保証するには、本番環境でポリシーを有効にします。
サーバーにポリシー違反を報告する方法はありますか?
Reporting API は準備中です。 CSP 違反や非推奨に関するレポートの受信をサイトがオプトインする方法と同様に、機能のポリシー違反に関するレポートを実際に受け取ることができます。
iframe コンテンツの継承ルールを教えてください。
スクリプト(ファーストパーティまたはサードパーティ)は、ブラウジング コンテキストのポリシーを継承します。つまり、最上位のスクリプトはメイン ドキュメントのポリシーを継承します。
iframe
は親ページのポリシーを継承します。iframe
に allow
属性が指定されている場合は、親ページと allow
リストの間にある、より厳格なポリシーが優先されます。iframe
の使用方法については、iframe の allow
属性をご覧ください。
ポリシーを適用すると、ページ ナビゲーション全体で適用されますか?
いいえ。ポリシーの存続期間は 1 つのページ ナビゲーション レスポンスです。ユーザーが新しいページに移動した場合、ポリシーが適用されるには、新しいレスポンスで Feature-Policy
ヘッダーを明示的に送信する必要があります。
機能ポリシーに対応しているブラウザを教えてください。
ブラウザ サポートの最新情報については、caniuse.com をご覧ください。
現時点では、機能ポリシーに対応しているブラウザは Chrome のみとなっています。ただし、API サーフェス全体がオプトインまたは機能検出が可能なため、機能ポリシーによって段階的な機能強化が実現します。
おわりに
機能ポリシーは、UX とパフォーマンスの向上に向けた明るい道筋を示すのに役立ちます。フットガンの可能性をコードベースに侵入する前に回避できるため、アプリの開発やメンテナンスで特に便利です。
参考情報:
- 機能ポリシーの説明
- 機能ポリシーの仕様
- キッチンシンクのデモ
- 機能ポリシー DevTools 拡張機能 - ページの機能ポリシーを試すテスター。
- chromestatus.com のエントリ