Changeset 251665 in webkit


Ignore:
Timestamp:
Oct 28, 2019 12:58:02 PM (4 years ago)
Author:
Wenson Hsieh
Message:

[iOS] 3 editing/pasteboard/smart-paste-paragraph-* tests are flaky
https://bugs.webkit.org/show_bug.cgi?id=203264
<rdar://problem/56512107>

Reviewed by Tim Horton.

Fixes several flaky layout tests that exercise a corner case in our logic for caching position information
responses in the UI process. When focusing an element via a tap, we send a position information request for the
tap location in -_webTouchEventsRecognized:. After the web process computes the information and hands it back to
the UI process, we cache this in WKContentView's _positionInformation.

However, at the time of computing the request, the tapped element has not been focused yet, so the value of the
position information's nodeAtPositionIsFocusedElement flag is false. After the tap is recognized, we'll then
focus the element, such that if a subsequent position information request were to arrive at the same location,
it would have a nodeAtPositionIsFocusedElement flag set to true.

In this state, if the user taps _exactly_ at the same location again, UIKit (through text interaction gestures)
will ask us for information at the same point; we will end up using the cached information, for which
nodeAtPositionIsFocusedElement is false, causing us to incorrectly prevent the text interaction. In this
particular case, we fail to select text via a double tap gesture.

To address this, we invalidate the cached position information in the UI process whenever the focused element
rect changes (e.g. when the focused element changes); the only exception to this is when the previously cached
position information was not over the focused element, and the new focused element rect is empty, in which case
the value of nodeAtPositionIsFocusedElement is guaranteed to have not changed.

While this may potentially leads to an additional synchronous position information request when tapping at the
same location after focusing an element, this is very difficult to achieve in practice, since the tap location
would need to be _exactly_ at the same location.

No new test, since this is exercised by existing flaky layout tests.

  • UIProcess/ios/WKContentViewInteraction.mm:

(-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:]):
(-[WKContentView _elementDidBlur]):

Also, add a FIXME about how we clear out surprisingly little of _focusedElementInformation when blurring the
focused element.

(-[WKContentView _didChangeFocusedElementRect:toRect:]):

Location:
trunk/Source/WebKit
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r251663 r251665  
     12019-10-28  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] 3 editing/pasteboard/smart-paste-paragraph-* tests are flaky
     4        https://bugs.webkit.org/show_bug.cgi?id=203264
     5        <rdar://problem/56512107>
     6
     7        Reviewed by Tim Horton.
     8
     9        Fixes several flaky layout tests that exercise a corner case in our logic for caching position information
     10        responses in the UI process. When focusing an element via a tap, we send a position information request for the
     11        tap location in -_webTouchEventsRecognized:. After the web process computes the information and hands it back to
     12        the UI process, we cache this in WKContentView's _positionInformation.
     13
     14        However, at the time of computing the request, the tapped element has not been focused yet, so the value of the
     15        position information's nodeAtPositionIsFocusedElement flag is false. After the tap is recognized, we'll then
     16        focus the element, such that if a subsequent position information request were to arrive at the same location,
     17        it would have a nodeAtPositionIsFocusedElement flag set to true.
     18
     19        In this state, if the user taps _exactly_ at the same location again, UIKit (through text interaction gestures)
     20        will ask us for information at the same point; we will end up using the cached information, for which
     21        nodeAtPositionIsFocusedElement is false, causing us to incorrectly prevent the text interaction. In this
     22        particular case, we fail to select text via a double tap gesture.
     23
     24        To address this, we invalidate the cached position information in the UI process whenever the focused element
     25        rect changes (e.g. when the focused element changes); the only exception to this is when the previously cached
     26        position information was not over the focused element, and the new focused element rect is empty, in which case
     27        the value of nodeAtPositionIsFocusedElement is guaranteed to have not changed.
     28
     29        While this may potentially leads to an additional synchronous position information request when tapping at the
     30        same location after focusing an element, this is very difficult to achieve in practice, since the tap location
     31        would need to be _exactly_ at the same location.
     32
     33        No new test, since this is exercised by existing flaky layout tests.
     34
     35        * UIProcess/ios/WKContentViewInteraction.mm:
     36        (-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:]):
     37        (-[WKContentView _elementDidBlur]):
     38
     39        Also, add a FIXME about how we clear out surprisingly little of _focusedElementInformation when blurring the
     40        focused element.
     41
     42        (-[WKContentView _didChangeFocusedElementRect:toRect:]):
     43
    1442019-10-28  John Wilander  <wilander@apple.com>
    245
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

    r251522 r251665  
    55575557        [inputDelegate _webView:_webView willStartInputSession:_formInputSession.get()];
    55585558
     5559    auto previousElementRect = _isChangingFocus ? _focusedElementInformation.elementRect : WebCore::IntRect();
    55595560    BOOL isSelectable = mayContainSelectableText(information.elementType);
    55605561    BOOL editableChanged = [self setIsEditable:isSelectable];
     
    56035604   
    56045605    [_webView didStartFormControlInteraction];
     5606
     5607    [self _didChangeFocusedElementRect:previousElementRect toRect:_focusedElementInformation.elementRect];
    56055608}
    56065609
     
    56265629
    56275630    BOOL editableChanged = [self setIsEditable:NO];
    5628 
     5631    auto previousElementRect = _focusedElementInformation.elementRect;
     5632    // FIXME: We should completely invalidate _focusedElementInformation here, instead of a subset of individual members.
    56295633    _focusedElementInformation.elementType = WebKit::InputType::None;
    56305634    _focusedElementInformation.shouldSynthesizeKeyEventsForEditing = false;
     
    56595663    }
    56605664
    5661     if (!_isChangingFocus)
     5665    if (!_isChangingFocus) {
    56625666        _didAccessoryTabInitiateFocus = NO;
     5667        [self _didChangeFocusedElementRect:previousElementRect toRect:WebCore::IntRect()];
     5668    }
     5669}
     5670
     5671- (void)_didChangeFocusedElementRect:(const WebCore::IntRect&)previousRect toRect:(const WebCore::IntRect&)newRect
     5672{
     5673    if (previousRect == newRect)
     5674        return;
     5675
     5676    if (newRect.isEmpty() && !_positionInformation.nodeAtPositionIsFocusedElement)
     5677        return;
     5678
     5679    // If the focused element rect changed, the cached position information's nodeAtPositionIsFocusedElement may be stale.
     5680    _hasValidPositionInformation = NO;
     5681    _positionInformation = { };
    56635682}
    56645683
Note: See TracChangeset for help on using the changeset viewer.