Title: [235647] trunk
Revision
235647
Author
wenson_hs...@apple.com
Date
2018-09-04 16:47:55 -0700 (Tue, 04 Sep 2018)

Log Message

Populate "text/uri-list" with multiple URLs when the pasteboard contains multiple URLs
https://bugs.webkit.org/show_bug.cgi?id=188890
<rdar://problem/43648605>

Reviewed by Tim Horton.

Source/WebCore:

Adds support for exposing a newline separated list of URLs via DataTransfer's "text/uri-list" type when pasting
or dropping multiple items on the pasteboard that can be represented as URLs. Currently on iOS, only the URL of
the first item (if present) is exposed, and on macOS, only the first out of all the URLs in the pasteboard is
exposed.

To fix this, we introduce `Pasteboard::readAllStrings`, which reads a list of pasteboard strings collected from
all available items on the platform pasteboard. Currently, this is only used to provide a list of URL strings
when fetching data for the "text/uri-list" type when calling `DataTransfer.getData()` and
`DataTransferItem.getAsString()`.

Tests:  DragAndDropTests.ExposeMultipleURLsInDataTransfer
        UIPasteboardTests.DataTransferURIListContainsMultipleURLs
        PasteMixedContent.PasteOneOrMoreURLs

* dom/DataTransfer.cpp:
(WebCore::readURLsFromPasteboardAsString):

Add a helper method that reads all URL strings from the pasteboard (for the MIME type "text/uri-list", which
corresponds to NSURLPboardType and "public.url" on macOS and iOS, respectively) and returns a single string
containing all non-empty URLs joined by newline characters. Also takes a filtering block which may be used to
reject URLs from being included in "text/uri-list" output.

(WebCore::DataTransfer::getDataForItem const):
(WebCore::DataTransfer::readStringFromPasteboard const):

Insteading of reading a single string from the pasteboard for "text/uri-list", call the above helper function to
read all URL strings in the pasteboard. If there are files present in the pasteboard, we also filter out URLs
whose schemes are not in the set of schemes that are safe to expose to the page (i.e. http(s), blob, and data).

* platform/Pasteboard.cpp:
(WebCore::Pasteboard::readAllStrings):

Add a default non-Cocoa implementation of readAllStrings() that returns a vector, which may contain the result
of readString().

* platform/Pasteboard.h:
* platform/PasteboardStrategy.h:
* platform/PlatformPasteboard.h:

Add plumbing to grab a list of strings from the pasteboard for a given type.

* platform/cocoa/PasteboardCocoa.mm:
(WebCore::Pasteboard::readAllStrings):
(WebCore::Pasteboard::readString):

Implement these two methods in terms of `readPlatformValuesAsStrings`. `readAllStrings` returns the full list of
results, while `readString` only returns the first result.

* platform/ios/PasteboardIOS.mm:
(WebCore::Pasteboard::readPlatformValuesAsStrings):
(WebCore::Pasteboard::readPlatformValueAsString): Deleted.

Refactor this Cocoa helper function to return a list of pasteboard string values for the given type, rather than
a single string.

* platform/ios/PlatformPasteboardIOS.mm:
(WebCore::PlatformPasteboard::allStringsForType const):

Grab a string for each item (represented by an NSItemProvider) in the pasteboard that has data for the given
type identifier.

(WebCore::PlatformPasteboard::readString const):

Return the absolute string of the NSURL, instead of WebCore::URL::string(). This is needed to handle the case
where the NSURL is constructed from absolute and relative parts using a Plist. While -absoluteString gets us the
full URL string, URL::string() only returns the relative portion.

* platform/mac/PasteboardMac.mm:
(WebCore::Pasteboard::readPlatformValuesAsStrings):
(WebCore::Pasteboard::readPlatformValueAsString): Deleted.

Also refactor this to retrieve a list of pasteboard strings, rather than a single result.

* platform/mac/PlatformPasteboardMac.mm:
(WebCore::typeIdentifierForPasteboardType):
(WebCore::PlatformPasteboard::allStringsForType const):

Add an implementation for `allStringsForType` on macOS. Unlike iOS, it's much trickier to get this right since
we need to maintain compatibility with legacy "NS*Pboard" types, and `NSPasteboardItem` can only provide data
for `NSPasteboardType`s (i.e. UTIs), so there's no way to just iterate through each pasteboard item and ask it
for data that matches the given type, if the types are not UTIs. However, in the case where we have multiple
items, the client must have used NSPasteboardWriting-conformant objects and/or NSPasteboardItem itself to write
data to the pasteboard. Since NSPasteboardWriting-conformant objects register modern pasteboard types when
writing to the pasteboard, we can simply iterate over these pasteboard items and ask for property lists using
type identifiers instead of having to worry about legacy pasteboard types. Furthermore, in the case where there
is only a single item in the pasteboard and we do need to handle legacy pasteboard types, using `-[NSPasteboard
stringForType:]` in the same way we do currently should yield the correct result.

As such, in the case where there is a single pasteboard item, we use `-[NSPasteboard stringForType:]` with the
original legacy type, and in the case where there are multiple items on the pasteboard, we iterate over each of
the pasteboard items and call `-[NSPasteboardItem propertyListForType:]` with the modern pasteboard type
corresponding to the given legacy pasteboard type.

The different corner cases in this logic are tested by the new API test, PasteMixedContent.PasteOneOrMoreURLs,
which exercises several different ways of writing one or more URLs to the pasteboard on macOS, which each result
in different legacy and modern pasteboard types being written to the pasteboard; our implementation of
`PlatformPasteboard::allStringsForType` on macOS handles all cases correctly.

Source/WebKit:

Add some plumbing through pasteboard classes to support `Pasteboard::readAllStrings`. See WebCore ChangeLog for
more detail.

* UIProcess/Cocoa/WebPasteboardProxyCocoa.mm:
(WebKit::WebPasteboardProxy::getPasteboardStringsForType):
* UIProcess/WebPasteboardProxy.h:
* UIProcess/WebPasteboardProxy.messages.in:
* WebProcess/WebCoreSupport/WebPlatformStrategies.cpp:
(WebKit::WebPlatformStrategies::allStringsForType):
* WebProcess/WebCoreSupport/WebPlatformStrategies.h:

