Title: [240882] trunk
Revision
240882
Author
[email protected]
Date
2019-02-01 15:12:14 -0800 (Fri, 01 Feb 2019)

Log Message

[iOS] Consistent 1 sec hang when triggering modal alerts while handling synchronous touch events
https://bugs.webkit.org/show_bug.cgi?id=194140
<rdar://problem/47728098>

Reviewed by Tim Horton.

Source/WebKit:

Currently, the UI process hangs when attempting to synchronously present modal UI from the web process while the
UI process is waiting for sync IPC in the web process. While we have logic to generally mitigate IPC deadlock in
this scenario by dispatching the web process' sync IPC immediately with the intention of allowing the web
process to finish processing sync IPC (and consequently unblock the UI process), this fails in the case where
the sync IPC message from the web process to the UI process requires main thread execution for an arbitrary
amount of time (for instance, modal alert dialogs). In this case, we'll end up in a state where we've handled
the web process' sync IPC in the UI process, yet we can't resume execution since the web process is still
blocked.

By far the most egregious scenario in which this manifests is during synchronous gesture recognizer IPC, i.e.
grabbing position information from the UI process, and handling touch events synchronously. Luckily, these are
also cases where (1) we know sync IPC may safely time out, and (2) the presentation of modal UI from the web
process should cause the gesture recognizers to fail anyways. As such, we can mitigate these scenarios in the
web process by responding to the these pending sync IPC messages *before* sending our own sync IPC to the UI
process.

Test: fast/events/touch/ios/show-modal-alert-during-touch-start.html

* Shared/ios/InteractionInformationAtPosition.h:
(WebKit::InteractionInformationAtPosition::invalidInformation):
* Shared/ios/InteractionInformationAtPosition.mm:
(WebKit::InteractionInformationAtPosition::encode const):
(WebKit::InteractionInformationAtPosition::decode):

Add a new flag to indicate whether an interaction information response can be valid. Interaction information
cannot be valid in the case where the interaction information request was interrupted by certain sync IPC
messages from the web process.

* UIProcess/API/C/WKContextConfigurationRef.cpp:
(WKContextConfigurationIgnoreSynchronousMessagingTimeoutsForTesting):
(WKContextConfigurationSetIgnoreSynchronousMessagingTimeoutsForTesting):

Add some testing SPI to ignore sync IPC timeouts, for the purposes of testing. Rather than use the existing
Objective-C SPI in WKWebProcessPoolConfiguration, I decided to add C API plumbing for this flag, so that other
non-Cocoa ports may also support the new layout test option to ignore sync IPC timeouts.

* UIProcess/API/C/WKContextConfigurationRef.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView ensurePositionInformationIsUpToDate:]):
(-[WKContentView _positionInformationDidChange:]):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):

Cancel any pending sync IPC replies prior to sending sync IPC messages to the UI process which may result in
sync IPC deadlock, by using the new helper method, sendSyncWithDelayedReply, instead of just sendSync.

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::cancelGesturesBlockedOnSynchronousReplies):

Add a helper to cancel pending sync messages coming in from the UI process that are being called from within
gesture recognizer delegate hooks.

(WebKit::WebPage::touchEventSync):
* WebProcess/WebPage/WebPage.h:

Add a new helper, sendSyncWithDelayedReply, to be used when sending a sync IPC message to the UI process that
cannot be immediately completed upon arrival. Importantly, this cancels pending sync replies, and also passes
IPC::SendSyncOption::InformPlatformProcessWillSuspend.

* WebProcess/WebPage/WebPage.messages.in:

Change these from LegacySync to Delayed messages.

* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::getPositionInformation):

Make this sync IPC handler (as well as WebPage::touchEventSync) store the IPC reply during the scope of the
method, and invoke the stored reply at the end of the method if it wasn't interrupted due to something calling
cancelGesturesBlockedOnSynchronousReplies().

(WebKit::WebPage::positionInformation):

Refactor getPositionInformation by pulling out the logic for building an InteractionInformationAtPosition into
a separate helper.

(WebKit::WebPage::requestPositionInformation):

Tools:

* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::setShouldDismissJavaScriptAlertsAsynchronously):

Add a new TestRunner hook to make modal _javascript_ alerts dismiss asynchronously. This is used by the new layout
test to induce an IPC deadlock when presenting a modal alert during touch start.

* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::runJavaScriptAlert):

Add a client callback function for running _javascript_ alerts.

(WTR::TestController::createOtherPage):
(WTR::TestController::generateContextConfiguration const):

Add a test option to disable IPC timeouts for a layout test. This forces the test to reliably time out without
the fix in this patch.

(WTR::TestController::createWebViewWithOptions):

Plumb TestOptions to generateContextConfiguration.

(WTR::TestController::resetPreferencesToConsistentValues):
(WTR::TestController::resetStateToConsistentValues):
(WTR::updateTestOptionsFromTestHeader):
(WTR::TestController::setShouldDismissJavaScriptAlertsAsynchronously):
(WTR::TestController::handleJavaScriptAlert):
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
* WebKitTestRunner/TestOptions.h:
(WTR::TestOptions::hasSameInitializationOptions const):

LayoutTests:

Add a test that induces sync IPC deadlock by presenting a modal alert while handling touch start. This test
forces sync IPC timeouts to be disabled, and passes if we do not time out while handling a touch.

* fast/events/touch/ios/show-modal-alert-during-touch-start-expected.txt: Added.
* fast/events/touch/ios/show-modal-alert-during-touch-start.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (240881 => 240882)


