Skip to content
Permalink
Browse files
Support File Promise during drag for macOS.
https://bugs.webkit.org/show_bug.cgi?id=165204
rdar://problem/19595567

Reviewed by Tim Horton.

Source/WebCore:

Adds the support for handling File Promise type during
drag. DragData now has the knowledge of the NSFilesPromisePboardType and
checks for the data type during drag.

* page/mac/DragControllerMac.mm:
(WebCore::DragController::dragOperation):
* platform/DragData.h:
(WebCore::DragData::setFileNames):
(WebCore::DragData::fileNames):
* platform/mac/DragDataMac.mm:
(WebCore::DragData::containsFiles):
(WebCore::DragData::numberOfFiles):
(WebCore::DragData::asFilenames):
(WebCore::DragData::containsCompatibleContent):
(WebCore::DragData::containsPromise):
(WebCore::DragData::asURL):

Source/WebKit/mac:

Adds support for dropping a File Promise in a WebView.
The implementation uses new File Promise API available in Sierra.

* Misc/WebNSPasteboardExtras.mm:
(+[NSPasteboard _web_dragTypesForURL]):
* WebView/WebView.mm:
(-[WebView performDragOperation:]):

Source/WebKit2:

Adds support for dropping a File Promise in a WKWebView.
The implementation uses new File Promise API available in Sierra.

* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<DragData>::encode):
(IPC::ArgumentCoder<DragData>::decode):
* Shared/mac/PasteboardTypes.mm:
(WebKit::PasteboardTypes::forURL):
* UIProcess/Cocoa/WebViewImpl.h:
* UIProcess/Cocoa/WebViewImpl.mm:
(WebKit::WebViewImpl::createSandboxExtensionsIfNeeded):
(WebKit::WebViewImpl::performDragOperation):
(WebKit::maybeCreateSandboxExtensionFromPasteboard): Deleted.
(WebKit::createSandboxExtensionsForFileUpload): Deleted.



Canonical link: https://commits.webkit.org/183835@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210287 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Enrica Casucci committed Jan 4, 2017
1 parent d5644d1 commit aa6aa31122cab49f5daa6887e4e3409a35bb7708
@@ -1,3 +1,28 @@
2017-01-04 Enrica Casucci <enrica@apple.com>

Support File Promise during drag for macOS.
https://bugs.webkit.org/show_bug.cgi?id=165204
rdar://problem/19595567

Reviewed by Tim Horton.

Adds the support for handling File Promise type during
drag. DragData now has the knowledge of the NSFilesPromisePboardType and
checks for the data type during drag.

* page/mac/DragControllerMac.mm:
(WebCore::DragController::dragOperation):
* platform/DragData.h:
(WebCore::DragData::setFileNames):
(WebCore::DragData::fileNames):
* platform/mac/DragDataMac.mm:
(WebCore::DragData::containsFiles):
(WebCore::DragData::numberOfFiles):
(WebCore::DragData::asFilenames):
(WebCore::DragData::containsCompatibleContent):
(WebCore::DragData::containsPromise):
(WebCore::DragData::asURL):

2017-01-04 Chris Dumez <cdumez@apple.com>

Assertion hit on redfin.com: ASSERTION FAILED: collection->length() > 1
@@ -61,7 +61,7 @@

