Avoid UI Process hangs when the WebContent process is showing JS prompts / alerts
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Jul 2019 15:42:11 +0000 (15:42 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Jul 2019 15:42:11 +0000 (15:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=200107
<rdar://problem/53034592>

Reviewed by Geoffrey Garen.

Source/WebCore:

Add testing infrastructure for SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply.

Test: fast/misc/testProcessIncomingSyncMessagesWhenWaitingForSyncReply.html

* page/ChromeClient.h:
* testing/Internals.cpp:
(WebCore::Internals::testProcessIncomingSyncMessagesWhenWaitingForSyncReply):
* testing/Internals.h:
* testing/Internals.idl:

Source/WebKit:

* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::incrementProcessIncomingSyncMessagesWhenWaitingForSyncReplyCount):
(IPC::Connection::SyncMessageState::decrementProcessIncomingSyncMessagesWhenWaitingForSyncReplyCount):
(IPC::Connection::SyncMessageState::processIncomingMessage):
(IPC::Connection::sendSyncMessage):
* Platform/IPC/Connection.h:
Add support for new SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply flag
to allow processing incoming sync messages while sending a particular sync IPC. This is the
default behavior in all processes except in the WebContent process, where we try to avoid
re-entering to prevent bugs. This flag allows the WebContent process to change its default
behavior for some specific IPCs, where we know it is safe to re-enter and where it benefits
performance to re-renter.

* NetworkProcess/NetworkConnectionToWebProcess.cpp:
(WebKit::NetworkConnectionToWebProcess::testProcessIncomingSyncMessagesWhenWaitingForSyncReply):
* NetworkProcess/NetworkConnectionToWebProcess.h:
* NetworkProcess/NetworkConnectionToWebProcess.messages.in:
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::didReceiveSyncMessage):
(WebKit::NetworkProcessProxy::testProcessIncomingSyncMessagesWhenWaitingForSyncReply):
* UIProcess/Network/NetworkProcessProxy.h:
* UIProcess/Network/NetworkProcessProxy.messages.in:
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::testProcessIncomingSyncMessagesWhenWaitingForSyncReply):
* WebProcess/WebCoreSupport/WebChromeClient.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::testProcessIncomingSyncMessagesWhenWaitingForSyncReply):
* WebProcess/WebPage/WebPage.h:
(WebKit::WebPage::sendSyncWithDelayedReply):
* WebProcess/WebPage/WebPage.messages.in:
SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply
Add testing infrastructure for SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply
flag.

* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
Use new SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply flag when sending
the synchronous IPC for JS alerts / prompt / confirm. This allows the WebProcess to process
incoming synchronous IPC for other processes (in particular the UIProcess) while it is blocked
on those synchronous IPCs. It is safe to re-enter the WebContent process on these sync IPCs
since they are triggered by JS and we return to JS right after. This should avoid UIProcess
hangs when the UIProcess is sending a sync IPC to the WebContent process, which is itself
stuck on the sync IPC to show a JS alert.

LayoutTests:

Add layout test coverage for SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply.
Without the flag on the sendSync from the WebContent process of the
NetworkConnectionToWebProcess::TestProcessIncomingSyncMessagesWhenWaitingForSyncReply IPC, the
test would hang. This is because the WebContent process sends a sync IPC to the network process,
which in turns sends one to the UIProcess, which itself sends one back to the WebContent process.
This would attempt to re-enter the WebContent process which is currently sending a sync IPC, which
is not allowed by default.

* fast/misc/testProcessIncomingSyncMessagesWhenWaitingForSyncReply-expected.txt: Added.
* fast/misc/testProcessIncomingSyncMessagesWhenWaitingForSyncReply.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@247822 268f45cc-cd09-0410-ab3c-d52691b4dbfc

22 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/misc/testProcessIncomingSyncMessagesWhenWaitingForSyncReply-expected.txt [new file with mode: 0644]
LayoutTests/fast/misc/testProcessIncomingSyncMessagesWhenWaitingForSyncReply.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/page/ChromeClient.h
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp
Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h
Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in
Source/WebKit/Platform/IPC/Connection.cpp
Source/WebKit/Platform/IPC/Connection.h
Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp
Source/WebKit/UIProcess/Network/NetworkProcessProxy.h
Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in
Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/WebPage.messages.in