--- trunk/LayoutTests/ChangeLog	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/LayoutTests/ChangeLog	2019-02-01 23:12:14 UTC (rev 240882)
@@ -1,3 +1,17 @@
+2019-02-01  Wenson Hsieh  <[email protected]>
+
+        [iOS] Consistent 1 sec hang when triggering modal alerts while handling synchronous touch events
+        https://bugs.webkit.org/show_bug.cgi?id=194140
+        <rdar://problem/47728098>
+
+        Reviewed by Tim Horton.
+
+        Add a test that induces sync IPC deadlock by presenting a modal alert while handling touch start. This test
+        forces sync IPC timeouts to be disabled, and passes if we do not time out while handling a touch.
+
+        * fast/events/touch/ios/show-modal-alert-during-touch-start-expected.txt: Added.
+        * fast/events/touch/ios/show-modal-alert-during-touch-start.html: Added.
+
 2019-02-01  Antoine Quint  <[email protected]>
 
         Dispatch pointercancel events when content is panned or zoomed on iOS

Added: trunk/LayoutTests/fast/events/touch/ios/show-modal-alert-during-touch-start-expected.txt (0 => 240882)


--- trunk/LayoutTests/fast/events/touch/ios/show-modal-alert-during-touch-start-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/show-modal-alert-during-touch-start-expected.txt	2019-02-01 23:12:14 UTC (rev 240882)
@@ -0,0 +1,3 @@
+ALERT: This is a modal alert.
+Tap to show an alert
+This test verifies that presenting a modal alert while handling a synchronous touch event doesn't cause the application process to hang. To verify manually, tap the red area above, and check that the _javascript_ alert is presented with no significant delay.

Added: trunk/LayoutTests/fast/events/touch/ios/show-modal-alert-during-touch-start.html (0 => 240882)


--- trunk/LayoutTests/fast/events/touch/ios/show-modal-alert-during-touch-start.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/show-modal-alert-during-touch-start.html	2019-02-01 23:12:14 UTC (rev 240882)
@@ -0,0 +1,38 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true, ignoreSynchronousMessagingTimeoutsForTesting=true ] -->
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+<script src=""
+<style>
+body, html {
+    width: 100%;
+    height: 100%;
+    margin: 0;
+}
+
+#target {
+    background-color: tomato;
+    color: white;
+    width: 100%;
+    height: 200px;
+    text-align: center;
+    font-size: 20px;
+}
+</style>
+</head>
+<body>
+<div id="target">Tap to show an alert</div>
+<p>This test verifies that presenting a modal alert while handling a synchronous touch event doesn't cause the application process to hang. To verify manually, tap the red area above, and check that the _javascript_ alert is presented with no significant delay.</p>
+<script>
+if (window.testRunner) {
+    testRunner.setShouldDismissJavaScriptAlertsAsynchronously(true);
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+target.addEventListener("touchstart", () => alert("This is a modal alert."));
+target.addEventListener("touchend", () => testRunner.notifyDone());
+addEventListener("load", async () => await UIHelper.activateAt(100, 100));
+</script>
+</body>
+</html>

Modified: trunk/Source/WebKit/ChangeLog (240881 => 240882)


--- trunk/Source/WebKit/ChangeLog	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Source/WebKit/ChangeLog	2019-02-01 23:12:14 UTC (rev 240882)
@@ -1,3 +1,94 @@
+2019-02-01  Wenson Hsieh  <[email protected]>
+
+        [iOS] Consistent 1 sec hang when triggering modal alerts while handling synchronous touch events
+        https://bugs.webkit.org/show_bug.cgi?id=194140
+        <rdar://problem/47728098>
+
+        Reviewed by Tim Horton.
+
+        Currently, the UI process hangs when attempting to synchronously present modal UI from the web process while the
+        UI process is waiting for sync IPC in the web process. While we have logic to generally mitigate IPC deadlock in
+        this scenario by dispatching the web process' sync IPC immediately with the intention of allowing the web
+        process to finish processing sync IPC (and consequently unblock the UI process), this fails in the case where
+        the sync IPC message from the web process to the UI process requires main thread execution for an arbitrary
+        amount of time (for instance, modal alert dialogs). In this case, we'll end up in a state where we've handled
+        the web process' sync IPC in the UI process, yet we can't resume execution since the web process is still
+        blocked.
+
+        By far the most egregious scenario in which this manifests is during synchronous gesture recognizer IPC, i.e.
+        grabbing position information from the UI process, and handling touch events synchronously. Luckily, these are
+        also cases where (1) we know sync IPC may safely time out, and (2) the presentation of modal UI from the web
+        process should cause the gesture recognizers to fail anyways. As such, we can mitigate these scenarios in the
+        web process by responding to the these pending sync IPC messages *before* sending our own sync IPC to the UI
+        process.
+
+        Test: fast/events/touch/ios/show-modal-alert-during-touch-start.html
+
+        * Shared/ios/InteractionInformationAtPosition.h:
+        (WebKit::InteractionInformationAtPosition::invalidInformation):
+        * Shared/ios/InteractionInformationAtPosition.mm:
+        (WebKit::InteractionInformationAtPosition::encode const):
+        (WebKit::InteractionInformationAtPosition::decode):
+
+        Add a new flag to indicate whether an interaction information response can be valid. Interaction information
+        cannot be valid in the case where the interaction information request was interrupted by certain sync IPC
+        messages from the web process.
+
+        * UIProcess/API/C/WKContextConfigurationRef.cpp:
+        (WKContextConfigurationIgnoreSynchronousMessagingTimeoutsForTesting):
+        (WKContextConfigurationSetIgnoreSynchronousMessagingTimeoutsForTesting):
+
+        Add some testing SPI to ignore sync IPC timeouts, for the purposes of testing. Rather than use the existing
+        Objective-C SPI in WKWebProcessPoolConfiguration, I decided to add C API plumbing for this flag, so that other
+        non-Cocoa ports may also support the new layout test option to ignore sync IPC timeouts.
+
+        * UIProcess/API/C/WKContextConfigurationRef.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView ensurePositionInformationIsUpToDate:]):
+        (-[WKContentView _positionInformationDidChange:]):
+        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+        (WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
+        (WebKit::WebChromeClient::runJavaScriptAlert):
+        (WebKit::WebChromeClient::runJavaScriptConfirm):
+        (WebKit::WebChromeClient::runJavaScriptPrompt):
+        (WebKit::WebChromeClient::print):
+        (WebKit::WebChromeClient::exceededDatabaseQuota):
+        (WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
+
+        Cancel any pending sync IPC replies prior to sending sync IPC messages to the UI process which may result in
+        sync IPC deadlock, by using the new helper method, sendSyncWithDelayedReply, instead of just sendSync.
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::cancelGesturesBlockedOnSynchronousReplies):
+
+        Add a helper to cancel pending sync messages coming in from the UI process that are being called from within
+        gesture recognizer delegate hooks.
+
+        (WebKit::WebPage::touchEventSync):
+        * WebProcess/WebPage/WebPage.h:
+
+        Add a new helper, sendSyncWithDelayedReply, to be used when sending a sync IPC message to the UI process that
+        cannot be immediately completed upon arrival. Importantly, this cancels pending sync replies, and also passes
+        IPC::SendSyncOption::InformPlatformProcessWillSuspend.
+
+        * WebProcess/WebPage/WebPage.messages.in:
+
+        Change these from LegacySync to Delayed messages.
+
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::getPositionInformation):
+
+        Make this sync IPC handler (as well as WebPage::touchEventSync) store the IPC reply during the scope of the
+        method, and invoke the stored reply at the end of the method if it wasn't interrupted due to something calling
+        cancelGesturesBlockedOnSynchronousReplies().
+
+        (WebKit::WebPage::positionInformation):
+
+        Refactor getPositionInformation by pulling out the logic for building an InteractionInformationAtPosition into
+        a separate helper.
+
+        (WebKit::WebPage::requestPositionInformation):
+
 2019-02-01  David Quesada  <[email protected]>
 
         Network Process crash when resuming downloads: '-[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance %p'

