Changeset 238795 in webkit
- Timestamp:
- Dec 3, 2018 7:42:12 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r238791 r238795 1 2018-12-03 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOSMac] Unable to upload non-image files using drag and drop in WKWebView 4 https://bugs.webkit.org/show_bug.cgi?id=192283 5 <rdar://problem/46399461> 6 7 Reviewed by Ryosuke Niwa. 8 9 Currently on iOS, file URLs aren't generally written to the pasteboard during drag and drop unless the 10 application providing the data explicitly registers "public.file-url" to item providers. As such, our current 11 logic on iOS for handling drops does not attempt to prevent "public.file-url" from being advertised as the 12 "text/uri-list" MIME type in DataTransfer, though we do currently succeed in suppressing access to the file URL. 13 14 However, on iOSMac, the scenario in which file URLs are registered to item providers becomes pertinent when 15 uploading files from other macOS apps (e.g. Finder) into a WKWebView running in iOSMac. Furthermore, the 16 `preferredPresentationStyle` flag on `NSItemProvider` is unavailable in iOSMac; currently, this flag is our 17 primary cue on iOS that an item should be treated as an attachment rather than inline data. In order to support 18 file uploads in iOSMac, we make several adjustments to drop handling logic in iOS to handle the case where the 19 "public.file-url" type is registered. See below for more details. 20 21 Tests: DragAndDropTests.DataTransferExposePlainTextWithFileURLAsFile 22 DragAndDropTests.DataTransferGetDataWhenDroppingImageWithFileURL 23 24 * platform/PasteboardItemInfo.h: 25 (WebCore::PasteboardItemInfo::encode const): 26 (WebCore::PasteboardItemInfo::decode): 27 28 Add a new flag that is set if and only if the item provider contains the "public.file-url" type, and also 29 contains some non-URL data type that conforms to one of the file types supported for file uploads (i.e. 30 "public.content", zip archives, and folders). 31 32 * platform/cocoa/PasteboardCocoa.mm: 33 (WebCore::Pasteboard::fileContentState): 34 35 Consider the pasteboard to contain files in the case where one or more of the items contains a file URL, along 36 with some other pasteboard data that can be represented as a file upload. 37 38 * platform/ios/PlatformPasteboardIOS.mm: 39 (WebCore::PlatformPasteboard::informationForItemAtIndex): 40 (WebCore::PlatformPasteboard::typesSafeForDOMToReadAndWrite const): 41 42 If the pasteboard contains "public.file-url", don't consider "text/uri-list" to be one of the data types that's 43 safe to expose to the page. Our current behavior in this case is that we will advertise "text/uri-list" as a 44 pasteboard type in the DataTransfer, but if the page attempts to request this information, we simply return the 45 empty string. Instead, we shouldn't expose "text/uri-list" as a type in the first place. 46 47 * platform/ios/WebItemProviderPasteboard.h: 48 * platform/ios/WebItemProviderPasteboard.mm: 49 50 Add a few more `__bridge`-ing casts where appropriate. 51 52 (typeConformsToTypes): 53 54 Move this further up the file so that it can be used in `NSItemProvider (WebCoreExtras)`. 55 56 (-[NSItemProvider web_containsFileURLAndFileUploadContent]): 57 58 Add a helper method on NSItemProvider to determine whether an item provider has a file URL, as well as a content 59 type suitable for file uploads. 60 61 (-[WebItemProviderLoadResult canBeRepresentedAsFileUpload]): 62 63 This currently always returns `NO` in iOSMac; instead, return `YES` on both iOS and iOSMac in the case where the 64 item provider contains a file URL and content which may be uploaded. 65 66 (-[WebItemProviderPasteboard preferredFileUploadURLAtIndex:fileType:]): 67 (-[WebItemProviderPasteboard typeIdentifiersToLoad:]): 68 69 Refactor this to take an `NSItemProvider` instead of a list of type identifiers, and bail out of loading data 70 for "public.url" if the item provider contains a file URL. 71 72 (-[WebItemProviderPasteboard doAfterLoadingProvidedContentIntoFileURLs:synchronousTimeout:]): 73 (-[WebItemProviderPasteboard typeIdentifiersToLoadForRegisteredTypeIdentifiers:]): Deleted. 74 1 75 2018-12-02 Zalan Bujtas <zalan@apple.com> 2 76 -
trunk/Source/WebCore/platform/PasteboardItemInfo.h
r237074 r238795 42 42 String suggestedFileName; 43 43 bool isNonTextType { false }; 44 bool containsFileURLAndFileUploadContent { false }; 44 45 PasteboardItemPresentationStyle preferredPresentationStyle { PasteboardItemPresentationStyle::Unspecified }; 45 46 … … 51 52 void PasteboardItemInfo::encode(Encoder& encoder) const 52 53 { 53 encoder << pathForFileUpload << contentTypeForFileUpload << suggestedFileName << isNonTextType ;54 encoder << pathForFileUpload << contentTypeForFileUpload << suggestedFileName << isNonTextType << containsFileURLAndFileUploadContent; 54 55 encoder.encodeEnum(preferredPresentationStyle); 55 56 } … … 69 70 70 71 if (!decoder.decode(result.isNonTextType)) 72 return std::nullopt; 73 74 if (!decoder.decode(result.containsFileURLAndFileUploadContent)) 71 75 return std::nullopt; 72 76 -
trunk/Source/WebCore/platform/cocoa/PasteboardCocoa.mm
r237266 r238795 163 163 return item.preferredPresentationStyle == PasteboardItemPresentationStyle::Attachment; 164 164 165 return !item.suggestedFileName.isEmpty() || item.isNonTextType ;165 return !item.suggestedFileName.isEmpty() || item.isNonTextType || item.containsFileURLAndFileUploadContent; 166 166 }); 167 167 } -
trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm
r238771 r238795 155 155 info.preferredPresentationStyle = pasteboardItemPresentationStyle(itemProvider.preferredPresentationStyle); 156 156 #endif 157 info.containsFileURLAndFileUploadContent = itemProvider.web_containsFileURLAndFileUploadContent; 157 158 info.suggestedFileName = itemProvider.suggestedName; 158 159 for (NSString *typeIdentifier in itemProvider.registeredTypeIdentifiers) { … … 531 532 BOOL ableToDetermineProtocolOfPasteboardURL = ![m_pasteboard isKindOfClass:[WebItemProviderPasteboard class]]; 532 533 if (ableToDetermineProtocolOfPasteboardURL && stringForType(kUTTypeURL).isEmpty()) 534 continue; 535 536 if ([[m_pasteboard pasteboardTypes] containsObject:(__bridge NSString *)kUTTypeFileURL]) 533 537 continue; 534 538 } -
trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.h
r238360 r238795 37 37 38 38 NS_ASSUME_NONNULL_BEGIN 39 40 @interface NSItemProvider (WebCoreExtras) 41 @property (nonatomic, readonly) BOOL web_containsFileURLAndFileUploadContent; 42 @end 39 43 40 44 /*! A WebItemProviderRegistrar encapsulates a single call to register something to an item provider. -
trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm
r238461 r238795 54 54 using WebCore::PasteboardCustomData; 55 55 56 static BOOL typeConformsToTypes(NSString *type, NSArray *conformsToTypes) 57 { 58 for (NSString *conformsToType in conformsToTypes) { 59 if (UTTypeConformsTo((__bridge CFStringRef)type, (__bridge CFStringRef)conformsToType)) 60 return YES; 61 } 62 return NO; 63 } 64 65 @implementation NSItemProvider (WebCoreExtras) 66 67 - (BOOL)web_containsFileURLAndFileUploadContent 68 { 69 BOOL containsFileURL = NO; 70 BOOL containsContentForFileUpload = NO; 71 for (NSString *identifier in self.registeredTypeIdentifiers) { 72 if (UTTypeConformsTo((__bridge CFStringRef)identifier, kUTTypeFileURL)) { 73 containsFileURL = YES; 74 continue; 75 } 76 77 if (UTTypeConformsTo((__bridge CFStringRef)identifier, kUTTypeURL)) 78 continue; 79 80 containsContentForFileUpload |= typeConformsToTypes(identifier, Pasteboard::supportedFileUploadPasteboardTypes()); 81 if (containsContentForFileUpload && containsFileURL) 82 return YES; 83 } 84 return NO; 85 } 86 87 @end 88 56 89 @interface WebItemProviderDataRegistrar : NSObject <WebItemProviderRegistrar> 57 90 - (instancetype)initWithData:(NSData *)data type:(NSString *)utiType; … … 343 376 - (BOOL)canBeRepresentedAsFileUpload 344 377 { 378 if ([_itemProvider web_containsFileURLAndFileUploadContent]) 379 return YES; 380 345 381 #if PLATFORM(IOSMAC) 346 return false;382 return NO; 347 383 #else 348 384 return [_itemProvider preferredPresentationStyle] != UIPreferredPresentationStyleInline; … … 607 643 for (NSString *registeredTypeIdentifier in itemProvider.registeredTypeIdentifiers) { 608 644 // Search for the highest fidelity non-private type identifier we loaded from the item provider. 609 if (!UTTypeIsDeclared(( CFStringRef)registeredTypeIdentifier) && !UTTypeIsDynamic((CFStringRef)registeredTypeIdentifier))645 if (!UTTypeIsDeclared((__bridge CFStringRef)registeredTypeIdentifier) && !UTTypeIsDynamic((__bridge CFStringRef)registeredTypeIdentifier)) 610 646 continue; 611 647 612 648 for (NSString *loadedTypeIdentifier in [result loadedTypeIdentifiers]) { 613 if (!UTTypeConformsTo(( CFStringRef)registeredTypeIdentifier, (CFStringRef)loadedTypeIdentifier))649 if (!UTTypeConformsTo((__bridge CFStringRef)registeredTypeIdentifier, (__bridge CFStringRef)loadedTypeIdentifier)) 614 650 continue; 615 651 … … 631 667 } 632 668 return fileURLs; 633 }634 635 static BOOL typeConformsToTypes(NSString *type, NSArray *conformsToTypes)636 {637 // A type is considered appropriate to load if it conforms to one or more supported types.638 for (NSString *conformsToType in conformsToTypes) {639 if (UTTypeConformsTo((CFStringRef)type, (CFStringRef)conformsToType))640 return YES;641 }642 return NO;643 669 } 644 670 … … 689 715 } 690 716 691 - (NSArray<NSString *> *)typeIdentifiersToLoad ForRegisteredTypeIdentifiers:(NSArray<NSString *> *)registeredTypeIdentifiers717 - (NSArray<NSString *> *)typeIdentifiersToLoad:(NSItemProvider *)itemProvider 692 718 { 693 719 auto typesToLoad = adoptNS([[NSMutableOrderedSet alloc] init]); … … 695 721 NSString *highestFidelityContentType = nil; 696 722 697 BOOL containsFlatRTFD = [registeredTypeIdentifiers containsObject:(NSString *)kUTTypeFlatRTFD]; 723 NSArray<NSString *> *registeredTypeIdentifiers = itemProvider.registeredTypeIdentifiers; 724 BOOL containsFile = itemProvider.web_containsFileURLAndFileUploadContent; 725 BOOL containsFlatRTFD = [registeredTypeIdentifiers containsObject:(__bridge NSString *)kUTTypeFlatRTFD]; 698 726 // First, search for the highest fidelity supported type or the highest fidelity generic content type. 699 727 for (NSString *registeredTypeIdentifier in registeredTypeIdentifiers) { 700 if (containsFlatRTFD && [registeredTypeIdentifier isEqualToString:( NSString *)kUTTypeRTFD]) {728 if (containsFlatRTFD && [registeredTypeIdentifier isEqualToString:(__bridge NSString *)kUTTypeRTFD]) { 701 729 // In the case where attachments are enabled and we're accepting all types of content using attachment 702 730 // elements as a fallback representation, if the source writes attributed strings to the pasteboard with … … 708 736 } 709 737 738 if (containsFile && UTTypeConformsTo((__bridge CFStringRef)registeredTypeIdentifier, kUTTypeURL)) 739 continue; 740 710 741 if (!highestFidelitySupportedType && typeConformsToTypes(registeredTypeIdentifier, _supportedTypeIdentifiers.get())) 711 742 highestFidelitySupportedType = registeredTypeIdentifier; … … 722 753 || [registeredTypeIdentifier isEqualToString:highestFidelitySupportedType] 723 754 || [registeredTypeIdentifier isEqualToString:customPasteboardDataUTI] 724 || UTTypeConformsTo((CFStringRef)registeredTypeIdentifier, kUTTypeURL)725 || UTTypeConformsTo(( CFStringRef)registeredTypeIdentifier, kUTTypeHTML)726 || UTTypeConformsTo(( CFStringRef)registeredTypeIdentifier, kUTTypePlainText))755 || (!containsFile && UTTypeConformsTo((__bridge CFStringRef)registeredTypeIdentifier, kUTTypeURL)) 756 || UTTypeConformsTo((__bridge CFStringRef)registeredTypeIdentifier, kUTTypeHTML) 757 || UTTypeConformsTo((__bridge CFStringRef)registeredTypeIdentifier, kUTTypePlainText)) 727 758 [typesToLoad addObject:registeredTypeIdentifier]; 728 759 } … … 747 778 RetainPtr<WebItemProviderPasteboard> protectedSelf = self; 748 779 for (NSItemProvider *itemProvider in _itemProviders.get()) { 749 NSArray<NSString *> *typeIdentifiersToLoad = [protectedSelf typeIdentifiersToLoad ForRegisteredTypeIdentifiers:itemProvider.registeredTypeIdentifiers];780 NSArray<NSString *> *typeIdentifiersToLoad = [protectedSelf typeIdentifiersToLoad:itemProvider]; 750 781 foundAnyDataToLoad |= typeIdentifiersToLoad.count; 751 782 [loadResults addObject:[WebItemProviderLoadResult loadResultWithItemProvider:itemProvider typesToLoad:typeIdentifiersToLoad]]; -
trunk/Tools/ChangeLog
r238789 r238795 1 2018-12-03 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOSMac] Unable to upload non-image files using drag and drop in WKWebView 4 https://bugs.webkit.org/show_bug.cgi?id=192283 5 <rdar://problem/46399461> 6 7 Reviewed by Ryosuke Niwa. 8 9 Add a new API test to check that an item provider which contains plain text data and a file URL (but is not 10 marked as an attachment) is still treated as an attachment upon drop. Furthermore, verify that "text/uri-list" 11 does not expose the actual file URL written to the item provider. 12 13 Additionally, rebaseline an existing API test to remove an extraneous "text/uri-list" type that appears in 14 `DataTransfer.types`, but whose data is inaccessible via `getData` anyways. 15 16 * TestWebKitAPI/Tests/ios/DragAndDropTestsIOS.mm: 17 1 18 2018-12-01 Don Olmstead <don.olmstead@sony.com> 2 19 -
trunk/Tools/TestWebKitAPI/Tests/ios/DragAndDropTestsIOS.mm
r238728 r238795 1647 1647 // File URLs should never be exposed directly to web content, so DataTransfer.getData should return an empty string here. 1648 1648 checkJSONWithLogging([webView stringByEvaluatingJavaScript:@"output.value"], @{ 1649 @"dragover": @{ @"Files": @"" , @"text/uri-list": @""},1650 @"drop": @{ @"Files": @"" , @"text/uri-list": @""}1649 @"dragover": @{ @"Files": @"" }, 1650 @"drop": @{ @"Files": @"" } 1651 1651 }); 1652 1652 } … … 1771 1771 EXPECT_WK_STREQ("(FILE, text/plain)", [webView stringByEvaluatingJavaScript:@"items.textContent"]); 1772 1772 EXPECT_WK_STREQ("('hello.txt', text/plain)", [webView stringByEvaluatingJavaScript:@"files.textContent"]); 1773 } 1774 1775 TEST(DragAndDropTests, DataTransferExposePlainTextWithFileURLAsFile) 1776 { 1777 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); 1778 [webView synchronouslyLoadTestPageNamed:@"DataTransfer"]; 1779 auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebView:webView.get()]); 1780 1781 auto itemProvider = adoptNS([[NSItemProvider alloc] init]); 1782 NSData *urlAsData = [@"file:///some/file/path.txt" dataUsingEncoding:NSUTF8StringEncoding]; 1783 [itemProvider registerDataRepresentationForTypeIdentifier:(__bridge NSString *)kUTTypeFileURL withData:urlAsData]; 1784 [itemProvider registerDataRepresentationForTypeIdentifier:(__bridge NSString *)kUTTypeURL withData:urlAsData]; 1785 [itemProvider registerObject:@"Hello world" visibility:NSItemProviderRepresentationVisibilityAll]; 1786 1787 [simulator setExternalItemProviders:@[ itemProvider.get() ]]; 1788 [simulator runFrom:CGPointZero to:CGPointMake(50, 100)]; 1789 1790 EXPECT_WK_STREQ("Files", [webView stringByEvaluatingJavaScript:@"types.textContent"]); 1791 EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"textData.textContent"]); 1792 EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"urlData.textContent"]); 1793 EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"htmlData.textContent"]); 1794 EXPECT_WK_STREQ("(FILE, text/plain)", [webView stringByEvaluatingJavaScript:@"items.textContent"]); 1795 EXPECT_WK_STREQ("('text.txt', text/plain)", [webView stringByEvaluatingJavaScript:@"files.textContent"]); 1773 1796 } 1774 1797
Note: See TracChangeset
for help on using the changeset viewer.