Source/WebKitLegacy/mac:

Add some plumbing through pasteboard classes to support `Pasteboard::readAllStrings`. See WebCore ChangeLog for
more detail.

* WebCoreSupport/WebPlatformStrategies.h:
* WebCoreSupport/WebPlatformStrategies.mm:
(WebPlatformStrategies::allStringsForType):

Tools:

* DumpRenderTree/mac/DumpRenderTreePasteboard.mm:
(-[LocalPasteboard pasteboardItems]):

Implement this method to avoid crashing when running layout tests that access the pasteboard.

* TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm:

Add a test to verify that on macOS and iOS, multiple URLs dropped onto the page are accessible via
"text/uri-list".

* TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm:

Add a test that exercises 5 different ways to write one or more URLs to the pasteboard on macOS; in all cases,
the URLs written to the pasteboard should be exposed to the page via "text/uri-list". In all of these different
cases, the results of using `-[NSPasteboardItem stringForType:]`, `-[NSURL URLFromPasteboard:]` and
`-[NSPasteboard stringForType:]` will yield different results, so the purpose of this API test is to ensure that
our logic for grabbing a list of URLs from the pasteboard on macOS is robust enough to handle all of these
different behaviors.

* TestWebKitAPI/Tests/ios/UIPasteboardTests.mm:

Add a test to verify that on iOS, using `-[UIPasteboard setURLs:]` to write to multiple URLs to the pasteboard
and then pasting results in "text/uri-list" exposing a list of all the URLs written to the pasteboard.

* WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm:
(-[LocalPasteboard pasteboardItems]):

Implement this method to avoid crashing when running layout tests that access the pasteboard.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (235646 => 235647)


--- trunk/Source/WebCore/ChangeLog	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebCore/ChangeLog	2018-09-04 23:47:55 UTC (rev 235647)
@@ -1,3 +1,109 @@
+2018-09-04  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Populate "text/uri-list" with multiple URLs when the pasteboard contains multiple URLs
+        https://bugs.webkit.org/show_bug.cgi?id=188890
+        <rdar://problem/43648605>
+
+        Reviewed by Tim Horton.
+
+        Adds support for exposing a newline separated list of URLs via DataTransfer's "text/uri-list" type when pasting
+        or dropping multiple items on the pasteboard that can be represented as URLs. Currently on iOS, only the URL of
+        the first item (if present) is exposed, and on macOS, only the first out of all the URLs in the pasteboard is
+        exposed.
+
+        To fix this, we introduce `Pasteboard::readAllStrings`, which reads a list of pasteboard strings collected from
+        all available items on the platform pasteboard. Currently, this is only used to provide a list of URL strings
+        when fetching data for the "text/uri-list" type when calling `DataTransfer.getData()` and
+        `DataTransferItem.getAsString()`.
+
+        Tests:  DragAndDropTests.ExposeMultipleURLsInDataTransfer
+                UIPasteboardTests.DataTransferURIListContainsMultipleURLs
+                PasteMixedContent.PasteOneOrMoreURLs
+
+        * dom/DataTransfer.cpp:
+        (WebCore::readURLsFromPasteboardAsString):
+
+        Add a helper method that reads all URL strings from the pasteboard (for the MIME type "text/uri-list", which
+        corresponds to NSURLPboardType and "public.url" on macOS and iOS, respectively) and returns a single string
+        containing all non-empty URLs joined by newline characters. Also takes a filtering block which may be used to
+        reject URLs from being included in "text/uri-list" output.
+
+        (WebCore::DataTransfer::getDataForItem const):
+        (WebCore::DataTransfer::readStringFromPasteboard const):
+
+        Insteading of reading a single string from the pasteboard for "text/uri-list", call the above helper function to
+        read all URL strings in the pasteboard. If there are files present in the pasteboard, we also filter out URLs
+        whose schemes are not in the set of schemes that are safe to expose to the page (i.e. http(s), blob, and data).
+
+        * platform/Pasteboard.cpp:
+        (WebCore::Pasteboard::readAllStrings):
+
+        Add a default non-Cocoa implementation of readAllStrings() that returns a vector, which may contain the result
+        of readString().
+
+        * platform/Pasteboard.h:
+        * platform/PasteboardStrategy.h:
+        * platform/PlatformPasteboard.h:
+
+        Add plumbing to grab a list of strings from the pasteboard for a given type.
+
+        * platform/cocoa/PasteboardCocoa.mm:
+        (WebCore::Pasteboard::readAllStrings):
+        (WebCore::Pasteboard::readString):
+
+        Implement these two methods in terms of `readPlatformValuesAsStrings`. `readAllStrings` returns the full list of
+        results, while `readString` only returns the first result.
+
+        * platform/ios/PasteboardIOS.mm:
+        (WebCore::Pasteboard::readPlatformValuesAsStrings):
+        (WebCore::Pasteboard::readPlatformValueAsString): Deleted.
+
+        Refactor this Cocoa helper function to return a list of pasteboard string values for the given type, rather than
+        a single string.
+
+        * platform/ios/PlatformPasteboardIOS.mm:
+        (WebCore::PlatformPasteboard::allStringsForType const):
+
+        Grab a string for each item (represented by an NSItemProvider) in the pasteboard that has data for the given
+        type identifier.
+
+        (WebCore::PlatformPasteboard::readString const):
+
+        Return the absolute string of the NSURL, instead of WebCore::URL::string(). This is needed to handle the case
+        where the NSURL is constructed from absolute and relative parts using a Plist. While -absoluteString gets us the
+        full URL string, URL::string() only returns the relative portion.
+
+        * platform/mac/PasteboardMac.mm:
+        (WebCore::Pasteboard::readPlatformValuesAsStrings):
+        (WebCore::Pasteboard::readPlatformValueAsString): Deleted.
+
+        Also refactor this to retrieve a list of pasteboard strings, rather than a single result.
+
+        * platform/mac/PlatformPasteboardMac.mm:
+        (WebCore::typeIdentifierForPasteboardType):
+        (WebCore::PlatformPasteboard::allStringsForType const):
+
+        Add an implementation for `allStringsForType` on macOS. Unlike iOS, it's much trickier to get this right since
+        we need to maintain compatibility with legacy "NS*Pboard" types, and `NSPasteboardItem` can only provide data
+        for `NSPasteboardType`s (i.e. UTIs), so there's no way to just iterate through each pasteboard item and ask it
+        for data that matches the given type, if the types are not UTIs. However, in the case where we have multiple
+        items, the client must have used NSPasteboardWriting-conformant objects and/or NSPasteboardItem itself to write
+        data to the pasteboard. Since NSPasteboardWriting-conformant objects register modern pasteboard types when
+        writing to the pasteboard, we can simply iterate over these pasteboard items and ask for property lists using
+        type identifiers instead of having to worry about legacy pasteboard types. Furthermore, in the case where there
+        is only a single item in the pasteboard and we do need to handle legacy pasteboard types, using `-[NSPasteboard
+        stringForType:]` in the same way we do currently should yield the correct result.
+
+        As such, in the case where there is a single pasteboard item, we use `-[NSPasteboard stringForType:]` with the
+        original legacy type, and in the case where there are multiple items on the pasteboard, we iterate over each of
+        the pasteboard items and call `-[NSPasteboardItem propertyListForType:]` with the modern pasteboard type
+        corresponding to the given legacy pasteboard type.
+
+        The different corner cases in this logic are tested by the new API test, PasteMixedContent.PasteOneOrMoreURLs,
+        which exercises several different ways of writing one or more URLs to the pasteboard on macOS, which each result
+        in different legacy and modern pasteboard types being written to the pasteboard; our implementation of
+        `PlatformPasteboard::allStringsForType` on macOS handles all cases correctly.
+
 2018-09-04  Simon Fraser  <simon.fra...@apple.com>
 
         CSS reference filter that references a tiled feTurbulence is blank

