Title: [222956] trunk
Revision
222956
Author
[email protected]
Date
2017-10-05 20:51:35 -0700 (Thu, 05 Oct 2017)

Log Message

DataTransfer shouldn't contain text/html when performing Paste and Match Style
https://bugs.webkit.org/show_bug.cgi?id=174165
<rdar://problem/33138027>

Reviewed by Wenson Hsieh.

Source/WebCore:

When performing Paste and Match Style, only expose the plain text by creating a StaticPasteboard with plain text content.

This patch introduces ClipboardEventKind enum class to differentiate regular paste and paste and match style (internally
called as pasteAsPlainText) since both operations use "paste" event.

Tests: editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-when-custom-pasteboard-data-disabled.html
       editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text.html

* dom/DataTransfer.cpp:
(WebCore::DataTransfer::createForCopyAndPaste): Made this function take Pasteboard as an argument.
* dom/DataTransfer.h:
* editing/Editor.cpp:
(WebCore::ClipboardEventKind): Added.
(WebCore::eventNameForClipboardEvent): Added.
(WebCore::createDataTransferForClipboardEvent): Added.
(WebCore::dispatchClipboardEvent):
(WebCore::Editor::canDHTMLCut):
(WebCore::Editor::canDHTMLCopy):
(WebCore::Editor::canDHTMLPaste):
(WebCore::Editor::tryDHTMLCopy):
(WebCore::Editor::tryDHTMLCut):
(WebCore::Editor::tryDHTMLPaste): Deleted.
(WebCore::Editor::paste):
(WebCore::Editor::pasteAsPlainText):
* platform/ios/PasteboardIOS.mm:
(WebCore::Pasteboard::addHTMLClipboardTypesForCocoaType): Add "text/html" when public.html UTI is in the pasteboard
even when the custom pasteboard data is disabled. We continue to add public.html in the case some app dependent on
seeing "public.html" in dataTransfer.types.

LayoutTests:

Added regression tests for pasting as plain text.

* editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-expected.txt: Added.
* editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-when-custom-pasteboard-data-disabled-expected.txt: Added.
* editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-when-custom-pasteboard-data-disabled.html: Added.
* editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (222955 => 222956)


--- trunk/LayoutTests/ChangeLog	2017-10-06 03:06:35 UTC (rev 222955)
+++ trunk/LayoutTests/ChangeLog	2017-10-06 03:51:35 UTC (rev 222956)
@@ -1,3 +1,18 @@
+2017-10-05  Ryosuke Niwa  <[email protected]>
+
+        DataTransfer shouldn't contain text/html when performing Paste and Match Style
+        https://bugs.webkit.org/show_bug.cgi?id=174165
+        <rdar://problem/33138027>
+
+        Reviewed by Wenson Hsieh.
+
+        Added regression tests for pasting as plain text.
+
+        * editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-expected.txt: Added.
+        * editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-when-custom-pasteboard-data-disabled-expected.txt: Added.
+        * editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-when-custom-pasteboard-data-disabled.html: Added.
+        * editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text.html: Added.
+
 2017-10-05  Myles C. Maxfield  <[email protected]>
 
         Add "display" to FontFace _javascript_ object

Added: trunk/LayoutTests/editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-expected.txt (0 => 222956)


--- trunk/LayoutTests/editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-expected.txt	2017-10-06 03:51:35 UTC (rev 222956)
@@ -0,0 +1,15 @@
+Tests that pasting as plain text only exposes "text/plain" in the clipboard. To manually test, press "Copy" below and paste (Command+V on macOS and Control+V elsewhere).
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS JSON.stringify(event.clipboardData.types) is "[\"text/plain\"]"
+PASS event.clipboardData.getData("text/plain") is "hello, world\nWebKit"
+PASS event.clipboardData.getData("text/html") is ""
+PASS event.clipboardData.items.length is 1
+PASS item = event.clipboardData.items[0]; item.kind is "string"
+PASS item.type is "text/plain"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-when-custom-pasteboard-data-disabled-expected.txt (0 => 222956)


