Title: [223340] trunk
Revision
223340
Author
[email protected]
Date
2017-10-16 00:59:39 -0700 (Mon, 16 Oct 2017)

Log Message

On ToT, event.dataTransfer.getData("text/uri-list") returns an empty string when dragging an image
https://bugs.webkit.org/show_bug.cgi?id=178301
<rdar://problem/34990050>

Reviewed by Darin Adler.

Source/WebCore:

After r222656, we consider images on the pasteboard to be files. This causes DataTransfer.getData to return the
empty string for all types, which brings back https://bugs.webkit.org/show_bug.cgi?id=170637. To allow pages to
access the URL part of a dragged image, we exempt "text/uri-list" from our heurstics to hide pasteboard data
which may contain files, and return the URL as long as its protocol is either HTTP or HTTPS.

Tweaked an existing layout test to cover this scenario, as well as the scenario in which the dragged image links
to a file URL (in which case we should avoid exposing the data).

Test: editing/pasteboard/drag-drop-href-as-url.html
      DataInteractionTests.DataTransferGetDataWhenDroppingImageWithHTTPURL

* dom/DataTransfer.cpp:
(WebCore::DataTransfer::getDataForItem const):

When the pasteboard contains files, allow data for "text/uri-list" to be returned, as long as the URL string has
a white-listed protocol (currently, this is just http and https).

(WebCore::DataTransfer::shouldSuppressGetAndSetDataToAvoidExposingFilePaths const):
(WebCore::DataTransfer::setData):
(WebCore::DataTransfer::types const):

When the pasteboard contains files, allow "text/uri-list" to be added, alongside the "Files" type, if it would
have been exposed in the list of safe DOM types.

* dom/DataTransfer.h:
* platform/Pasteboard.cpp:
(WebCore::Pasteboard::canExposeURLToDOMWhenPasteboardContainsFiles):

Add a new helper method to determine whether it is safe to expose an URL string as "text/uri-list" to bindings,
if the pasteboard contains files. While this currently checks whether or not the URL is in the HTTP family, we
may want to consider tweaking this to blacklist the "file" protocol instead, and allow all other valid URLs by
default.

* platform/Pasteboard.h:
* platform/PlatformPasteboard.h:
* platform/ios/PlatformPasteboardIOS.mm:
(WebCore::pasteboardMayContainFilePaths):
(WebCore::PlatformPasteboard::stringForType const):

Mark stringForType as const, and also teach stringForType to return the null string for the platform URL type if
the pasteboard might contain file paths.

(WebCore::PlatformPasteboard::typesSafeForDOMToReadAndWrite const):

Before coercing a platform type to "text/uri-list" when building the list of DOM-safe types, check that the
stringForType is not the empty string, in which case we don't expose the type to the DOM at all. This ensures
that in cases where the URL might reveal a file path, we don't advertise "text/uri-list" as a type. We adopt a
similar strategy on iOS.

(WebCore::PlatformPasteboard::stringForType): Deleted.
* platform/mac/PlatformPasteboardMac.mm:
(WebCore::pasteboardMayContainFilePaths):
(WebCore::PlatformPasteboard::stringForType const):
(WebCore::PlatformPasteboard::typesSafeForDOMToReadAndWrite const):
(WebCore::PlatformPasteboard::stringForType): Deleted.

Tools:

Fixes issues in DumpRenderTree's LocalPasteboard to ensure that drag-drop-href-as-url.html exposes files, and
also adds a new iOS drag and drop API test.

* DumpRenderTree/mac/DumpRenderTreePasteboard.mm:
(-[LocalPasteboard addTypes:owner:]):
(-[LocalPasteboard setData:forType:]):

Fixes LocalPasteboard's implementation of changeCount to incremement when the pasteboard owner changes, rather
than every time data is changed. This is consistent with NSPasteboard behavior.

* TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
(TestWebKitAPI::TEST):

Adds a new API test to verify that an image and HTTP URL written by the platform is correctly web exposed.

LayoutTests:

Fixes an existing test to account for asynchronous image decoding, and also rebaselines results to expect that
only the URL can be read, and not text.

* TestExpectations:
* editing/pasteboard/data-transfer-item-list-add-file-multiple-times-expected.txt:
* editing/pasteboard/drag-drop-href-as-text-data-expected.txt: Removed.
* editing/pasteboard/drag-drop-href-as-text-data.html: Removed.
* editing/pasteboard/drag-drop-href-as-url-expected.txt: Added.
* editing/pasteboard/drag-drop-href-as-url.html: Added.

Tweaks an existing drag and drop test to verify that an URL can be read back when dragging an image, but not
when if the URL is a file URL.

