Title: [226396] trunk
Revision
226396
Author
[email protected]
Date
2018-01-03 23:44:55 -0800 (Wed, 03 Jan 2018)

Log Message

[Attachment Support] Create attachment elements when dropping files on iOS
https://bugs.webkit.org/show_bug.cgi?id=181192
<rdar://problem/36280945>

Reviewed by Tim Horton.

Source/WebCore:

Implements support for dropping data as attachment elements on iOS. See comments below for more detail.

Tests:  WKAttachmentTests.InsertDroppedRichAndPlainTextFilesAsAttachments
        WKAttachmentTests.InsertDroppedZipArchiveAsAttachment
        WKAttachmentTests.InsertDroppedItemProvidersInOrder

* WebCore.xcodeproj/project.pbxproj:
* editing/WebContentReader.cpp:
(WebCore::WebContentReader::ensureFragment):

Add a new helper to create the WebContentReader's fragment, if it hasn't already been created.

* editing/WebContentReader.h:
* editing/cocoa/WebContentReaderCocoa.mm:
(WebCore::WebContentReader::readFilePaths):

Rename readFilenames to readFilePaths (which better reflects its parameters, which are file paths). Also, move
the implementation of readFilePaths to shared iOS/macOS code in WebContentReaderCocoa, and remove the stub
implementation on iOS.

There's a bit of code here that I kept macOS-only which deals with inserting file paths as plain text in
editable areas, but it's unclear to me why and if WebKit clients currently find this useful, so I left a FIXME
to investigate removing this altogether. Code for handling this plain text insertion of file paths on Mac was
introduced in r67403.

* editing/ios/WebContentReaderIOS.mm:
(WebCore::WebContentReader::readFilenames): Deleted.
* editing/mac/WebContentReaderMac.mm:
(WebCore::WebContentReader::readFilenames): Deleted.
* page/mac/DragControllerMac.mm:
(WebCore::DragController::updateSupportedTypeIdentifiersForDragHandlingMethod const):

Teach DragController to accept all types conforming to "public.item" and "public.content" on iOS, only when
attachment elements are enabled. This allows us to load content from item providers that we otherwise would not
have loaded, since we now have the ability to fall back to attachment element insertion if the type is not have
a default representation using standard web content.

* platform/Pasteboard.h:
* platform/PasteboardItemInfo.h: Added.
(WebCore::PasteboardItemInfo::encode const):
(WebCore::PasteboardItemInfo::decode):

Add PasteboardItemInfo, a struct that describes an item on the pasteboard. Also, implement encoding and decoding
support for PasteboardItemInfo. So far, the item info only describes file information about the pasteboard item,
and flags indicating whether the item prefers attachment or inline presentation.

* platform/PasteboardStrategy.h:

Replace getFilenamesForDataInteraction with informationForItemAtIndex. Instead of returning all of the file
paths associated with any item on the pasteboard, fetch a PasteboardItemInfo at a given item index, which
includes information about the file path as well as some other metadata we'll need when deciding how to read
pasteboard contents as a document fragment.

* platform/PlatformPasteboard.h:
* platform/cocoa/PasteboardCocoa.mm:
(WebCore::Pasteboard::read):
* platform/ios/AbstractPasteboard.h:
* platform/ios/PasteboardIOS.mm:
(WebCore::Pasteboard::read):
(WebCore::Pasteboard::readRespectingUTIFidelities):

Teach the iOS Pasteboard to read web content using attachment elements, if enabled. There are two scenarios in
which we would want to insert an attachment element:
(1) The item provider uses a preferred presentation style of attachment, in which case we bail out of trying to
    handle the drop using the default mechanisms, and simply insert it as an attachment. We need this to deal
    with the case where we drop text or HTML files from the Files app, so that we don't try and insert the
    contents of the text or HTML as inline web content.
(2) The item provider doesn't have a preferred attachment presentation style, but there's nothing WebKit would
    otherwise do with the dropped content, so insert an attachment element as a fallback. Examples where this is
    relevant are dropping a PDF or ZIP archive without attachment presentation style explicitly set.
We first check if we fall into case (1). If so, we can bail early by inserting an attachment; otherwise, we
proceed normally and see if we can read the contents of the drop as web content. If, at the end of default drop
handling, we don't still have a way to represent the dropped content, enter case (2).

(WebCore::Pasteboard::readFilePaths):
(WebCore::Pasteboard::readFilenames): Deleted.

Rename readFilenames to readFilePaths, and reimplement it using informationForItemAtIndex.

* platform/ios/PlatformPasteboardIOS.mm:
(WebCore::pasteboardItemPresentationStyle):
(WebCore::PlatformPasteboard::informationForItemAtIndex):
(WebCore::PlatformPasteboard::filenamesForDataInteraction): Deleted.

Implement informationForItemAtIndex and remove filenamesForDataInteraction. As before, we ask the pasteboard
(i.e. WebItemProviderPasteboard) for information about dropped file URLs. This time, we limit this to a single
file, so we don't end up creating multiple attachment elements for each representation of a single item
provider. See below for -preferredFileUploadURLAtIndex:fileType: for more detail.

* platform/ios/WebItemProviderPasteboard.h:
* platform/ios/WebItemProviderPasteboard.mm:
(-[WebItemProviderLoadResult initWithItemProvider:typesToLoad:]):
(-[WebItemProviderLoadResult canBeRepresentedAsFileUpload]):

Remove this synthesized instance variable and instead just check the item provider's preferredPresentationStyle.

(-[WebItemProviderLoadResult description]):

Add a verbose -description to the load result object. Useful for debugging what was content was loaded from an
item provider on drop.

(-[WebItemProviderPasteboard preferredFileUploadURLAtIndex:fileType:]):

Return the highest fidelity loaded type identifier for a given item.

(-[WebItemProviderPasteboard allDroppedFileURLs]):
(-[WebItemProviderPasteboard typeIdentifiersToLoadForRegisteredTypeIdentfiers:]):

Prefer flat RTFD to RTFD. In the case where attachments are enabled and we're accepting all types of content
using attachment elements as a fallback representation, if the source writes attributed strings to the
pasteboard with com.apple.rtfd at a higher fidelity than com.apple.flat-rtfd, we'll end up loading only
com.apple.rtfd and dropping the text as an attachment element because we cannot convert the dropped content to
markup. Instead, if flat RTFD is present in the item provider, always prefer that over RTFD so that dropping as
regular web content isn't overridden when attachment elements are enabled.

(-[WebItemProviderPasteboard doAfterLoadingProvidedContentIntoFileURLs:synchronousTimeout:]):
(-[WebItemProviderPasteboard droppedFileURLs]): Deleted.
* platform/mac/DragDataMac.mm:
(WebCore::DragData::containsCompatibleContent const):

DragData::containsCompatibleContent should be true when attachment elements are enabled, and there are files we
can drop as attachment elements.

* platform/mac/PasteboardMac.mm:
(WebCore::Pasteboard::read):
(WebCore::Pasteboard::readFilePaths):
(WebCore::Pasteboard::readFilenames): Deleted.

Source/WebKit:

Make some minor adjustments for changes to the pasteboard in WebCore. See WebCore/ChangeLog for more detail.
Teaches WebPasteboardProxy et. al. to plumb PasteboardItemInfo from the UI process to the web process via the
new `InformationForItemAtIndex` codepath.

* UIProcess/Cocoa/WebPasteboardProxyCocoa.mm:
(WebKit::WebPasteboardProxy::informationForItemAtIndex):
(WebKit::WebPasteboardProxy::getFilenamesForDataInteraction): Deleted.
* UIProcess/WebPasteboardProxy.h:
* UIProcess/WebPasteboardProxy.messages.in:
* WebProcess/WebCoreSupport/WebPlatformStrategies.cpp:
(WebKit::WebPlatformStrategies::informationForItemAtIndex):
(WebKit::WebPlatformStrategies::getFilenamesForDataInteraction): Deleted.
* WebProcess/WebCoreSupport/WebPlatformStrategies.h:

Source/WebKitLegacy/mac:

Make some minor adjustments for changes to the pasteboard in WebCore. See WebCore/ChangeLog for more detail.

* WebCoreSupport/WebPlatformStrategies.h:
* WebCoreSupport/WebPlatformStrategies.mm:
(WebPlatformStrategies::informationForItemAtIndex):
(WebPlatformStrategies::getFilenamesForDataInteraction): Deleted.

Tools:

Adds 3 new API tests to exercise different use cases of dropping content as attachment elements when the runtime
switch is enabled. See below for more details.

* TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
(-[NSItemProvider registerData:type:]):
(platformCopyPNG):
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/ios/DataInteractionTests.mm:

Fix some currently failing iOS drag and drop tests. In this case, there's no reason RTFD should appear in the
source item provider when dragging rich text *without* attachments, so this should have been a check for just
kUTTypeRTF instead.

(TestWebKitAPI::TEST):

Tests a few cases of inserting attachment elements via drop:
1.  We should distinguish between drops containing rich/plain text files from just dropping rich/plain text.
    Instead of inserting the contents as inline web content, this should generate attachment elements.
2.  Test the fallback mechanism for inserting attachment elements. If the preferred presentation style is not
    explicitly set, but there's nothing WebKit would otherwise do with the dropped content, then we should fall
    back to inserting the content as an attachment.
3.  Test that if multiple attachments and inline item providers are present, WebKit will respect the order in
    which they were inserted by the source (as opposed to, for instance, putting all of the attachments in front
    or at the end).

* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[TestWKWebView objectByEvaluatingJavaScript:]):

