Changeset 218508 in webkit


Ignore:
Timestamp:
Jun 19, 2017 2:12:28 PM (7 years ago)
Author:
Wenson Hsieh
Message:

[iOS DnD] Support .zip archives for file uploads via drag and drop
https://bugs.webkit.org/show_bug.cgi?id=173511
<rdar://problem/32521025>

Reviewed by Tim Horton.

Source/WebCore:

Allows dropped .zip archives to be uploaded as files by accepting types conforming to either
"public.zip-archive" or "public.content" as potential file types. Initially, I opted to accept the more general
"public.data" type; however, this includes UTIs such as "public.url" that should not be represented as files, so
this is a more targeted fix that allows us to very easily add additional content types in the future by adding
more types to supportedFileUploadPasteboardTypes.

Tests:
DataInteractionTests.ExternalSourceZIPArchiveToUploadArea
DataInteractionTests.ExternalSourceZIPArchiveAndURLToSingleFileInput

  • page/mac/DragControllerMac.mm:

(WebCore::DragController::updateSupportedTypeIdentifiersForDragHandlingMethod):

  • platform/Pasteboard.h:
  • platform/ios/PasteboardIOS.mm:

(WebCore::Pasteboard::read):
(WebCore::Pasteboard::supportedWebContentPasteboardTypes):
(WebCore::Pasteboard::supportedFileUploadPasteboardTypes):

Rename supportedPasteboardTypes to supportedWebContentPasteboardTypes, and also introduce
supportedFileUploadPasteboardTypes which returns an list of types, such that if a type conforms to any type in
this array, that type may be represented as a file. So far, this list contains "public.content" and
"public.zip-archive".

(WebCore::Pasteboard::types):
(WebCore::Pasteboard::supportedPasteboardTypes): Deleted.

  • platform/ios/WebItemProviderPasteboard.mm:

(typeConformsToTypes):

Remove -typeIsAppropriateForSupportedTypes: and replace it with typeConformsToTypes. Use this both when
determining the number of files on the pasteboard, and when determining preferred UTIs to load when dropping.

(-[WebItemProviderPasteboard numberOfFiles]):
(-[WebItemProviderPasteboard typeIdentifierToLoadForRegisteredTypeIdentfiers:]):
(-[WebItemProviderPasteboard typeIsAppropriateForSupportedTypes:]): Deleted.

  • platform/mac/DragDataMac.mm:

(WebCore::DragData::containsFiles):

  • platform/mac/PasteboardMac.mm:

(WebCore::Pasteboard::supportedFileUploadPasteboardTypes):

Tools:

Adds tests for dropping .zip archives into a JavaScript-based file upload area, as well as into a file input.
Also verifies that URLs are not handled as file drops. See WebCore ChangeLog for more details.

  • TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
  • TestWebKitAPI/Tests/WebKit2Cocoa/compressed-files.zip: Added.
  • TestWebKitAPI/Tests/ios/DataInteractionTests.mm:

(testZIPArchive):
(TestWebKitAPI::TEST):

