Changeset 233927 in webkit


Ignore:
Timestamp:
Jul 18, 2018 12:51:54 PM (6 years ago)
Author:
jer.noble@apple.com
Message:

-_beginAnimatedResizeWithUpdates: can leave view in bad state if called during an existing animation
https://bugs.webkit.org/show_bug.cgi?id=187739
Source/WebKit:

Reviewed by Tim Horton.

It's not enough to reset _dynamicViewportUpdateMode to NotResizing; other parts of the code
check whether _resizeAnimationView is non-nil, the contentView may be hidden, etc. Add a new
internal method _cancelAnimatedResize that cleans up state when a call to
_beginAnimatedResizeWithUpdates: fails.

  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView _processDidExit]):
(-[WKWebView _cancelAnimatedResize]):
(-[WKWebView _didCompleteAnimatedResize]):
(-[WKWebView _beginAnimatedResizeWithUpdates:]):

Tools:

<rdar://problem/42304518>

Reviewed by Tim Horton.

  • TestWebKitAPI/Tests/WebKitCocoa/AnimatedResize.mm:

(TEST):

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r233926 r233927  
     12018-07-18  Jer Noble  <jer.noble@apple.com>
     2
     3        -_beginAnimatedResizeWithUpdates: can leave view in bad state if called during an existing animation
     4        https://bugs.webkit.org/show_bug.cgi?id=187739
     5
     6        Reviewed by Tim Horton.
     7
     8        It's not enough to reset _dynamicViewportUpdateMode to NotResizing; other parts of the code
     9        check whether _resizeAnimationView is non-nil, the contentView may be hidden, etc. Add a new
     10        internal method _cancelAnimatedResize that cleans up state when a call to
     11        _beginAnimatedResizeWithUpdates: fails.
     12
     13        * UIProcess/API/Cocoa/WKWebView.mm:
     14        (-[WKWebView _processDidExit]):
     15        (-[WKWebView _cancelAnimatedResize]):
     16        (-[WKWebView _didCompleteAnimatedResize]):
     17        (-[WKWebView _beginAnimatedResizeWithUpdates:]):
     18
    1192018-07-18  Jer Noble  <jer.noble@apple.com>
    220
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm

    r233915 r233927  
    16601660    RELEASE_LOG_IF_ALLOWED("%p -[WKWebView _processDidExit]", self);
    16611661    [self _hidePasswordView];
    1662     if (!_customContentView && _dynamicViewportUpdateMode != WebKit::DynamicViewportUpdateMode::NotResizing) {
    1663         NSUInteger indexOfResizeAnimationView = [[_scrollView subviews] indexOfObject:_resizeAnimationView.get()];
    1664         [_scrollView insertSubview:_contentView.get() atIndex:indexOfResizeAnimationView];
    1665         [_scrollView insertSubview:[_contentView unscaledView] atIndex:indexOfResizeAnimationView + 1];
    1666         [_resizeAnimationView removeFromSuperview];
    1667         _resizeAnimationView = nil;
    1668 
    1669         _resizeAnimationTransformAdjustments = CATransform3DIdentity;
    1670     }
     1662    [self _cancelAnimatedResize];
    16711663    [_contentView setFrame:self.bounds];
    16721664    [_scrollView setBackgroundColor:[UIColor whiteColor]];
     
    28912883}
    28922884
     2885- (void)_cancelAnimatedResize
     2886{
     2887    LOG_WITH_STREAM(VisibleRects, stream << "-[WKWebView " << _page->pageID() << " _cancelAnimatedResize:] " << " _dynamicViewportUpdateMode " << (int)_dynamicViewportUpdateMode);
     2888    if (_dynamicViewportUpdateMode == WebKit::DynamicViewportUpdateMode::NotResizing)
     2889        return;
     2890
     2891    if (!_customContentView) {
     2892        if (_resizeAnimationView) {
     2893            NSUInteger indexOfResizeAnimationView = [[_scrollView subviews] indexOfObject:_resizeAnimationView.get()];
     2894            [_scrollView insertSubview:_contentView.get() atIndex:indexOfResizeAnimationView];
     2895            [_scrollView insertSubview:[_contentView unscaledView] atIndex:indexOfResizeAnimationView + 1];
     2896            [_resizeAnimationView removeFromSuperview];
     2897            _resizeAnimationView = nil;
     2898        }
     2899
     2900        [_contentView setHidden:NO];
     2901        _resizeAnimationTransformAdjustments = CATransform3DIdentity;
     2902    }
     2903
     2904    _dynamicViewportUpdateMode = WebKit::DynamicViewportUpdateMode::NotResizing;
     2905    [self _scheduleVisibleContentRectUpdate];
     2906}
     2907
    28932908- (void)_didCompleteAnimatedResize
    28942909{
     
    29012916        // Paranoia. If _resizeAnimationView is null we'll end up setting a zero scale on the content view.
    29022917        RELEASE_LOG_IF_ALLOWED("%p -[WKWebView _didCompleteAnimatedResize:] - _resizeAnimationView is nil", self);
    2903         _dynamicViewportUpdateMode = WebKit::DynamicViewportUpdateMode::NotResizing;
     2918        [self _cancelAnimatedResize];
    29042919        return;
    29052920    }
     
    52995314    ASSERT_WITH_MESSAGE(!(_overridesViewLayoutSize && newViewLayoutSize.isEmpty()), "Clients controlling the layout size should maintain a valid layout size to minimize layouts.");
    53005315    if (CGRectIsEmpty(newBounds) || newViewLayoutSize.isEmpty() || CGRectIsEmpty(futureUnobscuredRectInSelfCoordinates) || CGRectIsEmpty(contentViewBounds)) {
    5301         _dynamicViewportUpdateMode = WebKit::DynamicViewportUpdateMode::NotResizing;
     5316        [self _cancelAnimatedResize];
    53025317        [self _frameOrBoundsChanged];
    53035318        if (_overridesViewLayoutSize)
     
    53085323            [self _dispatchSetDeviceOrientation:newOrientation];
    53095324
    5310         [self _scheduleVisibleContentRectUpdate];
    53115325        return;
    53125326    }
     
    53175331        && oldOrientation == newOrientation
    53185332        && UIEdgeInsetsEqualToEdgeInsets(oldObscuredInsets, newObscuredInsets)) {
    5319         _dynamicViewportUpdateMode = WebKit::DynamicViewportUpdateMode::NotResizing;
    5320         [self _scheduleVisibleContentRectUpdate];
     5333        [self _cancelAnimatedResize];
    53215334        return;
    53225335    }
  • trunk/Tools/ChangeLog

    r233926 r233927  
     12018-07-18  Jer Noble  <jer.noble@apple.com>
     2
     3        -_beginAnimatedResizeWithUpdates: can leave view in bad state if called during an existing animation
     4        https://bugs.webkit.org/show_bug.cgi?id=187739
     5        <rdar://problem/42304518>
     6
     7        Reviewed by Tim Horton.
     8
     9        * TestWebKitAPI/Tests/WebKitCocoa/AnimatedResize.mm:
     10        (TEST):
     11
    1122018-07-18  Jer Noble  <jer.noble@apple.com>
    213
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/AnimatedResize.mm

    r233698 r233927  
    348348}
    349349
     350TEST(WebKit, ResizeWithContentHiddenWithSubsequentNoOpResizeCompletes)
     351{
     352    auto webView = createAnimatedResizeWebView();
     353    [webView setUIDelegate:webView.get()];
     354
     355    [webView loadHTMLString:@"<head><meta name='viewport' content='initial-scale=1'></head>" baseURL:nil];
     356    auto navigationDelegate = adoptNS([[TestNavigationDelegate alloc] init]);
     357    webView.get().navigationDelegate = navigationDelegate.get();
     358    [navigationDelegate waitForDidFinishNavigation];
     359
     360    auto window = adoptNS([[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 800, 600)]);
     361    [window addSubview:webView.get()];
     362    [window setHidden:NO];
     363
     364    [webView _resizeWhileHidingContentWithUpdates:^{
     365        [webView setFrame:CGRectMake(0, 0, 100, 200)];
     366    }];
     367
     368    [webView _beginAnimatedResizeWithUpdates:^{
     369        [webView setFrame:CGRectMake(0, 0, 100, 200)];
     370    }];
     371
     372    __block bool didReadLayoutSize = false;
     373    [webView _doAfterNextPresentationUpdate:^{
     374        [webView evaluateJavaScript:@"[window.innerWidth, window.innerHeight]" completionHandler:^(id value, NSError *error) {
     375            CGFloat innerWidth = [[value objectAtIndex:0] floatValue];
     376            CGFloat innerHeight = [[value objectAtIndex:1] floatValue];
     377
     378            EXPECT_EQ(innerWidth, 100);
     379            EXPECT_EQ(innerHeight, 200);
     380
     381            didReadLayoutSize = true;
     382        }];
     383    }];
     384    TestWebKitAPI::Util::run(&didReadLayoutSize);
     385
     386    UIView *scrollView = immediateSubviewOfClass(webView.get(), NSClassFromString(@"WKScrollView"));
     387    UIView *contentView = immediateSubviewOfClass(scrollView, NSClassFromString(@"WKContentView"));
     388
     389    // Make sure that we've put the view hierarchy back together after the resize completed.
     390    EXPECT_NOT_NULL(scrollView);
     391    EXPECT_NOT_NULL(contentView);
     392    EXPECT_FALSE(contentView.hidden);
     393}
    350394
    351395TEST(WebKit, AnimatedResizeBlocksDoAfterNextPresentationUpdate)
Note: See TracChangeset for help on using the changeset viewer.