Add a helper method to return an object that represents the result of evaluating some given script, and rewrite
-stringByEvaluatingJavaScript to just turn around and call this.

(-[TestWKWebView stringByEvaluatingJavaScript:]):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (226395 => 226396)


--- trunk/Source/WebCore/ChangeLog	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/ChangeLog	2018-01-04 07:44:55 UTC (rev 226396)
@@ -1,3 +1,139 @@
+2018-01-03  Wenson Hsieh  <[email protected]>
+
+        [Attachment Support] Create attachment elements when dropping files on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=181192
+        <rdar://problem/36280945>
+
+        Reviewed by Tim Horton.
+
+        Implements support for dropping data as attachment elements on iOS. See comments below for more detail.
+
+        Tests:  WKAttachmentTests.InsertDroppedRichAndPlainTextFilesAsAttachments
+                WKAttachmentTests.InsertDroppedZipArchiveAsAttachment
+                WKAttachmentTests.InsertDroppedItemProvidersInOrder
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * editing/WebContentReader.cpp:
+        (WebCore::WebContentReader::ensureFragment):
+
+        Add a new helper to create the WebContentReader's fragment, if it hasn't already been created.
+
+        * editing/WebContentReader.h:
+        * editing/cocoa/WebContentReaderCocoa.mm:
+        (WebCore::WebContentReader::readFilePaths):
+
+        Rename readFilenames to readFilePaths (which better reflects its parameters, which are file paths). Also, move
+        the implementation of readFilePaths to shared iOS/macOS code in WebContentReaderCocoa, and remove the stub
+        implementation on iOS.
+
+        There's a bit of code here that I kept macOS-only which deals with inserting file paths as plain text in
+        editable areas, but it's unclear to me why and if WebKit clients currently find this useful, so I left a FIXME
+        to investigate removing this altogether. Code for handling this plain text insertion of file paths on Mac was
+        introduced in r67403.
+
+        * editing/ios/WebContentReaderIOS.mm:
+        (WebCore::WebContentReader::readFilenames): Deleted.
+        * editing/mac/WebContentReaderMac.mm:
+        (WebCore::WebContentReader::readFilenames): Deleted.
+        * page/mac/DragControllerMac.mm:
+        (WebCore::DragController::updateSupportedTypeIdentifiersForDragHandlingMethod const):
+
+        Teach DragController to accept all types conforming to "public.item" and "public.content" on iOS, only when
+        attachment elements are enabled. This allows us to load content from item providers that we otherwise would not
+        have loaded, since we now have the ability to fall back to attachment element insertion if the type is not have
+        a default representation using standard web content.
+
+        * platform/Pasteboard.h:
+        * platform/PasteboardItemInfo.h: Added.
+        (WebCore::PasteboardItemInfo::encode const):
+        (WebCore::PasteboardItemInfo::decode):
+
+        Add PasteboardItemInfo, a struct that describes an item on the pasteboard. Also, implement encoding and decoding
+        support for PasteboardItemInfo. So far, the item info only describes file information about the pasteboard item,
+        and flags indicating whether the item prefers attachment or inline presentation.
+
+        * platform/PasteboardStrategy.h:
+
+        Replace getFilenamesForDataInteraction with informationForItemAtIndex. Instead of returning all of the file
+        paths associated with any item on the pasteboard, fetch a PasteboardItemInfo at a given item index, which
+        includes information about the file path as well as some other metadata we'll need when deciding how to read
+        pasteboard contents as a document fragment.
+
+        * platform/PlatformPasteboard.h:
+        * platform/cocoa/PasteboardCocoa.mm:
+        (WebCore::Pasteboard::read):
+        * platform/ios/AbstractPasteboard.h:
+        * platform/ios/PasteboardIOS.mm:
+        (WebCore::Pasteboard::read):
+        (WebCore::Pasteboard::readRespectingUTIFidelities):
+
+        Teach the iOS Pasteboard to read web content using attachment elements, if enabled. There are two scenarios in
+        which we would want to insert an attachment element:
+        (1) The item provider uses a preferred presentation style of attachment, in which case we bail out of trying to
+            handle the drop using the default mechanisms, and simply insert it as an attachment. We need this to deal
+            with the case where we drop text or HTML files from the Files app, so that we don't try and insert the
+            contents of the text or HTML as inline web content.
+        (2) The item provider doesn't have a preferred attachment presentation style, but there's nothing WebKit would
+            otherwise do with the dropped content, so insert an attachment element as a fallback. Examples where this is
+            relevant are dropping a PDF or ZIP archive without attachment presentation style explicitly set.
+        We first check if we fall into case (1). If so, we can bail early by inserting an attachment; otherwise, we
+        proceed normally and see if we can read the contents of the drop as web content. If, at the end of default drop
+        handling, we don't still have a way to represent the dropped content, enter case (2).
+
+        (WebCore::Pasteboard::readFilePaths):
+        (WebCore::Pasteboard::readFilenames): Deleted.
+
+        Rename readFilenames to readFilePaths, and reimplement it using informationForItemAtIndex.
+
+        * platform/ios/PlatformPasteboardIOS.mm:
+        (WebCore::pasteboardItemPresentationStyle):
+        (WebCore::PlatformPasteboard::informationForItemAtIndex):
+        (WebCore::PlatformPasteboard::filenamesForDataInteraction): Deleted.
+
+        Implement informationForItemAtIndex and remove filenamesForDataInteraction. As before, we ask the pasteboard
+        (i.e. WebItemProviderPasteboard) for information about dropped file URLs. This time, we limit this to a single
+        file, so we don't end up creating multiple attachment elements for each representation of a single item
+        provider. See below for -preferredFileUploadURLAtIndex:fileType: for more detail.
+
+        * platform/ios/WebItemProviderPasteboard.h:
+        * platform/ios/WebItemProviderPasteboard.mm:
+        (-[WebItemProviderLoadResult initWithItemProvider:typesToLoad:]):
+        (-[WebItemProviderLoadResult canBeRepresentedAsFileUpload]):
+
+        Remove this synthesized instance variable and instead just check the item provider's preferredPresentationStyle.
+
+        (-[WebItemProviderLoadResult description]):
+
+        Add a verbose -description to the load result object. Useful for debugging what was content was loaded from an
+        item provider on drop.
+
+        (-[WebItemProviderPasteboard preferredFileUploadURLAtIndex:fileType:]):
+
+        Return the highest fidelity loaded type identifier for a given item.
+
+        (-[WebItemProviderPasteboard allDroppedFileURLs]):
+        (-[WebItemProviderPasteboard typeIdentifiersToLoadForRegisteredTypeIdentfiers:]):
+
+        Prefer flat RTFD to RTFD. In the case where attachments are enabled and we're accepting all types of content
+        using attachment elements as a fallback representation, if the source writes attributed strings to the
+        pasteboard with com.apple.rtfd at a higher fidelity than com.apple.flat-rtfd, we'll end up loading only
+        com.apple.rtfd and dropping the text as an attachment element because we cannot convert the dropped content to
+        markup. Instead, if flat RTFD is present in the item provider, always prefer that over RTFD so that dropping as
+        regular web content isn't overridden when attachment elements are enabled.
+
+        (-[WebItemProviderPasteboard doAfterLoadingProvidedContentIntoFileURLs:synchronousTimeout:]):
+        (-[WebItemProviderPasteboard droppedFileURLs]): Deleted.
+        * platform/mac/DragDataMac.mm:
+        (WebCore::DragData::containsCompatibleContent const):
+
+        DragData::containsCompatibleContent should be true when attachment elements are enabled, and there are files we
+        can drop as attachment elements.
+
+        * platform/mac/PasteboardMac.mm:
+        (WebCore::Pasteboard::read):
+        (WebCore::Pasteboard::readFilePaths):
+        (WebCore::Pasteboard::readFilenames): Deleted.
+
 2018-01-03  Ting-Wei Lan  <[email protected]>
 
         Replace hard-coded paths in shebangs with #!/usr/bin/env

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (226395 => 226396)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2018-01-04 07:44:55 UTC (rev 226396)
@@ -4653,6 +4653,7 @@
 		F48223101E3869B80066FC79 /* WebItemProviderPasteboard.mm in Sources */ = {isa = PBXBuildFile; fileRef = F482230E1E3869B80066FC79 /* WebItemProviderPasteboard.mm */; };
 		F48223111E3869B80066FC79 /* WebItemProviderPasteboard.h in Headers */ = {isa = PBXBuildFile; fileRef = F482230F1E3869B80066FC79 /* WebItemProviderPasteboard.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		F48223131E386E240066FC79 /* AbstractPasteboard.h in Headers */ = {isa = PBXBuildFile; fileRef = F48223121E386E240066FC79 /* AbstractPasteboard.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		F49786881FF45FA500E060AB /* PasteboardItemInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F49786871FF45FA500E060AB /* PasteboardItemInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		F4BFB9851E1DDF9B00862C24 /* DumpEditingHistory.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389831E1DDF2B0076B7EA /* DumpEditingHistory.js */; };
 		F4BFB9861E1DDF9B00862C24 /* EditingHistoryUtil.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389841E1DDF2B0076B7EA /* EditingHistoryUtil.js */; };
 		F50664F8157F52DC00AC226F /* FormController.h in Headers */ = {isa = PBXBuildFile; fileRef = F50664F6157F52DC00AC226F /* FormController.h */; };
