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 & new layout test
bug-203168-20191021110743.patch (text/plain), 51.32 KB, created by
Wenson Hsieh
on 2019-10-21 11:07:44 PDT
(
hide
)
Description:
Fix & new layout test
Filename:
MIME Type:
Creator:
Wenson Hsieh
Created:
2019-10-21 11:07:44 PDT
Size:
51.32 KB
patch
obsolete
>Subversion Revision: 251330 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index bcb17e73a11ea2010ee28e922dba1a43571dd607..afd507b053a01ac0dc0fb806e257c2441d883a24 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,54 @@ >+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 Tim Horton. >+ >+ This patch completes support for ClipboardItem.getType(). >+ >+ Tests: editing/async-clipboard/clipboard-change-data-while-getting-type.html >+ editing/async-clipboard/clipboard-get-type-with-old-items.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-20 Zalan Bujtas <zalan@apple.com> > > [LFC][IFC] Make InlineTextItem reusable when 'segment break' behavior changes >diff --git a/Source/WebCore/Modules/async-clipboard/Clipboard.cpp b/Source/WebCore/Modules/async-clipboard/Clipboard.cpp >index acc5814066cd2a2e8e0c5d55407bfa584ed2cc27..b81400df212730e52a0f058fa5abbeb03054ecfb 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,64 @@ 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) { >+ 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 +199,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..1031e517af6f8463bfad3268d137e1dcae7bccbd 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. kUTTypeUTF8PlainText). 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..86175df2faa1e8ad37f69549c4ce82c4ea0c16b4 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 Tim Horton. >+ >+ 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 88d5890cc48071d4e10fcc7f75b75bac0ad2cbe2..4a9bcc4bb37d2fb60cdb79046bfbb6ce6865567b 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,37 @@ >+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 Tim Horton. >+ >+ Add 3 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-get-type-with-old-items.html: Added. >+ * editing/async-clipboard/clipboard-get-type-with-old-items-expected.txt: Added. >+ >+ Add a layout test to verify that after attempting to get data from invalid (stale) items, the page is still >+ capable of reading data from valid 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-19 Ryosuke Niwa <rniwa@webkit.org> > > Flaky Test: fast/events/resize-subframe-in-rendering-update.html >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-get-type-with-old-items-expected.txt b/LayoutTests/editing/async-clipboard/clipboard-get-type-with-old-items-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..3a1d43988aef150599bddf326aca9bab9d6b4dc6 >--- /dev/null >+++ b/LayoutTests/editing/async-clipboard/clipboard-get-type-with-old-items-expected.txt >@@ -0,0 +1,14 @@ >+This test verifies that it's still possible to read from the clipboard, after attempting to read data from stale items. Requires DumpRenderTree or WebKitTestRunner. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS itemsBeforeChange.length is 1 >+PASS text is "Hello" >+PASS itemsAfterChange.length is 1 >+PASS Caught expected exception: NotAllowedError >+PASS text is "World" >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/editing/async-clipboard/clipboard-get-type-with-old-items.html b/LayoutTests/editing/async-clipboard/clipboard-get-type-with-old-items.html >new file mode 100644 >index 0000000000000000000000000000000000000000..75ee5ce9eeff93fa155f7dd682079eeec97263c6 >--- /dev/null >+++ b/LayoutTests/editing/async-clipboard/clipboard-get-type-with-old-items.html >@@ -0,0 +1,53 @@ >+<!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 it's still possible to read from the clipboard, after attempting to read data from stale items. Requires DumpRenderTree or WebKitTestRunner."); >+ >+ await UIHelper.copyText("Hello"); >+ itemsBeforeChange = await navigator.clipboard.read(); >+ shouldBe("itemsBeforeChange.length", "1"); >+ >+ try { >+ const textBlob = await itemsBeforeChange[0].getType("text/plain"); >+ text = await loadText(textBlob); >+ shouldBeEqualToString("text", "Hello"); >+ } catch (exception) { >+ testFailed(`Caught unexpected exception: ${exception.name}`); >+ } >+ >+ await UIHelper.copyText("World"); >+ itemsAfterChange = await navigator.clipboard.read(); >+ shouldBe("itemsAfterChange.length", "1"); >+ >+ try { >+ const textBlob = await itemsBeforeChange[0].getType("text/plain"); >+ testFailed(`Expected exception when calling getType(). Instead, got Blob(${textBlob.size} bytes)`); >+ } catch (exception) { >+ testPassed(`Caught expected exception: ${exception.name}`); >+ } >+ >+ try { >+ const textBlob = await itemsAfterChange[0].getType("text/plain"); >+ text = await loadText(textBlob); >+ shouldBeEqualToString("text", "World"); >+ } catch (exception) { >+ testFailed(`Caught unexpected 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 f411fc0213bf22c5d1c1f54b49368f82f1f57c4b..1928e3902fcb8264e93935bc0d8ef5eb5c206e3a 100644 >--- a/LayoutTests/platform/win/TestExpectations >+++ b/LayoutTests/platform/win/TestExpectations >@@ -1191,6 +1191,9 @@ 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/203100 editing/async-clipboard/clipboard-get-type-with-old-items.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