Modified: trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.h (240881 => 240882)


--- trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.h	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.h	2019-02-01 23:12:14 UTC (rev 240882)
@@ -39,8 +39,16 @@
 namespace WebKit {
 
 struct InteractionInformationAtPosition {
+    static InteractionInformationAtPosition invalidInformation()
+    {
+        InteractionInformationAtPosition response;
+        response.canBeValid = false;
+        return response;
+    }
+
     InteractionInformationRequest request;
 
+    bool canBeValid { true };
     bool nodeAtPositionIsFocusedElement { false };
 #if ENABLE(DATA_INTERACTION)
     bool hasSelectionAtPosition { false };

Modified: trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.mm (240881 => 240882)


--- trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.mm	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.mm	2019-02-01 23:12:14 UTC (rev 240882)
@@ -43,6 +43,7 @@
 {
     encoder << request;
 
+    encoder << canBeValid;
     encoder << nodeAtPositionIsFocusedElement;
 #if ENABLE(DATA_INTERACTION)
     encoder << hasSelectionAtPosition;
@@ -89,6 +90,9 @@
     if (!decoder.decode(result.request))
         return false;
 
+    if (!decoder.decode(result.canBeValid))
+        return false;
+
     if (!decoder.decode(result.nodeAtPositionIsFocusedElement))
         return false;
 

Modified: trunk/Source/WebKit/UIProcess/API/C/WKContextConfigurationRef.cpp (240881 => 240882)


--- trunk/Source/WebKit/UIProcess/API/C/WKContextConfigurationRef.cpp	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Source/WebKit/UIProcess/API/C/WKContextConfigurationRef.cpp	2019-02-01 23:12:14 UTC (rev 240882)
@@ -138,6 +138,16 @@
     toImpl(configuration)->setFullySynchronousModeIsAllowedForTesting(allowed);
 }
 
+bool WKContextConfigurationIgnoreSynchronousMessagingTimeoutsForTesting(WKContextConfigurationRef configuration)
+{
+    return toImpl(configuration)->ignoreSynchronousMessagingTimeoutsForTesting();
+}
+
+void WKContextConfigurationSetIgnoreSynchronousMessagingTimeoutsForTesting(WKContextConfigurationRef configuration, bool ignore)
+{
+    toImpl(configuration)->setIgnoreSynchronousMessagingTimeoutsForTesting(ignore);
+}
+
 WKArrayRef WKContextConfigurationCopyOverrideLanguages(WKContextConfigurationRef configuration)
 {
     return toAPI(&API::Array::createStringArray(toImpl(configuration)->overrideLanguages()).leakRef());

Modified: trunk/Source/WebKit/UIProcess/API/C/WKContextConfigurationRef.h (240881 => 240882)


--- trunk/Source/WebKit/UIProcess/API/C/WKContextConfigurationRef.h	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Source/WebKit/UIProcess/API/C/WKContextConfigurationRef.h	2019-02-01 23:12:14 UTC (rev 240882)
@@ -63,6 +63,9 @@
 WK_EXPORT bool WKContextConfigurationFullySynchronousModeIsAllowedForTesting(WKContextConfigurationRef configuration);
 WK_EXPORT void WKContextConfigurationSetFullySynchronousModeIsAllowedForTesting(WKContextConfigurationRef configuration, bool allowed);
 
+WK_EXPORT bool WKContextConfigurationIgnoreSynchronousMessagingTimeoutsForTesting(WKContextConfigurationRef configuration);
+WK_EXPORT void WKContextConfigurationSetIgnoreSynchronousMessagingTimeoutsForTesting(WKContextConfigurationRef configuration, bool ignore);
+
 WK_EXPORT WKArrayRef WKContextConfigurationCopyOverrideLanguages(WKContextConfigurationRef configuration);
 WK_EXPORT void WKContextConfigurationSetOverrideLanguages(WKContextConfigurationRef configuration, WKArrayRef overrideLanguages);
 

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (240881 => 240882)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2019-02-01 23:12:14 UTC (rev 240882)
@@ -1763,7 +1763,8 @@
     if ([self _hasValidOutstandingPositionInformationRequest:request])
         return connection->waitForAndDispatchImmediately<Messages::WebPageProxy::DidReceivePositionInformation>(_page->pageID(), 1_s, IPC::WaitForOption::InterruptWaitingIfSyncMessageArrives);
 
-    _hasValidPositionInformation = _page->process().sendSync(Messages::WebPage::GetPositionInformation(request), Messages::WebPage::GetPositionInformation::Reply(_positionInformation), _page->pageID(), 1_s);
+    bool receivedResponse = _page->process().sendSync(Messages::WebPage::GetPositionInformation(request), Messages::WebPage::GetPositionInformation::Reply(_positionInformation), _page->pageID(), 1_s);
+    _hasValidPositionInformation = receivedResponse && _positionInformation.canBeValid;
     
     // FIXME: We need to clean up these handlers in the event that we are not able to collect data, or if the WebProcess crashes.
     if (_hasValidPositionInformation)
@@ -2284,7 +2285,7 @@
     newInfo.mergeCompatibleOptionalInformation(_positionInformation);
 
     _positionInformation = newInfo;
-    _hasValidPositionInformation = YES;
+    _hasValidPositionInformation = _positionInformation.canBeValid;
     if (_actionSheetAssistant)
         [_actionSheetAssistant updateSheetPosition];
     [self _invokeAndRemovePendingHandlersValidForCurrentPositionInformation];

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp (240881 => 240882)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp	2019-02-01 23:12:14 UTC (rev 240882)
@@ -405,7 +405,7 @@
 
     HangDetectionDisabler hangDetectionDisabler;
 
-    if (!WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::RunBeforeUnloadConfirmPanel(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message), Messages::WebPageProxy::RunBeforeUnloadConfirmPanel::Reply(shouldClose), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend))
+    if (!m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::RunBeforeUnloadConfirmPanel(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message), Messages::WebPageProxy::RunBeforeUnloadConfirmPanel::Reply(shouldClose)))
         return false;
 
     return shouldClose;
@@ -451,7 +451,7 @@
 
     HangDetectionDisabler hangDetectionDisabler;
 
-    WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::RunJavaScriptAlert(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), alertText), Messages::WebPageProxy::RunJavaScriptAlert::Reply(), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend);
+    m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::RunJavaScriptAlert(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), alertText), Messages::WebPageProxy::RunJavaScriptAlert::Reply());
 }
 
 bool WebChromeClient::runJavaScriptConfirm(Frame& frame, const String& message)