@@ -14086,6 +14087,7 @@
 		F48223121E386E240066FC79 /* AbstractPasteboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractPasteboard.h; sourceTree = "<group>"; };
 		F48389831E1DDF2B0076B7EA /* DumpEditingHistory.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; name = DumpEditingHistory.js; path = Scripts/DumpEditingHistory.js; sourceTree = "<group>"; };
 		F48389841E1DDF2B0076B7EA /* EditingHistoryUtil.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; name = EditingHistoryUtil.js; path = Scripts/EditingHistoryUtil.js; sourceTree = "<group>"; };
+		F49786871FF45FA500E060AB /* PasteboardItemInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PasteboardItemInfo.h; sourceTree = "<group>"; };
 		F50664F5157F52DC00AC226F /* FormController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormController.cpp; sourceTree = "<group>"; };
 		F50664F6157F52DC00AC226F /* FormController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormController.h; sourceTree = "<group>"; };
 		F513A3E915FF4841001526DB /* ValidationMessageClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValidationMessageClient.h; sourceTree = "<group>"; };
@@ -23691,6 +23693,7 @@
 				4184F5151EAF059800F18BF0 /* OrientationNotifier.h */,
 				2EE02A1E1F7324280006AF72 /* Pasteboard.cpp */,
 				4B2708C50AF19EE40065127F /* Pasteboard.h */,
+				F49786871FF45FA500E060AB /* PasteboardItemInfo.h */,
 				C5F765B414E1D414006C899B /* PasteboardStrategy.h */,
 				1AF5E4D21E56735A004A1F01 /* PasteboardWriterData.cpp */,
 				1AF5E4D31E56735A004A1F01 /* PasteboardWriterData.h */,
@@ -28690,6 +28693,7 @@
 				536D5A23193E8E0C00CE4CAB /* ParsingUtilities.h in Headers */,
 				F55B3DCA1251F12D003EF269 /* PasswordInputType.h in Headers */,
 				4B2708C70AF19EE40065127F /* Pasteboard.h in Headers */,
+				F49786881FF45FA500E060AB /* PasteboardItemInfo.h in Headers */,
 				C598905714E9C28000E8D18B /* PasteboardStrategy.h in Headers */,
 				1AF5E4E31E5779B1004A1F01 /* PasteboardWriter.h in Headers */,
 				1AF5E4D51E56735B004A1F01 /* PasteboardWriterData.h in Headers */,

Modified: trunk/Source/WebCore/editing/WebContentReader.cpp (226395 => 226396)


--- trunk/Source/WebCore/editing/WebContentReader.cpp	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/editing/WebContentReader.cpp	2018-01-04 07:44:55 UTC (rev 226396)
@@ -31,6 +31,14 @@
 
 namespace WebCore {
 
+DocumentFragment& WebContentReader::ensureFragment()
+{
+    ASSERT(frame.document());
+    if (!fragment)
+        fragment = frame.document()->createDocumentFragment();
+    return *fragment;
+}
+
 void WebContentReader::addFragment(Ref<DocumentFragment>&& newFragment)
 {
     if (!fragment)

Modified: trunk/Source/WebCore/editing/WebContentReader.h (226395 => 226396)


--- trunk/Source/WebCore/editing/WebContentReader.h	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/editing/WebContentReader.h	2018-01-04 07:44:55 UTC (rev 226396)
@@ -63,12 +63,13 @@
     {
     }
 
+    DocumentFragment& ensureFragment();
     void addFragment(Ref<DocumentFragment>&&);
 
 private:
 #if PLATFORM(COCOA)
     bool readWebArchive(SharedBuffer&) override;
-    bool readFilenames(const Vector<String>&) override;
+    bool readFilePaths(const Vector<String>&) override;
     bool readHTML(const String&) override;
     bool readRTFD(SharedBuffer&) override;
     bool readRTF(SharedBuffer&) override;
@@ -90,7 +91,7 @@
 private:
 #if PLATFORM(COCOA)
     bool readWebArchive(SharedBuffer&) override;
-    bool readFilenames(const Vector<String>&) override { return false; }
+    bool readFilePaths(const Vector<String>&) override { return false; }
     bool readHTML(const String&) override;
     bool readRTFD(SharedBuffer&) override;
     bool readRTF(SharedBuffer&) override;

Modified: trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm (226395 => 226396)


--- trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm	2018-01-04 07:44:55 UTC (rev 226396)
@@ -596,4 +596,34 @@
     return fragment;
 }
 
+bool WebContentReader::readFilePaths(const Vector<String>& paths)
+{
+    if (paths.isEmpty() || !frame.document())
+        return false;
+
+    auto& document = *frame.document();
+    bool readAnyFilePath = false;
+    for (auto& path : paths) {
+#if ENABLE(ATTACHMENT_ELEMENT)
+        if (RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled()) {
+            auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, document);
+            attachment->setUniqueIdentifier(createCanonicalUUIDString());
+            attachment->setFile(File::create(path), HTMLAttachmentElement::UpdateDisplayAttributes::Yes);
+            ensureFragment().appendChild(attachment);
+            readAnyFilePath = true;
+            continue;
+        }
+#endif
+#if PLATFORM(MAC)
+        // FIXME: Does (and should) any macOS client depend on inserting file paths as plain text in web content?
+        // If not, we should just remove this.
+        auto paragraph = createDefaultParagraphElement(document);
+        paragraph->appendChild(document.createTextNode(userVisibleString([NSURL fileURLWithPath:path])));
+        ensureFragment().appendChild(paragraph);
+        readAnyFilePath = true;
+#endif
+    }
+    return readAnyFilePath;
 }
+
+}

Modified: trunk/Source/WebCore/editing/ios/WebContentReaderIOS.mm (226395 => 226396)


--- trunk/Source/WebCore/editing/ios/WebContentReaderIOS.mm	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/editing/ios/WebContentReaderIOS.mm	2018-01-04 07:44:55 UTC (rev 226396)
@@ -47,11 +47,6 @@
 
 namespace WebCore {
 
-bool WebContentReader::readFilenames(const Vector<String>&)
-{
-    return false;
-}
-
 bool WebContentReader::readURL(const URL& url, const String& title)
 {
     if (url.isEmpty())

Modified: trunk/Source/WebCore/editing/mac/WebContentReaderMac.mm (226395 => 226396)


--- trunk/Source/WebCore/editing/mac/WebContentReaderMac.mm	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/editing/mac/WebContentReaderMac.mm	2018-01-04 07:44:55 UTC (rev 226396)
@@ -38,49 +38,15 @@
 #import "FrameLoader.h"
 #import "FrameLoaderClient.h"
 #import "HTMLAnchorElement.h"
-#import "HTMLAttachmentElement.h"
 #import "HTMLNames.h"
 #import "LegacyWebArchive.h"
-#import "MIMETypeRegistry.h"
-#import "RuntimeEnabledFeatures.h"
 #import "Settings.h"
 #import "Text.h"
 #import "WebCoreNSURLExtras.h"
 #import "markup.h"
-#import <wtf/UUID.h>
 
 namespace WebCore {
 
-bool WebContentReader::readFilenames(const Vector<String>& paths)
-{
-    if (paths.isEmpty())
-        return false;
-
-    if (!frame.document())
-        return false;
-    Document& document = *frame.document();
-
-    fragment = document.createDocumentFragment();
-
-    for (auto& text : paths) {
-#if ENABLE(ATTACHMENT_ELEMENT)
-        if (RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled()) {
-            auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, document);
-            attachment->setUniqueIdentifier(createCanonicalUUIDString());
-            attachment->setFile(File::create([NSURL fileURLWithPath:text].path), HTMLAttachmentElement::UpdateDisplayAttributes::Yes);
-            fragment->appendChild(attachment);
-            continue;
-        }
-#else
-        auto paragraph = createDefaultParagraphElement(document);
-        paragraph->appendChild(document.createTextNode(userVisibleString([NSURL fileURLWithPath:text])));
-        fragment->appendChild(paragraph);
-#endif
-    }
-
-    return true;
-}
-
 bool WebContentReader::readURL(const URL& url, const String& title)
 {
     if (url.string().isEmpty())

Modified: trunk/Source/WebCore/page/mac/DragControllerMac.mm (226395 => 226396)


--- trunk/Source/WebCore/page/mac/DragControllerMac.mm	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/page/mac/DragControllerMac.mm	2018-01-04 07:44:55 UTC (rev 226396)
@@ -45,6 +45,7 @@
 #import "PasteboardStrategy.h"
 #import "PlatformStrategies.h"
 #import "Range.h"
+#import "RuntimeEnabledFeatures.h"
 
 #if ENABLE(DATA_INTERACTION)
 #import <MobileCoreServices/MobileCoreServices.h>
@@ -125,8 +126,14 @@
         supportedTypes.append(kUTTypePlainText);
         break;
     case DragHandlingMethod::EditRichText:
-        for (NSString *type in Pasteboard::supportedWebContentPasteboardTypes())
-            supportedTypes.append(type);
+        if (RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled()) {
+            supportedTypes.append(WebArchivePboardType);
+            supportedTypes.append(kUTTypeContent);
+            supportedTypes.append(kUTTypeItem);
+        } else {
+            for (NSString *type in Pasteboard::supportedWebContentPasteboardTypes())
+                supportedTypes.append(type);
+        }
         break;
     default:
         for (NSString *type in Pasteboard::supportedFileUploadPasteboardTypes())

Modified: trunk/Source/WebCore/platform/Pasteboard.h (226395 => 226396)


--- trunk/Source/WebCore/platform/Pasteboard.h	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/platform/Pasteboard.h	2018-01-04 07:44:55 UTC (rev 226396)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "DragImage.h"
+#include "PasteboardItemInfo.h"
 #include "URL.h"
 #include <wtf/HashMap.h>
 #include <wtf/ListHashSet.h>
@@ -134,7 +135,7 @@
 
 #if PLATFORM(COCOA)
     virtual bool readWebArchive(SharedBuffer&) = 0;
-    virtual bool readFilenames(const Vector<String>&) = 0;
+    virtual bool readFilePaths(const Vector<String>&) = 0;
     virtual bool readHTML(const String&) = 0;
     virtual bool readRTFD(SharedBuffer&) = 0;
     virtual bool readRTF(SharedBuffer&) = 0;
@@ -290,7 +291,7 @@
 #endif
 
 #if PLATFORM(COCOA)
-    Vector<String> readFilenames();
+    Vector<String> readFilePaths();
     String readPlatformValueAsString(const String& domType, long changeCount, const String& pasteboardName);
     static void addHTMLClipboardTypesForCocoaType(ListHashSet<String>& resultTypes, const String& cocoaType);
     String readStringForPlatformType(const String&);

Added: trunk/Source/WebCore/platform/PasteboardItemInfo.h (0 => 226396)


--- trunk/Source/WebCore/platform/PasteboardItemInfo.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/PasteboardItemInfo.h	2018-01-04 07:44:55 UTC (rev 226396)
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/Optional.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+enum class PasteboardItemPresentationStyle {
+    Unspecified,
+    Inline,
+    Attachment
+};
+
+struct PasteboardItemInfo {
+    String pathForFileUpload;
+    String contentTypeForFileUpload;
+    PasteboardItemPresentationStyle preferredPresentationStyle { PasteboardItemPresentationStyle::Unspecified };
+
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static std::optional<PasteboardItemInfo> decode(Decoder&);
+};
+
+template<class Encoder>
+void PasteboardItemInfo::encode(Encoder& encoder) const
+{
+    encoder << pathForFileUpload << contentTypeForFileUpload;
+    encoder.encodeEnum(preferredPresentationStyle);
+}
+
+template<class Decoder>
+std::optional<PasteboardItemInfo> PasteboardItemInfo::decode(Decoder& decoder)
+{
+    PasteboardItemInfo result;
+    if (!decoder.decode(result.pathForFileUpload))
+        return std::nullopt;
+
+    if (!decoder.decode(result.contentTypeForFileUpload))
+        return std::nullopt;
+
+    if (!decoder.decodeEnum(result.preferredPresentationStyle))
+        return std::nullopt;
+
+    return WTFMove(result);
+}
+
+}
+
+namespace WTF {
+
+template<typename> struct EnumTraits;
+template<typename E, E...> struct EnumValues;
+
+template<> struct EnumTraits<WebCore::PasteboardItemPresentationStyle> {
+    using values = EnumValues<
+        WebCore::PasteboardItemPresentationStyle,
+        WebCore::PasteboardItemPresentationStyle::Unspecified,
+        WebCore::PasteboardItemPresentationStyle::Inline,
+        WebCore::PasteboardItemPresentationStyle::Attachment
+    >;
+};
+
+} // namespace WTF

Modified: trunk/Source/WebCore/platform/PasteboardStrategy.h (226395 => 226396)


--- trunk/Source/WebCore/platform/PasteboardStrategy.h	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/platform/PasteboardStrategy.h	2018-01-04 07:44:55 UTC (rev 226396)
@@ -35,6 +35,7 @@
 class SharedBuffer;
 class URL;
 struct PasteboardImage;
+struct PasteboardItemInfo;
 struct PasteboardURL;
 struct PasteboardWebContent;
 struct PasteboardCustomData;
@@ -50,7 +51,7 @@
     virtual String readStringFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName) = 0;
     virtual RefPtr<SharedBuffer> readBufferFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName) = 0;
     virtual URL readURLFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName, String& title) = 0;
