Title: [220865] trunk
Revision
220865
Author
[email protected]
Date
2017-08-17 11:34:15 -0700 (Thu, 17 Aug 2017)

Log Message

[iOS] Respect type fidelities when copying image elements to the pasteboard
https://bugs.webkit.org/show_bug.cgi?id=175638
<rdar://problem/26556043>

Reviewed by Ryosuke Niwa.

Source/WebCore:

Ensures that we respect type fidelities when copying on iOS, by unifying pasteboard writing codepaths across
dragging and copying. When dragging and copying, we now generate and set UIItemProviders on the UIPasteboard.

Tests: ActionSheetTests.CopyImageElementWithHREF
       ActionSheetTests.CopyImageElementWithoutHREF

* platform/PlatformPasteboard.h:

Remove all variants of the writeObjectRepresentations helper method. Now that both paths for writing to the
pasteboard are unified, it's no longer useful to separate out item-provider-based pasteboard logic.

* platform/ios/AbstractPasteboard.h:
* platform/ios/PlatformPasteboardIOS.mm:

Replaces -setItemsUsingRegistrationInfoLists: with -setRegistrationInfoLists:. Rather than have a helper that
both sets up item providers and item registration lists, split this functionality out into two setters. This is
because UIPasteboard does not need to know about the registration info lists used to set up the item providers
in the first place, but internal drag-and-drop clients require this information immediately when starting a drag
in order to construct custom drag previews.

(WebCore::richTextRepresentationsForPasteboardWebContent):
(WebCore::registerItemToPasteboard):

Add a new helper to register item providers to the pasteboard, given an WebItemProviderRegistrationInfoList.

(WebCore::PlatformPasteboard::write):
(WebCore::PlatformPasteboard::writeObjectRepresentations): Deleted.

Refactors PlatformPasteboard::write to always generate and set item providers, unless we're building for an SDK
prior to iOS 11. For images, strings and URLs, we can simply transition to using the new item-provider-based
codepaths used for drag and drop. For web content, we add two additional UTIs that were present when copying,
but not when dragging: flat RTFD and a string constant used to indicate to UIKit that the pasteboard contains
rich text.

* platform/ios/WebItemProviderPasteboard.h:
* platform/ios/WebItemProviderPasteboard.mm:
(-[WebItemProviderRegistrationInfoList init]):
(-[WebItemProviderRegistrationInfoList addData:forType:]):
(-[WebItemProviderRegistrationInfoList addRepresentingObject:]):
(-[WebItemProviderRegistrationInfoList numberOfItems]):
(-[WebItemProviderRegistrationInfoList itemAtIndex:]):
(-[WebItemProviderRegistrationInfoList itemProvider]):
(-[WebItemProviderRegistrationInfoList description]):

Make some small tweaks in WebItemProviderPasteboard (and related classes):
1. Transition to preferredPresentationSize from estimatedDisplayedSize, which is now deprecated.
2. Remove calls to -initWithItemProviderData:typeIdentifier:error:, which is deprecated.
3. Rename _items to _representations to better reflect the role of WebItemProviderRegistrationInfo.
4. Implement -description for WebItemProviderRegistrationInfoList for debugging purposes.

(-[WebItemProviderPasteboard valuesForPasteboardType:inItemSet:]):
(-[WebItemProviderPasteboard setRegistrationInfoLists:]):
(-[WebItemProviderPasteboard setItemsUsingRegistrationInfoLists:]): Deleted.

Source/WebCore/PAL:

Replace -estimatedDisplayedSize with its non-deprecated counterpart, -preferredPresentationSize.

* pal/spi/ios/UIKitSPI.h:

Source/WebKit:

Currently, we treat the case when copying an image enclosed by a link by only writing a URL to the pasteboard.
This patch tweaks logic in WebPage::performActionOnElement to write both an image and a link to the pasteboard
if the hit-tested image element is enclosed by an anchor.

* Platform/spi/ios/UIKitSPI.h:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::containingLinkElement):

Tweak this helper to be more restrictive when finding an enclosing 'link' -- only return an element if isLink()
is true, and it is an HTMLAnchorElement. Currently, the isLink() also matches HTMLLinkElements, but this isn't
the intention here.

(WebKit::WebPage::performActionOnElement):

Tools:

Add API tests that simulate copying an image element using the action sheet, and verifying that the pasteboard
contains UTIs in order of fidelity (image type before URL). Also pulls out UIKit SPI (UIApplicationInitialize)
used in UIPasteboardTests and ActionSheetTests into a common UIKitSPI header.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/ios/ActionSheetTests.mm:
(-[ActionSheetObserver _webView:actionsForElement:defaultActions:]):
(TestWebKitAPI::TEST):
(TestWebKitAPI::presentActionSheetAndChooseAction):
(-[ActionSheetObserver waitForActionSheetAfterBlock:]): Deleted.
* TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
(checkEstimatedSize):
(checkSuggestedNameAndEstimatedSize):

Replace -estimatedDisplayedSize with its non-deprecated counterpart, -preferredPresentationSize.

* TestWebKitAPI/Tests/ios/UIPasteboardTests.mm:
(TestWebKitAPI::TEST):
* TestWebKitAPI/ios/DataInteractionSimulator.h:
* TestWebKitAPI/ios/UIKitSPI.h: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (220864 => 220865)


