Cross-origin IFRAME opting-in to sharing ResourceTiming data
Nobody has claimed this yet.
- Dominant language
- Bikeshed
- Stars
- 135
- Forks
- 40
- PR merge metrics
- No merged PRs in 30d
Description
I'd like to propose a way for cross-origin IFRAMEs to share their ResourceTiming data with their parent pages, if they choose.
Background
ResourceTiming is one of the cornerstones of RUM, and provides a lot of value to anyone using it. Unfortunately one of the key limitations of ResourceTiming is that not all resources fetched by the page are "visible" to ResourceTiming. There are several reasons for this, but it is primarily due to each frame only reporting on the resources fetched by itself, and not any child IFRAMEs.
One can gather ResourceTiming entries from all children/grandchildren+ IFRAMEs by crawling them (though the ergonomics are not ideal). Both PerformanceTimeline (getEntries()) and PerformanceObserver need to do this crawling.
Unfortunately, due to cross-origin DOM restrictions, one cannot "crawl" into a cross-origin IFRAME to query its frames[n].performance.getEntries() interface. Thus, all content loaded from cross-origin IFRAMEs (and below) are completely hidden to ResourceTiming.
In an analysis I did of ResourceTiming Visibilty, I found that over 30% of all resources fetched by the browser on popular sites are missing from ResourceTiming's crawls, accounting for more than 50% of all bytes downloaded (Page Weight).
This is not ideal, and makes RUM analysis biased, especially compared to browser developer tools and synthetic tests, which report on 100% of all resources. RUM cannot report on Page Weight accurately today.
My guess, based on the common types of content typically loaded from cross-origin IFRAMEs, is that ads and social widgets are likely one of the biggest things completely flying under the radar for ResourceTiming/RUM. I'd really like to be able to shine a better light on both of those third-party components, so we can hold them accountable.
Video content is even worse, with 75% of videos missing from ResourceTiming, 97.3% by byte count.
Cross-origin IFRAMEs are restricted for a reason, as opening access has privacy, security, and probably other concerns. Hoping there's a way to get access to just their fetches, if they opt-in.
We've experimented with a way for third-parties (e.g. ad providers) to bubble up their content via a postMessage() handshake, but it takes JavaScript coordination in both pages to do so.
Proposal
I'd like to figure out if there's a way for content-owners (third-parties that serve content in IFRAMEs) to opt-in to sharing some of their performance data to the base page. We'll need three pieces to make this work:
- Giving content owners a way of opting-in to sharing performance data to the base page
- Figuring out which performance data is shared
- Accessing the shared performance data from the base page
1. Opting-In
For cross-origin resources fetched from the base page, the content owner (e.g. third-party site, CDN, etc) can opt-in to sharing detailed performance data via the TAO HTTP header:
Timing-Allow-Origin: *
I think we could re-use this concept for cross-origin frames. Two options come to mind:
- Re-use the
Timing-Allow-Originheader: IfTiming-Allow-Originis available on a HTML page that is an IFRAME, it has "opted-in" to sharing not only the detailed performance data for that URL itself, but also anything it fetches. This expands the scope of TAO, so I'm not sure it would pass a security review, but would get us a lot more data quicker (the TAO header is on only around 15% of responses today). - Add a new
Timing-Allow-Origin-Resources(or something) header, that would opt the IFRAME into sharing its performance data with the base page.
2. Which Content is Shared?
The most interesting information I personally want from cross-origin IFRAMEs is ResourceTiming data, but I could see it being useful to share UserTiming data as well.
LongTasks already exposes its data to parent frames.
There is probably more performance data that would be useful to "share up", but we could also just scope this to ResourceTiming data for now.
3. Accessing the Shared Performance Data
I'm not sure of the best ergonomics of this. A couple options come to mind:
- If opted-in, the base page could somehow get access to
frames[n].performance, but nothing else on theframes[n].*. Seems like a tough sell. - Provide an interface on the base page to access all IFRAMEs easily, and the browser would "crawl" the IFRAMES, same- and cross-origin-opted-in. Something like
performance.getEntriesByType('resource', { frames: true }). I know there's not much appetite for working on the "old" interfaces though. - If opted-in, a flag could be passed to PerformanceObserver (bubbles!) where any IFRAMEs, same- and cross-origin-opted-in, would report their entries.
The third option would probably get my vote, but it would require bubbles support.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing the ResourceTiming, PerformanceTimeline, and PerformanceObserver entry points described here, along with the linked Performance Timeline bubbles issue. Compare the Timing-Allow-Origin and proposed new-header options, then define the shared data scope, security boundaries, and parent-page access mechanism; the design is done when those three pieces have a resolved specification proposal.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- performance, web-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100