@@ -468,7 +468,7 @@
     HangDetectionDisabler hangDetectionDisabler;
 
     bool result = false;
-    if (!WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::RunJavaScriptConfirm(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message), Messages::WebPageProxy::RunJavaScriptConfirm::Reply(result), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend))
+    if (!m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::RunJavaScriptConfirm(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message), Messages::WebPageProxy::RunJavaScriptConfirm::Reply(result)))
         return false;
 
     return result;
@@ -487,7 +487,7 @@
 
     HangDetectionDisabler hangDetectionDisabler;
 
-    if (!WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::RunJavaScriptPrompt(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message, defaultValue), Messages::WebPageProxy::RunJavaScriptPrompt::Reply(result), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend))
+    if (!m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::RunJavaScriptPrompt(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message, defaultValue), Messages::WebPageProxy::RunJavaScriptPrompt::Reply(result)))
         return false;
 
     return !result.isNull();
@@ -714,7 +714,7 @@
     }
 #endif
 
-    m_page.sendSync(Messages::WebPageProxy::PrintFrame(webFrame->frameID()), Messages::WebPageProxy::PrintFrame::Reply(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend);
+    m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::PrintFrame(webFrame->frameID()), Messages::WebPageProxy::PrintFrame::Reply());
 }
 
 void WebChromeClient::exceededDatabaseQuota(Frame& frame, const String& databaseName, DatabaseDetails details)
@@ -731,11 +731,8 @@
     auto securityOrigin = API::SecurityOrigin::create(SecurityOriginData::fromDatabaseIdentifier(originData.databaseIdentifier())->securityOrigin());
     newQuota = m_page.injectedBundleUIClient().didExceedDatabaseQuota(&m_page, securityOrigin.ptr(), databaseName, details.displayName(), currentQuota, currentOriginUsage, details.currentUsage(), details.expectedUsage());
 
-    if (!newQuota) {
-        WebProcess::singleton().parentProcessConnection()->sendSync(
-            Messages::WebPageProxy::ExceededDatabaseQuota(webFrame->frameID(), originData.databaseIdentifier(), databaseName, details.displayName(), currentQuota, currentOriginUsage, details.currentUsage(), details.expectedUsage()),
-            Messages::WebPageProxy::ExceededDatabaseQuota::Reply(newQuota), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend);
-    }
+    if (!newQuota)
+        m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::ExceededDatabaseQuota(webFrame->frameID(), originData.databaseIdentifier(), databaseName, details.displayName(), currentQuota, currentOriginUsage, details.currentUsage(), details.expectedUsage()), Messages::WebPageProxy::ExceededDatabaseQuota::Reply(newQuota));
 
     tracker.setQuota(originData, newQuota);
 }
