Updating an existing scroll animation can succeed without the new scroll being performed/ |
|||||||
Issue descriptionI've tracked down an unexpected behaviour in LayerTreeHostImpl::ScrollAnimated() in which a new scroll delta being added to a current animation via ScrollAnimationUpdateTarget() may never get scrolled. This seems to happen when the animation has performed it's final update (before the arrival of the new delta), but has not yet been handled by ScrollOffsetAnimationsImpl::NotifyAnimationFinished(). ScrollAnimationUpdateTarget() returns 'true', which suggests the update of the animation's target was successful, i.e. the new delta has been added to the animation target. The repro case is to run SitePerProcessBrowserTest.ScrollBubblingFromOOPIFTest a number of times ... it's flakey. When the test fails, it's because a new MouseWheel scroll hits an existing scroll animation, but the test times out waiting for the new delta to be applied, which never happens. Application of the scroll is detected in the test when the browser process receives an IPC for frameRectsChanged, which is triggered by LayerTreeHost::ApplyScrollAndScale(). Since there is no way for a BrowserTest to track the completion of a scroll animation, it makes it difficult to test scrolling for OOPIFs without encountering this kind of flake. Assigning to flackr@ for triage. I'm happy to demonstrate the issue if that helps. Please adjust the 'component' if I've chosen the wrong one.
,
Apr 12 2017
+ajuma@ and loyso@ who own animations in CC. Presumably, fixing ScrollAnimationUpdateTarget to revive a "finished" animation or return false wouldn't really help right? Since we're already trying to "update existing" in the ScrollAnimated/ScrollAnimatedBegin methods. The test is hoping to bubble which requires us to be in the "targetting" part of those methods so we really need to wait until the CurrentlyScrollingNode is cleared. That happens in LayerTreeHostImpl::ScrollOffsetAnimationFinished so maybe we could make that happen sooner? Alternatively, ScrollAnimationUpdateTarget could return failure if the animation is already finished and the calling code could then clear it and start a new one.
,
Apr 13 2017
Does ScrollAnimationUpdateTarget() actually fail to apply the delta to the currently-scrolling node (i.e. this is a real bug outside of test code)? Or is it just that the test expected chaining to a different node, and is using scroll-offset polling as a flaky proxy for animation completion? The loops in that test look pretty hacky. I wonder if we can plumb an animation completion signal through the RenderFrameProxy. Alternatively the test could skip the smooth scrolling paths by setting has_precise_scrolling_deltas on the WebMouseWheelEvent.
,
Apr 13 2017
,
Apr 13 2017
skobes@ - Thanks for the tip about has_precise_scrolling_deltas ... I didn't realize that could be used to skip the animation pathways. I'm going to use that, in the short term at least, to get this test back online. I believe that ScrollAnimationUpdateTarget() actually fails to apply the delta. Now, because of the small deltas from the test resulting in animations with a single step, it may be that this doesn't reproduce as easily in the real world. Also, in the real world it's probably quite unnoticeable if the occasional scroll wheel delta gets dropped, and so the bug hasn't resulted in any reports (beyond this one). Finally, I would agree it would be useful to plumb an animation completion signal, as otherwise any browser test at present has no way to synchronize, making it difficult (or impossible) to write a browser test for scroll animation that won't be potentially flakey.
,
Apr 13 2017
I should add, for example, that the current bug I've been fixing with OOPIF scroll bubbling has been due to the logic in the animation path, so having a browser test that does use the animation path is important.
,
Apr 13 2017
SitePerProcessBrowserTest.ScrollBubblingFromOOPIFTest is extremely flaky on this CQ bot: https://build.chromium.org/p/tryserver.chromium.linux/builders/linux_chromium_chromeos_rel_ng Could you please disable it until this is fixed?
,
Apr 13 2017
flackr@, feel free to reassign if you know a better owner.
,
Apr 13 2017
re #7 ... the CL to re-enable the test should have waited until another CL (to fix the DCHECK issue) landed ... I've reverted it.
,
Apr 25 2017
I spent a bit more time investigating this, and here's what I've found: The problem seems to be that, when the test happens to hit ScrollAnimationUpdateTarget, it adds a delta so small that the animation curve assigns it a zero duration. Since the existing animation is already at its end, the next call to AnimationPlayer::MarkFinishedAnimations() sets the run state on the animation to 'finished', and the animation is deleted even though it has unconsumed scroll delta. Some of the points of interest in the code: 1) MarkFinishedAnimations() calls Animation::IsFinishedAt(), which (in the case of our test) indicates the animation is finished based on the value returned by curve_->Duration(). 2) In ScrollOffsetAnimationCurve::UpdateTarget() our test hits the branch if ((total_animation_duration_ - last_retarget_).is_zero()) and sets total_animation_duration_ to zero, since the new delta is very small. 3) ScrollOffsetAnimationCurve::UpdateTarget() is called from ScrollOffsetAnimationsImpl::ScrollAnimationUpdateTarget(). Since UpdateTarget() doesn't return any sort of status, the caller has no idea the duration is zero (or at least doesn't attempt to check). ScrollAnimationUpdateTarget() exits from the final return statement, which is always true, even though (in our case) the curve duration is zero. I don't know that the proper way to fix this is, but it seems wrong to consider the update successful when both (i) the curve duration hasn't changed, and (ii) the animation is terminating based solely on its duration, even when the curve has unconsumed scroll delta. I've uploaded an *experimental* cl at: https://codereview.chromium.org/2840883003 This is *not* meant to be a fix for the problem, but rather shows that if we detect the lack of change in the curve duration and use it to return false, and then use that in turn to force creation of a new animation, the test at least completes successfully.
,
May 16 2017
That's interesting. When SOAI::ScrollAnimationUpdateTarget runs, is the animation already marked finished? If so, we should probably return false without touching it (just as if there were no animation). If not, then there's something funny about the ordering of input and animation updates.
,
Jun 8 2017
,
Nov 3 2017
I'm guessing this isn't P1, as this bug hasn't seen recent activity. Dropping to P2. sunyunjia@, please upgrade priority if this is something we want to get done soon. Thanks!
,
Feb 7 2018
|
|||||||
►
Sign in to add a comment |
|||||||
Comment 1 by lfg@chromium.org
, Apr 11 2017