--- trunk/LayoutTests/editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-when-custom-pasteboard-data-disabled-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-when-custom-pasteboard-data-disabled-expected.txt	2017-10-06 03:51:35 UTC (rev 222956)
@@ -0,0 +1,16 @@
+Tests that pasting as plain text only exposes "text/html" as well as "text/plain" in the clipboard when custom data support is turned off.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS event.clipboardData.types.includes("text/plain") is true
+PASS event.clipboardData.types.includes("text/html") is true
+PASS event.clipboardData.getData("text/plain") is "hello, world\nWebKit"
+PASS event.clipboardData.getData("text/html") is not ""
+PASS items = Array.from(event.clipboardData.items); items.length >= 2 is true
+PASS items.some((item) => item.type == "text/plain") is true
+PASS items.some((item) => item.type == "text/html") is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-when-custom-pasteboard-data-disabled.html (0 => 222956)


--- trunk/LayoutTests/editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-when-custom-pasteboard-data-disabled.html	                        (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-when-custom-pasteboard-data-disabled.html	2017-10-06 03:51:35 UTC (rev 222956)
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<div id="container">
+<div id="source" contenteditable="true">hello, <b>world</b><br>WebKit</div>
+<div id="destination" _onpaste_="check(event)" contenteditable="true"></div>
+</div>
+</body>
+<script>
+description('Tests that pasting as plain text only exposes "text/html" as well as "text/plain" in the clipboard when custom data support is turned off.');
+
+if (!window.internals || !window.internals.settings)
+    testFailed('This test requires internals.settings');
+else {
+    internals.settings.setCustomPasteboardDataEnabled(false);
+
+    document.getElementById("source").focus();
+    document.execCommand("SelectAll");
+    document.execCommand("Copy");
+
+    document.getElementById("destination").focus();
+    document.execCommand("Paste");
+    document.getElementById('container').remove();
+}
+
+function check(event)
+{
+    shouldBeTrue('event.clipboardData.types.includes("text/plain")');
+    shouldBeTrue('event.clipboardData.types.includes("text/html")');
+    shouldBeEqualToString('event.clipboardData.getData("text/plain")', 'hello, world\nWebKit');
+    shouldNotBeEqualToString('event.clipboardData.getData("text/html")', '');
+    shouldBeTrue('items = Array.from(event.clipboardData.items); items.length >= 2');
+    shouldBeTrue('items.some((item) => item.type == "text/plain")');
+    shouldBeTrue('items.some((item) => item.type == "text/html")');
+}
+
+</script>
+<script src=""
+</html>

Added: trunk/LayoutTests/editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text.html (0 => 222956)


--- trunk/LayoutTests/editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text.html	                        (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text.html	2017-10-06 03:51:35 UTC (rev 222956)
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<div id="container">
+<button _onclick_="runTest()">Copy</button>
+<div id="source" contenteditable="true">hello, <b>world</b><br>WebKit</div>
+<div id="destination" _onpaste_="check(event)" contenteditable="true" style="width: 500px; height: 100px; border: solid red 1px"></div>
+</div>
+</body>
+<script>
+description('Tests that pasting as plain text only exposes "text/plain" in the clipboard. To manually test, press "Copy" below and paste (Command+V on macOS and Control+V elsewhere).');
+jsTestIsAsync = true;
+
+function runTest()
+{
+    if (window.internals)
+        internals.settings.setCustomPasteboardDataEnabled(true);
+
+    document.getElementById("source").focus();
+    document.execCommand("SelectAll");
+    document.execCommand("Copy");
+
+    document.getElementById("destination").focus();
+    if (window.testRunner)
+        document.execCommand("PasteAndMatchStyle");
+}
+
+function check(event)
+{
+    shouldBeEqualToString('JSON.stringify(event.clipboardData.types)', '["text/plain"]');
+    shouldBeEqualToString('event.clipboardData.getData("text/plain")', 'hello, world\nWebKit');
+    shouldBeEqualToString('event.clipboardData.getData("text/html")', '');
+    shouldBe('event.clipboardData.items.length', '1');
+    shouldBeEqualToString('item = event.clipboardData.items[0]; item.kind', 'string');
+    shouldBeEqualToString('item.type', 'text/plain');
+
+    document.getElementById('container').remove();
+
+    finishJSTest();
+}
+
+if (window.testRunner)
+    runTest();
+
+</script>
+<script src=""
+</html>

Modified: trunk/Source/WebCore/ChangeLog (222955 => 222956)


--- trunk/Source/WebCore/ChangeLog	2017-10-06 03:06:35 UTC (rev 222955)
+++ trunk/Source/WebCore/ChangeLog	2017-10-06 03:51:35 UTC (rev 222956)
@@ -1,3 +1,40 @@
+2017-10-05  Ryosuke Niwa  <[email protected]>
+
+        DataTransfer shouldn't contain text/html when performing Paste and Match Style
+        https://bugs.webkit.org/show_bug.cgi?id=174165
+        <rdar://problem/33138027>
+
+        Reviewed by Wenson Hsieh.
+
+        When performing Paste and Match Style, only expose the plain text by creating a StaticPasteboard with plain text content.
+
+        This patch introduces ClipboardEventKind enum class to differentiate regular paste and paste and match style (internally
+        called as pasteAsPlainText) since both operations use "paste" event.
+
+        Tests: editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text-when-custom-pasteboard-data-disabled.html
+               editing/pasteboard/data-transfer-get-data-on-paste-as-plain-text.html
+
+        * dom/DataTransfer.cpp:
+        (WebCore::DataTransfer::createForCopyAndPaste): Made this function take Pasteboard as an argument.
+        * dom/DataTransfer.h:
+        * editing/Editor.cpp:
+        (WebCore::ClipboardEventKind): Added.
+        (WebCore::eventNameForClipboardEvent): Added.
+        (WebCore::createDataTransferForClipboardEvent): Added.
+        (WebCore::dispatchClipboardEvent):
+        (WebCore::Editor::canDHTMLCut):
+        (WebCore::Editor::canDHTMLCopy):
+        (WebCore::Editor::canDHTMLPaste):
+        (WebCore::Editor::tryDHTMLCopy):
+        (WebCore::Editor::tryDHTMLCut):
+        (WebCore::Editor::tryDHTMLPaste): Deleted.
+        (WebCore::Editor::paste):
+        (WebCore::Editor::pasteAsPlainText):
+        * platform/ios/PasteboardIOS.mm:
+        (WebCore::Pasteboard::addHTMLClipboardTypesForCocoaType): Add "text/html" when public.html UTI is in the pasteboard
+        even when the custom pasteboard data is disabled. We continue to add public.html in the case some app dependent on
+        seeing "public.html" in dataTransfer.types.
+
 2017-10-05  Zalan Bujtas  <[email protected]>
 
         RenderTable should not hold section raw pointers

Modified: trunk/Source/WebCore/dom/DataTransfer.cpp (222955 => 222956)


--- trunk/Source/WebCore/dom/DataTransfer.cpp	2017-10-06 03:06:35 UTC (rev 222955)
+++ trunk/Source/WebCore/dom/DataTransfer.cpp	2017-10-06 03:51:35 UTC (rev 222956)
@@ -76,9 +76,9 @@
 #endif
 }
 
-Ref<DataTransfer> DataTransfer::createForCopyAndPaste(StoreMode mode)
+Ref<DataTransfer> DataTransfer::createForCopyAndPaste(StoreMode storeMode, std::unique_ptr<Pasteboard>&& pasteboard)
 {
-    return adoptRef(*new DataTransfer(mode, mode == StoreMode::ReadWrite ? std::make_unique<StaticPasteboard>() : Pasteboard::createForCopyAndPaste()));
+    return adoptRef(*new DataTransfer(storeMode, WTFMove(pasteboard)));
 }
 
 DataTransfer::~DataTransfer()

Modified: trunk/Source/WebCore/dom/DataTransfer.h (222955 => 222956)


--- trunk/Source/WebCore/dom/DataTransfer.h	2017-10-06 03:06:35 UTC (rev 222955)
+++ trunk/Source/WebCore/dom/DataTransfer.h	2017-10-06 03:51:35 UTC (rev 222956)
@@ -44,7 +44,7 @@
     // https://html.spec.whatwg.org/multipage/dnd.html#drag-data-store-mode
     enum class StoreMode { Invalid, ReadWrite, Readonly, Protected };
 
-    static Ref<DataTransfer> createForCopyAndPaste(StoreMode);
+    static Ref<DataTransfer> createForCopyAndPaste(StoreMode, std::unique_ptr<Pasteboard>&&);
     static Ref<DataTransfer> createForInputEvent(const String& plainText, const String& htmlText);
 
     WEBCORE_EXPORT ~DataTransfer();

Modified: trunk/Source/WebCore/editing/Editor.cpp (222955 => 222956)


--- trunk/Source/WebCore/editing/Editor.cpp	2017-10-06 03:06:35 UTC (rev 222955)
+++ trunk/Source/WebCore/editing/Editor.cpp	2017-10-06 03:51:35 UTC (rev 222956)
@@ -314,36 +314,83 @@
     return m_frame.selection().selection().isContentRichlyEditable();
 }
 
