Skip to content

Commit d4287a4

Browse files
[Attachment Support] Support dragging attachment elements out as files on iOS
https://bugs.webkit.org/show_bug.cgi?id=181199 <rdar://problem/36299316> Reviewed by Tim Horton, Andy Estes and Joseph Pecoraro. Source/WebCore: Adds support for dragging "files" (i.e. creating item providers with preferred attachment presentation styles) from attachment elements on iOS for Mail. See below for more detail. Tests: WKAttachmentTestsIOS.DragAttachmentInsertedAsData WKAttachmentTestsIOS.DragAttachmentInsertedAsFile * page/DragController.cpp: (WebCore::DragController::platformContentTypeForBlobType const): (WebCore::DragController::dragAttachmentElement): * page/DragController.h: * page/mac/DragControllerMac.mm: (WebCore::DragController::platformContentTypeForBlobType const): Add a private method to convert the type of a promised blob to a platform type. For Cocoa platforms, this converts the blob type (either a UTI or a MIME type) to a UTI for the platform to consume. * platform/ios/WebItemProviderPasteboard.h: * platform/ios/WebItemProviderPasteboard.mm: Refactor WebItemProviderRegistrationInfo. WebItemProviderRegistrationInfo currently encapsulates a single item provider registration call, and contains either a type identifier and data buffer, or an NSItemProviderWriting- conformant object. To register an item provider using a WebItemProviderRegistrationInfo, the item provider pasteboard currently checks to see whether the info contains an object or a type and data. This patch removes WebItemProviderRegistrationInfo and replaces it with WebItemProviderDataRegistrar. Objects that implement this protocol know how to take an NSItemProvider and register data to it. So far, there are three implementations below. (-[WebItemProviderDataRegistrar initWithData:type:]): (-[WebItemProviderDataRegistrar typeIdentifier]): (-[WebItemProviderDataRegistrar data]): (-[WebItemProviderDataRegistrar typeIdentifierForClient]): (-[WebItemProviderDataRegistrar dataForClient]): (-[WebItemProviderDataRegistrar registerItemProvider:]): (-[WebItemProviderDataRegistrar description]): A data registrar takes a UTI and data buffer, and registers the UTI to the data. This replaces a WebItemProviderRegistrationInfo with both a type and data, but no representing object. (-[WebItemProviderWritableObjectRegistrar initWithObject:]): (-[WebItemProviderWritableObjectRegistrar representingObjectForClient]): (-[WebItemProviderWritableObjectRegistrar registerItemProvider:]): (-[WebItemProviderWritableObjectRegistrar description]): The writable object registrar writes an NSItemProviderWriting-conformant object to an item provider. This replaces a WebItemProviderRegistrationInfo with only a representing object. (-[WebItemProviderPromisedFileRegistrar initWithType:callback:]): (-[WebItemProviderPromisedFileRegistrar registerItemProvider:]): (-[WebItemProviderPromisedFileRegistrar description]): (-[WebItemProviderRegistrationInfoList addData:forType:]): (-[WebItemProviderRegistrationInfoList addRepresentingObject:]): (-[WebItemProviderRegistrationInfoList addPromisedType:fileCallback:]): Helper methods to add new registrars to a registration info list. (-[WebItemProviderRegistrationInfoList itemAtIndex:]): (-[WebItemProviderRegistrationInfoList enumerateItems:]): (-[WebItemProviderRegistrationInfoList itemProvider]): (-[WebItemProviderRegistrationInfoList description]): (-[WebItemProviderRegistrationInfo initWithRepresentingObject:typeIdentifier:data:]): Deleted. (-[WebItemProviderRegistrationInfo representingObject]): Deleted. (-[WebItemProviderRegistrationInfo typeIdentifier]): Deleted. Source/WebKit: Implement support for registering and beginning a drag with promised blob info. See below for more detail. * UIProcess/ios/WKContentViewInteraction.mm: (-[WKDragSessionContext addTemporaryDirectory:]): (-[WKDragSessionContext cleanUpTemporaryDirectories]): Introduce WKDragSessionContext, which represents the localContext of a UIDragSession initiated in WebKit. The blob promise dragging codepath uses this to register temporary directories when saving blob data to a location on disk; when all data transfers are finished, or if the drag interaction is being reset, we then use -cleanUpTemporaryDirectories to remove each temporary directory. (existingLocalDragSessionContext): (ensureLocalDragSessionContext): Helper methods to set the UIDragSession's localContext to a WKDragSessionContext and query for any existing context. (-[WKContentView cleanupInteraction]): Before the content view's UIDragInteraction goes away, clean up any temporary directories added to the UIDragSession. (-[WKContentView _prepareToDragPromisedBlob:]): When dragging with a promised blob, register a new item provider on the pasteboard representing the blob data, along with any additional metadata associated with the blob. For the promise callback, call out to the network process to write the blob data to a temporary path; when done, call the NSItemProvider's completion handler with the temporary blob data location. (-[WKContentView _itemsForBeginningOrAddingToSessionWithRegistrationList:stagedDragSource:]): (-[WKContentView dragInteraction:sessionDidTransferItems:]): Use this delegate hook as an opportunity to remove any temporary directories created when promised blob data is requested upon drop. Since we know the drag session that has finished transferring data, we simply ask its local context (a WKDragSessionContext) to remove any temporary filepaths it has created. Tools: Add support in the drag and drop simulator for testing blob-backed attachment element dragging, and also add new attachment API tests. * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm: (-[NSItemProvider expectType:withData:]): (TestWebKitAPI::TEST): Add two new WKAttachmentTests to exercise dragging data- and file-backed blobs via attachment elements. These tests first insert attachments via drop or WKWebView SPI, and then drag these attachments out and use the -expectType:withData: helper to inspect the item providers created from the drag source. * TestWebKitAPI/Tests/ios/DataInteractionTests.mm: (TestWebKitAPI::TEST): * TestWebKitAPI/ios/DataInteractionSimulator.h: * TestWebKitAPI/ios/DataInteractionSimulator.mm: (-[MockDragSession localContext]): (-[MockDragSession setLocalContext:]): (-[DataInteractionSimulator _resetSimulatedState]): (-[DataInteractionSimulator simulateAllTouchesCanceled:]): (-[DataInteractionSimulator _concludeDataInteractionAndPerformOperationIfNecessary]): (-[DataInteractionSimulator _advanceProgress]): (-[DataInteractionSimulator endDataTransfer]): Make some tweaks to the iOS drag and drop simulator. In particular, this patch (1) adds a new hook to tell WebKit that data transfers have been completed, (2) fixes incorrect drop proposal handling when returning UIDropOperationForbidden by replacing _shouldPerformOperation with a UIDropProposal, and (3) teach the MockDragSession to hold on to a localContext. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@226779 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent acd1c66 commit d4287a4

