blob: 481bbae0c7ae5425274caa8a3a1f6f4a01444dcf [file] [log] [blame]
/*
* Copyright (C) 2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#if PLATFORM(MAC)
#import "PlatformUtilities.h"
#import "TestWKWebView.h"
#import <AppKit/NSDragging.h>
#import <WebKit/WebView.h>
#import <wtf/BlockPtr.h>
#import <wtf/RetainPtr.h>
@interface FrameLoadCompletionListener : NSObject<WebFrameLoadDelegate> {
BlockPtr<void (void)> _completionBlock;
}
+ (instancetype)listenerWithCompletionBlock:(dispatch_block_t)completionBlock;
@end
@implementation FrameLoadCompletionListener
+ (instancetype)listenerWithCompletionBlock:(dispatch_block_t)completionBlock
{
return [[[FrameLoadCompletionListener alloc] initWithCompletionBlock:completionBlock] autorelease];
}
- (instancetype)initWithCompletionBlock:(dispatch_block_t)completionBlock
{
if (self = [super init])
_completionBlock = completionBlock;
return self;
}
- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
{
if (_completionBlock)
_completionBlock();
}
@end
@interface DragSource : NSObject
- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)flag;
@end
@implementation DragSource
- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)flag
{
return NSDragOperationCopy;
}
@end
@interface DragInfo : NSObject<NSDraggingInfo> {
NSPoint _lastMousePosition;
RetainPtr<NSImage> _image;
RetainPtr<NSPasteboard> _pasteboard;
RetainPtr<DragSource> _source;
RetainPtr<NSWindow> _window;
NSSize _offset;
NSInteger _numberOfValidItemsForDrop;
}
@property (nonatomic) NSPoint lastMousePosition;
@end
@implementation DragInfo
- (id)initWithImage:(NSImage *)image offset:(NSSize)offset pasteboard:(NSPasteboard *)pasteboard source:(DragSource *)source destinationWindow:(NSWindow *)destinationWindow
{
if (self = [super init]) {
_image = image;
_pasteboard = pasteboard;
_source = source;
_window = destinationWindow;
_offset = offset;
}
return self;
}
- (NSPoint)lastMousePosition
{
return _lastMousePosition;
}
- (void)setLastMousePosition:(NSPoint)lastMousePosition
{
_lastMousePosition = lastMousePosition;
}
- (NSWindow *)draggingDestinationWindow
{
return _window.get();
}
- (NSDragOperation)draggingSourceOperationMask
{
return NSDragOperationCopy;
}
- (NSPoint)draggingLocation
{
return _lastMousePosition;
}
- (NSPoint)draggedImageLocation
{
return NSMakePoint(_lastMousePosition.x + _offset.width, _lastMousePosition.y + _offset.height);
}
- (NSImage *)draggedImage
{
return _image.get();
}
- (NSPasteboard *)draggingPasteboard
{
return _pasteboard.get();
}
- (id)draggingSource
{
return _source.get();
}
- (NSInteger)draggingSequenceNumber
{
return 0;
}
- (void)slideDraggedImageTo:(NSPoint)screenPoint
{
}
- (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination
{
return nil;
}
- (NSDraggingFormation)draggingFormation
{
return NSDraggingFormationDefault;
}
- (void)setDraggingFormation:(NSDraggingFormation)formation
{
}
- (BOOL)animatesToDestination
{
return NO;
}
- (void)setAnimatesToDestination:(BOOL)flag
{
}
- (NSInteger)numberOfValidItemsForDrop
{
return _numberOfValidItemsForDrop;
}
- (void)setNumberOfValidItemsForDrop:(NSInteger)number
{
_numberOfValidItemsForDrop = number;
}
- (void)enumerateDraggingItemsWithOptions:(NSEnumerationOptions)enumOpts forView:(NSView *)view classes:(NSArray *)classArray searchOptions:(NSDictionary *)searchOptions usingBlock:(void (^)(NSDraggingItem *draggingItem, NSInteger idx, BOOL *stop))block
{
}
- (NSSpringLoadingHighlight)springLoadingHighlight
{
return NSSpringLoadingHighlightNone;
}
- (void)resetSpringLoading
{
}
@end
namespace TestWebKitAPI {
static NSImage *getTestImage()
{
return [[[NSImage alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"icon" withExtension:@"png" subdirectory:@"TestWebKitAPI.resources"]] autorelease];
}
static WebView *webViewAfterPerformingDragOperation(NSPasteboard *pasteboard)
{
RetainPtr<WebView> destination = adoptNS([[WebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]);
RetainPtr<NSWindow> hostWindow = adoptNS([[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 400, 400) styleMask:0 backing:NSBackingStoreBuffered defer:NO]);
[hostWindow setFrameOrigin:NSMakePoint(0, 0)];
[[hostWindow contentView] addSubview:destination.get()];
__block bool isDone = false;
[destination setFrameLoadDelegate:[FrameLoadCompletionListener listenerWithCompletionBlock:^() {
RetainPtr<DragSource> source = adoptNS([[DragSource alloc] init]);
RetainPtr<DragInfo> info = adoptNS([[DragInfo alloc] initWithImage:getTestImage() offset:NSMakeSize(0, 0) pasteboard:pasteboard source:source.get() destinationWindow:hostWindow.get()]);
[info setLastMousePosition:NSMakePoint(0, 200)];
[destination draggingEntered:info.get()];
[info setLastMousePosition:NSMakePoint(200, 200)];
[destination draggingUpdated:info.get()];
EXPECT_TRUE([destination performDragOperation:info.get()]);
isDone = true;
}]];
[[destination mainFrame] loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"full-page-contenteditable" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]]];
TestWebKitAPI::Util::run(&isDone);
return destination.get();
}
TEST(DragAndDropPasteboardTests, DropUTF8PlainText)
{
NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName];
[pasteboard setData:[@"I am a WebKit." dataUsingEncoding:NSUTF8StringEncoding] forType:(__bridge NSString *)kUTTypeUTF8PlainText];
RetainPtr<WebView> resultingWebView = webViewAfterPerformingDragOperation(pasteboard);
EXPECT_TRUE([[resultingWebView stringByEvaluatingJavaScriptFromString:@"document.body.textContent"] containsString:@"I am a WebKit."]);
}
TEST(DragAndDropPasteboardTests, DropJPEG)
{
NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName];
NSImage *icon = getTestImage();
NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:icon.TIFFRepresentation];
[pasteboard setData:[imageRep representationUsingType:NSJPEGFileType properties:@{ NSImageCompressionFactor: @(0.9) }] forType:(__bridge NSString *)kUTTypeJPEG];
RetainPtr<WebView> resultingWebView = webViewAfterPerformingDragOperation(pasteboard);
EXPECT_TRUE([[resultingWebView stringByEvaluatingJavaScriptFromString:@"document.querySelector('img').tagName === 'IMG'"] isEqualToString:@"true"]);
}
#if WK_API_ENABLED
TEST(DragAndDropPasteboardTests, NumberOfValidItemsForDrop)
{
NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName];
[pasteboard declareTypes:@[NSFilenamesPboardType] owner:nil];
[pasteboard setPropertyList:@[@"file-name"] forType:NSFilenamesPboardType];
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]);
auto hostWindow = adoptNS([[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 400, 400) styleMask:0 backing:NSBackingStoreBuffered defer:NO]);
[hostWindow setFrameOrigin:NSMakePoint(0, 0)];
[[hostWindow contentView] addSubview:webView.get()];
[webView synchronouslyLoadTestPageNamed:@"full-page-dropzone"];
auto dragSource = adoptNS([[DragSource alloc] init]);
auto dragInfo = adoptNS([[DragInfo alloc] initWithImage:getTestImage() offset:NSMakeSize(0, 0) pasteboard:pasteboard source:dragSource.get() destinationWindow:hostWindow.get()]);
[dragInfo setLastMousePosition:NSMakePoint(0, 200)];
[webView draggingEntered:dragInfo.get()];
EXPECT_WK_STREQ(@"1", [webView stringByEvaluatingJavaScript:@"window.dragEnteredForTesting"]);
[dragInfo setLastMousePosition:NSMakePoint(200, 200)];
[webView draggingUpdated:dragInfo.get()];
EXPECT_EQ(1U, [dragInfo numberOfValidItemsForDrop]);
}
#endif // WK_API_ENABLED
} // namespace TestWebKitAPI
#endif