index b2aa552..d947ecb 100644 (file)
@@ -1,3 +1,22 @@
+2019-07-25  Chris Dumez  <cdumez@apple.com>
+
+        Avoid UI Process hangs when the WebContent process is showing JS prompts / alerts
+        https://bugs.webkit.org/show_bug.cgi?id=200107
+        <rdar://problem/53034592>
+
+        Reviewed by Geoffrey Garen.
+
+        Add layout test coverage for SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply.
+        Without the flag on the sendSync from the WebContent process of the
+        NetworkConnectionToWebProcess::TestProcessIncomingSyncMessagesWhenWaitingForSyncReply IPC, the
+        test would hang. This is because the WebContent process sends a sync IPC to the network process,
+        which in turns sends one to the UIProcess, which itself sends one back to the WebContent process.
+        This would attempt to re-enter the WebContent process which is currently sending a sync IPC, which
+        is not allowed by default.
+
+        * fast/misc/testProcessIncomingSyncMessagesWhenWaitingForSyncReply-expected.txt: Added.
+        * fast/misc/testProcessIncomingSyncMessagesWhenWaitingForSyncReply.html: Added.
+
 2019-07-25  Rob Buis  <rbuis@igalia.com>
 
         Make storing cross-origin top-level prefetches in HTTP cache optional
diff --git a/LayoutTests/fast/misc/testProcessIncomingSyncMessagesWhenWaitingForSyncReply-expected.txt b/LayoutTests/fast/misc/testProcessIncomingSyncMessagesWhenWaitingForSyncReply-expected.txt
new file mode 100644 (file)
index 0000000..c0c8c25
--- /dev/null
@@ -0,0 +1,10 @@
+Test for the SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply sendSync flag
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS internals.testProcessIncomingSyncMessagesWhenWaitingForSyncReply() is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/misc/testProcessIncomingSyncMessagesWhenWaitingForSyncReply.html b/LayoutTests/fast/misc/testProcessIncomingSyncMessagesWhenWaitingForSyncReply.html
new file mode 100644 (file)
index 0000000..b643ebb
--- /dev/null
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src="../../resources/js-test.js"></script>
+<script>
+description("Test for the SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply sendSync flag");
+
+shouldBeTrue("internals.testProcessIncomingSyncMessagesWhenWaitingForSyncReply()");
+</script>
+</body>
+</html>
index fc08e5b..631cf6c 100644 (file)
@@ -1,3 +1,21 @@
+2019-07-25  Chris Dumez  <cdumez@apple.com>
+
+        Avoid UI Process hangs when the WebContent process is showing JS prompts / alerts
+        https://bugs.webkit.org/show_bug.cgi?id=200107
+        <rdar://problem/53034592>
+
+        Reviewed by Geoffrey Garen.
+
+        Add testing infrastructure for SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply.
+
+        Test: fast/misc/testProcessIncomingSyncMessagesWhenWaitingForSyncReply.html
+
+        * page/ChromeClient.h:
+        * testing/Internals.cpp:
+        (WebCore::Internals::testProcessIncomingSyncMessagesWhenWaitingForSyncReply):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 2019-07-25  Rob Buis  <rbuis@igalia.com>
 
         Make storing cross-origin top-level prefetches in HTTP cache optional
index 169815a..9de1e91 100644 (file)
@@ -381,6 +381,8 @@ public:
     virtual void assistiveTechnologyMakeFirstResponder() { }
 #endif
 
+    virtual bool testProcessIncomingSyncMessagesWhenWaitingForSyncReply() { return true; }
+
 #if PLATFORM(IOS_FAMILY)
     // FIXME: Come up with a more descriptive name for this function and make it platform independent (if possible).
     virtual bool isStopping() = 0;
index 9c167eb..d23a92d 100644 (file)
@@ -2275,6 +2275,13 @@ void Internals::setAutomaticLinkDetectionEnabled(bool enabled)
 #endif
 }
 