13 files changed

+543
-74
lines changed

Source/WebCore/ChangeLog

+72
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,75 @@
1+
2018-01-11 Wenson Hsieh <[email protected]>
2+
3+
[Attachment Support] Support dragging attachment elements out as files on iOS
4+
https://bugs.webkit.org/show_bug.cgi?id=181199
5+
<rdar://problem/36299316>
6+
7+
Reviewed by Tim Horton, Andy Estes and Joseph Pecoraro.
8+
9+
Adds support for dragging "files" (i.e. creating item providers with preferred attachment presentation styles)
10+
from attachment elements on iOS for Mail. See below for more detail.
11+
12+
Tests: WKAttachmentTestsIOS.DragAttachmentInsertedAsData
13+
WKAttachmentTestsIOS.DragAttachmentInsertedAsFile
14+
15+
* page/DragController.cpp:
16+
(WebCore::DragController::platformContentTypeForBlobType const):
17+
(WebCore::DragController::dragAttachmentElement):
18+
* page/DragController.h:
19+
* page/mac/DragControllerMac.mm:
20+
(WebCore::DragController::platformContentTypeForBlobType const):
21+
22+
Add a private method to convert the type of a promised blob to a platform type. For Cocoa platforms, this
23+
converts the blob type (either a UTI or a MIME type) to a UTI for the platform to consume.
24+
25+
* platform/ios/WebItemProviderPasteboard.h:
26+
* platform/ios/WebItemProviderPasteboard.mm:
27+
28+
Refactor WebItemProviderRegistrationInfo. WebItemProviderRegistrationInfo currently encapsulates a single item
29+
provider registration call, and contains either a type identifier and data buffer, or an NSItemProviderWriting-
30+
conformant object. To register an item provider using a WebItemProviderRegistrationInfo, the item provider
31+
pasteboard currently checks to see whether the info contains an object or a type and data.
32+
33+
This patch removes WebItemProviderRegistrationInfo and replaces it with WebItemProviderDataRegistrar. Objects
34+
that implement this protocol know how to take an NSItemProvider and register data to it. So far, there are
35+
three implementations below.
36+
37+
(-[WebItemProviderDataRegistrar initWithData:type:]):
38+
(-[WebItemProviderDataRegistrar typeIdentifier]):
39+
(-[WebItemProviderDataRegistrar data]):
40+
(-[WebItemProviderDataRegistrar typeIdentifierForClient]):
41+
(-[WebItemProviderDataRegistrar dataForClient]):
42+
(-[WebItemProviderDataRegistrar registerItemProvider:]):
43+
(-[WebItemProviderDataRegistrar description]):
44+
45+
A data registrar takes a UTI and data buffer, and registers the UTI to the data. This replaces a
46+
WebItemProviderRegistrationInfo with both a type and data, but no representing object.
47+
48+
(-[WebItemProviderWritableObjectRegistrar initWithObject:]):
49+
(-[WebItemProviderWritableObjectRegistrar representingObjectForClient]):
50+
(-[WebItemProviderWritableObjectRegistrar registerItemProvider:]):
51+
(-[WebItemProviderWritableObjectRegistrar description]):
52+
53+
The writable object registrar writes an NSItemProviderWriting-conformant object to an item provider. This
54+
replaces a WebItemProviderRegistrationInfo with only a representing object.
55+
56+
(-[WebItemProviderPromisedFileRegistrar initWithType:callback:]):
57+
(-[WebItemProviderPromisedFileRegistrar registerItemProvider:]):
58+
(-[WebItemProviderPromisedFileRegistrar description]):
59+
(-[WebItemProviderRegistrationInfoList addData:forType:]):
60+
(-[WebItemProviderRegistrationInfoList addRepresentingObject:]):
61+
(-[WebItemProviderRegistrationInfoList addPromisedType:fileCallback:]):
62+
63+
Helper methods to add new registrars to a registration info list.
64+
65+
(-[WebItemProviderRegistrationInfoList itemAtIndex:]):
66+
(-[WebItemProviderRegistrationInfoList enumerateItems:]):
67+
(-[WebItemProviderRegistrationInfoList itemProvider]):
68+
(-[WebItemProviderRegistrationInfoList description]):
69+
(-[WebItemProviderRegistrationInfo initWithRepresentingObject:typeIdentifier:data:]): Deleted.
70+
(-[WebItemProviderRegistrationInfo representingObject]): Deleted.
71+
(-[WebItemProviderRegistrationInfo typeIdentifier]): Deleted.
72+
173
2018-01-11 Michael Saboff <[email protected]>
274