@@ -757,9 +754,7 @@
         return;
 
     uint64_t newQuota = 0;
-    WebProcess::singleton().parentProcessConnection()->sendSync(
-        Messages::WebPageProxy::ReachedApplicationCacheOriginQuota(origin.data().databaseIdentifier(), currentQuota, totalBytesNeeded),
-        Messages::WebPageProxy::ReachedApplicationCacheOriginQuota::Reply(newQuota), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend);
+    m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::ReachedApplicationCacheOriginQuota(origin.data().databaseIdentifier(), currentQuota, totalBytesNeeded), Messages::WebPageProxy::ReachedApplicationCacheOriginQuota::Reply(newQuota));
 
     cacheStorage.storeUpdatedQuotaForOrigin(&origin, newQuota);
 }

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (240881 => 240882)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2019-02-01 23:12:14 UTC (rev 240882)
@@ -262,6 +262,8 @@
 #endif
 
 #if PLATFORM(IOS_FAMILY)
+#include "InteractionInformationAtPosition.h"
+#include "InteractionInformationRequest.h"
 #include "RemoteLayerTreeDrawingArea.h"
 #include <CoreGraphics/CoreGraphics.h>
 #include <WebCore/Icon.h>
@@ -2725,6 +2727,19 @@
     send(Messages::WebPageProxy::FontAttributesCallback(attributes, callbackID));
 }
 
+void WebPage::cancelGesturesBlockedOnSynchronousReplies()
+{
+#if ENABLE(IOS_TOUCH_EVENTS)
+    if (auto reply = WTFMove(m_pendingSynchronousTouchEventReply))
+        reply(true);
+#endif
+
+#if PLATFORM(IOS_FAMILY)
+    if (auto reply = WTFMove(m_pendingSynchronousPositionInformationReply))
+        reply(InteractionInformationAtPosition::invalidInformation());
+#endif
+}
+
 #if ENABLE(TOUCH_EVENTS)
 static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page)
 {
@@ -2746,13 +2761,19 @@
     updatePotentialTapSecurityOrigin(touchEvent, handled);
 }
 
-void WebPage::touchEventSync(const WebTouchEvent& touchEvent, bool& handled)
+void WebPage::touchEventSync(const WebTouchEvent& touchEvent, CompletionHandler<void(bool)>&& reply)
 {
+    m_pendingSynchronousTouchEventReply = WTFMove(reply);
+
     EventDispatcher::TouchEventQueue queuedEvents;
     WebProcess::singleton().eventDispatcher().getQueuedTouchEventsForPage(*this, queuedEvents);
     dispatchAsynchronousTouchEvents(queuedEvents);
 
+    bool handled = true;
     dispatchTouchEvent(touchEvent, handled);
+
+    if (auto reply = WTFMove(m_pendingSynchronousTouchEventReply))
+        reply(handled);
 }
 
 void WebPage::updatePotentialTapSecurityOrigin(const WebTouchEvent& touchEvent, bool wasHandled)

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (240881 => 240882)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2019-02-01 23:12:14 UTC (rev 240882)
@@ -647,7 +647,7 @@
     void syncApplyAutocorrection(const String& correction, const String& originalText, bool& correctionApplied);
     void requestAutocorrectionContext(CallbackID);
     void getAutocorrectionContext(String& beforeText, String& markedText, String& selectedText, String& afterText, uint64_t& location, uint64_t& length);
-    void getPositionInformation(const InteractionInformationRequest&, InteractionInformationAtPosition&);
+    void getPositionInformation(const InteractionInformationRequest&, CompletionHandler<void(InteractionInformationAtPosition&&)>&&);
     void requestPositionInformation(const InteractionInformationRequest&);
     void startInteractionWithElementAtPosition(const WebCore::IntPoint&);
     void stopInteraction();
@@ -1137,6 +1137,13 @@
 
     void didReceiveWebPageMessage(IPC::Connection&, IPC::Decoder&);
 
+    template<typename T>
+    bool sendSyncWithDelayedReply(T&& message, typename T::Reply&& reply)
+    {
+        cancelGesturesBlockedOnSynchronousReplies();
+        return sendSync(WTFMove(message), WTFMove(reply), m_pageID, Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend);
+    }
+
 private:
     WebPage(uint64_t pageID, WebPageCreationParameters&&);
 
@@ -1178,6 +1185,9 @@
     void resetTextAutosizing();
     WebCore::VisiblePosition visiblePositionInFocusedNodeForPoint(const WebCore::Frame&, const WebCore::IntPoint&, bool isInteractingWithFocusedElement);
     RefPtr<WebCore::Range> rangeForGranularityAtPoint(WebCore::Frame&, const WebCore::IntPoint&, uint32_t granularity, bool isInteractingWithFocusedElement);
+
+    void sendPositionInformation(InteractionInformationAtPosition&&);
+    InteractionInformationAtPosition positionInformation(const InteractionInformationRequest&);
 #endif
 
 #if PLATFORM(IOS_FAMILY) && ENABLE(DATA_INTERACTION)
@@ -1234,7 +1244,7 @@
     void keyEvent(const WebKeyboardEvent&);
 
 #if ENABLE(IOS_TOUCH_EVENTS)