Modified: trunk/Source/WebCore/dom/DataTransfer.cpp (235646 => 235647)


--- trunk/Source/WebCore/dom/DataTransfer.cpp	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebCore/dom/DataTransfer.cpp	2018-09-04 23:47:55 UTC (rev 235647)
@@ -47,6 +47,7 @@
 #include "WebContentReader.h"
 #include "WebCorePasteboardFileReader.h"
 #include "markup.h"
+#include <wtf/unicode/CharacterNames.h>
 
 namespace WebCore {
 
@@ -142,6 +143,19 @@
         m_itemList->didClearStringData(normalizedType);
 }
 
+static String readURLsFromPasteboardAsString(Pasteboard& pasteboard, Function<bool(const String&)>&& shouldIncludeURL)
+{
+    StringBuilder urlList;
+    for (auto urlString : pasteboard.readAllStrings("text/uri-list"_s)) {
+        if (!shouldIncludeURL(urlString))
+            continue;
+        if (!urlList.isEmpty())
+            urlList.append(newlineCharacter);
+        urlList.append(urlString);
+    }
+    return urlList.toString();
+}
+
 String DataTransfer::getDataForItem(Document& document, const String& type) const
 {
     if (!canReadData())
@@ -150,9 +164,9 @@
     auto lowercaseType = stripLeadingAndTrailingHTMLSpaces(type).convertToASCIILowercase();
     if (shouldSuppressGetAndSetDataToAvoidExposingFilePaths()) {
         if (lowercaseType == "text/uri-list") {
-            auto urlString = m_pasteboard->readString(lowercaseType);
-            if (Pasteboard::canExposeURLToDOMWhenPasteboardContainsFiles(urlString))
-                return urlString;
+            return readURLsFromPasteboardAsString(*m_pasteboard, [] (auto& urlString) {
+                return Pasteboard::canExposeURLToDOMWhenPasteboardContainsFiles(urlString);
+            });
         }
 
         if (lowercaseType == "text/html" && RuntimeEnabledFeatures::sharedFeatures().customPasteboardDataEnabled()) {
@@ -192,6 +206,12 @@
         return reader.markup;
     }
 
+    if (!is<StaticPasteboard>(*m_pasteboard) && lowercaseType == "text/uri-list") {
+        return readURLsFromPasteboardAsString(*m_pasteboard, [] (auto&) {
+            return true;
+        });
+    }
+
     return m_pasteboard->readString(lowercaseType);
 }
 

Modified: trunk/Source/WebCore/platform/Pasteboard.cpp (235646 => 235647)


--- trunk/Source/WebCore/platform/Pasteboard.cpp	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebCore/platform/Pasteboard.cpp	2018-09-04 23:47:55 UTC (rev 235647)
@@ -85,4 +85,17 @@
     return result;
 }
 
+#if !PLATFORM(COCOA)
+
+Vector<String> Pasteboard::readAllStrings(const String& type)
+{
+    auto result = readString(type);
+    if (result.isEmpty())
+        return { };
+
+    return { result };
+}
+
+#endif
+
 };

Modified: trunk/Source/WebCore/platform/Pasteboard.h (235646 => 235647)


--- trunk/Source/WebCore/platform/Pasteboard.h	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebCore/platform/Pasteboard.h	2018-09-04 23:47:55 UTC (rev 235647)
@@ -204,6 +204,7 @@
     virtual WEBCORE_EXPORT String readOrigin();
     virtual WEBCORE_EXPORT String readString(const String& type);
     virtual WEBCORE_EXPORT String readStringInCustomData(const String& type);
+    virtual WEBCORE_EXPORT Vector<String> readAllStrings(const String& type);
 
     virtual WEBCORE_EXPORT void writeString(const String& type, const String& data);
     virtual WEBCORE_EXPORT void clear();
@@ -298,7 +299,7 @@
 
 #if PLATFORM(COCOA)
     Vector<String> readFilePaths();
-    String readPlatformValueAsString(const String& domType, long changeCount, const String& pasteboardName);
+    Vector<String> readPlatformValuesAsStrings(const String& domType, long changeCount, const String& pasteboardName);
     static void addHTMLClipboardTypesForCocoaType(ListHashSet<String>& resultTypes, const String& cocoaType);
     String readStringForPlatformType(const String&);
     Vector<String> readTypesWithSecurityCheck();