--- trunk/Source/WebCore/ChangeLog	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Source/WebCore/ChangeLog	2017-08-17 18:34:15 UTC (rev 220865)
@@ -1,3 +1,65 @@
+2017-08-17  Wenson Hsieh  <[email protected]>
+
+        [iOS] Respect type fidelities when copying image elements to the pasteboard
+        https://bugs.webkit.org/show_bug.cgi?id=175638
+        <rdar://problem/26556043>
+
+        Reviewed by Ryosuke Niwa.
+
+        Ensures that we respect type fidelities when copying on iOS, by unifying pasteboard writing codepaths across
+        dragging and copying. When dragging and copying, we now generate and set UIItemProviders on the UIPasteboard.
+
+        Tests: ActionSheetTests.CopyImageElementWithHREF
+               ActionSheetTests.CopyImageElementWithoutHREF
+
+        * platform/PlatformPasteboard.h:
+
+        Remove all variants of the writeObjectRepresentations helper method. Now that both paths for writing to the
+        pasteboard are unified, it's no longer useful to separate out item-provider-based pasteboard logic.
+
+        * platform/ios/AbstractPasteboard.h:
+        * platform/ios/PlatformPasteboardIOS.mm:
+
+        Replaces -setItemsUsingRegistrationInfoLists: with -setRegistrationInfoLists:. Rather than have a helper that
+        both sets up item providers and item registration lists, split this functionality out into two setters. This is
+        because UIPasteboard does not need to know about the registration info lists used to set up the item providers
+        in the first place, but internal drag-and-drop clients require this information immediately when starting a drag
+        in order to construct custom drag previews.
+
+        (WebCore::richTextRepresentationsForPasteboardWebContent):
+        (WebCore::registerItemToPasteboard):
+
+        Add a new helper to register item providers to the pasteboard, given an WebItemProviderRegistrationInfoList.
+
+        (WebCore::PlatformPasteboard::write):
+        (WebCore::PlatformPasteboard::writeObjectRepresentations): Deleted.
+
+        Refactors PlatformPasteboard::write to always generate and set item providers, unless we're building for an SDK
+        prior to iOS 11. For images, strings and URLs, we can simply transition to using the new item-provider-based
+        codepaths used for drag and drop. For web content, we add two additional UTIs that were present when copying,
+        but not when dragging: flat RTFD and a string constant used to indicate to UIKit that the pasteboard contains
+        rich text.
+
+        * platform/ios/WebItemProviderPasteboard.h:
+        * platform/ios/WebItemProviderPasteboard.mm:
+        (-[WebItemProviderRegistrationInfoList init]):
+        (-[WebItemProviderRegistrationInfoList addData:forType:]):
+        (-[WebItemProviderRegistrationInfoList addRepresentingObject:]):
+        (-[WebItemProviderRegistrationInfoList numberOfItems]):
+        (-[WebItemProviderRegistrationInfoList itemAtIndex:]):
+        (-[WebItemProviderRegistrationInfoList itemProvider]):
+        (-[WebItemProviderRegistrationInfoList description]):
+
+        Make some small tweaks in WebItemProviderPasteboard (and related classes):
+        1. Transition to preferredPresentationSize from estimatedDisplayedSize, which is now deprecated.
+        2. Remove calls to -initWithItemProviderData:typeIdentifier:error:, which is deprecated.
+        3. Rename _items to _representations to better reflect the role of WebItemProviderRegistrationInfo.
+        4. Implement -description for WebItemProviderRegistrationInfoList for debugging purposes.
+
+        (-[WebItemProviderPasteboard valuesForPasteboardType:inItemSet:]):
+        (-[WebItemProviderPasteboard setRegistrationInfoLists:]):
+        (-[WebItemProviderPasteboard setItemsUsingRegistrationInfoLists:]): Deleted.
+
 2017-08-17  Youenn Fablet  <[email protected]>
 
         Add a DOMPromiseDeferred method to handle ExceptionOr<> results

Modified: trunk/Source/WebCore/PAL/ChangeLog (220864 => 220865)


--- trunk/Source/WebCore/PAL/ChangeLog	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Source/WebCore/PAL/ChangeLog	2017-08-17 18:34:15 UTC (rev 220865)
@@ -1,3 +1,15 @@
+2017-08-17  Wenson Hsieh  <[email protected]>
+
+        [iOS] Respect type fidelities when copying image elements to the pasteboard
+        https://bugs.webkit.org/show_bug.cgi?id=175638
+        <rdar://problem/26556043>
+
+        Reviewed by Ryosuke Niwa.
+
+        Replace -estimatedDisplayedSize with its non-deprecated counterpart, -preferredPresentationSize.
+
+        * pal/spi/ios/UIKitSPI.h:
+
 2017-08-17  Don Olmstead  <[email protected]>
 
         [PAL] Move SessionID into PAL

Modified: trunk/Source/WebCore/PAL/pal/spi/ios/UIKitSPI.h (220864 => 220865)


--- trunk/Source/WebCore/PAL/pal/spi/ios/UIKitSPI.h	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Source/WebCore/PAL/pal/spi/ios/UIKitSPI.h	2017-08-17 18:34:15 UTC (rev 220865)
@@ -95,7 +95,7 @@
 NS_ASSUME_NONNULL_BEGIN
 
 @interface UIItemProvider : NSItemProvider
-@property (nonatomic) CGSize estimatedDisplayedSize;
+@property (nonatomic) CGSize preferredPresentationSize;
 @end
 
 #define UIItemProviderRepresentationOptionsVisibilityAll NSItemProviderRepresentationVisibilityAll

Modified: trunk/Source/WebCore/platform/PlatformPasteboard.h (220864 => 220865)


--- trunk/Source/WebCore/platform/PlatformPasteboard.h	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Source/WebCore/platform/PlatformPasteboard.h	2017-08-17 18:34:15 UTC (rev 220865)
@@ -98,10 +98,6 @@
 
 private:
 #if PLATFORM(IOS)
-    WEBCORE_EXPORT void writeObjectRepresentations(const PasteboardWebContent&);
-    WEBCORE_EXPORT void writeObjectRepresentations(const PasteboardImage&);
-    WEBCORE_EXPORT void writeObjectRepresentations(const String& pasteboardType, const String& text);
-    WEBCORE_EXPORT void writeObjectRepresentations(const PasteboardURL&);
     bool allowReadingURLAtIndex(const URL&, int index) const;
 #endif
 

Modified: trunk/Source/WebCore/platform/ios/AbstractPasteboard.h (220864 => 220865)


--- trunk/Source/WebCore/platform/ios/AbstractPasteboard.h	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Source/WebCore/platform/ios/AbstractPasteboard.h	2017-08-17 18:34:15 UTC (rev 220865)
@@ -29,6 +29,10 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000
+@class WebItemProviderRegistrationInfoList;
+#endif
+
 @protocol AbstractPasteboard <NSObject>
 @required
 
@@ -44,7 +48,9 @@
 - (NSInteger)changeCount;
 
 @optional
-- (void)setItemsUsingRegistrationInfoLists:(NSArray *)itemLists;
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000
+- (void)setRegistrationInfoLists:(NSArray <WebItemProviderRegistrationInfoList *> *)info;
+#endif
 - (void)setItems:(NSArray<NSDictionary *> *)items;
 - (NSArray<NSString *> *)pasteboardTypesByFidelityForItemAtIndex:(NSUInteger)index;
 @property (readonly, nonatomic) NSInteger numberOfFiles;

Modified: trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm (220864 => 220865)


--- trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm	2017-08-17 18:34:15 UTC (rev 220865)
@@ -173,6 +173,10 @@
     return String();
 }
 
+static NSString *webIOSPastePboardType = @"iOS rich content paste pasteboard type";
+
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 110000
+
 static RetainPtr<NSDictionary> richTextRepresentationsForPasteboardWebContent(const PasteboardWebContent& content)
 {
     RetainPtr<NSMutableDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]);
@@ -184,7 +188,6 @@
     if (content.dataInWebArchiveFormat) {
         [representations setValue:(NSData *)content.dataInWebArchiveFormat->createNSData().get() forKey:WebArchivePboardType];
         // Flag for UIKit to know that this copy contains rich content. This will trigger a two-step paste.
-        NSString *webIOSPastePboardType = @"iOS rich content paste pasteboard type";
         [representations setValue:webIOSPastePboardType forKey:webIOSPastePboardType];
     }
 
@@ -196,6 +199,23 @@
     return representations;
 }
 
+#else
+
+static void registerItemToPasteboard(WebItemProviderRegistrationInfoList *representationsToRegister, id <AbstractPasteboard> pasteboard)
+{
+    UIItemProvider *itemProvider = [representationsToRegister itemProvider];
+    if (!itemProvider) {
+        [pasteboard setItemProviders:@[ ]];
+        return;
+    }
+
+    [pasteboard setItemProviders:@[ itemProvider ]];
+    if ([pasteboard respondsToSelector:@selector(setRegistrationInfoLists:)])
+        [pasteboard setRegistrationInfoLists:@[ representationsToRegister ]];
+}
+
+#endif
+
 #if ENABLE(DATA_INTERACTION)
 
 static void addRepresentationsForPlainText(WebItemProviderRegistrationInfoList *itemsToRegister, const String& plainText)