-    void touchEventSync(const WebTouchEvent&, bool& handled);
+    void touchEventSync(const WebTouchEvent&, CompletionHandler<void(bool)>&&);
     void updatePotentialTapSecurityOrigin(const WebTouchEvent&, bool wasHandled);
 #elif ENABLE(TOUCH_EVENTS)
     void touchEvent(const WebTouchEvent&);
@@ -1493,6 +1503,8 @@
 
     bool canShowMIMEType(const String&, const Function<bool(const String&, WebCore::PluginData::AllowedPluginTypes)>& supportsPlugin) const;
 
+    void cancelGesturesBlockedOnSynchronousReplies();
+
     uint64_t m_pageID;
 
     std::unique_ptr<WebCore::Page> m_page;
@@ -1699,6 +1711,10 @@
     RefPtr<WebCore::Element> m_focusedElement;
     bool m_hasPendingBlurNotification { false };
     bool m_hasPendingEditorStateUpdate { false };
+
+#if ENABLE(IOS_TOUCH_EVENTS)
+    CompletionHandler<void(bool)> m_pendingSynchronousTouchEventReply;
+#endif
     
 #if PLATFORM(IOS_FAMILY)
     RefPtr<WebCore::Range> m_currentWordRange;
@@ -1744,6 +1760,8 @@
     Optional<DynamicViewportSizeUpdateID> m_pendingDynamicViewportSizeUpdateID;
     double m_lastTransactionPageScaleFactor { 0 };
     uint64_t m_lastTransactionIDWithScaleChange { 0 };
+
+    CompletionHandler<void(InteractionInformationAtPosition&&)> m_pendingSynchronousPositionInformationReply;
 #endif
 
     WebCore::Timer m_layerVolatilityTimer;

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (240881 => 240882)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2019-02-01 23:12:14 UTC (rev 240882)
@@ -80,7 +80,7 @@
     SyncApplyAutocorrection(String correction, String originalText) -> (bool autocorrectionApplied) LegacySync
     RequestAutocorrectionContext(WebKit::CallbackID callbackID)
     GetAutocorrectionContext() -> (String beforeContext, String markedText, String selectedText, String afterContext, uint64_t location, uint64_t length) LegacySync
-    GetPositionInformation(struct WebKit::InteractionInformationRequest request) -> (struct WebKit::InteractionInformationAtPosition information) LegacySync
+    GetPositionInformation(struct WebKit::InteractionInformationRequest request) -> (struct WebKit::InteractionInformationAtPosition information) Delayed
     RequestPositionInformation(struct WebKit::InteractionInformationRequest request)
     StartInteractionWithElementAtPosition(WebCore::IntPoint point)
     StopInteraction()
@@ -121,7 +121,7 @@
 #endif
 
 #if ENABLE(IOS_TOUCH_EVENTS)
-    TouchEventSync(WebKit::WebTouchEvent event) -> (bool handled) LegacySync
+    TouchEventSync(WebKit::WebTouchEvent event) -> (bool handled) Delayed
 #endif
 #if !ENABLE(IOS_TOUCH_EVENTS) && ENABLE(TOUCH_EVENTS)
     TouchEvent(WebKit::WebTouchEvent event)

Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (240881 => 240882)


--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2019-02-01 23:12:14 UTC (rev 240882)
@@ -2085,8 +2085,19 @@
     return node.isContentEditable();
 }
 
-void WebPage::getPositionInformation(const InteractionInformationRequest& request, InteractionInformationAtPosition& info)
+void WebPage::getPositionInformation(const InteractionInformationRequest& request, CompletionHandler<void(InteractionInformationAtPosition&&)>&& reply)
 {
+    m_pendingSynchronousPositionInformationReply = WTFMove(reply);
+
+    auto information = positionInformation(request);
+
+    if (auto reply = WTFMove(m_pendingSynchronousPositionInformationReply))
+        reply(WTFMove(information));
+}
+
+InteractionInformationAtPosition WebPage::positionInformation(const InteractionInformationRequest& request)
+{
+    InteractionInformationAtPosition info;
     info.request = request;
 
     FloatPoint adjustedPoint;
@@ -2262,14 +2273,13 @@
     info.hasSelectionAtPosition = m_page->hasSelectionAtPosition(adjustedPoint);
 #endif
     info.adjustedPointForNodeRespondingToClickEvents = adjustedPoint;
+
+    return info;
 }
 
 void WebPage::requestPositionInformation(const InteractionInformationRequest& request)
 {
-    InteractionInformationAtPosition info;
-
-    getPositionInformation(request, info);
-    send(Messages::WebPageProxy::DidReceivePositionInformation(info));
+    send(Messages::WebPageProxy::DidReceivePositionInformation(positionInformation(request)));
 }
 
 void WebPage::startInteractionWithElementAtPosition(const WebCore::IntPoint& point)

Modified: trunk/Tools/ChangeLog (240881 => 240882)