DragOperation DragController::dragOperation(const DragData& dragData)
{
if ((dragData.flags() & DragApplicationIsModal) || !dragData.containsURL())
if ((dragData.flags() & DragApplicationIsModal) || !(dragData.containsURL() || dragData.containsPromise()))
return DragOperationNone;

if (!m_documentUnderMouse || (!(dragData.flags() & (DragApplicationHasAttachedSheet | DragApplicationIsSource))))
@@ -105,8 +105,11 @@ class DragData {
bool containsColor() const;
bool containsFiles() const;
unsigned numberOfFiles() const;
void setFileNames(Vector<String>& fileNames) { m_fileNames = WTFMove(fileNames); }
const Vector<String>& fileNames() const { return m_fileNames; }
#if PLATFORM(MAC)
const String& pasteboardName() const { return m_pasteboardName; }
bool containsPromise() const;
#endif

#if PLATFORM(GTK)
@@ -128,6 +131,7 @@ class DragData {
DragDataRef m_platformDragData;
DragOperation m_draggingSourceOperationMask;
DragApplicationFlags m_applicationFlags;
Vector<String> m_fileNames;
#if PLATFORM(MAC)
String m_pasteboardName;
#endif
@@ -73,19 +73,23 @@
{
Vector<String> types;
platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName);
return types.contains(String(NSFilenamesPboardType));
return types.contains(String(NSFilenamesPboardType)) || types.contains(String(NSFilesPromisePboardType));
}

unsigned DragData::numberOfFiles() const
{
Vector<String> files;
platformStrategies()->pasteboardStrategy()->getPathnamesForType(files, String(NSFilenamesPboardType), m_pasteboardName);
if (!files.size())
platformStrategies()->pasteboardStrategy()->getPathnamesForType(files, String(NSFilesPromisePboardType), m_pasteboardName);
return files.size();
}

void DragData::asFilenames(Vector<String>& result) const
{
platformStrategies()->pasteboardStrategy()->getPathnamesForType(result, String(NSFilenamesPboardType), m_pasteboardName);
if (!result.size())
result = fileNames();
}

bool DragData::containsPlainText() const
@@ -128,6 +132,7 @@
return types.contains(String(WebArchivePboardType))
|| types.contains(String(NSHTMLPboardType))
|| types.contains(String(NSFilenamesPboardType))
|| types.contains(String(NSFilesPromisePboardType))
|| types.contains(String(NSTIFFPboardType))
|| types.contains(String(NSPDFPboardType))
|| types.contains(String(NSURLPboardType))
@@ -137,7 +142,14 @@
|| types.contains(String(NSColorPboardType))
|| types.contains(String(kUTTypePNG));
}


bool DragData::containsPromise() const
{
Vector<String> files;
platformStrategies()->pasteboardStrategy()->getPathnamesForType(files, String(NSFilesPromisePboardType), m_pasteboardName);
return files.size() == 1;
}

bool DragData::containsURL(FilenameConversionPolicy filenamePolicy) const
{
return !asURL(filenamePolicy).isEmpty();
@@ -184,7 +196,10 @@
return [URLByCanonicalizingURL([NSURL fileURLWithPath:files[0]]) absoluteString];
}
}


if (types.contains(String(NSFilesPromisePboardType)) && fileNames().size() == 1)
return [URLByCanonicalizingURL([NSURL fileURLWithPath:fileNames()[0]]) absoluteString];

return String();
}

@@ -1,3 +1,19 @@
2017-01-04 Enrica Casucci <enrica@apple.com>

Support File Promise during drag for macOS.
https://bugs.webkit.org/show_bug.cgi?id=165204
rdar://problem/19595567

Reviewed by Tim Horton.

Adds support for dropping a File Promise in a WebView.
The implementation uses new File Promise API available in Sierra.

* Misc/WebNSPasteboardExtras.mm:
(+[NSPasteboard _web_dragTypesForURL]):
* WebView/WebView.mm:
(-[WebView performDragOperation:]):

2017-01-04 Tim Horton <timothy_horton@apple.com>

Provide a setting for clients to always prefer low-power WebGL
@@ -113,6 +113,9 @@ + (NSArray *)_web_dragTypesForURL
WebURLNamePboardType,
NSStringPboardType,
NSFilenamesPboardType,
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
NSFilesPromisePboardType,
#endif
nil];
}

@@ -6517,8 +6517,45 @@ - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
{
IntPoint client([draggingInfo draggingLocation]);
IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]);
return core(self)->dragController().performDragOperation(dragData);
DragData *dragData = new DragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]);

#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
if ([draggingInfo.draggingPasteboard.types containsObject:NSFilesPromisePboardType]) {
NSArray *files = [draggingInfo.draggingPasteboard propertyListForType:NSFilesPromisePboardType];
if (![files isKindOfClass:[NSArray class]]) {
delete dragData;
return false;
}
size_t fileCount = files.count;
Vector<String> *fileNames = new Vector<String>;
NSURL *dropLocation = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
[draggingInfo enumerateDraggingItemsWithOptions:0 forView:self classes:@[[NSFilePromiseReceiver class]] searchOptions:@{ } usingBlock:^(NSDraggingItem * __nonnull draggingItem, NSInteger idx, BOOL * __nonnull stop) {
NSFilePromiseReceiver *item = draggingItem.item;
NSDictionary *options = @{ };

[item receivePromisedFilesAtDestination:dropLocation options:options operationQueue:[NSOperationQueue new] reader:^(NSURL * _Nonnull fileURL, NSError * _Nullable errorOrNil) {
if (errorOrNil)
return;

dispatch_async(dispatch_get_main_queue(), [self, path = RetainPtr<NSString>(fileURL.path), fileNames, fileCount, dragData] {
fileNames->append(path.get());
if (fileNames->size() == fileCount) {
dragData->setFileNames(*fileNames);
core(self)->dragController().performDragOperation(*dragData);
delete dragData;
delete fileNames;
}
});
}];
}];

return true;
}
#endif
bool returnValue = core(self)->dragController().performDragOperation(*dragData);
delete dragData;

return returnValue;
}

