Title: [265410] trunk
Revision
265410
Author
[email protected]
Date
2020-08-08 20:23:25 -0700 (Sat, 08 Aug 2020)

Log Message

[ iOS wk2 ] editing/pasteboard/paste-without-nesting.html is a flaky failure
https://bugs.webkit.org/show_bug.cgi?id=215218
<rdar://problem/66628493>

Reviewed by Darin Adler.

Source/WebKit:

This test writes to the system pasteboard using `document.execCommand("Copy")`, and then immediately reads from
the system pasteboard by triggering `document.execCommand("Paste")`. On rare occasions, this fails on iOS, where
IPC messages for writing content to the pasteboard (e.g. `WebPasteboardProxy::WriteWebContentToPasteboard`) are
asynchronous, but the IPC message to get the pasteboard change count before pasting (`GetPasteboardChangeCount`)
is synchronous. This means that `Connection` may end up dispatching the sync `GetPasteboardChangeCount` IPC
message before dispatching `WriteWebContentToPasteboard`, which causes the pasteboard read to fail, because the
contents on the pasteboard have changed after starting to read from the pasteboard.

Note that this is not a problem on macOS since all pasteboard writing IPC is synchronous. Instead of turning all
of the async iOS pasteboard writing messages synchronous as well, we can fix this by adding a mechanism in
`WebProcess` to keep track of outgoing async pasteboard write messages; then, before attempting to grab the
change count when we start reading, wait for any of these pending async writes to finish before we continue.

In a future patch, we could actually adopt this same mechanism in `SetPasteboardTypes` and neighboring IPC
messages to turn these all asynchronous.

* UIProcess/Cocoa/WebPasteboardProxyCocoa.mm:
(WebKit::WebPasteboardProxy::writeURLToPasteboard):
(WebKit::WebPasteboardProxy::writeWebContentToPasteboard):
(WebKit::WebPasteboardProxy::writeImageToPasteboard):
(WebKit::WebPasteboardProxy::writeStringToPasteboard):

Call `didWriteToPasteboardAsynchronously` after we finish writing to the pasteboard asynchronously.

* WebProcess/WebCoreSupport/WebPlatformStrategies.cpp:
(WebKit::WebPlatformStrategies::changeCount):

Before accessing changeCount, wait until any asynchronous calls to write to the system pasteboard have finished.

(WebKit::WebPlatformStrategies::writeToPasteboard):

Right before we send an async message to the UI process to write to the system pasteboard, notify `WebProcess`
so that it can keep track of pending clipboard writes.

* WebProcess/WebProcess.h:
* WebProcess/WebProcess.messages.in:
* WebProcess/cocoa/WebProcessCocoa.mm:
(WebKit::WebProcess::willWriteToPasteboardAsynchronously):
(WebKit::WebProcess::didWriteToPasteboardAsynchronously):
(WebKit::WebProcess::waitForPendingPasteboardWritesToFinish):

Wait for a maximum of 1 second for any outgoing pasteboard writing messages to return to the web process.

LayoutTests:

Remove the flaky test expectation.

* platform/ios-simulator-wk2/TestExpectations:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (265409 => 265410)


--- trunk/LayoutTests/ChangeLog	2020-08-08 20:31:13 UTC (rev 265409)
+++ trunk/LayoutTests/ChangeLog	2020-08-09 03:23:25 UTC (rev 265410)
@@ -1,3 +1,15 @@
+2020-08-08  Wenson Hsieh  <[email protected]>
+
+        [ iOS wk2 ] editing/pasteboard/paste-without-nesting.html is a flaky failure
+        https://bugs.webkit.org/show_bug.cgi?id=215218
+        <rdar://problem/66628493>
+
+        Reviewed by Darin Adler.
+
+        Remove the flaky test expectation.
+
+        * platform/ios-simulator-wk2/TestExpectations:
+
 2020-08-07  Lauro Moura  <[email protected]>
 
         [GTK][WPE] Gardening and adding some WPE baselines.

Modified: trunk/LayoutTests/platform/ios-simulator-wk2/TestExpectations (265409 => 265410)


