Changeset 221751 in webkit
- Timestamp:
- Sep 7, 2017 1:12:18 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r221743 r221751 1 2017-09-07 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [Directory Upload] Extend drag and drop support to iOS 4 https://bugs.webkit.org/show_bug.cgi?id=176492 5 <rdar://problem/34291584> 6 7 Reviewed by Tim Horton. 8 9 Adds support for accepting dropped folders on iOS. 10 11 Tests: DataInteractionTests.ExternalSourceDataTransferItemGetFolderAsEntry 12 DataInteractionTests.ExternalSourceDataTransferItemGetPlainTextFileAsEntry 13 14 * platform/ios/PasteboardIOS.mm: 15 (WebCore::Pasteboard::supportedFileUploadPasteboardTypes): 16 17 Add "public.folder" as a compatible pasteboard type for drops on iOS. This means file inputs and custom drop 18 targets that preventDefault() will, by default, be able to accept incoming folders. 19 20 * platform/ios/WebItemProviderPasteboard.mm: 21 (linkTemporaryItemProviderFilesToDropStagingDirectory): 22 23 Tweak temporaryFileURLForDataInteractionContent to also hard link UIKit's temporary files instead, and return 24 a non-null destination URL only if the necessary file operations succeeded. Also renames this helper to 25 linkTemporaryItemProviderFilesToDropStagingDirectory to better reflect its new purpose. This makes logic much 26 cleaner at the call site, which no longer checks against various conditions before proceeding to set the data 27 transfer URL. 28 29 (-[WebItemProviderPasteboard doAfterLoadingProvidedContentIntoFileURLs:synchronousTimeout:]): 30 (temporaryFileURLForDataInteractionContent): Deleted. 31 1 32 2017-09-07 Alex Christensen <achristensen@webkit.org> 2 33 -
trunk/Source/WebCore/platform/ios/PasteboardIOS.mm
r221063 r221751 307 307 NSArray *Pasteboard::supportedFileUploadPasteboardTypes() 308 308 { 309 return @[ (NSString *)kUTTypeContent, (NSString *)kUTTypeZipArchive ];309 return @[ (NSString *)kUTTypeContent, (NSString *)kUTTypeZipArchive, (NSString *)kUTTypeFolder ]; 310 310 } 311 311 -
trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm
r221617 r221751 414 414 } 415 415 416 static NSURL *temporaryFileURLForDataInteractionContent(NSURL *url, NSString *suggestedName) 417 { 418 static NSString *defaultDataInteractionFileName = @"file"; 416 static NSURL *linkTemporaryItemProviderFilesToDropStagingDirectory(NSURL *url, NSString *suggestedName, NSString *typeIdentifier) 417 { 418 static NSString *defaultDropFolderName = @"folder"; 419 static NSString *defaultDropFileName = @"file"; 419 420 static NSString *dataInteractionDirectoryPrefix = @"data-interaction"; 420 421 if (!url) … … 425 426 return nil; 426 427 427 suggestedName = suggestedName ?: defaultDataInteractionFileName; 428 if (![suggestedName containsString:@"."]) 428 NSURL *destination = nil; 429 BOOL isFolder = UTTypeConformsTo((CFStringRef)typeIdentifier, kUTTypeFolder); 430 NSFileManager *fileManager = [NSFileManager defaultManager]; 431 432 if (!suggestedName) 433 suggestedName = url.lastPathComponent ?: (isFolder ? defaultDropFolderName : defaultDropFileName); 434 435 if (![suggestedName containsString:@"."] && !isFolder) 429 436 suggestedName = [suggestedName stringByAppendingPathExtension:url.pathExtension]; 430 437 431 return [NSURL fileURLWithPath:[temporaryDataInteractionDirectory stringByAppendingPathComponent:suggestedName ?: url.lastPathComponent]]; 438 destination = [NSURL fileURLWithPath:[temporaryDataInteractionDirectory stringByAppendingPathComponent:suggestedName]]; 439 return [fileManager linkItemAtURL:url toURL:destination error:nil] ? destination : nil; 432 440 } 433 441 … … 485 493 dispatch_group_enter(fileLoadingGroup.get()); 486 494 dispatch_group_enter(synchronousFileLoadingGroup.get()); 487 [itemProvider loadFileRepresentationForTypeIdentifier:typeIdentifier.get() completionHandler:[synchronousFileLoadingGroup, setFileURLsLock, indexInItemProviderArray, suggestedName, typeIdentifier, typeToFileURLMaps, fileLoadingGroup] (NSURL *url, NSError * error) {495 [itemProvider loadFileRepresentationForTypeIdentifier:typeIdentifier.get() completionHandler:[synchronousFileLoadingGroup, setFileURLsLock, indexInItemProviderArray, suggestedName, typeIdentifier, typeToFileURLMaps, fileLoadingGroup] (NSURL *url, NSError *) { 488 496 // After executing this completion block, UIKit removes the file at the given URL. However, we need this data to persist longer for the web content process. 489 497 // To address this, we hard link the given URL to a new temporary file in the temporary directory. This follows the same flow as regular file upload, in 490 498 // WKFileUploadPanel.mm. The temporary files are cleaned up by the system at a later time. 491 RetainPtr<NSURL> destinationURL = temporaryFileURLForDataInteractionContent(url, suggestedName.get()); 492 if (destinationURL && !error && [[NSFileManager defaultManager] linkItemAtURL:url toURL:destinationURL.get() error:nil]) { 499 if (NSURL *destination = linkTemporaryItemProviderFilesToDropStagingDirectory(url, suggestedName.get(), typeIdentifier.get())) { 493 500 [setFileURLsLock lock]; 494 [typeToFileURLMaps setObject:[NSDictionary dictionaryWithObject:destination URL.get()forKey:typeIdentifier.get()] atIndexedSubscript:indexInItemProviderArray];501 [typeToFileURLMaps setObject:[NSDictionary dictionaryWithObject:destination forKey:typeIdentifier.get()] atIndexedSubscript:indexInItemProviderArray]; 495 502 [setFileURLsLock unlock]; 496 503 } -
trunk/Tools/ChangeLog
r221750 r221751 1 2017-09-07 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [Directory Upload] Extend drag and drop support to iOS 4 https://bugs.webkit.org/show_bug.cgi?id=176492 5 <rdar://problem/34291584> 6 7 Reviewed by Tim Horton. 8 9 Adds two new iOS drag and drop unit tests, which both exercise the DataTransferItem.webKitGetAsEntry codepath 10 upon drop. (...)GetFolderAsEntry creates a new folder in the temporary directory and uses it to generate an item 11 provider. This item provider is then dropped over a custom drop handling element, which writes information about 12 the exposed FileSystemEntries into a textarea. (...)ExternalSourceDataTransferItemGetPlainTextFileAsEntry does 13 something similar, except that it only drops a plain text file instead. 14 15 * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: 16 * TestWebKitAPI/Tests/WebKitCocoa/DataTransferItem-getAsEntry.html: Added. 17 18 Introduce a new test page that dumps information about DataTransferItems' file system entries upon drop. 19 20 * TestWebKitAPI/Tests/ios/DataInteractionTests.mm: 21 (runTestWithTemporaryTextFile): 22 (runTestWithTemporaryFolder): 23 24 Introduce helpers to set up and tear down temporary files and folders over the duration of a test. 25 26 (TestWebKitAPI::setUpTestWebViewForDataTransferItems): 27 (TestWebKitAPI::TEST): 28 1 29 2017-09-07 Filip Pizlo <fpizlo@apple.com> 2 30 -
trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
r221660 r221751 677 677 F44D06471F39627A001A0E29 /* EditorStateTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F44D06461F395C4D001A0E29 /* EditorStateTests.mm */; }; 678 678 F44D064A1F3962F2001A0E29 /* EditingTestHarness.mm in Sources */ = {isa = PBXBuildFile; fileRef = F44D06491F3962E3001A0E29 /* EditingTestHarness.mm */; }; 679 F4512E131F60C44600BB369E /* DataTransferItem-getAsEntry.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4512E121F60C43400BB369E /* DataTransferItem-getAsEntry.html */; }; 679 680 F4538EF71E8473E600B5C953 /* large-red-square.png in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4538EF01E846B4100B5C953 /* large-red-square.png */; }; 680 681 F45B63FB1F197F4A009D38B9 /* image-map.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F45B63FA1F197F33009D38B9 /* image-map.html */; }; … … 816 817 7AEAD4811E20122700416EFE /* CrossPartitionFileSchemeAccess.html in Copy Resources */, 817 818 290F4275172A221C00939FF0 /* custom-protocol-sync-xhr.html in Copy Resources */, 819 F4512E131F60C44600BB369E /* DataTransferItem-getAsEntry.html in Copy Resources */, 818 820 C07E6CB213FD73930038B22B /* devicePixelRatio.html in Copy Resources */, 819 821 0799C34B1EBA3301003B7532 /* disableGetUserMedia.html in Copy Resources */, … … 1707 1709 F44D06481F3962E3001A0E29 /* EditingTestHarness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditingTestHarness.h; sourceTree = "<group>"; }; 1708 1710 F44D06491F3962E3001A0E29 /* EditingTestHarness.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = EditingTestHarness.mm; sourceTree = "<group>"; }; 1711 F4512E121F60C43400BB369E /* DataTransferItem-getAsEntry.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "DataTransferItem-getAsEntry.html"; sourceTree = "<group>"; }; 1709 1712 F4538EF01E846B4100B5C953 /* large-red-square.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "large-red-square.png"; sourceTree = "<group>"; }; 1710 1713 F45B63FA1F197F33009D38B9 /* image-map.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "image-map.html"; sourceTree = "<group>"; }; … … 2153 2156 A16F66B91C40EA2000BD4D24 /* ContentFiltering.html */, 2154 2157 5C2936941D5BFD1900DEAB1E /* CookieMessage.html */, 2158 F4512E121F60C43400BB369E /* DataTransferItem-getAsEntry.html */, 2155 2159 0799C34A1EBA32F4003B7532 /* disableGetUserMedia.html */, 2156 2160 F41AB99E1EF4692C0083FA08 /* div-and-large-image.html */, -
trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm
r221660 r221751 35 35 #import <UIKit/NSItemProvider+UIKitAdditions.h> 36 36 #import <WebKit/WKPreferencesPrivate.h> 37 #import <WebKit/WKPreferencesRefPrivate.h> 37 38 #import <WebKit/WKProcessPoolPrivate.h> 38 39 #import <WebKit/WKWebViewConfigurationPrivate.h> … … 165 166 } 166 167 168 static void runTestWithTemporaryTextFile(void(^runTest)(NSURL *fileURL)) 169 { 170 NSString *fileName = [NSString stringWithFormat:@"drag-drop-text-file-%@.txt", [NSUUID UUID].UUIDString]; 171 RetainPtr<NSURL> temporaryFile = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:fileName] isDirectory:NO]; 172 [[NSFileManager defaultManager] removeItemAtURL:temporaryFile.get() error:nil]; 173 174 NSError *error = nil; 175 [@"This is a tiny blob of text." writeToURL:temporaryFile.get() atomically:YES encoding:NSUTF8StringEncoding error:&error]; 176 177 if (error) 178 NSLog(@"Error writing temporary file: %@", error); 179 180 @try { 181 runTest(temporaryFile.get()); 182 } @finally { 183 [[NSFileManager defaultManager] removeItemAtURL:temporaryFile.get() error:nil]; 184 } 185 } 186 187 static void runTestWithTemporaryFolder(void(^runTest)(NSURL *folderURL)) 188 { 189 NSString *folderName = [NSString stringWithFormat:@"some.directory-%@", [NSUUID UUID].UUIDString]; 190 RetainPtr<NSURL> temporaryFolder = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:folderName] isDirectory:YES]; 191 [[NSFileManager defaultManager] removeItemAtURL:temporaryFolder.get() error:nil]; 192 193 NSError *error = nil; 194 NSFileManager *defaultManager = [NSFileManager defaultManager]; 195 [defaultManager createDirectoryAtURL:temporaryFolder.get() withIntermediateDirectories:NO attributes:nil error:&error]; 196 [UIImagePNGRepresentation(testIconImage()) writeToURL:[temporaryFolder.get() URLByAppendingPathComponent:@"icon.png" isDirectory:NO] atomically:YES]; 197 [testZIPArchive() writeToURL:[temporaryFolder.get() URLByAppendingPathComponent:@"archive.zip" isDirectory:NO] atomically:YES]; 198 199 NSURL *firstSubdirectory = [temporaryFolder.get() URLByAppendingPathComponent:@"subdirectory1" isDirectory:YES]; 200 [defaultManager createDirectoryAtURL:firstSubdirectory withIntermediateDirectories:NO attributes:nil error:&error]; 201 [@"I am a text file in the first subdirectory." writeToURL:[firstSubdirectory URLByAppendingPathComponent:@"text-file-1.txt" isDirectory:NO] atomically:YES encoding:NSUTF8StringEncoding error:&error]; 202 203 NSURL *secondSubdirectory = [temporaryFolder.get() URLByAppendingPathComponent:@"subdirectory2" isDirectory:YES]; 204 [defaultManager createDirectoryAtURL:secondSubdirectory withIntermediateDirectories:NO attributes:nil error:&error]; 205 [@"I am a text file in the second subdirectory." writeToURL:[secondSubdirectory URLByAppendingPathComponent:@"text-file-2.txt" isDirectory:NO] atomically:YES encoding:NSUTF8StringEncoding error:&error]; 206 207 if (error) 208 NSLog(@"Error writing temporary file: %@", error); 209 210 @try { 211 runTest(temporaryFolder.get()); 212 } @finally { 213 [[NSFileManager defaultManager] removeItemAtURL:temporaryFolder.get() error:nil]; 214 } 215 } 216 167 217 namespace TestWebKitAPI { 168 218 … … 876 926 NSString *outputValue = [webView stringByEvaluatingJavaScript:@"output.value"]; 877 927 EXPECT_WK_STREQ("text/html", outputValue.UTF8String); 928 } 929 930 static RetainPtr<TestWKWebView> setUpTestWebViewForDataTransferItems() 931 { 932 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); 933 [webView synchronouslyLoadTestPageNamed:@"DataTransferItem-getAsEntry"]; 934 935 auto preferences = (WKPreferencesRef)[[webView configuration] preferences]; 936 WKPreferencesSetDataTransferItemsEnabled(preferences, true); 937 WKPreferencesSetDirectoryUploadEnabled(preferences, true); 938 939 return webView; 940 } 941 942 TEST(DataInteractionTests, ExternalSourceDataTransferItemGetFolderAsEntry) 943 { 944 NSArray<NSString *> *expectedOutput = @[ 945 @"Found data transfer item (kind: 'string', type: 'text/plain')", 946 @"Found data transfer item (kind: 'file', type: '')", 947 @"DIR: /somedirectory", 948 @"FILE: /somedirectory/icon.png ('image/png', 42130 bytes)", 949 @"DIR: /somedirectory/subdirectory1", 950 @"FILE: /somedirectory/subdirectory1/text-file-1.txt ('text/plain', 43 bytes)", 951 @"FILE: /somedirectory/archive.zip ('application/zip', 988 bytes)", 952 @"DIR: /somedirectory/subdirectory2", 953 @"FILE: /somedirectory/subdirectory2/text-file-2.txt ('text/plain', 44 bytes)", 954 @"" 955 ]; 956 957 auto webView = setUpTestWebViewForDataTransferItems(); 958 __block bool done = false; 959 [webView performAfterReceivingMessage:@"dropped" action:^() { 960 done = true; 961 }]; 962 963 runTestWithTemporaryFolder(^(NSURL *folderURL) { 964 auto itemProvider = adoptNS([[NSItemProvider alloc] init]); 965 [itemProvider setSuggestedName:@"somedirectory"]; 966 [itemProvider registerFileRepresentationForTypeIdentifier:(NSString *)kUTTypeFolder fileOptions:0 visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[capturedFolderURL = retainPtr(folderURL)] (FileLoadCompletionBlock completionHandler) -> NSProgress * { 967 completionHandler(capturedFolderURL.get(), NO, nil); 968 return nil; 969 }]; 970 971 auto dataInteractionSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]); 972 [dataInteractionSimulator setExternalItemProviders:@[ itemProvider.get() ]]; 973 [dataInteractionSimulator runFrom:CGPointMake(50, 50) to:CGPointMake(150, 50)]; 974 }); 975 976 TestWebKitAPI::Util::run(&done); 977 EXPECT_WK_STREQ([expectedOutput componentsJoinedByString:@"\n"], [webView stringByEvaluatingJavaScript:@"output.value"]); 978 } 979 980 TEST(DataInteractionTests, ExternalSourceDataTransferItemGetPlainTextFileAsEntry) 981 { 982 NSArray<NSString *> *expectedOutput = @[ 983 @"Found data transfer item (kind: 'string', type: 'text/plain')", 984 @"Found data transfer item (kind: 'file', type: 'text/plain')", 985 @"FILE: /foo.txt ('text/plain', 28 bytes)", 986 @"" 987 ]; 988 989 auto webView = setUpTestWebViewForDataTransferItems(); 990 __block bool done = false; 991 [webView performAfterReceivingMessage:@"dropped" action:^() { 992 done = true; 993 }]; 994 995 runTestWithTemporaryTextFile(^(NSURL *fileURL) { 996 auto itemProvider = adoptNS([[NSItemProvider alloc] init]); 997 [itemProvider setSuggestedName:@"foo"]; 998 [itemProvider registerFileRepresentationForTypeIdentifier:(NSString *)kUTTypeUTF8PlainText fileOptions:0 visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[capturedFileURL = retainPtr(fileURL)](FileLoadCompletionBlock completionHandler) -> NSProgress * { 999 completionHandler(capturedFileURL.get(), NO, nil); 1000 return nil; 1001 }]; 1002 1003 auto dataInteractionSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]); 1004 [dataInteractionSimulator setExternalItemProviders:@[ itemProvider.get() ]]; 1005 [dataInteractionSimulator runFrom:CGPointMake(50, 50) to:CGPointMake(150, 50)]; 1006 }); 1007 1008 TestWebKitAPI::Util::run(&done); 1009 EXPECT_WK_STREQ([expectedOutput componentsJoinedByString:@"\n"], [webView stringByEvaluatingJavaScript:@"output.value"]); 878 1010 } 879 1011
Note: See TracChangeset
for help on using the changeset viewer.