-    virtual void getFilenamesForDataInteraction(Vector<String>& filenames, const String& pasteboardName) = 0;
+    virtual PasteboardItemInfo informationForItemAtIndex(int index, const String& pasteboardName) = 0;
     virtual void updateSupportedTypeIdentifiers(const Vector<String>& identifiers, const String& pasteboardName) = 0;
     virtual void getTypesByFidelityForItemAtIndex(Vector<String>& types, uint64_t index, const String& pasteboardName) = 0;
 #endif // PLATFORM(IOS)

Modified: trunk/Source/WebCore/platform/PlatformPasteboard.h (226395 => 226396)


--- trunk/Source/WebCore/platform/PlatformPasteboard.h	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/platform/PlatformPasteboard.h	2018-01-04 07:44:55 UTC (rev 226396)
@@ -51,6 +51,7 @@
 class URL;
 struct PasteboardCustomData;
 struct PasteboardImage;
+struct PasteboardItemInfo;
 struct PasteboardURL;
 struct PasteboardWebContent;
 
@@ -59,7 +60,7 @@
     WEBCORE_EXPORT explicit PlatformPasteboard(const String& pasteboardName);
 #if PLATFORM(IOS) || PLATFORM(WPE)
     WEBCORE_EXPORT PlatformPasteboard();
-    WEBCORE_EXPORT Vector<String> filenamesForDataInteraction();
+    WEBCORE_EXPORT PasteboardItemInfo informationForItemAtIndex(int index);
     WEBCORE_EXPORT void getTypesByFidelityForItemAtIndex(Vector<String>& types, int index);
     WEBCORE_EXPORT void updateSupportedTypeIdentifiers(const Vector<String>& types);
 #endif

Modified: trunk/Source/WebCore/platform/cocoa/PasteboardCocoa.mm (226395 => 226396)


--- trunk/Source/WebCore/platform/cocoa/PasteboardCocoa.mm	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/platform/cocoa/PasteboardCocoa.mm	2018-01-04 07:44:55 UTC (rev 226396)
@@ -191,7 +191,7 @@
 
 void Pasteboard::read(PasteboardFileReader& reader)
 {
-    auto filenames = readFilenames();
+    auto filenames = readFilePaths();
     if (!filenames.isEmpty()) {
         for (auto& filename : filenames)
             reader.readFilename(filename);

Modified: trunk/Source/WebCore/platform/ios/AbstractPasteboard.h (226395 => 226396)


--- trunk/Source/WebCore/platform/ios/AbstractPasteboard.h	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/platform/ios/AbstractPasteboard.h	2018-01-04 07:44:55 UTC (rev 226396)
@@ -56,7 +56,8 @@
 - (void)setItems:(NSArray<NSDictionary *> *)items;
 - (NSArray<NSString *> *)pasteboardTypesByFidelityForItemAtIndex:(NSUInteger)index;
 @property (readonly, nonatomic) NSInteger numberOfFiles;
-@property (readonly, nonatomic) NSArray<NSURL *> *droppedFileURLs;
+@property (readonly, nonatomic) NSArray<NSURL *> *allDroppedFileURLs;
+- (nullable NSURL *)preferredFileUploadURLAtIndex:(NSUInteger)index fileType:(NSString *_Nullable *_Nullable)outFileType;
 - (void)updateSupportedTypeIdentifiers:(NSArray<NSString *> *)types;
 
 @end

Modified: trunk/Source/WebCore/platform/ios/PasteboardIOS.mm (226395 => 226396)


--- trunk/Source/WebCore/platform/ios/PasteboardIOS.mm	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/platform/ios/PasteboardIOS.mm	2018-01-04 07:44:55 UTC (rev 226396)
@@ -31,6 +31,7 @@
 #import "PasteboardStrategy.h"
 #import "PlatformPasteboard.h"
 #import "PlatformStrategies.h"
+#import "RuntimeEnabledFeatures.h"
 #import "SharedBuffer.h"
 #import "URL.h"
 #import "UTIUtilities.h"
@@ -244,10 +245,10 @@
 
     for (int i = 0; i < numberOfItems; i++) {
         for (int typeIndex = 0; typeIndex < numberOfTypes; typeIndex++) {
-            auto result = readPasteboardWebContentDataForType(reader, strategy, [types objectAtIndex:typeIndex], i);
-            if (result == ReaderResult::PasteboardWasChangedExternally)
+            auto itemResult = readPasteboardWebContentDataForType(reader, strategy, [types objectAtIndex:typeIndex], i);
+            if (itemResult == ReaderResult::PasteboardWasChangedExternally)
                 return;
-            if (result == ReaderResult::ReadType)
+            if (itemResult == ReaderResult::ReadType)
                 break;
         }
     }
@@ -266,17 +267,30 @@
     ASSERT(respectsUTIFidelities());
     auto& strategy = *platformStrategies()->pasteboardStrategy();
     for (NSUInteger index = 0, numberOfItems = strategy.getPasteboardItemsCount(m_pasteboardName); index < numberOfItems; ++index) {
+#if ENABLE(ATTACHMENT_ELEMENT)
+        auto info = strategy.informationForItemAtIndex(index, m_pasteboardName);
+        bool canReadAttachment = RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled() && !info.pathForFileUpload.isEmpty();
+        if (canReadAttachment && info.preferredPresentationStyle == PasteboardItemPresentationStyle::Attachment) {
+            reader.readFilePaths({ info.pathForFileUpload });
+            continue;
+        }
+#endif
         // Try to read data from each type identifier that this pasteboard item supports, and WebKit also recognizes. Type identifiers are
         // read in order of fidelity, as specified by each pasteboard item.
         Vector<String> typesForItemInOrderOfFidelity;
         strategy.getTypesByFidelityForItemAtIndex(typesForItemInOrderOfFidelity, index, m_pasteboardName);
+        ReaderResult result = ReaderResult::DidNotReadType;
         for (auto& type : typesForItemInOrderOfFidelity) {
-            auto result = readPasteboardWebContentDataForType(reader, strategy, type, index);
+            result = readPasteboardWebContentDataForType(reader, strategy, type, index);
             if (result == ReaderResult::PasteboardWasChangedExternally)
                 return;
             if (result == ReaderResult::ReadType)
                 break;
         }
+#if ENABLE(ATTACHMENT_ELEMENT)
+        if (canReadAttachment && result == ReaderResult::DidNotReadType)
+            reader.readFilePaths({ info.pathForFileUpload });
+#endif
     }
 }
 
@@ -405,12 +419,17 @@
     platformStrategies()->pasteboardStrategy()->writeToPasteboard(cocoaType.get(), data, m_pasteboardName);
 }
 