@@ -230,68 +250,74 @@
 
 #endif
 
-void PlatformPasteboard::writeObjectRepresentations(const PasteboardWebContent& content)
+void PlatformPasteboard::write(const PasteboardWebContent& content)
 {
-#if ENABLE(DATA_INTERACTION)
-    RetainPtr<WebItemProviderRegistrationInfoList> itemsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 110000
+    RetainPtr<NSMutableDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]);
+    [representations addEntriesFromDictionary:richTextRepresentationsForPasteboardWebContent(content).autorelease()];
 
+    NSString *textAsString = content.dataInStringFormat;
+    [representations setValue:[textAsString dataUsingEncoding:NSUTF8StringEncoding] forKey:(NSString *)kUTTypeUTF8PlainText];
+    [representations setValue:[textAsString dataUsingEncoding:NSUTF16StringEncoding] forKey:(NSString *)kUTTypeUTF16PlainText];
+    // FIXME: We vend "public.text" here for backwards compatibility with pre-iOS 11 apps. In the future, we should stop vending this UTI,
+    // and instead set data for concrete plain text types. See <https://bugs.webkit.org/show_bug.cgi?id=173317>.
+    [representations setValue:textAsString forKey:(NSString *)kUTTypeText];
+
+    // Explicitly cast m_pasteboard to UIPasteboard * to work around rdar://problem/33383354.
+    ASSERT([m_pasteboard isKindOfClass:getUIPasteboardClass()]);
+    [(UIPasteboard *)m_pasteboard setItems:@[representations.get()]];
+#else
+    auto representationsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);
+
+    [representationsToRegister addData:[webIOSPastePboardType dataUsingEncoding:NSUTF8StringEncoding] forType:webIOSPastePboardType];
+
     ASSERT(content.clientTypes.size() == content.clientData.size());
     for (size_t i = 0, size = content.clientTypes.size(); i < size; ++i)
-        [itemsToRegister addData:content.clientData[i]->createNSData().get() forType:content.clientTypes[i]];
+        [representationsToRegister addData:content.clientData[i]->createNSData().get() forType:content.clientTypes[i]];
 
     if (content.dataInWebArchiveFormat)
-        [itemsToRegister addData:content.dataInWebArchiveFormat->createNSData().get() forType:WebArchivePboardType];
+        [representationsToRegister addData:content.dataInWebArchiveFormat->createNSData().get() forType:WebArchivePboardType];
 
     if (content.dataInAttributedStringFormat) {
         NSAttributedString *attributedString = [NSKeyedUnarchiver unarchiveObjectWithData:content.dataInAttributedStringFormat->createNSData().get()];
         if (attributedString)
-            [itemsToRegister addRepresentingObject:attributedString];
+            [representationsToRegister addRepresentingObject:attributedString];
     }
 
+    if (content.dataInRTFDFormat)
+        [representationsToRegister addData:content.dataInRTFDFormat->createNSData().get() forType:(NSString *)kUTTypeFlatRTFD];
+
     if (content.dataInRTFFormat)
-        [itemsToRegister addData:content.dataInRTFFormat->createNSData().get() forType:(NSString *)kUTTypeRTF];
+        [representationsToRegister addData:content.dataInRTFFormat->createNSData().get() forType:(NSString *)kUTTypeRTF];
 
     if (!content.dataInStringFormat.isEmpty())
-        addRepresentationsForPlainText(itemsToRegister.get(), content.dataInStringFormat);
+        addRepresentationsForPlainText(representationsToRegister.get(), content.dataInStringFormat);
 
-    [m_pasteboard setItemsUsingRegistrationInfoLists:@[ itemsToRegister.get() ]];
-#else
-    UNUSED_PARAM(content);
+    registerItemToPasteboard(representationsToRegister.get(), m_pasteboard.get());
 #endif
 }
 
-void PlatformPasteboard::write(const PasteboardWebContent& content)
+void PlatformPasteboard::write(const PasteboardImage& pasteboardImage)
 {
-    if ([m_pasteboard respondsToSelector:@selector(setItemsUsingRegistrationInfoLists:)]) {
-        writeObjectRepresentations(content);
-        return;
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 110000
+    RetainPtr<NSMutableDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]);
+    if (!pasteboardImage.resourceMIMEType.isNull()) {
+        [representations setObject:pasteboardImage.resourceData->createNSData().get() forKey:pasteboardImage.resourceMIMEType];
+        if (!pasteboardImage.url.url.isNull())
+            [representations setObject:(NSURL *)pasteboardImage.url.url forKey:(NSString *)kUTTypeURL];
     }
 
-    RetainPtr<NSMutableDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]);
-    [representations addEntriesFromDictionary:richTextRepresentationsForPasteboardWebContent(content).autorelease()];
-
-    NSString *textAsString = content.dataInStringFormat;
-    [representations setValue:[textAsString dataUsingEncoding:NSUTF8StringEncoding] forKey:(NSString *)kUTTypeUTF8PlainText];
-    [representations setValue:[textAsString dataUsingEncoding:NSUTF16StringEncoding] forKey:(NSString *)kUTTypeUTF16PlainText];
-    // FIXME: We vend "public.text" here for backwards compatibility with pre-iOS 11 apps. In the future, we should stop vending this UTI,
-    // and instead set data for concrete plain text types. See <https://bugs.webkit.org/show_bug.cgi?id=173317>.
-    [representations setValue:textAsString forKey:(NSString *)kUTTypeText];
-
     // Explicitly cast m_pasteboard to UIPasteboard * to work around rdar://problem/33383354.
     ASSERT([m_pasteboard isKindOfClass:getUIPasteboardClass()]);
     [(UIPasteboard *)m_pasteboard setItems:@[representations.get()]];
-}
+#else
+    auto representationsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);
 
-void PlatformPasteboard::writeObjectRepresentations(const PasteboardImage& pasteboardImage)
-{
-#if ENABLE(DATA_INTERACTION)
-    RetainPtr<WebItemProviderRegistrationInfoList> itemsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);
-
     auto& types = pasteboardImage.clientTypes;
     auto& data = ""
     ASSERT(types.size() == data.size());
     for (size_t i = 0, size = types.size(); i < size; ++i)
-        [itemsToRegister addData:data[i]->createNSData().get() forType:types[i]];
+        [representationsToRegister addData:data[i]->createNSData().get() forType:types[i]];
 
     if (pasteboardImage.resourceData && !pasteboardImage.resourceMIMEType.isEmpty()) {
         auto utiOrMIMEType = pasteboardImage.resourceMIMEType;
@@ -299,67 +325,26 @@
             utiOrMIMEType = UTIFromMIMEType(utiOrMIMEType);
 
         auto imageData = pasteboardImage.resourceData->createNSData();
-        [itemsToRegister addData:imageData.get() forType:(NSString *)utiOrMIMEType];
-        [itemsToRegister setEstimatedDisplayedSize:pasteboardImage.imageSize];
-        [itemsToRegister setSuggestedName:pasteboardImage.suggestedName];
+        [representationsToRegister addData:imageData.get() forType:(NSString *)utiOrMIMEType];
+        [representationsToRegister setPreferredPresentationSize:pasteboardImage.imageSize];
+        [representationsToRegister setSuggestedName:pasteboardImage.suggestedName];
     }
 