Modified: trunk/Source/WebCore/platform/PasteboardStrategy.h (235646 => 235647)


--- trunk/Source/WebCore/platform/PasteboardStrategy.h	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebCore/platform/PasteboardStrategy.h	2018-09-04 23:47:55 UTC (rev 235647)
@@ -61,6 +61,7 @@
     virtual RefPtr<SharedBuffer> bufferForType(const String& pasteboardType, const String& pasteboardName) = 0;
     virtual void getPathnamesForType(Vector<String>& pathnames, const String& pasteboardType, const String& pasteboardName) = 0;
     virtual String stringForType(const String& pasteboardType, const String& pasteboardName) = 0;
+    virtual Vector<String> allStringsForType(const String& pasteboardType, const String& pasteboardName) = 0;
     virtual long changeCount(const String& pasteboardName) = 0;
     virtual String uniqueName() = 0;
     virtual Color color(const String& pasteboardName) = 0;

Modified: trunk/Source/WebCore/platform/PlatformPasteboard.h (235646 => 235647)


--- trunk/Source/WebCore/platform/PlatformPasteboard.h	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebCore/platform/PlatformPasteboard.h	2018-09-04 23:47:55 UTC (rev 235647)
@@ -73,6 +73,7 @@
     WEBCORE_EXPORT RefPtr<SharedBuffer> bufferForType(const String& pasteboardType);
     WEBCORE_EXPORT void getPathnamesForType(Vector<String>& pathnames, const String& pasteboardType) const;
     WEBCORE_EXPORT String stringForType(const String& pasteboardType) const;
+    WEBCORE_EXPORT Vector<String> allStringsForType(const String& pasteboardType) const;
     WEBCORE_EXPORT long changeCount() const;
     WEBCORE_EXPORT Color color();
     WEBCORE_EXPORT URL url();

Modified: trunk/Source/WebCore/platform/cocoa/PasteboardCocoa.mm (235646 => 235647)


--- trunk/Source/WebCore/platform/cocoa/PasteboardCocoa.mm	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebCore/platform/cocoa/PasteboardCocoa.mm	2018-09-04 23:47:55 UTC (rev 235647)
@@ -259,9 +259,15 @@
     }
 }
 
+Vector<String> Pasteboard::readAllStrings(const String& type)
+{
+    return readPlatformValuesAsStrings(type, m_changeCount, m_pasteboardName);
+}
+
 String Pasteboard::readString(const String& type)
 {
-    return readPlatformValueAsString(type, m_changeCount, m_pasteboardName);
+    auto values = readPlatformValuesAsStrings(type, m_changeCount, m_pasteboardName);
+    return values.isEmpty() ? String() : values.first();
 }
 
 String Pasteboard::readStringInCustomData(const String& type)

Modified: trunk/Source/WebCore/platform/ios/PasteboardIOS.mm (235646 => 235647)


--- trunk/Source/WebCore/platform/ios/PasteboardIOS.mm	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebCore/platform/ios/PasteboardIOS.mm	2018-09-04 23:47:55 UTC (rev 235647)
@@ -373,38 +373,28 @@
     platformStrategies()->pasteboardStrategy()->writeToPasteboard(String(), String(), m_pasteboardName);
 }
 
-String Pasteboard::readPlatformValueAsString(const String& domType, long changeCount, const String& pasteboardName)
+Vector<String> Pasteboard::readPlatformValuesAsStrings(const String& domType, long changeCount, const String& pasteboardName)
 {
-    PasteboardStrategy& strategy = *platformStrategies()->pasteboardStrategy();
+    auto& strategy = *platformStrategies()->pasteboardStrategy();
 
-    int numberOfItems = strategy.getPasteboardItemsCount(pasteboardName);
-
-    if (!numberOfItems)
-        return String();
-
     // Grab the value off the pasteboard corresponding to the cocoaType.
-    RetainPtr<NSString> cocoaType = cocoaTypeFromHTMLClipboardType(domType);
+    auto cocoaType = cocoaTypeFromHTMLClipboardType(domType);
+    if (!cocoaType)
+        return { };
 
-    NSString *cocoaValue = nil;
+    auto values = strategy.allStringsForType(cocoaType.get(), pasteboardName);
+    if ([cocoaType isEqualToString:(__bridge NSString *)kUTTypePlainText]) {
+        values = values.map([&] (auto& value) -> String {
+            return [value precomposedStringWithCanonicalMapping];
+        });
+    }
 
-    if ([cocoaType isEqualToString:(NSString *)kUTTypeURL]) {
-        String title;
-        URL url = "" pasteboardName, title);
-        if (!url.isNull())
-            cocoaValue = [(NSURL *)url absoluteString];
-    } else if ([cocoaType isEqualToString:(NSString *)kUTTypePlainText]) {
-        String value = strategy.readStringFromPasteboard(0, kUTTypePlainText, pasteboardName);
-        if (!value.isNull())
-            cocoaValue = [(NSString *)value precomposedStringWithCanonicalMapping];
-    } else if (cocoaType)
-        cocoaValue = (NSString *)strategy.readStringFromPasteboard(0, cocoaType.get(), pasteboardName);
-
     // Enforce changeCount ourselves for security. We check after reading instead of before to be
     // sure it doesn't change between our testing the change count and accessing the data.
-    if (cocoaValue && changeCount == changeCountForPasteboard(pasteboardName))
-        return cocoaValue;
+    if (changeCount != changeCountForPasteboard(pasteboardName))
+        return { };
 
-    return String();
+    return values;
 }
 
 void Pasteboard::addHTMLClipboardTypesForCocoaType(ListHashSet<String>& resultTypes, const String& cocoaType)

Modified: trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm (235646 => 235647)


--- trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm	2018-09-04 23:47:55 UTC (rev 235647)
@@ -603,6 +603,19 @@
     return [m_pasteboard numberOfItems];
 }
 
