⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 259613 in webkit


Ignore:
Timestamp:
Apr 6, 2020, 5:00:04 PM (6 years ago)
Author:
Wenson Hsieh
Message:

REGRESSION: 4 TestWebKitAPI.DragAndDropTests.DataTransferSetData tests failing on iOS
https://bugs.webkit.org/show_bug.cgi?id=209685
<rdar://problem/60987461>

Reviewed by Megan Gardner.

After updating a WebKit open source test runner to iOS 13.4, 4 pasteboard-related API tests began to fail in
release builds on that particular bot. Logging statements added in r259465, r259518, r259534, and r259541
strongly suggest that this is due to an IPC dispatch race when clearing the platform pasteboard before writing
custom pasteboard data. On iOS, the former is dispatched asynchronously, while the latter is dispatched as sync
IPC. This means that if the UI process happens to be waiting for a sync IPC response from the web process, it
will end up handling the incoming IPC messages out of order by immediately dispatching sync IPC (in this case,
writing custom pasteboard data) before dispatching the async IPC (clearing data). This causes the custom
pasteboard data to be cleared on the platform pasteboard immediately after it is written.

To fix this, we limit clearing pasteboard data to when we would've otherwise avoided writing any custom
pasteboard data, and additionally make it so that writing custom pasteboard data always clears out any pre-
existing content on the pasteboard (obviating the need for a separate message to clear the pasteboard). Note
that writing custom pasteboard data always clears the existing pasteboard on macOS and iOS -- on macOS, we use
-declareTypes:owner:; on iOS, we use -setItemProviders:; in the case of macCatalyst, we -setItems:.

  • dom/DataTransfer.cpp:

(WebCore::DataTransfer::commitToPasteboard):

Push the call to clear the pasteboard down from the call sites of commitToPasteboard into commitToPasteboard
itself; then, only explicitly clear the pasteboard in the case where we aren't writing custom pasteboard data
(i.e. either custom pasteboard data is disabled, or there is no data to write),

(WebCore::DataTransfer::moveDragState): See above.

  • editing/Editor.cpp:

(WebCore::dispatchClipboardEvent): See above.

  • platform/ios/WebItemProviderPasteboard.mm:

(-[WebItemProviderPasteboard stageRegistrationLists:]):

Remove always-on logging added in r259541 to help diagnose the test failures.

Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r259611 r259613  
     12020-04-06  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        REGRESSION: 4 TestWebKitAPI.DragAndDropTests.DataTransferSetData tests failing on iOS
     4        https://bugs.webkit.org/show_bug.cgi?id=209685
     5        <rdar://problem/60987461>
     6
     7        Reviewed by Megan Gardner.
     8
     9        After updating a WebKit open source test runner to iOS 13.4, 4 pasteboard-related API tests began to fail in
     10        release builds on that particular bot. Logging statements added in r259465, r259518, r259534, and r259541
     11        strongly suggest that this is due to an IPC dispatch race when clearing the platform pasteboard before writing
     12        custom pasteboard data. On iOS, the former is dispatched asynchronously, while the latter is dispatched as sync
     13        IPC. This means that if the UI process happens to be waiting for a sync IPC response from the web process, it
     14        will end up handling the incoming IPC messages out of order by immediately dispatching sync IPC (in this case,
     15        writing custom pasteboard data) before dispatching the async IPC (clearing data). This causes the custom
     16        pasteboard data to be cleared on the platform pasteboard immediately after it is written.
     17
     18        To fix this, we limit clearing pasteboard data to when we would've otherwise avoided writing any custom
     19        pasteboard data, and additionally make it so that writing custom pasteboard data always clears out any pre-
     20        existing content on the pasteboard (obviating the need for a separate message to clear the pasteboard). Note
     21        that writing custom pasteboard data always clears the existing pasteboard on macOS and iOS -- on macOS, we use
     22        `-declareTypes:owner:`; on iOS, we use `-setItemProviders:`; in the case of macCatalyst, we `-setItems:`.
     23
     24        * dom/DataTransfer.cpp:
     25        (WebCore::DataTransfer::commitToPasteboard):
     26
     27        Push the call to clear the pasteboard down from the call sites of `commitToPasteboard` into `commitToPasteboard`
     28        itself; then, only explicitly clear the pasteboard in the case where we aren't writing custom pasteboard data
     29        (i.e. either custom pasteboard data is disabled, or there is no data to write),
     30
     31        (WebCore::DataTransfer::moveDragState): See above.
     32        * editing/Editor.cpp:
     33        (WebCore::dispatchClipboardEvent): See above.
     34        * platform/ios/WebItemProviderPasteboard.mm:
     35        (-[WebItemProviderPasteboard stageRegistrationLists:]):
     36
     37        Remove always-on logging added in r259541 to help diagnose the test failures.
     38
    1392020-04-06  Zalan Bujtas  <zalan@apple.com>
    240
  • trunk/Source/WebCore/dom/DataTransfer.cpp

    r252627 r259613  
    426426    ASSERT(is<StaticPasteboard>(*m_pasteboard) && !is<StaticPasteboard>(nativePasteboard));
    427427    PasteboardCustomData customData = downcast<StaticPasteboard>(*m_pasteboard).takeCustomData();
    428     if (!customData.hasData())
    429         return;
     428    if (!customData.hasData()) {
     429        // We clear the platform pasteboard here to ensure that the pasteboard doesn't contain any data
     430        // that may have been written before starting the drag or copying, and after ending the last
     431        // drag session or paste. After pushing the static pasteboard's contents to the platform, the
     432        // pasteboard should only contain data that was in the static pasteboard.
     433        nativePasteboard.clear();
     434        return;
     435    }
    430436
    431437    if (RuntimeEnabledFeatures::sharedFeatures().customPasteboardDataEnabled()) {
     
    435441    }
    436442
     443    nativePasteboard.clear();
    437444    customData.forEachPlatformString([&] (auto& type, auto& string) {
    438445        nativePasteboard.writeString(type, string);
     
    703710{
    704711    RELEASE_ASSERT(is<StaticPasteboard>(other->pasteboard()));
    705     // We clear the platform pasteboard here to ensure that the pasteboard doesn't contain any data
    706     // that may have been written before starting the drag, and after ending the last drag session.
    707     // After pushing the static pasteboard's contents to the platform, the pasteboard should only
    708     // contain data that was in the static pasteboard.
    709     m_pasteboard->clear();
    710712    other->commitToPasteboard(*m_pasteboard);
    711713
  • trunk/Source/WebCore/editing/Editor.cpp

    r259575 r259613  
    428428    target->dispatchEvent(event);
    429429    bool noDefaultProcessing = event->defaultPrevented();
    430     if (noDefaultProcessing && (kind == ClipboardEventKind::Copy || kind == ClipboardEventKind::Cut)) {
    431         auto pasteboard = Pasteboard::createForCopyAndPaste();
    432         pasteboard->clear();
    433         dataTransfer->commitToPasteboard(*pasteboard);
    434     }
     430    if (noDefaultProcessing && (kind == ClipboardEventKind::Copy || kind == ClipboardEventKind::Cut))
     431        dataTransfer->commitToPasteboard(*Pasteboard::createForCopyAndPaste());
    435432
    436433    dataTransfer->makeInvalidForSecurity();
  • trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm

    r259541 r259613  
    857857{
    858858    ASSERT(lists.count);
    859     NSLog(@"%s - %@", __PRETTY_FUNCTION__, lists);
    860     WTFReportBacktrace();
    861859    _stagedRegistrationInfoLists = lists;
    862860}
Note: See TracChangeset for help on using the changeset viewer.