[Webkit-unassigned] [Bug 248303] REGRESSION (iOS 16): popstate events are not fired for swipe-back gesture

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Wed Mar 8 00:06:53 PST 2023


https://bugs.webkit.org/show_bug.cgi?id=248303

Matt Jacobson <mhjacobson at me.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |mhjacobson at me.com

--- Comment #7 from Matt Jacobson <mhjacobson at me.com> ---
Hey Chris and WebKit team,

Thanks for the explanation.  For reference, I believe that the change Chris is describing is <https://bugs.webkit.org/show_bug.cgi?id=241885> (<https://commits.webkit.org/251783@main>), plus follow-up fix in <https://bugs.webkit.org/show_bug.cgi?id=242947> (<https://commits.webkit.org/252649@main>).

Now: in my experimentation on an iPhone SE (2nd edition) running iOS 16.3.1 (20D67), the "is history item added by user interaction" detection is rather unpredictable when using the "touchend" event.  Sometimes, a history item added in a "touchend" listener is considered to be "added by user interaction", and sometimes it isn't, with little apparent pattern.

However, looking at the WebKit source changes in the commits above, I have a hypothesis.

The core of the "added by user interaction?" logic is (from Document.cpp):

```
bool Document::hasRecentUserInteractionForNavigationFromJS() const
{
    if (UserGestureIndicator::processingUserGesture(this))
        return true;

    static constexpr Seconds maximumItervalForUserGestureForwarding { 10_s };
    return (MonotonicTime::now() - lastHandledUserGestureTimestamp()) <= maximumItervalForUserGestureForwarding;
}
```

That is, we return true if either `processingUserGesture()` returns true or if the time returned by `lastHandledUserGestureTimestamp()` is no more than a second ago.

The return value of `lastHandledUserGestureTimestamp()` is a member updated by calls to `updateLastHandledUserGestureTimestamp()`.  Among other places, the latter is called when a `UserGestureIndicator` object is constructed and creates a new `UserGestureToken`.

Based on context clues, I suspect that `UserGestureToken` is an object that tracks the entire *lifetime* of a touch, not a single touch event.  (Here are the clues: `UserGestureToken` has `startTime` member; "gesture" is the term used in AppKit and UIKit to mean an entire touch-event sequence.)

This might mean that what `hasRecentUserInteractionForNavigationFromJS()` is *really* testing is whether the *beginning* of the last gesture was more than a second ago.

If that's true, then one downstream effect might be the following: attempting to add a history item in a "touchend" listener might succeed or not based on the duration of the entire gesture.

And in fact, that seems to be sort of what I'm seeing!

I'm not able to measure an exact one-second threshold (from the measurements I'm able to do in JavaScript), but I definitely see that *short* gestures tend to succeed (i.e., add the history item in a way that the back button respects), and *long* gestures tend not to.

(Maybe iOS changes that one-second value to something else?  Maybe there is a race?  I'm not breaking out a disassembler tonight, sorry!  But I'm interested to know what's going on there.)

I'll attach a test case that I'm using to demonstrate the above.  Hope this is enough to help you track down the bug.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-unassigned/attachments/20230308/f00ac2d3/attachment-0001.htm>


More information about the webkit-unassigned mailing list