+Vector<String> PlatformPasteboard::allStringsForType(const String& type) const
+{
+    auto numberOfItems = count();
+    Vector<String> strings;
+    strings.reserveInitialCapacity(numberOfItems);
+    for (int index = 0; index < numberOfItems; ++index) {
+        String value = readString(index, type);
+        if (!value.isEmpty())
+            strings.uncheckedAppend(WTFMove(value));
+    }
+    return strings;
+}
+
 RefPtr<SharedBuffer> PlatformPasteboard::readBuffer(int index, const String& type) const
 {
     NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:index];
@@ -618,7 +631,7 @@
 {
     if (type == String(kUTTypeURL)) {
         String title;
-        return readURL(index, title);
+        return [(NSURL *)readURL(index, title) absoluteString];
     }
 
     NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:index];

Modified: trunk/Source/WebCore/platform/mac/PasteboardMac.mm (235646 => 235647)


--- trunk/Source/WebCore/platform/mac/PasteboardMac.mm	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebCore/platform/mac/PasteboardMac.mm	2018-09-04 23:47:55 UTC (rev 235647)
@@ -488,22 +488,26 @@
     m_changeCount = platformStrategies()->pasteboardStrategy()->setStringForType(emptyString(), cocoaType, m_pasteboardName);
 }
 
-String Pasteboard::readPlatformValueAsString(const String& domType, long changeCount, const String& pasteboardName)
+Vector<String> Pasteboard::readPlatformValuesAsStrings(const String& domType, long changeCount, const String& pasteboardName)
 {
-    const String& cocoaType = cocoaTypeFromHTMLClipboardType(domType);
-    String cocoaValue;
+    auto& strategy = *platformStrategies()->pasteboardStrategy();
+    auto cocoaType = cocoaTypeFromHTMLClipboardType(domType);
+    if (cocoaType.isEmpty())
+        return { };
 
-    if (cocoaType == String(legacyStringPasteboardType()))
-        cocoaValue = [platformStrategies()->pasteboardStrategy()->stringForType(cocoaType, pasteboardName) precomposedStringWithCanonicalMapping];
-    else if (!cocoaType.isEmpty())
-        cocoaValue = platformStrategies()->pasteboardStrategy()->stringForType(cocoaType, pasteboardName);
+    auto values = strategy.allStringsForType(cocoaType, pasteboardName);
+    if (cocoaType == String(legacyStringPasteboardType())) {
+        values = values.map([&] (auto& value) -> String {
+            return [value precomposedStringWithCanonicalMapping];
+        });
+    }
 
     // Enforce changeCount ourselves for security.  We check after reading instead of before to be
     // sure it doesn't change between our testing the change count and accessing the data.
-    if (!cocoaValue.isEmpty() && changeCount == platformStrategies()->pasteboardStrategy()->changeCount(pasteboardName))
-        return cocoaValue;
+    if (changeCount != platformStrategies()->pasteboardStrategy()->changeCount(pasteboardName))
+        return { };
 
-    return String();
+    return values;
 }
 
 static String utiTypeFromCocoaType(const String& type)

Modified: trunk/Source/WebCore/platform/mac/PlatformPasteboardMac.mm (235646 => 235647)


--- trunk/Source/WebCore/platform/mac/PlatformPasteboardMac.mm	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebCore/platform/mac/PlatformPasteboardMac.mm	2018-09-04 23:47:55 UTC (rev 235647)
@@ -116,6 +116,68 @@
     return [m_pasteboard stringForType:pasteboardType];
 }
 
+static Vector<String> urlStringsFromPasteboard(NSPasteboard *pasteboard)
+{
+    NSArray<NSPasteboardItem *> *items = pasteboard.pasteboardItems;
+    Vector<String> urlStrings;
+    urlStrings.reserveInitialCapacity(items.count);
+    if (items.count > 1) {
+        for (NSPasteboardItem *item in items) {
+            if (id propertyList = [item propertyListForType:(__bridge NSString *)kUTTypeURL]) {
+                if (auto urlFromItem = adoptNS([[NSURL alloc] initWithPasteboardPropertyList:propertyList ofType:(__bridge NSString *)kUTTypeURL]))
+                    urlStrings.uncheckedAppend([urlFromItem absoluteString]);
+            }
+        }
+    } else if (NSURL *urlFromPasteboard = [NSURL URLFromPasteboard:pasteboard])
+        urlStrings.uncheckedAppend(urlFromPasteboard.absoluteString);
+    else if (NSString *urlStringFromPasteboard = [pasteboard stringForType:legacyURLPasteboardType()])
+        urlStrings.uncheckedAppend(urlStringFromPasteboard);
+
+    bool mayContainFiles = pasteboardMayContainFilePaths(pasteboard);
+    urlStrings.removeAllMatching([&] (auto& urlString) {
+        return urlString.isEmpty() || (mayContainFiles && !Pasteboard::canExposeURLToDOMWhenPasteboardContainsFiles(urlString));
+    });
+
+    return urlStrings;
+}
+
+static String typeIdentifierForPasteboardType(const String& pasteboardType)
+{
+    if (UTTypeIsDeclared(pasteboardType.createCFString().get()))
+        return pasteboardType;
+
+    if (pasteboardType == String(legacyStringPasteboardType()))
+        return kUTTypeUTF8PlainText;
+
+    if (pasteboardType == String(legacyHTMLPasteboardType()))
+        return kUTTypeHTML;
+
+    if (pasteboardType == String(legacyURLPasteboardType()))
+        return kUTTypeURL;
+
+    return { };
+}
+
+Vector<String> PlatformPasteboard::allStringsForType(const String& pasteboardType) const
+{
+    auto typeIdentifier = typeIdentifierForPasteboardType(pasteboardType);
+    if (typeIdentifier == String(kUTTypeURL))
+        return urlStringsFromPasteboard(m_pasteboard.get());
+
+    NSArray<NSPasteboardItem *> *items = [m_pasteboard pasteboardItems];
+    Vector<String> strings;
+    strings.reserveInitialCapacity(items.count);
+    if (items.count > 1 && !typeIdentifier.isNull()) {
+        for (NSPasteboardItem *item in items) {
+            if (NSString *stringFromItem = [item stringForType:typeIdentifier])
+                strings.append(stringFromItem);
+        }
+    } else if (NSString *stringFromPasteboard = [m_pasteboard stringForType:pasteboardType])
+        strings.append(stringFromPasteboard);
+
+    return strings;
+}
+
 static const char* safeTypeForDOMToReadAndWriteForPlatformType(const String& platformType)
 {
     if (platformType == String(legacyStringPasteboardType()) || platformType == String(NSPasteboardTypeString))

Modified: trunk/Source/WebKit/ChangeLog (235646 => 235647)


--- trunk/Source/WebKit/ChangeLog	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebKit/ChangeLog	2018-09-04 23:47:55 UTC (rev 235647)
@@ -1,3 +1,22 @@
+2018-09-04  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Populate "text/uri-list" with multiple URLs when the pasteboard contains multiple URLs
+        https://bugs.webkit.org/show_bug.cgi?id=188890
+        <rdar://problem/43648605>
+
+        Reviewed by Tim Horton.
+
+        Add some plumbing through pasteboard classes to support `Pasteboard::readAllStrings`. See WebCore ChangeLog for
+        more detail.
+
+        * UIProcess/Cocoa/WebPasteboardProxyCocoa.mm:
+        (WebKit::WebPasteboardProxy::getPasteboardStringsForType):
+        * UIProcess/WebPasteboardProxy.h:
+        * UIProcess/WebPasteboardProxy.messages.in:
+        * WebProcess/WebCoreSupport/WebPlatformStrategies.cpp:
+        (WebKit::WebPlatformStrategies::allStringsForType):
+        * WebProcess/WebCoreSupport/WebPlatformStrategies.h:
+
 2018-09-04  Youenn Fablet  <you...@apple.com>
 
         Disable WebRTC unified plan runtime flag by default

Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm (235646 => 235647)


--- trunk/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm	2018-09-04 23:47:55 UTC (rev 235647)
@@ -70,6 +70,11 @@
     string = PlatformPasteboard(pasteboardName).stringForType(pasteboardType);
 }
 