375
Add a DOM gadget for Spectre testing

Source/WebCore/page/DragController.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -1274,6 +1274,15 @@ bool DragController::shouldUseCachedImageForDragImage(const Image& image) const
12741274
#endif
12751275
}
12761276

1277+
#if !PLATFORM(COCOA)
1278+
1279+
String DragController::platformContentTypeForBlobType(const String& type) const
1280+
{
1281+
return type;
1282+
}
1283+
1284+
#endif
1285+
12771286
#if ENABLE(ATTACHMENT_ELEMENT)
12781287

12791288
bool DragController::dragAttachmentElement(Frame& frame, HTMLAttachmentElement& attachment)
@@ -1289,7 +1298,7 @@ bool DragController::dragAttachmentElement(Frame& frame, HTMLAttachmentElement&
12891298
#endif
12901299

12911300
auto& file = *attachment.file();
1292-
m_client.prepareToDragPromisedBlob({ file.url(), file.type(), file.name(), additionalTypes, additionalData });
1301+
m_client.prepareToDragPromisedBlob({ file.url(), platformContentTypeForBlobType(file.type()), file.name(), WTFMove(additionalTypes), WTFMove(additionalData) });
12931302

12941303
return true;
12951304
}

Source/WebCore/page/DragController.h

+2
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ struct DragState;
128128
#endif
129129
}
130130

131+
String platformContentTypeForBlobType(const String& type) const;
132+
131133
void cleanupAfterSystemDrag();
132134
void declareAndWriteDragImage(DataTransfer&, Element&, const URL&, const String& label);
133135