--- trunk/LayoutTests/platform/ios-simulator-wk2/TestExpectations	2020-08-08 20:31:13 UTC (rev 265409)
+++ trunk/LayoutTests/platform/ios-simulator-wk2/TestExpectations	2020-08-09 03:23:25 UTC (rev 265410)
@@ -130,5 +130,3 @@
 webkit.org/b/215033 imported/w3c/web-platform-tests/websockets/cookies/third-party-cookie-accepted.https.html [ Pass Failure ]
 
 webkit.org/b/215216 imported/w3c/web-platform-tests/svg/import/interact-zoom-01-t-manual.svg [ Pass Failure ]
-
-webkit.org/b/215218 editing/pasteboard/paste-without-nesting.html [ Pass Failure ]

Modified: trunk/Source/WebKit/ChangeLog (265409 => 265410)


--- trunk/Source/WebKit/ChangeLog	2020-08-08 20:31:13 UTC (rev 265409)
+++ trunk/Source/WebKit/ChangeLog	2020-08-09 03:23:25 UTC (rev 265410)
@@ -1,3 +1,54 @@
+2020-08-08  Wenson Hsieh  <[email protected]>
+
+        [ iOS wk2 ] editing/pasteboard/paste-without-nesting.html is a flaky failure
+        https://bugs.webkit.org/show_bug.cgi?id=215218
+        <rdar://problem/66628493>
+
+        Reviewed by Darin Adler.
+
+        This test writes to the system pasteboard using `document.execCommand("Copy")`, and then immediately reads from
+        the system pasteboard by triggering `document.execCommand("Paste")`. On rare occasions, this fails on iOS, where
+        IPC messages for writing content to the pasteboard (e.g. `WebPasteboardProxy::WriteWebContentToPasteboard`) are
+        asynchronous, but the IPC message to get the pasteboard change count before pasting (`GetPasteboardChangeCount`)
+        is synchronous. This means that `Connection` may end up dispatching the sync `GetPasteboardChangeCount` IPC
+        message before dispatching `WriteWebContentToPasteboard`, which causes the pasteboard read to fail, because the
+        contents on the pasteboard have changed after starting to read from the pasteboard.
+
+        Note that this is not a problem on macOS since all pasteboard writing IPC is synchronous. Instead of turning all
+        of the async iOS pasteboard writing messages synchronous as well, we can fix this by adding a mechanism in
+        `WebProcess` to keep track of outgoing async pasteboard write messages; then, before attempting to grab the
+        change count when we start reading, wait for any of these pending async writes to finish before we continue.
+
+        In a future patch, we could actually adopt this same mechanism in `SetPasteboardTypes` and neighboring IPC
+        messages to turn these all asynchronous.
+
+        * UIProcess/Cocoa/WebPasteboardProxyCocoa.mm:
+        (WebKit::WebPasteboardProxy::writeURLToPasteboard):
+        (WebKit::WebPasteboardProxy::writeWebContentToPasteboard):
+        (WebKit::WebPasteboardProxy::writeImageToPasteboard):
+        (WebKit::WebPasteboardProxy::writeStringToPasteboard):
+
+        Call `didWriteToPasteboardAsynchronously` after we finish writing to the pasteboard asynchronously.
+
+        * WebProcess/WebCoreSupport/WebPlatformStrategies.cpp:
+        (WebKit::WebPlatformStrategies::changeCount):
+
+        Before accessing changeCount, wait until any asynchronous calls to write to the system pasteboard have finished.
+
+        (WebKit::WebPlatformStrategies::writeToPasteboard):
+
+        Right before we send an async message to the UI process to write to the system pasteboard, notify `WebProcess`
+        so that it can keep track of pending clipboard writes.
+
+        * WebProcess/WebProcess.h:
+        * WebProcess/WebProcess.messages.in:
+        * WebProcess/cocoa/WebProcessCocoa.mm:
+        (WebKit::WebProcess::willWriteToPasteboardAsynchronously):
+        (WebKit::WebProcess::didWriteToPasteboardAsynchronously):
+        (WebKit::WebProcess::waitForPendingPasteboardWritesToFinish):
+
+        Wait for a maximum of 1 second for any outgoing pasteboard writing messages to return to the web process.
+
 2020-08-07  Chris Dumez  <[email protected]>
 
         baseLatency attribute is missing on AudioContext interface

Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm (265409 => 265410)