+void WebPasteboardProxy::getPasteboardStringsForType(const String& pasteboardName, const String& pasteboardType, Vector<String>& strings)
+{
+    strings = PlatformPasteboard(pasteboardName).allStringsForType(pasteboardType);
+}
+
 void WebPasteboardProxy::getPasteboardBufferForType(const String& pasteboardName, const String& pasteboardType, SharedMemory::Handle& handle, uint64_t& size)
 {
     RefPtr<SharedBuffer> buffer = PlatformPasteboard(pasteboardName).bufferForType(pasteboardType);

Modified: trunk/Source/WebKit/UIProcess/WebPasteboardProxy.h (235646 => 235647)


--- trunk/Source/WebKit/UIProcess/WebPasteboardProxy.h	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebKit/UIProcess/WebPasteboardProxy.h	2018-09-04 23:47:55 UTC (rev 235647)
@@ -87,6 +87,7 @@
     void getPasteboardTypes(const String& pasteboardName, Vector<String>& pasteboardTypes);
     void getPasteboardPathnamesForType(IPC::Connection&, const String& pasteboardName, const String& pasteboardType, Vector<String>& pathnames, SandboxExtension::HandleArray&);
     void getPasteboardStringForType(const String& pasteboardName, const String& pasteboardType, String&);
+    void getPasteboardStringsForType(const String& pasteboardName, const String& pasteboardType, Vector<String>&);
     void getPasteboardBufferForType(const String& pasteboardName, const String& pasteboardType, SharedMemory::Handle&, uint64_t& size);
     void pasteboardCopy(const String& fromPasteboard, const String& toPasteboard, uint64_t& newChangeCount);
     void getPasteboardChangeCount(const String& pasteboardName, uint64_t& changeCount);

Modified: trunk/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in (235646 => 235647)


--- trunk/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in	2018-09-04 23:47:55 UTC (rev 235647)
@@ -45,6 +45,7 @@
     GetPasteboardTypes(String pasteboardName) -> (Vector<String> types)
     GetPasteboardPathnamesForType(String pasteboardName, String pasteboardType) -> (Vector<String> pathnames, WebKit::SandboxExtension::HandleArray sandboxExtensions) WantsConnection
     GetPasteboardStringForType(String pasteboardName, String pasteboardType) -> (String string)
+    GetPasteboardStringsForType(String pasteboardName, String pasteboardType) -> (Vector<String> strings)
     GetPasteboardBufferForType(String pasteboardName, String pasteboardType) -> (WebKit::SharedMemory::Handle handle, uint64_t size)
     PasteboardCopy(String fromPasteboard, String toPasteboard) -> (uint64_t changeCount)
     GetPasteboardChangeCount(String pasteboardName) -> (uint64_t changeCount)

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp (235646 => 235647)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp	2018-09-04 23:47:55 UTC (rev 235647)
@@ -207,6 +207,13 @@
     return value;
 }
 