- (NSView *)_hitTest:(NSPoint *)point dragTypes:(NSSet *)types
@@ -1,3 +1,26 @@
2017-01-04 Enrica Casucci <enrica@apple.com>

Support File Promise during drag for macOS.
https://bugs.webkit.org/show_bug.cgi?id=165204
rdar://problem/19595567

Reviewed by Tim Horton.

Adds support for dropping a File Promise in a WKWebView.
The implementation uses new File Promise API available in Sierra.

* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<DragData>::encode):
(IPC::ArgumentCoder<DragData>::decode):
* Shared/mac/PasteboardTypes.mm:
(WebKit::PasteboardTypes::forURL):
* UIProcess/Cocoa/WebViewImpl.h:
* UIProcess/Cocoa/WebViewImpl.mm:
(WebKit::WebViewImpl::createSandboxExtensionsIfNeeded):
(WebKit::WebViewImpl::performDragOperation):
(WebKit::maybeCreateSandboxExtensionFromPasteboard): Deleted.
(WebKit::createSandboxExtensionsForFileUpload): Deleted.

2017-01-04 Jeremy Jones <jeremyj@apple.com>

Release pointer lock when page state is reset for any reason, not just for process exited.
@@ -1225,6 +1225,7 @@ void ArgumentCoder<DragData>::encode(Encoder& encoder, const DragData& dragData)
encoder.encodeEnum(dragData.flags());
#if PLATFORM(MAC)
encoder << dragData.pasteboardName();
encoder << dragData.fileNames();
#endif
}

@@ -1251,8 +1252,12 @@ bool ArgumentCoder<DragData>::decode(Decoder& decoder, DragData& dragData)
if (!decoder.decode(pasteboardName))
return false;
#endif
Vector<String> fileNames;
if (!decoder.decode(fileNames))
return false;

dragData = DragData(pasteboardName, clientPosition, globalPosition, draggingSourceOperationMask, applicationFlags);
dragData.setFileNames(fileNames);

return true;
}
@@ -53,7 +53,11 @@

NSArray* PasteboardTypes::forURL()
{
static NSArray *types = retain([NSArray arrayWithObjects:WebURLsWithTitlesPboardType, NSURLPboardType, WebURLPboardType, WebURLNamePboardType, NSStringPboardType, NSFilenamesPboardType, nil]);
static NSArray *types = retain([NSArray arrayWithObjects:WebURLsWithTitlesPboardType, NSURLPboardType, WebURLPboardType, WebURLNamePboardType, NSStringPboardType, NSFilenamesPboardType,
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
NSFilesPromisePboardType,
#endif
nil]);
return types;
}

@@ -582,6 +582,7 @@ class WebViewImpl {

bool mightBeginDragWhileInactive();
bool mightBeginScrollWhileInactive();
void createSandboxExtensionsIfNeeded(const Vector<String>& files, SandboxExtension::Handle&, SandboxExtension::HandleArray& handles);

#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
void handleRequestedCandidates(NSInteger sequenceNumber, NSArray<NSTextCheckingResult *> *candidates);
@@ -3616,43 +3616,24 @@ static String commandNameForSelector(SEL selector)
return true;
}

// FIXME: This code is more or less copied from Pasteboard::getBestURL.
// It would be nice to be able to share the code somehow.
static bool maybeCreateSandboxExtensionFromPasteboard(NSPasteboard *pasteboard, SandboxExtension::Handle& sandboxExtensionHandle)
void WebViewImpl::createSandboxExtensionsIfNeeded(const Vector<String>& files, SandboxExtension::Handle& handle, SandboxExtension::HandleArray& handles)
{
NSArray *types = pasteboard.types;
if (![types containsObject:NSFilenamesPboardType])
return false;

NSArray *files = [pasteboard propertyListForType:NSFilenamesPboardType];
if (files.count != 1)
return false;

NSString *file = [files objectAtIndex:0];
BOOL isDirectory;
if (![[NSFileManager defaultManager] fileExistsAtPath:file isDirectory:&isDirectory])
return false;

if (isDirectory)
return false;

SandboxExtension::createHandle("/", SandboxExtension::ReadOnly, sandboxExtensionHandle);
return true;
}