+    // FIXME: When writing a PasteboardImage, we currently always place the image data at a higer fidelity than the
+    // associated image URL. However, in the case of an image enclosed by an anchor, we might want to consider the
+    // the URL (i.e. the anchor's href attribute) to be a higher fidelity representation.
     if (!pasteboardImage.url.url.isEmpty()) {
-        NSURL *nsURL = pasteboardImage.url.url;
-        if (nsURL)
-            [itemsToRegister addRepresentingObject:nsURL];
+        if (NSURL *nsURL = pasteboardImage.url.url)
+            [representationsToRegister addRepresentingObject:nsURL];
     }
 
-    [m_pasteboard setItemsUsingRegistrationInfoLists:@[ itemsToRegister.get() ]];
-#else
-    UNUSED_PARAM(pasteboardImage);
+    registerItemToPasteboard(representationsToRegister.get(), m_pasteboard.get());
 #endif
 }
 
-void PlatformPasteboard::write(const PasteboardImage& pasteboardImage)
-{
-    if ([m_pasteboard respondsToSelector:@selector(setItemsUsingRegistrationInfoLists:)]) {
-        writeObjectRepresentations(pasteboardImage);
-        return;
-    }
-
-    RetainPtr<NSMutableDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]);
-    if (!pasteboardImage.resourceMIMEType.isNull()) {
-        [representations setObject:pasteboardImage.resourceData->createNSData().get() forKey:pasteboardImage.resourceMIMEType];
-        if (!pasteboardImage.url.url.isNull())
-            [representations setObject:(NSURL *)pasteboardImage.url.url forKey:(NSString *)kUTTypeURL];
-    }
-
-    // Explicitly cast m_pasteboard to UIPasteboard * to work around rdar://problem/33383354.
-    ASSERT([m_pasteboard isKindOfClass:getUIPasteboardClass()]);
-    [(UIPasteboard *)m_pasteboard setItems:@[representations.get()]];
-}
-
-void PlatformPasteboard::writeObjectRepresentations(const String& pasteboardType, const String& text)
-{
-#if ENABLE(DATA_INTERACTION)
-    RetainPtr<WebItemProviderRegistrationInfoList> itemsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);
-
-    NSString *pasteboardTypeAsNSString = pasteboardType;
-    if (!text.isEmpty() && pasteboardTypeAsNSString.length) {
-        if (UTTypeConformsTo((__bridge CFStringRef)pasteboardTypeAsNSString, kUTTypeURL) || UTTypeConformsTo((__bridge CFStringRef)pasteboardTypeAsNSString, kUTTypeText))
-            addRepresentationsForPlainText(itemsToRegister.get(), text);
-    }
-
-    [m_pasteboard setItemsUsingRegistrationInfoLists:@[ itemsToRegister.get() ]];
-#else
-    UNUSED_PARAM(pasteboardType);
-    UNUSED_PARAM(text);
-#endif
-}
-
 void PlatformPasteboard::write(const String& pasteboardType, const String& text)
 {
-    if ([m_pasteboard respondsToSelector:@selector(setItemsUsingRegistrationInfoLists:)]) {
-        writeObjectRepresentations(pasteboardType, text);
-        return;
-    }
-
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 110000
     RetainPtr<NSDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]);
 
     NSString *textAsString = text;
@@ -378,35 +363,39 @@
     // Explicitly cast m_pasteboard to UIPasteboard * to work around rdar://problem/33383354.
     ASSERT([m_pasteboard isKindOfClass:getUIPasteboardClass()]);
     [(UIPasteboard *)m_pasteboard setItems:@[representations.get()]];
+#else
+    auto representationsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);
+
+    NSString *pasteboardTypeAsNSString = pasteboardType;
+    if (!text.isEmpty() && pasteboardTypeAsNSString.length) {
+        auto pasteboardTypeAsCFString = (CFStringRef)pasteboardTypeAsNSString;
+        if (UTTypeConformsTo(pasteboardTypeAsCFString, kUTTypeURL) || UTTypeConformsTo(pasteboardTypeAsCFString, kUTTypeText))
+            addRepresentationsForPlainText(representationsToRegister.get(), text);
+        else
+            [representationsToRegister addData:[pasteboardTypeAsNSString dataUsingEncoding:NSUTF8StringEncoding] forType:pasteboardType];
+    }
+
+    registerItemToPasteboard(representationsToRegister.get(), m_pasteboard.get());
+#endif
 }
 
-void PlatformPasteboard::writeObjectRepresentations(const PasteboardURL& url)
+void PlatformPasteboard::write(const PasteboardURL& url)
 {
-#if ENABLE(DATA_INTERACTION)
-    RetainPtr<WebItemProviderRegistrationInfoList> itemsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 110000
+    write(kUTTypeURL, url.url.string());
+#else
+    auto representationsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);
 
     if (NSURL *nsURL = url.url) {
-        [itemsToRegister addRepresentingObject:nsURL];
         if (!url.title.isEmpty())
             nsURL._title = url.title;
+        [representationsToRegister addRepresentingObject:nsURL];
     }
 
-    [m_pasteboard setItemsUsingRegistrationInfoLists:@[ itemsToRegister.get() ]];
-#else
-    UNUSED_PARAM(url);
+    registerItemToPasteboard(representationsToRegister.get(), m_pasteboard.get());
 #endif
 }
 