+bool Internals::testProcessIncomingSyncMessagesWhenWaitingForSyncReply()
+{
+    ASSERT(contextDocument());
+    ASSERT(contextDocument()->page());
+    return contextDocument()->page()->chrome().client().testProcessIncomingSyncMessagesWhenWaitingForSyncReply();
+}
+
 void Internals::setAutomaticDashSubstitutionEnabled(bool enabled)
 {
     if (!contextDocument() || !contextDocument()->frame())
index 48df595..468fb83 100644 (file)
@@ -331,6 +331,8 @@ public:
     bool isOverwriteModeEnabled();
     void toggleOverwriteModeEnabled();
 
+    bool testProcessIncomingSyncMessagesWhenWaitingForSyncReply();
+
     ExceptionOr<RefPtr<Range>> rangeOfString(const String&, RefPtr<Range>&&, const Vector<String>& findOptions);
     ExceptionOr<unsigned> countMatchesForText(const String&, const Vector<String>& findOptions, const String& markMatches);
     ExceptionOr<unsigned> countFindMatches(const String&, const Vector<String>& findOptions);
index 7775302..aa50bcc 100644 (file)
@@ -382,6 +382,8 @@ enum CompositingPolicy {
     [MayThrowException] readonly attribute boolean areSVGAnimationsPaused;
     [MayThrowException] double svgAnimationsInterval(SVGSVGElement element);
 
+    boolean testProcessIncomingSyncMessagesWhenWaitingForSyncReply();
+
     // Flags for layerTreeAsText.
     const unsigned short LAYER_TREE_INCLUDES_VISIBLE_RECTS = 1;
     const unsigned short LAYER_TREE_INCLUDES_TILE_CACHES = 2;
index 381087a..d1dfd5e 100644 (file)
@@ -1,3 +1,57 @@
+2019-07-25  Chris Dumez  <cdumez@apple.com>
+
+        Avoid UI Process hangs when the WebContent process is showing JS prompts / alerts
+        https://bugs.webkit.org/show_bug.cgi?id=200107
+        <rdar://problem/53034592>
+
+        Reviewed by Geoffrey Garen.
+
+        * Platform/IPC/Connection.cpp:
+        (IPC::Connection::SyncMessageState::incrementProcessIncomingSyncMessagesWhenWaitingForSyncReplyCount):
+        (IPC::Connection::SyncMessageState::decrementProcessIncomingSyncMessagesWhenWaitingForSyncReplyCount):
+        (IPC::Connection::SyncMessageState::processIncomingMessage):
+        (IPC::Connection::sendSyncMessage):
+        * Platform/IPC/Connection.h:
+        Add support for new SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply flag
+        to allow processing incoming sync messages while sending a particular sync IPC. This is the
+        default behavior in all processes except in the WebContent process, where we try to avoid
+        re-entering to prevent bugs. This flag allows the WebContent process to change its default
+        behavior for some specific IPCs, where we know it is safe to re-enter and where it benefits
+        performance to re-renter.
+
+        * NetworkProcess/NetworkConnectionToWebProcess.cpp:
+        (WebKit::NetworkConnectionToWebProcess::testProcessIncomingSyncMessagesWhenWaitingForSyncReply):
+        * NetworkProcess/NetworkConnectionToWebProcess.h:
+        * NetworkProcess/NetworkConnectionToWebProcess.messages.in:
+        * UIProcess/Network/NetworkProcessProxy.cpp:
+        (WebKit::NetworkProcessProxy::didReceiveSyncMessage):
+        (WebKit::NetworkProcessProxy::testProcessIncomingSyncMessagesWhenWaitingForSyncReply):
+        * UIProcess/Network/NetworkProcessProxy.h:
+        * UIProcess/Network/NetworkProcessProxy.messages.in:
+        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+        (WebKit::WebChromeClient::testProcessIncomingSyncMessagesWhenWaitingForSyncReply):
+        * WebProcess/WebCoreSupport/WebChromeClient.h:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::testProcessIncomingSyncMessagesWhenWaitingForSyncReply):
+        * WebProcess/WebPage/WebPage.h:
+        (WebKit::WebPage::sendSyncWithDelayedReply):
+        * WebProcess/WebPage/WebPage.messages.in:
+        SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply
+        Add testing infrastructure for SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply
+        flag.
+
+        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+        (WebKit::WebChromeClient::runJavaScriptAlert):
+        (WebKit::WebChromeClient::runJavaScriptConfirm):
+        (WebKit::WebChromeClient::runJavaScriptPrompt):
+        Use new SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply flag when sending
+        the synchronous IPC for JS alerts / prompt / confirm. This allows the WebProcess to process
+        incoming synchronous IPC for other processes (in particular the UIProcess) while it is blocked
+        on those synchronous IPCs. It is safe to re-enter the WebContent process on these sync IPCs
+        since they are triggered by JS and we return to JS right after. This should avoid UIProcess
+        hangs when the UIProcess is sending a sync IPC to the WebContent process, which is itself
+        stuck on the sync IPC to show a JS alert.
+
 2019-07-25  Rob Buis  <rbuis@igalia.com>
 
         Make storing cross-origin top-level prefetches in HTTP cache optional
index 2d50e2f..f5565b9 100644 (file)
@@ -34,6 +34,7 @@
 #include "NetworkProcess.h"
 #include "NetworkProcessConnectionMessages.h"
 #include "NetworkProcessMessages.h"
+#include "NetworkProcessProxyMessages.h"
 #include "NetworkRTCMonitorMessages.h"
 #include "NetworkRTCProviderMessages.h"
 #include "NetworkRTCSocketMessages.h"
@@ -411,6 +412,14 @@ void NetworkConnectionToWebProcess::performSynchronousLoad(NetworkResourceLoadPa
     loader->start();
 }
 
+void NetworkConnectionToWebProcess::testProcessIncomingSyncMessagesWhenWaitingForSyncReply(WebCore::PageIdentifier webPageID, Messages::NetworkConnectionToWebProcess::TestProcessIncomingSyncMessagesWhenWaitingForSyncReply::DelayedReply&& reply)
+{
+    bool handled = false;
+    if (!m_networkProcess->parentProcessConnection()->sendSync(Messages::NetworkProcessProxy::TestProcessIncomingSyncMessagesWhenWaitingForSyncReply(webPageID), Messages::NetworkProcessProxy::TestProcessIncomingSyncMessagesWhenWaitingForSyncReply::Reply(handled), 0))
+        return reply(false);
+    reply(handled);
+}
+
 void NetworkConnectionToWebProcess::loadPing(NetworkResourceLoadParameters&& loadParameters)
 {
     auto completionHandler = [connection = m_connection.copyRef(), identifier = loadParameters.identifier] (const ResourceError& error, const ResourceResponse& response) {
index 19e7672..d7b2f1b 100644 (file)
@@ -165,6 +165,7 @@ private:
 
     void scheduleResourceLoad(NetworkResourceLoadParameters&&);
     void performSynchronousLoad(NetworkResourceLoadParameters&&, Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply&&);
+    void testProcessIncomingSyncMessagesWhenWaitingForSyncReply(WebCore::PageIdentifier, Messages::NetworkConnectionToWebProcess::TestProcessIncomingSyncMessagesWhenWaitingForSyncReply::DelayedReply&&);
     void loadPing(NetworkResourceLoadParameters&&);
     void prefetchDNS(const String&);
     void preconnectTo(uint64_t preconnectionIdentifier, NetworkResourceLoadParameters&&);
index 7709e2f..fa2c31a 100644 (file)
@@ -24,6 +24,7 @@ messages -> NetworkConnectionToWebProcess LegacyReceiver {
 
     ScheduleResourceLoad(WebKit::NetworkResourceLoadParameters resourceLoadParameters)
     PerformSynchronousLoad(WebKit::NetworkResourceLoadParameters resourceLoadParameters) -> (WebCore::ResourceError error, WebCore::ResourceResponse response, Vector<char> data) Synchronous
+    TestProcessIncomingSyncMessagesWhenWaitingForSyncReply(WebCore::PageIdentifier webPageID) -> (bool handled) Synchronous
     LoadPing(WebKit::NetworkResourceLoadParameters resourceLoadParameters)
     RemoveLoadIdentifier(uint64_t resourceLoadIdentifier)
     PageLoadCompleted(WebCore::PageIdentifier webPageID)
index 019fbc8..6cbeba9 100644 (file)
@@ -98,6 +98,9 @@ public:
     // from that connection and put the other messages back in the queue.
     void dispatchMessages(Connection* allowedConnection);
 
+    void incrementProcessIncomingSyncMessagesWhenWaitingForSyncReplyCount() { ++m_processIncomingSyncMessagesWhenWaitingForSyncReplyCount; }
+    void decrementProcessIncomingSyncMessagesWhenWaitingForSyncReplyCount() { --m_processIncomingSyncMessagesWhenWaitingForSyncReplyCount; }
+
 private:
     void dispatchMessageAndResetDidScheduleDispatchMessagesForConnection(Connection&);
 
@@ -114,6 +117,8 @@ private:
         std::unique_ptr<Decoder> message;
     };
     Vector<ConnectionAndIncomingMessage> m_messagesToDispatchWhileWaitingForSyncReply;
+
+    std::atomic<unsigned> m_processIncomingSyncMessagesWhenWaitingForSyncReplyCount { 0 };
 };
 
 Connection::SyncMessageState& Connection::SyncMessageState::singleton()
@@ -134,7 +139,16 @@ Connection::SyncMessageState::SyncMessageState()
 
 bool Connection::SyncMessageState::processIncomingMessage(Connection& connection, std::unique_ptr<Decoder>& message)
 {
-    if (!message->shouldDispatchMessageWhenWaitingForSyncReply())
+    bool shouldDispatchMessageWhenWaitingForSyncReply = message->shouldDispatchMessageWhenWaitingForSyncReply();
+
+    // We dispatch synchronous messages even if shouldDispatchMessageWhenWaitingForSyncReply returns false if the
+    // sendSync() used SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply. This is used for some messages
+    // in the WebContent process (which normally does not dispatch messages when waiting for a sync reply), to avoid
+    // hangs.
+    if (!shouldDispatchMessageWhenWaitingForSyncReply && message->isSyncMessage() && m_processIncomingSyncMessagesWhenWaitingForSyncReplyCount.load())
+        shouldDispatchMessageWhenWaitingForSyncReply = true;
+
+    if (!shouldDispatchMessageWhenWaitingForSyncReply)
         return false;
 
     ConnectionAndIncomingMessage connectionAndIncomingMessage { connection, WTFMove(message) };
@@ -565,11 +579,17 @@ std::unique_ptr<Decoder> Connection::sendSyncMessage(uint64_t syncRequestID, std
     // First send the message.
     sendMessage(WTFMove(encoder), IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
 
+    if (sendSyncOptions.contains(SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply))
+        SyncMessageState::singleton().incrementProcessIncomingSyncMessagesWhenWaitingForSyncReplyCount();
+
     // Then wait for a reply. Waiting for a reply could involve dispatching incoming sync messages, so
     // keep an extra reference to the connection here in case it's invalidated.
     Ref<Connection> protect(*this);
     std::unique_ptr<Decoder> reply = waitForSyncReply(syncRequestID, timeout, sendSyncOptions);
 
+    if (sendSyncOptions.contains(SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply))
+        SyncMessageState::singleton().decrementProcessIncomingSyncMessagesWhenWaitingForSyncReplyCount();
+
     --m_inSendSyncCount;
 
     // Finally, pop the pending sync reply information.
index 42f836d..a4907d1 100644 (file)
@@ -68,6 +68,7 @@ enum class SendSyncOption {
     // Use this to inform that this sync call will suspend this process until the user responds with input.
     InformPlatformProcessWillSuspend = 1 << 0,
     UseFullySynchronousModeForTesting = 1 << 1,
+    ProcessIncomingSyncMessagesWhenWaitingForSyncReply = 1 << 2,
 };
 
 enum class WaitForOption {
index 346ac67..a9dc327 100644 (file)
@@ -40,6 +40,7 @@
 #include "ShouldGrandfatherStatistics.h"
 #include "StorageAccessStatus.h"
 #include "WebCompiledContentRuleList.h"
+#include "WebPageMessages.h"
 #include "WebPageProxy.h"
 #include "WebProcessMessages.h"
 #include "WebProcessPool.h"
@@ -268,7 +269,7 @@ void NetworkProcessProxy::didReceiveSyncMessage(IPC::Connection& connection, IPC
     if (dispatchSyncMessage(connection, decoder, replyEncoder))
         return;
 
-    ASSERT_NOT_REACHED();
+    didReceiveSyncNetworkProcessProxyMessage(connection, decoder, replyEncoder);
 }
 
 void NetworkProcessProxy::didClose(IPC::Connection&)
@@ -1203,6 +1204,18 @@ void NetworkProcessProxy::clearUploadAssertion()
     m_uploadAssertion = nullptr;
 }
 
+void NetworkProcessProxy::testProcessIncomingSyncMessagesWhenWaitingForSyncReply(WebCore::PageIdentifier webPageID, Messages::NetworkProcessProxy::TestProcessIncomingSyncMessagesWhenWaitingForSyncReply::DelayedReply&& reply)
+{
+    auto* page = WebProcessProxy::webPage(webPageID);
+    if (!page)
+        return reply(false);
+
+    bool handled = false;
+    if (!page->sendSync(Messages::WebPage::TestProcessIncomingSyncMessagesWhenWaitingForSyncReply(), Messages::WebPage::TestProcessIncomingSyncMessagesWhenWaitingForSyncReply::Reply(handled)))
+        return reply(false);
+    reply(handled);
+}
+
 #if ENABLE(INDEXED_DATABASE)
 void NetworkProcessProxy::createSymLinkForFileUpgrade(const String& indexedDatabaseDirectory)
 {
index 97088e9..2d0be51 100644 (file)
@@ -163,6 +163,8 @@ public:
     void syncAllCookies();
     void didSyncAllCookies();
 
+    void testProcessIncomingSyncMessagesWhenWaitingForSyncReply(WebCore::PageIdentifier, Messages::NetworkProcessProxy::TestProcessIncomingSyncMessagesWhenWaitingForSyncReply::DelayedReply&&);
+
     ProcessThrottler& throttler() { return m_throttler; }
     WebProcessPool& processPool() { return m_processPool; }
 
@@ -203,6 +205,7 @@ private:
     void didReceiveSyncMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>&) override;
     void didClose(IPC::Connection&) override;
     void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
+    void didReceiveSyncNetworkProcessProxyMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>&);
 
     // Message handlers
     void didReceiveNetworkProcessProxyMessage(IPC::Connection&, IPC::Decoder&);
index 047dfe8..11d8c5d 100644 (file)
@@ -31,6 +31,8 @@ messages -> NetworkProcessProxy LegacyReceiver {
 
     DidSyncAllCookies()
 
+    TestProcessIncomingSyncMessagesWhenWaitingForSyncReply(WebCore::PageIdentifier webPageID) -> (bool handled) Synchronous
+
     ProcessReadyToSuspend()
     SetIsHoldingLockedFiles(bool isHoldingLockedFiles)
 
index a6566d2..9921dfb 100644 (file)
@@ -36,6 +36,8 @@
 #include "InjectedBundleNavigationAction.h"
 #include "InjectedBundleNodeHandle.h"
 #include "NavigationActionData.h"
+#include "NetworkConnectionToWebProcessMessages.h"
+#include "NetworkProcessConnection.h"
 #include "PageBanner.h"
 #include "UserData.h"
 #include "WebColorChooser.h"
@@ -303,6 +305,14 @@ Page* WebChromeClient::createWindow(Frame& frame, const FrameLoadRequest& reques
     return webProcess.webPage(*newPageID)->corePage();
 }
 
+bool WebChromeClient::testProcessIncomingSyncMessagesWhenWaitingForSyncReply()
+{
+    bool handled = false;
+    if (!WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::NetworkConnectionToWebProcess::TestProcessIncomingSyncMessagesWhenWaitingForSyncReply(m_page.pageID()), Messages::NetworkConnectionToWebProcess::TestProcessIncomingSyncMessagesWhenWaitingForSyncReply::Reply(handled), 0, Seconds::infinity(), IPC::SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply))
+        return false;
+    return handled;
+}
+
 void WebChromeClient::show()
 {
     m_page.show();
@@ -458,7 +468,7 @@ void WebChromeClient::runJavaScriptAlert(Frame& frame, const String& alertText)
 
     HangDetectionDisabler hangDetectionDisabler;
 
-    m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::RunJavaScriptAlert(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), alertText), Messages::WebPageProxy::RunJavaScriptAlert::Reply());
+    m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::RunJavaScriptAlert(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), alertText), Messages::WebPageProxy::RunJavaScriptAlert::Reply(), IPC::SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply);
 }
 
 bool WebChromeClient::runJavaScriptConfirm(Frame& frame, const String& message)