-Vector<String> Pasteboard::readFilenames()
+Vector<String> Pasteboard::readFilePaths()
 {
-    Vector<String> filenames;
-    // Currently, data interaction is the only case on iOS where the pasteboard may contain relevant filenames.
-    platformStrategies()->pasteboardStrategy()->getFilenamesForDataInteraction(filenames, m_pasteboardName);
-    return filenames;
+    Vector<String> filePaths;
+    auto& strategy = *platformStrategies()->pasteboardStrategy();
+    for (NSUInteger index = 0, numberOfItems = strategy.getPasteboardItemsCount(m_pasteboardName); index < numberOfItems; ++index) {
+        // Currently, drag and drop is the only case on iOS where the "pasteboard" may contain file paths.
+        auto filePath = strategy.informationForItemAtIndex(index, m_pasteboardName).pathForFileUpload;
+        if (!filePath.isEmpty())
+            filePaths.append(WTFMove(filePath));
+    }
+    return filePaths;
 }
 
 }

Modified: trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm (226395 => 226396)


--- trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm	2018-01-04 07:44:55 UTC (rev 226396)
@@ -102,18 +102,49 @@
     return [m_pasteboard respondsToSelector:@selector(numberOfFiles)] ? [m_pasteboard numberOfFiles] : 0;
 }
 
-Vector<String> PlatformPasteboard::filenamesForDataInteraction()
+#if PASTEBOARD_SUPPORTS_ITEM_PROVIDERS
+
+static PasteboardItemPresentationStyle pasteboardItemPresentationStyle(UIPreferredPresentationStyle style)
 {
-    if (![m_pasteboard respondsToSelector:@selector(droppedFileURLs)])
+    switch (style) {
+    case UIPreferredPresentationStyleUnspecified:
+        return PasteboardItemPresentationStyle::Unspecified;
+    case UIPreferredPresentationStyleInline:
+        return PasteboardItemPresentationStyle::Inline;
+    case UIPreferredPresentationStyleAttachment:
+        return PasteboardItemPresentationStyle::Attachment;
+    default:
+        ASSERT_NOT_REACHED();
+        return PasteboardItemPresentationStyle::Unspecified;
+    }
+}
+
+PasteboardItemInfo PlatformPasteboard::informationForItemAtIndex(int index)
+{
+    if (index >= [m_pasteboard numberOfItems])
         return { };
 
-    Vector<String> filenames;
-    for (NSURL *fileURL in [m_pasteboard droppedFileURLs])
-        filenames.append(fileURL.path);
+    PasteboardItemInfo info;
+    if ([m_pasteboard respondsToSelector:@selector(preferredFileUploadURLAtIndex:fileType:)]) {
+        NSString *fileType = nil;
+        info.pathForFileUpload = [m_pasteboard preferredFileUploadURLAtIndex:index fileType:&fileType].path;
+        info.contentTypeForFileUpload = fileType;
+    }
 
-    return filenames;
+    NSItemProvider *itemProvider = [[m_pasteboard itemProviders] objectAtIndex:index];
+    info.preferredPresentationStyle = pasteboardItemPresentationStyle(itemProvider.preferredPresentationStyle);
+    return info;
 }
 
+#else
+
+PasteboardItemInfo PlatformPasteboard::informationForItemAtIndex(int)
+{
+    return { };
+}
+
+#endif
+
 static bool pasteboardMayContainFilePaths(id<AbstractPasteboard> pasteboard)
 {
 #if PASTEBOARD_SUPPORTS_ITEM_PROVIDERS

Modified: trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.h (226395 => 226396)


--- trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.h	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.h	2018-01-04 07:44:55 UTC (rev 226396)
@@ -90,8 +90,11 @@
 @property (readonly, nonatomic) NSInteger changeCount;
 
 // This will only be non-empty when an operation is being performed.
-@property (readonly, nonatomic) NSArray<NSURL *> *droppedFileURLs;
+@property (readonly, nonatomic) NSArray<NSURL *> *allDroppedFileURLs;
 
+// The preferred file URL corresponds to the highest fidelity non-private UTI that was loaded.
+- (nullable NSURL *)preferredFileUploadURLAtIndex:(NSUInteger)index fileType:(NSString *_Nullable *_Nullable)outFileType;
+
 @property (readonly, nonatomic) BOOL hasPendingOperation;
 - (void)incrementPendingOperationCount;
 - (void)decrementPendingOperationCount;

Modified: trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm (226395 => 226396)


--- trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm	2018-01-04 07:44:55 UTC (rev 226396)
@@ -243,11 +243,15 @@
     _fileURLs = adoptNS([[NSMutableDictionary alloc] init]);
     _itemProvider = itemProvider;
     _typesToLoad = typesToLoad;
-    _canBeRepresentedAsFileUpload = itemProvider.preferredPresentationStyle != UIPreferredPresentationStyleInline;
 
     return self;
 }
 
+- (BOOL)canBeRepresentedAsFileUpload
+{
+    return [_itemProvider preferredPresentationStyle] != UIPreferredPresentationStyleInline;
+}
+
 - (NSArray<NSString *> *)typesToLoad
 {
     return _typesToLoad.get();
@@ -278,6 +282,26 @@
     return _itemProvider.get();
 }
 
+- (NSString *)description
+{
+    __block NSMutableString *description = [NSMutableString string];
+    [description appendFormat:@"<%@: %p typesToLoad: [ ", [self class], self];
+    [_typesToLoad enumerateObjectsUsingBlock:^(NSString *type, NSUInteger index, BOOL *) {
+        [description appendString:type];
+        if (index + 1 < [_typesToLoad count])
+            [description appendString:@", "];
+    }];
+    [description appendFormat:@" ] fileURLs: { "];
+    __block NSUInteger index = 0;
+    [_fileURLs enumerateKeysAndObjectsUsingBlock:^(NSString *type, NSURL *url, BOOL *) {
+        [description appendFormat:@"%@ => \"%@\"", type, url.path];
+        if (++index < [_fileURLs count])
+            [description appendString:@", "];
+    }];
+    [description appendFormat:@" }>"];
+    return description;
+}
+
 @end
 
 @interface WebItemProviderPasteboard ()
@@ -470,8 +494,39 @@
     return _changeCount;
 }
 
