Title: [228340] trunk
Revision
228340
Author
wenson_hs...@apple.com
Date
2018-02-09 15:41:34 -0800 (Fri, 09 Feb 2018)

Log Message

Pasting from Excel no longer provides text/html data
https://bugs.webkit.org/show_bug.cgi?id=182636
<rdar://problem/37087060>

Reviewed by Ryosuke Niwa.

Source/WebCore:

After r222656, we treat images on the pasteboard as files. However, we also have an existing policy which hides
text data ("text/uri-list", "text/html", "text/plain") from the page when files are present on the pasteboard.
When copying a table, Microsoft Excel writes a rendering of the table to the pasteboard as an image. This means
that we'll hide other data types (importantly, 'text/html') upon pasting, even though important clients (such as
Google Docs and Confluence) depend on the 'text/html' data in order to correctly handle the paste (rather than
paste as an image of a table).

To fix this, we add an exception to the DataTransfer.getData codepath when the pasteboard contains files.
Instead of always returning the empty string for text/html, we still allow pasteboard access, but only read
from a limited set of rich text types, i.e. web archive, RTF(D), and HTML markup. Importantly, this prevents
us from exposing any file paths that appear as plain text or URLs on the pasteboard. Just as in the regular
codepath for getData(), if the pasteboard data comes from the same origin, we allow unsanitized access;
otherwise, we use WebContentMarkupReader to extract markup from the pasteboard.

Tests:  PasteMixedContent.ImageFileAndPlainText
        PasteMixedContent.ImageFileAndWebArchive
        PasteMixedContent.ImageFileAndHTML
        PasteMixedContent.ImageFileAndRTF
        PasteMixedContent.ImageFileAndURL
        PasteMixedContent.ImageFileWithHTMLAndURL
        DataInteractionTests.DataTransferGetDataWhenDroppingImageAndMarkup

Also rebaselined some layout tests, which cover changes in behavior when dropping on macOS and pasting on iOS.

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

Augment the codepath handling the case where the pasteboard contains files, such that we allow reading
"text/html", but only from rich text types.

(WebCore::DataTransfer::readStringFromPasteboard const):

Factor out logic for reading from the pasteboard into a private helper. This is called in two places from
getDataForItem: in the normal (existing) path, and in the case where we allow 'text/html' to be read despite
files appearing in the pasteboard.

One important difference here is that this helper now takes a WebContentReadingPolicy, whose purpose is to
prevent reading from non-rich-text types when files appear in the pasteboard.

Another tweak here is that we now use `lowercaseType` instead of the original (unadjusted) `type` when reading
from the pasteboard. This doesn't seem to be intended in the first place.

(WebCore::DataTransfer::types const):

Tweak the implementation of DataTransfer.types() in the case where files exist on the pasteboard, such that we
also add "text/html" if it is present in the list of DOM-safe types.

* dom/DataTransfer.h:
* platform/Pasteboard.h:

Introduce WebContentReadingPolicy, which indicates whether or not we should limit web content reading from the
pasteboard to only rich text types upon paste or drop. Normally, we allow all types to be read as web content
(::AnyType), but when files appear on the pasteboard, we force OnlyRichTextTypes to ensure that no other types
can unintentionally be read back as web content.

* platform/StaticPasteboard.h:
* platform/gtk/PasteboardGtk.cpp:
(WebCore::Pasteboard::read):
* platform/ios/PasteboardIOS.mm:

Teach Pasteboard (on iOS) to respect WebContentReadingPolicy.

(WebCore::isTypeAllowedByReadingPolicy):
(WebCore::Pasteboard::read):
(WebCore::Pasteboard::readRespectingUTIFidelities):
* platform/mac/PasteboardMac.mm:

Teach Pasteboard (on macOS) to respect WebContentReadingPolicy.

(WebCore::Pasteboard::read):
* platform/win/PasteboardWin.cpp:
(WebCore::Pasteboard::read):
* platform/wpe/PasteboardWPE.cpp:
(WebCore::Pasteboard::read):

Adjust non-Cocoa Pasteboard implementations for an interface change.

Tools:

Add new API tests to exercise pasting images with various other content types on macOS, and when dropping images
and HTML markup on iOS. See the WebCore ChangeLog for more detail.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/DataTransfer.html: Added.

Add a new API test harness that dumps various bits of information about a DataTransfer upon paste and drop.
While somewhat similar to some existing harnesses, this makes a distinction between the raw HTML data on the
pasteboard and the actual result of inserting said HTML into the DOM. This allows us to check that the HTML has
been sanitized, while making checks for the actual content of the HTML robust against inline style changes.

* TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm:
* TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm: Added.

Add a new test suite to exercise pasting mixed content types. In these test cases, the pasteboard contains a
file, with some combination of plain text, rich text, and URLs.

(imagePath):
(writeTypesAndDataToPasteboard):

Add a helper to write a var-arg list of content types and data to the general NSPasteboard.

(setUpWebView):
(markupString):
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
(TestWebKitAPI::testIconImageData):
(TestWebKitAPI::TEST):
* TestWebKitAPI/cocoa/TestWKWebView.h:

Move a private declaration of -[WKWebView paste:] out to TestWKWebView.h, so that it can be shared across
multiple tests. Currently, it only resides in PasteImage.mm, but I need it in PasteMixedContent.mm as well.

LayoutTests:

Rebaseline some existing layout tests. We now expose "text/html" alongside "Files" on DataTransfer.types() in
some circumstances. This also provides some test coverage for ensuring that the paste codepath iOS allows the
page to request HTML, even if there are files on the pasteboard. See the WebCore ChangeLog for more detail.

* editing/pasteboard/data-transfer-item-list-add-file-multiple-times-expected.txt:
* editing/pasteboard/data-transfer-item-list-add-file-on-copy-expected.txt:
* editing/pasteboard/data-transfer-item-list-add-file-on-drag-expected.txt:

Adjust test expectations for the additional "text/html" type.

* editing/pasteboard/paste-image-does-not-reveal-file-url-expected.txt:
* editing/pasteboard/paste-image-does-not-reveal-file-url.html:

Instead of checking that types is [ "Files" ], just check that types contains "Files". On iOS, copying a
selected image does not also copy HTML, but on macOS it does; this covers both cases.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (228339 => 228340)


