1. 導入
この節は非規範的である。
重要な要素が画面に表示されるタイミングを知ることは、ページ読み込み性能を理解する鍵となる。 主要なコンポーネントの高速なレンダリングだけでは満足のいく読み込み体験には不十分だが、それは 必要である。 したがって、これらのレンダリング時刻印を監視することは、ページ読み込みの改善およびリグレッションの防止に重要である。
この仕様は、開発者および分析プロバイダーに、重要な要素のレンダリング時刻印を測定するためのAPIを提供する。 現在、実ユーザーについてこれらの時刻印を測定する良い方法はない。 既存の手法では、オブザーバーを非常に早い段階で登録するか、大きなDOM操作が必要となる。 これらの手法については、§ 4 セキュリティおよびプライバシーに関する考慮事項の節で説明する。
ウェブ開発者は、自身のサイトにおける重要なユーザー操作の専門家であるため、 関心のある要素がどれであるかをユーザーエージェントに伝えられるべきである。 したがって、このAPIは、ウェブ開発者により注釈付けされた要素についてのレンダリングタイミング情報を公開する。
1.1. 公開される要素
Element Timing APIは、timing-eligible 要素についてのタイミング情報をサポートする。これは[PAINT-TIMING]により定義される。
"elementtiming"コンテンツ属性を持つ要素は、画像
要素タイミングを報告するおよびテキスト要素タイミングを報告するアルゴリズムで報告される。
1.2. 使用例
次の例は、elementtiming属性を通じて観測対象として登録された画像と、タイミング情報を収集するオブザーバーを示す。
< img... elementtiming = 'foobar' /> < p elementtiming = 'important-paragraph' > これは私が関心を持つテキストである。</ p > ...< script > const observer= new PerformanceObserver(( list) => { let perfEntries= list. getEntries(); // それらを反復してエントリーを処理する。 }); observer. observe({ type: 'element' , buffered: true }); </ script >
以下は、このAPIを使用してレンダリング時刻印を測定でき、ページナビゲーションと比較されるべき 要素の例である:
-
ショッピングサイトの画像カルーセル内の画像。
-
ニュースサイトの記事内のメイン写真。
-
ブログ記事のタイトル。
-
百科事典サイトの項目内の最初の段落。
このAPIには、レンダリング時刻印を入力時刻印と比較することにより、ページ読み込み以外のユースケースもあり得る。 たとえば、開発者は、クリックにより起動されたウィジェットが表示されるまでにかかる時間を監視できる。
2. Element Timing
Element Timingには、次の新しいインターフェイスが含まれる:
2.1.
PerformanceElementTiming
インターフェイス
[Exposed =Window ]interface :PerformanceElementTiming PerformanceEntry {readonly attribute DOMHighResTimeStamp ;renderTime readonly attribute DOMHighResTimeStamp ;loadTime readonly attribute DOMRectReadOnly ;intersectionRect readonly attribute DOMString ;identifier readonly attribute unsigned long ;naturalWidth readonly attribute unsigned long ;naturalHeight readonly attribute DOMString ;id readonly attribute Element ?;element readonly attribute USVString ; [url Default ]object (); };toJSON PerformanceElementTiming includes PaintTimingMixin ;
PerformanceElementTiming
オブジェクトは、1つの関連付けられた要素についてのタイミング情報を報告する。
各PerformanceElementTiming
オブジェクトは次の関連概念を持ち、それらはすべて初期値としてに設定される:
PerformanceElementTiming
の関連概念および一部の属性は、§ 3.3 画像要素タイミングを報告するおよび§
3.4 テキスト要素タイミングを報告するの処理モデルで指定される。
entryType
属性の取得子は、DOMString
を返さなければならない。
name
属性の取得子は、初期化された値を返さなければならない。
startTime
属性の取得子は、0でない場合はthisのrenderTime
の値を返し、そうでなければthisのloadTime
の値を返さなければならない。
duration
属性の取得子は0を返さなければならない。
renderTime
属性の取得子手順は、thisのpaint timing情報を与えて、既定のpaint時刻印を返すことである。
loadTime
属性の取得子は、初期化された値を返さなければならない。
intersectionRect
属性は、初期化された値を返さなければならない。
identifier
属性の取得子は、初期化された値を返さなければならない。
naturalWidth
属性は、初期化された値を返さなければならない。
naturalHeight
属性は、初期化された値を返さなければならない。
id
属性の取得子は、初期化された値を返さなければならない。
element
属性の取得子は、次の手順を実行しなければならない:
-
thisの要素が、nullを与えてpaint timing用に公開されるものでない場合、nullを返す。
注: これは、Documentの子孫でなくなった要素は、
element
属性取得子により返されなくなることを意味する。
url
属性の取得子は、次の手順を実行しなければならない:
注: URLは、エントリー内で過剰なメモリを避けるため、 data URLについて切り詰められる。
3. 処理モデル
注: Element Timing APIを実装するユーザーエージェントは、
Window
コンテキスト用のsupportedEntryTypesにを含める必要がある。
これにより、開発者はelement timingのサポートを検出できる。
3.1. DOM仕様への修正
この節は、[DOM]仕様が修正されると削除される予定である。
次のようにElement
インターフェイスを拡張する:
partial interface Element { [CEReactions ,Reflect ]attribute DOMString ; };elementTiming
3.2. Element Timingを報告する
Document
doc、[/=paint timing情報=] paintTimingInfo、保留中の画像レコードpaintedImagesの順序付き集合、および要素paintedTextNodesの順序付き
集合が与えられて、element
timingを報告するよう求められたとき、次の手順を実行する:
-
paintedImages内の各recordについて:
-
record、paintTimingInfo、およびdocを渡して、画像要素タイミングを報告するアルゴリズムを実行する。
-
-
paintedTextNodes内の各
Elementelementについて:-
element、paintTimingInfo、およびdocが与えられて、 テキスト要素タイミングを報告するを実行する。
-
3.3. 画像要素タイミングを報告する
Document
documentが与えられて、画像要素タイミングを報告するよう求められたとき、次の手順を実行する:
-
recordの要素の"
elementtiming"コンテンツ属性が存在しない場合、これらの手順を中止する。 -
intersectionRectを、recordの要素を対象、viewportをrootとして使用するintersection rectアルゴリズムにより返される値とする。
-
documentの関連するrealmで、 paint timing情報が paintTimingInfoである
PerformanceElementTimingオブジェクトentryを作成して初期化する。-
entryの
intersectionRectをintersectionRectに初期化する。 -
entryの
identifierをrecordの要素の"elementtiming"コンテンツ属性に初期化する。 -
entryの
naturalWidthおよびnaturalHeightを、imgのnaturalWidthおよびnaturalHeight属性取得子と同じ手順を実行するが、recordのリクエストを画像として使用することにより初期化する。
-
entryであるPerformanceEntryをキューに入れる。
3.4. テキスト要素タイミングを報告する
Element
element、paint timing情報paintTimingInfo、およびDocument
documentが与えられて、テキスト要素タイミングを報告するよう求められたとき、次の手順を実行する:
-
elementの"
elementtiming"コンテンツ属性が 存在しない場合、これらの手順を中止する。 -
intersectionRectを空の矩形とする。
-
elementの所有テキストノード集合内の各
Textノードtextについて:-
intersectionRectを、textのborder boxとintersectionRectを含む最小の矩形になるように拡張する。
-
-
intersectionRectをvisual viewportと交差させる。
-
documentの関連するrealmで、 paint timing情報が paintTimingInfoである
PerformanceElementTimingオブジェクトentryを作成して初期化する。-
entryの要素をelementに初期化する。
-
entryの
loadTimeを0に初期化する。 -
entryの
intersectionRectをintersectionRectに初期化する。 -
entryの
identifierをelementの"elementtiming"コンテンツ 属性に初期化する。 -
entryの
naturalWidthおよびnaturalHeightを0に初期化する。 -
entryの
idをelementの"id"コンテンツ属性に初期化する。
-
-
entryであるPerformanceEntryをキューに入れる。
4. セキュリティおよびプライバシーに関する考慮事項
このAPIは、クロスオリジン画像についての一部の情報を公開する。 特に、画像はリソース読み込み時刻を公開するため、プライバシー上の懸念の原因となり得る。
しかし、これはResourceTiming APIがすでに同様の時刻印を公開しているため、ウェブプラットフォームに新しい攻撃を追加するものではないと考えられる。
さらに、onloadハンドラーは、利用可能な場合に読み込みタイミングを公開し、リソース読み込み時刻はこれに近い代理値である。
onloadハンドラーの開始時に計算される現在の高解像度時刻は、画像読み込み時刻を提供する。
loadTime
はonloadハンドラーなしでも非常に容易に取得できるため、これを公開することを選択する。
さらに、画像onloadハンドラーまたはResourceTimingにより提供される漏えいを取り除く修正は、
このAPIにより提供される漏えいも修正できると考える。
renderTime
(表示時刻印)は、確かに新たに公開される情報である。実装には、クロスオリジン画像間のデコード時間の差を公開することを避けるため、
少なくとも4ミリ秒の解像度まで、この時刻印をさらに粗くすることが推奨される。`Timing-Allow-Origin`などの他の検査は、
同一オリジン画像とクロスオリジン画像が同時にレンダリングされるため、ここでは機能しないことに注意する。
粗いrenderTime
を公開することは、画像の自然サイズ
および読み込み時間が他の方法で公開されていることを考えると、いずれにせよ実質的な攻撃ベクターではない。
// 攻撃者フレーム内。< iframe src = attack.html ></ iframe > < script > window. onmessage= e=> { let timestamp= e. data; // 'victim.jpg' の表示時刻印を取得した! } </ script > // attack.html iframe内。< img src = 'victim.jpg' /> < script > // PaintTimingエントリーが見えるようになるonloadまたは何らかの時点まで待つ。 onload() => { let entry= performance. getEntriesByType( 'paint' )[ 0 ]; top. postMessage( entry. startTime, '*' ); } </ script >
ここで公開されるもう1つの重要なパラメーターはintersectionRectである。
これは、たとえばIntersectionObserverを使用して、すでにpolyfill可能である。
polyfillプロセスも同様である。対象の画像またはテキストコンテンツのonloadハンドラー上にIntersectionObserver
を追加する。
この解決策は、コンテンツが読み込まれた後にオブザーバーを登録する必要があるため非効率だが、
それでも同じ精度レベルを提供するはずである。
画像が完全に表示されるまでrectのみを計算するなら、その時点の後にのみエントリーを公開できることになる。
画像のレンダリング時刻印を公開したくない場合は、エントリーを
PerformanceObserver
に直ちに送出することが望ましい。
element
timingを報告するアルゴリズム中に、待機してすべてのエントリーを公開すると仮定する。
攻撃者は、画像のレンダリング時刻印について重要な情報を推測できる。
その画像についてのタイミングのみを観測することでそうできる。
たとえ受け取ったPerformanceElementTiming
エントリーのメンバーとして時刻印が公開されないとしても、
次のレンダリングを更新する手順まで待つという事実により、攻撃者はエントリーを受け取った時刻を測定することで、
非常に遅いレンダリング時間と非常に速いレンダリング時間を区別できる。
これは意図せず画像の表示タイミングの一部を漏えいさせることになる。