Participants
Alex Christensen, Philippe Le Hegaret, Nicolás Peña, Marcus Armstrong, Benjamin De Kosnik, Nic Jansma, Annie Sullivan, Andrew Comminos, Philip Walton, Ilya Grigorik, Yoav Weiss, Ryosuke Niwa, Nate Schloss
Admin
Next call
- Shifting to Thursday @ 10AM PST, bi-weekly cadence
- Next call is on January 30th, 10AM PST
WebPerf F2F
- April 2nd+3rd in Bay area
- Day 1: ~50~60 expected people
- Day 2: ~25~30 core WG group
- AI: Followup w/ Andrew & Nic on space logistics
WebPerf WG Charter 2020
- WebPerf charter expires in June 2020
- We'll need to re-charter by then
- April F2F can help guide our priorities for the new charter
Largest Contentful Paint
- Annie: Currently: LCP ignores elements that have been removed from the DOM (e.g. from splash-elements)
- Annie: However this may affect carousels which often rotate through images and remove old ones -- LCP would be for the "last" image in the carousel if it's rotating automatically
- Annie: Other places where this breaks down is for header placeholders -- this seems OK as you'd want to wait for the "final" header to pop in to declare LCP
- Annie: Chrome will test implementing both algorithms (with and without element removal), to see where there are dramatic differences and figure out which is best. This will just be an internal tracking metric, not as part of RUM LCP timing.
- Annie: Do people prefer to have simpler algorithm for calculating LCP or something that is still work in all edge cases, i.e. splash screens/carousels/etc
- Nic, Alex, others: Lean towards a simpler API that can be explained cleanly. Advanced users / people needing something different can use ElementTiming.
- Ryosuke: Concerns around performance overhead of tracking all elements
- Nicolás: Currently shipped in Chrome, and removing the element-removal-logic might make it less expensive (because you no longer have to keep a log of all previous largest-paints in case an element is later removed)
- Ilya: Timeline for outcome of experiment?
- Annie: ~2 months to get feedback
- Ilya: Circle-back around end of March (F2F?)
isInputPending
Presentation
https://www.chromestatus.com/feature/5719830432841728
https://bugs.chromium.org/p/chromium/issues/detail?id=930987
- Andrew: ran an Origin Trial and confirmed our hypothesis that this is helpful and presented at TPAC
- ...: Spec changes from feedback post-TPAC
- ...: Avoid filtering using DOM event types -- hard to spec, and not performant, so moving away from that in favor of a continous/discrete dichotomy
- ...: Original API took in a list of strings to match each call, but when the browser had to do a lot of string matches -- for a API that can be called in quick succession, this isn't optimal. On top of that, the API used to be stateless, but the UA can benefit from knowing ahead of time is inInputPending will be called. So added an options object, that when it’s allocated, that can be used as a signal to the browser that isInputPending will soon be called and that it should warm up its prediction logic.
- ...: Needed to prove viability of adhering to same-origin policy. Have a prototype in Chromium that’s based on compositor hit testing. Expect it not to introduce any kind of new click-jacking attack vectors. Same as existing renderer-based delegation.
- Ryosuke: When you say SOP, who’s deciding which element gets the event?
- Andrew: The hit testing logic for isInputPending has to run off main thread logic, by definition. This is tricky because the hit-testing for event dispatch is done on the main thread. We suggested that UAs will perform this based on the last frame displayed to the user. Can perform origin level attribution per frame, so a frame from a different origin doesn’t mistakenly receive events.
- Ryosuke: That solves one problem but creates another. What happens if things have moved between the two hit testing occurances?
- Nicolás: Yeah, the frame that receives the inInputPending information is not guaranteed to be the same frame as the one that ends up handling the event?
- Andrew: It is not. What we did is based on last frame presented to the user, which is not well-defined in spec. But event targeting in general is suffering from very similar issues.
- …: Imagine a site that blocks the main thread and moves frames around. The user may click on something, but the event may get dispatched to another frame than the one they thought
- Nicolás: What’s “last frame presented to user”?
- Andrew: We did hit testing based on browsing context. Those browsing contexts group event by origins. So if you have multiple frames from the same origin, isInputPending would return true for an event that occured in any one of them. So we can the scheduling properties that we want, and yield for anything that needs our main thread.
- Yoav: That hit testing, regardless of isInputPending, that logic runs in the browser process? Top level renderer?
- Andrew: In Chrome in the OT, we ran this in the browser process which only has partial knowledge of origins in browsing contexts. We now moved this to the renderer as well, so it’d work for Android and other situations where you have multiple same-site cross-origin frames in the same process.
- Ryosuke: the discrepancy is an issue. We will not be comfortable implementing what you are proposing here, without solving the problem that it’s be sent to the wrong frame.
- Andrew: Are you not suffering from this problem already with event dispatch? The main frame can block the main thread after rendering a frame, shuffle iframes around and cause events to be triggered on the wrong frame. It’s already a know clickjacking attack vector
- … Mitigations for this in Chromium include blocking event dispatch after frames have moved around, for a brief period of time
- Nicolás: this case seems more problematic. With clickjacking the frame actually gets the event, but here we’d be reading events that are sent to a cross-origin frame. Will this also happen from an iframe?
- Andrew: This will only happen when you have multiple nested browsing contexts per page. The attack I can imagine is when you click on a cross-origin iframe and move it away programatically. So from the time the event is dispatched to a post-layout time when the task is run, it’s no longer hitting where the user thought they are clicking. So you might think that you’re getting events that you don’t.
- Nicolás: so if the iframe doesn’t move, the hit testing is correct?
- Andrew: yeah. The only concerns is those rare edge cases where iframes are moved
- Ryosuke: Could also be a result of scrolling?
- Andrew: Not for compositor-side scrolling
- Ryosuke: In Chrome, but not other engines. This is problematic. Just because there’s a current browser bug where this is an existing issue, doesn’t mean we can make it work. This proposal introduces a new security sensitive surface. So that needs to be carefully studied. What you’re currently proposing is not something we’d be comfortable implementing.
- Andrew: There are possible mitigations. For sync scrolling, a scroll event that forced a frame to move won’t cause misattribution, because the main thread was blocked so the frame hasn’t yet moved. Can you walk me through an example?
- Ryosuke: between the time the event was initiated and dispatched, scrolling may have happened, in WebKit’s case the UI process. Whatever iframe was there when the event was initiated may have moved by the time it was dispatched in the WebContents process.
- Andrew: So user scrolls and clicks, the frame doesn’t update but the scroll process is, and it clicks on a different origin iframe. The parent of the iframe will receive an inInputPending call from that that would be incorrect, and will leak a cross-origin click.
- Ryosuke: iframe could also incorrectly receive that information. The bigger issue here is that all this is very fuzzily defined in spec. Need to come up with model for how hit-testing works and what security mitigations are needed. Not OK to have a spec while saying “there are possible mitigations”. Need to clearly understand what mitigations need to be done, and what the security risk is.
- Andrew: We wrote about it in the explainer. Most of the privacy and security section is discussing this: https://github.com/WICG/is-input-pending#privacy-and-security
- … Need to think what actual attacks are possible with this, beyond philosophical SOP concerns. Maybe key events? But not likely since those are dispatched based on focus and not hit-testing.
- Ryosuke: very unlikely is not good enough for security. Can’t hope for the best. This new security surface needs to be carefully studied.
- Nicolás: Can talk to Chrome security folks that looked into the API’s security
- ...: AI to share the results of the Chrome security review
- Ryosuke: Just because Chrome security thinks it’s OK doesn’t mean we would.
- Yoav: A first good step would be to render the security discussion public, and then get Apple and Mozila to review and see if given your browser architecture, that result makes sense.
- Ryosuke: Not acceptable for the information to be different between isInputPending and event dispatch
- Andrew: That’s not going to be possible
- Ryosuke: then maybe it’s not implementable. Without this guaranty we cannot implement
- Yoav: Andrew - can you elaborate on why it won’t be possible?
- Andrew: hit testing off-main-thread an on-main-thread can disagree due to queued tasks on the main thread. isInputPending is doing hit testing based on what the user sees, which seems more accurate
- Nicolás: the browser has to send these events at some point, there must be a point in the browser process in which it knows which renderer to send it to
- Andrew: site isolation in Chrome suffers from the same issue and does sync hit-testing for edge cases
- Yoav: I agree with your statement that hit-testing for isInputPending is more accurate than hit testing done later on. But I’d expect the browser to not dispatch anything in case where those are different. We should dispatch the event to a frame that when the user didn’t intended for it to happen.
- Ryosuke: In that scenario, you wouldn’t re-disptach events from one renderer to another. That would never happen. So why isn’t that always the case? Why don’t we make an early decision and lock the event to that frame?
- Andrew: Locking?
- Nicolás: Run the event in the frame we originally thought it should go to
- Yoav: basically run hit testing once and then dispatch both isInputPending and the event based on that one result, that happened at a single point in time, instead of having it be racy.
- Andrew: Not sure how that’s different from what I described. We do lock to a frame
- Nicolás: yeah, but isInputPending can be assigned to the wrong frame. We’re trying to avoid leaking cross-origin information here.
- Andrew: You won’t know that the target frame has changed until you spin the main thread.
- Yoav: Yeah, but why would we change the target?
- Andrew: Because of a task that was queued on the main thread
- Ryosuke: Frames don’t move from one process to another. Why don’t we just stick to the process which we decided earlier, regardless of tasks that ran in the meantime.
- Nicolás: Could also drop the event to the floor if the target changed. Both options seem like a solution to this problem.
- Andrew: As a hacky mitigation, we could suppress the API if frames motion resulted in inconsistency
- Ryosuke: That would be too late
- Andrew: The locking behavior would require a fundamental change to how implementers do event dispatch
- Ryosuke: sure, but may be necessary in order to implement this
- Andrew: OK, useful feedback
- Ryosuke: Request to get feedback from multiple engines, members of other working groups (e.g. HTML, WebApps, CSS) to help us better understand what may work for APIs like this when they require implementation feedback on hit-testing, security issues, etc
- Benjamin: second that
- Yoav: Maybe we can organize a cross-WG call to discuss this.
- Ryosuke: maybe a GH issue can be sufficient
- Andrew: Will file for a TAG review
- Andrew: There were still a few more things to chat about but will follow up next meeting
Next Meeting: Jan 30 2020 at 10am PST