--- trunk/LayoutTests/ChangeLog	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/LayoutTests/ChangeLog	2018-02-09 23:41:34 UTC (rev 228340)
@@ -1,3 +1,27 @@
+2018-02-08  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Pasting from Excel no longer provides text/html data
+        https://bugs.webkit.org/show_bug.cgi?id=182636
+        <rdar://problem/37087060>
+
+        Reviewed by Ryosuke Niwa.
+
+        Rebaseline some existing layout tests. We now expose "text/html" alongside "Files" on DataTransfer.types() in
+        some circumstances. This also provides some test coverage for ensuring that the paste codepath iOS allows the
+        page to request HTML, even if there are files on the pasteboard. See the WebCore ChangeLog for more detail.
+
+        * editing/pasteboard/data-transfer-item-list-add-file-multiple-times-expected.txt:
+        * editing/pasteboard/data-transfer-item-list-add-file-on-copy-expected.txt:
+        * editing/pasteboard/data-transfer-item-list-add-file-on-drag-expected.txt:
+
+        Adjust test expectations for the additional "text/html" type.
+
+        * editing/pasteboard/paste-image-does-not-reveal-file-url-expected.txt:
+        * editing/pasteboard/paste-image-does-not-reveal-file-url.html:
+
+        Instead of checking that types is [ "Files" ], just check that types contains "Files". On iOS, copying a
+        selected image does not also copy HTML, but on macOS it does; this covers both cases.
+
 2018-02-09  Matt Baker  <mattba...@apple.com>
 
         Web Inspector: Object.shallowEqual always fails when comparing array property values

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


--- trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-multiple-times-expected.txt	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-multiple-times-expected.txt	2018-02-09 23:41:34 UTC (rev 228340)
@@ -247,7 +247,8 @@
 6. After adding two files and some string data again
 {
     "data": {
-        "Files": ""
+        "Files": "",
+        "text/html": "<strong>some styled text</strong>"
     },
     "items": [
         {
@@ -296,7 +297,8 @@
 7. After removing at index 2
 {
     "data": {
-        "Files": ""
+        "Files": "",
+        "text/html": "<strong>some styled text</strong>"
     },
     "items": [
         {
@@ -341,7 +343,8 @@
 8. After removing at index 2
 {
     "data": {
-        "Files": ""
+        "Files": "",
+        "text/html": "<strong>some styled text</strong>"
     },
     "items": [
         {

Modified: trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-copy-expected.txt (228339 => 228340)


--- trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-copy-expected.txt	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-copy-expected.txt	2018-02-09 23:41:34 UTC (rev 228340)
@@ -129,7 +129,8 @@
 5. After adding an HTML string
 {
     "data": {
-        "Files": ""
+        "Files": "",
+        "text/html": "<a>goodbye world</a>"
     },
     "items": [
         {
@@ -164,7 +165,8 @@
 6. After adding another plain text file
 {
     "data": {
-        "Files": ""
+        "Files": "",
+        "text/html": "<a>goodbye world</a>"
     },
     "items": [
         {
@@ -213,7 +215,8 @@
 7. After removing the custom file
 {
     "data": {
-        "Files": ""
+        "Files": "",
+        "text/html": "<a>goodbye world</a>"
     },
     "items": [
         {

Modified: trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-drag-expected.txt (228339 => 228340)


--- trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-drag-expected.txt	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-drag-expected.txt	2018-02-09 23:41:34 UTC (rev 228340)
@@ -129,7 +129,8 @@
 5. After adding an HTML string
 {
     "data": {
-        "Files": ""
+        "Files": "",
+        "text/html": "<a>goodbye world</a>"
     },
     "items": [
         {
@@ -164,7 +165,8 @@
 6. After adding another plain text file
 {
     "data": {
-        "Files": ""
+        "Files": "",
+        "text/html": "<a>goodbye world</a>"
     },
     "items": [
         {
@@ -213,7 +215,8 @@
 7. After removing the custom file
 {
     "data": {
-        "Files": ""
+        "Files": "",
+        "text/html": "<a>goodbye world</a>"
     },
     "items": [
         {

Modified: trunk/LayoutTests/editing/pasteboard/paste-image-does-not-reveal-file-url-expected.txt (228339 => 228340)


--- trunk/LayoutTests/editing/pasteboard/paste-image-does-not-reveal-file-url-expected.txt	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/LayoutTests/editing/pasteboard/paste-image-does-not-reveal-file-url-expected.txt	2018-02-09 23:41:34 UTC (rev 228340)
@@ -3,7 +3,7 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS JSON.stringify(event.clipboardData.types) is "[\"Files\"]"
+PASS event.clipboardData.types.includes("Files") is true
 PASS event.clipboardData.getData("url") is ""
 PASS event.clipboardData.getData("text/plain") is ""
 PASS event.clipboardData.getData("text/uri-list") is ""

Modified: trunk/LayoutTests/editing/pasteboard/paste-image-does-not-reveal-file-url.html (228339 => 228340)


--- trunk/LayoutTests/editing/pasteboard/paste-image-does-not-reveal-file-url.html	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/LayoutTests/editing/pasteboard/paste-image-does-not-reveal-file-url.html	2018-02-09 23:41:34 UTC (rev 228340)
@@ -31,7 +31,7 @@
 
 function check(event)
 {
-    shouldBeEqualToString('JSON.stringify(event.clipboardData.types)', '["Files"]');
+    shouldBeTrue('event.clipboardData.types.includes("Files")');
     shouldBeEqualToString('event.clipboardData.getData("url")', '');
     shouldBeEqualToString('event.clipboardData.getData("text/plain")', '');
     shouldBeEqualToString('event.clipboardData.getData("text/uri-list")', '');

Modified: trunk/Source/WebCore/ChangeLog (228339 => 228340)


--- trunk/Source/WebCore/ChangeLog	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/Source/WebCore/ChangeLog	2018-02-09 23:41:34 UTC (rev 228340)
@@ -1,3 +1,88 @@
+2018-02-09  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Pasting from Excel no longer provides text/html data
+        https://bugs.webkit.org/show_bug.cgi?id=182636
+        <rdar://problem/37087060>
+
+        Reviewed by Ryosuke Niwa.
+
+        After r222656, we treat images on the pasteboard as files. However, we also have an existing policy which hides
+        text data ("text/uri-list", "text/html", "text/plain") from the page when files are present on the pasteboard.
+        When copying a table, Microsoft Excel writes a rendering of the table to the pasteboard as an image. This means
+        that we'll hide other data types (importantly, 'text/html') upon pasting, even though important clients (such as
+        Google Docs and Confluence) depend on the 'text/html' data in order to correctly handle the paste (rather than
+        paste as an image of a table).
+
+        To fix this, we add an exception to the DataTransfer.getData codepath when the pasteboard contains files.
+        Instead of always returning the empty string for text/html, we still allow pasteboard access, but only read
+        from a limited set of rich text types, i.e. web archive, RTF(D), and HTML markup. Importantly, this prevents
+        us from exposing any file paths that appear as plain text or URLs on the pasteboard. Just as in the regular
+        codepath for getData(), if the pasteboard data comes from the same origin, we allow unsanitized access;
+        otherwise, we use WebContentMarkupReader to extract markup from the pasteboard.
+
+        Tests:  PasteMixedContent.ImageFileAndPlainText
+                PasteMixedContent.ImageFileAndWebArchive
+                PasteMixedContent.ImageFileAndHTML
+                PasteMixedContent.ImageFileAndRTF
+                PasteMixedContent.ImageFileAndURL
+                PasteMixedContent.ImageFileWithHTMLAndURL
+                DataInteractionTests.DataTransferGetDataWhenDroppingImageAndMarkup
+
+        Also rebaselined some layout tests, which cover changes in behavior when dropping on macOS and pasting on iOS.
+
+        * dom/DataTransfer.cpp:
+        (WebCore::DataTransfer::getDataForItem const):
+
+        Augment the codepath handling the case where the pasteboard contains files, such that we allow reading
+        "text/html", but only from rich text types.
+
+        (WebCore::DataTransfer::readStringFromPasteboard const):
+
+        Factor out logic for reading from the pasteboard into a private helper. This is called in two places from
+        getDataForItem: in the normal (existing) path, and in the case where we allow 'text/html' to be read despite
+        files appearing in the pasteboard.
+
+        One important difference here is that this helper now takes a WebContentReadingPolicy, whose purpose is to
+        prevent reading from non-rich-text types when files appear in the pasteboard.
+
+        Another tweak here is that we now use `lowercaseType` instead of the original (unadjusted) `type` when reading
+        from the pasteboard. This doesn't seem to be intended in the first place.
+
+        (WebCore::DataTransfer::types const):
+
+        Tweak the implementation of DataTransfer.types() in the case where files exist on the pasteboard, such that we
+        also add "text/html" if it is present in the list of DOM-safe types.
+
+        * dom/DataTransfer.h:
+        * platform/Pasteboard.h:
+
+        Introduce WebContentReadingPolicy, which indicates whether or not we should limit web content reading from the
+        pasteboard to only rich text types upon paste or drop. Normally, we allow all types to be read as web content
+        (::AnyType), but when files appear on the pasteboard, we force OnlyRichTextTypes to ensure that no other types
+        can unintentionally be read back as web content.
+
+        * platform/StaticPasteboard.h:
+        * platform/gtk/PasteboardGtk.cpp:
+        (WebCore::Pasteboard::read):
+        * platform/ios/PasteboardIOS.mm:
+
+        Teach Pasteboard (on iOS) to respect WebContentReadingPolicy.
+
+        (WebCore::isTypeAllowedByReadingPolicy):
+        (WebCore::Pasteboard::read):
+        (WebCore::Pasteboard::readRespectingUTIFidelities):
+        * platform/mac/PasteboardMac.mm:
+
+        Teach Pasteboard (on macOS) to respect WebContentReadingPolicy.
+
+        (WebCore::Pasteboard::read):
+        * platform/win/PasteboardWin.cpp:
+        (WebCore::Pasteboard::read):
+        * platform/wpe/PasteboardWPE.cpp:
+        (WebCore::Pasteboard::read):
+
+        Adjust non-Cocoa Pasteboard implementations for an interface change.
+
 2018-02-09  Zalan Bujtas  <za...@apple.com>
 
         [RenderTreeBuilder] Move RenderRubyAsInline/AsBlock::takeChild mutation to a RenderTreeBuilder

Modified: trunk/Source/WebCore/dom/DataTransfer.cpp (228339 => 228340)


--- trunk/Source/WebCore/dom/DataTransfer.cpp	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/Source/WebCore/dom/DataTransfer.cpp	2018-02-09 23:41:34 UTC (rev 228340)
@@ -154,9 +154,23 @@
             if (Pasteboard::canExposeURLToDOMWhenPasteboardContainsFiles(urlString))
                 return urlString;
         }
+
+        if (lowercaseType == "text/html" && RuntimeEnabledFeatures::sharedFeatures().customPasteboardDataEnabled()) {
+            // If the pasteboard contains files and the page requests 'text/html', we only read from rich text types to prevent file
+            // paths from leaking (e.g. from plain text data on the pasteboard) since we sanitize cross-origin markup. However, if
+            // custom pasteboard data is disabled, then we can't ensure that the markup we deliver is sanitized, so we fall back to
+            // current behavior and return an empty string.
+            return readStringFromPasteboard(document, lowercaseType, WebContentReadingPolicy::OnlyRichTextTypes);
+        }
+
         return { };
     }
 
+    return readStringFromPasteboard(document, lowercaseType, WebContentReadingPolicy::AnyType);
+}
+
+String DataTransfer::readStringFromPasteboard(Document& document, const String& lowercaseType, WebContentReadingPolicy policy) const
+{
     if (!RuntimeEnabledFeatures::sharedFeatures().customPasteboardDataEnabled())
         return m_pasteboard->readString(lowercaseType);
 
@@ -170,15 +184,15 @@
     if (!Pasteboard::isSafeTypeForDOMToReadAndWrite(lowercaseType))
         return { };
 
-    if (!is<StaticPasteboard>(*m_pasteboard) && type == "text/html") {
+    if (!is<StaticPasteboard>(*m_pasteboard) && lowercaseType == "text/html") {
         if (!document.frame())
             return { };
         WebContentMarkupReader reader { *document.frame() };
-        m_pasteboard->read(reader);
+        m_pasteboard->read(reader, policy);
         return reader.markup;
     }
 
-    return m_pasteboard->readString(type);
+    return m_pasteboard->readString(lowercaseType);
 }
 
 String DataTransfer::getData(Document& document, const String& type) const
@@ -293,6 +307,8 @@
             types.append(ASCIILiteral("Files"));
         if (safeTypes.contains("text/uri-list"))
             types.append(ASCIILiteral("text/uri-list"));
+        if (safeTypes.contains("text/html") && RuntimeEnabledFeatures::sharedFeatures().customPasteboardDataEnabled())
+            types.append(ASCIILiteral("text/html"));
         return types;
     }
 

Modified: trunk/Source/WebCore/dom/DataTransfer.h (228339 => 228340)


--- trunk/Source/WebCore/dom/DataTransfer.h	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/Source/WebCore/dom/DataTransfer.h	2018-02-09 23:41:34 UTC (rev 228340)
@@ -39,6 +39,7 @@
 class FileList;
 class File;
 class Pasteboard;
+enum class WebContentReadingPolicy;
 
 class DataTransfer : public RefCounted<DataTransfer> {
 public:
@@ -121,6 +122,7 @@
     bool forFileDrag() const { return false; }
 #endif
 
+    String readStringFromPasteboard(Document&, const String& lowercaseType, WebContentReadingPolicy) const;
     bool shouldSuppressGetAndSetDataToAvoidExposingFilePaths() const;
 
     enum class AddFilesType { No, Yes };

Modified: trunk/Source/WebCore/platform/Pasteboard.h (228339 => 228340)


--- trunk/Source/WebCore/platform/Pasteboard.h	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/Source/WebCore/platform/Pasteboard.h	2018-02-09 23:41:34 UTC (rev 228340)
@@ -64,6 +64,7 @@
 class SelectionData;
 class SharedBuffer;
 
+enum class WebContentReadingPolicy { AnyType, OnlyRichTextTypes };
 enum ShouldSerializeSelectedTextForDataTransfer { DefaultSelectedTextType, IncludeImageAltTextForDataTransfer };
 
 // For writing to the pasteboard. Generally sorted with the richest formats on top.
@@ -209,7 +210,7 @@
     virtual WEBCORE_EXPORT void clear(const String& type);
 
     virtual WEBCORE_EXPORT void read(PasteboardPlainText&);
-    virtual WEBCORE_EXPORT void read(PasteboardWebContentReader&);
+    virtual WEBCORE_EXPORT void read(PasteboardWebContentReader&, WebContentReadingPolicy = WebContentReadingPolicy::AnyType);
     virtual WEBCORE_EXPORT void read(PasteboardFileReader&);
 
     virtual WEBCORE_EXPORT void write(const PasteboardURL&);
@@ -273,7 +274,7 @@
 private:
 #if PLATFORM(IOS)
     bool respectsUTIFidelities() const;
-    void readRespectingUTIFidelities(PasteboardWebContentReader&);
+    void readRespectingUTIFidelities(PasteboardWebContentReader&, WebContentReadingPolicy);
 
     enum class ReaderResult {
         ReadType,

Modified: trunk/Source/WebCore/platform/StaticPasteboard.h (228339 => 228340)


--- trunk/Source/WebCore/platform/StaticPasteboard.h	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/Source/WebCore/platform/StaticPasteboard.h	2018-02-09 23:41:34 UTC (rev 228340)
@@ -53,7 +53,7 @@
     void clear(const String& type) final;
 
     void read(PasteboardPlainText&) final { }
-    void read(PasteboardWebContentReader&) final { }
+    void read(PasteboardWebContentReader&, WebContentReadingPolicy) final { }
 
     void write(const PasteboardURL&) final { }
     void write(const PasteboardImage&) final { }

Modified: trunk/Source/WebCore/platform/gtk/PasteboardGtk.cpp (228339 => 228340)


--- trunk/Source/WebCore/platform/gtk/PasteboardGtk.cpp	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/Source/WebCore/platform/gtk/PasteboardGtk.cpp	2018-02-09 23:41:34 UTC (rev 228340)
@@ -236,7 +236,7 @@
     text.text = m_selectionData->text();
 }
 
-void Pasteboard::read(PasteboardWebContentReader&)
+void Pasteboard::read(PasteboardWebContentReader&, WebContentReadingPolicy)
 {
 }
 

Modified: trunk/Source/WebCore/platform/ios/PasteboardIOS.mm (228339 => 228340)


--- trunk/Source/WebCore/platform/ios/PasteboardIOS.mm	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/Source/WebCore/platform/ios/PasteboardIOS.mm	2018-02-09 23:41:34 UTC (rev 228340)
@@ -163,6 +163,15 @@
     return @[(id)kUTTypePNG, (id)kUTTypeTIFF, (id)kUTTypeJPEG, (id)kUTTypeGIF];
 }
 
+static bool isTypeAllowedByReadingPolicy(NSString *type, WebContentReadingPolicy policy)
+{
+    return policy == WebContentReadingPolicy::AnyType
+        || [type isEqualToString:WebArchivePboardType]
+        || [type isEqualToString:(NSString *)kUTTypeHTML]
+        || [type isEqualToString:(NSString *)kUTTypeRTF]
+        || [type isEqualToString:(NSString *)kUTTypeFlatRTFD];
+}
+
 Pasteboard::ReaderResult Pasteboard::readPasteboardWebContentDataForType(PasteboardWebContentReader& reader, PasteboardStrategy& strategy, NSString *type, int itemIndex)
 {
     if ([type isEqualToString:WebArchivePboardType]) {
@@ -225,11 +234,11 @@
     return ReaderResult::DidNotReadType;
 }
 
-void Pasteboard::read(PasteboardWebContentReader& reader)
+void Pasteboard::read(PasteboardWebContentReader& reader, WebContentReadingPolicy policy)
 {
     reader.contentOrigin = readOrigin();
     if (respectsUTIFidelities()) {
-        readRespectingUTIFidelities(reader);
+        readRespectingUTIFidelities(reader, policy);
         return;
     }
 
@@ -245,9 +254,14 @@
 
     for (int i = 0; i < numberOfItems; i++) {
         for (int typeIndex = 0; typeIndex < numberOfTypes; typeIndex++) {
-            auto itemResult = readPasteboardWebContentDataForType(reader, strategy, [types objectAtIndex:typeIndex], i);
+            NSString *type = [types objectAtIndex:typeIndex];
+            if (!isTypeAllowedByReadingPolicy(type, policy))
+                continue;
+
+            auto itemResult = readPasteboardWebContentDataForType(reader, strategy, type, i);
             if (itemResult == ReaderResult::PasteboardWasChangedExternally)
                 return;
+
             if (itemResult == ReaderResult::ReadType)
                 break;
         }
@@ -262,7 +276,7 @@
     return m_pasteboardName == "data interaction pasteboard";
 }
 
-void Pasteboard::readRespectingUTIFidelities(PasteboardWebContentReader& reader)
+void Pasteboard::readRespectingUTIFidelities(PasteboardWebContentReader& reader, WebContentReadingPolicy policy)
 {
     ASSERT(respectsUTIFidelities());
     auto& strategy = *platformStrategies()->pasteboardStrategy();
@@ -269,7 +283,7 @@
     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();
+        bool canReadAttachment = policy == WebContentReadingPolicy::AnyType && RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled() && !info.pathForFileUpload.isEmpty();
         if (canReadAttachment && info.preferredPresentationStyle == PasteboardItemPresentationStyle::Attachment) {
             reader.readFilePaths({ info.pathForFileUpload });
             continue;
@@ -281,6 +295,9 @@
         strategy.getTypesByFidelityForItemAtIndex(typesForItemInOrderOfFidelity, index, m_pasteboardName);
         ReaderResult result = ReaderResult::DidNotReadType;
         for (auto& type : typesForItemInOrderOfFidelity) {
+            if (!isTypeAllowedByReadingPolicy(type, policy))
+                continue;
+
             result = readPasteboardWebContentDataForType(reader, strategy, type, index);
             if (result == ReaderResult::PasteboardWasChangedExternally)
                 return;

Modified: trunk/Source/WebCore/platform/mac/PasteboardMac.mm (228339 => 228340)


--- trunk/Source/WebCore/platform/mac/PasteboardMac.mm	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/Source/WebCore/platform/mac/PasteboardMac.mm	2018-02-09 23:41:34 UTC (rev 228340)
@@ -331,7 +331,7 @@
     text.isURL = !text.text.isNull();
 }
 
-void Pasteboard::read(PasteboardWebContentReader& reader)
+void Pasteboard::read(PasteboardWebContentReader& reader, WebContentReadingPolicy policy)
 {
     PasteboardStrategy& strategy = *platformStrategies()->pasteboardStrategy();
 
@@ -347,7 +347,7 @@
         }
     }
 
-    if (types.contains(String(legacyFilenamesPasteboardType()))) {
+    if (policy == WebContentReadingPolicy::AnyType && types.contains(String(legacyFilenamesPasteboardType()))) {
         Vector<String> paths;
         strategy.getPathnamesForType(paths, legacyFilenamesPasteboardType(), m_pasteboardName);
         if (m_changeCount != changeCount() || reader.readFilePaths(paths))
@@ -374,6 +374,9 @@
         }
     }
 
+    if (policy == WebContentReadingPolicy::OnlyRichTextTypes)
+        return;
+
     if (types.contains(String(legacyTIFFPasteboardType()))) {
         if (RefPtr<SharedBuffer> buffer = strategy.bufferForType(legacyTIFFPasteboardType(), m_pasteboardName)) {
             if (m_changeCount != changeCount() || reader.readImage(buffer.releaseNonNull(), ASCIILiteral("image/tiff")))

Modified: trunk/Source/WebCore/platform/win/PasteboardWin.cpp (228339 => 228340)


--- trunk/Source/WebCore/platform/win/PasteboardWin.cpp	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/Source/WebCore/platform/win/PasteboardWin.cpp	2018-02-09 23:41:34 UTC (rev 228340)
@@ -1073,7 +1073,7 @@
 {
 }
 
-void Pasteboard::read(PasteboardWebContentReader&)
+void Pasteboard::read(PasteboardWebContentReader&, WebContentReadingPolicy)
 {
 }
 

Modified: trunk/Source/WebCore/platform/wpe/PasteboardWPE.cpp (228339 => 228340)


--- trunk/Source/WebCore/platform/wpe/PasteboardWPE.cpp	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/Source/WebCore/platform/wpe/PasteboardWPE.cpp	2018-02-09 23:41:34 UTC (rev 228340)
@@ -97,7 +97,7 @@
     text.text = platformStrategies()->pasteboardStrategy()->readStringFromPasteboard(0, "text/plain;charset=utf-8");
 }
 
-void Pasteboard::read(PasteboardWebContentReader&)
+void Pasteboard::read(PasteboardWebContentReader&, WebContentReadingPolicy)
 {
     notImplemented();
 }

Modified: trunk/Tools/ChangeLog (228339 => 228340)


--- trunk/Tools/ChangeLog	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/Tools/ChangeLog	2018-02-09 23:41:34 UTC (rev 228340)
@@ -1,3 +1,44 @@
+2018-02-08  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Pasting from Excel no longer provides text/html data
+        https://bugs.webkit.org/show_bug.cgi?id=182636
+        <rdar://problem/37087060>
+
+        Reviewed by Ryosuke Niwa.
+
+        Add new API tests to exercise pasting images with various other content types on macOS, and when dropping images
+        and HTML markup on iOS. See the WebCore ChangeLog for more detail.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/DataTransfer.html: Added.
+
+        Add a new API test harness that dumps various bits of information about a DataTransfer upon paste and drop.
+        While somewhat similar to some existing harnesses, this makes a distinction between the raw HTML data on the
+        pasteboard and the actual result of inserting said HTML into the DOM. This allows us to check that the HTML has
+        been sanitized, while making checks for the actual content of the HTML robust against inline style changes.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm:
+        * TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm: Added.
+
+        Add a new test suite to exercise pasting mixed content types. In these test cases, the pasteboard contains a
+        file, with some combination of plain text, rich text, and URLs.
+
+        (imagePath):
+        (writeTypesAndDataToPasteboard):
+
+        Add a helper to write a var-arg list of content types and data to the general NSPasteboard.
+
+        (setUpWebView):
+        (markupString):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
+        (TestWebKitAPI::testIconImageData):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/cocoa/TestWKWebView.h:
+
+        Move a private declaration of -[WKWebView paste:] out to TestWKWebView.h, so that it can be shared across
+        multiple tests. Currently, it only resides in PasteImage.mm, but I need it in PasteMixedContent.mm as well.
+
 2018-02-09  Carlos Garcia Campos  <cgar...@igalia.com>
 
         Add a way to check if a host is an IP address

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (228339 => 228340)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2018-02-09 23:41:34 UTC (rev 228340)
@@ -741,6 +741,8 @@
 		F44D064A1F3962F2001A0E29 /* EditingTestHarness.mm in Sources */ = {isa = PBXBuildFile; fileRef = F44D06491F3962E3001A0E29 /* EditingTestHarness.mm */; };
 		F4512E131F60C44600BB369E /* DataTransferItem-getAsEntry.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4512E121F60C43400BB369E /* DataTransferItem-getAsEntry.html */; };
 		F4538EF71E8473E600B5C953 /* large-red-square.png in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4538EF01E846B4100B5C953 /* large-red-square.png */; };
+		F457A9B8202D5CDC00F7E9D5 /* PasteMixedContent.mm in Sources */ = {isa = PBXBuildFile; fileRef = F457A9B6202D5CDC00F7E9D5 /* PasteMixedContent.mm */; };
+		F457A9D6202D68AF00F7E9D5 /* DataTransfer.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F457A9B3202D535300F7E9D5 /* DataTransfer.html */; };
 		F45B63FB1F197F4A009D38B9 /* image-map.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F45B63FA1F197F33009D38B9 /* image-map.html */; };
 		F45B63FE1F19D410009D38B9 /* ActionSheetTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F45B63FC1F19D410009D38B9 /* ActionSheetTests.mm */; };
 		F46849BE1EEF58E400B937FE /* UIPasteboardTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F46849BD1EEF58E400B937FE /* UIPasteboardTests.mm */; };
@@ -894,6 +896,7 @@
 				F4AB578A1F65165400DB0DA1 /* custom-draggable-div.html in Copy Resources */,
 				290F4275172A221C00939FF0 /* custom-protocol-sync-xhr.html in Copy Resources */,
 				F486B1D01F67952300F34BDD /* DataTransfer-setDragImage.html in Copy Resources */,
+				F457A9D6202D68AF00F7E9D5 /* DataTransfer.html in Copy Resources */,
 				F4512E131F60C44600BB369E /* DataTransferItem-getAsEntry.html in Copy Resources */,
 				C07E6CB213FD73930038B22B /* devicePixelRatio.html in Copy Resources */,
 				0799C34B1EBA3301003B7532 /* disableGetUserMedia.html in Copy Resources */,
@@ -1862,6 +1865,8 @@
 		F44D06491F3962E3001A0E29 /* EditingTestHarness.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = EditingTestHarness.mm; sourceTree = "<group>"; };
 		F4512E121F60C43400BB369E /* DataTransferItem-getAsEntry.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "DataTransferItem-getAsEntry.html"; sourceTree = "<group>"; };
 		F4538EF01E846B4100B5C953 /* large-red-square.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "large-red-square.png"; sourceTree = "<group>"; };
+		F457A9B3202D535300F7E9D5 /* DataTransfer.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = DataTransfer.html; sourceTree = "<group>"; };
+		F457A9B6202D5CDC00F7E9D5 /* PasteMixedContent.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PasteMixedContent.mm; sourceTree = "<group>"; };
 		F45B63FA1F197F33009D38B9 /* image-map.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "image-map.html"; sourceTree = "<group>"; };
 		F45B63FC1F19D410009D38B9 /* ActionSheetTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ActionSheetTests.mm; sourceTree = "<group>"; };
 		F46849BD1EEF58E400B937FE /* UIPasteboardTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = UIPasteboardTests.mm; sourceTree = "<group>"; };
@@ -2130,6 +2135,7 @@
 				CEBCA12E1E3A660100C73293 /* OverrideContentSecurityPolicy.mm */,
 				9BCB7C2620130600003E7C0C /* PasteHTML.mm */,
 				9BDCCD851F7D0B0700009A18 /* PasteImage.mm */,
+				F457A9B6202D5CDC00F7E9D5 /* PasteMixedContent.mm */,
 				9BDD95561F83683600D20C60 /* PasteRTFD.mm */,
 				9B2346411F943A2400DB1D23 /* PasteWebArchive.mm */,
 				3FCC4FE41EC4E8520076E37C /* PictureInPictureDelegate.mm */,
@@ -2364,6 +2370,7 @@
 				9B62630B1F8C2510007EE29B /* copy-url.html */,
 				F4AB57891F65164B00DB0DA1 /* custom-draggable-div.html */,
 				F486B1CF1F6794FF00F34BDD /* DataTransfer-setDragImage.html */,
+				F457A9B3202D535300F7E9D5 /* DataTransfer.html */,
 				F4512E121F60C43400BB369E /* DataTransferItem-getAsEntry.html */,
 				0799C34A1EBA32F4003B7532 /* disableGetUserMedia.html */,
 				63A61B8A1FAD204D00F06885 /* display-mode.html */,
@@ -3555,6 +3562,7 @@
 				7CCE7F0A1A411AE600447C4C /* PasteboardNotifications.mm in Sources */,
 				9BCB7C2820130600003E7C0C /* PasteHTML.mm in Sources */,
 				9BDCCD871F7D0B0700009A18 /* PasteImage.mm in Sources */,
+				F457A9B8202D5CDC00F7E9D5 /* PasteMixedContent.mm in Sources */,
 				9BDD95581F83683600D20C60 /* PasteRTFD.mm in Sources */,
 				9B2346421F943E2700DB1D23 /* PasteWebArchive.mm in Sources */,
 				7C83E0531D0A643A00FEBCF3 /* PendingAPIRequestURL.cpp in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DataTransfer.html (0 => 228340)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DataTransfer.html	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DataTransfer.html	2018-02-09 23:41:34 UTC (rev 228340)
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<head>
+    <style>
+        body, html {
+            width: 100%;
+            height: 100%;
+            font-family: monospace;
+        }
+
+        .heading {
+            display: block;
+            width: 100%;
+            border-top: 2px gray dashed;
+            margin-top: 20px;
+            box-sizing: border-box;
+        }
+    </style>
+    <script>
+        function setup()
+        {
+            document.body.addEventListener("paste", event => {
+                dumpAsOutput(event.clipboardData);
+                event.preventDefault();
+            });
+            document.body.addEventListener("drop", event => {
+                dumpAsOutput(event.dataTransfer);
+                event.preventDefault();
+            });
+            document.body.addEventListener("beforeinput", event => event.preventDefault());
+            document.body.focus();
+        }
+
+        function dumpAsOutput(dataTransfer)
+        {
+            document.body.contentEditable = false;
+            types.textContent = dataTransfer.types.join(", ");
+            items.textContent = Array.from(dataTransfer.items).map(item => `(${item.kind.toUpperCase()}, ${item.type})`).join(", ");
+            files.textContent = Array.from(dataTransfer.files).map(file => `('${file.name}', ${file.type})`).join(", ");
+            urlData.textContent = dataTransfer.getData("text/uri-list");
+            textData.textContent = dataTransfer.getData("text/plain");
+            let markup = dataTransfer.getData("text/html");
+            htmlData.insertAdjacentHTML("beforeend", markup);
+            rawHTMLData.textContent = markup;
+        }
+
+        function reset()
+        {
+            Array.from(document.getElementsByClassName("output")).map(element => {
+                element.innerHTML = "";
+            });
+            document.body.contentEditable = true;
+        }
+    </script>
+</head>
+<body contenteditable _onload_=setup()>
+    <h3 class="heading">Types</h3>
+    <div class="output" id="types"></div>
+
+    <h3 class="heading">Items</h3>
+    <div class="output" id="items"></div>
+
+    <h3 class="heading">Files</h3>
+    <div class="output" id="files"></div>
+
+    <h3 class="heading">text/plain</h3>
+    <div class="output" id="textData"></div>
+
+    <h3 class="heading">text/uri-list</h3>
+    <div class="output" id="urlData"></div>
+
+    <h3 class="heading">text/html</h3>
+    <div class="output" id="htmlData"></div>
+    <div class="output" id="rawHTMLData"></div>
+</body>
+</html>

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm (228339 => 228340)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm	2018-02-09 23:41:34 UTC (rev 228340)
@@ -36,10 +36,6 @@
 #include <MobileCoreServices/MobileCoreServices.h>
 #endif
 
-@interface WKWebView ()
-- (void)paste:(id)sender;
-@end
-
 #if PLATFORM(MAC)
 void writeImageDataToPasteboard(NSString *type, NSData *data)
 {

Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm (0 => 228340)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm	2018-02-09 23:41:34 UTC (rev 228340)
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include "config.h"
+
+#if PLATFORM(MAC) && WK_API_ENABLED
+
+#import "PlatformUtilities.h"
+#import "TestWKWebView.h"
+#import <WebKit/WKPreferencesRef.h>
+#import <WebKit/WKPreferencesRefPrivate.h>
+#import <wtf/RetainPtr.h>
+#import <wtf/text/WTFString.h>
+
+static NSString *imagePath()
+{
+    return [[NSBundle mainBundle] pathForResource:@"icon" ofType:@"png" inDirectory:@"TestWebKitAPI.resources"];
+}
+
+void writeTypesAndDataToPasteboard(id type, ...)
+{
+    NSMutableArray<NSString *> *types = [NSMutableArray array];
+    NSMutableArray *data = "" array];
+    va_list argumentList;
+    if (type) {
+        ASSERT([type isKindOfClass:[NSString class]]);
+        [types addObject:type];
+        va_start(argumentList, type);
+        NSUInteger index = 1;
+        id object = va_arg(argumentList, id);
+        while (object) {
+            if (index % 2)
+                [data addObject:object];
+            else {
+                ASSERT([object isKindOfClass:[NSString class]]);
+                [types addObject:object];
+            }
+            ++index;
+            object = va_arg(argumentList, id);
+        }
+        va_end(argumentList);
+    }
+
+    if (types.count != data.count) {
+        NSLog(@"Expected number of types: %tu to match number of data items: %tu", types.count, data.count);
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    [[NSPasteboard generalPasteboard] declareTypes:types owner:nil];
+    [types enumerateObjectsUsingBlock:[&] (NSString *type, NSUInteger index, BOOL *) {
+        id dataToWrite = data[index];
+        if ([dataToWrite isKindOfClass:[NSData class]])
+            [[NSPasteboard generalPasteboard] setData:dataToWrite forType:type];
+        else if ([dataToWrite isKindOfClass:[NSString class]])
+            [[NSPasteboard generalPasteboard] setString:dataToWrite forType:type];
+        else
+            [[NSPasteboard generalPasteboard] setPropertyList:dataToWrite forType:type];
+    }];
+}
+
+static RetainPtr<TestWKWebView> setUpWebView()
+{
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]);
+    WKPreferencesSetCustomPasteboardDataEnabled((WKPreferencesRef)[webView configuration].preferences, true);
+    [webView synchronouslyLoadTestPageNamed:@"DataTransfer"];
+    return webView;
+}
+
+static NSString *markupString()
+{
+    // The script tag and mouseover listener attribute in the markup string below should be omitted during
+    // sanitization while pasting.
+    return @"<script>foo()</script><strong _onmouseover_='_javascript_:void(0)'>HELLO WORLD</strong>";
+}
+
+namespace TestWebKitAPI {
+
+TEST(PasteMixedContent, ImageFileAndPlainText)
+{
+    auto webView = setUpWebView();
+    writeTypesAndDataToPasteboard(NSFilenamesPboardType, @[ imagePath() ], NSPasteboardTypeString, imagePath(), nil);
+    [webView paste:nil];
+
+    EXPECT_WK_STREQ("Files", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
+    EXPECT_WK_STREQ("(FILE, image/png)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
+    EXPECT_WK_STREQ("('icon.png', image/png)", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"rawHTMLData.textContent"]);
+}
+
+TEST(PasteMixedContent, ImageFileAndWebArchive)
+{
+    auto webView = setUpWebView();
+    NSURL *mainResourceURL = [NSURL fileURLWithPath:@"/some/nonexistent/file.html"];
+    auto mainResource = adoptNS([[WebResource alloc] initWithData:[markupString() dataUsingEncoding:NSUTF8StringEncoding] URL:mainResourceURL MIMEType:@"text/html" textEncodingName:@"utf-8" frameName:nil]);
+    auto archive = adoptNS([[WebArchive alloc] initWithMainResource:mainResource.get() subresources:nil subframeArchives:nil]);
+    writeTypesAndDataToPasteboard(NSFilenamesPboardType, @[ imagePath() ], WebArchivePboardType, [archive data], nil);
+    [webView paste:nil];
+
+    EXPECT_WK_STREQ("Files, text/html", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
+    EXPECT_WK_STREQ("(STRING, text/html), (FILE, image/png)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
+    EXPECT_WK_STREQ("('icon.png', image/png)", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
+    EXPECT_WK_STREQ("HELLO WORLD", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
+    EXPECT_FALSE([[webView stringByEvaluatingJavaScript:@"rawHTMLData.textContent"] containsString:@"script"]);
+}
+
+TEST(PasteMixedContent, ImageFileAndHTML)
+{
+    auto webView = setUpWebView();
+    writeTypesAndDataToPasteboard(NSFilenamesPboardType, @[ imagePath() ], NSPasteboardTypeHTML, markupString(), nil);
+    [webView paste:nil];
+
+    EXPECT_WK_STREQ("Files, text/html", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
+    EXPECT_WK_STREQ("(STRING, text/html), (FILE, image/png)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
+    EXPECT_WK_STREQ("('icon.png', image/png)", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
+    EXPECT_WK_STREQ("HELLO WORLD", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
+    EXPECT_FALSE([[webView stringByEvaluatingJavaScript:@"rawHTMLData.textContent"] containsString:@"script"]);
+}
+
+TEST(PasteMixedContent, ImageFileAndRTF)
+{
+    auto webView = setUpWebView();
+    auto text = adoptNS([[NSMutableAttributedString alloc] init]);
+    [text appendAttributedString:[[NSAttributedString alloc] initWithString:@"link to "]];
+    [text appendAttributedString:[[NSAttributedString alloc] initWithString:@"apple" attributes:@{ NSLinkAttributeName: [NSURL URLWithString:@"https://www.apple.com/"] }]];
+    NSData *rtfData = [text RTFFromRange:NSMakeRange(0, [text length]) documentAttributes:@{ }];
+    writeTypesAndDataToPasteboard(NSFilenamesPboardType, @[ imagePath() ], NSPasteboardTypeRTF, rtfData, nil);
+    [webView paste:nil];
+
+    EXPECT_WK_STREQ("Files, text/html", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
+    EXPECT_WK_STREQ("(STRING, text/html), (FILE, image/png)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
+    EXPECT_WK_STREQ("('icon.png', image/png)", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
+    EXPECT_WK_STREQ("link to apple", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
+    EXPECT_WK_STREQ("https://www.apple.com/", [webView stringByEvaluatingJavaScript:@"htmlData.querySelector('a').href"]);
+}
+
+TEST(PasteMixedContent, ImageFileAndURL)
+{
+    auto webView = setUpWebView();
+    writeTypesAndDataToPasteboard(NSURLPboardType, @"https://www.webkit.org/", NSFilenamesPboardType, @[ imagePath() ], nil);
+    [webView paste:nil];
+
+    EXPECT_WK_STREQ("Files, text/uri-list", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
+    EXPECT_WK_STREQ("(STRING, text/uri-list), (FILE, image/png)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
+    EXPECT_WK_STREQ("('icon.png', image/png)", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
+    EXPECT_WK_STREQ("https://www.webkit.org/", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
+}
+
+TEST(PasteMixedContent, ImageFileWithHTMLAndURL)
+{
+    auto webView = setUpWebView();
+    writeTypesAndDataToPasteboard(NSURLPboardType, @"https://www.webkit.org/", NSPasteboardTypeHTML, markupString(), NSFilenamesPboardType, @[ imagePath() ], nil);
+    [webView paste:nil];
+
+    EXPECT_WK_STREQ("Files, text/uri-list, text/html", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
+    EXPECT_WK_STREQ("(STRING, text/uri-list), (STRING, text/html), (FILE, image/png)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
+    EXPECT_WK_STREQ("('icon.png', image/png)", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
+    EXPECT_WK_STREQ("https://www.webkit.org/", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
+    EXPECT_WK_STREQ("HELLO WORLD", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
+    EXPECT_FALSE([[webView stringByEvaluatingJavaScript:@"rawHTMLData.textContent"] containsString:@"script"]);
+}
+
+} // namespace TestWebKitAPI
+
+#endif // PLATFORM(MAC) && WK_API_ENABLED

Modified: trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm (228339 => 228340)


--- trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2018-02-09 23:41:34 UTC (rev 228340)
@@ -1499,6 +1499,35 @@
 
 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110300
 
+static NSData *testIconImageData()
+{
+    return [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"icon" ofType:@"png" inDirectory:@"TestWebKitAPI.resources"]];
+}
+
+TEST(DataInteractionTests, DataTransferGetDataWhenDroppingImageAndMarkup)
+{
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+    WKPreferencesSetCustomPasteboardDataEnabled((WKPreferencesRef)[webView configuration].preferences, true);
+    [webView synchronouslyLoadTestPageNamed:@"DataTransfer"];
+
+    auto simulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
+    auto itemProvider = adoptNS([[UIItemProvider alloc] init]);
+    [itemProvider registerDataRepresentationForTypeIdentifier:(NSString *)kUTTypePNG withData:testIconImageData()];
+    NSString *markupString = @"<script>bar()</script><strong _onmousedown_=_javascript_:void(0)>HELLO WORLD</strong>";
+    [itemProvider registerDataRepresentationForTypeIdentifier:(NSString *)kUTTypeHTML withData:[markupString dataUsingEncoding:NSUTF8StringEncoding]];
+    [itemProvider setSuggestedName:@"icon"];
+    [simulator setExternalItemProviders:@[ itemProvider.get() ]];
+    [simulator runFrom:CGPointZero to:CGPointMake(50, 100)];
+
+    EXPECT_WK_STREQ("Files, text/html", [webView stringByEvaluatingJavaScript:@"types.textContent"]);
+    EXPECT_WK_STREQ("(STRING, text/html), (FILE, image/png)", [webView stringByEvaluatingJavaScript:@"items.textContent"]);
+    EXPECT_WK_STREQ("('icon.png', image/png)", [webView stringByEvaluatingJavaScript:@"files.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]);
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"textData.textContent"]);
+    EXPECT_WK_STREQ("HELLO WORLD", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]);
+    EXPECT_FALSE([[webView stringByEvaluatingJavaScript:@"rawHTMLData.textContent"] containsString:@"script"]);
+}
+
 TEST(DataInteractionTests, DataTransferGetDataWhenDroppingPlainText)
 {
     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);

Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h (228339 => 228340)


--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h	2018-02-09 23:23:02 UTC (rev 228339)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h	2018-02-09 23:41:34 UTC (rev 228340)
@@ -34,6 +34,12 @@
 @class _WKActivatedElementInfo;
 #endif
 
+@interface WKWebView (AdditionalDeclarations)
+#if PLATFORM(MAC)
+- (void)paste:(id)sender;
+#endif
+@end
+
 @interface TestMessageHandler : NSObject <WKScriptMessageHandler>
 - (void)addMessage:(NSString *)message withHandler:(dispatch_block_t)handler;
 @end
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to