+Vector<String> WebPlatformStrategies::allStringsForType(const String& pasteboardType, const String& pasteboardName)
+{
+    Vector<String> values;
+    WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardStringsForType(pasteboardName, pasteboardType), Messages::WebPasteboardProxy::GetPasteboardStringsForType::Reply(values), 0);
+    return values;
+}
+
 long WebPlatformStrategies::changeCount(const WTF::String &pasteboardName)
 {
     uint64_t changeCount { 0 };

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.h (235646 => 235647)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.h	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.h	2018-09-04 23:47:55 UTC (rev 235647)
@@ -76,6 +76,7 @@
     RefPtr<WebCore::SharedBuffer> bufferForType(const String& pasteboardType, const String& pasteboardName) override;
     void getPathnamesForType(Vector<String>& pathnames, const String& pasteboardType, const String& pasteboardName) override;
     String stringForType(const String& pasteboardType, const String& pasteboardName) override;
+    Vector<String> allStringsForType(const String& pasteboardType, const String& pasteboardName) override;
     long changeCount(const String& pasteboardName) override;
     String uniqueName() override;
     WebCore::Color color(const String& pasteboardName) override;

Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (235646 => 235647)


--- trunk/Source/WebKitLegacy/mac/ChangeLog	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog	2018-09-04 23:47:55 UTC (rev 235647)
@@ -1,3 +1,18 @@
+2018-09-04  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Populate "text/uri-list" with multiple URLs when the pasteboard contains multiple URLs
+        https://bugs.webkit.org/show_bug.cgi?id=188890
+        <rdar://problem/43648605>
+
+        Reviewed by Tim Horton.
+
+        Add some plumbing through pasteboard classes to support `Pasteboard::readAllStrings`. See WebCore ChangeLog for
+        more detail.
+
+        * WebCoreSupport/WebPlatformStrategies.h:
+        * WebCoreSupport/WebPlatformStrategies.mm:
+        (WebPlatformStrategies::allStringsForType):
+
 2018-09-01  Darin Adler  <da...@apple.com>
 
         [CFNetwork] Update CFNetwork SPI use to use CFNetworkSPI.h more consistently

Modified: trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.h (235646 => 235647)


--- trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.h	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.h	2018-09-04 23:47:55 UTC (rev 235647)
@@ -76,6 +76,7 @@
     RefPtr<WebCore::SharedBuffer> bufferForType(const String& pasteboardType, const String& pasteboardName) override;
     void getPathnamesForType(Vector<String>& pathnames, const String& pasteboardType, const String& pasteboardName) override;
     String stringForType(const String& pasteboardType, const String& pasteboardName) override;
+    Vector<String> allStringsForType(const String& pasteboardType, const String& pasteboardName) override;
     long changeCount(const String& pasteboardName) override;
     String uniqueName() override;
     WebCore::Color color(const String& pasteboardName) override;

Modified: trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm (235646 => 235647)


--- trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm	2018-09-04 23:47:55 UTC (rev 235647)
@@ -123,6 +123,11 @@
     PlatformPasteboard(pasteboardName).getPathnamesForType(pathnames, pasteboardType);
 }
 
+Vector<String> WebPlatformStrategies::allStringsForType(const String& pasteboardType, const String& pasteboardName)
+{
+    return PlatformPasteboard(pasteboardName).allStringsForType(pasteboardType);
+}
+
 String WebPlatformStrategies::stringForType(const String& pasteboardType, const String& pasteboardName)
 {
     return PlatformPasteboard(pasteboardName).stringForType(pasteboardType);

Modified: trunk/Tools/ChangeLog (235646 => 235647)


--- trunk/Tools/ChangeLog	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Tools/ChangeLog	2018-09-04 23:47:55 UTC (rev 235647)
@@ -1,3 +1,40 @@
+2018-09-04  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Populate "text/uri-list" with multiple URLs when the pasteboard contains multiple URLs
+        https://bugs.webkit.org/show_bug.cgi?id=188890
+        <rdar://problem/43648605>
+
+        Reviewed by Tim Horton.
+
+        * DumpRenderTree/mac/DumpRenderTreePasteboard.mm:
+        (-[LocalPasteboard pasteboardItems]):
+
+        Implement this method to avoid crashing when running layout tests that access the pasteboard.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm:
+
+        Add a test to verify that on macOS and iOS, multiple URLs dropped onto the page are accessible via
+        "text/uri-list".
+
+        * TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm:
+
+        Add a test that exercises 5 different ways to write one or more URLs to the pasteboard on macOS; in all cases,
+        the URLs written to the pasteboard should be exposed to the page via "text/uri-list". In all of these different
+        cases, the results of using `-[NSPasteboardItem stringForType:]`, `-[NSURL URLFromPasteboard:]` and
+        `-[NSPasteboard stringForType:]` will yield different results, so the purpose of this API test is to ensure that
+        our logic for grabbing a list of URLs from the pasteboard on macOS is robust enough to handle all of these
+        different behaviors.
+
+        * TestWebKitAPI/Tests/ios/UIPasteboardTests.mm:
+
+        Add a test to verify that on iOS, using `-[UIPasteboard setURLs:]` to write to multiple URLs to the pasteboard
+        and then pasting results in "text/uri-list" exposing a list of all the URLs written to the pasteboard.
+
+        * WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm:
+        (-[LocalPasteboard pasteboardItems]):
+
+        Implement this method to avoid crashing when running layout tests that access the pasteboard.
+
 2018-09-04  Simon Fraser  <simon.fra...@apple.com>
 
         REGRESSION(r235408): GTK bots exiting early

Modified: trunk/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm (235646 => 235647)


--- trunk/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm	2018-09-04 23:47:55 UTC (rev 235647)
@@ -237,6 +237,17 @@
     return YES;
 }
 
+- (NSArray<NSPasteboardItem *> *)pasteboardItems
+{
+    auto item = adoptNS([[NSPasteboardItem alloc] init]);
+    for (auto typeAndData : _data) {
+        NSData *data = "" NSData *)typeAndData.value.get();
+        NSString *type = (__bridge NSString *)typeAndData.key.get();
+        [item setData:data forType:type];
+    }
+    return @[ item.get() ];
+}
+
 @end
 
 #endif // PLATFORM(MAC)

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm (235646 => 235647)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm	2018-09-04 23:47:55 UTC (rev 235647)
@@ -43,6 +43,37 @@
 #endif
 }
 
