attachment elements with `-webkit-user-drag: none;` should not be draggable
https://bugs.webkit.org/show_bug.cgi?id=241720
rdar://95401577

Reviewed by Tim Horton.

The logic to walk up the ancestor chain in search of draggable elements in `draggableElement()`
currently ignores `-webkit-user-drag` for `attachment` elements, and instead considers the
attachment draggable as long as it's either the only element in the selection range, or the
selection range does not encompass the hit-tested attachment element.

Fix this by only proceeding with the single-attachment-drag codepath (`DragSourceAction::Attachment`)
in the case where the dragged attachment has a `-webkit-user-drag` value that isn't `"none"`.

Test: WKAttachmentTests.UserDragNonePreventsDragOnAttachmentElement

* Source/WebCore/page/DragController.cpp:
(WebCore::DragController::draggableElement const):
* Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
(TestWebKitAPI::TEST):

Canonical link: https://commits.webkit.org/251650@main


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@295645 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/page/DragController.cpp b/Source/WebCore/page/DragController.cpp
index 9666ad4..a9dbe73 100644
--- a/Source/WebCore/page/DragController.cpp
+++ b/Source/WebCore/page/DragController.cpp
@@ -787,13 +787,17 @@
     if (auto attachment = enclosingAttachmentElement(*startElement)) {
         auto& selection = sourceFrame->selection().selection();
         bool isSingleAttachmentSelection = selection.start() == Position(attachment.get(), Position::PositionIsBeforeAnchor) && selection.end() == Position(attachment.get(), Position::PositionIsAfterAnchor);
+        auto* renderer = attachment->renderer();
+        if (!renderer || renderer->style().userDrag() == UserDrag::None)
+            return nullptr;
+
         auto selectedRange = selection.firstRange();
         if (isSingleAttachmentSelection || !selectedRange || !contains<ComposedTree>(*selectedRange, *attachment)) {
             state.type = DragSourceAction::Attachment;
             return attachment.get();
         }
     }
-#endif
+#endif // ENABLE(ATTACHMENT_ELEMENT)
 
     auto selectionDragElement = state.type.contains(DragSourceAction::Selection) && m_dragSourceAction.contains(DragSourceAction::Selection) ? startElement : nullptr;
     if (ImageOverlay::isOverlayText(startElement))
diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm
index c501ebf..80819a6 100644
--- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm
+++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm
@@ -40,9 +40,11 @@
 #import <MapKit/MapKit.h>
 #import <QuickLookThumbnailing/QLThumbnailGenerator.h>
 #import <WebKit/WKPreferencesRefPrivate.h>
+#import <WebKit/WKUserContentControllerPrivate.h>
 #import <WebKit/WKWebViewPrivateForTesting.h>
 #import <WebKit/WebArchive.h>
 #import <WebKit/WebKitPrivate.h>
+#import <WebKit/_WKUserStyleSheet.h>
 #import <wtf/RetainPtr.h>
 #import <wtf/SoftLinking.h>
 
@@ -1882,6 +1884,28 @@
     EXPECT_TRUE([[info data] isEqualToData:testImageData()]);
 }
 
+TEST(WKAttachmentTests, UserDragNonePreventsDragOnAttachmentElement)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto styleSheet = adoptNS([[_WKUserStyleSheet alloc] initWithSource:@"attachment { -webkit-user-drag: none; }" forMainFrameOnly:YES]);
+    [[configuration userContentController] _addUserStyleSheet:styleSheet.get()];
+    [configuration _setAttachmentElementEnabled:YES];
+
+    auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+    auto *webView = [simulator webView];
+    [webView synchronouslyLoadHTMLString:attachmentEditingTestMarkup];
+
+    auto file = adoptNS([[NSFileWrapper alloc] initWithURL:testPDFFileURL() options:0 error:nil]);
+    [webView synchronouslyInsertAttachmentWithFileWrapper:file.get() contentType:nil];
+    [simulator runFrom:NSMakePoint(15, 15) to:NSMakePoint(50, 50)];
+
+#if PLATFORM(MAC)
+    EXPECT_NULL([simulator draggingInfo]);
+#else
+    EXPECT_EQ(0U, [simulator sourceItemProviders].count);
+#endif
+}
+
 #pragma mark - Platform-specific tests
 
 #if PLATFORM(MAC)