Bug 165204 - Support File Promise during drag for macOS
Summary: Support File Promise during drag for macOS
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: HTML Editing (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified macOS 10.12
: P2 Normal
Assignee: Enrica Casucci
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-11-30 10:54 PST by Enrica Casucci
Modified: 2017-01-05 10:30 PST (History)
5 users (show)

See Also:


Attachments
Patch (18.31 KB, patch)
2016-11-30 11:00 PST, Enrica Casucci
no flags Details | Formatted Diff | Diff
Patch2 (18.66 KB, patch)
2016-12-06 12:38 PST, Enrica Casucci
no flags Details | Formatted Diff | Diff
Patch3 (19.47 KB, patch)
2016-12-14 17:05 PST, Enrica Casucci
buildbot: commit-queue-
Details | Formatted Diff | Diff
Archive of layout-test-results from ews115 for mac-yosemite (1.58 MB, application/zip)
2016-12-14 18:18 PST, Build Bot
no flags Details
Patch4 (19.79 KB, patch)
2017-01-03 14:01 PST, Enrica Casucci
thorton: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Enrica Casucci 2016-11-30 10:54:07 PST
File promise during drag is not supported when WebKit is the drop target.
We should add this, since Photos uses File Promise for drag and drop.

rdar://problem/19595567
Comment 1 Enrica Casucci 2016-11-30 11:00:30 PST
Created attachment 295733 [details]
Patch
Comment 2 WebKit Commit Bot 2016-11-30 11:03:14 PST
Attachment 295733 [details] did not pass style-queue:


ERROR: Source/WebKit2/ChangeLog:1:  ChangeLog entry has no bug number  [changelog/bugnumber] [5]
ERROR: Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3635:  Line contains only semicolon. If this should be an empty statement, use { } instead.  [whitespace/semicolon] [5]
ERROR: Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3636:  When wrapping a line, only indent 4 spaces.  [whitespace/indent] [3]
ERROR: Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3637:  Missing space inside { }.  [whitespace/braces] [5]
ERROR: Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3639:  Missing space inside { }.  [whitespace/braces] [5]
ERROR: Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3650:  No space between ^ and block definition.  [whitespace/brackets] [4]
ERROR: Source/WebKit2/UIProcess/Cocoa/WebViewImpl.h:585:  The parameter name "handle" adds no information, so it should be removed.  [readability/parameter_name] [5]
ERROR: Source/WebKit/mac/WebView/WebView.mm:6492:  Line contains only semicolon. If this should be an empty statement, use { } instead.  [whitespace/semicolon] [5]
ERROR: Source/WebKit/mac/WebView/WebView.mm:6494:  Missing space inside { }.  [whitespace/braces] [5]
ERROR: Source/WebKit/mac/WebView/WebView.mm:6496:  Missing space inside { }.  [whitespace/braces] [5]
ERROR: Source/WebKit/mac/WebView/WebView.mm:6506:  No space between ^ and block definition.  [whitespace/brackets] [4]
ERROR: Source/WebKit/mac/ChangeLog:1:  ChangeLog entry has no bug number  [changelog/bugnumber] [5]
ERROR: Source/WebCore/ChangeLog:1:  ChangeLog entry has no bug number  [changelog/bugnumber] [5]
Total errors found: 13 in 12 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 3 Tim Horton 2016-11-30 11:11:32 PST
Comment on attachment 295733 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=295733&action=review

> Source/WebCore/platform/mac/DragDataMac.mm:148
> +    return numberOfFiles() == 1;

Why does having one file mean that it is a promise? Couldn't you have one file before?
Comment 4 Sam Weinig 2016-11-30 13:20:21 PST
Comment on attachment 295733 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=295733&action=review

> Source/WebCore/ChangeLog:10
> +        Adds the support for handling File Promise type during
> +        drag.

Can you flesh out this ChangeLog (and the others)? Please include information about why this is 10.12 only.

> Source/WebKit2/Shared/WebCoreArgumentCoders.cpp:1262
>      dragData = DragData(pasteboardName, clientPosition, globalPosition, draggingSourceOperationMask, applicationFlags);
> +#if PLATFORM(MAC)
> +    dragData.setFileNames(fileNames);
> +#endif

Can we make fileNames cross-platform? It seems like a concept that will useful for other platforms and avoiding the #ifdef would make things more readable.

> Source/WebKit2/Shared/mac/PasteboardTypes.mm:58
> +                                    NSFilesPromisePboardType,

Is this actually new in 10.12?

> Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3631
> +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200

What about this requires 10.12?
Comment 5 Darin Adler 2016-12-01 09:27:03 PST
Comment on attachment 295733 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=295733&action=review

> Source/WebCore/platform/DragData.h:111
> +    void setFileNames(Vector<String>& fileNames) { m_fileNames = WTFMove(fileNames); }

This should be Vector<String>&&, an rvalue reference rather than an lvalue reference.
Comment 6 Enrica Casucci 2016-12-06 10:37:45 PST
(In reply to comment #4)
> Comment on attachment 295733 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=295733&action=review
> 
> > Source/WebCore/ChangeLog:10
> > +        Adds the support for handling File Promise type during
> > +        drag.
> 
> Can you flesh out this ChangeLog (and the others)? Please include
> information about why this is 10.12 only.
> 
> > Source/WebKit2/Shared/WebCoreArgumentCoders.cpp:1262
> >      dragData = DragData(pasteboardName, clientPosition, globalPosition, draggingSourceOperationMask, applicationFlags);
> > +#if PLATFORM(MAC)
> > +    dragData.setFileNames(fileNames);
> > +#endif
> 
> Can we make fileNames cross-platform? It seems like a concept that will
> useful for other platforms and avoiding the #ifdef would make things more
> readable.

Ok.
> 
> > Source/WebKit2/Shared/mac/PasteboardTypes.mm:58
> > +                                    NSFilesPromisePboardType,
> 
> Is this actually new in 10.12?

FilePromises are not new in 10.12, what is new is the API I'm using to request the fulfillment. I'll explain that in the ChangeLog.
> 
> > Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3631
> > +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
> 
> What about this requires 10.12?
Comment 7 Enrica Casucci 2016-12-06 10:38:52 PST
(In reply to comment #3)
> Comment on attachment 295733 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=295733&action=review
> 
> > Source/WebCore/platform/mac/DragDataMac.mm:148
> > +    return numberOfFiles() == 1;
> 
> Why does having one file mean that it is a promise? Couldn't you have one
> file before?

I agree this is not clear, I'll change the implementation.
Comment 8 Enrica Casucci 2016-12-06 12:38:35 PST
Created attachment 296307 [details]
Patch2
Comment 9 WebKit Commit Bot 2016-12-06 12:40:51 PST
Attachment 296307 [details] did not pass style-queue:


ERROR: Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3649:  No space between ^ and block definition.  [whitespace/brackets] [4]
ERROR: Source/WebKit/mac/WebView/WebView.mm:6537:  No space between ^ and block definition.  [whitespace/brackets] [4]
Total errors found: 2 in 12 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 10 Tim Horton 2016-12-06 16:07:28 PST
Comment on attachment 296307 [details]
Patch2

View in context: https://bugs.webkit.org/attachment.cgi?id=296307&action=review

> Source/WebKit2/Shared/mac/PasteboardTypes.mm:58
> +                                    NSFilesPromisePboardType,

usually we don't indent like this, just one level.

> Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3642
> +                    NSLog(@"There was an error with file:%@, skipping %@", fileURL, errorOrNil);

I don't love this logging (there should at least be a space after the colon, and maybe it should be reworded -- specifically the word "with" -- the error isn't "with" the file).

> Source/WebKit/mac/WebView/WebView.mm:6523
> +        __block Vector<String> fileNames;

Vector is not thread safe, but you're touching it from an operation queue's arbitrary dispatch thread? Seems like you need some locking, no? Maybe you should have Anders take a peek at this.
Comment 11 Enrica Casucci 2016-12-07 11:05:32 PST
(In reply to comment #10)
> Comment on attachment 296307 [details]
> Patch2
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=296307&action=review
> 
> > Source/WebKit2/Shared/mac/PasteboardTypes.mm:58
> > +                                    NSFilesPromisePboardType,
> 
> usually we don't indent like this, just one level.
> 
> > Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3642
> > +                    NSLog(@"There was an error with file:%@, skipping %@", fileURL, errorOrNil);
> 
> I don't love this logging (there should at least be a space after the colon,
> and maybe it should be reworded -- specifically the word "with" -- the error
> isn't "with" the file).
> 
> > Source/WebKit/mac/WebView/WebView.mm:6523
> > +        __block Vector<String> fileNames;
> 
> Vector is not thread safe, but you're touching it from an operation queue's
> arbitrary dispatch thread? Seems like you need some locking, no? Maybe you
> should have Anders take a peek at this.

It is one operation thread fulfilling the promise one file at a time, there should be no issue here. I'll CC Anders to take a look if you don't feel comfortable with this.
Comment 12 Tim Horton 2016-12-09 13:34:49 PST
Comment on attachment 296307 [details]
Patch2

View in context: https://bugs.webkit.org/attachment.cgi?id=296307&action=review

> Source/WebKit/mac/WebView/WebView.mm:6525
> +        [draggingInfo enumerateDraggingItemsWithOptions:0 forView:self classes:@[[NSFilePromiseReceiver class]] searchOptions:@{ } usingBlock:^(NSDraggingItem * __nonnull draggingItem, NSInteger idx, BOOL * __nonnull stop) {

Sam wants lambdas to make lifetimes easier.

> Source/WebKit/mac/WebView/WebView.mm:6534
> +                fileNames.append(fileURL.path);

Move this into the main thread block below.
Comment 13 Enrica Casucci 2016-12-14 17:05:00 PST
Created attachment 297146 [details]
Patch3

Uses lambdas and addresses non-thread safe use of vector.
Comment 14 Build Bot 2016-12-14 18:18:33 PST
Comment on attachment 297146 [details]
Patch3

Attachment 297146 [details] did not pass mac-debug-ews (mac):
Output: http://webkit-queues.webkit.org/results/2724669

New failing tests:
imported/w3c/web-platform-tests/IndexedDB/interfaces.worker.html
Comment 15 Build Bot 2016-12-14 18:18:37 PST
Created attachment 297153 [details]
Archive of layout-test-results from ews115 for mac-yosemite

The attached test failures were seen while running run-webkit-tests on the mac-debug-ews.
Bot: ews115  Port: mac-yosemite  Platform: Mac OS X 10.10.5
Comment 16 Tim Horton 2016-12-15 15:55:29 PST
Comment on attachment 297146 [details]
Patch3

View in context: https://bugs.webkit.org/attachment.cgi?id=297146&action=review

> Source/WebCore/platform/mac/DragDataMac.mm:149
> +    platformStrategies()->pasteboardStrategy()->getPathnamesForType(files, String(NSFilesPromisePboardType), m_pasteboardName);

How are you getting away without the macOS version #ifdef here but not in the WK2 code?

> Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3661
> +        NSArray *files = [draggingInfo.draggingPasteboard propertyListForType:NSFilenamesPboardType];

You shouldn't just cast/assume like this; check the type!

> Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3670
> +        size_t fileCount = ((NSArray *)[draggingInfo.draggingPasteboard propertyListForType:NSFilesPromisePboardType]).count;

You shouldn't just cast/assume like this; check the type!

> Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3680
> +                    NSLog(@"There was an error with file:%@, skipping %@", fileURL, errorOrNil);

Probably should have a space after the colon

> Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3683
> +                String path(fileURL.path);

Is there a reason to do this on this thread? Might as well just capture fileURL and do it there, instead, no?

> Source/WebKit/mac/WebView/WebView.mm:6523
> +        size_t fileCount = ((NSArray *)[draggingInfo.draggingPasteboard propertyListForType:NSFilesPromisePboardType]).count;

You shouldn't just cast like this; check the type!
Comment 17 Tim Horton 2016-12-15 15:57:28 PST
Comment on attachment 297146 [details]
Patch3

View in context: https://bugs.webkit.org/attachment.cgi?id=297146&action=review

> Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3672
> +        NSURL *dropLocation = [NSURL fileURLWithPath:@"/tmp" isDirectory:YES];

I don't think you're allowed to assume that /tmp is the right temporary directory, and should use NSTemporaryDirectory or something
Comment 18 Enrica Casucci 2017-01-03 14:01:21 PST
Created attachment 297949 [details]
Patch4

Addressing latest comments.
Comment 19 Tim Horton 2017-01-03 17:58:56 PST
Comment on attachment 297949 [details]
Patch4

You talked to Anders, about this, I know -- is there a reason you're using new/delete instead of unique_ptr or some such?
Comment 20 Enrica Casucci 2017-01-04 14:31:45 PST
Committed revision 210287
Comment 21 Darin Adler 2017-01-04 15:32:31 PST
Comment on attachment 297949 [details]
Patch4

View in context: https://bugs.webkit.org/attachment.cgi?id=297949&action=review

Some ideas for refinement.

> Source/WebCore/platform/DragData.h:108
> +    void setFileNames(Vector<String>& fileNames) { m_fileNames = WTFMove(fileNames); }

This argument should be a rvalue reference, &&, not an lvalue reference, &.

> Source/WebKit2/Shared/WebCoreArgumentCoders.cpp:1260
> +    dragData.setFileNames(fileNames);

This will need a WTFMove.

> Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3642
> +    WebCore::DragData *dragData = new WebCore::DragData(draggingInfo, client, global, static_cast<WebCore::DragOperation>(draggingInfo.draggingSourceOperationMask), applicationFlagsForDrag(m_view, draggingInfo));

The * should be next to the type, DragData*. Or better, just use auto*.

But also, this should probably use unique_ptr instead of hand-written delete calls. It’s too easy to have a storage leak otherwise. And we can use WTFMove to transfer ownership into the lambda. In fact, we can probably do that for a DragData too if we make sure we have a move constructor for it, eliminating the need to allocate on the heap at all.

> Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3658
> +        Vector<String> fileNames;
> +
> +        for (NSString *file in files)
> +            fileNames.append(file);

Would be better to use reserveInitialCapacity and uncheckedAppend here.

> Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3669
> +        Vector<String> *fileNames = new Vector<String>;

Spae is in the wrong place, Vector<String>*, or better, auto*.

> Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3672
> +        [draggingInfo enumerateDraggingItemsWithOptions:0 forView:m_view classes:@[[NSFilePromiseReceiver class]] searchOptions:@{ } usingBlock:^(NSDraggingItem * __nonnull draggingItem, NSInteger idx, BOOL * __nonnull stop) {

The "idx" and "stop" seem unused. Can we leave out the argument names?

Should we use a lambda instead of a block so that capturing is explicit?

> Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3674
> +            NSFilePromiseReceiver *item = draggingItem.item;
> +            NSDictionary *options = @{ };

Seems like we don’t need these local variables.

> Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3676
> +            [item receivePromisedFilesAtDestination:dropLocation options:options operationQueue:[NSOperationQueue new] reader:^(NSURL * _Nonnull fileURL, NSError * _Nullable errorOrNil) {

Strange that above we use __nonnull and here we use _Nonnull; inconsistent.

> Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm:3682
> +                    fileNames->append(path.get());
> +                    if (fileNames->size() == fileCount) {

This seems really fragile. I don’t see a solid guarantee that enumerateDraggingItems will return a number of items that exactly matches files.count and if an error occurs, we will be off.

If we get too few file names we leak dragData and fileNames. If we get too many file names, we dereference a deleted fileNames pointer. Is there some better way to write this that is less fragile?
Comment 22 Ryan Haddad 2017-01-04 16:33:59 PST
Reverted r210287 for reason:

This change caused editing test failures on macOS.

Committed r210300: <http://trac.webkit.org/changeset/210300>
Comment 23 Enrica Casucci 2017-01-05 10:30:22 PST
Committed revision 210360 with fix for failing tests.