--- trunk/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm	2020-08-08 20:31:13 UTC (rev 265409)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm	2020-08-09 03:23:25 UTC (rev 265410)
@@ -30,6 +30,7 @@
 #import "SandboxExtension.h"
 #import "WebPageProxy.h"
 #import "WebPreferences.h"
+#import "WebProcessMessages.h"
 #import "WebProcessProxy.h"
 #import <WebCore/Color.h>
 #import <WebCore/Pasteboard.h>
@@ -453,6 +454,8 @@
     auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
     PlatformPasteboard(pasteboardName).write(url);
     didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, PlatformPasteboard(pasteboardName).changeCount());
+    if (auto process = webProcessProxyForConnection(connection))
+        process->send(Messages::WebProcess::DidWriteToPasteboardAsynchronously(pasteboardName), 0);
 }
 
 void WebPasteboardProxy::writeWebContentToPasteboard(IPC::Connection& connection, const WebCore::PasteboardWebContent& content, const String& pasteboardName)
@@ -462,6 +465,8 @@
     auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
     PlatformPasteboard(pasteboardName).write(content);
     didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, PlatformPasteboard(pasteboardName).changeCount());
+    if (auto process = webProcessProxyForConnection(connection))
+        process->send(Messages::WebProcess::DidWriteToPasteboardAsynchronously(pasteboardName), 0);
 }
 
 void WebPasteboardProxy::writeImageToPasteboard(IPC::Connection& connection, const WebCore::PasteboardImage& pasteboardImage, const String& pasteboardName)
@@ -471,6 +476,8 @@
     auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
     PlatformPasteboard(pasteboardName).write(pasteboardImage);
     didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, PlatformPasteboard(pasteboardName).changeCount());
+    if (auto process = webProcessProxyForConnection(connection))
+        process->send(Messages::WebProcess::DidWriteToPasteboardAsynchronously(pasteboardName), 0);
 }
 
 void WebPasteboardProxy::writeStringToPasteboard(IPC::Connection& connection, const String& pasteboardType, const String& text, const String& pasteboardName)
@@ -481,6 +488,8 @@
     auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
     PlatformPasteboard(pasteboardName).write(pasteboardType, text);
     didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, PlatformPasteboard(pasteboardName).changeCount());
+    if (auto process = webProcessProxyForConnection(connection))
+        process->send(Messages::WebProcess::DidWriteToPasteboardAsynchronously(pasteboardName), 0);
 }
 
 void WebPasteboardProxy::updateSupportedTypeIdentifiers(const Vector<String>& identifiers, const String& pasteboardName)

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp (265409 => 265410)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp	2020-08-08 20:31:13 UTC (rev 265409)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp	2020-08-09 03:23:25 UTC (rev 265410)
@@ -170,6 +170,7 @@
 int64_t WebPlatformStrategies::changeCount(const String& pasteboardName)
 {
     int64_t changeCount { 0 };
+    WebProcess::singleton().waitForPendingPasteboardWritesToFinish(pasteboardName);
     WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardChangeCount(pasteboardName), Messages::WebPasteboardProxy::GetPasteboardChangeCount::Reply(changeCount), 0);
     return changeCount;
 }
@@ -265,21 +266,25 @@
 
 void WebPlatformStrategies::writeToPasteboard(const PasteboardURL& url, const String& pasteboardName)
 {
+    WebProcess::singleton().willWriteToPasteboardAsynchronously(pasteboardName);
     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteURLToPasteboard(url, pasteboardName), 0);
 }
 
 void WebPlatformStrategies::writeToPasteboard(const WebCore::PasteboardWebContent& content, const String& pasteboardName)
 {
+    WebProcess::singleton().willWriteToPasteboardAsynchronously(pasteboardName);
     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteWebContentToPasteboard(content, pasteboardName), 0);
 }
 
 void WebPlatformStrategies::writeToPasteboard(const WebCore::PasteboardImage& image, const String& pasteboardName)
 {
+    WebProcess::singleton().willWriteToPasteboardAsynchronously(pasteboardName);
     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteImageToPasteboard(image, pasteboardName), 0);
 }
 
 void WebPlatformStrategies::writeToPasteboard(const String& pasteboardType, const String& text, const String& pasteboardName)
 {
+    WebProcess::singleton().willWriteToPasteboardAsynchronously(pasteboardName);
     WebProcess::singleton().parentProcessConnection()->send(Messages::WebPasteboardProxy::WriteStringToPasteboard(pasteboardType, text, pasteboardName), 0);
 }
 