@@ -475,7 +485,7 @@ bool WebChromeClient::runJavaScriptConfirm(Frame& frame, const String& message)
     HangDetectionDisabler hangDetectionDisabler;
 
     bool result = false;
-    if (!m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::RunJavaScriptConfirm(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message), Messages::WebPageProxy::RunJavaScriptConfirm::Reply(result)))
+    if (!m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::RunJavaScriptConfirm(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message), Messages::WebPageProxy::RunJavaScriptConfirm::Reply(result), IPC::SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply))
         return false;
 
     return result;
@@ -494,7 +504,7 @@ bool WebChromeClient::runJavaScriptPrompt(Frame& frame, const String& message, c
 
     HangDetectionDisabler hangDetectionDisabler;
 
-    if (!m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::RunJavaScriptPrompt(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message, defaultValue), Messages::WebPageProxy::RunJavaScriptPrompt::Reply(result)))
+    if (!m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::RunJavaScriptPrompt(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message, defaultValue), Messages::WebPageProxy::RunJavaScriptPrompt::Reply(result), IPC::SendSyncOption::ProcessIncomingSyncMessagesWhenWaitingForSyncReply))
         return false;
 
     return !result.isNull();
index fa24657..8668031 100644 (file)
@@ -222,6 +222,8 @@ private:
 
     void contentRuleListNotification(const URL&, const WebCore::ContentRuleListResults&) final;
 