+TEST(DragAndDropTests, ExposeMultipleURLsInDataTransfer)
+{
+    auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:CGRectMake(0, 0, 320, 500)]);
+    auto webView = [simulator webView];
+    [webView synchronouslyLoadTestPageNamed:@"DataTransfer"];
+
+    NSString *stringData = @"Hello world";
+    NSURL *firstURL = [NSURL URLWithString:@"https://webkit.org/"];
+    NSURL *secondURL = [NSURL URLWithString:@"https://apple.com/"];
+
+#if PLATFORM(MAC)
+    NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName];
+    [pasteboard writeObjects:@[ stringData, firstURL, secondURL ]];
+    [simulator setExternalDragPasteboard:pasteboard];
+#else
+    auto stringItem = adoptNS([[NSItemProvider alloc] initWithObject:stringData]);
+    auto firstURLItem = adoptNS([[NSItemProvider alloc] initWithObject:firstURL]);
+    auto secondURLItem = adoptNS([[NSItemProvider alloc] initWithObject:secondURL]);
+    for (NSItemProvider *item in @[ stringItem.get(), firstURLItem.get(), secondURLItem.get() ])
+        item.preferredPresentationStyle = UIPreferredPresentationStyleInline;
+    [simulator setExternalItemProviders:@[ stringItem.get(), firstURLItem.get(), secondURLItem.get() ]];
+#endif
+
+    [simulator runFrom:CGPointMake(0, 0) to:CGPointMake(100, 100)];
+
+    EXPECT_WK_STREQ("text/plain, text/uri-list", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
+    EXPECT_WK_STREQ("(STRING, text/plain), (STRING, text/uri-list)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
+    EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
+    EXPECT_WK_STREQ("https://webkit.org/\nhttps://apple.com/", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
+}
+
 #if ENABLE(INPUT_TYPE_COLOR)
 
 TEST(DragAndDropTests, ColorInputToColorInput)

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm (235646 => 235647)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm	2018-09-04 23:47:55 UTC (rev 235647)
@@ -255,6 +255,50 @@
     EXPECT_WK_STREQ([webView stringByEvaluatingJavaScript:@"document.querySelector('a').textContent"], urlToCopy);
 }
 
+TEST(PasteMixedContent, PasteOneOrMoreURLs)
+{
+    NSURL *appleURL = [NSURL URLWithString:@"https://www.apple.com/"];
+    NSURL *webKitURL = [NSURL URLWithString:@"https://webkit.org/"];
+
+    auto webView = setUpWebView();
+    auto runTest = [webView] (NSString *description, NSString *expectedURLString, Function<void(NSPasteboard *)>&& writeURLsToPasteboard) {
+        NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
+
+        [pasteboard clearContents];
+        writeURLsToPasteboard(pasteboard);
+        [webView stringByEvaluatingJavaScript:@"reset(); document.body.focus()"];
+        [webView paste:nil];
+
+        EXPECT_WK_STREQ(expectedURLString, [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
+        EXPECT_WK_STREQ("(STRING, text/uri-list)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
+        EXPECT_WK_STREQ("text/uri-list", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
+    };
+
+    runTest(@"Write multiple URLs.", @"https://www.apple.com/\nhttps://webkit.org/", ^(NSPasteboard *pasteboard) {
+        [pasteboard writeObjects:@[appleURL, webKitURL]];
+    });
+
+    runTest(@"Declare legacy URL and write URL to pasteboard.", @"https://www.apple.com/", ^(NSPasteboard *pasteboard) {
+        [pasteboard declareTypes:@[NSURLPboardType] owner:nil];
+        [appleURL writeToPasteboard:pasteboard];
+    });
+
+    runTest(@"Declare legacy URL and set a URL string.", @"https://www.apple.com/", ^(NSPasteboard *pasteboard) {
+        [pasteboard declareTypes:@[NSURLPboardType] owner:nil];
+        [pasteboard setString:appleURL.absoluteString forType:NSURLPboardType];
+    });
+
+    runTest(@"Declare legacy URL and set a property list.", @"https://www.apple.com/", ^(NSPasteboard *pasteboard) {
+        [pasteboard declareTypes:@[NSURLPboardType] owner:nil];
+        [pasteboard setPropertyList:@[@"/", @"https://www.apple.com"] forType:NSURLPboardType];
+    });
+
+    runTest(@"Declare URL UTI and set a URL string.", @"https://www.apple.com/", ^(NSPasteboard *pasteboard) {
+        [pasteboard declareTypes:@[(__bridge NSString *)kUTTypeURL] owner:nil];
+        [pasteboard setString:appleURL.absoluteString forType:(__bridge NSString *)kUTTypeURL];
+    });
+}
+
 #endif // PLATFORM(MAC)
 
 TEST(PasteMixedContent, CopyAndPasteWithCustomPasteboardDataOnly)

Modified: trunk/Tools/TestWebKitAPI/Tests/ios/UIPasteboardTests.mm (235646 => 235647)


--- trunk/Tools/TestWebKitAPI/Tests/ios/UIPasteboardTests.mm	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/UIPasteboardTests.mm	2018-09-04 23:47:55 UTC (rev 235647)
@@ -267,6 +267,22 @@
     });
 }
 
+TEST(UIPasteboardTests, DataTransferURIListContainsMultipleURLs)
+{
+    auto webView = setUpWebViewForPasteboardTests(@"DataTransfer");
+
+    NSURL *firstURL = [NSURL URLWithString:@"https://www.apple.com/"];
+    NSURL *secondURL = [NSURL URLWithString:@"https://webkit.org/"];
+    [UIPasteboard generalPasteboard].URLs = @[ firstURL, secondURL ];
+
+    [webView paste:nil];
+
+    EXPECT_WK_STREQ("text/uri-list, text/plain", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
+    EXPECT_WK_STREQ("(STRING, text/uri-list), (STRING, text/plain)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
+    EXPECT_WK_STREQ("https://www.apple.com/\nhttps://webkit.org/", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
+    EXPECT_WK_STREQ("https://www.apple.com/", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
+}
+
 #endif // __IPHONE_OS_VERSION_MIN_REQUIRED >= 110300
 
 } // namespace TestWebKitAPI

Modified: trunk/Tools/WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm (235646 => 235647)


--- trunk/Tools/WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm	2018-09-04 23:45:06 UTC (rev 235646)
+++ trunk/Tools/WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm	2018-09-04 23:47:55 UTC (rev 235647)
@@ -29,6 +29,7 @@
 #include "WebKitTestRunnerPasteboard.h"
 
 #include <objc/runtime.h>
+#include <wtf/RetainPtr.h>
 
 @interface LocalPasteboard : NSPasteboard
 {
@@ -197,4 +198,12 @@
     return [self setData:[string dataUsingEncoding:NSUTF8StringEncoding] forType:dataType];
 }
 
+- (NSArray<NSPasteboardItem *> *)pasteboardItems
+{
+    auto item = adoptNS([[NSPasteboardItem alloc] init]);
+    for (NSString *type in dataByType)
+        [item setData:dataByType[type] forType:type];
+    return @[ item.get() ];
+}
+
 @end
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to