WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
WIP2
bug-178060-20171007225923.patch (text/plain), 99.06 KB, created by
Ryosuke Niwa
on 2017-10-07 22:59:25 PDT
(
hide
)
Description:
WIP2
Filename:
MIME Type:
Creator:
Ryosuke Niwa
Created:
2017-10-07 22:59:25 PDT
Size:
99.06 KB
patch
obsolete
>Subversion Revision: 223027 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 04a6c854441ad1198b132888def58dd27ef23070..3629221fef55cfcee14be355c5d77b4a86a381de 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,102 @@ >+2017-10-07 Ryosuke Niwa <rniwa@webkit.org> >+ >+ Sanitize URL in pasteboard for other applications and cross origin content >+ https://bugs.webkit.org/show_bug.cgi?id=178060 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Tests: editing/pasteboard/data-transfer-get-data-on-copying-pasting-malformed-url-in-same-document.html >+ editing/pasteboard/data-transfer-set-data-ignore-copied-walformed-url-in-null-origin.html >+ editing/pasteboard/data-transfer-set-data-sanitlize-url-when-copying-in-null-origin.html >+ editing/pasteboard/data-transfer-set-data-sanitlize-url-when-dragging-in-null-origin.html >+ http/tests/security/clipboard/copy-paste-url-across-origin-sanitizes-url.html >+ >+ * dom/DataTransfer.cpp: >+ (WebCore::originForDocument): >+ (WebCore::DataTransfer::createForCopyAndPaste): >+ (WebCore::DataTransfer::getData const): >+ (WebCore::DataTransfer::setDataFromItemList): >+ (WebCore::DataTransfer::types const): >+ (WebCore::DataTransfer::commitToPasteboard): >+ (WebCore::DataTransfer::createForDragStartEvent): >+ (WebCore::DataTransfer::createForDrop): >+ (WebCore::DataTransfer::createForUpdatingDropTarget): >+ (WebCore::DataTransfer::moveDragState): >+ * dom/DataTransfer.h: >+ * dom/Document.cpp: >+ (WebCore::Document::uniqueIdentifier): >+ * dom/Document.h: >+ * editing/Editor.cpp: >+ (WebCore::createDataTransferForClipboardEvent): >+ (WebCore::dispatchClipboardEvent): >+ * page/DragController.cpp: >+ (WebCore::DragController::dispatchTextInputEventFor): >+ * page/EventHandler.cpp: >+ (WebCore::EventHandler::performDragAndDrop): >+ (WebCore::EventHandler::handleDrag): >+ * platform/Pasteboard.h: >+ * platform/PasteboardStrategy.h: >+ * platform/PlatformPasteboard.h: >+ * platform/StaticPasteboard.cpp: >+ (WebCore::StaticPasteboard::takeCustomData): >+ * platform/StaticPasteboard.h: >+ * platform/cocoa/PasteboardCocoa.mm: >+ (WebCore::Pasteboard::typesSafeForBindings): >+ (WebCore::Pasteboard::readStringInCustomData): >+ (WebCore::Pasteboard::readOrigin): >+ (WebCore::Pasteboard::readCustomData): >+ * platform/gtk/PlatformPasteboardGtk.cpp: >+ (WebCore::PlatformPasteboard::typesSafeForDOMToReadAndWrite const): >+ * platform/ios/PlatformPasteboardIOS.mm: >+ (WebCore::PlatformPasteboard::typesSafeForDOMToReadAndWrite const): >+ (WebCore::PlatformPasteboard::write): >+ * platform/mac/PlatformPasteboardMac.mm: >+ (WebCore::PlatformPasteboard::typesSafeForDOMToReadAndWrite const): >+ * platform/wpe/PlatformPasteboardWPE.cpp: >+ (WebCore::PlatformPasteboard::typesSafeForDOMToReadAndWrite const): >+ >+2017-10-07 Ryosuke Niwa <rniwa@webkit.org> >+ >+ dragenter and dragleave shouldn't use the same data transfer object >+ https://bugs.webkit.org/show_bug.cgi?id=178056 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This patch fixes the bug that we were using a single DataTransfer to fire dragleave and dragenter events >+ when the drag target moves from one element to another. >+ >+ It alos refactors DragController and EventHandler code so that the construction of DataTransfer object >+ happens in EventHandler instead of DragController, and extracts createForUpdatingDropTarget out of >+ createForDrop to have a better encapsulation over the data store mode. >+ >+ drag related functions in EventHandler now takes std::unique_ptr<Pasteboard>&&, drag operation mask set >+ by the drag source, and a boolean indicating whether this drag & drop is for files or not. updateDragAndDrop >+ takes a closure which makes a pasteboard because it has to create two instances of DataTransfer one for >+ dragleave event and another one for dragenter event in some cases. >+ >+ Test: editing/pasteboard/data-transfer-is-unique-for-dragenter-and-dragleave.html >+ >+ * dom/DataTransfer.cpp: >+ (WebCore::DataTransfer::createForDrop): Now takes Pasteboard instead of DragData. >+ (WebCore::DataTransfer::createForUpdatingDropTarget): Extracted out of createForDrop. Moved the code to >+ use Readonly mode in dashboad here from createDataTransferToUpdateDrag in DragController.cpp. >+ * dom/DataTransfer.h: >+ * page/DragController.cpp: >+ (WebCore::createDataTransferToUpdateDrag): Deleted. >+ (WebCore::DragController::dragExited): >+ (WebCore::DragController::performDragOperation): >+ (WebCore::DragController::tryDHTMLDrag): >+ * page/EventHandler.cpp: >+ (WebCore::EventHandler::dispatchDragEvent): Made this fucntion take DataTransfer& instead of DataTransfer*. >+ (WebCore::findDropZone): Ditto. >+ (WebCore::EventHandler::dispatchDragEnterOrDragOverEvent): Added. >+ (WebCore::EventHandler::updateDragAndDrop): >+ (WebCore::EventHandler::cancelDragAndDrop): >+ (WebCore::EventHandler::performDragAndDrop): >+ (WebCore::EventHandler::dispatchDragSrcEvent): >+ (WebCore::EventHandler::dispatchDragStartEventOnSourceElement): >+ * page/EventHandler.h: >+ > 2017-10-07 Darin Adler <darin@apple.com> > > Update Document.createEvent for recent DOM specification changes >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 33910f0f665373d5ee4e8f09c4f40df52589d440..a3dce87a7bba49a7f29344900bc377936a41a63d 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,20 @@ >+2017-10-07 Ryosuke Niwa <rniwa@webkit.org> >+ >+ Sanitize URL in pasteboard for other applications and cross origin content >+ https://bugs.webkit.org/show_bug.cgi?id=178060 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * UIProcess/Cocoa/WebPasteboardProxyCocoa.mm: >+ (WebKit::WebPasteboardProxy::typesSafeForDOMToReadAndWrite): >+ * UIProcess/WebPasteboardProxy.cpp: >+ (WebKit::WebPasteboardProxy::typesSafeForDOMToReadAndWrite): >+ * UIProcess/WebPasteboardProxy.h: >+ * UIProcess/WebPasteboardProxy.messages.in: >+ * WebProcess/WebCoreSupport/WebPlatformStrategies.cpp: >+ (WebKit::WebPlatformStrategies::typesSafeForDOMToReadAndWrite): >+ * WebProcess/WebCoreSupport/WebPlatformStrategies.h: >+ > 2017-10-06 Wenson Hsieh <wenson_hsieh@apple.com> > > [iOS WK2] API tests added in r222991 are failing in iOS 11 test runners >diff --git a/Source/WebKitLegacy/mac/ChangeLog b/Source/WebKitLegacy/mac/ChangeLog >index 7a708c5d23db665f868bf2eeedd2c106f1fb473f..3ef665fd8a7dc7fa92df300714df409bcb8b5f9e 100644 >--- a/Source/WebKitLegacy/mac/ChangeLog >+++ b/Source/WebKitLegacy/mac/ChangeLog >@@ -1,3 +1,14 @@ >+2017-10-07 Ryosuke Niwa <rniwa@webkit.org> >+ >+ Sanitize URL in pasteboard for other applications and cross origin content >+ https://bugs.webkit.org/show_bug.cgi?id=178060 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * WebCoreSupport/WebPlatformStrategies.h: >+ * WebCoreSupport/WebPlatformStrategies.mm: >+ (WebPlatformStrategies::typesSafeForDOMToReadAndWrite): >+ > 2017-10-06 Wenson Hsieh <wenson_hsieh@apple.com> > > [iOS] Tweak support for classifying form controls (followup to r222487) >diff --git a/Source/WebCore/dom/DataTransfer.cpp b/Source/WebCore/dom/DataTransfer.cpp >index 59d74336416591336c059be0b97a3056b58cb890..4dbba84a756110c888e80b76fa0c26a1c21733c4 100644 >--- a/Source/WebCore/dom/DataTransfer.cpp >+++ b/Source/WebCore/dom/DataTransfer.cpp >@@ -40,6 +40,7 @@ > #include "Pasteboard.h" > #include "Settings.h" > #include "StaticPasteboard.h" >+#include "URLParser.h" > #include "WebCorePasteboardFileReader.h" > > namespace WebCore { >@@ -76,9 +77,19 @@ DataTransfer::DataTransfer(StoreMode mode, std::unique_ptr<Pasteboard> pasteboar > #endif > } > >-Ref<DataTransfer> DataTransfer::createForCopyAndPaste(StoreMode storeMode, std::unique_ptr<Pasteboard>&& pasteboard) >+static String originForDocument(Document& document) > { >- return adoptRef(*new DataTransfer(storeMode, WTFMove(pasteboard))); >+ auto origin = document.securityOrigin().toString(); >+ if (origin == "null") >+ return document.uniqueIdentifier(); >+ return origin; >+} >+ >+Ref<DataTransfer> DataTransfer::createForCopyAndPaste(Document& document, StoreMode storeMode, std::unique_ptr<Pasteboard>&& pasteboard) >+{ >+ auto dataTransfer = adoptRef(*new DataTransfer(storeMode, WTFMove(pasteboard))); >+ dataTransfer->m_origin = originForDocument(document); >+ return dataTransfer; > } > > DataTransfer::~DataTransfer() >@@ -143,9 +154,28 @@ String DataTransfer::getData(const String& type) const > return { }; > > auto normalizedType = normalizeType(type); >- if (Settings::customPasteboardDataEnabled() && !Pasteboard::isSafeTypeForDOMToReadAndWrite(normalizedType)) >- return m_pasteboard->readStringInCustomData(normalizedType); >- return m_pasteboard->readString(normalizedType); >+ if (!Settings::customPasteboardDataEnabled()) >+ return m_pasteboard->readString(normalizedType); >+ >+ bool isSameOrigin = false; >+ if (is<StaticPasteboard>(*m_pasteboard)) >+ isSameOrigin = true; >+ else if (!m_origin.isNull()) { >+ String originOfPasteboard = m_pasteboard->readOrigin(); >+// fprintf(stderr, "getData origin=%s\n", originOfPasteboard.ascii().data()); >+ isSameOrigin = m_origin == originOfPasteboard; >+ } >+ >+ if (!isSameOrigin) { >+ if (!Pasteboard::isSafeTypeForDOMToReadAndWrite(normalizedType)) >+ return { }; >+ return m_pasteboard->readString(normalizedType); >+ } >+ >+ String value = m_pasteboard->readStringInCustomData(normalizedType); >+ if (value.isNull() && Pasteboard::isSafeTypeForDOMToReadAndWrite(normalizedType)) >+ value = m_pasteboard->readString(normalizedType); >+ return value; > } > > void DataTransfer::setData(const String& type, const String& data) >@@ -166,11 +196,25 @@ void DataTransfer::setDataFromItemList(const String& type, const String& data) > { > ASSERT(canWriteData()); > RELEASE_ASSERT(is<StaticPasteboard>(*m_pasteboard)); >+ >+ if (!Settings::customPasteboardDataEnabled()) { >+ m_pasteboard->writeString(type, data); >+ return; >+ } >+ >+ String sanitizedData; >+ if (type == "text/uri-list") { >+ auto url = URLParser(data).result(); >+ if (url.isValid() && !url.isEmpty()) >+ sanitizedData = url.string(); >+ } else if (type == "text/plain") >+ sanitizedData = data; // Nothing to sanitize. > >- if (Settings::customPasteboardDataEnabled() && !Pasteboard::isSafeTypeForDOMToReadAndWrite(type)) >+ if (sanitizedData != data) > downcast<StaticPasteboard>(*m_pasteboard).writeStringInCustomData(type, data); >- else >- m_pasteboard->writeString(type, data); >+ >+ if (Pasteboard::isSafeTypeForDOMToReadAndWrite(type) && !sanitizedData.isNull()) >+ m_pasteboard->writeString(type, sanitizedData); > } > > void DataTransfer::updateFileList() >@@ -215,11 +259,11 @@ Vector<String> DataTransfer::types() const > return { ASCIILiteral("Files") }; > > if (m_pasteboard->containsFiles()) { >- ASSERT(!m_pasteboard->typesSafeForBindings().contains("Files")); >+ ASSERT(!m_pasteboard->typesSafeForBindings(m_origin).contains("Files")); > return { ASCIILiteral("Files") }; > } > >- auto types = m_pasteboard->typesSafeForBindings(); >+ auto types = m_pasteboard->typesSafeForBindings(m_origin); > ASSERT(!types.contains("Files")); > return types; > } >@@ -301,6 +345,23 @@ Ref<DataTransfer> DataTransfer::createForInputEvent(const String& plainText, con > return adoptRef(*new DataTransfer(StoreMode::Readonly, WTFMove(pasteboard), Type::InputEvent)); > } > >+void DataTransfer::commitToPasteboard(Pasteboard& nativePasteboard) >+{ >+ ASSERT(is<StaticPasteboard>(*m_pasteboard) && !is<StaticPasteboard>(nativePasteboard)); >+ PasteboardCustomData customData = downcast<StaticPasteboard>(*m_pasteboard).takeCustomData(); >+ if (Settings::customPasteboardDataEnabled()) { >+ customData.origin = m_origin; >+// fprintf(stderr, "commitToPasteboard origin=%s\n", customData.origin.ascii().data()); >+ nativePasteboard.writeCustomData(customData); >+ return; >+ } >+ >+ for (auto& entry : customData.platformData) >+ nativePasteboard.writeString(entry.key, entry.value); >+ for (auto& entry : customData.sameOriginCustomData) >+ nativePasteboard.writeString(entry.key, entry.value); >+} >+ > #if !ENABLE(DRAG_SUPPORT) > > String DataTransfer::dropEffect() const >@@ -332,15 +393,34 @@ Ref<DataTransfer> DataTransfer::createForDrag() > return adoptRef(*new DataTransfer(StoreMode::ReadWrite, Pasteboard::createForDragAndDrop(), Type::DragAndDropData)); > } > >-Ref<DataTransfer> DataTransfer::createForDragStartEvent() >+Ref<DataTransfer> DataTransfer::createForDragStartEvent(Document& document) >+{ >+ auto dataTransfer = adoptRef(*new DataTransfer(StoreMode::ReadWrite, std::make_unique<StaticPasteboard>(), Type::DragAndDropData)); >+ dataTransfer->m_origin = originForDocument(document); >+ return dataTransfer; >+} >+ >+Ref<DataTransfer> DataTransfer::createForDrop(Document& document, std::unique_ptr<Pasteboard>&& pasteboard, DragOperation sourceOperation, bool draggingFiles) > { >- return adoptRef(*new DataTransfer(StoreMode::ReadWrite, std::make_unique<StaticPasteboard>(), Type::DragAndDropData)); >+ auto dataTransfer = adoptRef(*new DataTransfer(DataTransfer::StoreMode::Readonly, WTFMove(pasteboard), draggingFiles ? Type::DragAndDropFiles : Type::DragAndDropData)); >+ dataTransfer->setSourceOperation(sourceOperation); >+ dataTransfer->m_origin = originForDocument(document); >+ return dataTransfer; > } > >-Ref<DataTransfer> DataTransfer::createForDrop(StoreMode accessMode, const DragData& dragData) >+Ref<DataTransfer> DataTransfer::createForUpdatingDropTarget(Document& document, std::unique_ptr<Pasteboard>&& pasteboard, DragOperation sourceOperation, bool draggingFiles) > { >- auto type = dragData.containsFiles() ? Type::DragAndDropFiles : Type::DragAndDropData; >- return adoptRef(*new DataTransfer(accessMode, Pasteboard::createForDragAndDrop(dragData), type)); >+ auto mode = DataTransfer::StoreMode::Protected; >+#if ENABLE(DASHBOARD_SUPPORT) >+ if (document.settings().usesDashboardBackwardCompatibilityMode() && document.securityOrigin().isLocal()) >+ mode = DataTransfer::StoreMode::Readonly; >+#else >+ UNUSED_PARAM(document); >+#endif >+ auto dataTransfer = adoptRef(*new DataTransfer(mode, WTFMove(pasteboard), draggingFiles ? Type::DragAndDropFiles : Type::DragAndDropData)); >+ dataTransfer->setSourceOperation(sourceOperation); >+ dataTransfer->m_origin = originForDocument(document); >+ return dataTransfer; > } > > void DataTransfer::setDragImage(Element* element, int x, int y) >@@ -553,7 +633,7 @@ void DataTransfer::moveDragState(Ref<DataTransfer>&& other) > // After pushing the static pasteboard's contents to the platform, the pasteboard should only > // contain data that was in the static pasteboard. > m_pasteboard->clear(); >- downcast<StaticPasteboard>(other->pasteboard()).commitToPasteboard(*m_pasteboard); >+ other->commitToPasteboard(*m_pasteboard); > > m_dropEffect = other->m_dropEffect; > m_effectAllowed = other->m_effectAllowed; >diff --git a/Source/WebCore/dom/DataTransfer.h b/Source/WebCore/dom/DataTransfer.h >index 8400d7a23d9367cd4e1108cf01b788ac4717aaa6..9ddb227dead9934698bc67776c93aaccf49fc394 100644 >--- a/Source/WebCore/dom/DataTransfer.h >+++ b/Source/WebCore/dom/DataTransfer.h >@@ -32,6 +32,7 @@ namespace WebCore { > > class CachedImage; > class DataTransferItemList; >+class Document; > class DragData; > class DragImageLoader; > class Element; >@@ -44,7 +45,7 @@ public: > // https://html.spec.whatwg.org/multipage/dnd.html#drag-data-store-mode > enum class StoreMode { Invalid, ReadWrite, Readonly, Protected }; > >- static Ref<DataTransfer> createForCopyAndPaste(StoreMode, std::unique_ptr<Pasteboard>&&); >+ static Ref<DataTransfer> createForCopyAndPaste(Document&, StoreMode, std::unique_ptr<Pasteboard>&&); > static Ref<DataTransfer> createForInputEvent(const String& plainText, const String& htmlText); > > WEBCORE_EXPORT ~DataTransfer(); >@@ -79,11 +80,13 @@ public: > bool hasStringOfType(const String&); > > Pasteboard& pasteboard() { return *m_pasteboard; } >+ void commitToPasteboard(Pasteboard&); > > #if ENABLE(DRAG_SUPPORT) > static Ref<DataTransfer> createForDrag(); >- static Ref<DataTransfer> createForDragStartEvent(); >- static Ref<DataTransfer> createForDrop(StoreMode, const DragData&); >+ static Ref<DataTransfer> createForDragStartEvent(Document&); >+ static Ref<DataTransfer> createForDrop(Document&, std::unique_ptr<Pasteboard>&&, DragOperation, bool draggingFiles); >+ static Ref<DataTransfer> createForUpdatingDropTarget(Document&, std::unique_ptr<Pasteboard>&&, DragOperation, bool draggingFiles); > > bool dropEffectIsUninitialized() const { return m_dropEffect == "uninitialized"; } > >@@ -118,6 +121,7 @@ private: > > Vector<Ref<File>> filesFromPasteboardAndItemList() const; > >+ String m_origin; > StoreMode m_storeMode; > std::unique_ptr<Pasteboard> m_pasteboard; > std::unique_ptr<DataTransferItemList> m_itemList; >diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp >index 0146d9822b776e20e99c02cfff5be2dbf0a0508e..eca59e38cc6ed4d79886dca04aa2b0cc9786d717 100644 >--- a/Source/WebCore/dom/Document.cpp >+++ b/Source/WebCore/dom/Document.cpp >@@ -208,11 +208,13 @@ > #include <inspector/ConsoleMessage.h> > #include <inspector/ScriptCallStack.h> > #include <pal/Logger.h> >+#include <wtf/CryptographicallyRandomNumber.h> > #include <wtf/CurrentTime.h> > #include <wtf/Language.h> > #include <wtf/NeverDestroyed.h> > #include <wtf/SetForScope.h> > #include <wtf/SystemTracing.h> >+#include <wtf/text/Base64.h> > #include <wtf/text/StringBuffer.h> > #include <yarr/RegularExpression.h> > >@@ -5298,6 +5300,27 @@ bool Document::isTelephoneNumberParsingAllowed() const > > #endif > >+String Document::uniqueIdentifier() >+{ >+ if (!m_uniqueIdentifier) { >+ // The unique identifier of a document would collide only if 256-bits of cryptographically random values >+ // happen to be identical within 1 miroseconds of one another for two documents with an identical pointer value. >+ Vector<uint8_t> result(256 / 8); >+ cryptographicallyRandomValues(result.data(), result.size()); >+ >+ StringBuilder identififer; >+ identififer.append("null:"); >+ identififer.appendFixedWidthNumber(MonotonicTime::now().approximateWallTime().secondsSinceEpoch().seconds(), 6); >+ identififer.append(':'); >+ identififer.append(base64URLEncode(result)); >+ identififer.append(':'); >+ identififer.appendNumber(reinterpret_cast<uint64_t>(this)); >+ m_uniqueIdentifier = identififer.toString(); >+ } >+ >+ return m_uniqueIdentifier; >+} >+ > ExceptionOr<Ref<XPathExpression>> Document::createExpression(const String& expression, RefPtr<XPathNSResolver>&& resolver) > { > if (!m_xpathEvaluator) >diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h >index 9011bd09fefd8bd506171ab6fad560f5ef5f3634..b7946ee74dca7391b79c418d43fe8bb17e4e3192 100644 >--- a/Source/WebCore/dom/Document.h >+++ b/Source/WebCore/dom/Document.h >@@ -958,6 +958,8 @@ public: > void incDOMTreeVersion() { m_domTreeVersion = ++s_globalTreeVersion; } > uint64_t domTreeVersion() const { return m_domTreeVersion; } > >+ String uniqueIdentifier(); >+ > // XPathEvaluator methods > WEBCORE_EXPORT ExceptionOr<Ref<XPathExpression>> createExpression(const String& expression, RefPtr<XPathNSResolver>&&); > WEBCORE_EXPORT Ref<XPathNSResolver> createNSResolver(Node* nodeResolver); >@@ -1518,7 +1520,9 @@ private: > > uint64_t m_domTreeVersion; > static uint64_t s_globalTreeVersion; >- >+ >+ String m_uniqueIdentifier; >+ > HashSet<NodeIterator*> m_nodeIterators; > HashSet<Range*> m_ranges; > >diff --git a/Source/WebCore/editing/Editor.cpp b/Source/WebCore/editing/Editor.cpp >index c4c25ab684bd5bb2000411c3441e813bcddad86c..4ca0a7789f61bd09ca5620eaee5834f435c68371 100644 >--- a/Source/WebCore/editing/Editor.cpp >+++ b/Source/WebCore/editing/Editor.cpp >@@ -345,30 +345,30 @@ static AtomicString eventNameForClipboardEvent(ClipboardEventKind kind) > return { }; > } > >-static Ref<DataTransfer> createDataTransferForClipboardEvent(ClipboardEventKind kind) >+static Ref<DataTransfer> createDataTransferForClipboardEvent(Document& document, ClipboardEventKind kind) > { > switch (kind) { > case ClipboardEventKind::Copy: > case ClipboardEventKind::Cut: >- return DataTransfer::createForCopyAndPaste(DataTransfer::StoreMode::ReadWrite, std::make_unique<StaticPasteboard>()); >+ return DataTransfer::createForCopyAndPaste(document, 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)); >+ return DataTransfer::createForCopyAndPaste(document, DataTransfer::StoreMode::Readonly, WTFMove(pasteboard)); > } > FALLTHROUGH; > case ClipboardEventKind::Paste: >- return DataTransfer::createForCopyAndPaste(DataTransfer::StoreMode::Readonly, Pasteboard::createForCopyAndPaste()); >+ return DataTransfer::createForCopyAndPaste(document, DataTransfer::StoreMode::Readonly, Pasteboard::createForCopyAndPaste()); > case ClipboardEventKind::BeforeCopy: > case ClipboardEventKind::BeforeCut: > case ClipboardEventKind::BeforePaste: >- return DataTransfer::createForCopyAndPaste(DataTransfer::StoreMode::Invalid, std::make_unique<StaticPasteboard>()); >+ return DataTransfer::createForCopyAndPaste(document, DataTransfer::StoreMode::Invalid, std::make_unique<StaticPasteboard>()); > } > ASSERT_NOT_REACHED(); >- return DataTransfer::createForCopyAndPaste(DataTransfer::StoreMode::Invalid, std::make_unique<StaticPasteboard>()); >+ return DataTransfer::createForCopyAndPaste(document, DataTransfer::StoreMode::Invalid, std::make_unique<StaticPasteboard>()); > } > > // Returns whether caller should continue with "the default processing", which is the same as >@@ -380,7 +380,7 @@ static bool dispatchClipboardEvent(RefPtr<Element>&& target, ClipboardEventKind > if (!target) > return true; > >- auto dataTransfer = createDataTransferForClipboardEvent(kind); >+ auto dataTransfer = createDataTransferForClipboardEvent(target->document(), kind); > > ClipboardEvent::Init init; > init.bubbles = true; >@@ -393,7 +393,7 @@ static bool dispatchClipboardEvent(RefPtr<Element>&& target, ClipboardEventKind > if (noDefaultProcessing && (kind == ClipboardEventKind::Copy || kind == ClipboardEventKind::Cut)) { > auto pasteboard = Pasteboard::createForCopyAndPaste(); > pasteboard->clear(); >- downcast<StaticPasteboard>(dataTransfer->pasteboard()).commitToPasteboard(*pasteboard); >+ dataTransfer->commitToPasteboard(*pasteboard); > } > > dataTransfer->makeInvalidForSecurity(); >diff --git a/Source/WebCore/page/DragController.cpp b/Source/WebCore/page/DragController.cpp >index 3f8a206b5559647c08e2b51ba5c6cfedaa6584d5..d830beb2700863d61c663c510ebd83993e6ab7b9 100644 >--- a/Source/WebCore/page/DragController.cpp >+++ b/Source/WebCore/page/DragController.cpp >@@ -220,31 +220,11 @@ DragOperation DragController::dragEntered(const DragData& dragData) > return dragEnteredOrUpdated(dragData); > } > >-static Ref<DataTransfer> createDataTransferToUpdateDrag(const DragData& dragData, const Settings& settings, RefPtr<Document>&& documentUnderMouse) >-{ >- auto accessMode = DataTransfer::StoreMode::Protected; >- >-#if ENABLE(DASHBOARD_SUPPORT) >- if (settings.usesDashboardBackwardCompatibilityMode() && (!documentUnderMouse || documentUnderMouse->securityOrigin().isLocal())) >- accessMode = DataTransfer::StoreMode::Readonly; >-#else >- UNUSED_PARAM(settings); >- UNUSED_PARAM(documentUnderMouse); >-#endif >- >- auto dataTransfer = DataTransfer::createForDrop(accessMode, dragData); >- dataTransfer->setSourceOperation(dragData.draggingSourceOperationMask()); >- >- return dataTransfer; >-} >- > void DragController::dragExited(const DragData& dragData) > { >- if (RefPtr<FrameView> v = m_page.mainFrame().view()) { >- auto dataTransfer = createDataTransferToUpdateDrag(dragData, m_page.mainFrame().settings(), m_documentUnderMouse.copyRef()); >- m_page.mainFrame().eventHandler().cancelDragAndDrop(createMouseEvent(dragData), dataTransfer); >- dataTransfer->makeInvalidForSecurity(); >- } >+ auto& mainFrame = m_page.mainFrame(); >+ if (mainFrame.view()) >+ mainFrame.eventHandler().cancelDragAndDrop(createMouseEvent(dragData), Pasteboard::createForDragAndDrop(dragData), dragData.draggingSourceOperationMask(), dragData.containsFiles()); > mouseMovedIntoDocument(nullptr); > if (m_fileInputElementUnderMouse) > m_fileInputElementUnderMouse->setCanReceiveDroppedFiles(false); >@@ -282,13 +262,8 @@ bool DragController::performDragOperation(const DragData& dragData) > m_client.willPerformDragDestinationAction(DragDestinationActionDHTML, dragData); > Ref<MainFrame> mainFrame(m_page.mainFrame()); > bool preventedDefault = false; >- if (mainFrame->view()) { >- // Sending an event can result in the destruction of the view and part. >- auto dataTransfer = DataTransfer::createForDrop(DataTransfer::StoreMode::Readonly, dragData); >- dataTransfer->setSourceOperation(dragData.draggingSourceOperationMask()); >- preventedDefault = mainFrame->eventHandler().performDragAndDrop(createMouseEvent(dragData), dataTransfer); >- dataTransfer->makeInvalidForSecurity(); >- } >+ if (mainFrame->view()) >+ preventedDefault = mainFrame->eventHandler().performDragAndDrop(createMouseEvent(dragData), Pasteboard::createForDragAndDrop(dragData), dragData.draggingSourceOperationMask(), dragData.containsFiles()); > if (preventedDefault) { > clearDragCaret(); > m_documentUnderMouse = nullptr; >@@ -531,6 +506,7 @@ bool DragController::dispatchTextInputEventFor(Frame* innerFrame, const DragData > ASSERT(m_page.dragCaretController().hasCaret()); > String text = m_page.dragCaretController().isContentRichlyEditable() ? emptyString() : dragData.asPlainText(); > Element* target = innerFrame->editor().findEventTargetFrom(m_page.dragCaretController().caretPosition()); >+ // FIXME: What guarantees target is not null? > return target->dispatchEvent(TextEvent::createForDrop(innerFrame->document()->domWindow(), text)); > } > >@@ -709,24 +685,18 @@ bool DragController::tryDHTMLDrag(const DragData& dragData, DragOperation& opera > if (!viewProtector) > return false; > >- auto dataTransfer = createDataTransferToUpdateDrag(dragData, mainFrame->settings(), m_documentUnderMouse.copyRef()); >- >- PlatformMouseEvent event = createMouseEvent(dragData); >- if (!mainFrame->eventHandler().updateDragAndDrop(event, dataTransfer)) { >- dataTransfer->makeInvalidForSecurity(); >+ DragOperation sourceOperation = dragData.draggingSourceOperationMask(); >+ std::optional<DragOperation> destinationOperation; >+ if (!mainFrame->eventHandler().updateDragAndDrop(createMouseEvent(dragData), [&dragData]() { return Pasteboard::createForDragAndDrop(dragData); }, sourceOperation, dragData.containsFiles(), destinationOperation)) > return false; >- } > >- operation = dataTransfer->destinationOperation(); >- DragOperation srcOpMask = dragData.draggingSourceOperationMask(); >- if (dataTransfer->dropEffectIsUninitialized()) >- operation = defaultOperationForDrag(srcOpMask); >- else if (!(srcOpMask & operation)) { >- // The element picked an operation which is not supported by the source >+ if (!destinationOperation) >+ operation = defaultOperationForDrag(sourceOperation); >+ else if (!(sourceOperation & *destinationOperation)) // The element picked an operation which is not supported by the source > operation = DragOperationNone; >- } >+ else >+ operation = *destinationOperation; > >- dataTransfer->makeInvalidForSecurity(); > return true; > } > >diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp >index 23d47c5a1950c1acfc4fe7009494e5863ff2f31e..d5848573f5edec7097f4d7eb0bc7b122e7169dec 100644 >--- a/Source/WebCore/page/EventHandler.cpp >+++ b/Source/WebCore/page/EventHandler.cpp >@@ -2180,7 +2180,7 @@ bool EventHandler::handlePasteGlobalSelection(const PlatformMouseEvent& platform > > #if ENABLE(DRAG_SUPPORT) > >-bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Element& dragTarget, const PlatformMouseEvent& event, DataTransfer* dataTransfer) >+bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Element& dragTarget, const PlatformMouseEvent& event, DataTransfer& dataTransfer) > { > Ref<Frame> protectedFrame(m_frame); > FrameView* view = m_frame.view(); >@@ -2197,7 +2197,7 @@ bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Element& dra > event.movementDelta().x(), event.movementDelta().y(), > #endif > event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), >- 0, 0, event.force(), NoTap, dataTransfer); >+ 0, 0, event.force(), NoTap, &dataTransfer); > > dragTarget.dispatchEvent(me); > return me->defaultPrevented(); >@@ -2248,10 +2248,9 @@ static bool hasDropZoneType(DataTransfer& dataTransfer, const String& keyword) > return false; > } > >-static bool findDropZone(Node* target, DataTransfer* dataTransfer) >+static bool findDropZone(Node& target, DataTransfer& dataTransfer) > { >- ASSERT(target); >- Element* element = is<Element>(*target) ? downcast<Element>(target) : target->parentElement(); >+ RefPtr<Element> element = is<Element>(target) ? &downcast<Element>(target) : target.parentElement(); > for (; element; element = element->parentElement()) { > SpaceSplitString keywords(element->attributeWithoutSynchronization(webkitdropzoneAttr), true); > bool matched = false; >@@ -2262,19 +2261,32 @@ static bool findDropZone(Node* target, DataTransfer* dataTransfer) > if (dragOperation == DragOperationNone) > dragOperation = op; > } else >- matched = matched || hasDropZoneType(*dataTransfer, keywords[i].string()); >+ matched = matched || hasDropZoneType(dataTransfer, keywords[i].string()); > if (matched && dragOperation != DragOperationNone) > break; > } > if (matched) { >- dataTransfer->setDropEffect(convertDragOperationToDropZoneOperation(dragOperation)); >+ dataTransfer.setDropEffect(convertDragOperationToDropZoneOperation(dragOperation)); > return true; > } > } > return false; > } >- >-bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, DataTransfer& dataTransfer) >+ >+bool EventHandler::dispatchDragEnterOrDragOverEvent(const AtomicString& eventType, Element& target, const PlatformMouseEvent& event, >+ std::unique_ptr<Pasteboard>&& pasteborad, DragOperation sourceOperation, bool draggingFiles, std::optional<DragOperation>& destinationOperation) >+{ >+ auto dataTransfer = DataTransfer::createForUpdatingDropTarget(target.document(), WTFMove(pasteborad), sourceOperation, draggingFiles); >+ bool accept = dispatchDragEvent(eventType, target, event, dataTransfer.get()); >+ if (!accept) >+ accept = findDropZone(target, dataTransfer); >+ dataTransfer->makeInvalidForSecurity(); >+ if (accept && !dataTransfer->dropEffectIsUninitialized()) >+ destinationOperation = dataTransfer->destinationOperation(); >+ return accept; >+} >+ >+bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, std::function<std::unique_ptr<Pasteboard>()> makePasteboard, DragOperation sourceOperation, bool draggingFiles, std::optional<DragOperation>& destinationOperation) > { > Ref<Frame> protectedFrame(m_frame); > >@@ -2306,23 +2318,25 @@ bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, DataTransf > Frame* targetFrame; > if (targetIsFrame(newTarget.get(), targetFrame)) { > if (targetFrame) >- accept = targetFrame->eventHandler().updateDragAndDrop(event, dataTransfer); >+ accept = targetFrame->eventHandler().updateDragAndDrop(event, makePasteboard, sourceOperation, draggingFiles, destinationOperation); > } else if (newTarget) { > // As per section 7.9.4 of the HTML 5 spec., we must always fire a drag event before firing a dragenter, dragleave, or dragover event. > if (dragState().source && dragState().shouldDispatchEvents) { > // for now we don't care if event handler cancels default behavior, since there is none > dispatchDragSrcEvent(eventNames().dragEvent, event); > } >- accept = dispatchDragEvent(eventNames().dragenterEvent, *newTarget, event, &dataTransfer); >- if (!accept) >- accept = findDropZone(newTarget.get(), &dataTransfer); >+ accept = dispatchDragEnterOrDragOverEvent(eventNames().dragenterEvent, *newTarget, event, makePasteboard(), sourceOperation, draggingFiles, destinationOperation); > } > > if (targetIsFrame(m_dragTarget.get(), targetFrame)) { >+ // FIXME: Recursing again here doesn't make sense if the newTarget and m_dragTarget were in the same frame. > if (targetFrame) >- accept = targetFrame->eventHandler().updateDragAndDrop(event, dataTransfer); >- } else if (m_dragTarget) >- dispatchDragEvent(eventNames().dragleaveEvent, *m_dragTarget, event, &dataTransfer); >+ accept = targetFrame->eventHandler().updateDragAndDrop(event, makePasteboard, sourceOperation, draggingFiles, destinationOperation); >+ } else if (m_dragTarget) { >+ auto dataTransfer = DataTransfer::createForUpdatingDropTarget(m_dragTarget->document(), makePasteboard(), sourceOperation, draggingFiles); >+ dispatchDragEvent(eventNames().dragleaveEvent, *m_dragTarget, event, dataTransfer.get()); >+ dataTransfer->makeInvalidForSecurity(); >+ } > > if (newTarget) { > // We do not explicitly call dispatchDragEvent here because it could ultimately result in the appearance that >@@ -2333,16 +2347,14 @@ bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, DataTransf > Frame* targetFrame; > if (targetIsFrame(newTarget.get(), targetFrame)) { > if (targetFrame) >- accept = targetFrame->eventHandler().updateDragAndDrop(event, dataTransfer); >+ accept = targetFrame->eventHandler().updateDragAndDrop(event, makePasteboard, sourceOperation, draggingFiles, destinationOperation); > } else if (newTarget) { > // Note, when dealing with sub-frames, we may need to fire only a dragover event as a drag event may have been fired earlier. > if (!m_shouldOnlyFireDragOverEvent && dragState().source && dragState().shouldDispatchEvents) { > // for now we don't care if event handler cancels default behavior, since there is none > dispatchDragSrcEvent(eventNames().dragEvent, event); > } >- accept = dispatchDragEvent(eventNames().dragoverEvent, *newTarget, event, &dataTransfer); >- if (!accept) >- accept = findDropZone(newTarget.get(), &dataTransfer); >+ accept = dispatchDragEnterOrDragOverEvent(eventNames().dragoverEvent, *newTarget, event, makePasteboard(), sourceOperation, draggingFiles, destinationOperation); > m_shouldOnlyFireDragOverEvent = false; > } > } >@@ -2350,23 +2362,26 @@ bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, DataTransf > return accept; > } > >-void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, DataTransfer& dataTransfer) >+void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, std::unique_ptr<Pasteboard>&& pasteboard, DragOperation sourceOperation, bool draggingFiles) > { > Ref<Frame> protectedFrame(m_frame); > > Frame* targetFrame; > if (targetIsFrame(m_dragTarget.get(), targetFrame)) { > if (targetFrame) >- targetFrame->eventHandler().cancelDragAndDrop(event, dataTransfer); >+ targetFrame->eventHandler().cancelDragAndDrop(event, WTFMove(pasteboard), sourceOperation, draggingFiles); > } else if (m_dragTarget) { > if (dragState().source && dragState().shouldDispatchEvents) > dispatchDragSrcEvent(eventNames().dragEvent, event); >- dispatchDragEvent(eventNames().dragleaveEvent, *m_dragTarget, event, &dataTransfer); >+ >+ auto dataTransfer = DataTransfer::createForUpdatingDropTarget(m_dragTarget->document(), WTFMove(pasteboard), sourceOperation, draggingFiles); >+ dispatchDragEvent(eventNames().dragleaveEvent, *m_dragTarget, event, dataTransfer.get()); >+ dataTransfer->makeInvalidForSecurity(); > } > clearDragState(); > } > >-bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, DataTransfer& dataTransfer) >+bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, std::unique_ptr<Pasteboard>&& pasteboard, DragOperation sourceOperation, bool draggingFiles) > { > Ref<Frame> protectedFrame(m_frame); > >@@ -2374,9 +2389,12 @@ bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, DataTrans > bool preventedDefault = false; > if (targetIsFrame(m_dragTarget.get(), targetFrame)) { > if (targetFrame) >- preventedDefault = targetFrame->eventHandler().performDragAndDrop(event, dataTransfer); >- } else if (m_dragTarget) >- preventedDefault = dispatchDragEvent(eventNames().dropEvent, *m_dragTarget, event, &dataTransfer); >+ preventedDefault = targetFrame->eventHandler().performDragAndDrop(event, WTFMove(pasteboard), sourceOperation, draggingFiles); >+ } else if (m_dragTarget) { >+ auto dataTransfer = DataTransfer::createForDrop(m_dragTarget->document(), WTFMove(pasteboard), sourceOperation, draggingFiles); >+ preventedDefault = dispatchDragEvent(eventNames().dropEvent, *m_dragTarget, event, dataTransfer); >+ dataTransfer->makeInvalidForSecurity(); >+ } > clearDragState(); > return preventedDefault; > } >@@ -3545,12 +3563,13 @@ void EventHandler::updateDragStateAfterEditDragIfNeeded(Element& rootEditableEle > // Return value indicates if we should continue "default processing", i.e., whether event handler canceled. > bool EventHandler::dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent& event) > { >- return !dispatchDragEvent(eventType, *dragState().source, event, dragState().dataTransfer.get()); >+ ASSERT(dragState().dataTransfer); >+ return !dispatchDragEvent(eventType, *dragState().source, event, *dragState().dataTransfer); > } > > bool EventHandler::dispatchDragStartEventOnSourceElement(DataTransfer& dataTransfer) > { >- return !dispatchDragEvent(eventNames().dragstartEvent, *dragState().source, m_mouseDown, &dataTransfer) && !m_frame.selection().selection().isInPasswordField(); >+ return !dispatchDragEvent(eventNames().dragstartEvent, *dragState().source, m_mouseDown, dataTransfer) && !m_frame.selection().selection().isInPasswordField(); > } > > static bool ExactlyOneBitSet(DragSourceAction n) >@@ -3623,7 +3642,8 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event, CheckDr > > if (!m_mouseDownMayStartDrag) > return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll; >- >+ ASSERT(dragState().source); >+ > if (!ExactlyOneBitSet(dragState().type)) { > ASSERT((dragState().type & DragSourceActionSelection)); > #if ENABLE(ATTACHMENT_ELEMENT) >@@ -3660,7 +3680,8 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event, CheckDr > HasNonDefaultPasteboardData hasNonDefaultPasteboardData = HasNonDefaultPasteboardData::No; > > if (dragState().shouldDispatchEvents) { >- auto dragStartDataTransfer = DataTransfer::createForDragStartEvent(); >+ ASSERT(dragState().source); >+ auto dragStartDataTransfer = DataTransfer::createForDragStartEvent(dragState().source->document()); > m_mouseDownMayStartDrag = dispatchDragStartEventOnSourceElement(dragStartDataTransfer); > hasNonDefaultPasteboardData = dragStartDataTransfer->pasteboard().hasData() ? HasNonDefaultPasteboardData::Yes : HasNonDefaultPasteboardData::No; > dragState().dataTransfer->moveDragState(WTFMove(dragStartDataTransfer)); >diff --git a/Source/WebCore/page/EventHandler.h b/Source/WebCore/page/EventHandler.h >index 2de5acf5ab2bba7c8a2336e7c38eb454e8327054..213c91d2f530ea5f9d10d3a27e2c186c9326a7f2 100644 >--- a/Source/WebCore/page/EventHandler.h >+++ b/Source/WebCore/page/EventHandler.h >@@ -75,6 +75,7 @@ class HitTestResult; > class KeyboardEvent; > class MouseEventWithHitTestResults; > class Node; >+class Pasteboard; > class PlatformGestureEvent; > class PlatformKeyboardEvent; > class PlatformTouchEvent; >@@ -155,9 +156,9 @@ public: > WEBCORE_EXPORT void setCapturingMouseEventsElement(Element*); > > #if ENABLE(DRAG_SUPPORT) >- bool updateDragAndDrop(const PlatformMouseEvent&, DataTransfer&); >- void cancelDragAndDrop(const PlatformMouseEvent&, DataTransfer&); >- bool performDragAndDrop(const PlatformMouseEvent&, DataTransfer&); >+ bool updateDragAndDrop(const PlatformMouseEvent&, std::function<std::unique_ptr<Pasteboard>()>, DragOperation sourceOperation, bool draggingFiles, std::optional<DragOperation>& destinationOperation); >+ void cancelDragAndDrop(const PlatformMouseEvent&, std::unique_ptr<Pasteboard>&&, DragOperation, bool draggingFiles); >+ bool performDragAndDrop(const PlatformMouseEvent&, std::unique_ptr<Pasteboard>&&, DragOperation, bool draggingFiles); > void updateDragStateAfterEditDragIfNeeded(Element& rootEditableElement); > RefPtr<Element> draggedElement() const; > #endif >@@ -392,7 +393,8 @@ private: > bool dispatchMouseEvent(const AtomicString& eventType, Node* target, bool cancelable, int clickCount, const PlatformMouseEvent&, bool setUnder); > > #if ENABLE(DRAG_SUPPORT) >- bool dispatchDragEvent(const AtomicString& eventType, Element& target, const PlatformMouseEvent&, DataTransfer*); >+ bool dispatchDragEvent(const AtomicString& eventType, Element& target, const PlatformMouseEvent&, DataTransfer&); >+ bool dispatchDragEnterOrDragOverEvent(const AtomicString& eventType, Element& target, const PlatformMouseEvent&, std::unique_ptr<Pasteboard>&& , DragOperation, bool draggingFiles, std::optional<DragOperation>& destinationOperation); > void invalidateDataTransfer(); > > bool handleDrag(const MouseEventWithHitTestResults&, CheckDragHysteresis); >diff --git a/Source/WebCore/platform/Pasteboard.h b/Source/WebCore/platform/Pasteboard.h >index 748b5cbef9a9b562a8c3b4adfdbebbc7d343ef6d..ce3175cf2fd5f891c4959f6cd68f7595c6cec784 100644 >--- a/Source/WebCore/platform/Pasteboard.h >+++ b/Source/WebCore/platform/Pasteboard.h >@@ -193,8 +193,9 @@ public: > virtual bool isStatic() const { return false; } > > virtual bool hasData(); >- virtual Vector<String> typesSafeForBindings(); >+ virtual Vector<String> typesSafeForBindings(const String& origin); > virtual Vector<String> typesForLegacyUnsafeBindings(); >+ virtual String readOrigin(); > virtual String readString(const String& type); > virtual String readStringInCustomData(const String& type); > >@@ -211,6 +212,8 @@ public: > virtual void write(const PasteboardImage&); > virtual void write(const PasteboardWebContent&); > >+ virtual void writeCustomData(const PasteboardCustomData&); >+ > virtual bool containsFiles(); > virtual bool canSmartReplace(); > >@@ -250,6 +253,7 @@ public: > WEBCORE_EXPORT static NSArray *supportedFileUploadPasteboardTypes(); > const String& name() const { return m_pasteboardName; } > long changeCount() const; >+ const PasteboardCustomData& readCustomData(); > #endif > > #if PLATFORM(WIN) >@@ -261,8 +265,6 @@ public: > void writeImageToDataObject(Element&, const URL&); // FIXME: Layering violation. > #endif > >- void writeCustomData(const PasteboardCustomData&); >- > private: > #if PLATFORM(IOS) > bool respectsUTIFidelities() const; >@@ -295,6 +297,7 @@ private: > #if PLATFORM(COCOA) > String m_pasteboardName; > long m_changeCount; >+ std::optional<PasteboardCustomData> m_customDataCache; > #endif > > #if PLATFORM(WIN) >diff --git a/Source/WebCore/platform/PasteboardStrategy.h b/Source/WebCore/platform/PasteboardStrategy.h >index b2684c968112352f3afcc0f7d59172ea66034997..c064ad0fc9fc86b5f22b489160535ce7237e112d 100644 >--- a/Source/WebCore/platform/PasteboardStrategy.h >+++ b/Source/WebCore/platform/PasteboardStrategy.h >@@ -72,7 +72,7 @@ public: > virtual long setStringForType(const String&, const String& pasteboardType, const String& pasteboardName) = 0; > #endif > >- virtual Vector<String> typesSafeForDOMToReadAndWrite(const String& pasteboardName) = 0; >+ virtual Vector<String> typesSafeForDOMToReadAndWrite(const String& pasteboardName, const String& origin) = 0; > virtual long writeCustomData(const PasteboardCustomData&, const String& pasteboardName) = 0; > > #if PLATFORM(GTK) >diff --git a/Source/WebCore/platform/PlatformPasteboard.h b/Source/WebCore/platform/PlatformPasteboard.h >index 3954c210cf974765b9587ecaf4b91e3af1931881..4f4ab0af1fa90f996012224d088b28274c276476 100644 >--- a/Source/WebCore/platform/PlatformPasteboard.h >+++ b/Source/WebCore/platform/PlatformPasteboard.h >@@ -95,7 +95,7 @@ public: > WEBCORE_EXPORT int numberOfFiles() const; > > WEBCORE_EXPORT long write(const PasteboardCustomData&); >- WEBCORE_EXPORT Vector<String> typesSafeForDOMToReadAndWrite() const; >+ WEBCORE_EXPORT Vector<String> typesSafeForDOMToReadAndWrite(const String& origin) const; > > #if PLATFORM(GTK) > WEBCORE_EXPORT void writeToClipboard(const SelectionData&, WTF::Function<void()>&& primarySelectionCleared); >diff --git a/Source/WebCore/platform/StaticPasteboard.cpp b/Source/WebCore/platform/StaticPasteboard.cpp >index 7c0aa3d97c8facd18277eb63af062a4b7f33a265..17313e460785f3034d410c311af398e68f09ae7a 100644 >--- a/Source/WebCore/platform/StaticPasteboard.cpp >+++ b/Source/WebCore/platform/StaticPasteboard.cpp >@@ -26,9 +26,6 @@ > #include "config.h" > #include "StaticPasteboard.h" > >-#include "Settings.h" >-#include "SharedBuffer.h" >- > namespace WebCore { > > StaticPasteboard::StaticPasteboard() >@@ -85,20 +82,9 @@ void StaticPasteboard::clear(const String& type) > ASSERT(!m_types.contains(type)); > } > >-void StaticPasteboard::commitToPasteboard(Pasteboard& pasteboard) >+PasteboardCustomData StaticPasteboard::takeCustomData() > { >- if (m_platformData.isEmpty() && m_customData.isEmpty()) >- return; >- >- if (Settings::customPasteboardDataEnabled()) { >- pasteboard.writeCustomData({ { }, WTFMove(m_types), WTFMove(m_platformData), WTFMove(m_customData) }); >- return; >- } >- >- for (auto& entry : m_platformData) >- pasteboard.writeString(entry.key, entry.value); >- for (auto& entry : m_customData) >- pasteboard.writeString(entry.key, entry.value); >+ return { { }, WTFMove(m_types), WTFMove(m_platformData), WTFMove(m_customData) }; > } > > } >diff --git a/Source/WebCore/platform/StaticPasteboard.h b/Source/WebCore/platform/StaticPasteboard.h >index 9cfcc72f12b463189286cec0ce2e5b753c05bfd3..6a3934da46d8bf39ece0254bc7c5d9978d98dd35 100644 >--- a/Source/WebCore/platform/StaticPasteboard.h >+++ b/Source/WebCore/platform/StaticPasteboard.h >@@ -36,13 +36,14 @@ class StaticPasteboard final : public Pasteboard { > public: > StaticPasteboard(); > >- void commitToPasteboard(Pasteboard&); >+ PasteboardCustomData takeCustomData(); > > bool isStatic() const final { return true; } > > bool hasData() final; >- Vector<String> typesSafeForBindings() final { return m_types; } >+ Vector<String> typesSafeForBindings(const String&) final { return m_types; } > Vector<String> typesForLegacyUnsafeBindings() final { return m_types; } >+ String readOrigin() final { return { }; } > String readString(const String& type) final; > String readStringInCustomData(const String& type) final; > >@@ -58,6 +59,8 @@ public: > void write(const PasteboardImage&) final { } > void write(const PasteboardWebContent&) final { } > >+ void writeCustomData(const PasteboardCustomData&) final { } >+ > bool containsFiles() final { return false; } > bool canSmartReplace() final { return false; } > >diff --git a/Source/WebCore/platform/cocoa/PasteboardCocoa.mm b/Source/WebCore/platform/cocoa/PasteboardCocoa.mm >index 05cebbbc91c0f8c1e39bf9566c27ad68771686f1..4d0d7863c16f8dbf3f55f9b7168601270828c840 100644 >--- a/Source/WebCore/platform/cocoa/PasteboardCocoa.mm >+++ b/Source/WebCore/platform/cocoa/PasteboardCocoa.mm >@@ -143,9 +143,9 @@ bool Pasteboard::containsFiles() > return true; > } > >-Vector<String> Pasteboard::typesSafeForBindings() >+Vector<String> Pasteboard::typesSafeForBindings(const String& origin) > { >- Vector<String> types = platformStrategies()->pasteboardStrategy()->typesSafeForDOMToReadAndWrite(m_pasteboardName); >+ Vector<String> types = platformStrategies()->pasteboardStrategy()->typesSafeForDOMToReadAndWrite(m_pasteboardName, origin); > > // Enforce changeCount ourselves for security. We check after reading instead of before to be > // sure it doesn't change between our testing the change count and accessing the data. >@@ -215,16 +215,24 @@ String Pasteboard::readString(const String& type) > > String Pasteboard::readStringInCustomData(const String& type) > { >- auto buffer = readBufferForTypeWithSecurityCheck(PasteboardCustomData::cocoaType()); >- if (!buffer) >- return { }; >+ return readCustomData().sameOriginCustomData.get(type); >+} > >- // Enforce changeCount ourselves for security. We check after reading instead of before to be >- // sure it doesn't change between our testing the change count and accessing the data. >- if (m_changeCount != platformStrategies()->pasteboardStrategy()->changeCount(m_pasteboardName)) >- return { }; >+String Pasteboard::readOrigin() >+{ >+ return readCustomData().origin; >+} > >- return PasteboardCustomData::fromSharedBuffer(*buffer).sameOriginCustomData.get(type); >+const PasteboardCustomData& Pasteboard::readCustomData() >+{ >+ if (m_customDataCache) >+ return *m_customDataCache; >+ >+ if (auto buffer = readBufferForTypeWithSecurityCheck(PasteboardCustomData::cocoaType())) >+ m_customDataCache = PasteboardCustomData::fromSharedBuffer(*buffer); >+ else >+ m_customDataCache = PasteboardCustomData { }; >+ return *m_customDataCache; > } > > void Pasteboard::writeCustomData(const PasteboardCustomData& data) >diff --git a/Source/WebCore/platform/gtk/PlatformPasteboardGtk.cpp b/Source/WebCore/platform/gtk/PlatformPasteboardGtk.cpp >index b9334da925e7c24d627d5fd357118f0f27fcf8ff..f308c2bb7e53691da34c6ebd0b34ed11beb2fb64 100644 >--- a/Source/WebCore/platform/gtk/PlatformPasteboardGtk.cpp >+++ b/Source/WebCore/platform/gtk/PlatformPasteboardGtk.cpp >@@ -46,7 +46,7 @@ Ref<SelectionData> PlatformPasteboard::readFromClipboard() > return selection; > } > >-Vector<String> PlatformPasteboard::typesSafeForDOMToReadAndWrite() const >+Vector<String> PlatformPasteboard::typesSafeForDOMToReadAndWrite(const String&) const > { > return { }; > } >diff --git a/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm b/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm >index bfcecafb1f20e6a67c5c56eb448531762d50ef52..7f00ed0065e4f216ef8621f52c89ec7b899d6963 100644 >--- a/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm >+++ b/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm >@@ -343,7 +343,10 @@ static const char *safeTypeForDOMToReadAndWriteForPlatformType(const String& pla > return nullptr; > } > >-Vector<String> PlatformPasteboard::typesSafeForDOMToReadAndWrite() const >+static const char customTypesKeyForOrigin[] = "com.apple.WebKit.drag-and-drop-team-data.origin"; >+static const char customTypesKeyForTeamData[] = "com.apple.WebKit.drag-and-drop-team-data.custom-types"; >+ >+Vector<String> PlatformPasteboard::typesSafeForDOMToReadAndWrite(const String& origin) const > { > ListHashSet<String> domPasteboardTypes; > for (NSItemProvider *provider in [m_pasteboard itemProviders]) { >@@ -354,7 +357,13 @@ Vector<String> PlatformPasteboard::typesSafeForDOMToReadAndWrite() const > if (!teamDataObject || ![teamDataObject isKindOfClass:[NSDictionary class]]) > continue; > >- id customTypes = [(NSDictionary *)teamDataObject objectForKey:@(PasteboardCustomData::cocoaType())]; >+ id originInTeamData = [(NSDictionary *)teamDataObject objectForKey:@(customTypesKeyForOrigin)]; >+ if (![originInTeamData isKindOfClass:[NSString class]]) >+ continue; >+ if (String((NSString *)originInTeamData) != origin) >+ continue; >+ >+ id customTypes = [(NSDictionary *)teamDataObject objectForKey:@(customTypesKeyForTeamData)]; > if (![customTypes isKindOfClass:[NSArray class]]) > continue; > >@@ -363,9 +372,11 @@ Vector<String> PlatformPasteboard::typesSafeForDOMToReadAndWrite() const > } > > if (NSData *serializedCustomData = [m_pasteboard dataForPasteboardType:@(PasteboardCustomData::cocoaType())]) { >- auto buffer = SharedBuffer::create(serializedCustomData); >- for (auto& type : PasteboardCustomData::fromSharedBuffer(buffer.get()).orderedTypes) >- domPasteboardTypes.add(type); >+ auto data = PasteboardCustomData::fromSharedBuffer(SharedBuffer::create(serializedCustomData).get()); >+ if (data.origin == origin) { >+ for (auto& type : data.orderedTypes) >+ domPasteboardTypes.add(type); >+ } > } > > for (NSString *type in [m_pasteboard pasteboardTypes]) { >@@ -402,7 +413,8 @@ long PlatformPasteboard::write(const PasteboardCustomData& data) > NSMutableArray<NSString *> *typesAsNSArray = [NSMutableArray array]; > for (auto& type : data.orderedTypes) > [typesAsNSArray addObject:type]; >- [representationsToRegister setTeamData:[NSKeyedArchiver archivedDataWithRootObject:@{ @(PasteboardCustomData::cocoaType()) : typesAsNSArray }]]; >+ [representationsToRegister setTeamData:[NSKeyedArchiver archivedDataWithRootObject:@{ >+ @(customTypesKeyForOrigin) : data.origin, @(customTypesKeyForTeamData) : typesAsNSArray }]]; > [representationsToRegister addData:serializedSharedBuffer.get() forType:@(PasteboardCustomData::cocoaType())]; > } > } >@@ -448,7 +460,7 @@ void PlatformPasteboard::write(const PasteboardURL&) > { > } > >-Vector<String> PlatformPasteboard::typesSafeForDOMToReadAndWrite() const >+Vector<String> PlatformPasteboard::typesSafeForDOMToReadAndWrite(const String&) const > { > return { }; > } >diff --git a/Source/WebCore/platform/mac/PlatformPasteboardMac.mm b/Source/WebCore/platform/mac/PlatformPasteboardMac.mm >index 4010f30858057d9bfb1311fb088c5a8d06cfa4c5..ff022d4d3492e1ac3d0c2eee93f59062fb4762db 100644 >--- a/Source/WebCore/platform/mac/PlatformPasteboardMac.mm >+++ b/Source/WebCore/platform/mac/PlatformPasteboardMac.mm >@@ -107,13 +107,15 @@ static const char* safeTypeForDOMToReadAndWriteForPlatformType(const String& pla > return nullptr; > } > >-Vector<String> PlatformPasteboard::typesSafeForDOMToReadAndWrite() const >+Vector<String> PlatformPasteboard::typesSafeForDOMToReadAndWrite(const String& origin) const > { > ListHashSet<String> domPasteboardTypes; > if (NSData *serializedCustomData = [m_pasteboard dataForType:@(PasteboardCustomData::cocoaType())]) { >- auto buffer = SharedBuffer::create(serializedCustomData); >- for (auto& type : PasteboardCustomData::fromSharedBuffer(buffer.get()).orderedTypes) >- domPasteboardTypes.add(type); >+ auto data = PasteboardCustomData::fromSharedBuffer(SharedBuffer::create(serializedCustomData).get()); >+ if (data.origin == origin) { >+ for (auto& type : data.orderedTypes) >+ domPasteboardTypes.add(type); >+ } > } > > NSArray<NSString *> *allTypes = [m_pasteboard types]; >diff --git a/Source/WebCore/platform/wpe/PlatformPasteboardWPE.cpp b/Source/WebCore/platform/wpe/PlatformPasteboardWPE.cpp >index 3bded132f40e535ae03a511834598688cca64438..610f2fd2a3ec0dea797aabc65ac6cb8bcd44cb05 100644 >--- a/Source/WebCore/platform/wpe/PlatformPasteboardWPE.cpp >+++ b/Source/WebCore/platform/wpe/PlatformPasteboardWPE.cpp >@@ -116,7 +116,7 @@ void PlatformPasteboard::write(const String& type, const String& string) > wpe_pasteboard_string_free(&pairs[0].string); > } > >-Vector<String> PlatformPasteboard::typesSafeForDOMToReadAndWrite() const >+Vector<String> PlatformPasteboard::typesSafeForDOMToReadAndWrite(const String&) const > { > return { }; > } >diff --git a/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm >index 576d24311d835746be89cba63f9e21de4d2fed27..63254d97dfc8aeb15987379635ba7cf5c5e8d341 100644 >--- a/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm >+++ b/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm >@@ -159,9 +159,9 @@ void WebPasteboardProxy::getNumberOfFiles(const String& pasteboardName, uint64_t > numberOfFiles = PlatformPasteboard(pasteboardName).numberOfFiles(); > } > >-void WebPasteboardProxy::typesSafeForDOMToReadAndWrite(const String& pasteboardName, Vector<String>& types) >+void WebPasteboardProxy::typesSafeForDOMToReadAndWrite(const String& pasteboardName, const String& origin, Vector<String>& types) > { >- types = PlatformPasteboard(pasteboardName).typesSafeForDOMToReadAndWrite(); >+ types = PlatformPasteboard(pasteboardName).typesSafeForDOMToReadAndWrite(origin); > } > > void WebPasteboardProxy::writeCustomData(const WebCore::PasteboardCustomData& data, const String& pasteboardName, uint64_t& newChangeCount) >diff --git a/Source/WebKit/UIProcess/WebPasteboardProxy.cpp b/Source/WebKit/UIProcess/WebPasteboardProxy.cpp >index 108d3dd9344ea7571ee2d84aab5b5d0c4246a387..0ee9945f817a436b7a1c6c83ad61b399794fdeda 100644 >--- a/Source/WebKit/UIProcess/WebPasteboardProxy.cpp >+++ b/Source/WebKit/UIProcess/WebPasteboardProxy.cpp >@@ -63,7 +63,7 @@ void WebPasteboardProxy::removeWebProcessProxy(WebProcessProxy& webProcessProxy) > > #if !PLATFORM(COCOA) > >-void WebPasteboardProxy::typesSafeForDOMToReadAndWrite(const String&, Vector<String>& types) >+void WebPasteboardProxy::typesSafeForDOMToReadAndWrite(const String&, const String&, Vector<String>& types) > { > types = { }; > } >diff --git a/Source/WebKit/UIProcess/WebPasteboardProxy.h b/Source/WebKit/UIProcess/WebPasteboardProxy.h >index 770930a6881995b9c6b4204d1dab321a949a2bf9..6cede05e2a33287eb2bd6b4a24e5ebd523064bb4 100644 >--- a/Source/WebKit/UIProcess/WebPasteboardProxy.h >+++ b/Source/WebKit/UIProcess/WebPasteboardProxy.h >@@ -99,7 +99,7 @@ private: > #endif > > void writeCustomData(const WebCore::PasteboardCustomData&, const String& pasteboardName, uint64_t& newChangeCount); >- void typesSafeForDOMToReadAndWrite(const String& pasteboardName, Vector<String>& types); >+ void typesSafeForDOMToReadAndWrite(const String& pasteboardName, const String& origin, Vector<String>& types); > > #if PLATFORM(GTK) > void writeToClipboard(const String& pasteboardName, const WebSelectionData&); >diff --git a/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in b/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in >index cd2841fb0b37e705d9ebcd580eb6107151121abf..be1618424c736cf2c181c37a4cd8447757dcafbc 100644 >--- a/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in >+++ b/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in >@@ -36,7 +36,7 @@ messages -> WebPasteboardProxy { > #endif > > WriteCustomData(struct WebCore::PasteboardCustomData data, String pasteboardName) -> (uint64_t changeCount) >- TypesSafeForDOMToReadAndWrite(String pasteboardName) -> (Vector<String> types) >+ TypesSafeForDOMToReadAndWrite(String pasteboardName, String origin) -> (Vector<String> types) > > #if PLATFORM(COCOA) > # Pasteboard messages. >diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp >index 84f73f0b22a0bcc1534da60276eaa9dd8c5b3c49..56474ba1e99229f774ebdc8624626ee1b59cc47e 100644 >--- a/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp >+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp >@@ -405,10 +405,10 @@ void WebPlatformStrategies::writeToPasteboard(const String& pasteboardType, cons > > #endif // PLATFORM(WPE) > >-Vector<String> WebPlatformStrategies::typesSafeForDOMToReadAndWrite(const String& pasteboardName) >+Vector<String> WebPlatformStrategies::typesSafeForDOMToReadAndWrite(const String& pasteboardName, const String& origin) > { > Vector<String> types; >- WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::TypesSafeForDOMToReadAndWrite(pasteboardName), Messages::WebPasteboardProxy::TypesSafeForDOMToReadAndWrite::Reply(types), 0); >+ WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::TypesSafeForDOMToReadAndWrite(pasteboardName, origin), Messages::WebPasteboardProxy::TypesSafeForDOMToReadAndWrite::Reply(types), 0); > return types; > } > >diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.h b/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.h >index d0eaa39aac3447c65768df9a5b1c37a3a52a2e0f..20ac6dbfdc896225eb2860901a05ffbdb08010ba 100644 >--- a/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.h >+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.h >@@ -97,7 +97,7 @@ private: > void writeToPasteboard(const String& pasteboardType, const String&) override; > #endif > >- Vector<String> typesSafeForDOMToReadAndWrite(const String& pasteboardName) override; >+ Vector<String> typesSafeForDOMToReadAndWrite(const String& pasteboardName, const String& origin) override; > long writeCustomData(const WebCore::PasteboardCustomData&, const String&) override; > }; > >diff --git a/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.h b/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.h >index b783abd3c36a63176f4b9aaad6eee3283e1859b2..a03eeacf6b4fc39e4e8b4bd2b9fb4964049893ed 100644 >--- a/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.h >+++ b/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.h >@@ -81,7 +81,7 @@ private: > WebCore::URL url(const String& pasteboardName) override; > > long writeCustomData(const WebCore::PasteboardCustomData&, const String& pasteboardName) override; >- Vector<String> typesSafeForDOMToReadAndWrite(const String& pasteboardName) override; >+ Vector<String> typesSafeForDOMToReadAndWrite(const String& pasteboardName, const String& origin) override; > > long addTypes(const Vector<String>& pasteboardTypes, const String& pasteboardName) override; > long setTypes(const Vector<String>& pasteboardTypes, const String& pasteboardName) override; >diff --git a/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm b/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm >index caa046b36cb4585518c8a7cd9c5487fbd4f92ac8..5fbec381a70980a0bc853d72aaead8e6848446c8 100644 >--- a/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm >+++ b/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm >@@ -178,9 +178,9 @@ int WebPlatformStrategies::getNumberOfFiles(const String& pasteboardName) > return PlatformPasteboard(pasteboardName).numberOfFiles(); > } > >-Vector<String> WebPlatformStrategies::typesSafeForDOMToReadAndWrite(const String& pasteboardName) >+Vector<String> WebPlatformStrategies::typesSafeForDOMToReadAndWrite(const String& pasteboardName, const String& origin) > { >- return PlatformPasteboard(pasteboardName).typesSafeForDOMToReadAndWrite(); >+ return PlatformPasteboard(pasteboardName).typesSafeForDOMToReadAndWrite(origin); > } > > long WebPlatformStrategies::writeCustomData(const WebCore::PasteboardCustomData& data, const String& pasteboardName) >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index a50c10d6b2d0a20f4711b2d63290903f377e9ba8..c702841ca1cc4aa82e561605baa45dd9f704e181 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,41 @@ >+2017-10-07 Ryosuke Niwa <rniwa@webkit.org> >+ >+ Sanitize URL in pasteboard for other applications and cross origin content >+ https://bugs.webkit.org/show_bug.cgi?id=178060 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * TestExpectations: >+ * editing/pasteboard/data-transfer-get-data-on-copying-pasting-malformed-url-in-same-document-expected.txt: Added. >+ * editing/pasteboard/data-transfer-get-data-on-copying-pasting-malformed-url-in-same-document.html: Added. >+ * editing/pasteboard/data-transfer-get-data-on-paste-custom-expected.txt: >+ * editing/pasteboard/data-transfer-set-data-ignore-copied-walformed-url-in-null-expected.txt: Added. >+ * editing/pasteboard/data-transfer-set-data-ignore-copied-walformed-url-in-null-origin-expected.txt: Added. >+ * editing/pasteboard/data-transfer-set-data-ignore-copied-walformed-url-in-null-origin.html: Added. >+ * editing/pasteboard/data-transfer-set-data-sanitlize-url-when-copying-in-null-origin-expected.txt: Added. >+ * editing/pasteboard/data-transfer-set-data-sanitlize-url-when-copying-in-null-origin.html: Added. >+ * editing/pasteboard/data-transfer-set-data-sanitlize-url-when-dragging-in-null-origin-expected.txt: Added. >+ * editing/pasteboard/data-transfer-set-data-sanitlize-url-when-dragging-in-null-origin.html: Added. >+ * http/tests/security/clipboard/copy-paste-url-across-origin-sanitizes-url-expected.txt: Added. >+ * http/tests/security/clipboard/copy-paste-url-across-origin-sanitizes-url.html: Added. >+ * http/tests/security/clipboard/resources/copy.html: Added. >+ * platform/mac-wk1/TestExpectations: >+ >+2017-10-07 Ryosuke Niwa <rniwa@webkit.org> >+ >+ dragenter and dragleave shouldn't use the same data transfer object >+ https://bugs.webkit.org/show_bug.cgi?id=178056 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Added a regression test for checking the uniqueness of dataTransfer object for dragenter and dragleave events. >+ Unfortunately, the test is only runnable in Mac WebKit1 port due to the lack of support in WebKitTestRunner. >+ >+ * TestExpectations: >+ * editing/pasteboard/data-transfer-is-unique-for-dragenter-and-dragleave-expected.txt: Added. >+ * editing/pasteboard/data-transfer-is-unique-for-dragenter-and-dragleave.html: Added. >+ * platform/mac-wk1/TestExpectations: >+ > 2017-10-07 Andy Estes <aestes@apple.com> > > [Payment Request] Implement PaymentRequest.show() and PaymentRequest.hide() >diff --git a/LayoutTests/TestExpectations b/LayoutTests/TestExpectations >index 25b34e4b6930746775db15f379296986e0ac333e..b941fc42a6f614cf4c9f54dfabb04ee386908c44 100644 >--- a/LayoutTests/TestExpectations >+++ b/LayoutTests/TestExpectations >@@ -73,6 +73,8 @@ editing/pasteboard/data-transfer-get-data-on-drop-custom.html [ Skip ] > editing/pasteboard/data-transfer-get-data-on-drop-plain-text.html [ Skip ] > editing/pasteboard/data-transfer-get-data-on-drop-rich-text.html [ Skip ] > editing/pasteboard/data-transfer-get-data-on-drop-url.html [ Skip ] >+editing/pasteboard/data-transfer-is-unique-for-dragenter-and-dragleave.html [ Skip ] >+editing/pasteboard/data-transfer-set-data-sanitlize-url-when-dragging-in-null-origin.html [ Skip ] > editing/pasteboard/drag-end-crash-accessing-item-list.html [ Skip ] > editing/pasteboard/data-transfer-item-list-add-file-on-drag.html [ Skip ] > >diff --git a/LayoutTests/editing/pasteboard/data-transfer-get-data-on-copying-pasting-malformed-url-in-same-document-expected.txt b/LayoutTests/editing/pasteboard/data-transfer-get-data-on-copying-pasting-malformed-url-in-same-document-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..66a12c17366a93b1adff62652054f740c82a2785 >--- /dev/null >+++ b/LayoutTests/editing/pasteboard/data-transfer-get-data-on-copying-pasting-malformed-url-in-same-document-expected.txt >@@ -0,0 +1,12 @@ >+This tests calling getData returns the same malformed URL string set by setData >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS event.clipboardData.getData("text/URI-list") is "some bad URL" >+PASS JSON.stringify(event.clipboardData.types) is "[\"text/uri-list\"]" >+FAIL JSON.stringify(Array.from(event.clipboardData.items).map((item) => {kind: item.kind, type: item.type})) should be [{"kind":"string","type":"text/uri-list"}]. Threw exception SyntaxError: Unexpected token ':' >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/editing/pasteboard/data-transfer-get-data-on-copying-pasting-malformed-url-in-same-document.html b/LayoutTests/editing/pasteboard/data-transfer-get-data-on-copying-pasting-malformed-url-in-same-document.html >new file mode 100644 >index 0000000000000000000000000000000000000000..fb419b31bcb6e22fa51a4e0f0de603455ab0bdd9 >--- /dev/null >+++ b/LayoutTests/editing/pasteboard/data-transfer-get-data-on-copying-pasting-malformed-url-in-same-document.html >@@ -0,0 +1,46 @@ >+<!DOCTYPE html> >+<html> >+<body> >+<script src="../../resources/js-test-pre.js"></script> >+<div id="container"> >+<button onclick="runTest()">1. Copy</button> >+<div id="source" oncopy="copy(event)" contenteditable>some text</div> >+<div id="destination" onpaste="paste(event)" contenteditable>2. Paste here</div> >+</div> >+<script> >+ >+description('This tests calling getData returns the same malformed URL string set by setData'); >+jsTestIsAsync = true; >+ >+function runTest() { >+ document.getElementById('source').focus(); >+ document.execCommand('selectAll'); >+ document.execCommand('copy'); >+ document.getElementById('destination').focus(); >+ if (window.testRunner) >+ document.execCommand('paste'); >+} >+ >+function copy(event) { >+ event.clipboardData.setData('url', 'some bad URL'); >+ event.preventDefault(); >+} >+ >+function paste(event) { >+ shouldBeEqualToString('event.clipboardData.getData("text/URI-list")', 'some bad URL'); >+ shouldBeEqualToString('JSON.stringify(event.clipboardData.types)', '["text/uri-list"]'); >+ shouldBeEqualToString('JSON.stringify(Array.from(event.clipboardData.items).map((item) => {kind: item.kind, type: item.type}))', >+ '[{"kind":"string","type":"text/uri-list"}]'); >+ document.getElementById('container').remove(); >+ finishJSTest(); >+} >+ >+if (window.testRunner && window.internals) { >+ internals.settings.setCustomPasteboardDataEnabled(true); >+ runTest(); >+} >+ >+</script> >+<script src="../../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/editing/pasteboard/data-transfer-get-data-on-paste-custom-expected.txt b/LayoutTests/editing/pasteboard/data-transfer-get-data-on-paste-custom-expected.txt >index 8607a4a4252cfca662e802b6a18a1826426936ad..bacb4aadb90412a024a61b8710d29d606036d6b3 100644 >--- a/LayoutTests/editing/pasteboard/data-transfer-get-data-on-paste-custom-expected.txt >+++ b/LayoutTests/editing/pasteboard/data-transfer-get-data-on-paste-custom-expected.txt >@@ -5,7 +5,7 @@ Rich text > "foo/ð¤ðð": "ð¤ðð", > "text/html": "<b>å¹´å¹´å¹´</b>", > "bar/××§×ר ××©× ×¢×ר×ת": "<i>××§×ר ××©× ×¢×ר×ת</i>", >- "text/uri-list": "https://www.apple.com/", >+ "text/uri-list": "https://www.apple.com", > "baz/å¹´å¹´å¹´": "https://www.webkit.org", > "text/rtf": "AAAAAAAAAAA" > } >diff --git a/LayoutTests/editing/pasteboard/data-transfer-is-unique-for-dragenter-and-dragleave-expected.txt b/LayoutTests/editing/pasteboard/data-transfer-is-unique-for-dragenter-and-dragleave-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..7c1524f9a938bffcb593748f352a73d040cbb227 >--- /dev/null >+++ b/LayoutTests/editing/pasteboard/data-transfer-is-unique-for-dragenter-and-dragleave-expected.txt >@@ -0,0 +1,9 @@ >+PASS dragstart for source had an unique dataTransfer object >+PASS dragenter for passover had an unique dataTransfer object >+PASS dragenter for destination had an unique dataTransfer object >+PASS dragleave for passover had an unique dataTransfer object >+PASS dragleave for destination had an unique dataTransfer object >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/editing/pasteboard/data-transfer-is-unique-for-dragenter-and-dragleave.html b/LayoutTests/editing/pasteboard/data-transfer-is-unique-for-dragenter-and-dragleave.html >new file mode 100644 >index 0000000000000000000000000000000000000000..eb2442760ba3d01c305ccfc085e418f6c007df31 >--- /dev/null >+++ b/LayoutTests/editing/pasteboard/data-transfer-is-unique-for-dragenter-and-dragleave.html >@@ -0,0 +1,68 @@ >+<!DOCTYPE html> >+<html> >+<body> >+<style> >+#container > div { width: 100px; height: 50px; margin: 0px; } >+</style> >+<p id="description"></p> >+<div id="container"> >+<div draggable="true" id="source" style="background: #9cf">Drag this</div> >+<div id="passover" style="background: #ff9">Drag over here</div> >+<div id="destination" style="background: #fc9">And drop here</div> >+</div> >+<div id="console"></div> >+<script src="../../resources/js-test-pre.js"></script> >+<script> >+ >+var jsTestIsAsync = true; >+ >+source.addEventListener("dragstart", (event) => { >+ event.dataTransfer.effectAllowed = 'copy'; >+ event.dataTransfer.setData('text', 'hello, world'); >+ dataTransferMap.clear(); >+ testUniquenessAndAdd(event.dataTransfer, 'source', 'dragstart'); >+}); >+ >+const dataTransferMap = new Map; >+function testUniquenessAndAdd(dataTransfer, label, eventType) { >+ const existingEntry = dataTransferMap.get(dataTransfer); >+ if (existingEntry) { >+ testFailed(`${eventType} for ${label} had the same dataTransfer object as ${existingEntry.eventType} for ${existingEntry.label}`); >+ return; >+ } >+ testPassed(`${eventType} for ${label} had an unique dataTransfer object`); >+ dataTransferMap.set(dataTransfer, {label, eventType}); >+} >+ >+passover.addEventListener("dragenter", (event) => { >+ testUniquenessAndAdd(event.dataTransfer, 'passover', 'dragenter'); >+}); >+passover.addEventListener("dragleave", (event) => { >+ testUniquenessAndAdd(event.dataTransfer, 'passover', 'dragleave'); >+}); >+destination.addEventListener("dragenter", (event) => { >+ testUniquenessAndAdd(event.dataTransfer, 'destination', 'dragenter'); >+}); >+destination.addEventListener("dragleave", (event) => { >+ testUniquenessAndAdd(event.dataTransfer, 'destination', 'dragleave'); >+}); >+destination.addEventListener("drop", (event) => { >+ testUniquenessAndAdd(event.dataTransfer, 'destination', 'drop'); >+ finishJSTest(); >+}); >+ >+if (window.eventSender) { >+ eventSender.mouseMoveTo(source.offsetLeft + 10, source.offsetTop + 10); >+ eventSender.mouseDown(); >+ eventSender.leapForward(500); >+ eventSender.mouseMoveTo(passover.offsetLeft + 10, passover.offsetTop + 10); >+ eventSender.leapForward(100); >+ eventSender.mouseMoveTo(destination.offsetLeft + 10, destination.offsetTop + 10); >+ eventSender.mouseUp(); >+ document.getElementById('container').remove(); >+} >+ >+</script> >+<script src="../../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/editing/pasteboard/data-transfer-set-data-ignore-copied-walformed-url-in-null-expected.txt b/LayoutTests/editing/pasteboard/data-transfer-set-data-ignore-copied-walformed-url-in-null-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..31bc32eb5c0cc4fd07a49fe7780d97584f97e845 >--- /dev/null >+++ b/LayoutTests/editing/pasteboard/data-transfer-set-data-ignore-copied-walformed-url-in-null-expected.txt >@@ -0,0 +1,15 @@ >+This tests calling setData with a malformed URL in a null origin document. The malformed value should not be readable in another document >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS urlReadInSameDocument is "hello, world" >+PASS JSON.stringify(typesInSameDocument) is "[\"text/uri-list\"]" >+PASS JSON.stringify(itemsInSameDocument) is "[{\"kind\":\"string\",\"type\":\"text/uri-list\"}]" >+PASS event.clipboardData.getData("url") is "" >+PASS JSON.stringify(event.clipboardData.types) is "[]" >+PASS JSON.stringify(Array.from(event.clipboardData.items).map((item) => ({kind: item.kind, type: item.type}))) is "[]" >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/editing/pasteboard/data-transfer-set-data-ignore-copied-walformed-url-in-null-origin-expected.txt b/LayoutTests/editing/pasteboard/data-transfer-set-data-ignore-copied-walformed-url-in-null-origin-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..31bc32eb5c0cc4fd07a49fe7780d97584f97e845 >--- /dev/null >+++ b/LayoutTests/editing/pasteboard/data-transfer-set-data-ignore-copied-walformed-url-in-null-origin-expected.txt >@@ -0,0 +1,15 @@ >+This tests calling setData with a malformed URL in a null origin document. The malformed value should not be readable in another document >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS urlReadInSameDocument is "hello, world" >+PASS JSON.stringify(typesInSameDocument) is "[\"text/uri-list\"]" >+PASS JSON.stringify(itemsInSameDocument) is "[{\"kind\":\"string\",\"type\":\"text/uri-list\"}]" >+PASS event.clipboardData.getData("url") is "" >+PASS JSON.stringify(event.clipboardData.types) is "[]" >+PASS JSON.stringify(Array.from(event.clipboardData.items).map((item) => ({kind: item.kind, type: item.type}))) is "[]" >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/editing/pasteboard/data-transfer-set-data-ignore-copied-walformed-url-in-null-origin.html b/LayoutTests/editing/pasteboard/data-transfer-set-data-ignore-copied-walformed-url-in-null-origin.html >new file mode 100644 >index 0000000000000000000000000000000000000000..735fcf3f3f9c21cbba23f4c28e38480c1f2ff6ba >--- /dev/null >+++ b/LayoutTests/editing/pasteboard/data-transfer-set-data-ignore-copied-walformed-url-in-null-origin.html >@@ -0,0 +1,72 @@ >+<!DOCTYPE html> >+<html> >+<body> >+<script src="../../resources/js-test-pre.js"></script> >+<script> >+ >+description('This tests calling setData with a malformed URL in a null origin document. The malformed value should not be readable in another document'); >+jsTestIsAsync = true; >+ >+if (window.internals) >+ internals.settings.setCustomPasteboardDataEnabled(true); >+ >+const iframe = document.createElement('iframe'); >+document.body.appendChild(iframe); >+iframe.src = `data:text/html;charset=utf-8,<!DOCTYPE html> >+<button onclick="runTest()">1. Copy</button> >+<div id="source" oncopy="copy(event)" contenteditable>some text</div> >+<div id="destination" onpaste="paste(event)" contenteditable>2. Paste here</div> >+<script> >+ >+function copy(event) { >+ event.clipboardData.setData('url', 'hello, world'); >+ event.preventDefault(); >+} >+ >+function paste(event) { >+ parent.postMessage({ >+ url: event.clipboardData.getData('url'), >+ types: event.clipboardData.types, >+ items: Array.from(event.clipboardData.items).map((item) => ({kind: item.kind, type: item.type})), >+ }, '*'); >+} >+ >+function runTest() { >+ document.getElementById('source').focus(); >+ document.execCommand('selectAll'); >+ document.execCommand('copy'); >+ document.getElementById('destination').focus(); >+ if (window.testRunner) >+ document.execCommand('paste'); >+} >+ >+if (window.testRunner) >+ runTest(); >+ >+</scri` + 'pt>'; >+ >+onmessage = (event) => { >+ urlReadInSameDocument = event.data.url; >+ shouldBeEqualToString('urlReadInSameDocument', 'hello, world'); >+ typesInSameDocument = event.data.types; >+ shouldBeEqualToString('JSON.stringify(typesInSameDocument)', '["text/uri-list"]'); >+ itemsInSameDocument = event.data.items; >+ shouldBeEqualToString('JSON.stringify(itemsInSameDocument)', '[{"kind":"string","type":"text/uri-list"}]'); >+ document.getElementById('destination').focus(); >+ if (window.testRunner) >+ document.execCommand('paste'); >+} >+ >+function doPaste(event) { >+ shouldBeEqualToString('event.clipboardData.getData("url")', ''); >+ shouldBeEqualToString('JSON.stringify(event.clipboardData.types)', '[]'); >+ shouldBeEqualToString('JSON.stringify(Array.from(event.clipboardData.items).map((item) => ({kind: item.kind, type: item.type})))', '[]'); >+ document.getElementById('destination').remove(); >+ finishJSTest(); >+} >+ >+</script> >+<div id="destination" onpaste="doPaste(event)" contenteditable>3. Paste here</div> >+<script src="../../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/editing/pasteboard/data-transfer-set-data-sanitlize-url-when-copying-in-null-origin-expected.txt b/LayoutTests/editing/pasteboard/data-transfer-set-data-sanitlize-url-when-copying-in-null-origin-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..6f11d5ee06fca59f78efe9a2d2222490e2d33c8f >--- /dev/null >+++ b/LayoutTests/editing/pasteboard/data-transfer-set-data-sanitlize-url-when-copying-in-null-origin-expected.txt >@@ -0,0 +1,15 @@ >+This tests calling setData with a malformed URL in a null origin document. The malformed value should not be readable in another document >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS urlReadInSameDocument is "http://webkit.org/b/ð¤?x=8 + 6<" >+PASS JSON.stringify(typesInSameDocument) is "[\"text/uri-list\"]" >+PASS JSON.stringify(itemsInSameDocument) is "[{\"kind\":\"string\",\"type\":\"text/uri-list\"}]" >+PASS event.clipboardData.getData("url") is "http://webkit.org/b/%F0%9F%A4%94?x=8%20+%206%3C" >+PASS JSON.stringify(event.clipboardData.types) is "[\"text/uri-list\"]" >+PASS JSON.stringify(Array.from(event.clipboardData.items).map((item) => ({kind: item.kind, type: item.type}))) is "[{\"kind\":\"string\",\"type\":\"text/uri-list\"}]" >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/editing/pasteboard/data-transfer-set-data-sanitlize-url-when-copying-in-null-origin.html b/LayoutTests/editing/pasteboard/data-transfer-set-data-sanitlize-url-when-copying-in-null-origin.html >new file mode 100644 >index 0000000000000000000000000000000000000000..fa8b85acce7efcb3a0b2b3ee538e9af1f4b924da >--- /dev/null >+++ b/LayoutTests/editing/pasteboard/data-transfer-set-data-sanitlize-url-when-copying-in-null-origin.html >@@ -0,0 +1,76 @@ >+<!DOCTYPE html> >+<html> >+<body> >+<script src="../../resources/js-test-pre.js"></script> >+<script> >+ >+description('This tests calling setData with a malformed URL in a null origin document. The malformed value should not be readable in another document'); >+jsTestIsAsync = true; >+ >+if (window.internals) >+ internals.settings.setCustomPasteboardDataEnabled(true); >+ >+const iframe = document.createElement('iframe'); >+document.body.appendChild(iframe); >+iframe.src = `data:text/html;charset=utf-8,<!DOCTYPE html> >+<button onclick="runTest()">1. Copy</button> >+<div id="source" oncopy="copy(event)" contenteditable>http://webkit.org/b/🤔?x=8 + 6<</div> >+<div id="destination" onpaste="paste(event)" contenteditable>2. Paste here</div> >+<script> >+ >+const originalURL = document.getElementById('source').textContent; >+function copy(event) { >+ event.clipboardData.setData('url', originalURL); >+ event.preventDefault(); >+} >+ >+function paste(event) { >+ parent.postMessage({ >+ originalURL, >+ url: event.clipboardData.getData('url'), >+ types: event.clipboardData.types, >+ items: Array.from(event.clipboardData.items).map((item) => ({kind: item.kind, type: item.type})), >+ }, '*'); >+} >+ >+function runTest() { >+ document.getElementById('source').focus(); >+ document.execCommand('selectAll'); >+ document.execCommand('copy'); >+ document.getElementById('destination').focus(); >+ if (window.testRunner) >+ document.execCommand('paste'); >+} >+ >+if (window.testRunner) >+ runTest(); >+ >+</scri` + 'pt>'; >+ >+onmessage = (event) => { >+ originalURL = event.data.originalURL; >+ urlReadInSameDocument = event.data.url; >+ shouldBeEqualToString('urlReadInSameDocument', originalURL); >+ typesInSameDocument = event.data.types; >+ shouldBeEqualToString('JSON.stringify(typesInSameDocument)', '["text/uri-list"]'); >+ itemsInSameDocument = event.data.items; >+ shouldBeEqualToString('JSON.stringify(itemsInSameDocument)', '[{"kind":"string","type":"text/uri-list"}]'); >+ document.getElementById('destination').focus(); >+ if (window.testRunner) >+ document.execCommand('paste'); >+} >+ >+function doPaste(event) { >+ shouldBeEqualToString('event.clipboardData.getData("url")', (new URL(originalURL)).href); >+ shouldBeEqualToString('JSON.stringify(event.clipboardData.types)', '["text/uri-list"]'); >+ shouldBeEqualToString('JSON.stringify(Array.from(event.clipboardData.items).map((item) => ({kind: item.kind, type: item.type})))', >+ '[{"kind":"string","type":"text/uri-list"}]'); >+ document.getElementById('destination').remove(); >+ finishJSTest(); >+} >+ >+</script> >+<div id="destination" onpaste="doPaste(event)" contenteditable>3. Paste here</div> >+<script src="../../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/editing/pasteboard/data-transfer-set-data-sanitlize-url-when-dragging-in-null-origin-expected.txt b/LayoutTests/editing/pasteboard/data-transfer-set-data-sanitlize-url-when-dragging-in-null-origin-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..6d31e3617c863e5dfda867dbcaee6ece231d3400 >--- /dev/null >+++ b/LayoutTests/editing/pasteboard/data-transfer-set-data-sanitlize-url-when-dragging-in-null-origin-expected.txt >@@ -0,0 +1,38 @@ >+This tests calling setData to set a URL in a null origin document. The URL should be sanitized when reading in another document. >+To manually test, drag and drop the "1. Drag this" above to "2. Drop here" and "3. Drop here". >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+dragstart in the null origin document: >+PASS urlReadInSameDocument is "http://webkit.org/b/ð¤?x=8 + 6" >+PASS JSON.stringify(typesInSameDocument) is "[\"text/uri-list\"]" >+PASS JSON.stringify(itemsInSameDocument) is "[{\"kind\":\"string\",\"type\":\"text/uri-list\"}]" >+ >+dragover in the null origin document: >+PASS urlReadInSameDocument is "" >+PASS JSON.stringify(typesInSameDocument) is "[\"text/uri-list\"]" >+PASS JSON.stringify(itemsInSameDocument) is "[{\"kind\":\"string\",\"type\":\"text/uri-list\"}]" >+ >+drop in the null origin document: >+PASS urlReadInSameDocument is "http://webkit.org/b/ð¤?x=8 + 6" >+PASS JSON.stringify(typesInSameDocument) is "[\"text/uri-list\"]" >+PASS JSON.stringify(itemsInSameDocument) is "[{\"kind\":\"string\",\"type\":\"text/uri-list\"}]" >+ >+dragstart in the null origin document: >+PASS urlReadInSameDocument is "http://webkit.org/b/ð¤?x=8 + 6" >+PASS JSON.stringify(typesInSameDocument) is "[\"text/uri-list\"]" >+PASS JSON.stringify(itemsInSameDocument) is "[{\"kind\":\"string\",\"type\":\"text/uri-list\"}]" >+ >+dragover in the file URL document: >+PASS urlReadInSameDocument is "" >+PASS JSON.stringify(typesInSameDocument) is "[\"text/uri-list\"]" >+PASS JSON.stringify(itemsInSameDocument) is "[{\"kind\":\"string\",\"type\":\"text/uri-list\"}]" >+ >+drop in the file URL document: >+PASS urlReadInSameDocument is "http://webkit.org/b/%F0%9F%A4%94?x=8%20+%206" >+PASS JSON.stringify(typesInSameDocument) is "[\"text/uri-list\"]" >+PASS JSON.stringify(itemsInSameDocument) is "[{\"kind\":\"string\",\"type\":\"text/uri-list\"}]" >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/editing/pasteboard/data-transfer-set-data-sanitlize-url-when-dragging-in-null-origin.html b/LayoutTests/editing/pasteboard/data-transfer-set-data-sanitlize-url-when-dragging-in-null-origin.html >new file mode 100644 >index 0000000000000000000000000000000000000000..fb71280fc55ffaeec51c5d86da13b1007a5172c2 >--- /dev/null >+++ b/LayoutTests/editing/pasteboard/data-transfer-set-data-sanitlize-url-when-dragging-in-null-origin.html >@@ -0,0 +1,157 @@ >+<!DOCTYPE html> >+<html> >+<body> >+<div id="container"> >+<div id="destination">3. Drop here</div> >+</div> >+<div id="description"></div> >+<div id="console"></div> >+<script src="../../resources/js-test-pre.js"></script> >+<script> >+ >+description('This tests calling setData to set a URL in a null origin document. The URL should be sanitized when reading in another document.<br>' >+ + 'To manually test, drag and drop the "1. Drag this" above to "2. Drop here" and "3. Drop here".'); >+jsTestIsAsync = true; >+ >+if (window.internals) >+ internals.settings.setCustomPasteboardDataEnabled(true); >+ >+const iframe = document.createElement('iframe'); >+const destination = document.getElementById('destination'); >+document.getElementById('container').prepend(iframe); >+ >+iframe.src = `data:text/html;charset=utf-8,<!DOCTYPE html> >+<div id="source" draggable="true" data-value="http://webkit.org/b/🤔?x=8 + 6">1. Drag this</div> >+<div id="destination" onpaste="paste(event)">2. Drop here</div> >+<script> >+ >+const source = document.getElementById('source'); >+const destination = document.getElementById('destination'); >+const originalURL = source.dataset.value; >+parent.postMessage({kind: 'originalURL', originalURL}, '*'); >+ >+function postContent(kind, dataTransfer) { >+ parent.postMessage({ >+ kind, >+ documentLabel: 'the null origin document', >+ url: dataTransfer.getData('url'), >+ types: dataTransfer.types, >+ items: Array.from(dataTransfer.items).map((item) => ({kind: item.kind, type: item.type})), >+ }, '*'); >+} >+ >+let postDragOver; >+source.addEventListener("dragstart", (event) => { >+ postDragOver = false; >+ event.dataTransfer.setData('url', originalURL); >+ postContent('dragstart', event.dataTransfer); >+}); >+destination.addEventListener("dragover", (event) => { >+ event.preventDefault(); >+ if (postDragOver) >+ return; >+ postDragOver = true; >+ postContent('dragover', event.dataTransfer); >+}); >+destination.addEventListener("drop", (event) => { >+ postContent('drop', event.dataTransfer); >+ destination.remove(); >+ top.postMessage({kind: 'secondDrop'}, '*'); >+}); >+ >+if (window.eventSender) { >+ const iframeOffset = {x: 10, y: 10}; >+ eventSender.mouseMoveTo(iframeOffset.x + source.offsetLeft + 5, iframeOffset.y + source.offsetTop + 5); >+ eventSender.mouseDown(); >+ eventSender.leapForward(500); >+ eventSender.mouseMoveTo(iframeOffset.x + destination.offsetLeft + 5, iframeOffset.y + destination.offsetTop + 5); >+ eventSender.mouseUp(); >+} >+ >+</scri` + 'pt>'; >+ >+onmessage = (event) => { >+ const kind = event.data.kind; >+ if (kind == 'originalURL') { >+ originalURL = event.data.originalURL; >+ return; >+ } >+ if (kind == 'secondDrop') >+ return doSecondDrop(event.data.postContent); >+ debug(`${kind} in ${event.data.documentLabel}:`); >+ switch (kind) { >+ case 'dragstart': >+ urlReadInSameDocument = event.data.url; >+ shouldBeEqualToString('urlReadInSameDocument', originalURL); >+ typesInSameDocument = event.data.types; >+ shouldBeEqualToString('JSON.stringify(typesInSameDocument)', '["text/uri-list"]'); >+ itemsInSameDocument = event.data.items; >+ shouldBeEqualToString('JSON.stringify(itemsInSameDocument)', '[{"kind":"string","type":"text/uri-list"}]'); >+ break; >+ case 'dragover': >+ urlReadInSameDocument = event.data.url; >+ shouldBeEqualToString('urlReadInSameDocument', ''); >+ typesInSameDocument = event.data.types; >+ shouldBeEqualToString('JSON.stringify(typesInSameDocument)', '["text/uri-list"]'); >+ itemsInSameDocument = event.data.items; >+ shouldBeEqualToString('JSON.stringify(itemsInSameDocument)', '[{"kind":"string","type":"text/uri-list"}]'); >+ break; >+ case 'drop': >+ urlReadInSameDocument = event.data.url; >+ shouldBeEqualToString('urlReadInSameDocument', event.data.documentLabel.includes('null') ? originalURL : (new URL(originalURL)).href); >+ typesInSameDocument = event.data.types; >+ shouldBeEqualToString('JSON.stringify(typesInSameDocument)', '["text/uri-list"]'); >+ itemsInSameDocument = event.data.items; >+ shouldBeEqualToString('JSON.stringify(itemsInSameDocument)', '[{"kind":"string","type":"text/uri-list"}]'); >+ if (!event.data.documentLabel.includes('null')) { >+ document.getElementById('container').remove(); >+ finishJSTest(); >+ } >+ break; >+ } >+ debug(''); >+} >+ >+function postContent(kind, dataTransfer) { >+ window.postMessage({ >+ kind, >+ documentLabel: 'the file URL document', >+ url: dataTransfer.getData('url'), >+ types: dataTransfer.types, >+ items: Array.from(dataTransfer.items).map((item) => ({kind: item.kind, type: item.type})), >+ }, '*'); >+} >+ >+let postDragOver = false; >+destination.addEventListener("dragover", (event) => { >+ event.preventDefault(); >+ if (postDragOver) >+ return; >+ postDragOver = true; >+ postContent('dragover', event.dataTransfer); >+}); >+destination.addEventListener("drop", (event) => { >+ postContent('drop', event.dataTransfer); >+}); >+ >+function doSecondDrop(postContent) { >+ postDragOver = false; >+ if (!window.eventSender) >+ return; >+ >+ eventSender.leapForward(500); >+ eventSender.mouseMoveTo(iframe.offsetLeft + 10, iframe.offsetTop + 10); >+ eventSender.mouseDown(); >+ eventSender.leapForward(500); >+ >+ const destinationRect = destination.getBoundingClientRect(); >+ eventSender.mouseMoveTo(destination.offsetLeft + 5, destination.offsetTop + 5); >+ eventSender.mouseUp(); >+} >+ >+setTimeout(finishJSTest, 3000); >+ >+</script> >+<script src="../../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/http/tests/security/clipboard/copy-paste-url-across-origin-sanitizes-url-expected.txt b/LayoutTests/http/tests/security/clipboard/copy-paste-url-across-origin-sanitizes-url-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..2db3c68c08d6e9f663655bad02dbe80563147479 >--- /dev/null >+++ b/LayoutTests/http/tests/security/clipboard/copy-paste-url-across-origin-sanitizes-url-expected.txt >@@ -0,0 +1,15 @@ >+This tests calling setData with a malformed URL in a null origin document. The malformed value should not be readable in another document >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS urlReadInSameDocument is "http://webkit.org/b/ð¤?x=8 + 6" >+PASS JSON.stringify(typesInSameDocument) is "[\"text/uri-list\"]" >+PASS JSON.stringify(itemsInSameDocument) is "[{\"kind\":\"string\",\"type\":\"text/uri-list\"}]" >+PASS event.clipboardData.getData("url") is "http://webkit.org/b/%F0%9F%A4%94?x=8%20+%206" >+PASS JSON.stringify(event.clipboardData.types) is "[\"text/uri-list\"]" >+PASS JSON.stringify(Array.from(event.clipboardData.items).map((item) => ({kind: item.kind, type: item.type}))) is "[{\"kind\":\"string\",\"type\":\"text/uri-list\"}]" >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/http/tests/security/clipboard/copy-paste-url-across-origin-sanitizes-url.html b/LayoutTests/http/tests/security/clipboard/copy-paste-url-across-origin-sanitizes-url.html >new file mode 100644 >index 0000000000000000000000000000000000000000..3c9ab5860eeb8405ea9bba039dfa2828173c0f03 >--- /dev/null >+++ b/LayoutTests/http/tests/security/clipboard/copy-paste-url-across-origin-sanitizes-url.html >@@ -0,0 +1,42 @@ >+<!DOCTYPE html> >+<html> >+<body> >+<script src="/resources/js-test-pre.js"></script> >+<script> >+ >+description('This tests calling setData with a malformed URL in a null origin document. The malformed value should not be readable in another document'); >+jsTestIsAsync = true; >+ >+if (window.internals) >+ internals.settings.setCustomPasteboardDataEnabled(true); >+ >+onmessage = (event) => { >+ originalURL = event.data.originalURL; >+ urlReadInSameDocument = event.data.url; >+ shouldBeEqualToString('urlReadInSameDocument', originalURL); >+ typesInSameDocument = event.data.types; >+ shouldBeEqualToString('JSON.stringify(typesInSameDocument)', '["text/uri-list"]'); >+ itemsInSameDocument = event.data.items; >+ shouldBeEqualToString('JSON.stringify(itemsInSameDocument)', '[{"kind":"string","type":"text/uri-list"}]'); >+ document.getElementById('destination').focus(); >+ if (window.testRunner) >+ document.execCommand('paste'); >+} >+ >+function doPaste(event) { >+ shouldBeEqualToString('event.clipboardData.getData("url")', (new URL(originalURL)).href); >+ shouldBeEqualToString('JSON.stringify(event.clipboardData.types)', '["text/uri-list"]'); >+ shouldBeEqualToString('JSON.stringify(Array.from(event.clipboardData.items).map((item) => ({kind: item.kind, type: item.type})))', >+ '[{"kind":"string","type":"text/uri-list"}]'); >+ document.getElementById('destination').remove(); >+ finishJSTest(); >+} >+ >+setTimeout(() => finishJSTest(), 3000); >+ >+</script> >+<iframe src="http://localhost:8000/security/clipboard/resources/copy.html"></iframe> >+<div id="destination" onpaste="doPaste(event)" contenteditable>3. Paste here</div> >+<script src="/resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/http/tests/security/clipboard/resources/copy.html b/LayoutTests/http/tests/security/clipboard/resources/copy.html >new file mode 100644 >index 0000000000000000000000000000000000000000..a9e58cb9e6b480faccb5b9b586090cca65cf86bd >--- /dev/null >+++ b/LayoutTests/http/tests/security/clipboard/resources/copy.html >@@ -0,0 +1,38 @@ >+<!DOCTYPE html> >+<html> >+<body> >+<button onclick="runTest()">1. Copy</button> >+<div id="source" oncopy="copy(event)" contenteditable>http://webkit.org/b/🤔?x=8 + 6</div> >+<div id="destination" onpaste="paste(event)" contenteditable>2. Paste here</div> >+<script> >+ >+const originalURL = document.getElementById('source').textContent; >+function copy(event) { >+ event.clipboardData.setData('url', originalURL); >+ event.preventDefault(); >+} >+ >+function paste(event) { >+ parent.postMessage({ >+ originalURL, >+ url: event.clipboardData.getData('url'), >+ types: event.clipboardData.types, >+ items: Array.from(event.clipboardData.items).map((item) => ({kind: item.kind, type: item.type})), >+ }, '*'); >+} >+ >+function runTest() { >+ document.getElementById('source').focus(); >+ document.execCommand('selectAll'); >+ document.execCommand('copy'); >+ document.getElementById('destination').focus(); >+ if (window.testRunner) >+ document.execCommand('paste'); >+} >+ >+if (window.testRunner) >+ runTest(); >+ >+</script> >+</body> >+</html> >diff --git a/LayoutTests/platform/mac-wk1/TestExpectations b/LayoutTests/platform/mac-wk1/TestExpectations >index 256f765d6d08858f896b23fd441e7c96c424a4e3..159ee627f04778e208575db48abc392a42af7c94 100644 >--- a/LayoutTests/platform/mac-wk1/TestExpectations >+++ b/LayoutTests/platform/mac-wk1/TestExpectations >@@ -11,6 +11,8 @@ editing/pasteboard/data-transfer-get-data-on-drop-custom.html [ Pass ] > editing/pasteboard/data-transfer-get-data-on-drop-plain-text.html [ Pass ] > editing/pasteboard/data-transfer-get-data-on-drop-rich-text.html [ Pass ] > editing/pasteboard/data-transfer-get-data-on-drop-url.html [ Pass ] >+editing/pasteboard/data-transfer-is-unique-for-dragenter-and-dragleave.html [ Pass ] >+editing/pasteboard/data-transfer-set-data-sanitlize-url-when-dragging-in-null-origin.html [ Pass ] > editing/pasteboard/drag-end-crash-accessing-item-list.html [ Pass ] > editing/pasteboard/data-transfer-item-list-add-file-on-drag.html [ Pass ] >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 178060
:
323120
|
323123
|
323141
|
323146
|
323147
|
323149
|
323263
|
323281
|
323285
|
323390
|
323391
|
323393