+    bool testProcessIncomingSyncMessagesWhenWaitingForSyncReply() final;
+
 #if PLATFORM(WIN)
     void setLastSetCursorToCurrentCursor() final { }
     void AXStartFrameLoad() final { }
index 6adc762..80067ce 100644 (file)
@@ -5885,6 +5885,11 @@ void WebPage::didRemoveMenuItemElement(HTMLMenuItemElement& element)
 #endif
 }
 
+void WebPage::testProcessIncomingSyncMessagesWhenWaitingForSyncReply(Messages::WebPage::TestProcessIncomingSyncMessagesWhenWaitingForSyncReply::DelayedReply&& reply)
+{
+    reply(true);
+}
+
 #if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
 static const int primarySnapshottedPlugInSearchLimit = 3000;
 static const float primarySnapshottedPlugInSearchBucketSize = 1.1;
index 95409e9..c5bc8cc 100644 (file)
@@ -49,6 +49,7 @@
 #include "SharedMemory.h"
 #include "UserData.h"
 #include "WebBackForwardListProxy.h"
+#include "WebPageMessages.h"
 #include "WebURLSchemeHandler.h"
 #include "WebUndoStepID.h"
 #include "WebUserContentController.h"
@@ -1166,10 +1167,10 @@ public:
     void didReceiveWebPageMessage(IPC::Connection&, IPC::Decoder&);
 
     template<typename T>
