https://bugs.webkit.org/show_bug.cgi?id=160289
<rdar://problem/
27553464>
Reviewed by Simon Fraser.
API Tests: WebKit2.AnimatedResizeDoesNotHang, WebKit2.ResizeWithHiddenContentDoesNotHang
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _didCommitLayerTree:]):
Avoid calling _endAnimatedResize when a commit comes in when we haven't yet received
a dynamic viewport update reply (and thus don't have a transaction ID to wait on).
Previously, in this case, _resizeAnimationTransformTransactionID would be 0,
and *any* commit would cause _endAnimatedResize to be called, causing us to always
fall into the worst-case sync wait.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::synchronizeDynamicViewportUpdate):
Make use of waitForDidUpdateViewState instead of having a separate waitForAndDispatchImmediately
here, because it knows to do things like dispatch the didUpdate message if it's still
pending. This also shortens the sync wait timeout from 1s to 500ms, which makes it
consistent with e.g. the newly-parented-view timeout duration, and should be nothing
but positive.
* Platform/IPC/Connection.cpp:
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessageFromSecondaryThread):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::ignoreTimeoutsForTesting):
* UIProcess/API/APIProcessPoolConfiguration.cpp:
(API::ProcessPoolConfiguration::copy):
* UIProcess/API/APIProcessPoolConfiguration.h:
* UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h:
* UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm:
(-[_WKProcessPoolConfiguration ignoreSynchronousMessagingTimeoutsForTesting]):
(-[_WKProcessPoolConfiguration setIgnoreSynchronousMessagingTimeoutsForTesting:]):
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::processDidFinishLaunching):
Add a mechanism for clients to cause all synchronous message timeouts to be effectively infinite.
The new API tests use this to ensure that the test will time out if they ever enter
the bad state (otherwise, the shorter sync wait timeout could make the test still pass).
* TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKit2Cocoa/AnimatedResize.mm: Added.
(-[AnimatedResizeNavigationDelegate _webView:renderingProgressDidChange:]):
(-[AnimatedResizeWebView _endAnimatedResize]):
(animatedResizeWebView):
(TEST):
* TestWebKitAPI/Tests/WebKit2Cocoa/blinking-div.html: Added.
Add two tests that ensure that hidden-content and animated resizes
don't cause unnecessary synchronous waits. Only the hidden-content
one fails before my patch, but it seemed reasonable to add both anyway.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@203842
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2016-07-28 Tim Horton <timothy_horton@apple.com>
+
+ Frequent animation lags when interacting with Safari (sidebar, tab switching, etc.)
+ https://bugs.webkit.org/show_bug.cgi?id=160289
+ <rdar://problem/27553464>
+
+ Reviewed by Simon Fraser.
+
+ API Tests: WebKit2.AnimatedResizeDoesNotHang, WebKit2.ResizeWithHiddenContentDoesNotHang
+
+ * UIProcess/API/Cocoa/WKWebView.mm:
+ (-[WKWebView _didCommitLayerTree:]):
+ Avoid calling _endAnimatedResize when a commit comes in when we haven't yet received
+ a dynamic viewport update reply (and thus don't have a transaction ID to wait on).
+ Previously, in this case, _resizeAnimationTransformTransactionID would be 0,
+ and *any* commit would cause _endAnimatedResize to be called, causing us to always
+ fall into the worst-case sync wait.
+
+ * UIProcess/ios/WebPageProxyIOS.mm:
+ (WebKit::WebPageProxy::synchronizeDynamicViewportUpdate):
+ Make use of waitForDidUpdateViewState instead of having a separate waitForAndDispatchImmediately
+ here, because it knows to do things like dispatch the didUpdate message if it's still
+ pending. This also shortens the sync wait timeout from 1s to 500ms, which makes it
+ consistent with e.g. the newly-parented-view timeout duration, and should be nothing
+ but positive.
+
+ * Platform/IPC/Connection.cpp:
+ (IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
+ (IPC::Connection::waitForMessage):
+ (IPC::Connection::sendSyncMessageFromSecondaryThread):
+ (IPC::Connection::waitForSyncReply):
+ * Platform/IPC/Connection.h:
+ (IPC::Connection::ignoreTimeoutsForTesting):
+ * UIProcess/API/APIProcessPoolConfiguration.cpp:
+ (API::ProcessPoolConfiguration::copy):
+ * UIProcess/API/APIProcessPoolConfiguration.h:
+ * UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h:
+ * UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm:
+ (-[_WKProcessPoolConfiguration ignoreSynchronousMessagingTimeoutsForTesting]):
+ (-[_WKProcessPoolConfiguration setIgnoreSynchronousMessagingTimeoutsForTesting:]):
+ * UIProcess/WebProcessPool.cpp:
+ (WebKit::WebProcessPool::processDidFinishLaunching):
+ Add a mechanism for clients to cause all synchronous message timeouts to be effectively infinite.
+ The new API tests use this to ensure that the test will time out if they ever enter
+ the bad state (otherwise, the shorter sync wait timeout could make the test still pass).
+
2016-07-27 Andy Estes <aestes@apple.com>
[iOS] Add WKUIDelegate SPI for specifying that an attachment list is from a managed source
return sendMessage(WTFMove(encoder));
}
+std::chrono::milliseconds Connection::timeoutRespectingIgnoreTimeoutsForTesting(std::chrono::milliseconds timeout) const
+{
+ return m_ignoreTimeoutsForTesting ? std::chrono::milliseconds::max() : timeout;
+}
+
std::unique_ptr<MessageDecoder> Connection::waitForMessage(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, std::chrono::milliseconds timeout, unsigned waitForMessageFlags)
{
ASSERT(RunLoop::isMain());
+ timeout = timeoutRespectingIgnoreTimeoutsForTesting(timeout);
+
bool hasIncomingSynchronousMessage = false;
// First, check if this message is already in the incoming messages queue.
sendMessage(WTFMove(encoder), 0, true);
+ timeout = timeoutRespectingIgnoreTimeoutsForTesting(timeout);
pendingReply.semaphore.wait(currentTime() + (timeout.count() / 1000.0));
// Finally, pop the pending sync reply information.
std::unique_ptr<MessageDecoder> Connection::waitForSyncReply(uint64_t syncRequestID, std::chrono::milliseconds timeout, unsigned syncSendFlags)
{
+ timeout = timeoutRespectingIgnoreTimeoutsForTesting(timeout);
double absoluteTime = currentTime() + (timeout.count() / 1000.0);
willSendSyncMessage(syncSendFlags);
void allowFullySynchronousModeForTesting() { m_fullySynchronousModeIsAllowedForTesting = true; }
+ void ignoreTimeoutsForTesting() { m_ignoreTimeoutsForTesting = true; }
+
private:
Connection(Identifier, bool isServer, Client&);
void platformInitialize(Identifier);
void willSendSyncMessage(unsigned syncSendFlags);
void didReceiveSyncReply(unsigned syncSendFlags);
+
+ std::chrono::milliseconds timeoutRespectingIgnoreTimeoutsForTesting(std::chrono::milliseconds) const;
Client* m_client;
bool m_isServer;
unsigned m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount;
unsigned m_inDispatchMessageMarkedToUseFullySynchronousModeForTesting { 0 };
bool m_fullySynchronousModeIsAllowedForTesting { false };
+ bool m_ignoreTimeoutsForTesting { false };
bool m_didReceiveInvalidMessage;
// Incoming messages.
copy->m_cachePartitionedURLSchemes = this->m_cachePartitionedURLSchemes;
copy->m_alwaysRevalidatedURLSchemes = this->m_alwaysRevalidatedURLSchemes;
copy->m_fullySynchronousModeIsAllowedForTesting = this->m_fullySynchronousModeIsAllowedForTesting;
+ copy->m_ignoreSynchronousMessagingTimeoutsForTesting = this->m_ignoreSynchronousMessagingTimeoutsForTesting;
copy->m_overrideLanguages = this->m_overrideLanguages;
return copy;
bool fullySynchronousModeIsAllowedForTesting() const { return m_fullySynchronousModeIsAllowedForTesting; }
void setFullySynchronousModeIsAllowedForTesting(bool allowed) { m_fullySynchronousModeIsAllowedForTesting = allowed; }
+ bool ignoreSynchronousMessagingTimeoutsForTesting() const { return m_ignoreSynchronousMessagingTimeoutsForTesting; }
+ void setIgnoreSynchronousMessagingTimeoutsForTesting(bool allowed) { m_ignoreSynchronousMessagingTimeoutsForTesting = allowed; }
+
const Vector<WTF::String>& overrideLanguages() const { return m_overrideLanguages; }
void setOverrideLanguages(Vector<WTF::String>&& languages) { m_overrideLanguages = WTFMove(languages); }
Vector<WTF::String> m_cachePartitionedURLSchemes;
Vector<WTF::String> m_alwaysRevalidatedURLSchemes;
bool m_fullySynchronousModeIsAllowedForTesting { false };
+ bool m_ignoreSynchronousMessagingTimeoutsForTesting { false };
Vector<WTF::String> m_overrideLanguages;
};
uint64_t _firstPaintAfterCommitLoadTransactionID;
DynamicViewportUpdateMode _dynamicViewportUpdateMode;
CATransform3D _resizeAnimationTransformAdjustments;
- uint64_t _resizeAnimationTransformTransactionID;
+ Optional<uint64_t> _resizeAnimationTransformTransactionID;
RetainPtr<UIView> _resizeAnimationView;
CGFloat _lastAdjustmentForScroller;
Optional<CGRect> _frozenVisibleContentRect;
return;
if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing) {
- if (layerTreeTransaction.transactionID() >= _resizeAnimationTransformTransactionID) {
+ if (_resizeAnimationTransformTransactionID && layerTreeTransaction.transactionID() >= _resizeAnimationTransformTransactionID.value()) {
+ _resizeAnimationTransformTransactionID = Nullopt;
[_resizeAnimationView layer].sublayerTransform = _resizeAnimationTransformAdjustments;
if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::ResizingWithDocumentHidden) {
[_contentView setHidden:NO];
@property (nonatomic, copy) NSArray *cachePartitionedURLSchemes;
@property (nonatomic, copy) NSArray<NSString *> *alwaysRevalidatedURLSchemes WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
@property (nonatomic) BOOL diskCacheSpeculativeValidationEnabled WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+@property (nonatomic) BOOL ignoreSynchronousMessagingTimeoutsForTesting WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
@end
_processPoolConfiguration->setDiskCacheSpeculativeValidationEnabled(enabled);
}
+- (BOOL)ignoreSynchronousMessagingTimeoutsForTesting
+{
+ return _processPoolConfiguration->ignoreSynchronousMessagingTimeoutsForTesting();
+}
+
+- (void)setIgnoreSynchronousMessagingTimeoutsForTesting:(BOOL)ignoreSynchronousMessagingTimeoutsForTesting
+{
+ _processPoolConfiguration->setIgnoreSynchronousMessagingTimeoutsForTesting(ignoreSynchronousMessagingTimeoutsForTesting);
+}
+
- (NSArray *)cachePartitionedURLSchemes
{
auto schemes = _processPoolConfiguration->cachePartitionedURLSchemes();
if (m_configuration->fullySynchronousModeIsAllowedForTesting())
process->connection()->allowFullySynchronousModeForTesting();
+ if (m_configuration->ignoreSynchronousMessagingTimeoutsForTesting())
+ process->connection()->ignoreTimeoutsForTesting();
+
m_connectionClient.didCreateConnection(this, process->webConnection());
}
}
// If m_dynamicViewportSizeUpdateWaitingForTarget is false, we are waiting for the next valid frame with the hope it is the one for the new target.
- // If m_dynamicViewportSizeUpdateWaitingForTarget is still true, this is a desesperate attempt to get the valid frame before finishing the animation.
+ // If m_dynamicViewportSizeUpdateWaitingForTarget is still true, this is a desperate attempt to get the valid frame before finishing the animation.
if (m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit)
- m_process->connection()->waitForAndDispatchImmediately<Messages::RemoteLayerTreeDrawingAreaProxy::CommitLayerTree>(m_pageID, std::chrono::seconds(1), IPC::InterruptWaitingIfSyncMessageArrives);
+ m_drawingArea->waitForDidUpdateViewState();
m_dynamicViewportSizeUpdateWaitingForTarget = false;
m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit = false;
+2016-07-28 Tim Horton <timothy_horton@apple.com>
+
+ Frequent animation lags when interacting with Safari (sidebar, tab switching, etc.)
+ https://bugs.webkit.org/show_bug.cgi?id=160289
+ <rdar://problem/27553464>
+
+ Reviewed by Simon Fraser.
+
+ * TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig:
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKit2Cocoa/AnimatedResize.mm: Added.
+ (-[AnimatedResizeNavigationDelegate _webView:renderingProgressDidChange:]):
+ (-[AnimatedResizeWebView _endAnimatedResize]):
+ (animatedResizeWebView):
+ (TEST):
+ * TestWebKitAPI/Tests/WebKit2Cocoa/blinking-div.html: Added.
+ Add two tests that ensure that hidden-content and animated resizes
+ don't cause unnecessary synchronous waits. Only the hidden-content
+ one fails before my patch, but it seemed reasonable to add both anyway.
+
2016-07-28 David Kilzer <ddkilzer@apple.com>
webkit-patch upload --suggest-reviewers shouldn't break in the presence of deleted or moved files
OTHER_LDFLAGS_PLATFORM[sdk=macosx*] = -framework Cocoa -framework Carbon;
// FIXME: This should not be built on iOS. Instead we should create and use a TestWebKitAPI application.
-OTHER_LDFLAGS_PLATFORM[sdk=iphone*] = -framework WebCore -framework CoreGraphics;
+OTHER_LDFLAGS_PLATFORM[sdk=iphone*] = -framework WebCore -framework CoreGraphics -framework UIKit;
LD_RUNPATH_SEARCH_PATHS = "@loader_path";
2D51A0C71C8BF00C00765C45 /* DOMHTMLVideoElementWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D51A0C51C8BF00400765C45 /* DOMHTMLVideoElementWrapper.mm */; };
2DC4CF771D2D9DD800ECCC94 /* DataDetection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DC4CF761D2D9DD800ECCC94 /* DataDetection.mm */; };
2DD7D3AF178227B30026E1E3 /* lots-of-text-vertical-lr.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2DD7D3AE178227AC0026E1E3 /* lots-of-text-vertical-lr.html */; };
+ 2DE71AFE1D49C0BD00904094 /* AnimatedResize.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DE71AFD1D49C0BD00904094 /* AnimatedResize.mm */; };
+ 2DE71B001D49C3ED00904094 /* blinking-div.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2DE71AFF1D49C2F000904094 /* blinking-div.html */; };
2E14A5291D3FE96B0010F35B /* autoplaying-video-with-audio.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E14A5281D3FE8B80010F35B /* autoplaying-video-with-audio.html */; };
2E1B7B001D41ABA7007558B4 /* large-video-seek-after-ending.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E1B7AFF1D41A95F007558B4 /* large-video-seek-after-ending.html */; };
2E1B7B021D41B1B9007558B4 /* large-video-hides-controls-after-seek-to-end.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E1B7B011D41B1B3007558B4 /* large-video-hides-controls-after-seek-to-end.html */; };
- 2E1DFDF11D42E1E400714A00 /* large-video-seek-to-beginning-and-play-after-ending.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E1DFDF01D42E14400714A00 /* large-video-seek-to-beginning-and-play-after-ending.html */; };
2E1DFDED1D42A51100714A00 /* large-videos-with-audio.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E1DFDEC1D42A41C00714A00 /* large-videos-with-audio.html */; };
2E1DFDEF1D42A6F200714A00 /* large-videos-with-audio-autoplay.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E1DFDEE1D42A6EB00714A00 /* large-videos-with-audio-autoplay.html */; };
+ 2E1DFDF11D42E1E400714A00 /* large-video-seek-to-beginning-and-play-after-ending.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E1DFDF01D42E14400714A00 /* large-video-seek-to-beginning-and-play-after-ending.html */; };
2E7765CD16C4D80A00BA2BB1 /* mainIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E7765CC16C4D80A00BA2BB1 /* mainIOS.mm */; };
2E7765CF16C4D81100BA2BB1 /* mainMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E7765CE16C4D81100BA2BB1 /* mainMac.mm */; };
33BE5AF9137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33BE5AF8137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp */; };
2E1DFDEF1D42A6F200714A00 /* large-videos-with-audio-autoplay.html in Copy Resources */,
2E1DFDED1D42A51100714A00 /* large-videos-with-audio.html in Copy Resources */,
5C9E59411D3EB5AC00E3C62E /* ApplicationCache.db in Copy Resources */,
+ 2DE71B001D49C3ED00904094 /* blinking-div.html in Copy Resources */,
5C9E59421D3EB5AC00E3C62E /* ApplicationCache.db-shm in Copy Resources */,
5C9E59431D3EB5AC00E3C62E /* ApplicationCache.db-wal in Copy Resources */,
2E14A5291D3FE96B0010F35B /* autoplaying-video-with-audio.html in Copy Resources */,
2DD355351BD08378005DF4A7 /* AutoLayoutIntegration.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AutoLayoutIntegration.mm; sourceTree = "<group>"; };
2DD7D3A9178205D00026E1E3 /* ResizeReversePaginatedWebView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResizeReversePaginatedWebView.cpp; sourceTree = "<group>"; };
2DD7D3AE178227AC0026E1E3 /* lots-of-text-vertical-lr.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "lots-of-text-vertical-lr.html"; sourceTree = "<group>"; };
+ 2DE71AFD1D49C0BD00904094 /* AnimatedResize.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AnimatedResize.mm; sourceTree = "<group>"; };
+ 2DE71AFF1D49C2F000904094 /* blinking-div.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "blinking-div.html"; sourceTree = "<group>"; };
2E14A5281D3FE8B80010F35B /* autoplaying-video-with-audio.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "autoplaying-video-with-audio.html"; sourceTree = "<group>"; };
2E1B7AFF1D41A95F007558B4 /* large-video-seek-after-ending.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-video-seek-after-ending.html"; sourceTree = "<group>"; };
2E1B7B011D41B1B3007558B4 /* large-video-hides-controls-after-seek-to-end.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-video-hides-controls-after-seek-to-end.html"; sourceTree = "<group>"; };
- 2E1DFDF01D42E14400714A00 /* large-video-seek-to-beginning-and-play-after-ending.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-video-seek-to-beginning-and-play-after-ending.html"; sourceTree = "<group>"; };
2E1DFDEC1D42A41C00714A00 /* large-videos-with-audio.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-videos-with-audio.html"; sourceTree = "<group>"; };
2E1DFDEE1D42A6EB00714A00 /* large-videos-with-audio-autoplay.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-videos-with-audio-autoplay.html"; sourceTree = "<group>"; };
+ 2E1DFDF01D42E14400714A00 /* large-video-seek-to-beginning-and-play-after-ending.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-video-seek-to-beginning-and-play-after-ending.html"; sourceTree = "<group>"; };
2E7765CC16C4D80A00BA2BB1 /* mainIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = mainIOS.mm; sourceTree = "<group>"; };
2E7765CE16C4D81100BA2BB1 /* mainMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = mainMac.mm; sourceTree = "<group>"; };
333B9CE11277F23100FEFCE3 /* PreventEmptyUserAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PreventEmptyUserAgent.cpp; sourceTree = "<group>"; };
A16F66B81C40E9E100BD4D24 /* Resources */,
7CEFA9641AC0B9E200B910FD /* _WKUserContentExtensionStore.mm */,
A1DF74301C41B65800A2F4D0 /* AlwaysRevalidatedURLSchemes.mm */,
+ 2DE71AFD1D49C0BD00904094 /* AnimatedResize.mm */,
2DD355351BD08378005DF4A7 /* AutoLayoutIntegration.mm */,
A13EBBAC1B87436F00097110 /* BundleParameters.mm */,
A13EBBAE1B87436F00097110 /* BundleParametersPlugIn.mm */,
5C9E59401D3EB1DE00E3C62E /* ApplicationCache.db-wal */,
2E14A5281D3FE8B80010F35B /* autoplaying-video-with-audio.html */,
93CFA8661CEB9DE1000565A8 /* autofocused-text-input.html */,
+ 2DE71AFF1D49C2F000904094 /* blinking-div.html */,
A16F66B91C40EA2000BD4D24 /* ContentFiltering.html */,
5714ECB81CA8B58800051AC8 /* DownloadRequestOriginalURL.html */,
5714ECBC1CA8C21800051AC8 /* DownloadRequestOriginalURL2.html */,
7CCE7F241A411AF600447C4C /* Navigation.mm in Sources */,
A14FC5881B8991BF00D107EB /* ContentFiltering.mm in Sources */,
7CCE7F021A411AE600447C4C /* NewFirstVisuallyNonEmptyLayout.cpp in Sources */,
+ 2DE71AFE1D49C0BD00904094 /* AnimatedResize.mm in Sources */,
51A587861D273AA9004BA9AF /* IndexedDBDatabaseProcessKill.mm in Sources */,
7CCE7F031A411AE600447C4C /* NewFirstVisuallyNonEmptyLayoutFails.cpp in Sources */,
7CCE7F041A411AE600447C4C /* NewFirstVisuallyNonEmptyLayoutForImages.cpp in Sources */,
--- /dev/null
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#import "PlatformUtilities.h"
+#import <WebKit/WKNavigationDelegatePrivate.h>
+#import <WebKit/WKPreferences.h>
+#import <WebKit/WKProcessPoolPrivate.h>
+#import <WebKit/WKWebView.h>
+#import <WebKit/WKWebViewConfiguration.h>
+#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/_WKProcessPoolConfiguration.h>
+#import <wtf/RetainPtr.h>
+
+#if WK_API_ENABLED && PLATFORM(IOS)
+
+static bool didLayout;
+static bool didEndAnimatedResize;
+
+@interface AnimatedResizeNavigationDelegate : NSObject <WKNavigationDelegate>
+@end
+
+@implementation AnimatedResizeNavigationDelegate
+
+- (void)_webView:(WKWebView *)webView renderingProgressDidChange:(_WKRenderingProgressEvents)progressEvents
+{
+ if (progressEvents & _WKRenderingProgressEventFirstVisuallyNonEmptyLayout)
+ didLayout = true;
+}
+
+@end
+
+@interface AnimatedResizeWebView : WKWebView
+
+@end
+
+@implementation AnimatedResizeWebView
+
+- (void)_endAnimatedResize
+{
+ [super _endAnimatedResize];
+
+ didEndAnimatedResize = true;
+}
+
+@end
+
+static RetainPtr<WKWebView> animatedResizeWebView()
+{
+ RetainPtr<_WKProcessPoolConfiguration> processPoolConfiguration = [[_WKProcessPoolConfiguration alloc] init];
+ [processPoolConfiguration setIgnoreSynchronousMessagingTimeoutsForTesting:YES];
+ RetainPtr<WKProcessPool> processPool = [[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()];
+
+ RetainPtr<WKWebViewConfiguration> webViewConfiguration = [[WKWebViewConfiguration alloc] init];
+ [webViewConfiguration setProcessPool:processPool.get()];
+
+ RetainPtr<WKWebView> webView = adoptNS([[AnimatedResizeWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+
+ AnimatedResizeNavigationDelegate *navigationDelegate = [[AnimatedResizeNavigationDelegate alloc] init];
+ [webView setNavigationDelegate:navigationDelegate];
+
+ NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"blinking-div" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
+ [webView loadRequest:request];
+
+ return webView;
+}
+
+TEST(WebKit2, ResizeWithHiddenContentDoesNotHang)
+{
+ auto webView = animatedResizeWebView();
+ RetainPtr<UIWindow> window = adoptNS([[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 800, 600)]);
+ [window addSubview:webView.get()];
+ [window setHidden:NO];
+
+ TestWebKitAPI::Util::run(&didLayout);
+ didLayout = false;
+
+ for (unsigned i = 0; i < 50; i++) {
+ [webView _resizeWhileHidingContentWithUpdates:^{
+ [webView setFrame:CGRectMake(0, 0, [webView frame].size.width + 100, 400)];
+ }];
+
+ TestWebKitAPI::Util::run(&didEndAnimatedResize);
+ didEndAnimatedResize = false;
+ }
+}
+
+TEST(WebKit2, AnimatedResizeDoesNotHang)
+{
+ auto webView = animatedResizeWebView();
+ RetainPtr<UIWindow> window = adoptNS([[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 800, 600)]);
+ [window addSubview:webView.get()];
+ [window setHidden:NO];
+
+ TestWebKitAPI::Util::run(&didLayout);
+ didLayout = false;
+
+ for (unsigned i = 0; i < 50; i++) {
+ [webView _beginAnimatedResizeWithUpdates:^{
+ [webView setFrame:CGRectMake(0, 0, [webView frame].size.width + 100, 400)];
+ }];
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [webView _endAnimatedResize];
+ });
+
+ TestWebKitAPI::Util::run(&didEndAnimatedResize);
+ didEndAnimatedResize = false;
+ }
+}
+
+#endif
--- /dev/null
+<html>
+ <script>
+window.onload = function () {
+ setInterval(blink, 0);
+}
+
+var a = 0;
+
+function blink() {
+ document.getElementById("blink").style.backgroundColor = a ? "blue" : "green";
+ a = !a;
+}
+ </script>
+ <style>
+#blink {
+ width: 200px; height: 200px;
+ display: inline-block;
+}
+ </style>
+ <body>
+ <div id="blink"></div>
+ </body>
+</html>