+enum class ClipboardEventKind {
+    Copy,
+    Cut,
+    Paste,
+    PasteAsPlainText,
+    BeforeCopy,
+    BeforeCut,
+    BeforePaste,
+};
+
+static AtomicString eventNameForClipboardEvent(ClipboardEventKind kind)
+{
+    switch (kind) {
+    case ClipboardEventKind::Copy:
+        return eventNames().copyEvent;
+    case ClipboardEventKind::Cut:
+        return eventNames().cutEvent;
+    case ClipboardEventKind::Paste:
+    case ClipboardEventKind::PasteAsPlainText:
+        return eventNames().pasteEvent;
+    case ClipboardEventKind::BeforeCopy:
+        return eventNames().beforecopyEvent;
+    case ClipboardEventKind::BeforeCut:
+        return eventNames().beforecutEvent;
+    case ClipboardEventKind::BeforePaste:
+        return eventNames().beforepasteEvent;
+    }
+    ASSERT_NOT_REACHED();
+    return { };
+}
+
+static Ref<DataTransfer> createDataTransferForClipboardEvent(ClipboardEventKind kind)
+{
+    switch (kind) {
+    case ClipboardEventKind::Copy:
+    case ClipboardEventKind::Cut:
+        return DataTransfer::createForCopyAndPaste(DataTransfer::StoreMode::ReadWrite, std::make_unique<StaticPasteboard>());
+    case ClipboardEventKind::PasteAsPlainText:
+        if (Settings::customPasteboardDataEnabled()) {
+            auto plainTextType = ASCIILiteral("text/plain");
+            auto plainText = Pasteboard::createForCopyAndPaste()->readString(plainTextType);
+            auto pasteboard = std::make_unique<StaticPasteboard>();
+            pasteboard->writeString(plainTextType, plainText);
+            return DataTransfer::createForCopyAndPaste(DataTransfer::StoreMode::Readonly, WTFMove(pasteboard));
+        }
+        FALLTHROUGH;
+    case ClipboardEventKind::Paste:
+        return DataTransfer::createForCopyAndPaste(DataTransfer::StoreMode::Readonly, Pasteboard::createForCopyAndPaste());
+    case ClipboardEventKind::BeforeCopy:
+    case ClipboardEventKind::BeforeCut:
+    case ClipboardEventKind::BeforePaste:
+        return DataTransfer::createForCopyAndPaste(DataTransfer::StoreMode::Invalid, std::make_unique<StaticPasteboard>());
+    }
+    ASSERT_NOT_REACHED();
+    return DataTransfer::createForCopyAndPaste(DataTransfer::StoreMode::Invalid, std::make_unique<StaticPasteboard>());
+}
+
 // Returns whether caller should continue with "the default processing", which is the same as
 // the event handler NOT setting the return value to false
 // https://w3c.github.io/clipboard-apis/#fire-a-clipboard-event
