Skip to content

Commit

Permalink
Performing a no-op animated resize cancels any pending resize immedia…
Browse files Browse the repository at this point in the history
…tely

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

Reviewed by Wenson Hsieh.

* Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm:
(-[WKWebView _beginAnimatedResizeWithUpdates:]):
_beginAnimatedResizeWithUpdates cancels the resize and completes immediately
if the update block didn't change any relevant state. For clients who want
to do multiple animated resizes in a row, this can result in a discontinuity
if a impactful animated resize is performed, followed by a no-op animated
resize before the results of the first resize arrive: this results in
the first resize being cancelled, and the web view being shown in an
incompletely-updated state. To avoid this, just avoid cancelling no-op
resizes when there is already a pending resize.

* Tools/TestWebKitAPI/Tests/WebKitCocoa/AnimatedResize.mm:
(TEST):
Add a test. Also move all of the other tests into an AnimatedResize test group
to make it easy to run them together. Add a missing `_endAnimatedResize` to
ResizeWithContentHiddenWithSubsequentNoOpResizeCompletes, because previously
it was depending on this bug.

Canonical link: https://commits.webkit.org/252106@main
  • Loading branch information
hortont424 committed Jul 3, 2022
1 parent 1671a01 commit b18af70
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 12 deletions.
4 changes: 3 additions & 1 deletion Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3188,6 +3188,7 @@ - (void)_hideContentUntilNextUpdate

- (void)_beginAnimatedResizeWithUpdates:(void (^)(void))updateBlock
{
bool hadPendingAnimatedResize = _dynamicViewportUpdateMode != WebKit::DynamicViewportUpdateMode::NotResizing;
CGRect oldBounds = self.bounds;
WebCore::FloatRect oldUnobscuredContentRect = _page->unobscuredContentRect();

Expand Down Expand Up @@ -3261,7 +3262,8 @@ - (void)_beginAnimatedResizeWithUpdates:(void (^)(void))updateBlock
return;
}

if (CGRectEqualToRect(oldBounds, newBounds)
if (!hadPendingAnimatedResize
&& CGRectEqualToRect(oldBounds, newBounds)
&& oldViewLayoutSize == newViewLayoutSize
&& oldMinimumUnobscuredSize == newMinimumUnobscuredSize
&& oldMaximumUnobscuredSize == newMaximumUnobscuredSize
Expand Down
54 changes: 43 additions & 11 deletions Tools/TestWebKitAPI/Tests/WebKitCocoa/AnimatedResize.mm
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ - (void)_webView:(WKWebView *)webView didChangeSafeAreaShouldAffectObscuredInset
return navigationDelegate;
}

TEST(WebKit, DISABLED_ResizeWithHiddenContentDoesNotHang)
TEST(AnimatedResize, DISABLED_ResizeWithHiddenContentDoesNotHang)
{
auto webView = createAnimatedResizeWebView();
[webView loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"blinking-div" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]]];
Expand All @@ -112,7 +112,7 @@ - (void)_webView:(WKWebView *)webView didChangeSafeAreaShouldAffectObscuredInset
}
}

TEST(WebKit, AnimatedResizeDoesNotHang)
TEST(AnimatedResize, AnimatedResizeDoesNotHang)
{
auto webView = createAnimatedResizeWebView();
[webView loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"blinking-div" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]]];
Expand Down Expand Up @@ -140,7 +140,7 @@ - (void)_webView:(WKWebView *)webView didChangeSafeAreaShouldAffectObscuredInset
}
}

TEST(WebKit, AnimatedResizeBlocksViewportFitChanges)
TEST(AnimatedResize, AnimatedResizeBlocksViewportFitChanges)
{
auto webView = createAnimatedResizeWebView();
[webView setUIDelegate:webView.get()];
Expand Down Expand Up @@ -187,7 +187,7 @@ - (void)_webView:(WKWebView *)webView didChangeSafeAreaShouldAffectObscuredInset
EXPECT_TRUE(didChangeSafeAreaShouldAffectObscuredInsets);
}

TEST(WebKit, OverrideLayoutSizeChangesDuringAnimatedResizeSucceed)
TEST(AnimatedResize, OverrideLayoutSizeChangesDuringAnimatedResizeSucceed)
{
auto webView = createAnimatedResizeWebView();
[webView setUIDelegate:webView.get()];
Expand Down Expand Up @@ -227,7 +227,7 @@ - (void)_webView:(WKWebView *)webView didChangeSafeAreaShouldAffectObscuredInset
TestWebKitAPI::Util::run(&didReadLayoutSize);
}

TEST(WebKit, OverrideLayoutSizeIsRestoredAfterProcessRelaunch)
TEST(AnimatedResize, OverrideLayoutSizeIsRestoredAfterProcessRelaunch)
{
auto webView = createAnimatedResizeWebView();
[webView setUIDelegate:webView.get()];
Expand Down Expand Up @@ -258,7 +258,7 @@ - (void)_webView:(WKWebView *)webView didChangeSafeAreaShouldAffectObscuredInset
TestWebKitAPI::Util::run(&didReadLayoutSize);
}