-- (NSArray<NSURL *> *)droppedFileURLs
+- (NSURL *)preferredFileUploadURLAtIndex:(NSUInteger)index fileType:(NSString **)outFileType
 {
+    if (outFileType)
+        *outFileType = nil;
+
+    if (index >= _loadResults.size())
+        return nil;
+
+    auto result = _loadResults[index];
+    if (![result canBeRepresentedAsFileUpload])
+        return nil;
+
+    NSItemProvider *itemProvider = [result itemProvider];
+    for (NSString *registeredTypeIdentifier in itemProvider.registeredTypeIdentifiers) {
+        // Search for the highest fidelity non-private type identifier we loaded from the item provider.
+        if (!UTTypeIsDeclared((CFStringRef)registeredTypeIdentifier) && !UTTypeIsDynamic((CFStringRef)registeredTypeIdentifier))
+            continue;
+
+        for (NSString *loadedTypeIdentifier in [result loadedTypeIdentifiers]) {
+            if (!UTTypeConformsTo((CFStringRef)registeredTypeIdentifier, (CFStringRef)loadedTypeIdentifier))
+                continue;
+
+            if (outFileType)
+                *outFileType = loadedTypeIdentifier;
+            return [result fileURLForType:loadedTypeIdentifier];
+        }
+    }
+
+    return nil;
+}
+
+- (NSArray<NSURL *> *)allDroppedFileURLs
+{
     NSMutableArray<NSURL *> *fileURLs = [NSMutableArray array];
     for (auto loadResult : _loadResults) {
         if ([loadResult canBeRepresentedAsFileUpload])
@@ -539,8 +594,19 @@
     NSMutableSet *typesToLoad = [NSMutableSet set];
     NSString *highestFidelityContentType = nil;
 
+    BOOL containsFlatRTFD = [registeredTypeIdentifiers containsObject:(NSString *)kUTTypeFlatRTFD];
     // First, we want to either load the highest fidelity supported type or the highest fidelity generic content type.
     for (NSString *registeredTypeIdentifier in registeredTypeIdentifiers) {
+        if (containsFlatRTFD && [registeredTypeIdentifier isEqualToString:(NSString *)kUTTypeRTFD]) {
+            // In the case where attachments are enabled and we're accepting all types of content using attachment
+            // elements as a fallback representation, if the source writes attributed strings to the pasteboard with
+            // com.apple.rtfd at a higher fidelity than com.apple.flat-rtfd, we'll end up loading only com.apple.rtfd
+            // and dropping the text as an attachment element because we cannot convert the dropped content to markup.
+            // Instead, if flat RTFD is present in the item provider, always prefer that over RTFD so that dropping as
+            // regular web content isn't overridden by enabling attachment elements.
+            continue;
+        }
+
         if (typeConformsToTypes(registeredTypeIdentifier, _supportedTypeIdentifiers.get())) {
             [typesToLoad addObject:registeredTypeIdentifier];
             break;
@@ -626,7 +692,7 @@
                 retainedSelf->_loadResults.append(loadResult);
         }
 
-        completionBlock([retainedSelf droppedFileURLs]);
+        completionBlock([retainedSelf allDroppedFileURLs]);
     };
 
     if (synchronousTimeout > 0 && !dispatch_group_wait(synchronousFileLoadingGroup.get(), dispatch_time(DISPATCH_TIME_NOW, synchronousTimeout * NSEC_PER_SEC))) {

Modified: trunk/Source/WebCore/platform/mac/DragDataMac.mm (226395 => 226396)


--- trunk/Source/WebCore/platform/mac/DragDataMac.mm	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/platform/mac/DragDataMac.mm	2018-01-04 07:44:55 UTC (rev 226396)
@@ -34,6 +34,7 @@
 #import "PasteboardStrategy.h"
 #import "PlatformPasteboard.h"
 #import "PlatformStrategies.h"
+#import "RuntimeEnabledFeatures.h"
 #import "WebCoreNSURLExtras.h"
 
 #if PLATFORM(IOS)
@@ -220,6 +221,9 @@
     if (purpose == DraggingPurpose::ForFileUpload)
         return containsFiles();
 
+    if (purpose == DraggingPurpose::ForEditing && RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled() && containsFiles())
+        return true;
+
     Vector<String> types;
     platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName);
     return types.contains(String(WebArchivePboardType))

Modified: trunk/Source/WebCore/platform/mac/PasteboardMac.mm (226395 => 226396)


--- trunk/Source/WebCore/platform/mac/PasteboardMac.mm	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebCore/platform/mac/PasteboardMac.mm	2018-01-04 07:44:55 UTC (rev 226396)
@@ -350,7 +350,7 @@
     if (types.contains(String(legacyFilenamesPasteboardType()))) {
         Vector<String> paths;
         strategy.getPathnamesForType(paths, legacyFilenamesPasteboardType(), m_pasteboardName);
-        if (m_changeCount != changeCount() || reader.readFilenames(paths))
+        if (m_changeCount != changeCount() || reader.readFilePaths(paths))
             return;
     }
 
@@ -554,7 +554,7 @@
     }
 }
 
-Vector<String> Pasteboard::readFilenames()
+Vector<String> Pasteboard::readFilePaths()
 {
     // FIXME: Seems silly to convert paths to URLs and then back to paths. Does that do anything helpful?
     Vector<String> absoluteURLs = absoluteURLsFromPasteboardFilenames(m_pasteboardName);

Modified: trunk/Source/WebKit/ChangeLog (226395 => 226396)


--- trunk/Source/WebKit/ChangeLog	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebKit/ChangeLog	2018-01-04 07:44:55 UTC (rev 226396)
@@ -1,3 +1,25 @@
+2018-01-03  Wenson Hsieh  <[email protected]>
+
+        [Attachment Support] Create attachment elements when dropping files on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=181192
+        <rdar://problem/36280945>
+
+        Reviewed by Tim Horton.
+
+        Make some minor adjustments for changes to the pasteboard in WebCore. See WebCore/ChangeLog for more detail.
+        Teaches WebPasteboardProxy et. al. to plumb PasteboardItemInfo from the UI process to the web process via the
+        new `InformationForItemAtIndex` codepath.
+
+        * UIProcess/Cocoa/WebPasteboardProxyCocoa.mm:
+        (WebKit::WebPasteboardProxy::informationForItemAtIndex):
+        (WebKit::WebPasteboardProxy::getFilenamesForDataInteraction): Deleted.
+        * UIProcess/WebPasteboardProxy.h:
+        * UIProcess/WebPasteboardProxy.messages.in:
+        * WebProcess/WebCoreSupport/WebPlatformStrategies.cpp:
+        (WebKit::WebPlatformStrategies::informationForItemAtIndex):
+        (WebKit::WebPlatformStrategies::getFilenamesForDataInteraction): Deleted.
+        * WebProcess/WebCoreSupport/WebPlatformStrategies.h:
+
 2018-01-03  Ting-Wei Lan  <[email protected]>
 
         Replace hard-coded paths in shebangs with #!/usr/bin/env

Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm (226395 => 226396)


--- trunk/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm	2018-01-04 07:44:55 UTC (rev 226396)
@@ -29,6 +29,7 @@
 #import "SandboxExtension.h"
 #import "WebProcessProxy.h"
 #import <WebCore/Color.h>
+#import <WebCore/PasteboardItemInfo.h>
 #import <WebCore/PlatformPasteboard.h>
 #import <WebCore/SharedBuffer.h>
 #import <WebCore/URL.h>
@@ -225,9 +226,9 @@
     itemsCount = PlatformPasteboard(pasteboardName).count();
 }
 
-void WebPasteboardProxy::getFilenamesForDataInteraction(const String& pasteboardName, Vector<String>& filenames)
+void WebPasteboardProxy::informationForItemAtIndex(int index, const String& pasteboardName, PasteboardItemInfo& info)
 {
-    filenames = PlatformPasteboard(pasteboardName).filenamesForDataInteraction();
+    info = PlatformPasteboard(pasteboardName).informationForItemAtIndex(index);
 }
 
 void WebPasteboardProxy::updateSupportedTypeIdentifiers(const Vector<String>& identifiers, const String& pasteboardName)

Modified: trunk/Source/WebKit/UIProcess/WebPasteboardProxy.h (226395 => 226396)


--- trunk/Source/WebKit/UIProcess/WebPasteboardProxy.h	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebKit/UIProcess/WebPasteboardProxy.h	2018-01-04 07:44:55 UTC (rev 226396)
@@ -35,6 +35,7 @@
 class Color;
 struct PasteboardCustomData;
 struct PasteboardImage;
+struct PasteboardItemInfo;
 struct PasteboardURL;
 struct PasteboardWebContent;
 }
@@ -77,7 +78,7 @@
     void readURLFromPasteboard(uint64_t index, const String& pasteboardType, const String& pasteboardName, String& url, String& title);
     void readBufferFromPasteboard(uint64_t index, const String& pasteboardType, const String& pasteboardName, SharedMemory::Handle&, uint64_t& size);
     void getPasteboardItemsCount(const String& pasteboardName, uint64_t& itemsCount);
-    void getFilenamesForDataInteraction(const String& pasteboardName, Vector<String>& filenames);
+    void informationForItemAtIndex(int index, const String& pasteboardName, WebCore::PasteboardItemInfo& filename);
     void updateSupportedTypeIdentifiers(const Vector<String>& identifiers, const String& pasteboardName);
 #endif
 #if PLATFORM(COCOA)

Modified: trunk/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in (226395 => 226396)


--- trunk/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in	2018-01-04 07:44:55 UTC (rev 226396)
@@ -30,7 +30,7 @@
     ReadURLFromPasteboard(uint64_t index, String pasteboardType, String pasteboardName) -> (String url, String title)
     ReadBufferFromPasteboard(uint64_t index, String pasteboardType, String pasteboardName) -> (WebKit::SharedMemory::Handle handle, uint64_t size)
     GetPasteboardItemsCount(String pasteboardName) -> (uint64_t itemsCount)
-    GetFilenamesForDataInteraction(String pasteboardName) -> (Vector<String> filenames)
+    InformationForItemAtIndex(uint64_t index, String pasteboardName) -> (struct WebCore::PasteboardItemInfo info)
     UpdateSupportedTypeIdentifiers(Vector<String> identifiers, String pasteboardName)
     GetPasteboardTypesByFidelityForItemAtIndex(uint64_t index, String pasteboardName) -> (Vector<String> types)
 #endif

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp (226395 => 226396)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp	2018-01-04 07:44:55 UTC (rev 226396)
@@ -55,6 +55,7 @@
 #include <WebCore/NetworkingContext.h>
 #include <WebCore/Page.h>
 #include <WebCore/PageGroup.h>
+#include <WebCore/PasteboardItemInfo.h>
 #include <WebCore/PlatformCookieJar.h>
 #include <WebCore/PlatformPasteboard.h>
 #include <WebCore/ProgressTracker.h>
@@ -322,9 +323,11 @@
     return itemsCount;
 }
 
-void WebPlatformStrategies::getFilenamesForDataInteraction(Vector<String>& filenames, const String& pasteboardName)
+PasteboardItemInfo WebPlatformStrategies::informationForItemAtIndex(int index, const String& pasteboardName)
 {
-    WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetFilenamesForDataInteraction(pasteboardName), Messages::WebPasteboardProxy::GetFilenamesForDataInteraction::Reply(filenames), 0);
+    PasteboardItemInfo info;
+    WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::InformationForItemAtIndex(index, pasteboardName), Messages::WebPasteboardProxy::InformationForItemAtIndex::Reply(info), 0);
+    return info;
 }
 
 void WebPlatformStrategies::updateSupportedTypeIdentifiers(const Vector<String>& identifiers, const String& pasteboardName)

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.h (226395 => 226396)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.h	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.h	2018-01-04 07:44:55 UTC (rev 226396)
@@ -65,7 +65,7 @@
     String readStringFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName) override;
     RefPtr<WebCore::SharedBuffer> readBufferFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName) override;
     WebCore::URL readURLFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName, String& title) override;