-void PlatformPasteboard::write(const PasteboardURL& url)
-{
-    if ([m_pasteboard respondsToSelector:@selector(setItemsUsingRegistrationInfoLists:)]) {
-        writeObjectRepresentations(url);
-        return;
-    }
-
-    write(kUTTypeURL, url.url.string());
-}
-
 int PlatformPasteboard::count()
 {
     return [m_pasteboard numberOfItems];

Modified: trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.h (220864 => 220865)


--- trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.h	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.h	2017-08-17 18:34:15 UTC (rev 220865)
@@ -60,8 +60,9 @@
 - (void)addRepresentingObject:(id <UIItemProviderWriting>)object;
 - (void)addData:(NSData *)data forType:(NSString *)typeIdentifier;
 
-@property (nonatomic) CGSize estimatedDisplayedSize;
+@property (nonatomic) CGSize preferredPresentationSize;
 @property (nonatomic, copy) NSString *suggestedName;
+@property (nonatomic, readonly, nullable) UIItemProvider *itemProvider;
 
 - (NSUInteger)numberOfItems;
 - (nullable WebItemProviderRegistrationInfo *)itemAtIndex:(NSUInteger)index;

Modified: trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm (220864 => 220865)


--- trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm	2017-08-17 18:34:15 UTC (rev 220865)
@@ -28,8 +28,10 @@
 
 #if ENABLE(DATA_INTERACTION)
 
+#import <Foundation/NSItemProvider.h>
 #import <Foundation/NSProgress.h>
 #import <MobileCoreServices/MobileCoreServices.h>
+#import <UIKit/NSItemProvider+UIKitAdditions.h>
 #import <UIKit/UIColor.h>
 #import <UIKit/UIImage.h>
 #import <WebCore/FileSystemIOS.h>
@@ -45,12 +47,6 @@
 SOFT_LINK_CLASS(UIKit, UIImage)
 SOFT_LINK_CLASS(UIKit, UIItemProvider)
 
-// FIXME: Remove once +objectWithItemProviderData:typeIdentifier:error: is available in the public SDK.
-@interface NSObject (Foundation_NSItemProvider_Staging)
-+ (id <NSItemProviderReading>)objectWithItemProviderData:(NSData *)data typeIdentifier:(NSString *)typeIdentifier error:(NSError **)outError;
-- (id <NSItemProviderReading>)initWithItemProviderData:(NSData *)data typeIdentifier:(NSString *)typeIdentifier error:(NSError **)outError;
-@end
-
 using namespace WebCore;
 
 typedef void(^ItemProviderDataLoadCompletionHandler)(NSData *, NSError *);
@@ -100,7 +96,7 @@
 
 @interface WebItemProviderRegistrationInfoList ()
 {
-    RetainPtr<NSMutableArray> _items;
+    RetainPtr<NSMutableArray> _representations;
 }
 @end
 
@@ -109,8 +105,8 @@
 - (instancetype)init
 {
     if (self = [super init]) {
-        _items = adoptNS([[NSMutableArray alloc] init]);
-        _estimatedDisplayedSize = CGSizeZero;
+        _representations = adoptNS([[NSMutableArray alloc] init]);
+        _preferredPresentationSize = CGSizeZero;
     }
 
     return self;
@@ -124,18 +120,18 @@
 
 - (void)addData:(NSData *)data forType:(NSString *)typeIdentifier
 {
-    [_items addObject:[[[WebItemProviderRegistrationInfo alloc] initWithRepresentingObject:nil typeIdentifier:typeIdentifier data:data] autorelease]];
+    [_representations addObject:[[[WebItemProviderRegistrationInfo alloc] initWithRepresentingObject:nil typeIdentifier:typeIdentifier data:data] autorelease]];
 }
 
 - (void)addRepresentingObject:(id <UIItemProviderWriting>)object
 {
     ASSERT([object conformsToProtocol:@protocol(UIItemProviderWriting)]);
-    [_items addObject:[[[WebItemProviderRegistrationInfo alloc] initWithRepresentingObject:object typeIdentifier:nil data:nil] autorelease]];
+    [_representations addObject:[[[WebItemProviderRegistrationInfo alloc] initWithRepresentingObject:object typeIdentifier:nil data:nil] autorelease]];
 }
 
 - (NSUInteger)numberOfItems
 {
-    return [_items count];
+    return [_representations count];
 }
 
 - (WebItemProviderRegistrationInfo *)itemAtIndex:(NSUInteger)index
@@ -143,7 +139,7 @@
     if (index >= self.numberOfItems)
         return nil;
 
-    return [_items objectAtIndex:index];
+    return [_representations objectAtIndex:index];
 }
 
 - (void)enumerateItems:(void (^)(WebItemProviderRegistrationInfo *, NSUInteger))block
@@ -152,6 +148,49 @@
         block([self itemAtIndex:index], index);
 }
 
+- (UIItemProvider *)itemProvider
+{
+    if (!self.numberOfItems)
+        return nil;
+
+    auto itemProvider = adoptNS([allocUIItemProviderInstance() init]);
+    for (WebItemProviderRegistrationInfo *representation in _representations.get()) {
+        if (representation.representingObject) {
+            [itemProvider registerObject:representation.representingObject visibility:UIItemProviderRepresentationOptionsVisibilityAll];
+            continue;
+        }
+
+        if (!representation.typeIdentifier.length || !representation.data.length)
+            continue;
+
+        RetainPtr<NSData> itemData = representation.data;
+        [itemProvider registerDataRepresentationForTypeIdentifier:representation.typeIdentifier visibility:UIItemProviderRepresentationOptionsVisibilityAll loadHandler:[itemData] (ItemProviderDataLoadCompletionHandler completionHandler) -> NSProgress * {
+            completionHandler(itemData.get(), nil);
+            return nil;
+        }];
+    }
+    [itemProvider setPreferredPresentationSize:self.preferredPresentationSize];
+    [itemProvider setSuggestedName:self.suggestedName];
+    return itemProvider.autorelease();
+}
+
+- (NSString *)description
+{
+    __block NSMutableString *description = [NSMutableString string];
+    [description appendFormat:@"<%@: %p", [self class], self];
+    [self enumerateItems:^(WebItemProviderRegistrationInfo *item, NSUInteger index) {
+        if (index)
+            [description appendString:@","];
+
+        if (item.representingObject)
+            [description appendFormat:@" (%@: %p)", [item.representingObject class], item.representingObject];
+        else
+            [description appendFormat:@" ('%@' => %tu bytes)", item.typeIdentifier, item.data.length];
+    }];
+    [description appendString:@">"];
+    return description;
+}
+
 @end
 
 @interface WebItemProviderPasteboard ()
@@ -251,41 +290,6 @@
     return [_itemProviders count];
 }
 
-- (void)setItemsUsingRegistrationInfoLists:(NSArray<WebItemProviderRegistrationInfoList *> *)itemLists
-{
-    NSMutableArray *providers = [NSMutableArray array];
-    for (WebItemProviderRegistrationInfoList *itemList in itemLists) {
-        if (!itemList.numberOfItems)
-            continue;
-
-        auto itemProvider = adoptNS([allocUIItemProviderInstance() init]);
-        [itemList enumerateItems:[itemProvider] (WebItemProviderRegistrationInfo *item, NSUInteger) {
-            if (item.representingObject) {
-                [itemProvider registerObject:item.representingObject visibility:UIItemProviderRepresentationOptionsVisibilityAll];
-                return;
-            }
-
-            if (!item.typeIdentifier.length || !item.data.length)
-                return;
-
-            RetainPtr<NSData> itemData = item.data;
-            [itemProvider registerDataRepresentationForTypeIdentifier:item.typeIdentifier visibility:UIItemProviderRepresentationOptionsVisibilityAll loadHandler:[itemData] (ItemProviderDataLoadCompletionHandler completionHandler) -> NSProgress * {
-                completionHandler(itemData.get(), nil);
-                return nil;
-            }];
-        }];
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-        [itemProvider setEstimatedDisplayedSize:itemList.estimatedDisplayedSize];
-#pragma clang diagnostic pop
-        [itemProvider setSuggestedName:itemList.suggestedName];
-        [providers addObject:itemProvider.get()];
-    }
-
-    self.itemProviders = providers;
-    _registrationInfoLists = itemLists;
-}
-
 - (NSData *)_preLoadedDataConformingToType:(NSString *)typeIdentifier forItemProviderAtIndex:(NSUInteger)index
 {
     if ([_typeToFileURLMaps count] != [_itemProviders count]) {
@@ -364,13 +368,8 @@
         if (!preloadedData)
             return;
 
-        if ([readableClass respondsToSelector:@selector(objectWithItemProviderData:typeIdentifier:error:)]) {
-            if (id <NSItemProviderReading> readObject = [readableClass objectWithItemProviderData:preloadedData typeIdentifier:(NSString *)typeIdentifierToLoad error:nil])
-                [values addObject:readObject];
-        } else {
-            if (auto readObject = adoptNS([[readableClass alloc] initWithItemProviderData:preloadedData typeIdentifier:(NSString *)typeIdentifierToLoad error:nil]))
-                [values addObject:readObject.get()];
-        }
+        if (id <NSItemProviderReading> readObject = [readableClass objectWithItemProviderData:preloadedData typeIdentifier:(NSString *)typeIdentifierToLoad error:nil])
+            [values addObject:readObject];
     }];
 
     return values.autorelease();