TEST(WebKit, OverrideLayoutSizeIsRestoredAfterChangingDuringProcessRelaunch)
TEST(AnimatedResize, OverrideLayoutSizeIsRestoredAfterChangingDuringProcessRelaunch)
{
auto webView = createAnimatedResizeWebView();
[webView setUIDelegate:webView.get()];
Expand Down Expand Up @@ -291,7 +291,7 @@ - (void)_webView:(WKWebView *)webView didChangeSafeAreaShouldAffectObscuredInset
TestWebKitAPI::Util::run(&didReadLayoutSize);
}

TEST(WebKit, ChangeFrameAndMinimumEffectiveDeviceWidthDuringAnimatedResize)
TEST(AnimatedResize, ChangeFrameAndMinimumEffectiveDeviceWidthDuringAnimatedResize)
{
auto webView = createAnimatedResizeWebView();
[[webView configuration] preferences]._shouldIgnoreMetaViewport = YES;
Expand Down Expand Up @@ -346,7 +346,7 @@ - (void)_webView:(WKWebView *)webView didChangeSafeAreaShouldAffectObscuredInset
return foundSubview;
}

TEST(WebKit, ResizeWithContentHiddenCompletes)
TEST(AnimatedResize, ResizeWithContentHiddenCompletes)
{
auto webView = createAnimatedResizeWebView();
[webView setUIDelegate:webView.get()];
Expand Down Expand Up @@ -387,7 +387,7 @@ - (void)_webView:(WKWebView *)webView didChangeSafeAreaShouldAffectObscuredInset
EXPECT_FALSE(contentView.hidden);
}

TEST(WebKit, ResizeWithContentHiddenWithSubsequentNoOpResizeCompletes)
TEST(AnimatedResize, ResizeWithContentHiddenWithSubsequentNoOpResizeCompletes)
{
auto webView = createAnimatedResizeWebView();
[webView setUIDelegate:webView.get()];
Expand All @@ -409,6 +409,8 @@ - (void)_webView:(WKWebView *)webView didChangeSafeAreaShouldAffectObscuredInset
[webView setFrame:CGRectMake(0, 0, 100, 200)];
}];

[webView _endAnimatedResize];

__block bool didReadLayoutSize = false;
[webView _doAfterNextPresentationUpdate:^{
[webView evaluateJavaScript:@"[window.innerWidth, window.innerHeight]" completionHandler:^(id value, NSError *error) {
Expand All @@ -432,7 +434,7 @@ - (void)_webView:(WKWebView *)webView didChangeSafeAreaShouldAffectObscuredInset
EXPECT_FALSE(contentView.hidden);
}

TEST(WebKit, AnimatedResizeBlocksDoAfterNextPresentationUpdate)
TEST(AnimatedResize, AnimatedResizeBlocksDoAfterNextPresentationUpdate)
{
auto webView = createAnimatedResizeWebView();
[webView setUIDelegate:webView.get()];
Expand Down Expand Up @@ -468,7 +470,7 @@ - (void)_webView:(WKWebView *)webView didChangeSafeAreaShouldAffectObscuredInset
TestWebKitAPI::Util::run(&didGetCommitAfterEndAnimatedResize);
}

TEST(WebKit, CreateWebPageAfterAnimatedResize)
TEST(AnimatedResize, CreateWebPageAfterAnimatedResize)
{
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)]);
[webView synchronouslyLoadTestPageNamed:@"large-red-square-image"];
Expand Down Expand Up @@ -496,4 +498,34 @@ - (void)_webView:(WKWebView *)webView didChangeSafeAreaShouldAffectObscuredInset
EXPECT_EQ(1024, dimensions.lastObject.intValue);
}

TEST(AnimatedResize, ResizeWithWithSubsequentNoOpResizeIsNotCancelled)
{
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)]);
[webView synchronouslyLoadHTMLString:@"<head><meta name='viewport' content='initial-scale=1'></head>"];

UIView *scrollView = immediateSubviewOfClass(webView.get(), NSClassFromString(@"WKScrollView"));
UIView *contentView = immediateSubviewOfClass(scrollView, NSClassFromString(@"WKContentView"));

[webView _resizeWhileHidingContentWithUpdates:^{
[webView setFrame:CGRectMake(0, 0, 100, 200)];
}];

EXPECT_TRUE(contentView.hidden);

[webView _resizeWhileHidingContentWithUpdates:^{
[webView setFrame:CGRectMake(0, 0, 100, 200)];
}];

// The animated resize shouldn't be cancelled just because we did a no-op resize;
// the first one is still in progress at this point.
EXPECT_TRUE(contentView.hidden);

// Eventually we should get a commit that un-hides the content view.
while (1) {
[webView waitForNextPresentationUpdate];
if (!contentView.hidden)
break;
}
}

#endif

0 comments on commit b18af70

Please sign in to comment.