--- trunk/Tools/ChangeLog	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Tools/ChangeLog	2019-02-01 23:12:14 UTC (rev 240882)
@@ -1,3 +1,45 @@
+2019-02-01  Wenson Hsieh  <[email protected]>
+
+        [iOS] Consistent 1 sec hang when triggering modal alerts while handling synchronous touch events
+        https://bugs.webkit.org/show_bug.cgi?id=194140
+        <rdar://problem/47728098>
+
+        Reviewed by Tim Horton.
+
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::setShouldDismissJavaScriptAlertsAsynchronously):
+
+        Add a new TestRunner hook to make modal _javascript_ alerts dismiss asynchronously. This is used by the new layout
+        test to induce an IPC deadlock when presenting a modal alert during touch start.
+
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::runJavaScriptAlert):
+
+        Add a client callback function for running _javascript_ alerts.
+
+        (WTR::TestController::createOtherPage):
+        (WTR::TestController::generateContextConfiguration const):
+
+        Add a test option to disable IPC timeouts for a layout test. This forces the test to reliably time out without
+        the fix in this patch.
+
+        (WTR::TestController::createWebViewWithOptions):
+
+        Plumb TestOptions to generateContextConfiguration.
+
+        (WTR::TestController::resetPreferencesToConsistentValues):
+        (WTR::TestController::resetStateToConsistentValues):
+        (WTR::updateTestOptionsFromTestHeader):
+        (WTR::TestController::setShouldDismissJavaScriptAlertsAsynchronously):
+        (WTR::TestController::handleJavaScriptAlert):
+        * WebKitTestRunner/TestController.h:
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+        * WebKitTestRunner/TestOptions.h:
+        (WTR::TestOptions::hasSameInitializationOptions const):
+
 2019-02-01  Chris Dumez  <[email protected]>
 
         REGRESSION: Flaky ASSERTION FAILED: m_uncommittedState.state == State::Committed on http/tests/cookies/same-site/fetch-after-top-level-navigation-initiated-from-iframe-in-cross-origin-page.html

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl (240881 => 240882)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl	2019-02-01 23:12:14 UTC (rev 240882)
@@ -329,6 +329,9 @@
     // Open panel
     void setOpenPanelFiles(object filesArray);
 
+    // Modal alerts
+    void setShouldDismissJavaScriptAlertsAsynchronously(boolean value);
+
     void setWebRTCMDNSICECandidatesEnabled(boolean value);
     void setWebRTCUnifiedPlanEnabled(boolean value);
     void setCustomUserAgent(DOMString userAgent);

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp (240881 => 240882)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp	2019-02-01 23:12:14 UTC (rev 240882)
@@ -2715,4 +2715,11 @@
     return WKUInt64GetValue(adoptWK(static_cast<WKUInt64Ref>(returnData)).get());
 }
 
+void TestRunner::setShouldDismissJavaScriptAlertsAsynchronously(bool shouldDismissAsynchronously)
+{
+    WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ShouldDismissJavaScriptAlertsAsynchronously"));
+    WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(shouldDismissAsynchronously));
+    WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
+}
+
 } // namespace WTR

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h (240881 => 240882)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h	2019-02-01 23:12:14 UTC (rev 240882)
@@ -448,6 +448,9 @@
     // Open panel
     void setOpenPanelFiles(JSValueRef);
 
+    // Modal alerts
+    void setShouldDismissJavaScriptAlertsAsynchronously(bool);
+
     void terminateNetworkProcess();
     void terminateServiceWorkerProcess();
 

Modified: trunk/Tools/WebKitTestRunner/TestController.cpp (240881 => 240882)


--- trunk/Tools/WebKitTestRunner/TestController.cpp	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Tools/WebKitTestRunner/TestController.cpp	2019-02-01 23:12:14 UTC (rev 240882)
@@ -239,6 +239,11 @@
     TestController::singleton().handleUserMediaPermissionRequest(frame, userMediaDocumentOrigin, topLevelDocumentOrigin, permissionRequest);
 }
 
+static void runJavaScriptAlert(WKPageRef page, WKStringRef alertText, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptAlertResultListenerRef listener, const void *clientInfo)
+{
+    TestController::singleton().handleJavaScriptAlert(listener);
+}
+
 static void checkUserMediaPermissionForOrigin(WKPageRef, WKFrameRef frame, WKSecurityOriginRef userMediaDocumentOrigin, WKSecurityOriginRef topLevelDocumentOrigin, WKUserMediaPermissionCheckRef checkRequest, const void*)
 {
     TestController::singleton().handleCheckOfUserMediaPermissionForOrigin(frame, userMediaDocumentOrigin, topLevelDocumentOrigin, checkRequest);
@@ -326,7 +331,7 @@
         0, // runJavaScriptPrompt
         0, // mediaSessionMetadataDidChange
         createOtherPage,
-        0, // runJavaScriptAlert
+        runJavaScriptAlert,
         0, // runJavaScriptConfirm
         0, // runJavaScriptPrompt
         checkUserMediaPermissionForOrigin,
@@ -442,11 +447,12 @@
     m_pageGroup.adopt(WKPageGroupCreateWithIdentifier(pageGroupIdentifier.get()));
 }
 