@@ -546,6 +545,11 @@
     [_itemProviders enumerateObjectsUsingBlock:block];
 }
 
+- (void)setRegistrationInfoLists:(NSArray <WebItemProviderRegistrationInfoList *> *)infoLists
+{
+    _registrationInfoLists = infoLists;
+}
+
 @end
 
 #endif // ENABLE(DATA_INTERACTION)

Modified: trunk/Source/WebKit/ChangeLog (220864 => 220865)


--- trunk/Source/WebKit/ChangeLog	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Source/WebKit/ChangeLog	2017-08-17 18:34:15 UTC (rev 220865)
@@ -1,3 +1,25 @@
+2017-08-17  Wenson Hsieh  <[email protected]>
+
+        [iOS] Respect type fidelities when copying image elements to the pasteboard
+        https://bugs.webkit.org/show_bug.cgi?id=175638
+        <rdar://problem/26556043>
+
+        Reviewed by Ryosuke Niwa.
+
+        Currently, we treat the case when copying an image enclosed by a link by only writing a URL to the pasteboard.
+        This patch tweaks logic in WebPage::performActionOnElement to write both an image and a link to the pasteboard
+        if the hit-tested image element is enclosed by an anchor.
+
+        * Platform/spi/ios/UIKitSPI.h:
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::containingLinkElement):
+
+        Tweak this helper to be more restrictive when finding an enclosing 'link' -- only return an element if isLink()
+        is true, and it is an HTMLAnchorElement. Currently, the isLink() also matches HTMLLinkElements, but this isn't
+        the intention here.
+
+        (WebKit::WebPage::performActionOnElement):
+
 2017-08-17  Jacobo Aragunde PĂ©rez  <[email protected]>
 
         [WPE][GTK] Ensure proper casting of data in gvariants

Modified: trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h (220864 => 220865)


--- trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h	2017-08-17 18:34:15 UTC (rev 220865)
@@ -876,7 +876,7 @@
 #if ENABLE(DRAG_SUPPORT)
 
 @interface UIItemProvider : NSItemProvider
-@property (nonatomic) CGSize estimatedDisplayedSize;
+@property (nonatomic) CGSize preferredPresentationSize;
 @end
 
 WTF_EXTERN_C_BEGIN

Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (220864 => 220865)


--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2017-08-17 18:34:15 UTC (rev 220865)
@@ -2410,11 +2410,11 @@
     computeAutocorrectionContext(m_page->focusController().focusedOrMainFrame(), contextBefore, markedText, selectedText, contextAfter, location, length);
 }
 
-static Element* containingLinkElement(Element* element)
+static HTMLAnchorElement* containingLinkElement(Element* element)
 {
     for (auto& currentElement : elementLineage(element)) {
-        if (currentElement.isLink())
-            return &currentElement;
+        if (currentElement.isLink() && is<HTMLAnchorElement>(currentElement))
+            return downcast<HTMLAnchorElement>(&currentElement);
     }
     return nullptr;
 }
@@ -2627,11 +2627,16 @@
 
     if (static_cast<SheetAction>(action) == SheetAction::Copy) {
         if (is<RenderImage>(*element.renderer())) {
-            Element* linkElement = containingLinkElement(&element);
-            if (!linkElement)
-                m_interactionNode->document().frame()->editor().writeImageToPasteboard(*Pasteboard::createForCopyAndPaste(), element, URL(), String());
-            else
-                m_interactionNode->document().frame()->editor().copyURL(linkElement->document().completeURL(stripLeadingAndTrailingHTMLSpaces(linkElement->attributeWithoutSynchronization(HTMLNames::hrefAttr))), linkElement->textContent());
+            URL url;
+            String title;
+            if (auto* linkElement = containingLinkElement(&element)) {
+                url = ""
+                title = linkElement->attributeWithoutSynchronization(HTMLNames::titleAttr);
+                if (!title.length())
+                    title = linkElement->textContent();
+                title = stripLeadingAndTrailingHTMLSpaces(title);
+            }
+            m_interactionNode->document().frame()->editor().writeImageToPasteboard(*Pasteboard::createForCopyAndPaste(), element, url, title);
         } else if (element.isLink()) {
             m_interactionNode->document().frame()->editor().copyURL(element.document().completeURL(stripLeadingAndTrailingHTMLSpaces(element.attributeWithoutSynchronization(HTMLNames::hrefAttr))), element.textContent());
         }

Modified: trunk/Tools/ChangeLog (220864 => 220865)


--- trunk/Tools/ChangeLog	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Tools/ChangeLog	2017-08-17 18:34:15 UTC (rev 220865)
@@ -1,3 +1,32 @@
+2017-08-17  Wenson Hsieh  <[email protected]>
+
+        [iOS] Respect type fidelities when copying image elements to the pasteboard
+        https://bugs.webkit.org/show_bug.cgi?id=175638
+        <rdar://problem/26556043>
+
+        Reviewed by Ryosuke Niwa.
+
+        Add API tests that simulate copying an image element using the action sheet, and verifying that the pasteboard
+        contains UTIs in order of fidelity (image type before URL). Also pulls out UIKit SPI (UIApplicationInitialize)
+        used in UIPasteboardTests and ActionSheetTests into a common UIKitSPI header.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/ios/ActionSheetTests.mm:
+        (-[ActionSheetObserver _webView:actionsForElement:defaultActions:]):
+        (TestWebKitAPI::TEST):
+        (TestWebKitAPI::presentActionSheetAndChooseAction):
+        (-[ActionSheetObserver waitForActionSheetAfterBlock:]): Deleted.
+        * TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
+        (checkEstimatedSize):
+        (checkSuggestedNameAndEstimatedSize):
+
+        Replace -estimatedDisplayedSize with its non-deprecated counterpart, -preferredPresentationSize.
+
+        * TestWebKitAPI/Tests/ios/UIPasteboardTests.mm:
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/ios/DataInteractionSimulator.h:
+        * TestWebKitAPI/ios/UIKitSPI.h: Added.
+
 2017-08-17  Jonathan Bedard  <[email protected]>
 
         Recursively create resource load statistics folder for testing

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (220864 => 220865)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-08-17 18:34:15 UTC (rev 220865)
@@ -1691,6 +1691,7 @@
 		F47D30EB1ED28619000482E1 /* apple.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = apple.gif; sourceTree = "<group>"; };
 		F47D30ED1ED28A6C000482E1 /* gif-and-file-input.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "gif-and-file-input.html"; sourceTree = "<group>"; };
 		F4856CA21E6498A8009D7EE7 /* attachment-element.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "attachment-element.html"; sourceTree = "<group>"; };
+		F493247C1F44DF8D006F4336 /* UIKitSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UIKitSPI.h; sourceTree = "<group>"; };
 		F4A32EC31F05F3780047C544 /* dragstart-change-selection-offscreen.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "dragstart-change-selection-offscreen.html"; sourceTree = "<group>"; };
 		F4A32ECA1F0642F40047C544 /* contenteditable-in-iframe.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "contenteditable-in-iframe.html"; sourceTree = "<group>"; };
 		F4B825D61EF4DBD4006E417F /* compressed-files.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = "compressed-files.zip"; sourceTree = "<group>"; };
@@ -1981,6 +1982,7 @@
 				F4D4F3B51E4E2BCB00BB2767 /* DataInteractionSimulator.h */,
 				F4D4F3B41E4E2BCB00BB2767 /* DataInteractionSimulator.mm */,
 				2E7765CC16C4D80A00BA2BB1 /* mainIOS.mm */,
+				F493247C1F44DF8D006F4336 /* UIKitSPI.h */,
 			);
 			path = ios;
 			sourceTree = "<group>";