-static bool dispatchClipboardEvent(RefPtr<Element>&& target, const AtomicString& eventType)
+static bool dispatchClipboardEvent(RefPtr<Element>&& target, ClipboardEventKind kind)
 {
     // FIXME: Move the target selection code here.
     if (!target)
         return true;
 
-    DataTransfer::StoreMode storeMode;
-    if (eventType == eventNames().pasteEvent)
-        storeMode = DataTransfer::StoreMode::Readonly;
-    else if (eventType == eventNames().copyEvent || eventType == eventNames().cutEvent)
-        storeMode = DataTransfer::StoreMode::ReadWrite;
-    else {
-        ASSERT(eventType == eventNames().beforecutEvent || eventType == eventNames().beforecopyEvent || eventType == eventNames().beforepasteEvent);
-        storeMode = DataTransfer::StoreMode::Invalid;
-    }
+    auto dataTransfer = createDataTransferForClipboardEvent(kind);
 
-    auto dataTransfer = DataTransfer::createForCopyAndPaste(storeMode);
-
     ClipboardEvent::Init init;
     init.bubbles = true;
     init.cancelable = true;
     init.clipboardData = dataTransfer.ptr();
-    auto event = ClipboardEvent::create(eventType, init, Event::IsTrusted::Yes);
+    auto event = ClipboardEvent::create(eventNameForClipboardEvent(kind), init, Event::IsTrusted::Yes);
 
     target->dispatchEvent(event);
     bool noDefaultProcessing = event->defaultPrevented();
-    if (noDefaultProcessing && storeMode == DataTransfer::StoreMode::ReadWrite) {
+    if (noDefaultProcessing && (kind == ClipboardEventKind::Copy || kind == ClipboardEventKind::Cut)) {
         auto pasteboard = Pasteboard::createForCopyAndPaste();
         pasteboard->clear();
         downcast<StaticPasteboard>(dataTransfer->pasteboard()).commitToPasteboard(*pasteboard);
@@ -364,7 +411,7 @@
     if (m_frame.selection().selection().isInPasswordField())
         return false;
 
-    return !dispatchClipboardEvent(findEventTargetFromSelection(), eventNames().beforecutEvent);
+    return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::BeforeCut);
 }
 
 bool Editor::canDHTMLCopy()
@@ -371,12 +418,12 @@
 {
     if (m_frame.selection().selection().isInPasswordField())
         return false;
-    return !dispatchClipboardEvent(findEventTargetFromSelection(), eventNames().beforecopyEvent);
+    return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::BeforeCopy);
 }
 
 bool Editor::canDHTMLPaste()
 {
-    return !dispatchClipboardEvent(findEventTargetFromSelection(), eventNames().beforepasteEvent);
+    return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::BeforePaste);
 }
 
 bool Editor::canCut() const
