WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Fix Win/GTK/WPE
bug-203168-20191019175826.patch (text/plain), 47.42 KB, created by
Wenson Hsieh
on 2019-10-19 17:58:27 PDT
(
hide
)
Description:
Fix Win/GTK/WPE
Filename:
MIME Type:
Creator:
Wenson Hsieh
Created:
2019-10-19 17:58:27 PDT
Size:
47.42 KB
patch
obsolete
>Subversion Revision: 251317 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index c5436d7482a4fd0e88f86fe5d4cdaef6c2fa0f67..b8c157ac6427d7f0e1c225f09ffed7333874a509 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,53 @@ >+2019-10-19 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ [Clipboard API] Implement ClipboardItem.getType() for platform clipboard items >+ https://bugs.webkit.org/show_bug.cgi?id=203168 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This patch completes support for ClipboardItem.getType(). >+ >+ Tests: editing/async-clipboard/clipboard-change-data-while-getting-type.html >+ editing/async-clipboard/clipboard-item-get-type-basic.html >+ ClipboardTests.ReadMultipleItems >+ >+ * Modules/async-clipboard/Clipboard.cpp: >+ (WebCore::Clipboard::getType): >+ >+ Implement getType(). If the given clipboard item is being tracked as one of the active clipboard items, then >+ allow it to read data from the platform pasteboard. We use existing pasteboard reading methods and classes >+ (PasteboardPlainText and WebContentMarkupReader) to ask the platform pasteboard for text and markup data, >+ respectively, and go through readURL() for "text/uri-list". >+ >+ Before exposing any data to the page, we additionally check that the change count of the pasteboard is still >+ what we started with when setting up the current session. If this is not the case, we reject the promise and >+ immediately clear out the session. >+ >+ (WebCore::Clipboard::activePasteboard): >+ * Modules/async-clipboard/Clipboard.h: >+ * dom/DataTransfer.h: >+ >+ Drive-by tweak: make the WebContentReadingPolicy enum class narrower. >+ >+ * platform/Pasteboard.h: >+ >+ Add an enum flag for allowing or ignoring the platform URL type when reading plain text from the platform >+ pasteboard. We use this in Clipboard::getType() to ignore URLs on the platform pasteboard when plain text, since >+ the plain text reader would otherwise prefer URLs over plain text by default, and read the URL type instead of >+ the plain text type. >+ >+ * platform/StaticPasteboard.h: >+ * platform/gtk/PasteboardGtk.cpp: >+ (WebCore::Pasteboard::read): >+ * platform/ios/PasteboardIOS.mm: >+ (WebCore::Pasteboard::read): >+ * platform/libwpe/PasteboardLibWPE.cpp: >+ (WebCore::Pasteboard::read): >+ * platform/mac/PasteboardMac.mm: >+ (WebCore::Pasteboard::read): >+ * platform/win/PasteboardWin.cpp: >+ (WebCore::Pasteboard::read): >+ > 2019-10-18 Wenson Hsieh <wenson_hsieh@apple.com> > > [Clipboard API] Refactor Pasteboard::read() to take an optional item index >diff --git a/Source/WebCore/Modules/async-clipboard/Clipboard.cpp b/Source/WebCore/Modules/async-clipboard/Clipboard.cpp >index acc5814066cd2a2e8e0c5d55407bfa584ed2cc27..9b949e5c7b9cfa2e1bfa62602be46ad67b2d41b4 100644 >--- a/Source/WebCore/Modules/async-clipboard/Clipboard.cpp >+++ b/Source/WebCore/Modules/async-clipboard/Clipboard.cpp >@@ -34,6 +34,8 @@ > #include "JSDOMPromiseDeferred.h" > #include "Navigator.h" > #include "Pasteboard.h" >+#include "SharedBuffer.h" >+#include "WebContentReader.h" > #include <wtf/IsoMallocInlines.h> > > namespace WebCore { >@@ -126,9 +128,65 @@ void Clipboard::read(Ref<DeferredPromise>&& promise) > > void Clipboard::getType(ClipboardItem& item, const String& type, Ref<DeferredPromise>&& promise) > { >- UNUSED_PARAM(item); >- UNUSED_PARAM(type); >- promise->reject(NotSupportedError); >+ if (!m_activeSession) { >+ promise->reject(NotAllowedError); >+ return; >+ } >+ >+ auto frame = makeRefPtr(this->frame()); >+ if (!frame) { >+ m_activeSession = WTF::nullopt; >+ promise->reject(NotAllowedError); >+ return; >+ } >+ >+ auto itemIndex = m_activeSession->items.findMatching([&] (auto& activeItem) { >+ return activeItem.ptr() == &item; >+ }); >+ >+ if (itemIndex == notFound) { >+ m_activeSession = WTF::nullopt; >+ promise->reject(NotAllowedError); >+ return; >+ } >+ >+ if (!item.types().contains(type)) { >+ promise->reject(NotAllowedError); >+ return; >+ } >+ >+ String resultAsString; >+ >+ if (type == "text/uri-list"_s) { >+ String title; >+ resultAsString = activePasteboard().readURL(itemIndex, title).string(); >+ } >+ >+ if (type == "text/plain"_s) { >+ PasteboardPlainText plainTextReader; >+ activePasteboard().read(plainTextReader, PlainTextURLReadingPolicy::IgnoreURL, itemIndex); >+ resultAsString = WTFMove(plainTextReader.text); >+ } >+ >+ if (type == "text/html"_s) { >+ WebContentMarkupReader markupReader { *frame }; >+ activePasteboard().read(markupReader, WebContentReadingPolicy::OnlyRichTextTypes, itemIndex); >+ resultAsString = WTFMove(markupReader.markup); >+ } >+ >+ // FIXME: Support reading "image/png" as well as custom data. >+ // FIXME: Instead of checking changeCount here, we should send the changeCount over to the UI process to be vetted >+ // when attempting to read the data in the first place. >+ if (m_activeSession->changeCount != activePasteboard().changeCount()) { >+ m_activeSession = WTF::nullopt; >+ promise->reject(NotAllowedError); >+ return; >+ } >+ >+ if (!resultAsString.isNull()) >+ promise->resolve<IDLInterface<Blob>>(ClipboardItem::blobFromString(resultAsString, type)); >+ else >+ promise->reject(NotAllowedError); > } > > void Clipboard::write(const Vector<RefPtr<ClipboardItem>>& items, Ref<DeferredPromise>&& promise) >@@ -142,4 +200,11 @@ Frame* Clipboard::frame() const > return m_navigator ? m_navigator->frame() : nullptr; > } > >+Pasteboard& Clipboard::activePasteboard() >+{ >+ ASSERT(m_activeSession); >+ ASSERT(m_activeSession->pasteboard); >+ return *m_activeSession->pasteboard; >+} >+ > } >diff --git a/Source/WebCore/Modules/async-clipboard/Clipboard.h b/Source/WebCore/Modules/async-clipboard/Clipboard.h >index 217314bd36e8ee5fe400e8a234a78659926aaeb9..87ae57ac840e77a07e7e91f6013132a03562c14d 100644 >--- a/Source/WebCore/Modules/async-clipboard/Clipboard.h >+++ b/Source/WebCore/Modules/async-clipboard/Clipboard.h >@@ -73,6 +73,8 @@ private: > void refEventTarget() final { ref(); } > void derefEventTarget() final { deref(); } > >+ Pasteboard& activePasteboard(); >+ > Optional<Session> m_activeSession; > WeakPtr<Navigator> m_navigator; > }; >diff --git a/Source/WebCore/dom/DataTransfer.h b/Source/WebCore/dom/DataTransfer.h >index 650793cf86b1a1dfd419b9b3335993ad956804f1..e5cfaf856fb2883fc154ddc88b0d7723bc988b04 100644 >--- a/Source/WebCore/dom/DataTransfer.h >+++ b/Source/WebCore/dom/DataTransfer.h >@@ -39,7 +39,7 @@ class Element; > class FileList; > class File; > class Pasteboard; >-enum class WebContentReadingPolicy; >+enum class WebContentReadingPolicy : bool; > > class DataTransfer : public RefCounted<DataTransfer> { > public: >diff --git a/Source/WebCore/platform/Pasteboard.h b/Source/WebCore/platform/Pasteboard.h >index 3141325cb2e24138bc464512b0a429d903ac9024..3bcdd8235c3da1957e13f2494ba9fdc4cde1ecea 100644 >--- a/Source/WebCore/platform/Pasteboard.h >+++ b/Source/WebCore/platform/Pasteboard.h >@@ -65,7 +65,8 @@ class Range; > class SelectionData; > class SharedBuffer; > >-enum class WebContentReadingPolicy { AnyType, OnlyRichTextTypes }; >+enum class PlainTextURLReadingPolicy : bool { IgnoreURL, AllowURL }; >+enum class WebContentReadingPolicy : bool { AnyType, OnlyRichTextTypes }; > enum ShouldSerializeSelectedTextForDataTransfer { DefaultSelectedTextType, IncludeImageAltTextForDataTransfer }; > > // For writing to the pasteboard. Generally sorted with the richest formats on top. >@@ -198,7 +199,7 @@ public: > virtual WEBCORE_EXPORT void clear(); > virtual WEBCORE_EXPORT void clear(const String& type); > >- virtual WEBCORE_EXPORT void read(PasteboardPlainText&, Optional<size_t> itemIndex = WTF::nullopt); >+ virtual WEBCORE_EXPORT void read(PasteboardPlainText&, PlainTextURLReadingPolicy = PlainTextURLReadingPolicy::AllowURL, Optional<size_t> itemIndex = WTF::nullopt); > virtual WEBCORE_EXPORT void read(PasteboardWebContentReader&, WebContentReadingPolicy = WebContentReadingPolicy::AnyType, Optional<size_t> itemIndex = WTF::nullopt); > virtual WEBCORE_EXPORT void read(PasteboardFileReader&); > >diff --git a/Source/WebCore/platform/StaticPasteboard.h b/Source/WebCore/platform/StaticPasteboard.h >index 0e764eac444c6612b88bcda8357fa105ccd39d2b..a6d50d8ab7fa4779d568fa9a8fcb24eaf87d4034 100644 >--- a/Source/WebCore/platform/StaticPasteboard.h >+++ b/Source/WebCore/platform/StaticPasteboard.h >@@ -56,7 +56,7 @@ public: > void clear() final; > void clear(const String& type) final; > >- void read(PasteboardPlainText&, Optional<size_t> = WTF::nullopt) final { } >+ void read(PasteboardPlainText&, PlainTextURLReadingPolicy = PlainTextURLReadingPolicy::AllowURL, Optional<size_t> = WTF::nullopt) final { } > void read(PasteboardWebContentReader&, WebContentReadingPolicy, Optional<size_t> = WTF::nullopt) final { } > > void write(const PasteboardURL&) final { } >diff --git a/Source/WebCore/platform/gtk/PasteboardGtk.cpp b/Source/WebCore/platform/gtk/PasteboardGtk.cpp >index ec97f13cb43be899be9d1dda19b87640b0674cac..206782075dfca62f8f598e1bd4af75265dffa727 100644 >--- a/Source/WebCore/platform/gtk/PasteboardGtk.cpp >+++ b/Source/WebCore/platform/gtk/PasteboardGtk.cpp >@@ -232,7 +232,7 @@ void Pasteboard::setDragImage(DragImage, const IntPoint&) > } > #endif > >-void Pasteboard::read(PasteboardPlainText& text, Optional<size_t>) >+void Pasteboard::read(PasteboardPlainText& text, PlainTextURLReadingPolicy, Optional<size_t>) > { > readFromClipboard(); > text.text = m_selectionData->text(); >diff --git a/Source/WebCore/platform/ios/PasteboardIOS.mm b/Source/WebCore/platform/ios/PasteboardIOS.mm >index f6273f0ae7b3a6a2f09508d14304fbb0badc91bf..ed2f0e3a02bf580f2721c599662827ece1bfa3cc 100644 >--- a/Source/WebCore/platform/ios/PasteboardIOS.mm >+++ b/Source/WebCore/platform/ios/PasteboardIOS.mm >@@ -150,17 +150,24 @@ bool Pasteboard::canSmartReplace() > return true; > } > >-void Pasteboard::read(PasteboardPlainText& text, Optional<size_t> itemIndex) >+void Pasteboard::read(PasteboardPlainText& text, PlainTextURLReadingPolicy allowURL, Optional<size_t> itemIndex) > { > auto itemIndexToQuery = itemIndex.valueOr(0); > > PasteboardStrategy& strategy = *platformStrategies()->pasteboardStrategy(); >- text.text = strategy.readStringFromPasteboard(itemIndexToQuery, kUTTypeURL, m_pasteboardName); >- if (!text.text.isEmpty()) { >- text.isURL = true; >- return; >+ >+ if (allowURL == PlainTextURLReadingPolicy::AllowURL) { >+ text.text = strategy.readStringFromPasteboard(itemIndexToQuery, kUTTypeURL, m_pasteboardName); >+ if (!text.text.isEmpty()) { >+ text.isURL = true; >+ return; >+ } > } > >+ // We ask for the "public.text" representation only as a legacy fallback, in case apps still directly write >+ // plain text for this abstract UTI. In almost all cases, the more correct choice would be to write to >+ // one of the concrete "public.plain-text" representations (e.g. kUTTypeUTF8). In the future, we should >+ // consider removing support for reading plain text from "public.text". > text.text = strategy.readStringFromPasteboard(itemIndexToQuery, kUTTypePlainText, m_pasteboardName); > if (text.text.isEmpty()) > text.text = strategy.readStringFromPasteboard(itemIndexToQuery, kUTTypeText, m_pasteboardName); >diff --git a/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp b/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp >index 7d7800962d256fd96886d910c9b168a6f7e0d626..b630dfb7d6e5aa0d3ff7539cd8d0b92e57e12a54 100644 >--- a/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp >+++ b/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp >@@ -95,7 +95,7 @@ void Pasteboard::clear(const String&) > { > } > >-void Pasteboard::read(PasteboardPlainText& text, Optional<size_t>) >+void Pasteboard::read(PasteboardPlainText& text, PlainTextURLReadingPolicy, Optional<size_t>) > { > text.text = platformStrategies()->pasteboardStrategy()->readStringFromPasteboard(0, "text/plain;charset=utf-8", name()); > } >diff --git a/Source/WebCore/platform/mac/PasteboardMac.mm b/Source/WebCore/platform/mac/PasteboardMac.mm >index a3e4b29b6258f7d9daa952685558ccd4ca43906d..88f44b6263f60139694a63fb0978529e8c279e76 100644 >--- a/Source/WebCore/platform/mac/PasteboardMac.mm >+++ b/Source/WebCore/platform/mac/PasteboardMac.mm >@@ -318,7 +318,7 @@ static RefPtr<SharedBuffer> readBufferAtPreferredItemIndex(const String& type, O > return strategy.bufferForType(type, pasteboardName); > } > >-void Pasteboard::read(PasteboardPlainText& text, Optional<size_t> itemIndex) >+void Pasteboard::read(PasteboardPlainText& text, PlainTextURLReadingPolicy allowURL, Optional<size_t> itemIndex) > { > auto& strategy = *platformStrategies()->pasteboardStrategy(); > >@@ -395,8 +395,10 @@ void Pasteboard::read(PasteboardPlainText& text, Optional<size_t> itemIndex) > } > > // FIXME: The code above looks at the types vector first, but this just gets the string without checking. Why the difference? >- text.text = readStringAtPreferredItemIndex(legacyURLPasteboardType(), itemIndex, strategy, m_pasteboardName); >- text.isURL = !text.text.isNull(); >+ if (allowURL == PlainTextURLReadingPolicy::AllowURL) { >+ text.text = readStringAtPreferredItemIndex(legacyURLPasteboardType(), itemIndex, strategy, m_pasteboardName); >+ text.isURL = !text.text.isNull(); >+ } > } > > void Pasteboard::read(PasteboardWebContentReader& reader, WebContentReadingPolicy policy, Optional<size_t> itemIndex) >diff --git a/Source/WebCore/platform/win/PasteboardWin.cpp b/Source/WebCore/platform/win/PasteboardWin.cpp >index 45a37cac83cb25ae3f1b94dc11c10f0e22603346..28d873c4612dbdce4179c3a38ed0dc0a50b8878a 100644 >--- a/Source/WebCore/platform/win/PasteboardWin.cpp >+++ b/Source/WebCore/platform/win/PasteboardWin.cpp >@@ -789,7 +789,7 @@ bool Pasteboard::canSmartReplace() > return ::IsClipboardFormatAvailable(WebSmartPasteFormat); > } > >-void Pasteboard::read(PasteboardPlainText& text, Optional<size_t>) >+void Pasteboard::read(PasteboardPlainText& text, PlainTextURLReadingPolicy, Optional<size_t>) > { > if (::IsClipboardFormatAvailable(CF_UNICODETEXT) && ::OpenClipboard(m_owner)) { > if (HANDLE cbData = ::GetClipboardData(CF_UNICODETEXT)) { >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 085db8b67088f6bfb4499015fd3287d9f493007a..2f116d4ffec46bb80e37112c22a4578614662a89 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,45 @@ >+2019-10-19 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ [Clipboard API] Implement ClipboardItem.getType() for platform clipboard items >+ https://bugs.webkit.org/show_bug.cgi?id=203168 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add support for the new layout tests, as well as a new API test. >+ >+ * DumpRenderTree/ios/UIScriptControllerIOS.h: >+ * DumpRenderTree/ios/UIScriptControllerIOS.mm: >+ (WTR::UIScriptControllerIOS::copyText): >+ >+ Implement UIScriptController.copyText in WebKit1. This is used in one of the new layout tests, which passes in >+ WebKit1 on macOS and iOS. >+ >+ * DumpRenderTree/mac/DumpRenderTreePasteboard.mm: >+ (-[LocalPasteboard declareTypes:owner:]): >+ (-[LocalPasteboard addTypes:owner:]): >+ (-[LocalPasteboard _addTypesWithoutUpdatingChangeCount:owner:]): >+ >+ Adjust logic when declaring types on the platform pasteboard, such that it behaves more like the platform; when >+ declaring types, even if the owner doesn't change, the change count should still get bumped up by 1. >+ >+ * DumpRenderTree/mac/UIScriptControllerMac.h: >+ * DumpRenderTree/mac/UIScriptControllerMac.mm: >+ (WTR::UIScriptControllerMac::copyText): >+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: >+ * TestWebKitAPI/Tests/WebKitCocoa/ClipboardTests.mm: Added. >+ (-[TestWKWebView readClipboard]): >+ (createWebViewForClipboardTests): >+ (writeMultipleObjectsToPlatformPasteboard): >+ >+ Add a new API test to verify that clipboard items contain the right data when writing multiple items (each with >+ different sets of types) to the platform pasteboard using native APIs. >+ >+ * TestWebKitAPI/Tests/WebKitCocoa/clipboard.html: Added. >+ * WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm: >+ (-[LocalPasteboard declareTypes:owner:]): >+ (-[LocalPasteboard addTypes:owner:]): >+ (-[LocalPasteboard _addTypesWithoutUpdatingChangeCount:owner:]): >+ > 2019-10-18 Jiewen Tan <jiewen_tan@apple.com> > > [WebAuthn] Warn users when no credentials are found >diff --git a/Tools/DumpRenderTree/ios/UIScriptControllerIOS.h b/Tools/DumpRenderTree/ios/UIScriptControllerIOS.h >index 88181e9aac5aba0d8f38ef2e422f897a0816d38f..7a2a2e05c519579255cd48e4b77a7126a80dd3a0 100644 >--- a/Tools/DumpRenderTree/ios/UIScriptControllerIOS.h >+++ b/Tools/DumpRenderTree/ios/UIScriptControllerIOS.h >@@ -49,6 +49,7 @@ public: > double minimumZoomScale() const override; > double maximumZoomScale() const override; > JSObjectRef contentVisibleRect() const override; >+ void copyText(JSStringRef) override; > }; > > } >diff --git a/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm b/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm >index 42a6b956ae431a673b30c3794dc880ee4bc64d60..0006e3d6d5fdbe50a0c922129f1ad54701309741 100644 >--- a/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm >+++ b/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm >@@ -30,6 +30,7 @@ > > #import "DumpRenderTreeBrowserView.h" > #import "UIScriptContext.h" >+#import <JavaScriptCore/OpaqueJSString.h> > #import <WebCore/FloatRect.h> > #import <wtf/MainThread.h> > >@@ -131,6 +132,11 @@ JSObjectRef UIScriptControllerIOS::contentVisibleRect() const > return m_context->objectFromRect(rect); > } > >+void UIScriptControllerIOS::copyText(JSStringRef text) >+{ >+ UIPasteboard.generalPasteboard.string = text->string(); >+} >+ > } > > #endif // PLATFORM(IOS_FAMILY) >diff --git a/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm b/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm >index f9530f4d313a9cac7bd985ae4154ffaac5a6fd87..e87df8b8a1be99c78ff4afe57f8023fb63314b0e 100644 >--- a/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm >+++ b/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm >@@ -123,7 +123,8 @@ - (NSInteger)declareTypes:(NSArray *)newTypes owner:(id)newOwner > _types.clear(); > _data.clear(); > >- return [self addTypes:newTypes owner:newOwner]; >+ [self _addTypesWithoutUpdatingChangeCount:newTypes owner:newOwner]; >+ return ++_changeCount; > } > > static bool isUTI(NSString *type) >@@ -141,17 +142,21 @@ static RetainPtr<CFStringRef> toUTI(NSString *type) > return adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassNSPboardType, (__bridge CFStringRef)type, nullptr)); > } > >-- (NSInteger)addTypes:(NSArray *)newTypes owner:(id)newOwner >+- (NSInteger)addTypes:(NSArray<NSPasteboardType> *)newTypes owner:(id)newOwner > { >- if (_owner != newOwner) { >- _owner = newOwner; >+ auto previousOwner = _owner; >+ [self _addTypesWithoutUpdatingChangeCount:newTypes owner:newOwner]; >+ if (previousOwner != newOwner) > ++_changeCount; >- } >+ return _changeCount; >+} >+ >+- (void)_addTypesWithoutUpdatingChangeCount:(NSArray *)newTypes owner:(id)newOwner >+{ >+ _owner = newOwner; > > for (NSString *type in newTypes) > _types.add(toUTI(type)); >- >- return _changeCount; > } > > - (NSInteger)changeCount >diff --git a/Tools/DumpRenderTree/mac/UIScriptControllerMac.h b/Tools/DumpRenderTree/mac/UIScriptControllerMac.h >index d26407c875afd9471c264d40333337b3c5aa9b27..0e7ec28213462735b3c66ae0f6242271df884263 100644 >--- a/Tools/DumpRenderTree/mac/UIScriptControllerMac.h >+++ b/Tools/DumpRenderTree/mac/UIScriptControllerMac.h >@@ -49,6 +49,7 @@ public: > void toggleCapsLock(JSValueRef) override; > void simulateAccessibilitySettingsChangeNotification(JSValueRef) override; > NSUndoManager *platformUndoManager() const override; >+ void copyText(JSStringRef) override; > }; > > } >diff --git a/Tools/DumpRenderTree/mac/UIScriptControllerMac.mm b/Tools/DumpRenderTree/mac/UIScriptControllerMac.mm >index 7989eb408fdc3f6a245727fc9e7cf0ab5320ac65..996fb92ee3f497962448794859a9c859a1e8daf1 100644 >--- a/Tools/DumpRenderTree/mac/UIScriptControllerMac.mm >+++ b/Tools/DumpRenderTree/mac/UIScriptControllerMac.mm >@@ -31,6 +31,7 @@ > #import <JavaScriptCore/JSContext.h> > #import <JavaScriptCore/JSStringRefCF.h> > #import <JavaScriptCore/JSValue.h> >+#import <JavaScriptCore/OpaqueJSString.h> > #import <WebKit/WebKit.h> > #import <WebKit/WebViewPrivate.h> > >@@ -146,6 +147,13 @@ NSUndoManager *UIScriptControllerMac::platformUndoManager() const > return nil; > } > >+void UIScriptControllerMac::copyText(JSStringRef text) >+{ >+ NSPasteboard *pasteboard = NSPasteboard.generalPasteboard; >+ [pasteboard declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:nil]; >+ [pasteboard setString:text->string() forType:NSPasteboardTypeString]; >+} >+ > } > > #endif // PLATFORM(MAC) >diff --git a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj b/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj >index b80e82440ede5aa73aa2a88355c3e9e7162f37f8..1b8bdd4f38247c9a3e909849382c939319cd367a 100644 >--- a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj >+++ b/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj >@@ -974,6 +974,8 @@ > F41AB9A81EF4696B0083FA08 /* prevent-operation.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F41AB9941EF4692C0083FA08 /* prevent-operation.html */; }; > F41AB9A91EF4696B0083FA08 /* prevent-start.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F41AB99A1EF4692C0083FA08 /* prevent-start.html */; }; > F41AB9AA1EF4696B0083FA08 /* textarea-to-input.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F41AB9951EF4692C0083FA08 /* textarea-to-input.html */; }; >+ F422A3E9235ACA9B00CF00CA /* ClipboardTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F422A3E8235ACA9B00CF00CA /* ClipboardTests.mm */; }; >+ F422A3EB235BB16200CF00CA /* clipboard.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F422A3EA235BB14500CF00CA /* clipboard.html */; }; > F42D634422A1729F00D2FB3A /* AutocorrectionTestsIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = F42D634322A1729F00D2FB3A /* AutocorrectionTestsIOS.mm */; }; > F42DA5161D8CEFE400336F40 /* large-input-field-focus-onload.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F42DA5151D8CEFDB00336F40 /* large-input-field-focus-onload.html */; }; > F434CA1A22E65BCA005DDB26 /* ScrollToRevealSelection.mm in Sources */ = {isa = PBXBuildFile; fileRef = F434CA1922E65BCA005DDB26 /* ScrollToRevealSelection.mm */; }; >@@ -1177,6 +1179,7 @@ > 2EFF06C71D886A580004BB30 /* change-video-source-on-end.html in Copy Resources */, > 9BD4239C1E04C01C00200395 /* chinese-character-with-image.html in Copy Resources */, > 839AA35F21A26B0300980DD6 /* client-side-redirect.html in Copy Resources */, >+ F422A3EB235BB16200CF00CA /* clipboard.html in Copy Resources */, > 1A50AA201A2A51FC00F4C345 /* close-from-within-create-page.html in Copy Resources */, > 9B270FEE1DDC2C0B002D53F3 /* closed-shadow-tree-test.html in Copy Resources */, > 9B9332CE2320C745002D50E8 /* cocoa-writer-markup-with-lists.html in Copy Resources */, >@@ -2474,6 +2477,8 @@ > F41AB99C1EF4692C0083FA08 /* contenteditable-and-textarea.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "contenteditable-and-textarea.html"; sourceTree = "<group>"; }; > F41AB99D1EF4692C0083FA08 /* link-and-target-div.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "link-and-target-div.html"; sourceTree = "<group>"; }; > F41AB99E1EF4692C0083FA08 /* div-and-large-image.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "div-and-large-image.html"; sourceTree = "<group>"; }; >+ F422A3E8235ACA9B00CF00CA /* ClipboardTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ClipboardTests.mm; sourceTree = "<group>"; }; >+ F422A3EA235BB14500CF00CA /* clipboard.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = clipboard.html; sourceTree = "<group>"; }; > F42D634322A1729F00D2FB3A /* AutocorrectionTestsIOS.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AutocorrectionTestsIOS.mm; sourceTree = "<group>"; }; > F42DA5151D8CEFDB00336F40 /* large-input-field-focus-onload.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = "large-input-field-focus-onload.html"; path = "Tests/WebKitCocoa/large-input-field-focus-onload.html"; sourceTree = SOURCE_ROOT; }; > F434CA1922E65BCA005DDB26 /* ScrollToRevealSelection.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollToRevealSelection.mm; sourceTree = "<group>"; }; >@@ -2787,6 +2792,7 @@ > 1C2B81811C891EFA00A5529F /* CancelFontSubresourcePlugIn.mm */, > 5C23DF0A2245C9D700F454B6 /* Challenge.mm */, > 5CB18BA71F5645B200EE23C4 /* ClickAutoFillButton.mm */, >+ F422A3E8235ACA9B00CF00CA /* ClipboardTests.mm */, > CDF92236216D186400647AA7 /* CloseWebViewAfterEnterFullscreen.mm */, > CDF0B789216D484300421ECC /* CloseWebViewDuringEnterFullscreen.mm */, > 1AAD19F51C7CE20300831E47 /* Coding.mm */, >@@ -3233,6 +3239,7 @@ > 2EFF06C41D8867700004BB30 /* change-video-source-on-click.html */, > 2EFF06C61D886A560004BB30 /* change-video-source-on-end.html */, > 839AA35E21A26ACD00980DD6 /* client-side-redirect.html */, >+ F422A3EA235BB14500CF00CA /* clipboard.html */, > 9B9332CD2320C73E002D50E8 /* cocoa-writer-markup-with-lists.html */, > 9BAE177A22E2BB6B00DF3098 /* cocoa-writer-markup-with-system-fonts.html */, > E5036F77211BC22800BFDBE2 /* color-drop.html */, >@@ -4469,6 +4476,7 @@ > 57303BC9200824D300355965 /* CBORValueTest.cpp in Sources */, > 57303BCA20082C0100355965 /* CBORWriterTest.cpp in Sources */, > 5C23DF0B2246015800F454B6 /* Challenge.mm in Sources */, >+ F422A3E9235ACA9B00CF00CA /* ClipboardTests.mm in Sources */, > 7CCE7EE61A411AE600447C4C /* CloseFromWithinCreatePage.cpp in Sources */, > 7CCE7EB71A411A7E00447C4C /* CloseNewWindowInNavigationPolicyDelegate.mm in Sources */, > 7CCE7EE51A411AE600447C4C /* CloseThenTerminate.cpp in Sources */, >diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/ClipboardTests.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/ClipboardTests.mm >new file mode 100644 >index 0000000000000000000000000000000000000000..d16f27fd7b28f78c9fa707562d7cc9da1dcd8dc5 >--- /dev/null >+++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/ClipboardTests.mm >@@ -0,0 +1,135 @@ >+/* >+ * Copyright (C) 2019 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#import "config.h" >+ >+#import "PlatformUtilities.h" >+#import "TestWKWebView.h" >+#import "UIKitSPI.h" >+#import <CoreServices/CoreServices.h> >+#import <WebKit/WKPreferencesPrivate.h> >+#import <WebKit/_WKExperimentalFeature.h> >+ >+@interface TestWKWebView (ClipboardTests) >+ >+- (void)readClipboard; >+ >+@end >+ >+@implementation TestWKWebView (ClipboardTests) >+ >+- (void)readClipboard >+{ >+ __block bool done = false; >+ [self performAfterReceivingMessage:@"readClipboard" action:^{ >+ done = true; >+ }]; >+ [self evaluateJavaScript:@"readClipboard()" completionHandler:nil]; >+ TestWebKitAPI::Util::run(&done); >+} >+ >+@end >+ >+static RetainPtr<TestWKWebView> createWebViewForClipboardTests() >+{ >+#if PLATFORM(IOS_FAMILY) >+ static dispatch_once_t onceToken; >+ dispatch_once(&onceToken, ^{ >+ // UIPasteboard's type coercion codepaths only take effect when the UIApplication has been initialized. >+ UIApplicationInitialize(); >+ }); >+#endif // PLATFORM(IOS_FAMILY) >+ >+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); >+ [[configuration preferences] _setDOMPasteAllowed:YES]; >+ [[configuration preferences] _setJavaScriptCanAccessClipboard:YES]; >+ for (_WKExperimentalFeature *feature in [WKPreferences _experimentalFeatures]) { >+ if ([feature.key isEqualToString:@"AsyncClipboardAPIEnabled"]) { >+ [[configuration preferences] _setEnabled:YES forExperimentalFeature:feature]; >+ break; >+ } >+ } >+ >+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400) configuration:configuration.get()]); >+ [webView synchronouslyLoadTestPageNamed:@"clipboard"]; >+ return webView; >+} >+ >+static void writeMultipleObjectsToPlatformPasteboard() >+{ >+#if PLATFORM(MAC) >+ auto firstItem = adoptNS([[NSPasteboardItem alloc] init]); >+ [firstItem setString:@"Hello" forType:NSPasteboardTypeString]; >+ >+ auto secondItem = adoptNS([[NSPasteboardItem alloc] init]); >+ [secondItem setString:@"https://apple.com/" forType:NSPasteboardTypeURL]; >+ >+ auto thirdItem = adoptNS([[NSPasteboardItem alloc] init]); >+ [thirdItem setString:@"<strong style='color: rgb(0, 255, 0);'>Hello world</strong>" forType:NSPasteboardTypeHTML]; >+ >+ auto fourthItem = adoptNS([[NSPasteboardItem alloc] init]); >+ [fourthItem setString:@"WebKit" forType:NSPasteboardTypeString]; >+ [fourthItem setString:@"https://webkit.org/" forType:NSPasteboardTypeURL]; >+ [fourthItem setString:@"<a href='https://webkit.org/'>Hello world</a>" forType:NSPasteboardTypeHTML]; >+ >+ NSPasteboard *pasteboard = NSPasteboard.generalPasteboard; >+ [pasteboard clearContents]; >+ [pasteboard writeObjects:@[firstItem.get(), secondItem.get(), thirdItem.get(), fourthItem.get()]]; >+#else >+ auto firstItem = adoptNS([[NSItemProvider alloc] initWithObject:@"Hello"]); >+ auto secondItem = adoptNS([[NSItemProvider alloc] initWithObject:[NSURL URLWithString:@"https://apple.com/"]]); >+ auto thirdItem = adoptNS([[NSItemProvider alloc] init]); >+ [thirdItem registerDataRepresentationForTypeIdentifier:(__bridge NSString *)kUTTypeHTML visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[&] (void (^completionHandler)(NSData *, NSError *)) -> NSProgress * { >+ completionHandler([@"<strong style='color: rgb(0, 255, 0);'>Hello world</strong>" dataUsingEncoding:NSUTF8StringEncoding], nil); >+ return nil; >+ }]; >+ >+ auto fourthItem = adoptNS([[NSItemProvider alloc] init]); >+ [fourthItem registerObject:@"WebKit" visibility:NSItemProviderRepresentationVisibilityAll]; >+ [fourthItem registerObject:[NSURL URLWithString:@"https://webkit.org/"] visibility:NSItemProviderRepresentationVisibilityAll]; >+ [fourthItem registerDataRepresentationForTypeIdentifier:(__bridge NSString *)kUTTypeHTML visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[&] (void (^completionHandler)(NSData *, NSError *)) -> NSProgress * { >+ completionHandler([@"<a href='https://webkit.org/'>Hello world</a>" dataUsingEncoding:NSUTF8StringEncoding], nil); >+ return nil; >+ }]; >+ >+ UIPasteboard.generalPasteboard.itemProviders = @[ firstItem.get(), secondItem.get(), thirdItem.get(), fourthItem.get() ]; >+#endif >+} >+ >+TEST(ClipboardTests, ReadMultipleItems) >+{ >+ auto webView = createWebViewForClipboardTests(); >+ writeMultipleObjectsToPlatformPasteboard(); >+ [webView readClipboard]; >+ >+ EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"exception ? exception.message : ''"]); >+ EXPECT_EQ(4U, [[webView objectByEvaluatingJavaScript:@"clipboardData.length"] unsignedIntValue]); >+ EXPECT_WK_STREQ("Hello", [webView stringByEvaluatingJavaScript:@"clipboardData[0]['text/plain']"]); >+ EXPECT_WK_STREQ("https://apple.com/", [webView stringByEvaluatingJavaScript:@"clipboardData[1]['text/uri-list']"]); >+ EXPECT_WK_STREQ("rgb(0, 255, 0)", [webView stringByEvaluatingJavaScript:@"getComputedStyle(clipboardData[2]['text/html'].querySelector('strong')).color"]); >+ EXPECT_WK_STREQ("WebKit", [webView stringByEvaluatingJavaScript:@"clipboardData[3]['text/plain']"]); >+ EXPECT_WK_STREQ("https://webkit.org/", [webView objectByEvaluatingJavaScript:@"clipboardData[3]['text/uri-list']"]); >+ EXPECT_WK_STREQ("https://webkit.org/", [webView stringByEvaluatingJavaScript:@"clipboardData[3]['text/html'].querySelector('a').href"]); >+} >diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/clipboard.html b/Tools/TestWebKitAPI/Tests/WebKitCocoa/clipboard.html >new file mode 100644 >index 0000000000000000000000000000000000000000..fa382908dfd9b2038151d42684f1803a9f803bd6 >--- /dev/null >+++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/clipboard.html >@@ -0,0 +1,57 @@ >+<!DOCTYPE> >+<html> >+<script> >+function loadText(blob) { >+ return new Promise((resolve, reject) => { >+ const reader = new FileReader; >+ reader.addEventListener("load", () => resolve(reader.result), { once: true }); >+ reader.addEventListener("error", reject, { once: true }); >+ reader.readAsText(blob); >+ }); >+} >+ >+function loadImage(blob) { >+ return new Promise((resolve, reject) => { >+ const image = new Image; >+ image.addEventListener("load", () => resolve(image), { once: true }); >+ image.addEventListener("error", reject, { once: true }); >+ image.src = URL.createObjectURL(blob); >+ }); >+} >+ >+function loadDocument(blob) { >+ return new Promise(async resolve => { >+ resolve(new DOMParser().parseFromString(await loadText(blob), "text/html")); >+ }); >+} >+ >+clipboardData = []; >+exception = null; >+ >+async function readClipboard() { >+ try { >+ const items = await navigator.clipboard.read(); >+ for (const item of items) { >+ let itemData = {}; >+ for (const type of item.types) { >+ const blob = await item.getType(type); >+ if (type === "text/html") >+ itemData[type] = await loadDocument(blob); >+ else if (type === "image/png") >+ itemData[type] = await loadImage(blob); >+ else >+ itemData[type] = await loadText(blob); >+ } >+ clipboardData.push(itemData); >+ } >+ } catch (e) { >+ exception = e; >+ } finally { >+ webkit.messageHandlers.testHandler.postMessage("readClipboard"); >+ } >+} >+</script> >+<body> >+ >+</body> >+</html> >diff --git a/Tools/WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm b/Tools/WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm >index 9dbf6dd2448c211573b56ab0613af116277a4c6a..6a42bcaba463445c13fde3a1e07046920a1974b4 100644 >--- a/Tools/WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm >+++ b/Tools/WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm >@@ -140,10 +140,19 @@ - (NSInteger)clearContents > - (NSInteger)declareTypes:(NSArray *)newTypes owner:(id)newOwner > { > [self _clearContentsWithoutUpdatingChangeCount]; >- return [self addTypes:newTypes owner:newOwner]; >+ [self _addTypesWithoutUpdatingChangeCount:newTypes owner:newOwner]; >+ return ++changeCount; >+} >+ >+- (NSInteger)addTypes:(NSArray<NSPasteboardType> *)newTypes owner:(id)newOwner >+{ >+ [self _addTypesWithoutUpdatingChangeCount:newTypes owner:newOwner]; >+ // FIXME: Ideally, we would keep track of the current owner and only bump the change >+ // count if the new owner is different. >+ return ++changeCount; > } > >-- (NSInteger)addTypes:(NSArray *)newTypes owner:(id)newOwner >+- (void)_addTypesWithoutUpdatingChangeCount:(NSArray *)newTypes owner:(id)newOwner > { > unsigned count = [newTypes count]; > unsigned i; >@@ -159,7 +168,6 @@ - (NSInteger)addTypes:(NSArray *)newTypes owner:(id)newOwner > if (newOwner && [newOwner respondsToSelector:@selector(pasteboard:provideDataForType:)]) > [newOwner pasteboard:self provideDataForType:setType]; > } >- return ++changeCount; > } > > - (NSInteger)changeCount >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index fa7f7f705fb4628f4abb564fe493a019f2afcac1..b9b47cf0eb64146834c3c80826c5b44b0840dde9 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,31 @@ >+2019-10-19 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ [Clipboard API] Implement ClipboardItem.getType() for platform clipboard items >+ https://bugs.webkit.org/show_bug.cgi?id=203168 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add a couple of new layout tests. >+ >+ * editing/async-clipboard/clipboard-change-data-while-getting-type-expected.txt: Added. >+ * editing/async-clipboard/clipboard-change-data-while-getting-type.html: Added. >+ >+ Add a layout test to verify that if the pasteboard changes right after the page has obtained clipboard items, >+ the page should not be able to fetch the new contents of the pasteboard using these clipboard items. >+ >+ * editing/async-clipboard/clipboard-item-get-type-basic-expected.txt: Added. >+ * editing/async-clipboard/clipboard-item-get-type-basic.html: Added. >+ >+ Add a layout test to verify that after writing multiple types to the clipboard using the DataTransfer API, we >+ should be able to read them back using the async clipboard API, as a single ClipboardItem, and also get data out >+ of the clipboard item using ClipboardItem.getType. >+ >+ * editing/async-clipboard/resources/async-clipboard-helpers.js: >+ * platform/win/TestExpectations: >+ * resources/ui-helper.js: >+ (window.UIHelper.async.copyText): >+ (window.UIHelper): >+ > 2019-10-18 Jiewen Tan <jiewen_tan@apple.com> > > [WebAuthn] Warn users when no credentials are found >diff --git a/LayoutTests/editing/async-clipboard/clipboard-change-data-while-getting-type-expected.txt b/LayoutTests/editing/async-clipboard/clipboard-change-data-while-getting-type-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..811e8d07dc6e253da37a80ff3353d58891602698 >--- /dev/null >+++ b/LayoutTests/editing/async-clipboard/clipboard-change-data-while-getting-type-expected.txt >@@ -0,0 +1,11 @@ >+This test verifies that if platform pasteboard contents are changed before reading from a ClipboardItem, the new contents of the pasteboard should not be exposed to the page and the result of getType() should be rejected. This test requires WebKitTestRunner. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS items.length is 1 >+PASS Handled exception: NotAllowedError >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/editing/async-clipboard/clipboard-change-data-while-getting-type.html b/LayoutTests/editing/async-clipboard/clipboard-change-data-while-getting-type.html >new file mode 100644 >index 0000000000000000000000000000000000000000..762a46b61ed0879f293ac7aba6202e2b882aa71a >--- /dev/null >+++ b/LayoutTests/editing/async-clipboard/clipboard-change-data-while-getting-type.html >@@ -0,0 +1,32 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true experimental:AsyncClipboardAPIEnabled=true ] --> >+<html> >+ <meta charset="utf8"> >+ <head> >+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> >+ <script src="../../resources/js-test.js"></script> >+ <script src="../../resources/ui-helper.js"></script> >+ <script src="./resources/async-clipboard-helpers.js"></script> >+ </head> >+ <script> >+ jsTestIsAsync = true; >+ >+ async function runTest() { >+ description("This test verifies that if platform pasteboard contents are changed before reading from a ClipboardItem, the new contents of the pasteboard should not be exposed to the page and the result of getType() should be rejected. This test requires WebKitTestRunner."); >+ >+ await UIHelper.copyText("Foo"); >+ items = await navigator.clipboard.read(); >+ shouldBe("items.length", "1"); >+ await UIHelper.copyText("Bar"); >+ try { >+ const textBlob = await items[0].getType("text/plain"); >+ testFailed(`Did not handle exception (instead, got text: "${await loadText(textBlob)}")`); >+ } catch (exception) { >+ testPassed(`Handled exception: ${exception.name}`); >+ } >+ finishJSTest(); >+ } >+ >+ addEventListener("load", runTest); >+ </script> >+ <body></body> >+</html> >diff --git a/LayoutTests/editing/async-clipboard/clipboard-item-get-type-basic-expected.txt b/LayoutTests/editing/async-clipboard/clipboard-item-get-type-basic-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..21463b0a343edbc565dfda1665ff57819e814bf4 >--- /dev/null >+++ b/LayoutTests/editing/async-clipboard/clipboard-item-get-type-basic-expected.txt >@@ -0,0 +1,13 @@ >+This test verifies that ClipboardItem.getType() can be used to get clipboard data written using DataTransfer APIs. To test manually, click the top button to write to the pasteboard, and then click the bottom button to paste. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+PASS items.length is 1 >+PASS item.types.length is 3 >+PASS text is "Apple, Inc." >+PASS url is "https://www.apple.com/" >+PASS doc.querySelector('a').href is "https://www.apple.com/" >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/editing/async-clipboard/clipboard-item-get-type-basic.html b/LayoutTests/editing/async-clipboard/clipboard-item-get-type-basic.html >new file mode 100644 >index 0000000000000000000000000000000000000000..135cc53fec79a3ff450d7832686eee605d884a87 >--- /dev/null >+++ b/LayoutTests/editing/async-clipboard/clipboard-item-get-type-basic.html >@@ -0,0 +1,65 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true experimental:AsyncClipboardAPIEnabled=true ] --> >+<html> >+ <meta charset="utf8"> >+ <head> >+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> >+ <script src="../../resources/js-test.js"></script> >+ <script src="../../resources/ui-helper.js"></script> >+ <script src="./resources/async-clipboard-helpers.js"></script> >+ <style> >+ button { >+ width: 100%; >+ height: 100px; >+ } >+ </style> >+ </head> >+ <script> >+ jsTestIsAsync = true; >+ >+ async function runTest() { >+ description("This test verifies that ClipboardItem.getType() can be used to get clipboard data written using DataTransfer APIs. To test manually, click the top button to write to the pasteboard, and then click the bottom button to paste."); >+ >+ const copyButton = document.getElementById("copy"); >+ const pasteButton = document.getElementById("paste"); >+ >+ copyButton.addEventListener("click", () => { >+ writeToClipboardUsingDataTransfer({ >+ "text/html" : "<a href='https://www.apple.com/'>Apple</a>", >+ "text/uri-list" : "https://www.apple.com/", >+ "text/plain" : "Apple, Inc." >+ }); >+ }, { once: true }); >+ >+ pasteButton.addEventListener("click", async () => { >+ try { >+ items = await navigator.clipboard.read(); >+ shouldBe("items.length", "1"); >+ item = items[0]; >+ shouldBe("item.types.length", "3"); >+ text = await loadText(await item.getType("text/plain")); >+ url = await loadText(await item.getType("text/uri-list")); >+ doc = await loadDocument(await item.getType("text/html")); >+ shouldBeEqualToString("text", "Apple, Inc."); >+ shouldBeEqualToString("url", "https://www.apple.com/"); >+ shouldBeEqualToString("doc.querySelector('a').href", "https://www.apple.com/"); >+ } catch (exception) { >+ testFailed(`Caught unexpected exception: ${exception.name}`); >+ } finally { >+ [copyButton, pasteButton].map(button => button.remove()); >+ finishJSTest(); >+ } >+ }, { once: true }); >+ >+ await UIHelper.activateElement(copyButton); >+ await UIHelper.activateElement(pasteButton); >+ } >+ >+ addEventListener("load", runTest); >+ </script> >+ <body> >+ <button id="copy">Click here to copy</button> >+ <button id="paste">Click here to paste</button> >+ <div id="description"></div> >+ <div id="console"></div> >+ </body> >+</html> >diff --git a/LayoutTests/editing/async-clipboard/resources/async-clipboard-helpers.js b/LayoutTests/editing/async-clipboard/resources/async-clipboard-helpers.js >index 9f48b609696db8b820d6c1fdc8ba1a710abef7a7..57647c951f475895d3a49a66204ff6130a0f50b8 100644 >--- a/LayoutTests/editing/async-clipboard/resources/async-clipboard-helpers.js >+++ b/LayoutTests/editing/async-clipboard/resources/async-clipboard-helpers.js >@@ -30,6 +30,12 @@ function loadImage(blob) { > }); > } > >+function loadDocument(blob) { >+ return new Promise(async resolve => { >+ resolve(new DOMParser().parseFromString(await loadText(blob), "text/html")); >+ }); >+} >+ > function writeToClipboardUsingDataTransfer(data) { > const input = document.createElement("input"); > document.body.appendChild(input); >diff --git a/LayoutTests/platform/win/TestExpectations b/LayoutTests/platform/win/TestExpectations >index c9241de6beae19f6b49c0f7745c9a0ff87f41b41..97a688b95bdfee2468f3c3784cfd478c63a1df2e 100644 >--- a/LayoutTests/platform/win/TestExpectations >+++ b/LayoutTests/platform/win/TestExpectations >@@ -1191,6 +1191,8 @@ http/tests/security/clipboard/copy-paste-html-across-origin-strips-mso-list.html > > webkit.org/b/203100 editing/async-clipboard/clipboard-read-basic.html [ Skip ] > webkit.org/b/203100 editing/async-clipboard/clipboard-change-data-while-reading.html [ Skip ] >+webkit.org/b/203100 editing/async-clipboard/clipboard-change-data-while-getting-type.html [ Skip ] >+webkit.org/b/203100 editing/async-clipboard/clipboard-item-get-type-basic.html [ Skip ] > > webkit.org/b/140783 [ Release ] editing/pasteboard/copy-standalone-image.html [ Failure ImageOnlyFailure ] > webkit.org/b/140783 [ Debug ] editing/pasteboard/copy-standalone-image.html [ Skip ] # Debug Assertion >diff --git a/LayoutTests/resources/ui-helper.js b/LayoutTests/resources/ui-helper.js >index c010612d0d9f73568fbbde46ce1e5f03f11ba28a..3cc09312a85074177cf10573d845d3191dbc7880 100644 >--- a/LayoutTests/resources/ui-helper.js >+++ b/LayoutTests/resources/ui-helper.js >@@ -1036,4 +1036,9 @@ window.UIHelper = class UIHelper { > break; > } > } >+ >+ static async copyText(text) { >+ const copyTextScript = `uiController.copyText(\`${text.replace(/`/g, "\\`")}\`)()`; >+ return new Promise(resolve => testRunner.runUIScript(copyTextScript, resolve)); >+ } > }
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 203168
:
381380
|
381381
|
381419