[Mac] Teach WebCore::Pasteboard about file promise drags
authoraestes@apple.com <aestes@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 6 Mar 2018 01:36:31 +0000 (01:36 +0000)
committeraestes@apple.com <aestes@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 6 Mar 2018 01:36:31 +0000 (01:36 +0000)
commit1d22211acbaa9376b16ccb1a32c37215a4f7f797
tree89f43999092619f04cf3a4a4d71523edc569fbd7
parent98bcc00ed59e5f982a9743f26ec57f9c600c2283
[Mac] Teach WebCore::Pasteboard about file promise drags
https://bugs.webkit.org/show_bug.cgi?id=183314
<rdar://problem/38105493>

Reviewed by Darin Adler.

Source/WebCore:

While WebKit does support receiving file promise drags (since r210360), WebCore::Pasteboard
has not been instructed on how to read their file paths. When the various pasteboard readers
ask for file paths after a file promise drop, they receive an empty vector. This impacts
various features, most notably the DataTransfer API.

Pasteboard actually cannot learn about promised file paths from the pasteboard itself, as
the pasteboard only contains the dragged files' UTIs. Promised file paths aren't known until
the WebKits call -[NSFilePromiseReceiver receivePromisedFilesAtDestination:...], at which
point the file paths are passed to WebCore as part of WebCore::DragData.

When we construct new Pasteboards for drag and drop, we need to store any promised file
paths from the DragData. Then, when the various pasteboard readers ask for file paths and
NSFilesPromisePboardType is on the pasteboard, we can return these promised file paths.

Tests: editing/pasteboard/data-transfer-items-drag-drop-file-promise.html
       editing/pasteboard/data-transfer-items-drop-file-promise.html
       editing/pasteboard/datatransfer-items-drop-plaintext-file-promise.html
       editing/pasteboard/datatransfer-types-dropping-text-file-promise.html
       editing/pasteboard/drag-file-promises-to-editable-element-as-URLs.html
       editing/pasteboard/drag-file-promises-to-editable-element-as-attachment.html
       editing/pasteboard/file-input-files-access-promise.html

* platform/FileSystem.h:
* platform/Pasteboard.h:
(WebCore::Pasteboard::Pasteboard):
* platform/mac/DragDataMac.mm:
(WebCore::DragData::containsPromise const):
* platform/mac/PasteboardMac.mm:
(WebCore::Pasteboard::Pasteboard):
(WebCore::Pasteboard::createForDragAndDrop):
(WebCore::toString):
(WebCore::Pasteboard::read):
(WebCore::Pasteboard::readFilePaths):
(WebCore::absoluteURLsFromPasteboardFilenames): Deleted.
* platform/mac/PlatformPasteboardMac.mm:
(WebCore::PlatformPasteboard::numberOfFiles const):

Source/WebKit:

Added a FIXME comment.

* UIProcess/Cocoa/WebViewImpl.mm:
(WebKit::WebViewImpl::performDragOperation):

Source/WebKitLegacy/mac:

Added a FIXME comment.

* WebView/WebView.mm:
(-[WebView performDragOperation:]):

Tools:

* DumpRenderTree/DumpRenderTreeFileDraggingSource.h:
* DumpRenderTree/DumpRenderTreeFileDraggingSource.m:
(-[DumpRenderTreeFileDraggingSource initWithPromisedFileURLs:]):
(-[DumpRenderTreeFileDraggingSource dealloc]):

Taught DumpRenderTreeFileDraggingSource to store the promised file URLs.

* DumpRenderTree/mac/DumpRenderTree.mm:
(runTest):

Called +[DumpRenderTreeDraggingInfo clearAllFilePromiseReceivers] after running a test.

* DumpRenderTree/mac/DumpRenderTreeDraggingInfo.h:
* DumpRenderTree/mac/DumpRenderTreeDraggingInfo.mm:
(-[DumpRenderTreeFilePromiseReceiver initWithPromisedUTIs:]):
(-[DumpRenderTreeFilePromiseReceiver fileTypes]):
(-[DumpRenderTreeFilePromiseReceiver fileNames]):
(-[DumpRenderTreeFilePromiseReceiver dealloc]):
(copyFile):
(-[DumpRenderTreeFilePromiseReceiver receivePromisedFilesAtDestination:options:operationQueue:reader:]):

We can't instantiate real NSFilePromiseReceivers in DumpRenderTree. They rely on the
pasteboard server to generate unique file URLs, which is incompatible with our swizzled
NSPasteboard.

Instead, create a subclass of NSFilePromiseReceiver that implements its own promise resolution.
-receivePromisedFilesAtDestination:... asks its DumpRenderTreeFileDraggingSource for the
array of file URLs, then copies each to the destination directory on the specified operation
queue. It emulates how NSPasteboard tries to find a unique destination name by appending
numbers to the file name.