* editing/pasteboard/files-during-page-drags-expected.txt:
* editing/pasteboard/files-during-page-drags.html:

Fixes this test by decoding the dragged image element before starting the drag and drop simulation.

* platform/mac-wk1/TestExpectations:

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (223339 => 223340)


--- trunk/LayoutTests/ChangeLog	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/LayoutTests/ChangeLog	2017-10-16 07:59:39 UTC (rev 223340)
@@ -1,3 +1,31 @@
+2017-10-16  Wenson Hsieh  <[email protected]>
+
+        On ToT, event.dataTransfer.getData("text/uri-list") returns an empty string when dragging an image
+        https://bugs.webkit.org/show_bug.cgi?id=178301
+        <rdar://problem/34990050>
+
+        Reviewed by Darin Adler.
+
+        Fixes an existing test to account for asynchronous image decoding, and also rebaselines results to expect that
+        only the URL can be read, and not text.
+
+        * TestExpectations:
+        * editing/pasteboard/data-transfer-item-list-add-file-multiple-times-expected.txt:
+        * editing/pasteboard/drag-drop-href-as-text-data-expected.txt: Removed.
+        * editing/pasteboard/drag-drop-href-as-text-data.html: Removed.
+        * editing/pasteboard/drag-drop-href-as-url-expected.txt: Added.
+        * editing/pasteboard/drag-drop-href-as-url.html: Added.
+
+        Tweaks an existing drag and drop test to verify that an URL can be read back when dragging an image, but not
+        when if the URL is a file URL.
+
+        * editing/pasteboard/files-during-page-drags-expected.txt:
+        * editing/pasteboard/files-during-page-drags.html:
+
+        Fixes this test by decoding the dragged image element before starting the drag and drop simulation.
+
+        * platform/mac-wk1/TestExpectations:
+
 2017-10-15  Nikita Vasilyev  <[email protected]>
 
         Web Inspector: Modify CSS number values with up key and down key

Modified: trunk/LayoutTests/TestExpectations (223339 => 223340)


--- trunk/LayoutTests/TestExpectations	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/LayoutTests/TestExpectations	2017-10-16 07:59:39 UTC (rev 223340)
@@ -71,7 +71,7 @@
 fast/events/autoscroll-main-document.html [ Skip ]
 
 # Drag and drop via EventSender is only supported on Mac WK1
-editing/pasteboard/drag-drop-href-as-text-data.html [ Skip ]
+editing/pasteboard/drag-drop-href-as-url.html [ Skip ]
 editing/pasteboard/data-transfer-get-data-on-drop-custom.html [ Skip ]
 editing/pasteboard/data-transfer-get-data-on-drop-plain-text.html [ Skip ]
 editing/pasteboard/data-transfer-get-data-on-drop-rich-text.html [ Skip ]

Modified: trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-multiple-times-expected.txt (223339 => 223340)


--- trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-multiple-times-expected.txt	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-multiple-times-expected.txt	2017-10-16 07:59:39 UTC (rev 223340)
@@ -9,7 +9,8 @@
 1. After adding all items
 {
     "data": {
-        "Files": ""
+        "Files": "",
+        "text/uri-list": "https://webkit.org"
     },
     "items": [
         {
@@ -86,7 +87,8 @@
 2. After removing at index 4
 {
     "data": {
-        "Files": ""
+        "Files": "",
+        "text/uri-list": "https://webkit.org"
     },
     "items": [
         {
@@ -150,7 +152,8 @@
 3. After removing at index 1
 {
     "data": {
-        "Files": ""
+        "Files": "",
+        "text/uri-list": "https://webkit.org"
     },
     "items": [
         {
@@ -200,7 +203,8 @@
 4. After removing at index 3
 {
     "data": {
-        "Files": ""
+        "Files": "",
+        "text/uri-list": "https://webkit.org"
     },
     "items": [
         {

Deleted: trunk/LayoutTests/editing/pasteboard/drag-drop-href-as-text-data-expected.txt (223339 => 223340)


--- trunk/LayoutTests/editing/pasteboard/drag-drop-href-as-text-data-expected.txt	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/LayoutTests/editing/pasteboard/drag-drop-href-as-text-data-expected.txt	2017-10-16 07:59:39 UTC (rev 223340)
@@ -1,5 +0,0 @@
-
-text: "https://www.webkit.org/"
-url: "https://www.webkit.org/"
-text/plain: "https://www.webkit.org/"
-text/uri-list: "https://www.webkit.org/"

Deleted: trunk/LayoutTests/editing/pasteboard/drag-drop-href-as-text-data.html (223339 => 223340)


--- trunk/LayoutTests/editing/pasteboard/drag-drop-href-as-text-data.html	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/LayoutTests/editing/pasteboard/drag-drop-href-as-text-data.html	2017-10-16 07:59:39 UTC (rev 223340)
@@ -1,52 +0,0 @@
-<!DOCTYPE html>
-<html>
-<style>
-body {
-    margin: 0;
-}
-#source {
-    width: 300px;
-    height: 300px;
-}
-#target {
-    border: 1px blue dashed;
-    font-family: monospace;
-    overflow: scroll;
-    white-space: nowrap;
-    width: 100%;
-    height: 300px;
-}
-</style>
-
-<a id="link" href="" id="source" src=""
-<div id="target"></div>
-
-<script>
-function append(text) {
-    let div = document.createElement("div");
-    div.textContent = text;
-    target.appendChild(div);
-}
-
-if (window.testRunner)
-    testRunner.dumpAsText();
-
-target.addEventListener("dragenter", event => event.preventDefault());
-target.addEventListener("dragover", event => event.preventDefault());
-target.addEventListener("drop", event => {
-    for (let type of ["text", "url", "text/plain", "text/uri-list"])
-        append(`${type}: "${event.dataTransfer.getData(type)}"`);
-    event.preventDefault();
-});
-
-if (window.eventSender) {
-    let x = source.offsetLeft + source.offsetWidth / 2;
-    let y = source.offsetTop + source.offsetHeight / 2;
-    eventSender.mouseMoveTo(x, y);
-    eventSender.mouseDown();
-    eventSender.leapForward(500);
-    eventSender.mouseMoveTo(x, y + 300);
-    eventSender.mouseUp();
-}
-</script>
-</html>
\ No newline at end of file

Added: trunk/LayoutTests/editing/pasteboard/drag-drop-href-as-url-expected.txt (0 => 223340)


--- trunk/LayoutTests/editing/pasteboard/drag-drop-href-as-url-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/drag-drop-href-as-url-expected.txt	2017-10-16 07:59:39 UTC (rev 223340)
@@ -0,0 +1,11 @@
+
+1. link.href = ""
+URL: "https://www.webkit.org/"
+url: "https://www.webkit.org/"
+text/uri-list: "https://www.webkit.org/"
+Found file of type image/png
+2. link.href = ""
+URL: ""
+url: ""
+text/uri-list: ""
+Found file of type image/png

Added: trunk/LayoutTests/editing/pasteboard/drag-drop-href-as-url.html (0 => 223340)


--- trunk/LayoutTests/editing/pasteboard/drag-drop-href-as-url.html	                        (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/drag-drop-href-as-url.html	2017-10-16 07:59:39 UTC (rev 223340)
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html>
+<style>
+body {
+    margin: 0;
+}
+#source {
+    width: 300px;
+    height: 300px;
+}
+#target {
+    border: 1px blue dashed;
+    font-family: monospace;
+    overflow: scroll;
+    white-space: nowrap;
+    width: 100%;
+    height: 300px;
+}
+</style>
+
+<body _onload_=setup()>
+<a id="link" href="" id="source" src=""
+<div id="target"></div>
+</body>
+
+<script>
+function append(text) {
+    let div = document.createElement("div");
+    div.textContent = text;
+    target.appendChild(div);
+}
+
+async function setup() {
+    target.addEventListener("dragenter", event => event.preventDefault());
+    target.addEventListener("dragover", event => event.preventDefault());
+    target.addEventListener("drop", event => {
+        for (const type of ["URL", "url", "text/uri-list"])
+            append(`${type}: "${event.dataTransfer.getData(type)}"`);
+        for (const file of event.dataTransfer.files)
+            append(`Found file of type ${file.type}`);
+        event.preventDefault();
+    });
+
+    if (!window.testRunner || !window.eventSender || !window.internals)
+        return;
+
+    internals.settings.setCustomPasteboardDataEnabled(true);
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+
+    await source.decode();
+    let x = source.offsetLeft + source.offsetWidth / 2;
+    let y = source.offsetTop + source.offsetHeight / 2;
+
+    append(`1. link.href = ""
+    eventSender.mouseMoveTo(x, y);
+    eventSender.mouseDown();
+    eventSender.leapForward(500);
+    eventSender.mouseMoveTo(x, y + 300);
+    eventSender.mouseUp();
+
+    link.href = ""
+    append(`2. link.href = ""
+    eventSender.mouseMoveTo(x, y);
+    eventSender.mouseDown();
+    eventSender.leapForward(500);
+    eventSender.mouseMoveTo(x, y + 300);
+    eventSender.mouseUp();
+
+    testRunner.notifyDone();
+}
+</script>
+</html>
\ No newline at end of file

Modified: trunk/LayoutTests/editing/pasteboard/files-during-page-drags-expected.txt (223339 => 223340)


--- trunk/LayoutTests/editing/pasteboard/files-during-page-drags-expected.txt	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/LayoutTests/editing/pasteboard/files-during-page-drags-expected.txt	2017-10-16 07:59:39 UTC (rev 223340)
@@ -4,7 +4,7 @@
 
 
 PASS Drag of A resulted in empty files array.
-PASS Drag of IMG resulted in empty files array.
+PASS Drag of IMG resulted in files array of size 1
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/editing/pasteboard/files-during-page-drags.html (223339 => 223340)


--- trunk/LayoutTests/editing/pasteboard/files-during-page-drags.html	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/LayoutTests/editing/pasteboard/files-during-page-drags.html	2017-10-16 07:59:39 UTC (rev 223340)
@@ -3,12 +3,14 @@
 <head>
 <script src=""
 </head>
-<body>
+<body _onload_=runTest()>
 <p id="description"></p>
 <div id="console"></div>
 <script>
 description("Make sure that .files arrays are always empty for non-file drags.");
 
+jsTestIsAsync = true;
+
 var testContainer = document.createElement('div');
 // Put dragables at the top so that logging does not cause them to move off screen (where we can't drag).
 document.body.insertBefore(testContainer, document.body.firstChild);
@@ -69,23 +71,25 @@
         testFailed("Drop of " + source.tagName + " never occured!");
     else if (droppedFiles.length == 0)
         testPassed("Drag of " + source.tagName + " resulted in empty files array.");
+    else if (source == image)
+        testPassed(`Drag of ${source.tagName} resulted in files array of size ${droppedFiles.length}`);
     else
         testFailed("Drag of " + source.tagName + " resulted in non-empty files array! (files: " + droppedFiles.length + ")");
     droppedFiles = null;
 }
 
-function runTest()
+async function runTest()
 {
+    if (!window.eventSender || !window.testRunner) {
+        testFailed("This test is not interactive, please run using DumpRenderTree");
+        return;
+    }
+
+    await image.decode();
     testDrag(link);
     testDrag(image);
-}
-
-if (window.eventSender) {
-    runTest();
-    // Clean up after ourselves
     document.body.removeChild(testContainer);
-} else {
-    testFailed("This test is not interactive, please run using DumpRenderTree");
+    finishJSTest();
 }
 
 var successfullyParsed = true;

Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (223339 => 223340)


--- trunk/LayoutTests/platform/mac-wk1/TestExpectations	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations	2017-10-16 07:59:39 UTC (rev 223340)
@@ -6,7 +6,7 @@
 #//////////////////////////////////////////////////////////////////////////////////////////
 
 fast/forms/attributed-strings.html [ Pass ]
-editing/pasteboard/drag-drop-href-as-text-data.html [ Pass ]
+editing/pasteboard/drag-drop-href-as-url.html [ Pass ]
 editing/pasteboard/data-transfer-get-data-on-drop-custom.html [ Pass ]
 editing/pasteboard/data-transfer-get-data-on-drop-plain-text.html [ Pass ]
 editing/pasteboard/data-transfer-get-data-on-drop-rich-text.html [ Pass ]

Modified: trunk/Source/WebCore/ChangeLog (223339 => 223340)


--- trunk/Source/WebCore/ChangeLog	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/Source/WebCore/ChangeLog	2017-10-16 07:59:39 UTC (rev 223340)
@@ -1,3 +1,67 @@
+2017-10-16  Wenson Hsieh  <[email protected]>
+
+        On ToT, event.dataTransfer.getData("text/uri-list") returns an empty string when dragging an image
+        https://bugs.webkit.org/show_bug.cgi?id=178301
+        <rdar://problem/34990050>
+
+        Reviewed by Darin Adler.
+
+        After r222656, we consider images on the pasteboard to be files. This causes DataTransfer.getData to return the
+        empty string for all types, which brings back https://bugs.webkit.org/show_bug.cgi?id=170637. To allow pages to
+        access the URL part of a dragged image, we exempt "text/uri-list" from our heurstics to hide pasteboard data
+        which may contain files, and return the URL as long as its protocol is either HTTP or HTTPS.
+
+        Tweaked an existing layout test to cover this scenario, as well as the scenario in which the dragged image links
+        to a file URL (in which case we should avoid exposing the data).
+
+        Test: editing/pasteboard/drag-drop-href-as-url.html
+              DataInteractionTests.DataTransferGetDataWhenDroppingImageWithHTTPURL
+
+        * dom/DataTransfer.cpp:
+        (WebCore::DataTransfer::getDataForItem const):
+
+        When the pasteboard contains files, allow data for "text/uri-list" to be returned, as long as the URL string has
+        a white-listed protocol (currently, this is just http and https).
+
+        (WebCore::DataTransfer::shouldSuppressGetAndSetDataToAvoidExposingFilePaths const):
+        (WebCore::DataTransfer::setData):
+        (WebCore::DataTransfer::types const):
+
+        When the pasteboard contains files, allow "text/uri-list" to be added, alongside the "Files" type, if it would
+        have been exposed in the list of safe DOM types.
+
+        * dom/DataTransfer.h:
+        * platform/Pasteboard.cpp:
+        (WebCore::Pasteboard::canExposeURLToDOMWhenPasteboardContainsFiles):
+
+        Add a new helper method to determine whether it is safe to expose an URL string as "text/uri-list" to bindings,
+        if the pasteboard contains files. While this currently checks whether or not the URL is in the HTTP family, we
+        may want to consider tweaking this to blacklist the "file" protocol instead, and allow all other valid URLs by
+        default.
+
+        * platform/Pasteboard.h:
+        * platform/PlatformPasteboard.h:
+        * platform/ios/PlatformPasteboardIOS.mm:
+        (WebCore::pasteboardMayContainFilePaths):
+        (WebCore::PlatformPasteboard::stringForType const):
+
+        Mark stringForType as const, and also teach stringForType to return the null string for the platform URL type if
+        the pasteboard might contain file paths.
+
+        (WebCore::PlatformPasteboard::typesSafeForDOMToReadAndWrite const):
+
+        Before coercing a platform type to "text/uri-list" when building the list of DOM-safe types, check that the
+        stringForType is not the empty string, in which case we don't expose the type to the DOM at all. This ensures
+        that in cases where the URL might reveal a file path, we don't advertise "text/uri-list" as a type. We adopt a
+        similar strategy on iOS.
+
+        (WebCore::PlatformPasteboard::stringForType): Deleted.
+        * platform/mac/PlatformPasteboardMac.mm:
+        (WebCore::pasteboardMayContainFilePaths):
+        (WebCore::PlatformPasteboard::stringForType const):
+        (WebCore::PlatformPasteboard::typesSafeForDOMToReadAndWrite const):
+        (WebCore::PlatformPasteboard::stringForType): Deleted.
+
 2017-10-16  Frederic Wang  <[email protected]>
 
         Use auto/nullptr in scrolling code

Modified: trunk/Source/WebCore/dom/DataTransfer.cpp (223339 => 223340)


--- trunk/Source/WebCore/dom/DataTransfer.cpp	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/Source/WebCore/dom/DataTransfer.cpp	2017-10-16 07:59:39 UTC (rev 223340)
@@ -149,12 +149,18 @@
 String DataTransfer::getDataForItem(const String& type) const
 {
     if (!canReadData())
-        return String();
+        return { };
 
-    if ((forFileDrag() || Settings::customPasteboardDataEnabled()) && m_pasteboard->containsFiles())
+    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 { };
+    }
 
-    auto lowercaseType = stripLeadingAndTrailingHTMLSpaces(type).convertToASCIILowercase();
     if (!Settings::customPasteboardDataEnabled())
         return m_pasteboard->readString(lowercaseType);
 
@@ -184,12 +190,19 @@
     return getDataForItem(normalizeType(type));
 }
 
+bool DataTransfer::shouldSuppressGetAndSetDataToAvoidExposingFilePaths() const
+{
+    if (!forFileDrag() && !Settings::customPasteboardDataEnabled())
+        return false;
+    return m_pasteboard->containsFiles();
+}
+
 void DataTransfer::setData(const String& type, const String& data)
 {
     if (!canWriteData())
         return;
 
-    if ((forFileDrag() || Settings::customPasteboardDataEnabled()) && m_pasteboard->containsFiles())
+    if (shouldSuppressGetAndSetDataToAvoidExposingFilePaths())
         return;
 
     auto normalizedType = normalizeType(type);
@@ -271,17 +284,22 @@
         return types;
     }
 
-    if (m_itemList && m_itemList->hasItems() && m_itemList->items().findMatching([] (const auto& item) { return item->isFile(); }) != notFound)
-        return addFilesType == AddFilesType::Yes ? Vector<String> { ASCIILiteral("Files") } : Vector<String> { };
+    auto safeTypes = m_pasteboard->typesSafeForBindings(m_originIdentifier);
+    bool hasFileBackedItem = m_itemList && m_itemList->hasItems() && notFound != m_itemList->items().findMatching([] (const auto& item) {
+        return item->isFile();
+    });
 
-    if (m_pasteboard->containsFiles()) {
-        ASSERT(!m_pasteboard->typesSafeForBindings(m_originIdentifier).contains("Files"));
-        return addFilesType == AddFilesType::Yes ? Vector<String> { ASCIILiteral("Files") } : Vector<String> { };
+    if (hasFileBackedItem || m_pasteboard->containsFiles()) {
+        Vector<String> types;
+        if (addFilesType == AddFilesType::Yes)
+            types.append(ASCIILiteral("Files"));
+        if (safeTypes.contains("text/uri-list"))
+            types.append(ASCIILiteral("text/uri-list"));
+        return types;
     }
 
-    auto types = m_pasteboard->typesSafeForBindings(m_originIdentifier);
-    ASSERT(!types.contains("Files"));
-    return types;
+    ASSERT(!safeTypes.contains("Files"));
+    return safeTypes;
 }
 
 Vector<Ref<File>> DataTransfer::filesFromPasteboardAndItemList() const

Modified: trunk/Source/WebCore/dom/DataTransfer.h (223339 => 223340)


--- trunk/Source/WebCore/dom/DataTransfer.h	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/Source/WebCore/dom/DataTransfer.h	2017-10-16 07:59:39 UTC (rev 223340)
@@ -121,6 +121,8 @@
     bool forFileDrag() const { return false; }
 #endif
 
+    bool shouldSuppressGetAndSetDataToAvoidExposingFilePaths() const;
+
     enum class AddFilesType { No, Yes };
     Vector<String> types(AddFilesType) const;
     Vector<Ref<File>> filesFromPasteboardAndItemList() const;

Modified: trunk/Source/WebCore/platform/Pasteboard.cpp (223339 => 223340)


--- trunk/Source/WebCore/platform/Pasteboard.cpp	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/Source/WebCore/platform/Pasteboard.cpp	2017-10-16 07:59:39 UTC (rev 223340)
@@ -30,6 +30,7 @@
 #include "PlatformStrategies.h"
 #include "Settings.h"
 #include "SharedBuffer.h"
+#include "URLParser.h"
 #include <wtf/persistence/PersistentCoders.h>
 #include <wtf/text/StringHash.h>
 
@@ -44,6 +45,11 @@
     return type == "text/plain" || type == "text/html" || type == "text/uri-list";
 }
 
+bool Pasteboard::canExposeURLToDOMWhenPasteboardContainsFiles(const String& urlString)
+{
+    return URLParser { urlString }.result().protocolIsInHTTPFamily();
+}
+
 Ref<SharedBuffer> PasteboardCustomData::createSharedBuffer() const
 {
     const static unsigned currentCustomDataSerializationVersion = 1;

Modified: trunk/Source/WebCore/platform/Pasteboard.h (223339 => 223340)


--- trunk/Source/WebCore/platform/Pasteboard.h	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/Source/WebCore/platform/Pasteboard.h	2017-10-16 07:59:39 UTC (rev 223340)
@@ -189,6 +189,7 @@
     WEBCORE_EXPORT static std::unique_ptr<Pasteboard> createForCopyAndPaste();
 
     static bool isSafeTypeForDOMToReadAndWrite(const String&);
+    static bool canExposeURLToDOMWhenPasteboardContainsFiles(const String&);
 
     virtual bool isStatic() const { return false; }
 

Modified: trunk/Source/WebCore/platform/PlatformPasteboard.h (223339 => 223340)


--- trunk/Source/WebCore/platform/PlatformPasteboard.h	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/Source/WebCore/platform/PlatformPasteboard.h	2017-10-16 07:59:39 UTC (rev 223340)
@@ -70,7 +70,7 @@
     WEBCORE_EXPORT void getTypes(Vector<String>& types);
     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);
+    WEBCORE_EXPORT String stringForType(const String& pasteboardType) const;
     WEBCORE_EXPORT long changeCount() const;
     WEBCORE_EXPORT Color color();
     WEBCORE_EXPORT URL url();

Modified: trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm (223339 => 223340)


--- trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm	2017-10-16 07:59:39 UTC (rev 223340)
@@ -111,20 +111,37 @@
     return filenames;
 }
 
-String PlatformPasteboard::stringForType(const String& type)
+static bool pasteboardMayContainFilePaths(id<AbstractPasteboard> pasteboard)
 {
-    NSArray *values = [m_pasteboard valuesForPasteboardType:type inItemSet:[NSIndexSet indexSetWithIndex:0]];
-    for (id value in values) {
-        if ([value isKindOfClass:[NSURL class]])
-            return [(NSURL *)value absoluteString];
+    if ([pasteboard isKindOfClass:[WebItemProviderPasteboard class]])
+        return false;
 
-        if ([value isKindOfClass:[NSAttributedString class]])
-            return [(NSAttributedString *)value string];
+    for (NSString *type in pasteboard.pasteboardTypes) {
+        if (Pasteboard::shouldTreatCocoaTypeAsFile(type))
+            return true;
+    }
+    return false;
+}
 
-        if ([value isKindOfClass:[NSString class]])
-            return (NSString *)value;
+String PlatformPasteboard::stringForType(const String& type) const
+{
+    auto value = retainPtr([m_pasteboard valuesForPasteboardType:type inItemSet:[NSIndexSet indexSetWithIndex:0]].firstObject);
+    String result;
+    if ([value isKindOfClass:[NSURL class]])
+        result = [(NSURL *)value absoluteString];
+
+    else if ([value isKindOfClass:[NSAttributedString class]])
+        result = [(NSAttributedString *)value string];
+
+    else if ([value isKindOfClass:[NSString class]])
+        result = (NSString *)value;
+
+    if (pasteboardMayContainFilePaths(m_pasteboard.get()) && type == String { kUTTypeURL }) {
+        if (!Pasteboard::canExposeURLToDOMWhenPasteboardContainsFiles(result))
+            result = { };
     }
-    return String();
+
+    return result;
 }
 
 Color PlatformPasteboard::color()
@@ -388,8 +405,15 @@
             continue;
         }
 
-        if (auto* coercedType = safeTypeForDOMToReadAndWriteForPlatformType(type))
-            domPasteboardTypes.add(String::fromUTF8(coercedType));
+        if (auto* coercedType = safeTypeForDOMToReadAndWriteForPlatformType(type)) {
+            auto domTypeAsString = String::fromUTF8(coercedType);
+            if (domTypeAsString == "text/uri-list") {
+                BOOL ableToDetermineProtocolOfPasteboardURL = ![m_pasteboard isKindOfClass:[WebItemProviderPasteboard class]];
+                if (ableToDetermineProtocolOfPasteboardURL && stringForType(kUTTypeURL).isEmpty())
+                    continue;
+            }
+            domPasteboardTypes.add(WTFMove(domTypeAsString));
+        }
     }
 
     return copyToVector(domPasteboardTypes);

Modified: trunk/Source/WebCore/platform/mac/PlatformPasteboardMac.mm (223339 => 223340)


--- trunk/Source/WebCore/platform/mac/PlatformPasteboardMac.mm	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/Source/WebCore/platform/mac/PlatformPasteboardMac.mm	2017-10-16 07:59:39 UTC (rev 223340)
@@ -78,16 +78,22 @@
         pathnames.append([paths objectAtIndex:i]);
 }
 
-String PlatformPasteboard::stringForType(const String& pasteboardType)
+static bool pasteboardMayContainFilePaths(NSPasteboard *pasteboard)
 {
-    if (pasteboardType == String(NSURLPboardType)) {
-        if (NSURL *urlFromPasteboard = [NSURL URLFromPasteboard:m_pasteboard.get()])
-            return urlFromPasteboard.absoluteString;
+    for (NSString *type in pasteboard.types) {
+        if ([type isEqualToString:(NSString *)NSFilenamesPboardType] || [type isEqualToString:(NSString *)NSFilesPromisePboardType] || Pasteboard::shouldTreatCocoaTypeAsFile(type))
+            return true;
+    }
+    return false;
+}
 
-        URL url([NSURL URLWithString:[m_pasteboard stringForType:NSURLPboardType]]);
-        if (!url.isValid())
+String PlatformPasteboard::stringForType(const String& pasteboardType) const
+{
+    if (pasteboardType == String { NSURLPboardType }) {
+        String urlString = ([NSURL URLFromPasteboard:m_pasteboard.get()] ?: [NSURL URLWithString:[m_pasteboard stringForType:NSURLPboardType]]).absoluteString;
+        if (pasteboardMayContainFilePaths(m_pasteboard.get()) && !Pasteboard::canExposeURLToDOMWhenPasteboardContainsFiles(urlString))
             return { };
-        return url.string();
+        return urlString;
     }
 
     return [m_pasteboard stringForType:pasteboardType];
@@ -125,8 +131,12 @@
 
         if (Pasteboard::isSafeTypeForDOMToReadAndWrite(type))
             domPasteboardTypes.add(type);
-        else if (auto* domType = safeTypeForDOMToReadAndWriteForPlatformType(type))
-            domPasteboardTypes.add(String::fromUTF8(domType));
+        else if (auto* domType = safeTypeForDOMToReadAndWriteForPlatformType(type)) {
+            auto domTypeAsString = String::fromUTF8(domType);
+            if (domTypeAsString == "text/uri-list" && stringForType(NSURLPboardType).isEmpty())
+                continue;
+            domPasteboardTypes.add(WTFMove(domTypeAsString));
+        }
     }
 
     return copyToVector(domPasteboardTypes);

Modified: trunk/Tools/ChangeLog (223339 => 223340)


--- trunk/Tools/ChangeLog	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/Tools/ChangeLog	2017-10-16 07:59:39 UTC (rev 223340)
@@ -1,3 +1,26 @@
+2017-10-16  Wenson Hsieh  <[email protected]>
+
+        On ToT, event.dataTransfer.getData("text/uri-list") returns an empty string when dragging an image
+        https://bugs.webkit.org/show_bug.cgi?id=178301
+        <rdar://problem/34990050>
+
+        Reviewed by Darin Adler.
+
+        Fixes issues in DumpRenderTree's LocalPasteboard to ensure that drag-drop-href-as-url.html exposes files, and
+        also adds a new iOS drag and drop API test.
+
+        * DumpRenderTree/mac/DumpRenderTreePasteboard.mm:
+        (-[LocalPasteboard addTypes:owner:]):
+        (-[LocalPasteboard setData:forType:]):
+
+        Fixes LocalPasteboard's implementation of changeCount to incremement when the pasteboard owner changes, rather
+        than every time data is changed. This is consistent with NSPasteboard behavior.
+
+        * TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
+        (TestWebKitAPI::TEST):
+
+        Adds a new API test to verify that an image and HTTP URL written by the platform is correctly web exposed.
+
 2017-10-15  Darin Adler  <[email protected]>
 
         UTF-8 decoding produces one replacement character per byte; Encoding standard requires one replacement character per illegal sequence instead

Modified: trunk/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm (223339 => 223340)


--- trunk/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm	2017-10-16 07:59:39 UTC (rev 223340)
@@ -141,11 +141,15 @@
 
 - (NSInteger)addTypes:(NSArray *)newTypes owner:(id)newOwner
 {
-    _owner = newOwner;
+    if (_owner != newOwner) {
+        _owner = newOwner;
+        ++_changeCount;
+    }
+
     for (NSString *type in newTypes)
         _types.add(toUTI(type));
 
-    return ++_changeCount;
+    return _changeCount;
 }
 
 - (NSInteger)changeCount
@@ -186,7 +190,6 @@
         return NO;
 
     _data.set(WTFMove(uti), data ? data : [NSData data]);
-    ++_changeCount;
     return YES;
 }
 

Modified: trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm (223339 => 223340)


--- trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2017-10-16 07:58:15 UTC (rev 223339)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2017-10-16 07:59:39 UTC (rev 223340)
@@ -1560,11 +1560,33 @@
 
     // File URLs should never be exposed directly to web content, so DataTransfer.getData should return an empty string here.
     checkJSONWithLogging([webView stringByEvaluatingJavaScript:@"output.value"], @{
-        @"dragover": @{ @"Files": @"" },
-        @"drop": @{ @"Files": @"" }
+        @"dragover": @{ @"Files": @"", @"text/uri-list": @"" },
+        @"drop": @{ @"Files": @"", @"text/uri-list": @"" }
     });
 }
 
+TEST(DataInteractionTests, DataTransferGetDataWhenDroppingImageWithHTTPURL)
+{
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+    [webView synchronouslyLoadTestPageNamed:@"dump-datatransfer-types"];
+    auto simulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
+
+    auto itemProvider = adoptNS([[UIItemProvider alloc] init]);
+    [itemProvider registerDataRepresentationForTypeIdentifier:(NSString *)kUTTypeJPEG visibility:NSItemProviderRepresentationVisibilityAll loadHandler:^NSProgress *(DataLoadCompletionBlock completionHandler)
+    {
+        completionHandler(UIImageJPEGRepresentation(testIconImage(), 0.5), nil);
+        return nil;
+    }];
+    [itemProvider registerObject:[NSURL URLWithString:@"http://webkit.org"] visibility:UIItemProviderRepresentationOptionsVisibilityAll];
+    [simulator setExternalItemProviders:@[ itemProvider.get() ]];
+
+    [simulator runFrom:CGPointMake(300, 375) to:CGPointMake(50, 375)];
+    checkJSONWithLogging([webView stringByEvaluatingJavaScript:@"output.value"], @{
+        @"dragover": @{ @"Files": @"", @"text/uri-list": @"" },
+        @"drop": @{ @"Files": @"", @"text/uri-list": @"http://webkit.org/" }
+    });
+}
+
 TEST(DataInteractionTests, DataTransferGetDataWhenDroppingRespectsPresentationStyle)
 {
     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to