Diff
Modified: trunk/Source/WebCore/ChangeLog (261637 => 261638)
--- trunk/Source/WebCore/ChangeLog 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebCore/ChangeLog 2020-05-13 19:43:10 UTC (rev 261638)
@@ -1,3 +1,41 @@
+2020-05-13 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [iOS] "Copy" context menu action for attachment element does not work in Mail
+ https://bugs.webkit.org/show_bug.cgi?id=211817
+ <rdar://problem/58043110>
+
+ Reviewed by Tim Horton.
+
+ Minor refactoring to help support writing attachment data to the pasteboard when using context menu actions to
+ copy an attachment element on iOS. See below for more details, as well as the WebKit ChangeLog entry.
+
+ Test: WKAttachmentTestsIOS.CopyAttachmentUsingElementAction
+
+ * editing/Editor.cpp:
+ (WebCore::Editor::platformContentTypeForBlobType const):
+ (WebCore::Editor::promisedAttachmentInfo):
+
+ Move promisedAttachmentInfo out of DragController and into Editor, so that it is accessible outside of drag
+ and drop code.
+
+ * editing/Editor.h:
+ * editing/cocoa/EditorCocoa.mm:
+ (WebCore::Editor::platformContentTypeForBlobType const):
+
+ Move this private helper function out of DragController as well, and into Editor.
+
+ * page/DragClient.h:
+ * page/DragController.cpp:
+ (WebCore::DragController::startDrag):
+
+ Refactor this to use Editor::promisedAttachmentInfo().
+
+ (WebCore::DragController::platformContentTypeForBlobType const): Deleted.
+ (WebCore::DragController::promisedAttachmentInfo): Deleted.
+ * page/DragController.h:
+ * page/mac/DragControllerMac.mm:
+ (WebCore::DragController::platformContentTypeForBlobType const): Deleted.
+
2020-05-13 Antoine Quint <grao...@apple.com>
[Web Animations] Calling reverse() on an accelerated animation has no effect
Modified: trunk/Source/WebCore/editing/Editor.cpp (261637 => 261638)
--- trunk/Source/WebCore/editing/Editor.cpp 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebCore/editing/Editor.cpp 2020-05-13 19:43:10 UTC (rev 261638)
@@ -124,6 +124,10 @@
#include "ServicesOverlayController.h"
#endif
+#if ENABLE(ATTACHMENT_ELEMENT)
+#include "PromisedAttachmentInfo.h"
+#endif
+
namespace WebCore {
static bool dispatchBeforeInputEvent(Element& element, const AtomString& inputType, const String& data = { }, RefPtr<DataTransfer>&& dataTransfer = nullptr, const Vector<RefPtr<StaticRange>>& targetRanges = { }, Event::IsCancelable cancelable = Event::IsCancelable::Yes)
@@ -3950,6 +3954,11 @@
{
}
+String Editor::platformContentTypeForBlobType(const String& type) const
+{
+ return type;
+}
+
#endif
static Vector<TextList> editableTextListsAtPositionInDescendingOrder(const Position& position)
@@ -4083,6 +4092,33 @@
#if ENABLE(ATTACHMENT_ELEMENT)
+PromisedAttachmentInfo Editor::promisedAttachmentInfo(Element& element)
+{
+ auto* client = this->client();
+ if (!client || !client->supportsClientSideAttachmentData())
+ return { };
+
+ RefPtr<HTMLAttachmentElement> attachment;
+ if (is<HTMLAttachmentElement>(element))
+ attachment = &downcast<HTMLAttachmentElement>(element);
+ else if (is<HTMLImageElement>(element))
+ attachment = downcast<HTMLImageElement>(element).attachmentElement();
+
+ if (!attachment)
+ return { };
+
+ Vector<String> additionalTypes;
+ Vector<RefPtr<SharedBuffer>> additionalData;
+#if PLATFORM(COCOA)
+ getPasteboardTypesAndDataForAttachment(element, additionalTypes, additionalData);
+#endif
+
+ if (auto* file = attachment->file())
+ return { file->url(), platformContentTypeForBlobType(file->type()), file->name(), { }, WTFMove(additionalTypes), WTFMove(additionalData) };
+
+ return { { }, { }, { }, attachment->uniqueIdentifier(), WTFMove(additionalTypes), WTFMove(additionalData) };
+}
+
void Editor::registerAttachmentIdentifier(const String& identifier, const String& contentType, const String& preferredFileName, Ref<SharedBuffer>&& data)
{
if (auto* client = this->client())
Modified: trunk/Source/WebCore/editing/Editor.h (261637 => 261638)
--- trunk/Source/WebCore/editing/Editor.h 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebCore/editing/Editor.h 2020-05-13 19:43:10 UTC (rev 261638)
@@ -92,6 +92,7 @@
struct TextCheckingResult;
#if ENABLE(ATTACHMENT_ELEMENT)
+struct PromisedAttachmentInfo;
struct SerializedAttachmentData;
#endif
@@ -559,6 +560,7 @@
void didInsertAttachmentElement(HTMLAttachmentElement&);
void didRemoveAttachmentElement(HTMLAttachmentElement&);
+ WEBCORE_EXPORT PromisedAttachmentInfo promisedAttachmentInfo(Element&);
#if PLATFORM(COCOA)
void getPasteboardTypesAndDataForAttachment(Element&, Vector<String>& outTypes, Vector<RefPtr<SharedBuffer>>& outData);
#endif
@@ -619,6 +621,8 @@
void notifyClientOfAttachmentUpdates();
#endif
+ String platformContentTypeForBlobType(const String& type) const;
+
void postTextStateChangeNotificationForCut(const String&, const VisibleSelection&);
Document& m_document;
Modified: trunk/Source/WebCore/editing/cocoa/EditorCocoa.mm (261637 => 261638)
--- trunk/Source/WebCore/editing/cocoa/EditorCocoa.mm 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebCore/editing/cocoa/EditorCocoa.mm 2020-05-13 19:43:10 UTC (rev 261638)
@@ -55,6 +55,7 @@
#import "RenderStyle.h"
#import "Settings.h"
#import "Text.h"
+#import "UTIUtilities.h"
#import "WebContentReader.h"
#import "markup.h"
#import <pal/spi/cocoa/NSAttributedStringSPI.h>
@@ -257,4 +258,12 @@
#endif
}
+String Editor::platformContentTypeForBlobType(const String& type) const
+{
+ auto utiType = UTIFromMIMEType(type);
+ if (!utiType.isEmpty())
+ return utiType;
+ return type;
}
+
+}
Modified: trunk/Source/WebCore/page/DragClient.h (261637 => 261638)
--- trunk/Source/WebCore/page/DragClient.h 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebCore/page/DragClient.h 2020-05-13 19:43:10 UTC (rev 261638)
@@ -37,7 +37,10 @@
class Element;
class Frame;
class Image;
+
+#if ENABLE(ATTACHMENT_ELEMENT)
struct PromisedAttachmentInfo;
+#endif
class DragClient {
WTF_MAKE_FAST_ALLOCATED;
Modified: trunk/Source/WebCore/page/DragController.cpp (261637 => 261638)
--- trunk/Source/WebCore/page/DragController.cpp 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebCore/page/DragController.cpp 2020-05-13 19:43:10 UTC (rev 261638)
@@ -1036,7 +1036,7 @@
ASSERT(!image->filenameExtension().isEmpty());
#if ENABLE(ATTACHMENT_ELEMENT)
- auto attachmentInfo = promisedAttachmentInfo(src, element);
+ auto attachmentInfo = src.editor().promisedAttachmentInfo(element);
#else
PromisedAttachmentInfo attachmentInfo;
#endif
@@ -1132,9 +1132,9 @@
PromisedAttachmentInfo promisedAttachment;
if (hasData == HasNonDefaultPasteboardData::No) {
- promisedAttachment = promisedAttachmentInfo(src, attachment);
+ auto& editor = src.editor();
+ promisedAttachment = editor.promisedAttachmentInfo(attachment);
#if PLATFORM(COCOA)
- auto& editor = src.editor();
if (!promisedAttachment && editor.client()) {
// Otherwise, if no file URL is specified, call out to the injected bundle to populate the pasteboard with data.
editor.willWriteSelectionToPasteboard(createLiveRange(src.selection().selection().toNormalizedRange()).get());
@@ -1474,46 +1474,6 @@
#endif
}
-#if !PLATFORM(COCOA)
-
-String DragController::platformContentTypeForBlobType(const String& type) const
-{
- return type;
-}
-
-#endif
-
-#if ENABLE(ATTACHMENT_ELEMENT)
-
-PromisedAttachmentInfo DragController::promisedAttachmentInfo(Frame& frame, Element& element)
-{
- auto* client = frame.editor().client();
- if (!client || !client->supportsClientSideAttachmentData())
- return { };
-
- RefPtr<HTMLAttachmentElement> attachment;
- if (is<HTMLAttachmentElement>(element))
- attachment = &downcast<HTMLAttachmentElement>(element);
- else if (is<HTMLImageElement>(element))
- attachment = downcast<HTMLImageElement>(element).attachmentElement();
-
- if (!attachment)
- return { };
-
- Vector<String> additionalTypes;
- Vector<RefPtr<SharedBuffer>> additionalData;
-#if PLATFORM(COCOA)
- frame.editor().getPasteboardTypesAndDataForAttachment(element, additionalTypes, additionalData);
-#endif
-
- if (auto* file = attachment->file())
- return { file->url(), platformContentTypeForBlobType(file->type()), file->name(), { }, WTFMove(additionalTypes), WTFMove(additionalData) };
-
- return { { }, { }, { }, attachment->uniqueIdentifier(), WTFMove(additionalTypes), WTFMove(additionalData) };
-}
-
-#endif // ENABLE(ATTACHMENT_ELEMENT)
-
#endif // ENABLE(DRAG_SUPPORT)
} // namespace WebCore
Modified: trunk/Source/WebCore/page/DragController.h (261637 => 261638)
--- trunk/Source/WebCore/page/DragController.h 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebCore/page/DragController.h 2020-05-13 19:43:10 UTC (rev 261638)
@@ -137,14 +137,9 @@
bool tryToUpdateDroppedImagePlaceholders(const DragData&);
void removeAllDroppedImagePlaceholders();
- String platformContentTypeForBlobType(const String& type) const;
-
void cleanupAfterSystemDrag();
void declareAndWriteDragImage(DataTransfer&, Element&, const URL&, const String& label);
-#if ENABLE(ATTACHMENT_ELEMENT)
- PromisedAttachmentInfo promisedAttachmentInfo(Frame&, Element&);
-#endif
Page& m_page;
std::unique_ptr<DragClient> m_client;
Modified: trunk/Source/WebCore/page/mac/DragControllerMac.mm (261637 => 261638)
--- trunk/Source/WebCore/page/mac/DragControllerMac.mm 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebCore/page/mac/DragControllerMac.mm 2020-05-13 19:43:10 UTC (rev 261638)
@@ -46,7 +46,6 @@
#import "PlatformStrategies.h"
#import "Range.h"
#import "RuntimeEnabledFeatures.h"
-#import "UTIUtilities.h"
#if ENABLE(DATA_INTERACTION)
#import <MobileCoreServices/MobileCoreServices.h>
@@ -92,14 +91,6 @@
return maxDragImageSize;
}
-String DragController::platformContentTypeForBlobType(const String& type) const
-{
- auto utiType = UTIFromMIMEType(type);
- if (!utiType.isEmpty())
- return utiType;
- return type;
-}
-
void DragController::cleanupAfterSystemDrag()
{
#if PLATFORM(MAC)
Modified: trunk/Source/WebKit/ChangeLog (261637 => 261638)
--- trunk/Source/WebKit/ChangeLog 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebKit/ChangeLog 2020-05-13 19:43:10 UTC (rev 261638)
@@ -1,3 +1,65 @@
+2020-05-13 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [iOS] "Copy" context menu action for attachment element does not work in Mail
+ https://bugs.webkit.org/show_bug.cgi?id=211817
+ <rdar://problem/58043110>
+
+ Reviewed by Tim Horton.
+
+ Implements support for copying an attachment element, via context menu actions. To achieve this, we first
+ refactor code in WebCore that is currently responsible for converting an attachment element into a
+ PromisedAttachmentInfo, which provides a handle to an UI-process-side API attachment object. We then use this
+ helper in WebKit to send PromisedAttachmentInfo back to the UI process when handling the copy action from the
+ context menu on iOS.
+
+ On iOS, we then take this promised attachment info in the UI process, map it to an API::Attachment object, and
+ use the file handle to create and write an NSItemProvider to the general pasteboard. (In the future, similar
+ logic could be implemented on macOS as well to handle copying attachment elements by implementing a version of
+ writePromisedAttachmentToPasteboard in PageClientImplMac. Currently, we fall back to treating this case as if
+ we're copying a text selection containing a single attachment element).
+
+ * UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h:
+
+ Add a new helper function to simulate an element action (_WKElementActionType) for an element at the given
+ location. This is used by the new API test.
+
+ * UIProcess/API/ios/WKWebViewTestingIOS.mm:
+ (-[WKWebView _simulateElementAction:atLocation:]):
+ * UIProcess/PageClient.h:
+ (WebKit::PageClient::writePromisedAttachmentToPasteboard):
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::writePromisedAttachmentToPasteboard):
+ * UIProcess/WebPageProxy.h:
+ * UIProcess/WebPageProxy.messages.in:
+
+ Add an IPC message for the UI process to receive a PromisedAttachmentInfo, and copy it to the system pasteboard
+ if it maps to an actual API::Attachment. For now, we only support copying data if the attachment is backed by
+ a file wrapper in the UI process (as opposed to blob data written by the web process).
+
+ * UIProcess/ios/PageClientImplIOS.h:
+ * UIProcess/ios/PageClientImplIOS.mm:
+ (WebKit::PageClientImpl::writePromisedAttachmentToPasteboard):
+ * UIProcess/ios/WKContentViewInteraction.h:
+ * UIProcess/ios/WKContentViewInteraction.mm:
+ (createItemProvider):
+
+ Create a helper function to convert PromisedAttachmentInfo into an NSItemProvider. This is similar to
+ `-_prepareToDragPromisedAttachment:`, but with a couple differences: (1) we only create an NSItemProvider
+ instead of going through `WebItemProviderRegistrationInfoList`; (2) since there's no opportunity to clean up
+ temporary after pasting, serialize the attachment data using `-serializedRepresentation`, and provide the
+ attachment data instead of a file URL.
+
+ Ideally, we would offer the data directly to the pasteboard so that even if Mail terminates, the contents of the
+ pasteboard can still be provided when pasting; however, it doesn't seem like we can do this while being able to
+ offer a suggested name for the item we're writing. Some other apps work around this limitation by writing the
+ file name as plain text on the pasteboard, but this doesn't work then attempting to copy a plain text file that
+ has a file name.
+
+ (-[WKContentView _writePromisedAttachmentToPasteboard:]):
+ (-[WKContentView _simulateElementAction:atLocation:]):
+ * WebProcess/WebPage/ios/WebPageIOS.mm:
+ (WebKit::WebPage::performActionOnElement):
+
2020-05-13 Per Arne Vollan <pvol...@apple.com>
[iOS] Update message filtering rules in the WebContent process' sandbox
Modified: trunk/Source/WebKit/UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h (261637 => 261638)
--- trunk/Source/WebKit/UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebKit/UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h 2020-05-13 19:43:10 UTC (rev 261638)
@@ -24,6 +24,7 @@
*/
#import <WebKit/WKWebView.h>
+#import <WebKit/_WKElementAction.h>
#if TARGET_OS_IPHONE
@@ -67,6 +68,7 @@
- (void)_doAfterResettingSingleTapGesture:(dispatch_block_t)action;
- (NSDictionary *)_propertiesOfLayerWithID:(unsigned long long)layerID;
+- (void)_simulateElementAction:(_WKElementActionType)actionType atLocation:(CGPoint)location;
- (void)_simulateLongPressActionAtLocation:(CGPoint)location;
- (void)_simulateTextEntered:(NSString *)text;
Modified: trunk/Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm (261637 => 261638)
--- trunk/Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm 2020-05-13 19:43:10 UTC (rev 261638)
@@ -293,6 +293,11 @@
#endif
}
+- (void)_simulateElementAction:(_WKElementActionType)actionType atLocation:(CGPoint)location
+{
+ [_contentView _simulateElementAction:actionType atLocation:location];
+}
+
- (void)_simulateLongPressActionAtLocation:(CGPoint)location
{
[_contentView _simulateLongPressActionAtLocation:location];
Modified: trunk/Source/WebKit/UIProcess/PageClient.h (261637 => 261638)
--- trunk/Source/WebKit/UIProcess/PageClient.h 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebKit/UIProcess/PageClient.h 2020-05-13 19:43:10 UTC (rev 261638)
@@ -106,6 +106,10 @@
#if ENABLE(DRAG_SUPPORT)
struct DragItem;
#endif
+
+#if ENABLE(ATTACHMENT_ELEMENT)
+struct PromisedAttachmentInfo;
+#endif
}
namespace WebKit {
@@ -509,6 +513,7 @@
virtual void didInsertAttachment(API::Attachment&, const String& source) { }
virtual void didRemoveAttachment(API::Attachment&) { }
virtual void didInvalidateDataForAttachment(API::Attachment&) { }
+ virtual void writePromisedAttachmentToPasteboard(WebCore::PromisedAttachmentInfo&&) { }
#if PLATFORM(COCOA)
virtual NSFileWrapper *allocFileWrapperInstance() const { return nullptr; }
virtual NSSet *serializableFileWrapperClasses() const { return nullptr; }
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (261637 => 261638)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2020-05-13 19:43:10 UTC (rev 261638)
@@ -9456,6 +9456,11 @@
#if ENABLE(ATTACHMENT_ELEMENT)
+void WebPageProxy::writePromisedAttachmentToPasteboard(WebCore::PromisedAttachmentInfo&& info)
+{
+ pageClient().writePromisedAttachmentToPasteboard(WTFMove(info));
+}
+
RefPtr<API::Attachment> WebPageProxy::attachmentForIdentifier(const String& identifier) const
{
if (identifier.isEmpty())
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (261637 => 261638)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.h 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h 2020-05-13 19:43:10 UTC (rev 261638)
@@ -157,6 +157,10 @@
#include "SOAuthorizationLoadPolicy.h"
#endif
+#if ENABLE(ATTACHMENT_ELEMENT)
+#include <WebCore/PromisedAttachmentInfo.h>
+#endif
+
#if ENABLE(MEDIA_SESSION)
namespace WebCore {
class MediaSessionMetadata;
@@ -2262,6 +2266,8 @@
void didRemoveAttachment(API::Attachment&);
Ref<API::Attachment> ensureAttachment(const String& identifier);
void invalidateAllAttachments();
+
+ void writePromisedAttachmentToPasteboard(WebCore::PromisedAttachmentInfo&&);
#endif
void reportPageLoadResult(const WebCore::ResourceError& = { });
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in (261637 => 261638)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in 2020-05-13 19:43:10 UTC (rev 261638)
@@ -556,6 +556,7 @@
DidInsertAttachmentWithIdentifier(String identifier, String source, bool hasEnclosingImage)
DidRemoveAttachmentWithIdentifier(String identifier)
SerializedAttachmentDataForIdentifiers(Vector<String> identifiers) -> (Vector<WebCore::SerializedAttachmentData> seralizedData) Synchronous
+ WritePromisedAttachmentToPasteboard(struct WebCore::PromisedAttachmentInfo info)
#endif
SignedPublicKeyAndChallengeString(unsigned keySizeIndex, String challengeString, URL url) -> (String result) Synchronous
Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h (261637 => 261638)
--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h 2020-05-13 19:43:10 UTC (rev 261638)
@@ -258,6 +258,10 @@
RetainPtr<WKDrawingView> createDrawingView(WebCore::GraphicsLayer::EmbeddedViewID) override;
#endif
+#if ENABLE(ATTACHMENT_ELEMENT)
+ void writePromisedAttachmentToPasteboard(WebCore::PromisedAttachmentInfo&&) final;
+#endif
+
void cancelPointersForGestureRecognizer(UIGestureRecognizer*) override;
WTF::Optional<unsigned> activeTouchIdentifierForGestureRecognizer(UIGestureRecognizer*) override;
Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm (261637 => 261638)
--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm 2020-05-13 19:43:10 UTC (rev 261638)
@@ -952,6 +952,15 @@
[m_contentView _showDataDetectorsUIForPositionInformation:positionInformation];
}
+#if ENABLE(ATTACHMENT_ELEMENT)
+
+void PageClientImpl::writePromisedAttachmentToPasteboard(WebCore::PromisedAttachmentInfo&& info)
+{
+ [m_contentView _writePromisedAttachmentToPasteboard:WTFMove(info)];
+}
+
+#endif // ENABLE(ATTACHMENT_ELEMENT)
+
} // namespace WebKit
#endif // PLATFORM(IOS_FAMILY)
Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h (261637 => 261638)
--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h 2020-05-13 19:43:10 UTC (rev 261638)
@@ -50,6 +50,7 @@
#import "WKShareSheet.h"
#import "WKSyntheticTapGestureRecognizer.h"
#import "WKTouchActionGestureRecognizer.h"
+#import "_WKElementAction.h"
#import "_WKFormInputSession.h"
#import <UIKit/UIView.h>
#import <WebCore/ActivityState.h>
@@ -598,10 +599,15 @@
- (void)_removeContextMenuViewIfPossible;
#endif
+#if ENABLE(ATTACHMENT_ELEMENT)
+- (void)_writePromisedAttachmentToPasteboard:(WebCore::PromisedAttachmentInfo&&)info;
+#endif
+
@end
@interface WKContentView (WKTesting)
+- (void)_simulateElementAction:(_WKElementActionType)actionType atLocation:(CGPoint)location;
- (void)_simulateLongPressActionAtLocation:(CGPoint)location;
- (void)_simulateTextEntered:(NSString *)text;
- (void)selectFormAccessoryPickerRow:(NSInteger)rowIndex;
Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (261637 => 261638)
--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm 2020-05-13 19:43:10 UTC (rev 261638)
@@ -149,6 +149,10 @@
#import <UIKit/_UILookupGestureRecognizer.h>
#endif
+#if ENABLE(ATTACHMENT_ELEMENT)
+#import "APIAttachment.h"
+#endif
+
#if ENABLE(INPUT_TYPE_COLOR)
#import "WKFormColorControl.h"
#endif
@@ -8587,6 +8591,61 @@
#endif // HAVE(UI_CURSOR_INTERACTION)
+#if ENABLE(ATTACHMENT_ELEMENT)
+
+static RetainPtr<NSItemProvider> createItemProvider(const WebKit::WebPageProxy& page, const WebCore::PromisedAttachmentInfo& info)
+{
+ auto numberOfAdditionalTypes = info.additionalTypes.size();
+ ASSERT(numberOfAdditionalTypes == info.additionalData.size());
+
+ auto attachment = page.attachmentForIdentifier(info.attachmentIdentifier);
+ if (!attachment)
+ return { };
+
+ NSString *utiType = attachment->utiType();
+ if (![utiType length])
+ return { };
+
+ auto fileWrapper = retainPtr(attachment->fileWrapper());
+ if (!fileWrapper)
+ return { };
+
+ auto item = adoptNS([[NSItemProvider alloc] init]);
+ [item setPreferredPresentationStyle:UIPreferredPresentationStyleAttachment];
+
+ NSString *fileName = attachment->fileName();
+ if ([fileName length])
+ [item setSuggestedName:fileName];
+
+ if (numberOfAdditionalTypes == info.additionalData.size() && numberOfAdditionalTypes) {
+ for (size_t index = 0; index < numberOfAdditionalTypes; ++index) {
+ auto nsData = info.additionalData[index]->createNSData();
+ [item registerDataRepresentationForTypeIdentifier:info.additionalTypes[index] visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[nsData](void (^completionHandler)(NSData *, NSError *)) -> NSProgress * {
+ completionHandler(nsData.get(), nil);
+ return nil;
+ }];
+ }
+ }
+
+ [item registerDataRepresentationForTypeIdentifier:utiType visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[fileWrapper](void (^completionHandler)(NSData *, NSError *)) -> NSProgress * {
+ if (auto nsData = retainPtr([fileWrapper serializedRepresentation]))
+ completionHandler(nsData.get(), nil);
+ else
+ completionHandler(nil, [NSError errorWithDomain:WKErrorDomain code:WKErrorUnknown userInfo:nil]);
+ return nil;
+ }];
+
+ return item;
+}
+
+- (void)_writePromisedAttachmentToPasteboard:(WebCore::PromisedAttachmentInfo&&)info
+{
+ if (auto item = createItemProvider(*_page, WTFMove(info)))
+ UIPasteboard.generalPasteboard.itemProviders = @[ item.get() ];
+}
+
+#endif // ENABLE(ATTACHMENT_ELEMENT)
+
@end
@implementation WKContentView (WKTesting)
@@ -8629,6 +8688,16 @@
#endif
}
+- (void)_simulateElementAction:(_WKElementActionType)actionType atLocation:(CGPoint)location
+{
+ RetainPtr<WKContentView> protectedSelf = self;
+ [self doAfterPositionInformationUpdate:[actionType, protectedSelf] (WebKit::InteractionInformationAtPosition info) {
+ _WKElementAction *action = "" _elementActionWithType:actionType assistant:protectedSelf->_actionSheetAssistant.get()];
+ _WKActivatedElementInfo *elementInfo = [_WKActivatedElementInfo activatedElementInfoWithInteractionInformationAtPosition:info userInfo:nil];
+ [action runActionWithElementInfo:elementInfo];
+ } forRequest:WebKit::InteractionInformationRequest(WebCore::roundedIntPoint(location))];
+}
+
- (void)_simulateLongPressActionAtLocation:(CGPoint)location
{
RetainPtr<WKContentView> protectedSelf = self;
Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (261637 => 261638)
--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2020-05-13 19:43:10 UTC (rev 261638)
@@ -138,6 +138,10 @@
#import <wtf/cocoa/Entitlements.h>
#import <wtf/text/TextStream.h>
+#if ENABLE(ATTACHMENT_ELEMENT)
+#import <WebCore/PromisedAttachmentInfo.h>
+#endif
+
#define RELEASE_LOG_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, "%p - WebPage::" fmt, this, ##__VA_ARGS__)
#define RELEASE_LOG_ERROR_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_ERROR_IF(isAlwaysOnLoggingAllowed(), channel, "%p - WebPage::" fmt, this, ##__VA_ARGS__)
@@ -2976,9 +2980,12 @@
title = stripLeadingAndTrailingHTMLSpaces(title);
}
m_interactionNode->document().editor().writeImageToPasteboard(*Pasteboard::createForCopyAndPaste(), element, url, title);
- } else if (element.isLink()) {
+ } else if (element.isLink())
m_interactionNode->document().editor().copyURL(element.document().completeURL(stripLeadingAndTrailingHTMLSpaces(element.attributeWithoutSynchronization(HTMLNames::hrefAttr))), element.textContent());
- }
+#if ENABLE(ATTACHMENT_ELEMENT)
+ else if (auto attachmentInfo = element.document().editor().promisedAttachmentInfo(element))
+ send(Messages::WebPageProxy::WritePromisedAttachmentToPasteboard(WTFMove(attachmentInfo)));
+#endif
} else if (static_cast<SheetAction>(action) == SheetAction::SaveImage) {
if (!is<RenderImage>(*element.renderer()))
return;
Modified: trunk/Tools/ChangeLog (261637 => 261638)
--- trunk/Tools/ChangeLog 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Tools/ChangeLog 2020-05-13 19:43:10 UTC (rev 261638)
@@ -1,3 +1,15 @@
+2020-05-13 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [iOS] "Copy" context menu action for attachment element does not work in Mail
+ https://bugs.webkit.org/show_bug.cgi?id=211817
+ <rdar://problem/58043110>
+
+ Reviewed by Tim Horton.
+
+ Add a new iOS API test that simulates the context menu action to "copy" on an attachment element.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
+
2020-05-12 Matt Lewis <jlew...@apple.com>
Run-webkit-tests should not fail if all tests found to run are skipped.
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm (261637 => 261638)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm 2020-05-13 19:26:58 UTC (rev 261637)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm 2020-05-13 19:43:10 UTC (rev 261638)
@@ -2153,6 +2153,48 @@
});
}
+TEST(WKAttachmentTestsIOS, CopyAttachmentUsingElementAction)
+{
+ UIPasteboard.generalPasteboard.items = @[ ];
+
+ auto webView = webViewForTestingAttachments();
+ [webView _setEditable:YES];
+ [webView synchronouslyLoadHTMLString:@"<body></body><script>document.body.focus();</script>"];
+
+ auto document = adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:testPDFData()]);
+ [document setPreferredFilename:@"hello.pdf"];
+
+ auto attachment = retainPtr([webView synchronouslyInsertAttachmentWithFileWrapper:document.get() contentType:(__bridge NSString *)kUTTypePDF]);
+ NSString *identifier = [webView stringByEvaluatingJavaScript:@"document.querySelector('attachment').uniqueIdentifier"];
+ EXPECT_WK_STREQ(identifier, [attachment uniqueIdentifier]);
+
+ // Ensure that we can hit-test to the attachment element when simulating a context menu element by adding a click event handler.
+ [webView objectByEvaluatingJavaScript:@"document.querySelector('attachment').addEventListener('click', () => { })"];
+ [webView _setEditable:NO];
+
+ [webView _simulateElementAction:_WKElementActionTypeCopy atLocation:CGPointMake(20, 20)];
+
+ // It takes two IPC round trips between the UI process and web process until the pasteboard data is written,
+ // since we first need to hit-test to discover the activated element, and then use the activated element to
+ // simulate the "copy" action.
+ [webView waitForNextPresentationUpdate];
+ [webView waitForNextPresentationUpdate];
+
+ NSArray<NSItemProvider *> *itemProviders = UIPasteboard.generalPasteboard.itemProviders;
+ EXPECT_EQ(1U, itemProviders.count);
+
+ NSItemProvider *itemProvider = itemProviders.firstObject;
+ EXPECT_EQ(UIPreferredPresentationStyleAttachment, itemProvider.preferredPresentationStyle);
+ EXPECT_WK_STREQ("hello.pdf", itemProvider.suggestedName);
+
+ __block bool done = false;
+ [itemProvider loadDataRepresentationForTypeIdentifier:(__bridge NSString *)kUTTypePDF completionHandler:^(NSData *data, NSError *) {
+ EXPECT_TRUE([[document serializedRepresentation] isEqualToData:data]);
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+}
+
#if HAVE(PENCILKIT)
static BOOL forEachViewInHierarchy(UIView *view, void(^mapFunction)(UIView *subview, BOOL *stop))
{