static void createSandboxExtensionsForFileUpload(NSPasteboard *pasteboard, SandboxExtension::HandleArray& handles)
{
NSArray *types = pasteboard.types;
if (![types containsObject:NSFilenamesPboardType])
if (!files.size())
return;

NSArray *files = [pasteboard propertyListForType:NSFilenamesPboardType];
handles.allocate(files.count);
for (unsigned i = 0; i < files.count; i++) {
NSString *file = [files objectAtIndex:i];
if (files.size() == 1) {
BOOL isDirectory;
if ([[NSFileManager defaultManager] fileExistsAtPath:files[0] isDirectory:&isDirectory] && !isDirectory) {
SandboxExtension::createHandle("/", SandboxExtension::ReadOnly, handle);
m_page->process().willAcquireUniversalFileReadSandboxExtension();
}
}

handles.allocate(files.size());
for (size_t i = 0; i< files.size(); i++) {
NSString *file = files[i];
if (![[NSFileManager defaultManager] fileExistsAtPath:file])
continue;
SandboxExtension::Handle handle;
SandboxExtension::createHandle(file, SandboxExtension::ReadOnly, handles[i]);
}
}
@@ -3661,17 +3642,66 @@ static void createSandboxExtensionsForFileUpload(NSPasteboard *pasteboard, Sandb
{
WebCore::IntPoint client([m_view convertPoint:draggingInfo.draggingLocation fromView:nil]);
WebCore::IntPoint global(WebCore::globalPoint(draggingInfo.draggingLocation, m_view.window));
WebCore::DragData dragData(draggingInfo, client, global, static_cast<WebCore::DragOperation>(draggingInfo.draggingSourceOperationMask), applicationFlagsForDrag(m_view, draggingInfo));
WebCore::DragData *dragData = new WebCore::DragData(draggingInfo, client, global, static_cast<WebCore::DragOperation>(draggingInfo.draggingSourceOperationMask), applicationFlagsForDrag(m_view, draggingInfo));

NSArray *types = draggingInfo.draggingPasteboard.types;
SandboxExtension::Handle sandboxExtensionHandle;
bool createdExtension = maybeCreateSandboxExtensionFromPasteboard(draggingInfo.draggingPasteboard, sandboxExtensionHandle);
if (createdExtension)
m_page->process().willAcquireUniversalFileReadSandboxExtension();

SandboxExtension::HandleArray sandboxExtensionForUpload;
createSandboxExtensionsForFileUpload(draggingInfo.draggingPasteboard, sandboxExtensionForUpload);

m_page->performDragOperation(dragData, draggingInfo.draggingPasteboard.name, sandboxExtensionHandle, sandboxExtensionForUpload);
if ([types containsObject:NSFilenamesPboardType]) {
NSArray *files = [draggingInfo.draggingPasteboard propertyListForType:NSFilenamesPboardType];
if (![files isKindOfClass:[NSArray class]]) {
delete dragData;
return false;
}

Vector<String> fileNames;

for (NSString *file in files)
fileNames.append(file);
createSandboxExtensionsIfNeeded(fileNames, sandboxExtensionHandle, sandboxExtensionForUpload);
}
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
else if ([types containsObject:NSFilesPromisePboardType]) {
NSArray *files = [draggingInfo.draggingPasteboard propertyListForType:NSFilesPromisePboardType];
if (![files isKindOfClass:[NSArray class]]) {
delete dragData;
return false;
}
size_t fileCount = files.count;
Vector<String> *fileNames = new Vector<String>;
NSURL *dropLocation = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
String pasteboardName = draggingInfo.draggingPasteboard.name;
[draggingInfo enumerateDraggingItemsWithOptions:0 forView:m_view classes:@[[NSFilePromiseReceiver class]] searchOptions:@{ } usingBlock:^(NSDraggingItem * __nonnull draggingItem, NSInteger idx, BOOL * __nonnull stop) {
NSFilePromiseReceiver *item = draggingItem.item;
NSDictionary *options = @{ };

[item receivePromisedFilesAtDestination:dropLocation options:options operationQueue:[NSOperationQueue new] reader:^(NSURL * _Nonnull fileURL, NSError * _Nullable errorOrNil) {
if (errorOrNil)
return;

dispatch_async(dispatch_get_main_queue(), [this, path = RetainPtr<NSString>(fileURL.path), fileNames, fileCount, dragData, pasteboardName] {
fileNames->append(path.get());
if (fileNames->size() == fileCount) {
SandboxExtension::Handle sandboxExtensionHandle;
SandboxExtension::HandleArray sandboxExtensionForUpload;

createSandboxExtensionsIfNeeded(*fileNames, sandboxExtensionHandle, sandboxExtensionForUpload);
dragData->setFileNames(*fileNames);
m_page->performDragOperation(*dragData, pasteboardName, sandboxExtensionHandle, sandboxExtensionForUpload);
delete dragData;
delete fileNames;
}
});
}];
}];

return true;
}
#endif

m_page->performDragOperation(*dragData, draggingInfo.draggingPasteboard.name, sandboxExtensionHandle, sandboxExtensionForUpload);
delete dragData;

return true;
}

0 comments on commit aa6aa31

Please sign in to comment.