All receivers are collected in a global array that is cleared when each test finishes.
DumpRenderTreeFilePromiseReceiver will delete the files it copied in -dealloc.

(+[DumpRenderTreeDraggingInfo clearAllFilePromiseReceivers]):
(-[DumpRenderTreeDraggingInfo enumerateDraggingItemsWithOptions:forView:classes:searchOptions:usingBlock:]):

If NSFilesPromisePboardType is on the pasteboard and classArray contains
NSFilePromiseReceiver, construct a DumpRenderTreeFilePromiseReceiver, add it to the array of
all file promise receivers, then wrap it in an NSDraggingItem and call block.

* DumpRenderTree/mac/EventSendingController.mm:
(+[EventSendingController isSelectorExcludedFromWebScript:]):
(+[EventSendingController webScriptNameForSelector:]):
(-[EventSendingController beginDragWithFilePromises:]):

Implement eventSender.beginDragWithFilePromises() by placing file UTIs on the pasteboard
with type NSFilesPromisePboardType, creating a DumpRenderTreeFileDraggingSource with the
file URLs, and creating a new DumpRenderTreeDraggingInfo and passing it to
-[WebView draggingEntered:].

LayoutTests:

Added versions of file dragging tests in editing/pasteboard/ that use
beginDragWithFilePromises() instead of beginDragWithFiles().

* TestExpectations: Skipped the new tests.
* editing/pasteboard/data-transfer-items-drag-drop-file-promise-expected.txt: Added.
* editing/pasteboard/data-transfer-items-drag-drop-file-promise.html: Added.
* editing/pasteboard/data-transfer-items-drop-file-promise-expected.txt: Added.
* editing/pasteboard/data-transfer-items-drop-file-promise.html: Added.
* editing/pasteboard/datatransfer-items-drop-plaintext-file-promise-expected.txt: Added.
* editing/pasteboard/datatransfer-items-drop-plaintext-file-promise.html: Added.
* editing/pasteboard/datatransfer-types-dropping-text-file-promise-expected.txt: Added.
* editing/pasteboard/datatransfer-types-dropping-text-file-promise.html: Added.
* editing/pasteboard/drag-file-promises-to-editable-element-as-URLs-expected.txt: Added.
* editing/pasteboard/drag-file-promises-to-editable-element-as-URLs.html: Added.
* editing/pasteboard/drag-file-promises-to-editable-element-as-attachment-expected.txt: Added.
* editing/pasteboard/drag-file-promises-to-editable-element-as-attachment.html: Added.
* editing/pasteboard/file-input-files-access-promise-expected.txt: Added.
* editing/pasteboard/file-input-files-access-promise.html: Added.
* platform/mac-wk1/TestExpectations: Un-skipped the new tests.
* platform/win/TestExpectations: Skipped the new tests.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@229297 268f45cc-cd09-0410-ab3c-d52691b4dbfc
34 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/editing/pasteboard/data-transfer-items-drag-drop-file-promise-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/data-transfer-items-drag-drop-file-promise.html [new file with mode: 0644]
LayoutTests/editing/pasteboard/data-transfer-items-drop-file-promise-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/data-transfer-items-drop-file-promise.html [new file with mode: 0644]
LayoutTests/editing/pasteboard/datatransfer-items-drop-plaintext-file-promise-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/datatransfer-items-drop-plaintext-file-promise.html [new file with mode: 0644]
LayoutTests/editing/pasteboard/datatransfer-types-dropping-text-file-promise-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/datatransfer-types-dropping-text-file-promise.html [new file with mode: 0644]
LayoutTests/editing/pasteboard/drag-file-promises-to-editable-element-as-URLs-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/drag-file-promises-to-editable-element-as-URLs.html [new file with mode: 0644]
LayoutTests/editing/pasteboard/drag-file-promises-to-editable-element-as-attachment-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/drag-file-promises-to-editable-element-as-attachment.html [new file with mode: 0644]
LayoutTests/editing/pasteboard/file-input-files-access-promise-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/file-input-files-access-promise.html [new file with mode: 0644]
LayoutTests/platform/mac-wk1/TestExpectations
LayoutTests/platform/win/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/platform/Pasteboard.h
Source/WebCore/platform/mac/DragDataMac.mm
Source/WebCore/platform/mac/PasteboardMac.mm
Source/WebCore/platform/mac/PlatformPasteboardMac.mm
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/WebView/WebView.mm
Tools/ChangeLog
Tools/DumpRenderTree/DumpRenderTreeFileDraggingSource.h
Tools/DumpRenderTree/DumpRenderTreeFileDraggingSource.m
Tools/DumpRenderTree/mac/DumpRenderTree.mm
Tools/DumpRenderTree/mac/DumpRenderTreeDraggingInfo.h
Tools/DumpRenderTree/mac/DumpRenderTreeDraggingInfo.mm
Tools/DumpRenderTree/mac/EventSendingController.mm