Modified: trunk/Tools/TestWebKitAPI/Tests/ios/ActionSheetTests.mm (220864 => 220865)


--- trunk/Tools/TestWebKitAPI/Tests/ios/ActionSheetTests.mm	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/ActionSheetTests.mm	2017-08-17 18:34:15 UTC (rev 220865)
@@ -30,34 +30,27 @@
 #import "InstanceMethodSwizzler.h"
 #import "PlatformUtilities.h"
 #import "TestWKWebView.h"
+#import "UIKitSPI.h"
+#import <MobileCoreServices/MobileCoreServices.h>
 #import <WebKit/WKUIDelegatePrivate.h>
 #import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/_WKActivatedElementInfo.h>
+#import <WebKit/_WKElementAction.h>
+#import <wtf/BlockPtr.h>
 #import <wtf/RetainPtr.h>
 #import <wtf/SoftLinking.h>
 
 @interface ActionSheetObserver : NSObject<WKUIDelegatePrivate>
-@property (nonatomic) BOOL presentedActionSheet;
+@property (nonatomic) BlockPtr<NSArray *(_WKActivatedElementInfo *, NSArray *)> presentationHandler;
 @end
 
 @implementation ActionSheetObserver
 
-- (BOOL)waitForActionSheetAfterBlock:(dispatch_block_t)block
+- (NSArray *)_webView:(WKWebView *)webView actionsForElement:(_WKActivatedElementInfo *)element defaultActions:(NSArray<_WKElementAction *> *)defaultActions
 {
-    _presentedActionSheet = NO;
-    block();
-    while ([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]]) {
-        if (_presentedActionSheet)
-            break;
-    }
-    return _presentedActionSheet;
+    return _presentationHandler ? _presentationHandler(element, defaultActions) : defaultActions;
 }
 
-- (NSArray *)_webView:(ActionSheetObserver *)webView actionsForElement:(_WKActivatedElementInfo *)element defaultActions:(NSArray<_WKElementAction *> *)defaultActions
-{
-    _presentedActionSheet = YES;
-    return defaultActions;
-}
-
 @end
 
 namespace TestWebKitAPI {
@@ -87,12 +80,100 @@
     [webView stringByEvaluatingJavaScript:@"selectTextNode(h1.childNodes[0])"];
 
     EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"getSelection().toString()"]);