Modified: trunk/Source/WebKit/WebProcess/WebProcess.h (265409 => 265410)


--- trunk/Source/WebKit/WebProcess/WebProcess.h	2020-08-08 20:31:13 UTC (rev 265409)
+++ trunk/Source/WebKit/WebProcess/WebProcess.h	2020-08-09 03:23:25 UTC (rev 265410)
@@ -334,6 +334,12 @@
 
     void enableVP9Decoder();
 
+#if PLATFORM(COCOA)
+    void willWriteToPasteboardAsynchronously(const String& pasteboardName);
+    void waitForPendingPasteboardWritesToFinish(const String& pasteboardName);
+    void didWriteToPasteboardAsynchronously(const String& pasteboardName);
+#endif
+
 private:
     WebProcess();
     ~WebProcess();
@@ -648,6 +654,10 @@
     RefPtr<SandboxExtension> m_assetServiceV2Extension;
 #endif
 
+#if PLATFORM(COCOA)
+    HashCountedSet<String> m_pendingPasteboardWriteCounts;
+#endif
+
     bool m_useGPUProcessForMedia { false };
     bool m_vp9DecoderEnabled { false };
 };

Modified: trunk/Source/WebKit/WebProcess/WebProcess.messages.in (265409 => 265410)


--- trunk/Source/WebKit/WebProcess/WebProcess.messages.in	2020-08-08 20:31:13 UTC (rev 265409)
+++ trunk/Source/WebKit/WebProcess/WebProcess.messages.in	2020-08-09 03:23:25 UTC (rev 265410)
@@ -178,4 +178,8 @@
 #if PLATFORM(GTK) && !USE(GTK4)
     SetUseSystemAppearanceForScrollbars(bool useSystemAppearanceForScrollbars)
 #endif
+
+#if PLATFORM(COCOA)
+    DidWriteToPasteboardAsynchronously(String pasteboardName);
+#endif
 }

Modified: trunk/Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm (265409 => 265410)


--- trunk/Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm	2020-08-08 20:31:13 UTC (rev 265409)
+++ trunk/Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm	2020-08-09 03:23:25 UTC (rev 265410)
@@ -45,6 +45,7 @@
 #import "WebPage.h"
 #import "WebProcessCreationParameters.h"
 #import "WebProcessDataStoreParameters.h"
+#import "WebProcessMessages.h"
 #import "WebProcessProxyMessages.h"
 #import "WebSleepDisablerClient.h"
 #import "WebsiteDataStoreParameters.h"
@@ -1075,7 +1076,26 @@
     setSystemHasAC(hasAC);
 }
 
+void WebProcess::willWriteToPasteboardAsynchronously(const String& pasteboardName)
+{
+    m_pendingPasteboardWriteCounts.add(pasteboardName);
+}
 
+void WebProcess::didWriteToPasteboardAsynchronously(const String& pasteboardName)
+{
+    m_pendingPasteboardWriteCounts.remove(pasteboardName);
+}
+
+void WebProcess::waitForPendingPasteboardWritesToFinish(const String& pasteboardName)
+{
+    while (m_pendingPasteboardWriteCounts.contains(pasteboardName)) {
+        if (!parentProcessConnection()->waitForAndDispatchImmediately<Messages::WebProcess::DidWriteToPasteboardAsynchronously>(0, 1_s, IPC::WaitForOption::InterruptWaitingIfSyncMessageArrives)) {
+            m_pendingPasteboardWriteCounts.removeAll(pasteboardName);
+            break;
+        }
+    }
+}
+
 } // namespace WebKit
 
 #undef RELEASE_LOG_SESSION_ID
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to