-    void getFilenamesForDataInteraction(Vector<String>& filenames, const String& pasteboardName) override;
+    WebCore::PasteboardItemInfo informationForItemAtIndex(int index, const String& pasteboardName) override;
     void updateSupportedTypeIdentifiers(const Vector<String>& identifiers, const String& pasteboardName) override;
     void getTypesByFidelityForItemAtIndex(Vector<String>& types, uint64_t index, const String& pasteboardName) override;
 #endif

Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (226395 => 226396)


--- trunk/Source/WebKitLegacy/mac/ChangeLog	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog	2018-01-04 07:44:55 UTC (rev 226396)
@@ -1,5 +1,20 @@
 2018-01-03  Wenson Hsieh  <[email protected]>
 
+        [Attachment Support] Create attachment elements when dropping files on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=181192
+        <rdar://problem/36280945>
+
+        Reviewed by Tim Horton.
+
+        Make some minor adjustments for changes to the pasteboard in WebCore. See WebCore/ChangeLog for more detail.
+
+        * WebCoreSupport/WebPlatformStrategies.h:
+        * WebCoreSupport/WebPlatformStrategies.mm:
+        (WebPlatformStrategies::informationForItemAtIndex):
+        (WebPlatformStrategies::getFilenamesForDataInteraction): Deleted.
+
+2018-01-03  Wenson Hsieh  <[email protected]>
+
         [Attachment Support] Add plumbing for starting a drag with promised blob data
         https://bugs.webkit.org/show_bug.cgi?id=181201
 

Modified: trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.h (226395 => 226396)


--- trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.h	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.h	2018-01-04 07:44:55 UTC (rev 226396)
@@ -66,7 +66,7 @@
     String readStringFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName) override;
     RefPtr<WebCore::SharedBuffer> readBufferFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName) override;
     WebCore::URL readURLFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName, String& title) override;
-    void getFilenamesForDataInteraction(Vector<String>& filenames, const String& pasteboardName) override;
+    WebCore::PasteboardItemInfo informationForItemAtIndex(int index, const String& pasteboardName) override;
     void updateSupportedTypeIdentifiers(const Vector<String>& identifiers, const String& pasteboardName) override;
     void getTypesByFidelityForItemAtIndex(Vector<String>& types, uint64_t index, const String& pasteboardName) override;
 #endif

Modified: trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm (226395 => 226396)


--- trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm	2018-01-04 07:44:55 UTC (rev 226396)
@@ -32,6 +32,7 @@
 #import <WebCore/Color.h>
 #import <WebCore/MainFrame.h>
 #import <WebCore/NetworkStorageSession.h>
+#import <WebCore/PasteboardItemInfo.h>
 #import <WebCore/PlatformCookieJar.h>
 #import <WebCore/PlatformPasteboard.h>
 #import <WebCore/SharedBuffer.h>
@@ -239,8 +240,8 @@
     return PlatformPasteboard(pasteboardName).readString(index, type);
 }
 
-void WebPlatformStrategies::getFilenamesForDataInteraction(Vector<String>& filenames, const String& pasteboardName)
+WebCore::PasteboardItemInfo WebPlatformStrategies::informationForItemAtIndex(int index, const String& pasteboardName)
 {
-    filenames = PlatformPasteboard(pasteboardName).filenamesForDataInteraction();
+    return PlatformPasteboard(pasteboardName).informationForItemAtIndex(index);
 }
 #endif // PLATFORM(IOS)

Modified: trunk/Tools/ChangeLog (226395 => 226396)


--- trunk/Tools/ChangeLog	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Tools/ChangeLog	2018-01-04 07:44:55 UTC (rev 226396)
@@ -1,3 +1,45 @@
+2018-01-03  Wenson Hsieh  <[email protected]>
+
+        [Attachment Support] Create attachment elements when dropping files on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=181192
+        <rdar://problem/36280945>
+
+        Reviewed by Tim Horton.
+
+        Adds 3 new API tests to exercise different use cases of dropping content as attachment elements when the runtime
+        switch is enabled. See below for more details.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
+        (-[NSItemProvider registerData:type:]):
+        (platformCopyPNG):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
+
+        Fix some currently failing iOS drag and drop tests. In this case, there's no reason RTFD should appear in the
+        source item provider when dragging rich text *without* attachments, so this should have been a check for just
+        kUTTypeRTF instead.
+
+        (TestWebKitAPI::TEST):
+
+        Tests a few cases of inserting attachment elements via drop:
+        1.  We should distinguish between drops containing rich/plain text files from just dropping rich/plain text.
+            Instead of inserting the contents as inline web content, this should generate attachment elements.
+        2.  Test the fallback mechanism for inserting attachment elements. If the preferred presentation style is not
+            explicitly set, but there's nothing WebKit would otherwise do with the dropped content, then we should fall
+            back to inserting the content as an attachment.
+        3.  Test that if multiple attachments and inline item providers are present, WebKit will respect the order in
+            which they were inserted by the source (as opposed to, for instance, putting all of the attachments in front
+            or at the end).
+
+        * TestWebKitAPI/cocoa/TestWKWebView.h:
+        * TestWebKitAPI/cocoa/TestWKWebView.mm:
+        (-[TestWKWebView objectByEvaluatingJavaScript:]):
+
+        Add a helper method to return an object that represents the result of evaluating some given script, and rewrite
+        -stringByEvaluatingJavaScript to just turn around and call this.
+
+        (-[TestWKWebView stringByEvaluatingJavaScript:]):
+
 2018-01-03  Ting-Wei Lan  <[email protected]>
 
         Replace hard-coded paths in shebangs with #!/usr/bin/env

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm (226395 => 226396)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm	2018-01-04 07:44:55 UTC (rev 226396)
@@ -321,6 +321,24 @@
 
 #pragma mark - Platform testing helper functions
 
+#if PLATFORM(IOS)
+
+typedef void(^ItemProviderDataLoadHandler)(NSData *, NSError *);
+
+@implementation NSItemProvider (AttachmentTesting)
+
+- (void)registerData:(NSData *)data type:(NSString *)type
+{
+    [self registerDataRepresentationForTypeIdentifier:type visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[protectedData = retainPtr(data)] (ItemProviderDataLoadHandler completionHandler) -> NSProgress * {
+        completionHandler(protectedData.get(), nil);
+        return nil;
+    }];
+}
+
+@end
+
+#endif // PLATFORM(IOS)
+
 void platformCopyRichTextWithMultipleAttachments()
 {
     auto image = adoptNS([[NSTextAttachment alloc] initWithData:testImageData() ofType:(NSString *)kUTTypePNG]);
@@ -363,8 +381,6 @@
 #endif
 }
 
-typedef void(^ItemProviderDataLoadHandler)(NSData *, NSError *);
-
 void platformCopyPNG()
 {
 #if PLATFORM(MAC)
@@ -375,10 +391,7 @@
     UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
     auto item = adoptNS([[UIItemProvider alloc] init]);
     [item setPreferredPresentationStyle:UIPreferredPresentationStyleAttachment];
-    [item registerDataRepresentationForTypeIdentifier:(NSString *)kUTTypePNG visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[] (ItemProviderDataLoadHandler completionHandler) -> NSProgress * {
-        completionHandler(testImageData(), nil);
-        return nil;
-    }];
+    [item registerData:testImageData() type:(NSString *)kUTTypePNG];
     pasteboard.itemProviders = @[ item.get() ];
 #endif
 }
@@ -960,11 +973,7 @@
     auto webView = webViewForTestingAttachments();
     auto draggingSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
     auto item = adoptNS([[NSItemProvider alloc] init]);
-    [item setPreferredPresentationStyle:UIPreferredPresentationStyleAttachment];
-    [item registerDataRepresentationForTypeIdentifier:(NSString *)kUTTypePNG visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[] (ItemProviderDataLoadHandler completionHandler) -> NSProgress * {
-        completionHandler(testImageData(), nil);
-        return nil;
-    }];
+    [item registerData:testImageData() type:(NSString *)kUTTypePNG];
     [draggingSimulator setExternalItemProviders:@[ item.get() ]];
     [draggingSimulator runFrom:CGPointZero to:CGPointMake(50, 50)];
 
@@ -1010,6 +1019,115 @@
     }
 }
 