-WKRetainPtr<WKContextConfigurationRef> TestController::generateContextConfiguration() const
+WKRetainPtr<WKContextConfigurationRef> TestController::generateContextConfiguration(const TestOptions& options) const
 {
     auto configuration = adoptWK(WKContextConfigurationCreate());
     WKContextConfigurationSetInjectedBundlePath(configuration.get(), injectedBundlePath());
     WKContextConfigurationSetFullySynchronousModeIsAllowedForTesting(configuration.get(), true);
+    WKContextConfigurationSetIgnoreSynchronousMessagingTimeoutsForTesting(configuration.get(), options.ignoreSynchronousMessagingTimeoutsForTesting);
 
     if (const char* dumpRenderTreeTemp = libraryPathForTesting()) {
         String temporaryFolder = String::fromUTF8(dumpRenderTreeTemp);
@@ -534,7 +540,7 @@
 
 void TestController::createWebViewWithOptions(const TestOptions& options)
 {
-    auto contextConfiguration = generateContextConfiguration();
+    auto contextConfiguration = generateContextConfiguration(options);
 
     WKRetainPtr<WKMutableArrayRef> overrideLanguages = adoptWK(WKMutableArrayCreate());
     for (auto& language : options.overrideLanguages)
@@ -614,7 +620,7 @@
         0, // runJavaScriptPrompt
         0, // mediaSessionMetadataDidChange
         createOtherPage,
-        0, // runJavaScriptAlert
+        runJavaScriptAlert,
         0, // runJavaScriptConfirm
         0, // runJavaScriptPrompt
         checkUserMediaPermissionForOrigin,
@@ -824,8 +830,6 @@
 
     WKPreferencesSetWebSQLDisabled(preferences, false);
 
-    m_serverTrustEvaluationCallbackCallsCount = 0;
-
     platformResetPreferencesToConsistentValues();
 }
 
@@ -957,6 +961,8 @@
     statisticsResetToConsistentState();
 
     m_didReceiveServerRedirectForProvisionalNavigation = false;
+    m_serverTrustEvaluationCallbackCallsCount = 0;
+    m_shouldDismissJavaScriptAlertsAsynchronously = false;
 
     // Reset main page back to about:blank
     m_doneResetting = false;
@@ -1278,6 +1284,8 @@
             testOptions.enableUndoManagerAPI = parseBooleanTestHeaderValue(value);
         else if (key == "contentInset.top")
             testOptions.contentInsetTop = std::stod(value);
+        else if (key == "ignoreSynchronousMessagingTimeoutsForTesting")
+            testOptions.ignoreSynchronousMessagingTimeoutsForTesting = parseBooleanTestHeaderValue(value);
         pairStart = pairEnd + 1;
     }
 }
@@ -2330,6 +2338,25 @@
     m_isUserMediaPermissionSet = false;
 }
 
+void TestController::setShouldDismissJavaScriptAlertsAsynchronously(bool value)
+{
+    m_shouldDismissJavaScriptAlertsAsynchronously = value;
+}
+
+void TestController::handleJavaScriptAlert(WKPageRunJavaScriptAlertResultListenerRef listener)
+{
+    if (!m_shouldDismissJavaScriptAlertsAsynchronously) {
+        WKPageRunJavaScriptAlertResultListenerCall(listener);
+        return;
+    }
+
+    WKRetain(listener);
+    callOnMainThread([listener] {
+        WKPageRunJavaScriptAlertResultListenerCall(listener);
+        WKRelease(listener);
+    });
+}
+
 class OriginSettings : public RefCounted<OriginSettings> {
 public:
     explicit OriginSettings()

Modified: trunk/Tools/WebKitTestRunner/TestController.h (240881 => 240882)


--- trunk/Tools/WebKitTestRunner/TestController.h	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Tools/WebKitTestRunner/TestController.h	2019-02-01 23:12:14 UTC (rev 240882)
@@ -284,9 +284,12 @@
     bool canDoServerTrustEvaluationInNetworkProcess() const;
     uint64_t serverTrustEvaluationCallbackCallsCount() const { return m_serverTrustEvaluationCallbackCallsCount; }
 
+    void setShouldDismissJavaScriptAlertsAsynchronously(bool);
+    void handleJavaScriptAlert(WKPageRunJavaScriptAlertResultListenerRef);
+
 private:
     WKRetainPtr<WKPageConfigurationRef> generatePageConfiguration(WKContextConfigurationRef);
-    WKRetainPtr<WKContextConfigurationRef> generateContextConfiguration() const;
+    WKRetainPtr<WKContextConfigurationRef> generateContextConfiguration(const TestOptions&) const;
     void initialize(int argc, const char* argv[]);
     void createWebViewWithOptions(const TestOptions&);
     void run();
@@ -539,6 +542,7 @@
     HashMap<uint64_t, AbandonedDocumentInfo> m_abandonedDocumentInfo;
 
     uint64_t m_serverTrustEvaluationCallbackCallsCount { 0 };
+    bool m_shouldDismissJavaScriptAlertsAsynchronously { false };
 };
 
 struct TestCommand {

Modified: trunk/Tools/WebKitTestRunner/TestInvocation.cpp (240881 => 240882)


--- trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2019-02-01 23:12:14 UTC (rev 240882)
@@ -1539,6 +1539,13 @@
         return result;
     }
 
+    if (WKStringIsEqualToUTF8CString(messageName, "ShouldDismissJavaScriptAlertsAsynchronously")) {
+        ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
+        WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
+        TestController::singleton().setShouldDismissJavaScriptAlertsAsynchronously(WKBooleanGetValue(value));
+        return nullptr;
+    }
+
     ASSERT_NOT_REACHED();
     return nullptr;
 }

Modified: trunk/Tools/WebKitTestRunner/TestOptions.h (240881 => 240882)


--- trunk/Tools/WebKitTestRunner/TestOptions.h	2019-02-01 23:08:48 UTC (rev 240881)
+++ trunk/Tools/WebKitTestRunner/TestOptions.h	2019-02-01 23:12:14 UTC (rev 240882)
@@ -68,6 +68,7 @@
     bool enableEditableImages { false };
     bool editable { false };
     bool enableUndoManagerAPI { false };
+    bool ignoreSynchronousMessagingTimeoutsForTesting { false };
 
     double contentInsetTop { 0 };
 
@@ -116,7 +117,8 @@
             || enableEditableImages != options.enableEditableImages
             || editable != options.editable
             || enableUndoManagerAPI != options.enableUndoManagerAPI
-            || contentInsetTop != options.contentInsetTop)
+            || contentInsetTop != options.contentInsetTop
+            || ignoreSynchronousMessagingTimeoutsForTesting != options.ignoreSynchronousMessagingTimeoutsForTesting)
             return false;
 
         if (experimentalFeatures != options.experimentalFeatures)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to