Source/WebCore/page/mac/DragControllerMac.mm

+9
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#import "PlatformStrategies.h"
4747
#import "Range.h"
4848
#import "RuntimeEnabledFeatures.h"
49+
#import "UTIUtilities.h"
4950

5051
#if ENABLE(DATA_INTERACTION)
5152
#import <MobileCoreServices/MobileCoreServices.h>
@@ -91,6 +92,14 @@
9192
return maxDragImageSize;
9293
}
9394

95+
String DragController::platformContentTypeForBlobType(const String& type) const
96+
{
97+
auto utiType = UTIFromMIMEType(type);
98+
if (!utiType.isEmpty())
99+
return utiType;
100+
return type;
101+
}
102+
94103
void DragController::cleanupAfterSystemDrag()
95104
{
96105
#if PLATFORM(MAC)

Source/WebCore/platform/ios/WebItemProviderPasteboard.h

+16-12
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,23 @@ typedef NS_ENUM(NSInteger, WebPreferredPresentationStyle) {
4040

4141
NS_ASSUME_NONNULL_BEGIN
4242

43-
/*! A WebItemProviderRegistrationInfo represents a single call to register something to an item provider.
44-
@discussion Either the representing object exists and the type identifier and data are nil, or the
45-
representing object is nil and the type identifier and data exist. The former represents a call to
46-
register an entire UIItemProviderWriting-conformant object to the item provider, while the latter
47-
represents a call to register only a data representation for the given type identifier.
43+
/*! A WebItemProviderRegistrar encapsulates a single call to register something to an item provider.
44+
@discussion Classes that implement this protocol each represent a different way of writing data to
45+
an item provider. Some examples include setting a chunk of data corresponding to a type identifier,
46+
or registering a NSItemProviderWriting-conformant object, or registering a type to a promised file
47+
where the data has been written.
4848
*/
49-
WEBCORE_EXPORT @interface WebItemProviderRegistrationInfo : NSObject
50-
51-
@property (nonatomic, readonly, nullable, strong) id <UIItemProviderWriting> representingObject;
52-
@property (nonatomic, readonly, nullable, strong) NSString *typeIdentifier;
53-
@property (nonatomic, readonly, nullable, strong) NSData *data;
49+
@protocol WebItemProviderRegistrar <NSObject>
50+
- (void)registerItemProvider:(NSItemProvider *)itemProvider;
5451

52+
@optional
53+
@property (nonatomic, readonly) id <NSItemProviderWriting> representingObjectForClient;
54+
@property (nonatomic, readonly) NSString *typeIdentifierForClient;
55+
@property (nonatomic, readonly) NSData *dataForClient;
5556
@end
5657

58+
typedef void(^WebItemProviderFileCallback)(NSURL * _Nullable, NSError * _Nullable);
59+
5760
/*! A WebItemProviderRegistrationInfoList represents a series of registration calls used to set up a
5861
single item provider.
5962
@discussion The order of items specified in the list (lowest indices first) is the order in which
@@ -65,6 +68,7 @@ WEBCORE_EXPORT @interface WebItemProviderRegistrationInfoList : NSObject
6568

6669
- (void)addRepresentingObject:(id <UIItemProviderWriting>)object;
6770
- (void)addData:(NSData *)data forType:(NSString *)typeIdentifier;
71+
- (void)addPromisedType:(NSString *)typeIdentifier fileCallback:(void(^)(WebItemProviderFileCallback))callback;
6872

6973
@property (nonatomic) CGSize preferredPresentationSize;
7074
@property (nonatomic, copy) NSString *suggestedName;
@@ -74,8 +78,8 @@ WEBCORE_EXPORT @interface WebItemProviderRegistrationInfoList : NSObject
7478
@property (nonatomic, copy) NSData *teamData;
7579

7680
- (NSUInteger)numberOfItems;
77-
- (nullable WebItemProviderRegistrationInfo *)itemAtIndex:(NSUInteger)index;
78-
- (void)enumerateItems:(void(^)(WebItemProviderRegistrationInfo *item, NSUInteger index))block;
81+
- (nullable id <WebItemProviderRegistrar>)itemAtIndex:(NSUInteger)index;
82+
- (void)enumerateItems:(void(^)(id <WebItemProviderRegistrar> item, NSUInteger index))block;
7983

8084
@end
8185

0 commit comments

Comments
 (0)