- Revision
- 235202
- Author
- wenson_hs...@apple.com
- Date
- 2018-08-22 14:35:02 -0700 (Wed, 22 Aug 2018)
Log Message
[Attachment Support] Support dragging attachment elements out as files on macOS
https://bugs.webkit.org/show_bug.cgi?id=181294
<rdar://problem/36298801>
Reviewed by Tim Horton.
Source/WebCore:
Serialize a dragged attachment element as a web archive on macOS. This allows us to move attachment elements
around a document by dragging, without performing a file upload upon every drop. Ideally, we should do this on
iOS as well, but this currently causes attachment data to go missing; further investigation to fix this for iOS
is tracked in <https://bugs.webkit.org/show_bug.cgi?id=181514>.
Tests: WKAttachmentTestsMac.DragAttachmentAsFilePromise
WKAttachmentTests.MoveAttachmentElementAsIconByDragging
* editing/cocoa/EditorCocoa.mm:
(WebCore::Editor::getPasteboardTypesAndDataForAttachment):
Source/WebKit:
Add support for dragging attachment elements on macOS by writing promised files to drag pasteboard. See changes
below for more details.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView filePromiseProvider:fileNameForType:]):
(-[WKWebView filePromiseProvider:writePromiseToURL:completionHandler:]):
(-[WKWebView draggingSession:sourceOperationMaskForDraggingContext:]):
(-[WKWebView draggingSession:endedAtPoint:operation:]):
* UIProcess/API/mac/WKView.mm:
(-[WKView filePromiseProvider:fileNameForType:]):
(-[WKView filePromiseProvider:writePromiseToURL:completionHandler:]):
(-[WKView draggingSession:sourceOperationMaskForDraggingContext:]):
(-[WKView draggingSession:endedAtPoint:operation:]):
Plumb NSFilePromiseProviderDelegate and NSDraggingSource method implementations to WebViewImpl.
* UIProcess/Cocoa/WebViewImpl.h:
* UIProcess/Cocoa/WebViewImpl.mm:
(-[WKPromisedAttachmentContext initWithAttachmentInfo:]):
(-[WKPromisedAttachmentContext blobURL]):
(-[WKPromisedAttachmentContext filename]):
(-[WKPromisedAttachmentContext attachmentIdentifier]):
Add an object that contains the information needed to deliver a dragged attachment element's data via
NSFilePromiseProvider. This is stored as the userInfo of the NSFilePromiseProvider created upon drag start.
(WebKit::WebViewImpl::draggedImage):
(WebKit::WebViewImpl::sendDragEndToPage):
Add a helper method to handle cleanup after the dragging has finished, and call it from -draggedImage:… and
-draggingSessionEnded:…. The latter is only triggered in the where -beginDraggingSessionWithItems:… is used,
which currently only happens when dragging attachment elements.
(WebKit::WebViewImpl::fileNameForFilePromiseProvider):
(WebKit::webKitUnknownError):
(WebKit::WebViewImpl::writeToURLForFilePromiseProvider):
Deliver either NSFileWrapper data to the destination URL (in the case where an attachment identifier is known
and the corresponding API::Attachment is backed by a file wrapper), or save the contents of the blob URL to the
destination.
(WebKit::WebViewImpl::dragSourceOperationMask):
(WebKit::WebViewImpl::draggingSessionEnded):
(WebKit::WebViewImpl::startDrag):
Tools:
Add DragAndDropSimulator support for intercepting calls to -beginDraggingSessionWithitems:event:source:. This
enables us to write API tests for macOS that exercise the attachment SPI in combination with dragging attachment
elements.
* TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
(-[TestWKWebView attachmentElementMidPoint]):
Add a helper method local to this test suite that grabs the midpoint (in client coordinates) or the first
attachment element in the document.
(TestWebKitAPI::TEST):
Add a new API test to verify that dragging an attachment element on macOS produces file providers which may be
used to write attachment data to a path on disk. Additionally, refactor an existing API test,
MoveAttachmentElementAsIconByDragging, so that it runs on both iOS and macOS, to test the ability to move
attachment elements around in a document by using drag and drop.
* TestWebKitAPI/cocoa/DragAndDropSimulator.h:
* TestWebKitAPI/mac/DragAndDropSimulatorMac.mm:
(-[DragAndDropTestWKWebView beginDraggingSessionWithItems:event:source:]):
(-[DragAndDropSimulator initWithWebViewFrame:configuration:]):
(-[DragAndDropSimulator dealloc]):
(-[DragAndDropSimulator runFrom:to:]):
(-[DragAndDropSimulator beginDraggingSessionInWebView:withItems:source:]):
Begin a drag session and kick off the -continueDragSession loop. Unlike -performDragInWebView:…, which spins
the main runloop until dragging ends, this version returns execution to the web view and schedules dragging
updates asynchronously. This matches AppKit behavior.
(-[DragAndDropSimulator continueDragSession]):
Increment the dragging progress amount, send a drag update to the web view, and continue scheduling calls to
itself until the progress reaches 1.
(-[DragAndDropSimulator performDragInWebView:atLocation:withImage:pasteboard:source:]):
(-[DragAndDropSimulator initializeDraggingInfo:dragImage:source:]):
Pull out common logic for creating a new TestDraggingInfo after starting a drag.
(-[DragAndDropSimulator insertedAttachments]):
(-[DragAndDropSimulator removedAttachments]):
(-[DragAndDropSimulator draggingSession]):
(-[DragAndDropSimulator receivePromisedFiles]):
Helper method to save promised files written to the pasteboard after a drag to the temporary directory. These
files are tracked by DragAndDropSimulator and automatically cleaned up after the test finishes.
(-[DragAndDropSimulator endDataTransfer]):
Add a method stub on macOS, so that MoveAttachmentElementAsIconByDragging can be made cross-platform.
(-[DragAndDropSimulator _webView:didInsertAttachment:withSource:]):
(-[DragAndDropSimulator _webView:didRemoveAttachment:]):
Implement method stubs to keep track of inserted or removed attachments while simulating a drag.
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (235201 => 235202)
--- trunk/Source/WebCore/ChangeLog 2018-08-22 21:22:13 UTC (rev 235201)
+++ trunk/Source/WebCore/ChangeLog 2018-08-22 21:35:02 UTC (rev 235202)
@@ -1,3 +1,22 @@
+2018-08-22 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [Attachment Support] Support dragging attachment elements out as files on macOS
+ https://bugs.webkit.org/show_bug.cgi?id=181294
+ <rdar://problem/36298801>
+
+ Reviewed by Tim Horton.
+
+ Serialize a dragged attachment element as a web archive on macOS. This allows us to move attachment elements
+ around a document by dragging, without performing a file upload upon every drop. Ideally, we should do this on
+ iOS as well, but this currently causes attachment data to go missing; further investigation to fix this for iOS
+ is tracked in <https://bugs.webkit.org/show_bug.cgi?id=181514>.
+
+ Tests: WKAttachmentTestsMac.DragAttachmentAsFilePromise
+ WKAttachmentTests.MoveAttachmentElementAsIconByDragging
+
+ * editing/cocoa/EditorCocoa.mm:
+ (WebCore::Editor::getPasteboardTypesAndDataForAttachment):
+
2018-08-22 Aditya Keerthi <akeer...@apple.com>
[iOS] Add support for the inputmode attribute
Modified: trunk/Source/WebCore/editing/cocoa/EditorCocoa.mm (235201 => 235202)
--- trunk/Source/WebCore/editing/cocoa/EditorCocoa.mm 2018-08-22 21:22:13 UTC (rev 235201)
+++ trunk/Source/WebCore/editing/cocoa/EditorCocoa.mm 2018-08-22 21:35:02 UTC (rev 235202)
@@ -169,6 +169,17 @@
// display mode when dragging and dropping or cutting and pasting. For the time being, this is disabled because
// inserting attachment elements from web archive data sometimes causes attachment data to be lost; this requires
// further investigation.
+#if PLATFORM(MAC)
+ // On macOS, we currently write the attachment as a web archive; we can't do the same for iOS and remove the platform guard above
+ // quite yet without breaking drag moves. This investigation is tracked in <https://bugs.webkit.org/show_bug.cgi?id=181514>.
+ // See the above FIXME for more details.
+ if (auto archive = LegacyWebArchive::create(attachmentRange.ptr())) {
+ if (auto webArchiveData = archive->rawDataRepresentation()) {
+ outTypes.append(WebArchivePboardType);
+ outData.append(SharedBuffer::create(webArchiveData.get()));
+ }
+ }
+#endif
}
#endif
Modified: trunk/Source/WebKit/ChangeLog (235201 => 235202)
--- trunk/Source/WebKit/ChangeLog 2018-08-22 21:22:13 UTC (rev 235201)
+++ trunk/Source/WebKit/ChangeLog 2018-08-22 21:35:02 UTC (rev 235202)
@@ -1,3 +1,56 @@
+2018-08-22 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [Attachment Support] Support dragging attachment elements out as files on macOS
+ https://bugs.webkit.org/show_bug.cgi?id=181294
+ <rdar://problem/36298801>
+
+ Reviewed by Tim Horton.
+
+ Add support for dragging attachment elements on macOS by writing promised files to drag pasteboard. See changes
+ below for more details.
+
+ * UIProcess/API/Cocoa/WKWebView.mm:
+ (-[WKWebView filePromiseProvider:fileNameForType:]):
+ (-[WKWebView filePromiseProvider:writePromiseToURL:completionHandler:]):
+ (-[WKWebView draggingSession:sourceOperationMaskForDraggingContext:]):
+ (-[WKWebView draggingSession:endedAtPoint:operation:]):
+ * UIProcess/API/mac/WKView.mm:
+ (-[WKView filePromiseProvider:fileNameForType:]):
+ (-[WKView filePromiseProvider:writePromiseToURL:completionHandler:]):
+ (-[WKView draggingSession:sourceOperationMaskForDraggingContext:]):
+ (-[WKView draggingSession:endedAtPoint:operation:]):
+
+ Plumb NSFilePromiseProviderDelegate and NSDraggingSource method implementations to WebViewImpl.
+
+ * UIProcess/Cocoa/WebViewImpl.h:
+ * UIProcess/Cocoa/WebViewImpl.mm:
+ (-[WKPromisedAttachmentContext initWithAttachmentInfo:]):
+ (-[WKPromisedAttachmentContext blobURL]):
+ (-[WKPromisedAttachmentContext filename]):
+ (-[WKPromisedAttachmentContext attachmentIdentifier]):
+
+ Add an object that contains the information needed to deliver a dragged attachment element's data via
+ NSFilePromiseProvider. This is stored as the userInfo of the NSFilePromiseProvider created upon drag start.
+
+ (WebKit::WebViewImpl::draggedImage):
+ (WebKit::WebViewImpl::sendDragEndToPage):
+
+ Add a helper method to handle cleanup after the dragging has finished, and call it from -draggedImage:… and
+ -draggingSessionEnded:…. The latter is only triggered in the where -beginDraggingSessionWithItems:… is used,
+ which currently only happens when dragging attachment elements.
+
+ (WebKit::WebViewImpl::fileNameForFilePromiseProvider):
+ (WebKit::webKitUnknownError):
+ (WebKit::WebViewImpl::writeToURLForFilePromiseProvider):
+
+ Deliver either NSFileWrapper data to the destination URL (in the case where an attachment identifier is known
+ and the corresponding API::Attachment is backed by a file wrapper), or save the contents of the blob URL to the
+ destination.
+
+ (WebKit::WebViewImpl::dragSourceOperationMask):
+ (WebKit::WebViewImpl::draggingSessionEnded):
+ (WebKit::WebViewImpl::startDrag):
+
2018-08-22 Aditya Keerthi <akeer...@apple.com>
[iOS] Add support for the inputmode attribute
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm (235201 => 235202)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm 2018-08-22 21:22:13 UTC (rev 235201)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm 2018-08-22 21:35:02 UTC (rev 235202)
@@ -201,6 +201,13 @@
#endif
#endif
+#if PLATFORM(MAC) && ENABLE(DRAG_SUPPORT)
+
+@interface WKWebView () <NSFilePromiseProviderDelegate, NSDraggingSource>
+@end
+
+#endif
+
static HashMap<WebKit::WebPageProxy*, WKWebView *>& pageToViewMap()
{
static NeverDestroyed<HashMap<WebKit::WebPageProxy*, WKWebView *>> map;
@@ -4079,6 +4086,30 @@
[self _gestureEventWasNotHandledByWebCore:event];
}
+#if ENABLE(DRAG_SUPPORT)
+
+- (NSString *)filePromiseProvider:(NSFilePromiseProvider *)filePromiseProvider fileNameForType:(NSString *)fileType
+{
+ return _impl->fileNameForFilePromiseProvider(filePromiseProvider, fileType);
+}
+
+- (void)filePromiseProvider:(NSFilePromiseProvider *)filePromiseProvider writePromiseToURL:(NSURL *)url completionHandler:(void (^)(NSError *error))completionHandler
+{
+ _impl->writeToURLForFilePromiseProvider(filePromiseProvider, url, completionHandler);
+}
+
+- (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context
+{
+ return _impl->dragSourceOperationMask(session, context);
+}
+
+- (void)draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation
+{
+ _impl->draggingSessionEnded(session, screenPoint, operation);
+}
+
+#endif // ENABLE(DRAG_SUPPORT)
+
#endif // PLATFORM(MAC)
#if HAVE(TOUCH_BAR)
Modified: trunk/Source/WebKit/UIProcess/API/mac/WKView.mm (235201 => 235202)
--- trunk/Source/WebKit/UIProcess/API/mac/WKView.mm 2018-08-22 21:22:13 UTC (rev 235201)
+++ trunk/Source/WebKit/UIProcess/API/mac/WKView.mm 2018-08-22 21:35:02 UTC (rev 235202)
@@ -66,6 +66,13 @@
@end
#endif
+#if ENABLE(DRAG_SUPPORT)
+
+@interface WKView () <NSFilePromiseProviderDelegate, NSDraggingSource>
+@end
+
+#endif
+
@implementation WKView
#if WK_API_ENABLED
@@ -1084,6 +1091,30 @@
#endif // HAVE(TOUCH_BAR)
+#if ENABLE(DRAG_SUPPORT)
+
+- (NSString *)filePromiseProvider:(NSFilePromiseProvider *)filePromiseProvider fileNameForType:(NSString *)fileType
+{
+ return _data->_impl->fileNameForFilePromiseProvider(filePromiseProvider, fileType);
+}
+
+- (void)filePromiseProvider:(NSFilePromiseProvider *)filePromiseProvider writePromiseToURL:(NSURL *)url completionHandler:(void (^)(NSError *error))completionHandler
+{
+ _data->_impl->writeToURLForFilePromiseProvider(filePromiseProvider, url, completionHandler);
+}
+
+- (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context
+{
+ return _data->_impl->dragSourceOperationMask(session, context);
+}
+
+- (void)draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation
+{
+ _data->_impl->draggingSessionEnded(session, screenPoint, operation);
+}
+
+#endif // ENABLE(DRAG_SUPPORT)
+
@end
@implementation WKView (Private)
Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h (235201 => 235202)
--- trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h 2018-08-22 21:22:13 UTC (rev 235201)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h 2018-08-22 21:35:02 UTC (rev 235202)
@@ -424,6 +424,12 @@
bool performDragOperation(id <NSDraggingInfo>);
NSView *hitTestForDragTypes(CGPoint, NSSet *types);
void registerDraggedTypes();
+
+ NSDragOperation dragSourceOperationMask(NSDraggingSession *, NSDraggingContext);
+ void draggingSessionEnded(NSDraggingSession *, NSPoint, NSDragOperation);
+
+ NSString *fileNameForFilePromiseProvider(NSFilePromiseProvider *, NSString *fileType);
+ void writeToURLForFilePromiseProvider(NSFilePromiseProvider *, NSURL *, void(^)(NSError *));
#endif
void startWindowDrag();
@@ -627,6 +633,10 @@
void handleRequestedCandidates(NSInteger sequenceNumber, NSArray<NSTextCheckingResult *> *candidates);
void flushPendingMouseEventCallbacks();
+#if ENABLE(DRAG_SUPPORT)
+ void sendDragEndToPage(CGPoint endPoint, NSDragOperation);
+#endif
+
WeakObjCPtr<NSView<WebViewImplDelegate>> m_view;
std::unique_ptr<PageClient> m_pageClient;
Ref<WebPageProxy> m_page;
Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm (235201 => 235202)
--- trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm 2018-08-22 21:22:13 UTC (rev 235201)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm 2018-08-22 21:35:02 UTC (rev 235202)
@@ -28,6 +28,7 @@
#if PLATFORM(MAC)
+#import "APIAttachment.h"
#import "APILegacyContextHistoryClient.h"
#import "APINavigation.h"
#import "AttributedString.h"
@@ -54,6 +55,7 @@
#import "UndoOrRedo.h"
#import "ViewGestureController.h"
#import "WKBrowsingContextControllerInternal.h"
+#import "WKErrorInternal.h"
#import "WKFullScreenWindowController.h"
#import "WKImmediateActionController.h"
#import "WKPrintingView.h"
@@ -83,6 +85,7 @@
#import <WebCore/LoaderNSURLExtras.h>
#import <WebCore/LocalizedStrings.h>
#import <WebCore/PlatformEventFactoryMac.h>
+#import <WebCore/PromisedAttachmentInfo.h>
#import <WebCore/TextAlternativeWithRange.h>
#import <WebCore/TextUndoInsertionMarkupMac.h>
#import <WebCore/WebActionDisablingCALayerDelegate.h>
@@ -874,6 +877,51 @@
@end
+@interface WKPromisedAttachmentContext : NSObject {
+@private
+ RetainPtr<NSURL> _blobURL;
+ RetainPtr<NSString> _filename;
+ RetainPtr<NSString> _attachmentIdentifier;
+}
+
+- (instancetype)initWithAttachmentInfo:(const WebCore::PromisedAttachmentInfo&)info;
+
+@property (nonatomic, readonly) NSURL *blobURL;
+@property (nonatomic, readonly) NSString *filename;
+@property (nonatomic, readonly) NSString *attachmentIdentifier;
+
+@end
+
+@implementation WKPromisedAttachmentContext
+
+- (instancetype)initWithAttachmentInfo:(const WebCore::PromisedAttachmentInfo&)info
+{
+ if (!(self = [super init]))
+ return nil;
+
+ _blobURL = info.blobURL;
+ _filename = info.filename;
+ _attachmentIdentifier = info.attachmentIdentifier;
+ return self;
+}
+
+- (NSURL *)blobURL
+{
+ return _blobURL.get();
+}
+
+- (NSString *)filename
+{
+ return _filename.get();
+}
+
+- (NSString *)attachmentIdentifier
+{
+ return _attachmentIdentifier.get();
+}
+
+@end
+
namespace WebKit {
NSTouchBar *WebViewImpl::makeTouchBar()
@@ -3660,8 +3708,13 @@
#endif // WK_API_ENABLED
#if ENABLE(DRAG_SUPPORT)
-void WebViewImpl::draggedImage(NSImage *image, CGPoint endPoint, NSDragOperation operation)
+void WebViewImpl::draggedImage(NSImage *, CGPoint endPoint, NSDragOperation operation)
{
+ sendDragEndToPage(endPoint, operation);
+}
+
+void WebViewImpl::sendDragEndToPage(CGPoint endPoint, NSDragOperation operation)
+{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
NSPoint windowImageLoc = [[m_view window] convertScreenToBase:NSPointFromCGPoint(endPoint)];
@@ -3849,6 +3902,66 @@
[m_view registerForDraggedTypes:[types allObjects]];
}
+NSString *WebViewImpl::fileNameForFilePromiseProvider(NSFilePromiseProvider *provider, NSString *)
+{
+ id userInfo = provider.userInfo;
+ if (![userInfo isKindOfClass:[WKPromisedAttachmentContext class]])
+ return nil;
+
+ return [(WKPromisedAttachmentContext *)userInfo filename];
+}
+
+static NSError *webKitUnknownError()
+{
+#if WK_API_ENABLED
+ return [NSError errorWithDomain:WKErrorDomain code:WKErrorUnknown userInfo:nil];
+#else
+ return [NSError errorWithDomain:@"WKErrorDomain" code:1 userInfo:nil];
+#endif
+}
+
+void WebViewImpl::writeToURLForFilePromiseProvider(NSFilePromiseProvider *provider, NSURL *fileURL, void(^completionHandler)(NSError *))
+{
+ id userInfo = provider.userInfo;
+ if (![userInfo isKindOfClass:[WKPromisedAttachmentContext class]]) {
+ completionHandler(webKitUnknownError());
+ return;
+ }
+
+ WKPromisedAttachmentContext *info = (WKPromisedAttachmentContext *)userInfo;
+ auto attachment = m_page->attachmentForIdentifier(info.attachmentIdentifier);
+ if (NSFileWrapper *fileWrapper = attachment ? attachment->fileWrapper() : nil) {
+ NSError *attachmentWritingError = nil;
+ if ([fileWrapper writeToURL:fileURL options:0 originalContentsURL:nil error:&attachmentWritingError])
+ completionHandler(nil);
+ else
+ completionHandler(attachmentWritingError);
+ return;
+ }
+
+ WebCore::URL blobURL { info.blobURL };
+ if (blobURL.isEmpty()) {
+ completionHandler(webKitUnknownError());
+ return;
+ }
+
+ m_page->writeBlobToFilePath(blobURL, fileURL.path, [protectedCompletionHandler = makeBlockPtr(completionHandler)] (bool success) {
+ protectedCompletionHandler(success ? nil : webKitUnknownError());
+ });
+}
+
+NSDragOperation WebViewImpl::dragSourceOperationMask(NSDraggingSession *, NSDraggingContext context)
+{
+ if (context == NSDraggingContextOutsideApplication || m_page->currentDragIsOverFileInput())
+ return NSDragOperationCopy;
+ return NSDragOperationGeneric | NSDragOperationMove | NSDragOperationCopy;
+}
+
+void WebViewImpl::draggingSessionEnded(NSDraggingSession *, NSPoint endPoint, NSDragOperation operation)
+{
+ sendDragEndToPage(NSPointToCGPoint(endPoint), operation);
+}
+
#endif // ENABLE(DRAG_SUPPORT)
void WebViewImpl::startWindowDrag()
@@ -3873,14 +3986,34 @@
// The call below could release the view.
auto protector = m_view.get();
+ auto clientDragLocation = item.dragLocationInWindowCoordinates;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
#pragma clang diagnostic pop
+
+ if (auto& attachmentInfo = item.promisedAttachmentInfo) {
+ auto provider = adoptNS([[NSFilePromiseProvider alloc] initWithFileType:attachmentInfo.contentType delegate:(id <NSFilePromiseProviderDelegate>)m_view.getAutoreleased()]);
+ [provider setUserInfo:[[[WKPromisedAttachmentContext alloc] initWithAttachmentInfo:attachmentInfo] autorelease]];
+ auto draggingItem = adoptNS([[NSDraggingItem alloc] initWithPasteboardWriter:provider.get()]);
+ [draggingItem setDraggingFrame:NSMakeRect(clientDragLocation.x(), clientDragLocation.y() - size.height(), size.width(), size.height()) contents:dragNSImage.get()];
+ [m_view beginDraggingSessionWithItems:@[draggingItem.get()] event:m_lastMouseDownEvent.get() source:(id <NSDraggingSource>)m_view.getAutoreleased()];
+
+ ASSERT(attachmentInfo.additionalTypes.size() == attachmentInfo.additionalData.size());
+ if (attachmentInfo.additionalTypes.size() == attachmentInfo.additionalData.size()) {
+ for (size_t index = 0; index < attachmentInfo.additionalTypes.size(); ++index) {
+ auto nsData = attachmentInfo.additionalData[index]->createNSData();
+ [pasteboard setData:nsData.get() forType:attachmentInfo.additionalTypes[index]];
+ }
+ }
+ m_page->didStartDrag();
+ return;
+ }
+
[pasteboard setString:@"" forType:PasteboardTypes::WebDummyPboardType];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- [m_view dragImage:dragNSImage.get() at:NSPointFromCGPoint(item.dragLocationInWindowCoordinates) offset:NSZeroSize event:m_lastMouseDownEvent.get() pasteboard:pasteboard source:m_view.getAutoreleased() slideBack:YES];
+ [m_view dragImage:dragNSImage.get() at:NSPointFromCGPoint(clientDragLocation) offset:NSZeroSize event:m_lastMouseDownEvent.get() pasteboard:pasteboard source:m_view.getAutoreleased() slideBack:YES];
#pragma clang diagnostic pop
m_page->didStartDrag();
}
Modified: trunk/Tools/ChangeLog (235201 => 235202)
--- trunk/Tools/ChangeLog 2018-08-22 21:22:13 UTC (rev 235201)
+++ trunk/Tools/ChangeLog 2018-08-22 21:35:02 UTC (rev 235202)
@@ -1,3 +1,67 @@
+2018-08-22 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [Attachment Support] Support dragging attachment elements out as files on macOS
+ https://bugs.webkit.org/show_bug.cgi?id=181294
+ <rdar://problem/36298801>
+
+ Reviewed by Tim Horton.
+
+ Add DragAndDropSimulator support for intercepting calls to -beginDraggingSessionWithitems:event:source:. This
+ enables us to write API tests for macOS that exercise the attachment SPI in combination with dragging attachment
+ elements.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
+ (-[TestWKWebView attachmentElementMidPoint]):
+
+ Add a helper method local to this test suite that grabs the midpoint (in client coordinates) or the first
+ attachment element in the document.
+
+ (TestWebKitAPI::TEST):
+
+ Add a new API test to verify that dragging an attachment element on macOS produces file providers which may be
+ used to write attachment data to a path on disk. Additionally, refactor an existing API test,
+ MoveAttachmentElementAsIconByDragging, so that it runs on both iOS and macOS, to test the ability to move
+ attachment elements around in a document by using drag and drop.
+
+ * TestWebKitAPI/cocoa/DragAndDropSimulator.h:
+ * TestWebKitAPI/mac/DragAndDropSimulatorMac.mm:
+ (-[DragAndDropTestWKWebView beginDraggingSessionWithItems:event:source:]):
+ (-[DragAndDropSimulator initWithWebViewFrame:configuration:]):
+ (-[DragAndDropSimulator dealloc]):
+ (-[DragAndDropSimulator runFrom:to:]):
+ (-[DragAndDropSimulator beginDraggingSessionInWebView:withItems:source:]):
+
+ Begin a drag session and kick off the -continueDragSession loop. Unlike -performDragInWebView:…, which spins
+ the main runloop until dragging ends, this version returns execution to the web view and schedules dragging
+ updates asynchronously. This matches AppKit behavior.
+
+ (-[DragAndDropSimulator continueDragSession]):
+
+ Increment the dragging progress amount, send a drag update to the web view, and continue scheduling calls to
+ itself until the progress reaches 1.
+
+ (-[DragAndDropSimulator performDragInWebView:atLocation:withImage:pasteboard:source:]):
+ (-[DragAndDropSimulator initializeDraggingInfo:dragImage:source:]):
+
+ Pull out common logic for creating a new TestDraggingInfo after starting a drag.
+
+ (-[DragAndDropSimulator insertedAttachments]):
+ (-[DragAndDropSimulator removedAttachments]):
+ (-[DragAndDropSimulator draggingSession]):
+ (-[DragAndDropSimulator receivePromisedFiles]):
+
+ Helper method to save promised files written to the pasteboard after a drag to the temporary directory. These
+ files are tracked by DragAndDropSimulator and automatically cleaned up after the test finishes.
+
+ (-[DragAndDropSimulator endDataTransfer]):
+
+ Add a method stub on macOS, so that MoveAttachmentElementAsIconByDragging can be made cross-platform.
+
+ (-[DragAndDropSimulator _webView:didInsertAttachment:withSource:]):
+ (-[DragAndDropSimulator _webView:didRemoveAttachment:]):
+
+ Implement method stubs to keep track of inserted or removed attachments while simulating a drag.
+
2018-08-22 Aditya Keerthi <akeer...@apple.com>
[iOS] Add support for the inputmode attribute
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm (235201 => 235202)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm 2018-08-22 21:22:13 UTC (rev 235201)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm 2018-08-22 21:35:02 UTC (rev 235202)
@@ -265,6 +265,18 @@
return attachment.autorelease();
}
+- (CGPoint)attachmentElementMidPoint
+{
+ __block CGPoint midPoint;
+ __block bool doneEvaluatingScript = false;
+ [self evaluateJavaScript:@"r = document.querySelector('attachment').getBoundingClientRect(); [r.left + r.width / 2, r.top + r.height / 2]" completionHandler:^(NSArray<NSNumber *> *result, NSError *) {
+ midPoint = CGPointMake(result.firstObject.floatValue, result.lastObject.floatValue);
+ doneEvaluatingScript = true;
+ }];
+ TestWebKitAPI::Util::run(&doneEvaluatingScript);
+ return midPoint;
+}
+
- (CGSize)attachmentElementSize
{
__block CGSize size;
@@ -1077,6 +1089,34 @@
[htmlAttachment expectRequestedDataToBe:nil];
}
+TEST(WKAttachmentTests, MoveAttachmentElementAsIconByDragging)
+{
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ [configuration _setAttachmentElementEnabled:YES];
+ auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:NSMakeRect(0, 0, 400, 400) configuration:configuration.get()]);
+ TestWKWebView *webView = [simulator webView];
+ [webView synchronouslyLoadHTMLString:attachmentEditingTestMarkup];
+
+ auto data = ""
+ auto attachment = retainPtr([webView synchronouslyInsertAttachmentWithFilename:@"document.pdf" contentType:@"application/pdf" data:data.get()]);
+
+ [webView _executeEditCommand:@"InsertParagraph" argument:nil completion:nil];
+ [webView _executeEditCommand:@"InsertHTML" argument:@"<strong>text</strong>" completion:nil];
+ [webView _synchronouslyExecuteEditCommand:@"InsertParagraph" argument:nil];
+ [webView expectElementTag:@"ATTACHMENT" toComeBefore:@"STRONG"];
+
+ // Drag the attachment element to somewhere below the strong text.
+ [simulator runFrom:[webView attachmentElementMidPoint] to:CGPointMake(50, 300)];
+
+ EXPECT_EQ([simulator insertedAttachments].count, [simulator removedAttachments].count);
+ [attachment expectRequestedDataToBe:data.get()];
+ EXPECT_WK_STREQ("document.pdf", [webView valueOfAttribute:@"title" forQuerySelector:@"attachment"]);
+ EXPECT_WK_STREQ("application/pdf", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]);
+
+ [webView expectElementTag:@"STRONG" toComeBefore:@"ATTACHMENT"];
+ [simulator endDataTransfer];
+}
+
#pragma mark - Platform-specific tests
#if PLATFORM(MAC)
@@ -1128,15 +1168,14 @@
[webView synchronouslyLoadHTMLString:attachmentEditingTestMarkup];
[simulator writePromisedFiles:@[ testPDFFileURL(), testImageFileURL() ]];
- ObserveAttachmentUpdatesForScope observer(webView);
[simulator runFrom:CGPointMake(0, 0) to:CGPointMake(50, 50)];
while ([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]]) {
- if (observer.observer().inserted.count == 2)
+ if ([simulator insertedAttachments].count == 2)
break;
}
EXPECT_EQ(2, [[webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment').length"] intValue]);
- auto insertedAttachments = retainPtr(observer.observer().inserted);
+ auto insertedAttachments = retainPtr([simulator insertedAttachments]);
NSArray<NSData *> *expectedData = @[ testPDFData(), testImageData() ];
for (_WKAttachment *attachment in insertedAttachments.get()) {
EXPECT_GT(attachment.info.filePath.length, 0U);
@@ -1149,13 +1188,30 @@
[webView _synchronouslyExecuteEditCommand:@"SelectAll" argument:nil];
[webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil];
- NSArray<_WKAttachment *> *removedAttachments = [observer.observer() removed];
- EXPECT_EQ(2U, removedAttachments.count);
+ auto removedAttachments = retainPtr([simulator removedAttachments]);
+ EXPECT_EQ(2U, [removedAttachments count]);
EXPECT_EQ(0, [[webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment').length"] intValue]);
EXPECT_TRUE([removedAttachments containsObject:[insertedAttachments firstObject]]);
EXPECT_TRUE([removedAttachments containsObject:[insertedAttachments lastObject]]);
}
+TEST(WKAttachmentTestsMac, DragAttachmentAsFilePromise)
+{
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ [configuration _setAttachmentElementEnabled:YES];
+ auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:NSMakeRect(0, 0, 400, 400) configuration:configuration.get()]);
+ TestWKWebView *webView = [simulator webView];
+ [webView synchronouslyLoadHTMLString:attachmentEditingTestMarkup];
+
+ auto fileWrapper = adoptNS([[NSFileWrapper alloc] initWithURL:testPDFFileURL() options:0 error:nil]);
+ auto attachment = retainPtr([webView synchronouslyInsertAttachmentWithFileWrapper:fileWrapper.get() contentType:nil]);
+ [simulator runFrom:[webView attachmentElementMidPoint] to:CGPointMake(300, 300)];
+
+ NSArray<NSURL *> *urls = [simulator receivePromisedFiles];
+ EXPECT_EQ(1U, urls.count);
+ EXPECT_TRUE([[NSData dataWithContentsOfURL:urls.firstObject] isEqualToData:testPDFData()]);
+}
+
#endif // PLATFORM(MAC)
#if PLATFORM(IOS)
@@ -1367,34 +1423,6 @@
[dragAndDropSimulator endDataTransfer];
}
-TEST(WKAttachmentTestsIOS, MoveAttachmentElementAsIconByDragging)
-{
- auto webView = webViewForTestingAttachments();
- auto data = ""
- RetainPtr<_WKAttachment> attachment;
- {
- ObserveAttachmentUpdatesForScope observer(webView.get());
- attachment = [webView synchronouslyInsertAttachmentWithFilename:@"document.pdf" contentType:@"application/pdf" data:data.get()];
- observer.expectAttachmentUpdates(@[], @[attachment.get()]);
- }
-
- [webView _executeEditCommand:@"InsertParagraph" argument:nil completion:nil];
- [webView _executeEditCommand:@"InsertHTML" argument:@"<strong>text</strong>" completion:nil];
- [webView _synchronouslyExecuteEditCommand:@"InsertParagraph" argument:nil];
- [webView expectElementTag:@"ATTACHMENT" toComeBefore:@"STRONG"];
-
- auto dragAndDropSimulator = adoptNS([[DragAndDropSimulator alloc] initWithWebView:webView.get()]);
- [dragAndDropSimulator runFrom:CGPointMake(25, 25) to:CGPointMake(25, 425)];
-
- attachment = [[dragAndDropSimulator insertedAttachments] firstObject];
- [attachment expectRequestedDataToBe:data.get()];
- EXPECT_WK_STREQ("document.pdf", [webView valueOfAttribute:@"title" forQuerySelector:@"attachment"]);
- EXPECT_WK_STREQ("application/pdf", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]);
-
- [webView expectElementTag:@"STRONG" toComeBefore:@"ATTACHMENT"];
- [dragAndDropSimulator endDataTransfer];
-}
-
#endif // PLATFORM(IOS)
} // namespace TestWebKitAPI
Modified: trunk/Tools/TestWebKitAPI/cocoa/DragAndDropSimulator.h (235201 => 235202)
--- trunk/Tools/TestWebKitAPI/cocoa/DragAndDropSimulator.h 2018-08-22 21:22:13 UTC (rev 235201)
+++ trunk/Tools/TestWebKitAPI/cocoa/DragAndDropSimulator.h 2018-08-22 21:35:02 UTC (rev 235202)
@@ -79,6 +79,7 @@
- (instancetype)initWithWebViewFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration;
// The start location, end location, and locations of additional item requests are all in window coordinates.
- (void)runFrom:(CGPoint)startLocation to:(CGPoint)endLocation;
+- (void)endDataTransfer;
@property (nonatomic, readonly) NSArray<_WKAttachment *> *insertedAttachments;
@property (nonatomic, readonly) NSArray<_WKAttachment *> *removedAttachments;
@property (nonatomic, readonly) TestWKWebView *webView;
@@ -88,7 +89,6 @@
- (instancetype)initWithWebView:(TestWKWebView *)webView;
- (void)runFrom:(CGPoint)startLocation to:(CGPoint)endLocation additionalItemRequestLocations:(ProgressToCGPointValueMap)additionalItemRequestLocations;
- (void)waitForInputSession;
-- (void)endDataTransfer;
@property (nonatomic, readonly) DragAndDropPhase phase;
@property (nonatomic) BOOL allowsFocusToStartInputSession;
@@ -121,6 +121,7 @@
- (void)writePromisedFiles:(NSArray<NSURL *> *)fileURLs;
- (void)writeFiles:(NSArray<NSURL *> *)fileURLs;
+- (NSArray<NSURL *> *)receivePromisedFiles;
#endif // PLATFORM(MAC)
Modified: trunk/Tools/TestWebKitAPI/mac/DragAndDropSimulatorMac.mm (235201 => 235202)
--- trunk/Tools/TestWebKitAPI/mac/DragAndDropSimulatorMac.mm 2018-08-22 21:22:13 UTC (rev 235201)
+++ trunk/Tools/TestWebKitAPI/mac/DragAndDropSimulatorMac.mm 2018-08-22 21:35:02 UTC (rev 235202)
@@ -37,7 +37,9 @@
@class DragAndDropTestWKWebView;
@interface DragAndDropSimulator ()
+- (void)beginDraggingSessionInWebView:(DragAndDropTestWKWebView *)webView withItems:(NSArray<NSDraggingItem *> *)items source:(id<NSDraggingSource>)source;
- (void)performDragInWebView:(DragAndDropTestWKWebView *)webView atLocation:(NSPoint)viewLocation withImage:(NSImage *)image pasteboard:(NSPasteboard *)pasteboard source:(id)source;
+@property (nonatomic, readonly) NSDraggingSession *draggingSession;
@end
@interface DragAndDropTestWKWebView : TestWKWebView
@@ -59,6 +61,12 @@
[_dragAndDropSimulator performDragInWebView:self atLocation:viewLocation withImage:image pasteboard:pboard source:sourceObj];
}
+- (NSDraggingSession *)beginDraggingSessionWithItems:(NSArray<NSDraggingItem *> *)items event:(NSEvent *)event source:(id<NSDraggingSource>)source
+{
+ [_dragAndDropSimulator beginDraggingSessionInWebView:self withItems:items source:source];
+ return [_dragAndDropSimulator draggingSession];
+}
+
- (void)waitForPendingMouseEvents
{
__block bool doneProcessMouseEvents = false;
@@ -85,10 +93,16 @@
RetainPtr<NSPasteboard> _externalDragPasteboard;
RetainPtr<NSImage> _externalDragImage;
RetainPtr<NSArray<NSURL *>> _externalPromisedFiles;
+ RetainPtr<NSMutableArray<_WKAttachment *>> _insertedAttachments;
+ RetainPtr<NSMutableArray<_WKAttachment *>> _removedAttachments;
+ RetainPtr<NSMutableArray<NSURL *>> _filePromiseDestinationURLs;
+ RetainPtr<NSDraggingSession> _draggingSession;
+ RetainPtr<NSMutableArray<NSFilePromiseProvider *>> _filePromiseProviders;
BlockPtr<void()> _willEndDraggingHandler;
NSPoint _startLocationInWindow;
NSPoint _endLocationInWindow;
double _progress;
+ bool _doneWaitingForDraggingSession;
}
@synthesize currentDragOperation=_currentDragOperation;
@@ -103,11 +117,20 @@
{
if (self = [super init]) {
_webView = adoptNS([[DragAndDropTestWKWebView alloc] initWithFrame:frame configuration:configuration ?: [[[WKWebViewConfiguration alloc] init] autorelease] simulator:self]);
+ _filePromiseDestinationURLs = adoptNS([NSMutableArray new]);
[_webView setUIDelegate:self];
}
return self;
}
+- (void)dealloc
+{
+ for (NSURL *url in _filePromiseDestinationURLs.get())
+ [[NSFileManager defaultManager] removeItemAtURL:url error:nil];
+
+ [super dealloc];
+}
+
- (NSPoint)flipAboutXAxisInHostWindow:(NSPoint)point
{
return { point.x, NSHeight([[_webView hostWindow] frame]) - point.y };
@@ -129,11 +152,16 @@
- (void)runFrom:(CGPoint)flippedStartLocation to:(CGPoint)flippedEndLocation
{
+ _insertedAttachments = adoptNS([NSMutableArray new]);
+ _removedAttachments = adoptNS([NSMutableArray new]);
+ _doneWaitingForDraggingSession = true;
_startLocationInWindow = [self flipAboutXAxisInHostWindow:flippedStartLocation];
_endLocationInWindow = [self flipAboutXAxisInHostWindow:flippedEndLocation];
_currentDragOperation = NSDragOperationNone;
_draggingInfo = nil;
+ _draggingSession = nil;
_progress = 0;
+ _filePromiseProviders = adoptNS([NSMutableArray new]);
if (NSPasteboard *pasteboard = self.externalDragPasteboard) {
NSPoint startLocationInView = [_webView convertPoint:_startLocationInWindow fromView:nil];
@@ -154,20 +182,76 @@
[_webView mouseDragToPoint:[self locationInViewForCurrentProgress]];
[_webView waitForPendingMouseEvents];
+ TestWebKitAPI::Util::run(&_doneWaitingForDraggingSession);
+
[_webView mouseUpAtPoint:_endLocationInWindow];
[_webView waitForPendingMouseEvents];
}
+- (void)beginDraggingSessionInWebView:(DragAndDropTestWKWebView *)webView withItems:(NSArray<NSDraggingItem *> *)items source:(id<NSDraggingSource>)source
+{
+ NSMutableArray *pasteboardObjects = [NSMutableArray arrayWithCapacity:items.count];
+ NSMutableArray<NSString *> *promisedFileTypes = [NSMutableArray array];
+ for (NSDraggingItem *item in items) {
+ id pasteboardObject = item.item;
+ [pasteboardObjects addObject:pasteboardObject];
+ if ([pasteboardObject isKindOfClass:[NSFilePromiseProvider class]]) {
+ [_filePromiseProviders addObject:pasteboardObject];
+ [promisedFileTypes addObject:[(NSFilePromiseProvider *)pasteboardObject fileType]];
+ }
+ }
+
+ NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
+ [pasteboard clearContents];
+ [pasteboard writeObjects:pasteboardObjects];
+ if (promisedFileTypes.count) {
+ // Match AppKit behavior by writing legacy file promise types to the pasteboard as well.
+ [pasteboard setPropertyList:promisedFileTypes forType:NSFilesPromisePboardType];
+ [pasteboard addTypes:@[@"NSPromiseContentsPboardType", (NSString *)kPasteboardTypeFileURLPromise] owner:nil];
+ }
+
+ _draggingSession = adoptNS([[NSDraggingSession alloc] init]);
+ _doneWaitingForDraggingSession = false;
+ _initialDragImageLocationInView = items[0].draggingFrame.origin;
+ id dragImageContents = items[0].imageComponents.firstObject.contents;
+ [self initializeDraggingInfo:pasteboard dragImage:[dragImageContents isKindOfClass:[NSImage class]] ? dragImageContents : nil source:source];
+
+ _currentDragOperation = [_webView draggingEntered:_draggingInfo.get()];
+ [_webView waitForNextPresentationUpdate];
+ [self performSelector:@selector(continueDragSession) withObject:nil afterDelay:0];
+}
+
+- (void)continueDragSession
+{
+ _progress = std::min<double>(1, _progress + dragUpdateProgressIncrement);
+
+ if (_progress < 1) {
+ [_draggingInfo setDraggingLocation:[self locationInViewForCurrentProgress]];
+ _currentDragOperation = [_webView draggingUpdated:_draggingInfo.get()];
+ [_webView waitForNextPresentationUpdate];
+ [self performSelector:@selector(continueDragSession) withObject:nil afterDelay:0];
+ return;
+ }
+
+ [_draggingInfo setDraggingLocation:_endLocationInWindow];
+
+ if (_willEndDraggingHandler)
+ _willEndDraggingHandler();
+
+ if (_currentDragOperation != NSDragOperationNone && [_webView prepareForDragOperation:_draggingInfo.get()])
+ [_webView performDragOperation:_draggingInfo.get()];
+ else if (_currentDragOperation == NSDragOperationNone)
+ [_webView draggingExited:_draggingInfo.get()];
+ [_webView waitForNextPresentationUpdate];
+ [(id <NSDraggingSource>)_webView.get() draggingSession:_draggingSession.get() endedAtPoint:_endLocationInWindow operation:_currentDragOperation];
+
+ _doneWaitingForDraggingSession = true;
+}
+
- (void)performDragInWebView:(DragAndDropTestWKWebView *)webView atLocation:(NSPoint)viewLocation withImage:(NSImage *)image pasteboard:(NSPasteboard *)pasteboard source:(id)source
{
_initialDragImageLocationInView = viewLocation;
- _draggingInfo = adoptNS([[TestDraggingInfo alloc] initWithDragAndDropSimulator:self]);
- [_draggingInfo setDraggedImage:image];
- [_draggingInfo setDraggingPasteboard:pasteboard];
- [_draggingInfo setDraggingSource:source];
- [_draggingInfo setDraggingLocation:[self locationInViewForCurrentProgress]];
- [_draggingInfo setDraggingSourceOperationMask:NSDragOperationEvery];
- [_draggingInfo setNumberOfValidItemsForDrop:pasteboard.pasteboardItems.count];
+ [self initializeDraggingInfo:pasteboard dragImage:image source:source];
_currentDragOperation = [_webView draggingEntered:_draggingInfo.get()];
[_webView waitForNextPresentationUpdate];
@@ -196,14 +280,25 @@
}
}
+- (void)initializeDraggingInfo:(NSPasteboard *)pasteboard dragImage:(NSImage *)image source:(id)source
+{
+ _draggingInfo = adoptNS([[TestDraggingInfo alloc] initWithDragAndDropSimulator:self]);
+ [_draggingInfo setDraggedImage:image];
+ [_draggingInfo setDraggingPasteboard:pasteboard];
+ [_draggingInfo setDraggingSource:source];
+ [_draggingInfo setDraggingLocation:[self locationInViewForCurrentProgress]];
+ [_draggingInfo setDraggingSourceOperationMask:NSDragOperationEvery];
+ [_draggingInfo setNumberOfValidItemsForDrop:pasteboard.pasteboardItems.count];
+}
+
- (NSArray<_WKAttachment *> *)insertedAttachments
{
- return @[ ];
+ return _insertedAttachments.get();
}
- (NSArray<_WKAttachment *> *)removedAttachments
{
- return @[ ];
+ return _removedAttachments.get();
}
- (TestWKWebView *)webView
@@ -231,6 +326,11 @@
return _externalDragImage.get();
}
+- (NSDraggingSession *)draggingSession
+{
+ return _draggingSession.get();
+}
+
- (id <NSDraggingInfo>)draggingInfo
{
return _draggingInfo.get();
@@ -308,6 +408,45 @@
[_externalDragPasteboard setPropertyList:paths forType:NSFilenamesPboardType];
}
+- (NSArray<NSURL *> *)receivePromisedFiles
+{
+ auto destinationURLs = adoptNS([NSMutableArray new]);
+ for (NSFilePromiseProvider *provider in _filePromiseProviders.get()) {
+ if (!provider.delegate)
+ continue;
+
+ int suffix = 1;
+ NSString *baseFileName = [provider.delegate filePromiseProvider:provider fileNameForType:provider.fileType];
+ NSString *uniqueFileName = baseFileName;
+ while ([[NSFileManager defaultManager] fileExistsAtPath:[NSTemporaryDirectory() stringByAppendingPathComponent:uniqueFileName]])
+ uniqueFileName = [NSString stringWithFormat:@"%@ %d", baseFileName, ++suffix];
+
+ NSURL *destinationURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:uniqueFileName]];
+ __block bool done = false;
+ [provider.delegate filePromiseProvider:provider writePromiseToURL:destinationURL completionHandler:^(NSError *) {
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+ [destinationURLs addObject:destinationURL];
+ [_filePromiseDestinationURLs addObject:destinationURL];
+ }
+ return destinationURLs.autorelease();
+}
+
+- (void)endDataTransfer
+{
+}
+
+- (void)_webView:(WKWebView *)webView didInsertAttachment:(_WKAttachment *)attachment withSource:(NSString *)source
+{
+ [_insertedAttachments addObject:attachment];
+}
+
+- (void)_webView:(WKWebView *)webView didRemoveAttachment:(_WKAttachment *)attachment
+{
+ [_removedAttachments addObject:attachment];
+}
+
@end
#endif // ENABLE(DRAG_SUPPORT) && PLATFORM(MAC) && WK_API_ENABLED