+TEST(WKAttachmentTestsIOS, InsertDroppedRichAndPlainTextFilesAsAttachments)
+{
+    // Here, both rich text and plain text are content types that WebKit already understands how to insert in editable
+    // areas in the absence of attachment elements. However, due to the explicitly set attachment presentation style
+    // on the item providers, we should instead treat them as dropped files and insert attachment elements.
+    // This exercises the scenario of dragging rich and plain text files from Files to Mail.
+    auto richTextItem = adoptNS([[NSItemProvider alloc] init]);
+    auto richText = adoptNS([[NSAttributedString alloc] initWithString:@"Hello world" attributes:@{ NSFontAttributeName: [UIFont boldSystemFontOfSize:12] }]);
+    [richTextItem setPreferredPresentationStyle:UIPreferredPresentationStyleAttachment];
+    [richTextItem registerObject:richText.get() visibility:NSItemProviderRepresentationVisibilityAll];
+    [richTextItem setSuggestedName:@"hello.rtf"];
+
+    auto plainTextItem = adoptNS([[NSItemProvider alloc] init]);
+    [plainTextItem setPreferredPresentationStyle:UIPreferredPresentationStyleAttachment];
+    [plainTextItem registerObject:@"Hello world" visibility:NSItemProviderRepresentationVisibilityAll];
+    [plainTextItem setSuggestedName:@"world.txt"];
+
+    auto webView = webViewForTestingAttachments();
+    auto draggingSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
+    [draggingSimulator setExternalItemProviders:@[ richTextItem.get(), plainTextItem.get() ]];
+    [draggingSimulator runFrom:CGPointZero to:CGPointMake(50, 50)];
+
+    EXPECT_EQ(2U, [draggingSimulator insertedAttachments].count);
+    EXPECT_EQ(0U, [draggingSimulator removedAttachments].count);
+
+    for (_WKAttachment *attachment in [draggingSimulator insertedAttachments]) {
+        NSError *error = nil;
+        EXPECT_GT([attachment synchronouslyRequestData:&error].length, 0U);
+        EXPECT_TRUE(!error);
+        if (error)
+            NSLog(@"Error: %@", error);
+    }
+
+    EXPECT_EQ(2, [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment').length"].intValue);
+    EXPECT_WK_STREQ("hello.rtf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('title')"]);
+    EXPECT_WK_STREQ("text/rtf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('type')"]);
+    EXPECT_WK_STREQ("world.txt", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('title')"]);
+    EXPECT_WK_STREQ("text/plain", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('type')"]);
+}
+
+TEST(WKAttachmentTestsIOS, InsertDroppedZipArchiveAsAttachment)
+{
+    // Since WebKit doesn't have any default DOM representation for ZIP archives, we should fall back to inserting
+    // attachment elements. This exercises the flow of dragging a ZIP file from an app that doesn't specify a preferred
+    // presentation style (e.g. Notes) into Mail.
+    auto item = adoptNS([[NSItemProvider alloc] init]);
+    NSData *data = ""
+    [item registerData:data type:(NSString *)kUTTypeZipArchive];
+    [item setSuggestedName:@"archive.zip"];
+
+    auto webView = webViewForTestingAttachments();
+    auto draggingSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
+    [draggingSimulator setExternalItemProviders:@[ item.get() ]];
+    [draggingSimulator runFrom:CGPointZero to:CGPointMake(50, 50)];
+
+    EXPECT_EQ(1U, [draggingSimulator insertedAttachments].count);
+    EXPECT_EQ(0U, [draggingSimulator removedAttachments].count);
+    [[draggingSimulator insertedAttachments].firstObject expectRequestedDataToBe:data];
+    EXPECT_EQ(1, [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment').length"].intValue);
+    EXPECT_WK_STREQ("archive.zip", [webView valueOfAttribute:@"title" forQuerySelector:@"attachment"]);
+    EXPECT_WK_STREQ("application/zip", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]);
+}
+
+TEST(WKAttachmentTestsIOS, InsertDroppedItemProvidersInOrder)
+{
+    // Tests that item providers are inserted in the order they are specified. In this case, the two inserted attachments
+    // should be separated by a link.
+    auto firstAttachmentItem = adoptNS([[NSItemProvider alloc] init]);
+    [firstAttachmentItem setPreferredPresentationStyle:UIPreferredPresentationStyleAttachment];
+    [firstAttachmentItem registerObject:@"FIRST" visibility:NSItemProviderRepresentationVisibilityAll];
+    [firstAttachmentItem setSuggestedName:@"first.txt"];
+
+    auto inlineTextItem = adoptNS([[NSItemProvider alloc] init]);
+    auto appleURL = retainPtr([NSURL URLWithString:@"https://www.apple.com/"]);
+    [inlineTextItem registerObject:appleURL.get() visibility:NSItemProviderRepresentationVisibilityAll];
+
+    auto secondAttachmentItem = adoptNS([[NSItemProvider alloc] init]);
+    [secondAttachmentItem registerData:testPDFData() type:(NSString *)kUTTypePDF];
+    [secondAttachmentItem setSuggestedName:@"second.pdf"];
+
+    auto webView = webViewForTestingAttachments();
+    auto draggingSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
+    [draggingSimulator setExternalItemProviders:@[ firstAttachmentItem.get(), inlineTextItem.get(), secondAttachmentItem.get() ]];
+    [draggingSimulator runFrom:CGPointZero to:CGPointMake(50, 50)];
+
+    EXPECT_EQ(2U, [draggingSimulator insertedAttachments].count);
+    EXPECT_EQ(0U, [draggingSimulator removedAttachments].count);
+
+    for (_WKAttachment *attachment in [draggingSimulator insertedAttachments]) {
+        NSError *error = nil;
+        EXPECT_GT([attachment synchronouslyRequestData:&error].length, 0U);
+        EXPECT_TRUE(!error);
+        if (error)
+            NSLog(@"Error: %@", error);
+    }
+
+    NSArray *observedElementTags = (NSArray *)[webView objectByEvaluatingJavaScript:@"Array.from(document.body.children).map(e => e.tagName)"];
+    NSArray *expectedElementTags = @[ @"ATTACHMENT", @"A", @"ATTACHMENT" ];
+    EXPECT_TRUE([observedElementTags isEqualToArray:expectedElementTags]);
+    if (![observedElementTags isEqualToArray:expectedElementTags])
+        NSLog(@"Observed elements: %@ did not match expectations: %@", observedElementTags, expectedElementTags);
+
+    EXPECT_WK_STREQ("first.txt", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('title')"]);
+    EXPECT_WK_STREQ("text/plain", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('type')"]);
+    EXPECT_WK_STREQ([appleURL absoluteString], [webView valueOfAttribute:@"href" forQuerySelector:@"a"]);
+    EXPECT_WK_STREQ("second.pdf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('title')"]);
+    EXPECT_WK_STREQ("application/pdf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('type')"]);
+}
+
 #endif // PLATFORM(IOS)
 
 } // namespace TestWebKitAPI

Modified: trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm (226395 => 226396)


--- trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2018-01-04 07:44:55 UTC (rev 226396)
@@ -344,7 +344,7 @@
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionPerformOperationEventName]);
     checkSelectionRectsWithLogging(@[ makeCGRectValue(1, 201, 961, 227) ], [dataInteractionSimulator finalSelectionRects]);
-    checkTypeIdentifierPrecedesOtherTypeIdentifier(dataInteractionSimulator.get(), (NSString *)kUTTypeRTFD, (NSString *)kUTTypeUTF8PlainText);
+    checkTypeIdentifierPrecedesOtherTypeIdentifier(dataInteractionSimulator.get(), (NSString *)kUTTypeRTF, (NSString *)kUTTypeUTF8PlainText);
 }
 
 TEST(DataInteractionTests, ContentEditableToTextarea)
@@ -364,7 +364,7 @@
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionPerformOperationEventName]);
     checkSelectionRectsWithLogging(@[ makeCGRectValue(6, 203, 990, 232) ], [dataInteractionSimulator finalSelectionRects]);
-    checkTypeIdentifierPrecedesOtherTypeIdentifier(dataInteractionSimulator.get(), (NSString *)kUTTypeRTFD, (NSString *)kUTTypeUTF8PlainText);
+    checkTypeIdentifierPrecedesOtherTypeIdentifier(dataInteractionSimulator.get(), (NSString *)kUTTypeRTF, (NSString *)kUTTypeUTF8PlainText);
 }
 
 TEST(DataInteractionTests, ContentEditableMoveParagraphs)

Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h (226395 => 226396)


--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h	2018-01-04 07:44:55 UTC (rev 226396)
@@ -45,6 +45,7 @@
 - (void)loadTestPageNamed:(NSString *)pageName;
 - (void)synchronouslyLoadHTMLString:(NSString *)html;
 - (void)synchronouslyLoadTestPageNamed:(NSString *)pageName;
+- (id)objectByEvaluatingJavaScript:(NSString *)script;
 - (NSString *)stringByEvaluatingJavaScript:(NSString *)script;
 - (void)waitForMessage:(NSString *)message;
 - (void)performAfterLoading:(dispatch_block_t)actions;

Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm (226395 => 226396)


--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm	2018-01-04 07:18:18 UTC (rev 226395)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm	2018-01-04 07:44:55 UTC (rev 226396)
@@ -238,23 +238,26 @@
     [self _test_waitForDidFinishNavigation];
 }
 
-- (NSString *)stringByEvaluatingJavaScript:(NSString *)script
+- (id)objectByEvaluatingJavaScript:(NSString *)script
 {
-    __block bool isWaitingForJavaScript = false;
-    __block NSString *evalResult = nil;
-    [self _evaluateJavaScriptWithoutUserGesture:script completionHandler:^(id result, NSError *error)
-    {
-        evalResult = [[NSString alloc] initWithFormat:@"%@", result];
+    bool isWaitingForJavaScript = false;
+    RetainPtr<id> evalResult;
+    [self _evaluateJavaScriptWithoutUserGesture:script completionHandler:[&] (id result, NSError *error) {
+        evalResult = result;
         isWaitingForJavaScript = true;
         EXPECT_TRUE(!error);
         if (error)
             NSLog(@"Encountered error: %@ while evaluating script: %@", error, script);
     }];
-
     TestWebKitAPI::Util::run(&isWaitingForJavaScript);
-    return [evalResult autorelease];
+    return evalResult.autorelease();
 }
 
+- (NSString *)stringByEvaluatingJavaScript:(NSString *)script
+{
+    return [NSString stringWithFormat:@"%@", [self objectByEvaluatingJavaScript:script]];
+}
+
 - (void)waitForMessage:(NSString *)message
 {
     __block bool isDoneWaiting = false;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to