WebKit Bugzilla
Attachment 348783 Details for
Bug 188890
: Populate "text/uri-list" with multiple URLs when the pasteboard contains multiple URLs
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-188890-20180903112528.patch (text/plain), 42.72 KB, created by
Wenson Hsieh
on 2018-09-03 11:25:28 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Wenson Hsieh
Created:
2018-09-03 11:25:28 PDT
Size:
42.72 KB
patch
obsolete
>Subversion Revision: 235579 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 7de7e235a48bda373f93e195782d7c7829e12dbb..b375a15f2b51bead56e5dac9016f90d4bf1ff9c4 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,109 @@ >+2018-09-03 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ Populate "text/uri-list" with multiple URLs when the pasteboard contains multiple URLs >+ https://bugs.webkit.org/show_bug.cgi?id=188890 >+ <rdar://problem/43648605> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Adds support for exposing a newline separated list of URLs via DataTransfer's "text/uri-list" type when pasting >+ or dropping multiple items on the pasteboard that can be represented as URLs. Currently on iOS, only the URL of >+ the first item (if present) is exposed, and on macOS, only the first out of all the URLs in the pasteboard is >+ exposed. >+ >+ To fix this, we introduce `Pasteboard::readAllStrings`, which reads a list of pasteboard strings collected from >+ all available items on the platform pasteboard. Currently, this is only used to provide a list of URL strings >+ when fetching data for the "text/uri-list" type when calling `DataTransfer.getData()` and >+ `DataTransferItem.getAsString()`. >+ >+ Tests: DragAndDropTests.ExposeMultipleURLsInDataTransfer >+ UIPasteboardTests.DataTransferURIListContainsMultipleURLs >+ PasteMixedContent.PasteOneOrMoreURLs >+ >+ * dom/DataTransfer.cpp: >+ (WebCore::readURLsFromPasteboardAsString): >+ >+ Add a helper method that reads all URL strings from the pasteboard (for the MIME type "text/uri-list", which >+ corresponds to NSURLPboardType and "public.url" on macOS and iOS, respectively) and returns a single string >+ containing all non-empty URLs joined by newline characters. Also takes a filtering block which may be used to >+ reject URLs from being included in "text/uri-list" output. >+ >+ (WebCore::DataTransfer::getDataForItem const): >+ (WebCore::DataTransfer::readStringFromPasteboard const): >+ >+ Insteading of reading a single string from the pasteboard for "text/uri-list", call the above helper function to >+ read all URL strings in the pasteboard. If there are files present in the pasteboard, we also filter out URLs >+ whose schemes are not in the set of schemes that are safe to expose to the page (i.e. http(s), blob, and data). >+ >+ * platform/Pasteboard.cpp: >+ (WebCore::Pasteboard::readAllStrings): >+ >+ Add a default non-Cocoa implementation of readAllStrings() that returns a vector, which may contain the result >+ of readString(). >+ >+ * platform/Pasteboard.h: >+ * platform/PasteboardStrategy.h: >+ * platform/PlatformPasteboard.h: >+ >+ Add plumbing to grab a list of strings from the pasteboard for a given type. >+ >+ * platform/cocoa/PasteboardCocoa.mm: >+ (WebCore::Pasteboard::readAllStrings): >+ (WebCore::Pasteboard::readString): >+ >+ Implement these two methods in terms of `readPlatformValuesAsStrings`. `readAllStrings` returns the full list of >+ results, while `readString` only returns the first result. >+ >+ * platform/ios/PasteboardIOS.mm: >+ (WebCore::Pasteboard::readPlatformValuesAsStrings): >+ (WebCore::Pasteboard::readPlatformValueAsString): Deleted. >+ >+ Refactor this Cocoa helper function to return a list of pasteboard string values for the given type, rather than >+ a single string. >+ >+ * platform/ios/PlatformPasteboardIOS.mm: >+ (WebCore::PlatformPasteboard::allStringsForType const): >+ >+ Grab a string for each item (represented by an NSItemProvider) in the pasteboard that has data for the given >+ type identifier. >+ >+ (WebCore::PlatformPasteboard::readString const): >+ >+ Return the absolute string of the NSURL, instead of WebCore::URL::string(). This is needed to handle the case >+ where the NSURL is constructed from absolute and relative parts using a Plist. While -absoluteString gets us the >+ full URL string, URL::string() only returns the relative portion. >+ >+ * platform/mac/PasteboardMac.mm: >+ (WebCore::Pasteboard::readPlatformValuesAsStrings): >+ (WebCore::Pasteboard::readPlatformValueAsString): Deleted. >+ >+ Also refactor this to retrieve a list of pasteboard strings, rather than a single result. >+ >+ * platform/mac/PlatformPasteboardMac.mm: >+ (WebCore::typeIdentifierForPasteboardType): >+ (WebCore::PlatformPasteboard::allStringsForType const): >+ >+ Add an implementation for `allStringsForType` on macOS. Unlike iOS, it's much trickier to get this right since >+ we need to maintain compatibility with legacy "NS*Pboard" types, and `NSPasteboardItem` can only provide data >+ for `NSPasteboardType`s (i.e. UTIs), so there's no way to just iterate through each pasteboard item and ask it >+ for data that matches the given type, if the types are not UTIs. However, in the case where we have multiple >+ items, the client must have used NSPasteboardWriting-conformant objects and/or NSPasteboardItem itself to write >+ data to the pasteboard. Since NSPasteboardWriting-conformant objects register modern pasteboard types when >+ writing to the pasteboard, we can simply iterate over these pasteboard items and ask for string values using >+ type identifiers instead of having to worry about legacy pasteboard types. Furthermore, in the case where there >+ is only a single item in the pasteboard and we do need to handle legacy pasteboard types, using `-[NSPasteboard >+ stringForType:]` in the same way we do currently should yield the correct result. >+ >+ As such, in the case where there is a single pasteboard item, we use `-[NSPasteboard stringForType:]` with the >+ original legacy type, and in the case where there are multiple items on the pasteboard, we iterate over each of >+ the pasteboard items and call `-[NSPasteboardItem stringForType:]` with the modern pasteboard type corresponding >+ to the given legacy pasteboard type. >+ >+ The different corner cases in this logic are tested by the new API test, PasteMixedContent.PasteOneOrMoreURLs, >+ which exercises several different ways of writing one or more URLs to the pasteboard on macOS, which each result >+ in different legacy and modern pasteboard types being written to the pasteboard; our implementation of >+ `PlatformPasteboard::allStringsForType` on macOS handles all cases correctly. >+ > 2018-08-31 Youenn Fablet <youenn@apple.com> > > Move stats gathering out of LibWebRTCMediaEndpoint >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index fc03a5651c260cacf00093a99c5a2ac8f0c75343..00de248c0dadf46ed588e905199010fcce8ab9af 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,22 @@ >+2018-09-03 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ Populate "text/uri-list" with multiple URLs when the pasteboard contains multiple URLs >+ https://bugs.webkit.org/show_bug.cgi?id=188890 >+ <rdar://problem/43648605> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add some plumbing through pasteboard classes to support `Pasteboard::readAllStrings`. See WebCore ChangeLog for >+ more detail. >+ >+ * UIProcess/Cocoa/WebPasteboardProxyCocoa.mm: >+ (WebKit::WebPasteboardProxy::getPasteboardStringsForType): >+ * UIProcess/WebPasteboardProxy.h: >+ * UIProcess/WebPasteboardProxy.messages.in: >+ * WebProcess/WebCoreSupport/WebPlatformStrategies.cpp: >+ (WebKit::WebPlatformStrategies::allStringsForType): >+ * WebProcess/WebCoreSupport/WebPlatformStrategies.h: >+ > 2018-08-31 John Wilander <wilander@apple.com> > > Storage Access API: Maintain access through same-site navigations >diff --git a/Source/WebKitLegacy/mac/ChangeLog b/Source/WebKitLegacy/mac/ChangeLog >index 9b1d5790768eaa0aad71861cd65f77d4e482a285..4da5f3dd9f2836af5b147d2ccb0f2a9cd15f4de3 100644 >--- a/Source/WebKitLegacy/mac/ChangeLog >+++ b/Source/WebKitLegacy/mac/ChangeLog >@@ -1,3 +1,18 @@ >+2018-09-03 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ Populate "text/uri-list" with multiple URLs when the pasteboard contains multiple URLs >+ https://bugs.webkit.org/show_bug.cgi?id=188890 >+ <rdar://problem/43648605> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add some plumbing through pasteboard classes to support `Pasteboard::readAllStrings`. See WebCore ChangeLog for >+ more detail. >+ >+ * WebCoreSupport/WebPlatformStrategies.h: >+ * WebCoreSupport/WebPlatformStrategies.mm: >+ (WebPlatformStrategies::allStringsForType): >+ > 2018-08-31 Chris Dumez <cdumez@apple.com> > > Assertion hit in ~CompletionHandler() from ~WebFrame() >diff --git a/Source/WebCore/dom/DataTransfer.cpp b/Source/WebCore/dom/DataTransfer.cpp >index 5141f472fe9b4915e8ba467f375a8322605f787d..6d39da455d42f3382dc7425dad8007bfd6707b9e 100644 >--- a/Source/WebCore/dom/DataTransfer.cpp >+++ b/Source/WebCore/dom/DataTransfer.cpp >@@ -47,6 +47,7 @@ > #include "WebContentReader.h" > #include "WebCorePasteboardFileReader.h" > #include "markup.h" >+#include <wtf/unicode/CharacterNames.h> > > namespace WebCore { > >@@ -142,6 +143,19 @@ void DataTransfer::clearData(const String& type) > m_itemList->didClearStringData(normalizedType); > } > >+static String readURLsFromPasteboardAsString(Pasteboard& pasteboard, Function<bool(const String&)>&& shouldIncludeURL) >+{ >+ StringBuilder urlList; >+ for (auto urlString : pasteboard.readAllStrings("text/uri-list"_s)) { >+ if (!shouldIncludeURL(urlString)) >+ continue; >+ if (!urlList.isEmpty()) >+ urlList.append(newlineCharacter); >+ urlList.append(urlString); >+ } >+ return urlList.toString(); >+} >+ > String DataTransfer::getDataForItem(Document& document, const String& type) const > { > if (!canReadData()) >@@ -150,9 +164,9 @@ String DataTransfer::getDataForItem(Document& document, const String& type) cons > auto lowercaseType = stripLeadingAndTrailingHTMLSpaces(type).convertToASCIILowercase(); > if (shouldSuppressGetAndSetDataToAvoidExposingFilePaths()) { > if (lowercaseType == "text/uri-list") { >- auto urlString = m_pasteboard->readString(lowercaseType); >- if (Pasteboard::canExposeURLToDOMWhenPasteboardContainsFiles(urlString)) >- return urlString; >+ return readURLsFromPasteboardAsString(*m_pasteboard, [] (auto& urlString) { >+ return Pasteboard::canExposeURLToDOMWhenPasteboardContainsFiles(urlString); >+ }); > } > > if (lowercaseType == "text/html" && RuntimeEnabledFeatures::sharedFeatures().customPasteboardDataEnabled()) { >@@ -192,6 +206,12 @@ String DataTransfer::readStringFromPasteboard(Document& document, const String& > return reader.markup; > } > >+ if (!is<StaticPasteboard>(*m_pasteboard) && lowercaseType == "text/uri-list") { >+ return readURLsFromPasteboardAsString(*m_pasteboard, [] (auto&) { >+ return true; >+ }); >+ } >+ > return m_pasteboard->readString(lowercaseType); > } > >diff --git a/Source/WebCore/platform/Pasteboard.cpp b/Source/WebCore/platform/Pasteboard.cpp >index 18fdeb2d9e85d7e91621a455df3e7f9c5a940d28..737a3904257de643bc0d9ab99bc264a314fd6ff7 100644 >--- a/Source/WebCore/platform/Pasteboard.cpp >+++ b/Source/WebCore/platform/Pasteboard.cpp >@@ -85,4 +85,17 @@ PasteboardCustomData PasteboardCustomData::fromSharedBuffer(const SharedBuffer& > return result; > } > >+#if !PLATFORM(COCOA) >+ >+Vector<String> Pasteboard::readAllStrings(const String& type) >+{ >+ auto result = readString(type); >+ if (result.isEmpty()) >+ return { }; >+ >+ return { result }; >+} >+ >+#endif >+ > }; >diff --git a/Source/WebCore/platform/Pasteboard.h b/Source/WebCore/platform/Pasteboard.h >index e09815651bd2d60574da4236c380fad4d60215a9..20635ab0294f2997e28fbffd50986948a99b6030 100644 >--- a/Source/WebCore/platform/Pasteboard.h >+++ b/Source/WebCore/platform/Pasteboard.h >@@ -204,6 +204,7 @@ public: > virtual WEBCORE_EXPORT String readOrigin(); > virtual WEBCORE_EXPORT String readString(const String& type); > virtual WEBCORE_EXPORT String readStringInCustomData(const String& type); >+ virtual WEBCORE_EXPORT Vector<String> readAllStrings(const String& type); > > virtual WEBCORE_EXPORT void writeString(const String& type, const String& data); > virtual WEBCORE_EXPORT void clear(); >@@ -298,7 +299,7 @@ private: > > #if PLATFORM(COCOA) > Vector<String> readFilePaths(); >- String readPlatformValueAsString(const String& domType, long changeCount, const String& pasteboardName); >+ Vector<String> readPlatformValuesAsStrings(const String& domType, long changeCount, const String& pasteboardName); > static void addHTMLClipboardTypesForCocoaType(ListHashSet<String>& resultTypes, const String& cocoaType); > String readStringForPlatformType(const String&); > Vector<String> readTypesWithSecurityCheck(); >diff --git a/Source/WebCore/platform/PasteboardStrategy.h b/Source/WebCore/platform/PasteboardStrategy.h >index 9d827c01f85cc02b21695d9b2e7bca15b4b9fd05..99d8ddffae00eace1a632cb0d3f5381a23fa365c 100644 >--- a/Source/WebCore/platform/PasteboardStrategy.h >+++ b/Source/WebCore/platform/PasteboardStrategy.h >@@ -61,6 +61,7 @@ public: > virtual RefPtr<SharedBuffer> bufferForType(const String& pasteboardType, const String& pasteboardName) = 0; > virtual void getPathnamesForType(Vector<String>& pathnames, const String& pasteboardType, const String& pasteboardName) = 0; > virtual String stringForType(const String& pasteboardType, const String& pasteboardName) = 0; >+ virtual Vector<String> allStringsForType(const String& pasteboardType, const String& pasteboardName) = 0; > virtual long changeCount(const String& pasteboardName) = 0; > virtual String uniqueName() = 0; > virtual Color color(const String& pasteboardName) = 0; >diff --git a/Source/WebCore/platform/PlatformPasteboard.h b/Source/WebCore/platform/PlatformPasteboard.h >index dc650c33350a87d97cf50984eb6e534502138d76..8e13bf4d841413bf1c117dec9eff85c4824b88ef 100644 >--- a/Source/WebCore/platform/PlatformPasteboard.h >+++ b/Source/WebCore/platform/PlatformPasteboard.h >@@ -73,6 +73,7 @@ public: > WEBCORE_EXPORT RefPtr<SharedBuffer> bufferForType(const String& pasteboardType); > WEBCORE_EXPORT void getPathnamesForType(Vector<String>& pathnames, const String& pasteboardType) const; > WEBCORE_EXPORT String stringForType(const String& pasteboardType) const; >+ WEBCORE_EXPORT Vector<String> allStringsForType(const String& pasteboardType) const; > WEBCORE_EXPORT long changeCount() const; > WEBCORE_EXPORT Color color(); > WEBCORE_EXPORT URL url(); >diff --git a/Source/WebCore/platform/cocoa/PasteboardCocoa.mm b/Source/WebCore/platform/cocoa/PasteboardCocoa.mm >index f48e7b8370baccc4030af06a37d1408fee0970d6..fa50e4c9c5513517b336c0226090e3f6027712d9 100644 >--- a/Source/WebCore/platform/cocoa/PasteboardCocoa.mm >+++ b/Source/WebCore/platform/cocoa/PasteboardCocoa.mm >@@ -259,9 +259,15 @@ void Pasteboard::read(PasteboardFileReader& reader) > } > } > >+Vector<String> Pasteboard::readAllStrings(const String& type) >+{ >+ return readPlatformValuesAsStrings(type, m_changeCount, m_pasteboardName); >+} >+ > String Pasteboard::readString(const String& type) > { >- return readPlatformValueAsString(type, m_changeCount, m_pasteboardName); >+ auto values = readPlatformValuesAsStrings(type, m_changeCount, m_pasteboardName); >+ return values.isEmpty() ? String() : values.first(); > } > > String Pasteboard::readStringInCustomData(const String& type) >diff --git a/Source/WebCore/platform/ios/PasteboardIOS.mm b/Source/WebCore/platform/ios/PasteboardIOS.mm >index d1c02edf22028b4531afc7ec0f7609a5715372a3..3d12582c8ef800e040b163a7afe1c8ed2b670bbf 100644 >--- a/Source/WebCore/platform/ios/PasteboardIOS.mm >+++ b/Source/WebCore/platform/ios/PasteboardIOS.mm >@@ -373,38 +373,26 @@ void Pasteboard::clear() > platformStrategies()->pasteboardStrategy()->writeToPasteboard(String(), String(), m_pasteboardName); > } > >-String Pasteboard::readPlatformValueAsString(const String& domType, long changeCount, const String& pasteboardName) >+Vector<String> Pasteboard::readPlatformValuesAsStrings(const String& domType, long changeCount, const String& pasteboardName) > { >- PasteboardStrategy& strategy = *platformStrategies()->pasteboardStrategy(); >- >- int numberOfItems = strategy.getPasteboardItemsCount(pasteboardName); >- >- if (!numberOfItems) >- return String(); >+ auto& strategy = *platformStrategies()->pasteboardStrategy(); > > // Grab the value off the pasteboard corresponding to the cocoaType. >- RetainPtr<NSString> cocoaType = cocoaTypeFromHTMLClipboardType(domType); >- >- NSString *cocoaValue = nil; >+ auto cocoaType = cocoaTypeFromHTMLClipboardType(domType); >+ if (!cocoaType) >+ return { }; > >- if ([cocoaType isEqualToString:(NSString *)kUTTypeURL]) { >- String title; >- URL url = strategy.readURLFromPasteboard(0, pasteboardName, title); >- if (!url.isNull()) >- cocoaValue = [(NSURL *)url absoluteString]; >- } else if ([cocoaType isEqualToString:(NSString *)kUTTypePlainText]) { >- String value = strategy.readStringFromPasteboard(0, kUTTypePlainText, pasteboardName); >- if (!value.isNull()) >- cocoaValue = [(NSString *)value precomposedStringWithCanonicalMapping]; >- } else if (cocoaType) >- cocoaValue = (NSString *)strategy.readStringFromPasteboard(0, cocoaType.get(), pasteboardName); >+ bool isPlainTextType = [cocoaType isEqualToString:(NSString *)kUTTypePlainText]; >+ Vector<String> values; >+ for (auto& value : strategy.allStringsForType(cocoaType.get(), pasteboardName)) >+ values.append(isPlainTextType ? String([value precomposedStringWithCanonicalMapping]) : value); > > // Enforce changeCount ourselves for security. We check after reading instead of before to be > // sure it doesn't change between our testing the change count and accessing the data. >- if (cocoaValue && changeCount == changeCountForPasteboard(pasteboardName)) >- return cocoaValue; >+ if (changeCount != changeCountForPasteboard(pasteboardName)) >+ return { }; > >- return String(); >+ return values; > } > > void Pasteboard::addHTMLClipboardTypesForCocoaType(ListHashSet<String>& resultTypes, const String& cocoaType) >diff --git a/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm b/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm >index e02893ed6e4a6b01e728221bf6f1d418fb2155b0..da7f62177ac8596053101b5b89182e021a9b26dc 100644 >--- a/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm >+++ b/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm >@@ -603,6 +603,19 @@ int PlatformPasteboard::count() const > return [m_pasteboard numberOfItems]; > } > >+Vector<String> PlatformPasteboard::allStringsForType(const String& type) const >+{ >+ auto numberOfItems = count(); >+ Vector<String> strings; >+ strings.reserveInitialCapacity(numberOfItems); >+ for (int index = 0; index < numberOfItems; ++index) { >+ String value = readString(index, type); >+ if (!value.isEmpty()) >+ strings.uncheckedAppend(WTFMove(value)); >+ } >+ return strings; >+} >+ > RefPtr<SharedBuffer> PlatformPasteboard::readBuffer(int index, const String& type) const > { > NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:index]; >@@ -618,7 +631,7 @@ String PlatformPasteboard::readString(int index, const String& type) const > { > if (type == String(kUTTypeURL)) { > String title; >- return readURL(index, title); >+ return [(NSURL *)readURL(index, title) absoluteString]; > } > > NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:index]; >diff --git a/Source/WebCore/platform/mac/PasteboardMac.mm b/Source/WebCore/platform/mac/PasteboardMac.mm >index fd6e9298774faf4fe8735bf27565adc9532bf636..9d81874897d6eeff57004ef28199a773bd07fc8d 100644 >--- a/Source/WebCore/platform/mac/PasteboardMac.mm >+++ b/Source/WebCore/platform/mac/PasteboardMac.mm >@@ -488,22 +488,24 @@ void Pasteboard::clear(const String& type) > m_changeCount = platformStrategies()->pasteboardStrategy()->setStringForType(emptyString(), cocoaType, m_pasteboardName); > } > >-String Pasteboard::readPlatformValueAsString(const String& domType, long changeCount, const String& pasteboardName) >+Vector<String> Pasteboard::readPlatformValuesAsStrings(const String& domType, long changeCount, const String& pasteboardName) > { >- const String& cocoaType = cocoaTypeFromHTMLClipboardType(domType); >- String cocoaValue; >+ auto& strategy = *platformStrategies()->pasteboardStrategy(); >+ auto cocoaType = cocoaTypeFromHTMLClipboardType(domType); >+ if (cocoaType.isEmpty()) >+ return { }; > >- if (cocoaType == String(legacyStringPasteboardType())) >- cocoaValue = [platformStrategies()->pasteboardStrategy()->stringForType(cocoaType, pasteboardName) precomposedStringWithCanonicalMapping]; >- else if (!cocoaType.isEmpty()) >- cocoaValue = platformStrategies()->pasteboardStrategy()->stringForType(cocoaType, pasteboardName); >+ bool isStringType = cocoaType == String(legacyStringPasteboardType()); >+ Vector<String> values; >+ for (auto& value : strategy.allStringsForType(cocoaType, pasteboardName)) >+ values.append(isStringType ? String([value precomposedStringWithCanonicalMapping]) : value); > > // Enforce changeCount ourselves for security. We check after reading instead of before to be > // sure it doesn't change between our testing the change count and accessing the data. >- if (!cocoaValue.isEmpty() && changeCount == platformStrategies()->pasteboardStrategy()->changeCount(pasteboardName)) >- return cocoaValue; >+ if (changeCount != platformStrategies()->pasteboardStrategy()->changeCount(pasteboardName)) >+ return { }; > >- return String(); >+ return values; > } > > static String utiTypeFromCocoaType(const String& type) >diff --git a/Source/WebCore/platform/mac/PlatformPasteboardMac.mm b/Source/WebCore/platform/mac/PlatformPasteboardMac.mm >index a1925badc93b6c71931ec9549d8cd72e622d1d7e..a8f77fa0abec013d3046c03d30a5a026e01f1113 100644 >--- a/Source/WebCore/platform/mac/PlatformPasteboardMac.mm >+++ b/Source/WebCore/platform/mac/PlatformPasteboardMac.mm >@@ -116,6 +116,75 @@ String PlatformPasteboard::stringForType(const String& pasteboardType) const > return [m_pasteboard stringForType:pasteboardType]; > } > >+static NSArray<NSURL *> *urlsFromPasteboard(NSPasteboard *pasteboard) >+{ >+ NSArray<NSPasteboardItem *> *items = pasteboard.pasteboardItems; >+ if (items.count > 1) { >+ NSMutableArray<NSURL *> *urlsFromItems = [NSMutableArray arrayWithCapacity:items.count]; >+ for (NSPasteboardItem *item in items) { >+ if (id propertyList = [item propertyListForType:(__bridge NSString *)kUTTypeURL]) { >+ auto url = adoptNS([[NSURL alloc] initWithPasteboardPropertyList:propertyList ofType:(__bridge NSString *)kUTTypeURL]); >+ [urlsFromItems addObject:url.get()]; >+ } >+ } >+ return urlsFromItems; >+ } >+ >+ if (NSURL *urlFromString = [NSURL URLFromPasteboard:pasteboard]) >+ return @[ urlFromString ]; >+ >+ if (NSURL *urlFromPasteboard = [NSURL URLWithString:[pasteboard stringForType:legacyURLPasteboardType()]]) >+ return @[ urlFromPasteboard ]; >+ >+ return @[ ]; >+} >+ >+static String typeIdentifierForPasteboardType(const String& pasteboardType) >+{ >+ if (UTTypeIsDeclared(pasteboardType.createCFString().get())) >+ return pasteboardType; >+ >+ if (pasteboardType == String(legacyStringPasteboardType())) >+ return kUTTypeUTF8PlainText; >+ >+ if (pasteboardType == String(legacyHTMLPasteboardType())) >+ return kUTTypeHTML; >+ >+ if (pasteboardType == String(legacyURLPasteboardType())) >+ return kUTTypeURL; >+ >+ return { }; >+} >+ >+Vector<String> PlatformPasteboard::allStringsForType(const String& pasteboardType) const >+{ >+ bool mayContainFiles = pasteboardMayContainFilePaths(m_pasteboard.get()); >+ auto typeIdentifier = typeIdentifierForPasteboardType(pasteboardType); >+ NSArray<NSURL *> *platformURLs = urlsFromPasteboard(m_pasteboard.get()); >+ Vector<String> strings; >+ strings.reserveInitialCapacity(platformURLs.count); >+ if (typeIdentifier == String(kUTTypeURL)) { >+ for (NSURL *url in platformURLs) { >+ String urlString = url.absoluteString; >+ if (urlString.isEmpty() || (mayContainFiles && !Pasteboard::canExposeURLToDOMWhenPasteboardContainsFiles(urlString))) >+ continue; >+ strings.uncheckedAppend(WTFMove(urlString)); >+ } >+ return strings; >+ } >+ >+ NSArray<NSPasteboardItem *> *items = [m_pasteboard pasteboardItems]; >+ if (items.count > 1 && !typeIdentifier.isNull()) { >+ for (NSPasteboardItem *item in items) { >+ if (NSString *stringFromItem = [item stringForType:typeIdentifier]) >+ strings.append(stringFromItem); >+ } >+ } else if (NSString *stringFromPasteboard = [m_pasteboard stringForType:pasteboardType]) >+ strings.append(stringFromPasteboard); >+ >+ return strings; >+} >+ > static const char* safeTypeForDOMToReadAndWriteForPlatformType(const String& platformType) > { > if (platformType == String(legacyStringPasteboardType()) || platformType == String(NSPasteboardTypeString)) >diff --git a/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm >index c9924404febb09ae017b10ce9c5f882a59312709..ae64707da151c22bc3839dab4af7e74014e0220e 100644 >--- a/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm >+++ b/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm >@@ -70,6 +70,11 @@ void WebPasteboardProxy::getPasteboardStringForType(const String& pasteboardName > string = PlatformPasteboard(pasteboardName).stringForType(pasteboardType); > } > >+void WebPasteboardProxy::getPasteboardStringsForType(const String& pasteboardName, const String& pasteboardType, Vector<String>& strings) >+{ >+ strings = PlatformPasteboard(pasteboardName).allStringsForType(pasteboardType); >+} >+ > void WebPasteboardProxy::getPasteboardBufferForType(const String& pasteboardName, const String& pasteboardType, SharedMemory::Handle& handle, uint64_t& size) > { > RefPtr<SharedBuffer> buffer = PlatformPasteboard(pasteboardName).bufferForType(pasteboardType); >diff --git a/Source/WebKit/UIProcess/WebPasteboardProxy.h b/Source/WebKit/UIProcess/WebPasteboardProxy.h >index e5ec209327da0760e82cb44ae8339fdbd19105eb..3ae2603eaed226ececa1f442b428fe7adf621e36 100644 >--- a/Source/WebKit/UIProcess/WebPasteboardProxy.h >+++ b/Source/WebKit/UIProcess/WebPasteboardProxy.h >@@ -87,6 +87,7 @@ private: > void getPasteboardTypes(const String& pasteboardName, Vector<String>& pasteboardTypes); > void getPasteboardPathnamesForType(IPC::Connection&, const String& pasteboardName, const String& pasteboardType, Vector<String>& pathnames, SandboxExtension::HandleArray&); > void getPasteboardStringForType(const String& pasteboardName, const String& pasteboardType, String&); >+ void getPasteboardStringsForType(const String& pasteboardName, const String& pasteboardType, Vector<String>&); > void getPasteboardBufferForType(const String& pasteboardName, const String& pasteboardType, SharedMemory::Handle&, uint64_t& size); > void pasteboardCopy(const String& fromPasteboard, const String& toPasteboard, uint64_t& newChangeCount); > void getPasteboardChangeCount(const String& pasteboardName, uint64_t& changeCount); >diff --git a/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in b/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in >index b92cb81b6a66e01b10788c9a2cf625cb5fc8eecd..5dd6988b91311fc33860f722205fe02fd76bd888 100644 >--- a/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in >+++ b/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in >@@ -45,6 +45,7 @@ messages -> WebPasteboardProxy { > GetPasteboardTypes(String pasteboardName) -> (Vector<String> types) > GetPasteboardPathnamesForType(String pasteboardName, String pasteboardType) -> (Vector<String> pathnames, WebKit::SandboxExtension::HandleArray sandboxExtensions) WantsConnection > GetPasteboardStringForType(String pasteboardName, String pasteboardType) -> (String string) >+ GetPasteboardStringsForType(String pasteboardName, String pasteboardType) -> (Vector<String> strings) > GetPasteboardBufferForType(String pasteboardName, String pasteboardType) -> (WebKit::SharedMemory::Handle handle, uint64_t size) > PasteboardCopy(String fromPasteboard, String toPasteboard) -> (uint64_t changeCount) > GetPasteboardChangeCount(String pasteboardName) -> (uint64_t changeCount) >diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp >index 7602f5c94b2e55fd2705a5d56fc60519c944dbf3..243298e047b8e23c186421ab155210abf6943a73 100644 >--- a/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp >+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp >@@ -207,6 +207,13 @@ String WebPlatformStrategies::stringForType(const String& pasteboardType, const > return value; > } > >+Vector<String> WebPlatformStrategies::allStringsForType(const String& pasteboardType, const String& pasteboardName) >+{ >+ Vector<String> values; >+ WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetPasteboardStringsForType(pasteboardName, pasteboardType), Messages::WebPasteboardProxy::GetPasteboardStringsForType::Reply(values), 0); >+ return values; >+} >+ > long WebPlatformStrategies::changeCount(const WTF::String &pasteboardName) > { > uint64_t changeCount { 0 }; >diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.h b/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.h >index 591d78fcdd09e90a0cad5c110b35bda628239c36..6eec09b1ed22b9ad068e3f6924b592574515d146 100644 >--- a/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.h >+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.h >@@ -76,6 +76,7 @@ private: > RefPtr<WebCore::SharedBuffer> bufferForType(const String& pasteboardType, const String& pasteboardName) override; > void getPathnamesForType(Vector<String>& pathnames, const String& pasteboardType, const String& pasteboardName) override; > String stringForType(const String& pasteboardType, const String& pasteboardName) override; >+ Vector<String> allStringsForType(const String& pasteboardType, const String& pasteboardName) override; > long changeCount(const String& pasteboardName) override; > String uniqueName() override; > WebCore::Color color(const String& pasteboardName) override; >diff --git a/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.h b/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.h >index a8d96263494a8f12a8516092d63d6377b25c1db9..739c951f6bd7ff55f2992adff3a509a6ce100594 100644 >--- a/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.h >+++ b/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.h >@@ -76,6 +76,7 @@ private: > RefPtr<WebCore::SharedBuffer> bufferForType(const String& pasteboardType, const String& pasteboardName) override; > void getPathnamesForType(Vector<String>& pathnames, const String& pasteboardType, const String& pasteboardName) override; > String stringForType(const String& pasteboardType, const String& pasteboardName) override; >+ Vector<String> allStringsForType(const String& pasteboardType, const String& pasteboardName) override; > long changeCount(const String& pasteboardName) override; > String uniqueName() override; > WebCore::Color color(const String& pasteboardName) override; >diff --git a/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm b/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm >index 9d578a0b957f261310688652841dcf9ecb754270..bd7581fa50481c9897c9a1fcdd32190f67f06b45 100644 >--- a/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm >+++ b/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm >@@ -123,6 +123,11 @@ void WebPlatformStrategies::getPathnamesForType(Vector<String>& pathnames, const > PlatformPasteboard(pasteboardName).getPathnamesForType(pathnames, pasteboardType); > } > >+Vector<String> WebPlatformStrategies::allStringsForType(const String& pasteboardType, const String& pasteboardName) >+{ >+ return PlatformPasteboard(pasteboardName).allStringsForType(pasteboardType); >+} >+ > String WebPlatformStrategies::stringForType(const String& pasteboardType, const String& pasteboardName) > { > return PlatformPasteboard(pasteboardName).stringForType(pasteboardType); >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 7d898d414ce68f81a23e3bd2156f75d3e230e938..1ff21376503e962559b9f8a6710a57222ab2f1dc 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,40 @@ >+2018-09-03 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ Populate "text/uri-list" with multiple URLs when the pasteboard contains multiple URLs >+ https://bugs.webkit.org/show_bug.cgi?id=188890 >+ <rdar://problem/43648605> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * DumpRenderTree/mac/DumpRenderTreePasteboard.mm: >+ (-[LocalPasteboard pasteboardItems]): >+ >+ Implement this method to avoid crashing when running layout tests that access the pasteboard. >+ >+ * TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm: >+ >+ Add a test to verify that on macOS and iOS, multiple URLs dropped onto the page are accessible via >+ "text/uri-list". >+ >+ * TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm: >+ >+ Add a test that exercises 5 different ways to write one or more URLs to the pasteboard on macOS; in all cases, >+ the URLs written to the pasteboard should be exposed to the page via "text/uri-list". In all of these different >+ cases, the results of using `-[NSPasteboardItem stringForType:]`, `-[NSURL URLFromPasteboard:]` and >+ `-[NSPasteboard stringForType:]` will yield different results, so the purpose of this API test is to ensure that >+ our logic for grabbing a list of URLs from the pasteboard on macOS is robust enough to handle all of these >+ different behaviors. >+ >+ * TestWebKitAPI/Tests/ios/UIPasteboardTests.mm: >+ >+ Add a test to verify that on iOS, using `-[UIPasteboard setURLs:]` to write to multiple URLs to the pasteboard >+ and then pasting results in "text/uri-list" exposing a list of all the URLs written to the pasteboard. >+ >+ * WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm: >+ (-[LocalPasteboard pasteboardItems]): >+ >+ Implement this method to avoid crashing when running layout tests that access the pasteboard. >+ > 2018-08-31 Aditya Keerthi <akeerthi@apple.com> > > Unreviewed, add an alternate email for Aditya Keerthi. >diff --git a/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm b/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm >index cdd31b3bbb35bb86250fefc0cabf1c55c341bcae..ae29a94420e72e84144c5061f3b0c731ddcd9459 100644 >--- a/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm >+++ b/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm >@@ -237,6 +237,17 @@ static RetainPtr<CFStringRef> toUTI(NSString *type) > return YES; > } > >+- (NSArray<NSPasteboardItem *> *)pasteboardItems >+{ >+ auto item = adoptNS([[NSPasteboardItem alloc] init]); >+ for (auto typeAndData : _data) { >+ NSData *data = (__bridge NSData *)typeAndData.value.get(); >+ NSString *type = (__bridge NSString *)typeAndData.key.get(); >+ [item setData:data forType:type]; >+ } >+ return @[ item.get() ]; >+} >+ > @end > > #endif // PLATFORM(MAC) >diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm >index 15e4148fda4707bd52e82367751e936c23926a0f..94b5f708e96704b9003117e54de6c55a0040c8f3 100644 >--- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm >+++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm >@@ -43,6 +43,37 @@ TEST(DragAndDropTests, DragImageLocationForLinkInSubframe) > #endif > } > >+TEST(DragAndDropTests, ExposeMultipleURLsInDataTransfer) >+{ >+ auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:CGRectMake(0, 0, 320, 500)]); >+ auto webView = [simulator webView]; >+ [webView synchronouslyLoadTestPageNamed:@"DataTransfer"]; >+ >+ NSString *stringData = @"Hello world"; >+ NSURL *firstURL = [NSURL URLWithString:@"https://webkit.org/"]; >+ NSURL *secondURL = [NSURL URLWithString:@"https://apple.com/"]; >+ >+#if PLATFORM(MAC) >+ NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName]; >+ [pasteboard writeObjects:@[ stringData, firstURL, secondURL ]]; >+ [simulator setExternalDragPasteboard:pasteboard]; >+#else >+ auto stringItem = adoptNS([[NSItemProvider alloc] initWithObject:stringData]); >+ auto firstURLItem = adoptNS([[NSItemProvider alloc] initWithObject:firstURL]); >+ auto secondURLItem = adoptNS([[NSItemProvider alloc] initWithObject:secondURL]); >+ for (NSItemProvider *item in @[ stringItem.get(), firstURLItem.get(), secondURLItem.get() ]) >+ item.preferredPresentationStyle = UIPreferredPresentationStyleInline; >+ [simulator setExternalItemProviders:@[ stringItem.get(), firstURLItem.get(), secondURLItem.get() ]]; >+#endif >+ >+ [simulator runFrom:CGPointMake(0, 0) to:CGPointMake(100, 100)]; >+ >+ EXPECT_WK_STREQ("text/plain, text/uri-list", [webView stringByEvaluatingJavaScript:@"types.textContent"]); >+ EXPECT_WK_STREQ("(STRING, text/plain), (STRING, text/uri-list)", [webView stringByEvaluatingJavaScript:@"items.textContent"]); >+ EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"textData.textContent"]); >+ EXPECT_WK_STREQ("https://webkit.org/\nhttps://apple.com/", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]); >+} >+ > #if ENABLE(INPUT_TYPE_COLOR) > > TEST(DragAndDropTests, ColorInputToColorInput) >diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm >index c5e50e2dab783c406c94aefe0b0d3bf69ecd2af0..7132a2ec9c693e6ecce152b459b3d8bf83dc74bb 100644 >--- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm >+++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm >@@ -255,6 +255,50 @@ TEST(PasteMixedContent, PasteURLWrittenToPasteboardUsingWriteObjects) > EXPECT_WK_STREQ([webView stringByEvaluatingJavaScript:@"document.querySelector('a').textContent"], urlToCopy); > } > >+TEST(PasteMixedContent, PasteOneOrMoreURLs) >+{ >+ NSURL *appleURL = [NSURL URLWithString:@"https://www.apple.com/"]; >+ NSURL *webKitURL = [NSURL URLWithString:@"https://webkit.org/"]; >+ >+ auto webView = setUpWebView(); >+ auto runTest = [webView] (NSString *description, NSString *expectedURLString, Function<void(NSPasteboard *)>&& writeURLsToPasteboard) { >+ NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; >+ >+ [pasteboard clearContents]; >+ writeURLsToPasteboard(pasteboard); >+ [webView stringByEvaluatingJavaScript:@"reset(); document.body.focus()"]; >+ [webView paste:nil]; >+ >+ EXPECT_WK_STREQ(expectedURLString, [webView stringByEvaluatingJavaScript:@"urlData.textContent"]); >+ EXPECT_WK_STREQ("(STRING, text/uri-list)", [webView stringByEvaluatingJavaScript:@"items.textContent"]); >+ EXPECT_WK_STREQ("text/uri-list", [webView stringByEvaluatingJavaScript:@"types.textContent"]); >+ }; >+ >+ runTest(@"Write multiple URLs.", @"https://www.apple.com/\nhttps://webkit.org/", ^(NSPasteboard *pasteboard) { >+ [pasteboard writeObjects:@[appleURL, webKitURL]]; >+ }); >+ >+ runTest(@"Declare legacy URL and write URL to pasteboard.", @"https://www.apple.com/", ^(NSPasteboard *pasteboard) { >+ [pasteboard declareTypes:@[NSURLPboardType] owner:nil]; >+ [appleURL writeToPasteboard:pasteboard]; >+ }); >+ >+ runTest(@"Declare legacy URL and set a URL string.", @"https://www.apple.com/", ^(NSPasteboard *pasteboard) { >+ [pasteboard declareTypes:@[NSURLPboardType] owner:nil]; >+ [pasteboard setString:appleURL.absoluteString forType:NSURLPboardType]; >+ }); >+ >+ runTest(@"Declare legacy URL and set a property list.", @"https://www.apple.com/", ^(NSPasteboard *pasteboard) { >+ [pasteboard declareTypes:@[NSURLPboardType] owner:nil]; >+ [pasteboard setPropertyList:@[@"/", @"https://www.apple.com"] forType:NSURLPboardType]; >+ }); >+ >+ runTest(@"Declare URL UTI and set a URL string.", @"https://www.apple.com/", ^(NSPasteboard *pasteboard) { >+ [pasteboard declareTypes:@[(__bridge NSString *)kUTTypeURL] owner:nil]; >+ [pasteboard setString:appleURL.absoluteString forType:(__bridge NSString *)kUTTypeURL]; >+ }); >+} >+ > #endif // PLATFORM(MAC) > > TEST(PasteMixedContent, CopyAndPasteWithCustomPasteboardDataOnly) >diff --git a/Tools/TestWebKitAPI/Tests/ios/UIPasteboardTests.mm b/Tools/TestWebKitAPI/Tests/ios/UIPasteboardTests.mm >index 433485561e50d5c0c7e2da04479ef3fb3a47080f..1c19a375b91349bed6f988e8cb98e96b66b67bb2 100644 >--- a/Tools/TestWebKitAPI/Tests/ios/UIPasteboardTests.mm >+++ b/Tools/TestWebKitAPI/Tests/ios/UIPasteboardTests.mm >@@ -267,6 +267,22 @@ TEST(UIPasteboardTests, DataTransferGetDataCannotReadArbitraryPlatformTypes) > }); > } > >+TEST(UIPasteboardTests, DataTransferURIListContainsMultipleURLs) >+{ >+ auto webView = setUpWebViewForPasteboardTests(@"DataTransfer"); >+ >+ NSURL *firstURL = [NSURL URLWithString:@"https://www.apple.com/"]; >+ NSURL *secondURL = [NSURL URLWithString:@"https://webkit.org/"]; >+ [UIPasteboard generalPasteboard].URLs = @[ firstURL, secondURL ]; >+ >+ [webView paste:nil]; >+ >+ EXPECT_WK_STREQ("text/uri-list, text/plain", [webView stringByEvaluatingJavaScript:@"types.textContent"]); >+ EXPECT_WK_STREQ("(STRING, text/uri-list), (STRING, text/plain)", [webView stringByEvaluatingJavaScript:@"items.textContent"]); >+ EXPECT_WK_STREQ("https://www.apple.com/\nhttps://webkit.org/", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]); >+ EXPECT_WK_STREQ("https://www.apple.com/", [webView stringByEvaluatingJavaScript:@"textData.textContent"]); >+} >+ > #endif // __IPHONE_OS_VERSION_MIN_REQUIRED >= 110300 > > } // namespace TestWebKitAPI >diff --git a/Tools/WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm b/Tools/WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm >index abcdf4147517ecbe5fc5dbf57c65ab1d4affb84b..5e5cac4e7cfb1190f8038e6e8a7290e92c1aafa7 100644 >--- a/Tools/WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm >+++ b/Tools/WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm >@@ -29,6 +29,7 @@ > #include "WebKitTestRunnerPasteboard.h" > > #include <objc/runtime.h> >+#include <wtf/RetainPtr.h> > > @interface LocalPasteboard : NSPasteboard > { >@@ -197,4 +198,12 @@ static NSMutableDictionary *localPasteboards; > return [self setData:[string dataUsingEncoding:NSUTF8StringEncoding] forType:dataType]; > } > >+- (NSArray<NSPasteboardItem *> *)pasteboardItems >+{ >+ auto item = adoptNS([[NSPasteboardItem alloc] init]); >+ for (NSString *type in dataByType) >+ [item setData:dataByType[type] forType:type]; >+ return @[ item.get() ]; >+} >+ > @end
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 188890
:
348725
|
348756
|
348783
|
348856