-    [observer waitForActionSheetAfterBlock:^() {
-        [webView _simulateLongPressActionAtLocation:CGPointMake(200, 200)];
+
+    __block bool done = false;
+    [observer setPresentationHandler:^(_WKActivatedElementInfo *element, NSArray *actions) {
+        done = true;
+        return actions;
     }];
+    [webView _simulateLongPressActionAtLocation:CGPointMake(200, 200)];
+    TestWebKitAPI::Util::run(&done);
+
     EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"getSelection().toString()"]);
 }
 
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000
+
+static void presentActionSheetAndChooseAction(WKWebView *webView, ActionSheetObserver *observer, CGPoint location, _WKElementActionType actionType)
+{
+    __block RetainPtr<_WKElementAction> copyAction;
+    __block RetainPtr<_WKActivatedElementInfo> copyElement;
+    __block bool done = false;
+    [observer setPresentationHandler:^(_WKActivatedElementInfo *element, NSArray *actions) {
+        copyElement = element;
+        for (_WKElementAction *action in actions) {
+            if (action.type == actionType)
+                copyAction = action;
+        }
+        done = true;
+        return @[ copyAction.get() ];
+    }];
+    [webView _simulateLongPressActionAtLocation:location];
+    TestWebKitAPI::Util::run(&done);
+
+    EXPECT_TRUE(!!copyAction);
+    EXPECT_TRUE(!!copyElement);
+    [copyAction runActionWithElementInfo:copyElement.get()];
+}
+
+TEST(ActionSheetTests, CopyImageElementWithHREF)
+{
+    UIApplicationInitialize();
+    [UIPasteboard generalPasteboard].items = @[ ];
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+    auto observer = adoptNS([[ActionSheetObserver alloc] init]);
+    [webView setUIDelegate:observer.get()];
+    [webView synchronouslyLoadTestPageNamed:@"image-in-link-and-input"];
+
+    presentActionSheetAndChooseAction(webView.get(), observer.get(), CGPointMake(100, 50), _WKElementActionTypeCopy);
+
+    __block bool done = false;
+    [webView _doAfterNextPresentationUpdate:^() {
+        NSArray <NSString *> *pasteboardTypes = [[UIPasteboard generalPasteboard] pasteboardTypes];
+        EXPECT_EQ(2UL, pasteboardTypes.count);
+        EXPECT_WK_STREQ((NSString *)kUTTypePNG, pasteboardTypes.firstObject);
+        EXPECT_WK_STREQ((NSString *)kUTTypeURL, pasteboardTypes.lastObject);
+        NSArray <NSItemProvider *> *itemProviders = [[UIPasteboard generalPasteboard] itemProviders];
+        EXPECT_EQ(1UL, itemProviders.count);
+        NSItemProvider *itemProvider = itemProviders.firstObject;
+        EXPECT_EQ(2UL, itemProvider.registeredTypeIdentifiers.count);
+        EXPECT_WK_STREQ((NSString *)kUTTypePNG, itemProvider.registeredTypeIdentifiers.firstObject);
+        EXPECT_WK_STREQ((NSString *)kUTTypeURL, itemProvider.registeredTypeIdentifiers.lastObject);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+}
+
+TEST(ActionSheetTests, CopyImageElementWithoutHREF)
+{
+    UIApplicationInitialize();
+    [UIPasteboard generalPasteboard].items = @[ ];
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+    auto observer = adoptNS([[ActionSheetObserver alloc] init]);
+    [webView setUIDelegate:observer.get()];
+    [webView synchronouslyLoadTestPageNamed:@"image-and-contenteditable"];
+
+    presentActionSheetAndChooseAction(webView.get(), observer.get(), CGPointMake(100, 100), _WKElementActionTypeCopy);
+
+    __block bool done = false;
+    [webView _doAfterNextPresentationUpdate:^() {
+        NSArray <NSString *> *pasteboardTypes = [[UIPasteboard generalPasteboard] pasteboardTypes];
+        EXPECT_EQ(1UL, pasteboardTypes.count);
+        EXPECT_WK_STREQ((NSString *)kUTTypePNG, pasteboardTypes.firstObject);
+        NSArray <NSItemProvider *> *itemProviders = [[UIPasteboard generalPasteboard] itemProviders];
+        EXPECT_EQ(1UL, itemProviders.count);
+        NSItemProvider *itemProvider = itemProviders.firstObject;
+        EXPECT_EQ(1UL, itemProvider.registeredTypeIdentifiers.count);
+        EXPECT_WK_STREQ((NSString *)kUTTypePNG, itemProvider.registeredTypeIdentifiers.firstObject);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+}
+
+#endif // __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000
+
 } // namespace TestWebKitAPI
 
 #endif // PLATFORM(IOS)

Modified: trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm (220864 => 220865)


--- trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2017-08-17 18:34:15 UTC (rev 220865)
@@ -32,6 +32,7 @@
 #import "TestWKWebView.h"
 #import "WKWebViewConfigurationExtras.h"
 #import <MobileCoreServices/MobileCoreServices.h>
+#import <UIKit/NSItemProvider+UIKitAdditions.h>
 #import <WebKit/WKPreferencesPrivate.h>
 #import <WebKit/WKProcessPoolPrivate.h>
 #import <WebKit/WKWebViewConfigurationPrivate.h>
@@ -131,8 +132,8 @@
 static void checkEstimatedSize(DataInteractionSimulator *simulator, CGSize estimatedSize)
 {
     UIItemProvider *sourceItemProvider = [simulator sourceItemProviders].firstObject;
-    EXPECT_EQ(estimatedSize.width, sourceItemProvider.estimatedDisplayedSize.width);
-    EXPECT_EQ(estimatedSize.height, sourceItemProvider.estimatedDisplayedSize.height);
+    EXPECT_EQ(estimatedSize.width, sourceItemProvider.preferredPresentationSize.width);
+    EXPECT_EQ(estimatedSize.height, sourceItemProvider.preferredPresentationSize.height);
 }
 
 static void checkSuggestedNameAndEstimatedSize(DataInteractionSimulator *simulator, NSString *suggestedName, CGSize estimatedSize)
@@ -139,8 +140,8 @@
 {
     UIItemProvider *sourceItemProvider = [simulator sourceItemProviders].firstObject;
     EXPECT_WK_STREQ(suggestedName.UTF8String, sourceItemProvider.suggestedName.UTF8String);
-    EXPECT_EQ(estimatedSize.width, sourceItemProvider.estimatedDisplayedSize.width);
-    EXPECT_EQ(estimatedSize.height, sourceItemProvider.estimatedDisplayedSize.height);
+    EXPECT_EQ(estimatedSize.width, sourceItemProvider.preferredPresentationSize.width);
+    EXPECT_EQ(estimatedSize.height, sourceItemProvider.preferredPresentationSize.height);
 }
 
 static void checkStringArraysAreEqual(NSArray<NSString *> *expected, NSArray<NSString *> *observed)

Modified: trunk/Tools/TestWebKitAPI/Tests/ios/UIPasteboardTests.mm (220864 => 220865)


--- trunk/Tools/TestWebKitAPI/Tests/ios/UIPasteboardTests.mm	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/UIPasteboardTests.mm	2017-08-17 18:34:15 UTC (rev 220865)
@@ -29,6 +29,7 @@
 
 #import "PlatformUtilities.h"
 #import "TestWKWebView.h"
+#import "UIKitSPI.h"
 #import <MobileCoreServices/MobileCoreServices.h>
 #import <UIKit/UIPasteboard.h>
 #import <WebKit/WKPreferencesPrivate.h>
@@ -35,9 +36,6 @@
 #import <WebKit/WKWebViewPrivate.h>
 #import <wtf/SoftLinking.h>
 
-SOFT_LINK_FRAMEWORK(UIKit)
-SOFT_LINK(UIKit, UIApplicationInitialize, void, (void), ())
-
 namespace TestWebKitAPI {
 
 NSData *dataForPasteboardType(CFStringRef type)
@@ -69,9 +67,7 @@
     [webView stringByEvaluatingJavaScript:@"document.execCommand('copy')"];
 
     auto utf8Result = adoptNS([[NSString alloc] initWithData:dataForPasteboardType(kUTTypeUTF8PlainText) encoding:NSUTF8StringEncoding]);
-    auto utf16Result = adoptNS([[NSString alloc] initWithData:dataForPasteboardType(kUTTypeUTF16PlainText) encoding:NSUTF16StringEncoding]);
     EXPECT_WK_STREQ("Hello world", [utf8Result UTF8String]);
-    EXPECT_WK_STREQ("Hello world", [utf16Result UTF8String]);
 }
 
 TEST(UIPasteboardTests, CopyRichTextWritesConcreteTypes)
@@ -81,9 +77,7 @@
     [webView stringByEvaluatingJavaScript:@"document.execCommand('copy')"];
 
     auto utf8Result = adoptNS([[NSString alloc] initWithData:dataForPasteboardType(kUTTypeUTF8PlainText) encoding:NSUTF8StringEncoding]);
-    auto utf16Result = adoptNS([[NSString alloc] initWithData:dataForPasteboardType(kUTTypeUTF16PlainText) encoding:NSUTF16StringEncoding]);
     EXPECT_WK_STREQ("Hello world", [utf8Result UTF8String]);
-    EXPECT_WK_STREQ("Hello world", [utf16Result UTF8String]);
 }
 
 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000

Modified: trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h (220864 => 220865)


--- trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h	2017-08-17 18:21:27 UTC (rev 220864)
+++ trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h	2017-08-17 18:34:15 UTC (rev 220865)
@@ -41,10 +41,6 @@
 @property (nonatomic, copy, setter=_setTitle:) NSString *_title;
 @end
 
-@interface UIItemProvider : NSItemProvider
-@property (nonatomic) CGSize estimatedDisplayedSize;
-@end
-
 #define UIItemProviderRepresentationOptionsVisibilityAll NSItemProviderRepresentationVisibilityAll
 
 @protocol UIItemProviderReading <NSItemProviderReading>

Copied: trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h (from rev 220864, trunk/Source/WebCore/platform/ios/AbstractPasteboard.h) (0 => 220865)


--- trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h	2017-08-17 18:34:15 UTC (rev 220865)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#if PLATFORM(IOS)
+
+#if USE(APPLE_INTERNAL_SDK)
+
+#import <UIKit/UIApplication_Private.h>
+
+#else
+
+WTF_EXTERN_C_BEGIN
+
+void UIApplicationInitialize(void);
+
+WTF_EXTERN_C_END
+
+#endif
+
+#endif // PLATFORM(IOS)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to