Location:
trunk
Files:
1 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r218507 r218508  
     12017-06-19  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS DnD] Support .zip archives for file uploads via drag and drop
     4        https://bugs.webkit.org/show_bug.cgi?id=173511
     5        <rdar://problem/32521025>
     6
     7        Reviewed by Tim Horton.
     8
     9        Allows dropped .zip archives to be uploaded as files by accepting types conforming to either
     10        "public.zip-archive" or "public.content" as potential file types. Initially, I opted to accept the more general
     11        "public.data" type; however, this includes UTIs such as "public.url" that should not be represented as files, so
     12        this is a more targeted fix that allows us to very easily add additional content types in the future by adding
     13        more types to supportedFileUploadPasteboardTypes.
     14
     15        Tests:
     16        DataInteractionTests.ExternalSourceZIPArchiveToUploadArea
     17        DataInteractionTests.ExternalSourceZIPArchiveAndURLToSingleFileInput
     18
     19        * page/mac/DragControllerMac.mm:
     20        (WebCore::DragController::updateSupportedTypeIdentifiersForDragHandlingMethod):
     21        * platform/Pasteboard.h:
     22        * platform/ios/PasteboardIOS.mm:
     23        (WebCore::Pasteboard::read):
     24        (WebCore::Pasteboard::supportedWebContentPasteboardTypes):
     25        (WebCore::Pasteboard::supportedFileUploadPasteboardTypes):
     26
     27        Rename supportedPasteboardTypes to supportedWebContentPasteboardTypes, and also introduce
     28        supportedFileUploadPasteboardTypes which returns an list of types, such that if a type conforms to any type in
     29        this array, that type may be represented as a file. So far, this list contains "public.content" and
     30        "public.zip-archive".
     31
     32        (WebCore::Pasteboard::types):
     33        (WebCore::Pasteboard::supportedPasteboardTypes): Deleted.
     34        * platform/ios/WebItemProviderPasteboard.mm:
     35        (typeConformsToTypes):
     36
     37        Remove -typeIsAppropriateForSupportedTypes: and replace it with typeConformsToTypes. Use this both when
     38        determining the number of files on the pasteboard, and when determining preferred UTIs to load when dropping.
     39
     40        (-[WebItemProviderPasteboard numberOfFiles]):
     41        (-[WebItemProviderPasteboard typeIdentifierToLoadForRegisteredTypeIdentfiers:]):
     42        (-[WebItemProviderPasteboard typeIsAppropriateForSupportedTypes:]): Deleted.
     43        * platform/mac/DragDataMac.mm:
     44        (WebCore::DragData::containsFiles):
     45        * platform/mac/PasteboardMac.mm:
     46        (WebCore::Pasteboard::supportedFileUploadPasteboardTypes):
     47
    1482017-06-19  Sam Weinig  <sam@webkit.org>
    249
  • trunk/Source/WebCore/page/mac/DragControllerMac.mm

    r218343 r218508  
    119119        break;
    120120    case DragHandlingMethod::EditRichText:
    121         for (NSString *type in Pasteboard::supportedPasteboardTypes())
     121        for (NSString *type in Pasteboard::supportedWebContentPasteboardTypes())
    122122            supportedTypes.append(type);
    123123        break;
    124124    default:
    125         supportedTypes.append(kUTTypeContent);
     125        for (NSString *type in Pasteboard::supportedFileUploadPasteboardTypes())
     126            supportedTypes.append(type);
    126127        break;
    127128    }
  • trunk/Source/WebCore/platform/Pasteboard.h

    r218128 r218508  
    3333
    3434#if PLATFORM(IOS)
     35OBJC_CLASS NSString;
     36#endif
     37
     38#if PLATFORM(COCOA)
    3539OBJC_CLASS NSArray;
    36 OBJC_CLASS NSString;
    3740#endif
    3841
     
    207210    explicit Pasteboard(long changeCount);
    208211
    209     static NSArray* supportedPasteboardTypes();
     212    static NSArray *supportedWebContentPasteboardTypes();
    210213    static String resourceMIMEType(const NSString *mimeType);
    211214#endif
     
    214217    explicit Pasteboard(const String& pasteboardName);
    215218
     219    WEBCORE_EXPORT static NSArray *supportedFileUploadPasteboardTypes();
    216220    const String& name() const { return m_pasteboardName; }
    217221#endif
  • trunk/Source/WebCore/platform/ios/PasteboardIOS.mm

    r218433 r218508  
    264264        return;
    265265
    266     NSArray *types = supportedPasteboardTypes();
     266    NSArray *types = supportedWebContentPasteboardTypes();
    267267    int numberOfTypes = [types count];
    268268
     
    299299}
    300300
    301 NSArray* Pasteboard::supportedPasteboardTypes()
     301NSArray *Pasteboard::supportedWebContentPasteboardTypes()
    302302{
    303303    return @[(id)WebArchivePboardType, (id)kUTTypeFlatRTFD, (id)kUTTypeRTF, (id)kUTTypeHTML, (id)kUTTypePNG, (id)kUTTypeTIFF, (id)kUTTypeJPEG, (id)kUTTypeGIF, (id)kUTTypeURL, (id)kUTTypeText];
     304}
     305
     306NSArray *Pasteboard::supportedFileUploadPasteboardTypes()
     307{
     308    return @[ (NSString *)kUTTypeContent, (NSString *)kUTTypeZipArchive ];
    304309}
    305310
     
    425430Vector<String> Pasteboard::types()
    426431{
    427     NSArray* types = supportedPasteboardTypes();
     432    NSArray *types = supportedWebContentPasteboardTypes();
    428433
    429434    // Enforce changeCount ourselves for security. We check after reading instead of before to be
  • trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm

    r218343 r218508  
    4040#import <UIKit/UIItemProviderWriting.h>
    4141#import <WebCore/FileSystemIOS.h>
     42#import <WebCore/Pasteboard.h>
    4243#import <wtf/BlockPtr.h>
    4344#import <wtf/OSObjectPtr.h>
     
    4849SOFT_LINK_CLASS(UIKit, UIImage)
    4950SOFT_LINK_CLASS(UIKit, UIItemProvider)
     51
     52using namespace WebCore;
    5053
    5154typedef void(^ItemProviderDataLoadCompletionHandler)(NSData *, NSError *);
     
    374377}
    375378
     379static BOOL typeConformsToTypes(NSString *type, NSArray *conformsToTypes)
     380{
     381    // A type is considered appropriate to load if it conforms to one or more supported types.
     382    for (NSString *conformsToType in conformsToTypes) {
     383        if (UTTypeConformsTo((CFStringRef)type, (CFStringRef)conformsToType))
     384            return YES;
     385    }
     386    return NO;
     387}
     388
    376389- (NSInteger)numberOfFiles
    377390{
     391    NSArray *supportedFileTypes = Pasteboard::supportedFileUploadPasteboardTypes();
    378392    NSInteger numberOfFiles = 0;
    379393    for (UIItemProvider *itemProvider in _itemProviders.get()) {
    380394        for (NSString *identifier in itemProvider.registeredTypeIdentifiers) {
    381             if (!UTTypeConformsTo((__bridge CFStringRef)identifier, kUTTypeContent))
     395            if (!typeConformsToTypes(identifier, supportedFileTypes))
    382396                continue;
    383397            ++numberOfFiles;
     
    406420}
    407421
    408 - (BOOL)typeIsAppropriateForSupportedTypes:(NSString *)type
    409 {
    410     // A type is considered appropriate to load if it conforms to one or more supported types.
    411     for (NSString *supportedTypeIdentifier in _supportedTypeIdentifiers.get()) {
    412         if (UTTypeConformsTo((CFStringRef)type, (CFStringRef)supportedTypeIdentifier))
    413             return YES;
    414     }
    415     return NO;
    416 }
    417 
    418422- (NSString *)typeIdentifierToLoadForRegisteredTypeIdentfiers:(NSArray<NSString *> *)registeredTypeIdentifiers
    419423{
    420424    NSString *highestFidelityContentType = nil;
    421425    for (NSString *registeredTypeIdentifier in registeredTypeIdentifiers) {
    422         if ([self typeIsAppropriateForSupportedTypes:registeredTypeIdentifier])
     426        if (typeConformsToTypes(registeredTypeIdentifier, _supportedTypeIdentifiers.get()))
    423427            return registeredTypeIdentifier;
    424428
  • trunk/Source/WebCore/platform/mac/DragDataMac.mm

    r218433 r218508  
    161161bool DragData::containsFiles() const
    162162{
     163    NSArray *supportedFileTypes = Pasteboard::supportedFileUploadPasteboardTypes();
    163164    Vector<String> types;
    164165    platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName);
    165166    for (auto& type : types) {
    166 #if PLATFORM(MAC)
    167         if (type == String(NSFilesPromisePboardType) || type == String(NSFilenamesPboardType))
    168             return true;
    169 #else
    170         if (UTTypeConformsTo(type.createCFString().autorelease(), kUTTypeContent))
    171             return true;
    172 #endif
     167        auto cfType = type.createCFString();
     168        for (NSString *fileType in supportedFileTypes) {
     169            if (UTTypeConformsTo(cfType.get(), (CFStringRef)fileType))
     170                return true;
     171        }
    173172    }
    174173    return false;
  • trunk/Source/WebCore/platform/mac/PasteboardMac.mm

    r217893 r218508  
    105105}
    106106
     107NSArray *Pasteboard::supportedFileUploadPasteboardTypes()
     108{
     109    return @[ (NSString *)NSFilesPromisePboardType, (NSString *)NSFilenamesPboardType ];
     110}
     111
    107112Pasteboard::Pasteboard()
    108113    : m_pasteboardName(emptyString())
  • trunk/Tools/ChangeLog

    r218496 r218508  
     12017-06-19  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS DnD] Support .zip archives for file uploads via drag and drop
     4        https://bugs.webkit.org/show_bug.cgi?id=173511
     5        <rdar://problem/32521025>
     6
     7        Reviewed by Tim Horton.
     8
     9        Adds tests for dropping .zip archives into a JavaScript-based file upload area, as well as into a file input.
     10        Also verifies that URLs are not handled as file drops. See WebCore ChangeLog for more details.
     11
     12        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
     13        * TestWebKitAPI/Tests/WebKit2Cocoa/compressed-files.zip: Added.
     14        * TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
     15        (testZIPArchive):
     16        (TestWebKitAPI::TEST):
     17
    1182017-06-18  Darin Adler  <darin@apple.com>
    219
  • trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

    r218496 r218508  
    647647                F47728991E4AE3C1007ABF6A /* full-page-contenteditable.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F47728981E4AE3AD007ABF6A /* full-page-contenteditable.html */; };
    648648                F4856CA31E649EA8009D7EE7 /* attachment-element.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4856CA21E6498A8009D7EE7 /* attachment-element.html */; };
     649                F4B825D81EF4DBFB006E417F /* compressed-files.zip in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4B825D61EF4DBD4006E417F /* compressed-files.zip */; };
    649650                F4BFA68E1E4AD08000154298 /* DragAndDropPasteboardTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4BFA68C1E4AD08000154298 /* DragAndDropPasteboardTests.mm */; };
    650651                F4C2AB221DD6D95E00E06D5B /* enormous-video-with-sound.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4C2AB211DD6D94100E06D5B /* enormous-video-with-sound.html */; };
     
    727728                        dstSubfolderSpec = 7;
    728729                        files = (
     730                                F4B825D81EF4DBFB006E417F /* compressed-files.zip in Copy Resources */,
    729731                                F41AB99F1EF4696B0083FA08 /* autofocus-contenteditable.html in Copy Resources */,
    730732                                F41AB9A01EF4696B0083FA08 /* background-image-link-and-input.html in Copy Resources */,
     
    16121614                F47D30ED1ED28A6C000482E1 /* gif-and-file-input.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "gif-and-file-input.html"; sourceTree = "<group>"; };
    16131615                F4856CA21E6498A8009D7EE7 /* attachment-element.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "attachment-element.html"; sourceTree = "<group>"; };
     1616                F4B825D61EF4DBD4006E417F /* compressed-files.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = "compressed-files.zip"; sourceTree = "<group>"; };
    16141617                F4BFA68C1E4AD08000154298 /* DragAndDropPasteboardTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DragAndDropPasteboardTests.mm; sourceTree = "<group>"; };
    16151618                F4C2AB211DD6D94100E06D5B /* enormous-video-with-sound.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "enormous-video-with-sound.html"; sourceTree = "<group>"; };
     
    20032006                        isa = PBXGroup;
    20042007                        children = (
     2008                                F4B825D61EF4DBD4006E417F /* compressed-files.zip */,
    20052009                                F41AB9981EF4692C0083FA08 /* autofocus-contenteditable.html */,
    20062010                                F41AB9971EF4692C0083FA08 /* background-image-link-and-input.html */,
  • trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm

    r218343 r218508  
    5353}
    5454
     55static NSData *testZIPArchive()
     56{
     57    NSURL *zipFileURL = [[NSBundle mainBundle] URLForResource:@"compressed-files" withExtension:@"zip" subdirectory:@"TestWebKitAPI.resources"];
     58    return [NSData dataWithContentsOfURL:zipFileURL];
     59}
     60
    5561@implementation UIItemProvider (DataInteractionTests)
    5662
     
    454460    NSString *outputValue = [webView stringByEvaluatingJavaScript:@"output.value"];
    455461    EXPECT_WK_STREQ("text/html", outputValue.UTF8String);
     462}
     463
     464TEST(DataInteractionTests, ExternalSourceZIPArchiveAndURLToSingleFileInput)
     465{
     466    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
     467    [webView synchronouslyLoadTestPageNamed:@"file-uploading"];
     468
     469    auto archiveProvider = adoptNS([[UIItemProvider alloc] init]);
     470    [archiveProvider registerDataRepresentationForTypeIdentifier:(NSString *)kUTTypeZipArchive withData:testZIPArchive()];
     471
     472    auto urlProvider = adoptNS([[UIItemProvider alloc] init]);
     473    [urlProvider registerObject:[NSURL URLWithString:@"https://webkit.org"] visibility:UIItemProviderRepresentationOptionsVisibilityAll];
     474
     475    auto dataInteractionSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
     476    [dataInteractionSimulator setExternalItemProviders:@[ archiveProvider.get(), urlProvider.get() ]];
     477    [dataInteractionSimulator runFrom:CGPointMake(200, 100) to:CGPointMake(100, 100)];
     478
     479    NSString *outputValue = [webView stringByEvaluatingJavaScript:@"output.value"];
     480    EXPECT_WK_STREQ("application/zip", outputValue.UTF8String);
     481}
     482
     483TEST(DataInteractionTests, ExternalSourceZIPArchiveToUploadArea)
     484{
     485    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
     486    [webView synchronouslyLoadTestPageNamed:@"file-uploading"];
     487
     488    auto itemProvider = adoptNS([[UIItemProvider alloc] init]);
     489    [itemProvider registerDataRepresentationForTypeIdentifier:(NSString *)kUTTypeZipArchive withData:testZIPArchive()];
     490
     491    auto dataInteractionSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
     492    [dataInteractionSimulator setExternalItemProviders:@[ itemProvider.get() ]];
     493    [dataInteractionSimulator runFrom:CGPointMake(200, 300) to:CGPointMake(100, 300)];
     494
     495    NSString *outputValue = [webView stringByEvaluatingJavaScript:@"output.value"];
     496    EXPECT_WK_STREQ("application/zip", outputValue.UTF8String);
    456497}
    457498
Note: See TracChangeset for help on using the changeset viewer.