-    bool sendSyncWithDelayedReply(T&& message, typename T::Reply&& reply)
+    bool sendSyncWithDelayedReply(T&& message, typename T::Reply&& reply, OptionSet<IPC::SendSyncOption> sendSyncOptions = { })
     {
         cancelGesturesBlockedOnSynchronousReplies();
-        return sendSync(WTFMove(message), WTFMove(reply), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend);
+        return sendSync(WTFMove(message), WTFMove(reply), Seconds::infinity(), sendSyncOptions | IPC::SendSyncOption::InformPlatformProcessWillSuspend);
     }
 
     WebCore::DOMPasteAccessResponse requestDOMPasteAccess(const String& originIdentifier);
@@ -1291,6 +1292,8 @@ private:
     bool executeKeypressCommandsInternal(const Vector<WebCore::KeypressCommand>&, WebCore::KeyboardEvent*);
 #endif
 
+    void testProcessIncomingSyncMessagesWhenWaitingForSyncReply(Messages::WebPage::TestProcessIncomingSyncMessagesWhenWaitingForSyncReply::DelayedReply&&);
+
     void updateDrawingAreaLayerTreeFreezeState();
     bool markLayersVolatileImmediatelyIfPossible();
     void layerVolatilityTimerFired();
index c11b49d..28bf717 100644 (file)
@@ -31,6 +31,8 @@ messages -> WebPage LegacyReceiver {
     SendCSPViolationReport(uint64_t frameID, URL reportURL, IPC::FormDataReference reportData)
     EnqueueSecurityPolicyViolationEvent(uint64_t frameID, WebCore::SecurityPolicyViolationEvent::Init eventInit)
 
+    TestProcessIncomingSyncMessagesWhenWaitingForSyncReply() -> (bool handled) Synchronous
+
 #if PLATFORM(COCOA)
     SetTopContentInsetFenced(float contentInset, IPC::Attachment fencePort)
 #endif