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);