フェンス付きフレームの概要

クロスサイト データを共有することなく、コンテンツをページに安全に埋め込むことができます。

実装ステータス

フェンス付きフレームが必要な理由

フェンス付きフレーム(<fencedframe>)は iframe と同様に、埋め込み コンテンツ用の HTML 要素です。iframe とは異なり、フェンス付きフレームは埋め込みコンテキストとの通信を制限し、埋め込みコンテキストと共有することなく、フレームがクロスサイト データにアクセスできるようにします。一部のプライバシー サンドボックス API では、フェンス付きフレーム内で特定のドキュメントをレンダリングする必要があります

同様に、埋め込みコンテキスト内のファーストパーティ データは、フェンス付きフレームと共有できません。

たとえば、news.example(埋め込みコンテキスト)が shoes.example の広告をフェンス付きフレームに埋め込む場合、news.exampleshoes.example の広告からデータを抽出できません。また、shoes.examplenews.example からファーストパーティ データを取得できません。

ストレージ パーティショニングでクロスサイト プライバシーを強化する

ウェブを閲覧しているときに、あるサイトで見た商品が、まったく別のサイトの広告に表示されたことがあるかもしれません。

現在、この広告手法は主に、サードパーティ Cookie を使用してサイト間で情報を共有するトラッキング技術によって実現されています。

Chrome は、サイトごとにブラウザ ストレージを分離するストレージ パーティショニングに取り組んでいます。パーティショニングを行わない場合、shoes.example の iframe が news.example に埋め込まれ、その iframe がストレージに値を保存すると、その値は shoes.example サイトから読み取ることができます。ストレージがパーティション分割されると、クロスサイト iframe はストレージを共有しなくなるため、shoes.example は iframe によって保存された情報にアクセスできなくなります。iframe が *.shoes.example から配信され、*.shoes.example に埋め込まれている場合、これらは 同じサイトと見なされるため、ブラウザ ストレージは共有されます。

ストレージ パーティショニングの変更前後の状態の比較。

ストレージ パーティショニングは、LocalStorage、IndexedDB、Cookie などの標準ストレージ API に適用されます。パーティション分割された環境では、ファーストパーティ ストレージ間の情報漏洩が大幅に削減されます。

クロスサイト データを操作する

フェンス付きフレームは、プライバシー サンドボックス機能 であり、トップレベル サイトがデータをパーティション分割することを推奨します。多くのプライバシー サンドボックスの提案と API は、サードパーティ Cookie や他のトラッキング メカニズムを使用せずに、複数のサイトにまたがるユースケースに対応することを目的としています。次に例を示します。

  • Protected Audience API を使用すると、インタレスト ベースの広告を プライバシーを保護しながら配信できます。
  • Shared Storage を使用すると、 安全な環境でパーティション分割されていないクロスサイト データにアクセスできます。

フェンス付きフレームは、Protected Audience API と連携するように設計されています。Protected Audience API では、ユーザーの興味関心 は、ユーザーが関心を持つ可能性のある広告とともに、広告主のサイトでインタレスト グループに登録されます。その後、別のサイト(「パブリッシャー」と呼ばれる)で、関連するインタレスト グループに登録された広告がオークションにかけられ、落札した広告がフェンス付きフレームに表示されます。

パブリッシャーが落札した広告を iframe に表示し、スクリプトが iframe の src 属性を読み取れる場合、パブリッシャーはその広告の URL から訪問者の興味関心に関する情報を推測できます。これはプライバシーの保護にはなりません。

フェンス付きフレームを使用すると、パブリッシャーは訪問者の興味関心に一致する広告を表示できますが、src とインタレスト グループはフレーム内の広告主のみが知ることができます。パブリッシャーはこの情報にアクセスできません。

フェンス付きフレームの仕組み

フェンス付きフレームは、ナビゲーションに FencedFrameConfig オブジェクトを使用します。このオブジェクトは、Protected Audience API オークションまたは Shared Storage の URL 選択オペレーションから返されます。次に、構成オブジェクトはフェンス付きフレーム要素の config 属性として設定されます。これは、URL または不透明な URNsrc 属性に割り当てられる iframe とは異なります。FencedFrameConfig オブジェクトには読み取り専用の url プロパティがありますが、現在のユースケースでは内部リソースの実際の URL を非表示にする必要があるため、このプロパティは読み取られると文字列 opaque を返します。