@@ -644,7 +691,7 @@
     if (m_frame.selection().selection().isInPasswordField())
         return false;
 
-    return !dispatchClipboardEvent(findEventTargetFromSelection(), eventNames().copyEvent);
+    return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::Copy);
 }
 
 bool Editor::tryDHTMLCut()
@@ -652,14 +699,9 @@
     if (m_frame.selection().selection().isInPasswordField())
         return false;
     
-    return !dispatchClipboardEvent(findEventTargetFromSelection(), eventNames().cutEvent);
+    return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::Cut);
 }
 
-bool Editor::tryDHTMLPaste()
-{
-    return !dispatchClipboardEvent(findEventTargetFromSelection(), eventNames().pasteEvent);
-}
-
 bool Editor::shouldInsertText(const String& text, Range* range, EditorInsertAction action) const
 {
     if (m_frame.mainFrame().loader().shouldSuppressKeyboardInput() && action == EditorInsertAction::Typed)
@@ -1336,7 +1378,7 @@
 
 void Editor::paste(Pasteboard& pasteboard)
 {
-    if (tryDHTMLPaste())
+    if (!dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::Paste))
         return; // DHTML did the whole operation
     if (!canPaste())
         return;
@@ -1350,7 +1392,7 @@
 
 void Editor::pasteAsPlainText()
 {
-    if (tryDHTMLPaste())
+    if (!dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::PasteAsPlainText))
         return;
     if (!canPaste())
         return;

Modified: trunk/Source/WebCore/editing/Editor.h (222955 => 222956)


--- trunk/Source/WebCore/editing/Editor.h	2017-10-06 03:06:35 UTC (rev 222955)
+++ trunk/Source/WebCore/editing/Editor.h	2017-10-06 03:51:35 UTC (rev 222956)
@@ -146,7 +146,6 @@
     WEBCORE_EXPORT bool canDHTMLPaste();
     bool tryDHTMLCopy();
     bool tryDHTMLCut();
-    WEBCORE_EXPORT bool tryDHTMLPaste();
 
     WEBCORE_EXPORT bool canCut() const;
     WEBCORE_EXPORT bool canCopy() const;

Modified: trunk/Source/WebCore/platform/ios/PasteboardIOS.mm (222955 => 222956)


--- trunk/Source/WebCore/platform/ios/PasteboardIOS.mm	2017-10-06 03:06:35 UTC (rev 222955)
+++ trunk/Source/WebCore/platform/ios/PasteboardIOS.mm	2017-10-06 03:51:35 UTC (rev 222956)
@@ -358,6 +358,10 @@
         resultTypes.add(ASCIILiteral("text/uri-list"));
         return;
     }
+    if ([cocoaType isEqualToString:(NSString *)kUTTypeHTML]) {
+        resultTypes.add(ASCIILiteral("text/html"));
+        // We don't return here for App compatibility.
+    }
     if (Pasteboard::shouldTreatCocoaTypeAsFile(cocoaType))
         return;
     String utiType = utiTypeFromCocoaType(cocoaType);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to