フェンス付きフレームは、postMessage を使用して埋め込み元と通信できません。ただし、フェンス付きフレーム内の iframe で postMessage を使用することはできます。

フェンス付きフレームは、他の方法でもパブリッシャーから分離されます。たとえば、パブリッシャーはフェンス付きフレーム内の DOM にアクセスできません。また、フェンス付きフレームはパブリッシャーの DOM にアクセスできません。さらに、name などの属性は、任意の値に設定してパブリッシャーが確認できますが、フェンス付きフレームでは使用できません。

フェンス付きフレームは、トップレベルのブラウジング コンテキスト (ブラウザタブなど)のように動作します。特定のユースケース(インタレスト ベースのリターゲティング広告など)では、フェンス付きフレームにクロスサイト データ(Protected Audience API インタレスト グループなど)を含めることができますが、フレームはパーティション分割されていないストレージや Cookie にアクセスできません。フェンス付きフレームは、一意の nonce ベースの Cookie とストレージ パーティションにアクセスできます。

フェンス付きフレームの特性について詳しくは、 解説をご覧ください。

フェンス付きフレームと iframe の違い

フェンス付きフレームでできることとできないことがわかったので、既存の iframe 機能と比較してみましょう。

機能 iframe fencedframe
コンテンツの埋め込み はい はい
埋め込みコンテンツが埋め込みコンテキストの DOM にアクセスできる はい いいえ
埋め込みコンテキストが埋め込みコンテンツの DOM にアクセスできる はい いいえ
監視可能な属性(name など) はい いいえ
URL(http://example.com はい はい(ユースケースによる
ブラウザ管理の不透明なソース(urn:uuid いいえ はい(ユースケースによる)
クロスサイト データへのアクセス いいえ はい(ユースケースによる)

フェンス付きフレームは、プライバシーを保護するために、外部通信オプションの数を減らしています。

フェンス付きフレームは iframe に置き換わるのですか?

最終的に、フェンス付きフレームは iframe に置き換わることはなく、使用する必要はありません。 フェンス付きフレームは、異なるトップレベル パーティションのデータを同じページに表示する必要がある場合に使用する、よりプライベートなフレームです。

同じサイトの iframe(フレンドリー iframe とも呼ばれます)は、信頼できるコンテンツと見なされます。

フェンス付きフレームを使用する

フェンス付きフレームは、他のプライバシー サンドボックス API と組み合わせて、1 つのページ内に異なるストレージ パーティションのドキュメントを表示します。 候補となる API については現在検討中です。

この組み合わせの現在の候補は次のとおりです。

詳しくは、フェンス付きフレーム のユースケースの解説をご覧ください。

フェンス付きフレームの config オブジェクトを取得するには、Protected Audience API の runAdAuction() 呼び出しまたは Shared Storage の selectURL() 呼び出しに resolveToConfig: true を渡す必要があります。プロパティが追加されていない場合(または false に設定されている場合)、結果の Promise は iframe でのみ使用できる URN に解決されます。

Protected Audience API オークションからフェンス付きフレームの構成を取得する
const frameConfig = await navigator.runAdAuction({
  // ...auction configuration
  resolveToConfig: true
});
Shared Storage URL 選択からフェンス付きフレームの構成を取得する
const frameConfig = await sharedStorage.selectURL('operation-name', {
  resolveToConfig: true
});

構成を取得したら、フェンス付きフレームの config 属性に割り当てて、フレームを構成で表されるリソースに移動できます。以前のバージョンの Chrome では resolveToConfig プロパティがサポートされていないため、移動する前に Promise が FencedFrameConfig に解決されたことを確認する必要があります。

構成をフェンス付きフレーム属性に設定する
if (window.FencedFrameConfig && frameConfig instanceof FencedFrameConfig) {
  const frame = document.createElement('fencedframe');
  frame.config = frameConfig;
}

詳しくは、フェンス付きフレームフェンス付きフレームの構成に関する解説をご覧ください。

ヘッダー

ブラウザは、フェンス付きフレームと、フェンス付きフレーム内に埋め込まれた iframe からのリクエストに対して Sec-Fetch-Dest: fencedframe を設定します。

Sec-Fetch-Dest: fencedframe

ドキュメントをフェンス付きフレームに読み込むには、サーバーで Supports-Loading-Mode: fenced-frame レスポンス ヘッダーを設定する必要があります。フェンス付きフレーム内の iframe にもヘッダーが必要です。

Supports-Loading-Mode: fenced-frame

Shared Storage コンテキスト

Private Aggregation を使用して、埋め込み元のコンテキスト データに関連付けられたフェンス付きフレームでイベントレベルのデータをレポートすることがあります。fencedFrameConfig.setSharedStorageContext() メソッドを使用すると、イベント ID などのコンテキスト データを埋め込み元から Protected Audience API によって開始された Shared Storage ワークレットに渡すことができます。

次の例では、埋め込み元ページで使用可能なデータと、フェンス付きフレームで使用可能なデータを Shared Storage に保存します。埋め込み元ページから、モック イベント ID が Shared Storage コンテキストとして設定されます。フェンス付きフレームから、フレーム イベント データが渡されます。

埋め込み元ページから、コンテキスト データを Shared Storage コンテキストとして設定できます。

const frameConfig = await navigator.runAdAuction({ resolveToConfig: true });

// Data from the embedder that you want to pass to the shared storage worklet
frameConfig.setSharedStorageContext('some-event-id');

const frame = document.createElement('fencedframe');
frame.config = frameConfig;

フェンス付きフレームから、フレームのイベントレベルのデータを Shared Storage ワークレットに渡すことができます(上記の埋め込み元のコンテキスト データとは無関係です)。

const frameData = {
  // Data available only inside the fenced frame
}

await window.sharedStorage.worklet.addModule('reporting-worklet.js');

await window.sharedStorage.run('send-report', {
  data: {
    frameData
  },
});

埋め込み元のコンテキスト情報は sharedStorage.context から、フレームのイベントレベルのデータは data オブジェクトから読み取り、Private Aggregation を介してレポートできます。

class ReportingOperation {
  convertEventIdToBucket(eventId) { ... }
  convertEventPayloadToValue(info) { ... }

  async run(data) {
    // Data from the embedder
    const eventId = sharedStorage.context;

    // Data from the fenced frame
    const eventPayload = data.frameData;

    privateAggregation.contributeToHistogram({
      bucket: convertEventIdToBucket(eventId),
      value: convertEventPayloadToValue(eventPayload)
    });
  }
}

register('send-report', ReportingOperation);

フェンス付きフレーム構成オブジェクトの埋め込み元のコンテキストについて詳しくは、解説をご覧ください。

フェンス付きフレームを試す

Chrome フラグを使用して、 Fenced Frame API を chrome://flags/#enable-fenced-frames で有効にします。

Chrome の試験運用版で、Enable the Fenced frame element という名前のフラグを有効に設定します。

ダイアログには複数の選択肢があります。 *Enable* を選択することを強くおすすめします。これにより、新しいアーキテクチャが利用可能になると、Chrome が自動的に更新されます。

その他のオプション(Enabled with ShadowDOMEnabled with multiple page architecture )は、ブラウザ エンジニアにのみ関連するさまざまな実装戦略を提供します。現在、EnableEnabled with ShadowDOM と同じように動作します。今後、EnableEnable with multiple page architecture にマッピングされます。

機能検出

フェンス付きフレームが定義されているかどうかを確認するには:

if (window.HTMLFencedFrameElement) {
  // The fenced frame element is defined
}

フェンス付きフレームの構成が利用可能かどうかを確認するには:

if (window.FencedFrameConfig && frameConfig instanceof FencedFrameConfig) {
   // The fenced frame config is available
}

ブラウザ サポート

意見交換とフィードバックの提供

フェンス付きフレームは現在検討中で、今後変更される可能性があります。この API を試してフィードバックがございましたら、ぜひお聞かせください。

詳細