/*
 * Copyright (C) 2017-2018 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.
 */

#import "config.h"
#import "WebItemProviderPasteboard.h"

#if PLATFORM(IOS_FAMILY) && ENABLE(DRAG_SUPPORT)

#import <Foundation/NSItemProvider.h>
#import <Foundation/NSProgress.h>
#import <MobileCoreServices/MobileCoreServices.h>
#import <UIKit/NSItemProvider+UIKitAdditions.h>
#import <UIKit/UIColor.h>
#import <UIKit/UIImage.h>
#import <WebCore/Pasteboard.h>
#import <pal/ios/UIKitSoftLink.h>
#import <pal/spi/ios/UIKitSPI.h>
#import <wtf/BlockPtr.h>
#import <wtf/FileSystem.h>
#import <wtf/OSObjectPtr.h>
#import <wtf/RetainPtr.h>

typedef void(^ItemProviderDataLoadCompletionHandler)(NSData *, NSError *);
typedef void(^ItemProviderFileLoadCompletionHandler)(NSURL *, BOOL, NSError *);
typedef NSMutableDictionary<NSString *, NSURL *> TypeToFileURLMap;

using WebCore::Pasteboard;
using WebCore::PasteboardCustomData;

static BOOL typeConformsToTypes(NSString *type, NSArray *conformsToTypes)
{
    for (NSString *conformsToType in conformsToTypes) {
ALLOW_DEPRECATED_DECLARATIONS_BEGIN
        if (UTTypeConformsTo((__bridge CFStringRef)type, (__bridge CFStringRef)conformsToType))
            return YES;
ALLOW_DEPRECATED_DECLARATIONS_END
    }
    return NO;
}

@implementation NSItemProvider (WebCoreExtras)

- (BOOL)web_containsFileURLAndFileUploadContent
{
    for (NSString *identifier in self.registeredTypeIdentifiers) {
ALLOW_DEPRECATED_DECLARATIONS_BEGIN
        if (UTTypeConformsTo((__bridge CFStringRef)identifier, kUTTypeFileURL))
            return self.web_fileUploadContentTypes.count;
ALLOW_DEPRECATED_DECLARATIONS_END
    }
    return NO;
}

- (NSArray<NSString *> *)web_fileUploadContentTypes
{
    auto types = adoptNS([NSMutableArray new]);
    for (NSString *identifier in self.registeredTypeIdentifiers) {
ALLOW_DEPRECATED_DECLARATIONS_BEGIN
        if (UTTypeConformsTo((__bridge CFStringRef)identifier, kUTTypeURL))
            continue;
ALLOW_DEPRECATED_DECLARATIONS_END

        if ([identifier isEqualToString:@"com.apple.mapkit.map-item"]) {
            // This type conforms to "public.content", yet the corresponding data is only a serialization of MKMapItem and isn't suitable for file uploads.
            // Ignore over this type representation for the purposes of file uploads, in favor of "public.vcard" data.
            continue;
        }

        if (typeConformsToTypes(identifier, Pasteboard::supportedFileUploadPasteboardTypes()))
            [types addObject:identifier];
    }

    return types.autorelease();
}

@end

@interface WebItemProviderDataRegistrar : NSObject <WebItemProviderRegistrar>
- (instancetype)initWithData:(NSData *)data type:(NSString *)utiType;
@property (nonatomic, readonly) NSString *typeIdentifier;
@property (nonatomic, readonly) NSData *data;
@end

@implementation WebItemProviderDataRegistrar {
    RetainPtr<NSString> _typeIdentifier;
    RetainPtr<NSData> _data;
}

- (instancetype)initWithData:(NSData *)data type:(NSString *)utiType
{
    if (!(self = [super init]))
        return nil;

    _data = data;
    _typeIdentifier = utiType;
    return self;
}

- (NSString *)typeIdentifier
{
    return _typeIdentifier.get();
}

- (NSData *)data
{
    return _data.get();
}

- (NSString *)typeIdentifierForClient
{
    return self.typeIdentifier;
}

- (NSData *)dataForClient
{
    return self.data;
}

- (void)registerItemProvider:(NSItemProvider *)itemProvider
{
    [itemProvider registerDataRepresentationForTypeIdentifier:self.typeIdentifier visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[itemData = _data] (ItemProviderDataLoadCompletionHandler completionHandler) -> NSProgress * {
        completionHandler(itemData.get(), nil);
        return nil;
    }];
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"(%@ => %tu bytes)", _typeIdentifier.get(), [_data length]];
}

@end

@interface WebItemProviderWritableObjectRegistrar : NSObject <WebItemProviderRegistrar>
- (instancetype)initWithObject:(id <NSItemProviderWriting>)representingObject;
@property (nonatomic, readonly) id <NSItemProviderWriting> representingObject;
@end

@implementation WebItemProviderWritableObjectRegistrar {
    RetainPtr<id <NSItemProviderWriting>> _representingObject;
}

- (instancetype)initWithObject:(id <NSItemProviderWriting>)representingObject
{
    if (!(self = [super init]))
        return nil;

    _representingObject = representingObject;
    return self;
}

- (id <NSItemProviderWriting>)representingObject
{
    return _representingObject.get();
}

- (id <NSItemProviderWriting>)representingObjectForClient
{
    return self.representingObject;
}

- (void)registerItemProvider:(NSItemProvider *)itemProvider
{
    [itemProvider registerObject:self.representingObject visibility:NSItemProviderRepresentationVisibilityAll];
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"(%@)", [_representingObject class]];
}

@end

@interface WebItemProviderPromisedFileRegistrar : NSObject <WebItemProviderRegistrar>
- (instancetype)initWithType:(NSString *)utiType callback:(void(^)(WebItemProviderFileCallback))callback;
@property (nonatomic, readonly) NSString *typeIdentifier;
@end

@implementation WebItemProviderPromisedFileRegistrar {
    RetainPtr<NSString> _typeIdentifier;
    BlockPtr<void(WebItemProviderFileCallback)> _callback;
}

- (instancetype)initWithType:(NSString *)utiType callback:(void(^)(WebItemProviderFileCallback))callback
{
    if (!(self = [super init]))
        return nil;

    _typeIdentifier = utiType;
    _callback = callback;
    return self;
}

- (void)registerItemProvider:(NSItemProvider *)itemProvider
{
    [itemProvider registerFileRepresentationForTypeIdentifier:_typeIdentifier.get() fileOptions:0 visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[callback = _callback] (ItemProviderFileLoadCompletionHandler completionHandler) -> NSProgress * {
        callback([protectedCompletionHandler = makeBlockPtr(completionHandler)] (NSURL *fileURL, NSError *error) {
            protectedCompletionHandler(fileURL, NO, error);
        });
        return nil;
    }];
}

- (NSString *)typeIdentifier
{
    return _typeIdentifier.get();
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"(file promise: %@)", _typeIdentifier.get()];
}

@end

@interface WebItemProviderRegistrationInfoList ()
{
    RetainPtr<NSMutableArray> _representations;
}
@end

@implementation WebItemProviderRegistrationInfoList

- (instancetype)init
{
    if (self = [super init]) {
        _representations = adoptNS([[NSMutableArray alloc] init]);
        _preferredPresentationSize = CGSizeZero;
        _preferredPresentationStyle = WebPreferredPresentationStyleUnspecified;
    }

    return self;
}

- (void)dealloc
{
    [_suggestedName release];
    [_teamData release];
    [super dealloc];
}

- (void)addData:(NSData *)data forType:(NSString *)typeIdentifier
{
    auto representation = adoptNS([[WebItemProviderDataRegistrar alloc] initWithData:data type:typeIdentifier]);
    [_representations addObject:representation.get()];
}

- (void)addRepresentingObject:(id <NSItemProviderWriting>)object
{
    ASSERT([object conformsToProtocol:@protocol(NSItemProviderWriting)]);
    auto representation = adoptNS([[WebItemProviderWritableObjectRegistrar alloc] initWithObject:object]);
    [_representations addObject:representation.get()];
}

- (void)addPromisedType:(NSString *)typeIdentifier fileCallback:(void(^)(WebItemProviderFileCallback))callback
{
    auto representation = adoptNS([[WebItemProviderPromisedFileRegistrar alloc] initWithType:typeIdentifier callback:callback]);
    [_representations addObject:representation.get()];
}

- (NSUInteger)numberOfItems
{
    return [_representations count];
}

- (id <WebItemProviderRegistrar>)itemAtIndex:(NSUInteger)index
{
    if (index >= self.numberOfItems)
        return nil;

    return [_representations objectAtIndex:index];
}

- (void)enumerateItems:(void (^)(id <WebItemProviderRegistrar>, NSUInteger))block
{
    for (NSUInteger index = 0; index < self.numberOfItems; ++index)
        block([self itemAtIndex:index], index);
}

#if !PLATFORM(MACCATALYST)
static UIPreferredPresentationStyle uiPreferredPresentationStyle(WebPreferredPresentationStyle style)
{
    switch (style) {
    case WebPreferredPresentationStyleUnspecified:
        return UIPreferredPresentationStyleUnspecified;
    case WebPreferredPresentationStyleInline:
        return UIPreferredPresentationStyleInline;
    case WebPreferredPresentationStyleAttachment:
        return UIPreferredPresentationStyleAttachment;
    default:
        ASSERT_NOT_REACHED();
        return UIPreferredPresentationStyleUnspecified;
    }
}
#endif

- (NSItemProvider *)itemProvider
{
    if (!self.numberOfItems)
        return nil;

    auto itemProvider = adoptNS([NSItemProvider new]);
    for (id <WebItemProviderRegistrar> representation in _representations.get())
        [representation registerItemProvider:itemProvider.get()];
    [itemProvider setSuggestedName:self.suggestedName];
#if !PLATFORM(MACCATALYST)
    [itemProvider setPreferredPresentationSize:self.preferredPresentationSize];
    [itemProvider setPreferredPresentationStyle:uiPreferredPresentationStyle(self.preferredPresentationStyle)];
    [itemProvider setTeamData:self.teamData];
#endif
    return itemProvider.autorelease();
}

- (NSString *)description
{
    __block NSMutableString *description = [NSMutableString string];
    [description appendFormat:@"<%@: %p", [self class], self];
    [self enumerateItems:^(id <WebItemProviderRegistrar> item, NSUInteger index) {
        if (index)
            [description appendString:@", "];
        [description appendString:[item description]];
    }];
    [description appendString:@">"];
    return description;
}

@end

@interface WebItemProviderLoadResult : NSObject

- (instancetype)initWithItemProvider:(NSItemProvider *)itemProvider typesToLoad:(NSArray<NSString *> *)typesToLoad;
- (NSURL *)fileURLForType:(NSString *)type;
- (void)setFileURL:(NSURL *)url forType:(NSString *)type;
@property (nonatomic, readonly) NSArray<NSURL *> *loadedFileURLs;
@property (nonatomic, readonly) NSArray<NSString *> *loadedTypeIdentifiers;
@property (nonatomic, readonly) BOOL canBeRepresentedAsFileUpload;
@property (nonatomic, readonly) NSItemProvider *itemProvider;
@property (nonatomic, readonly) NSArray<NSString *> *typesToLoad;

@end

@implementation WebItemProviderLoadResult {
    RetainPtr<TypeToFileURLMap> _fileURLs;
    RetainPtr<NSItemProvider> _itemProvider;
    RetainPtr<NSArray<NSString *>> _typesToLoad;
}

+ (instancetype)loadResultWithItemProvider:(NSItemProvider *)itemProvider typesToLoad:(NSArray<NSString *> *)typesToLoad
{
    return adoptNS([[self alloc] initWithItemProvider:itemProvider typesToLoad:typesToLoad]).autorelease();
}

- (instancetype)initWithItemProvider:(NSItemProvider *)itemProvider typesToLoad:(NSArray<NSString *> *)typesToLoad
{
    if (!(self = [super init]))
        return nil;

    _fileURLs = adoptNS([[NSMutableDictionary alloc] init]);
    _itemProvider = itemProvider;
    _typesToLoad = typesToLoad;

    return self;
}

- (BOOL)canBeRepresentedAsFileUpload
{
    if ([_itemProvider web_containsFileURLAndFileUploadContent])
        return YES;

    if ([_itemProvider preferredPresentationStyle] == UIPreferredPresentationStyleInline)
        return NO;

#if PLATFORM(MACCATALYST)
    // On macCatalyst, -preferredPresentationStyle always returns UIPreferredPresentationStyleUnspecified,
    // even when the preferredPresentationStyle is set to something other than unspecified using the setter.
    // This means we're unable to avoid exposing item providers that have been marked as inline data as files
    // to the page -- see <rdar://55002929> for more details. In the meantime, only expose item providers as
    // files if they have explicitly been given a suggested file name.
    return [_itemProvider suggestedName].length;
#else
    return YES;
#endif
}

- (NSArray<NSString *> *)typesToLoad
{
    return _typesToLoad.get();
}

- (NSURL *)fileURLForType:(NSString *)type
{
    return [_fileURLs objectForKey:type];
}

- (void)setFileURL:(NSURL *)url forType:(NSString *)type
{
    [_fileURLs setObject:url forKey:type];
}

- (NSArray<NSURL *> *)loadedFileURLs
{
    return [_fileURLs allValues];
}

- (NSArray<NSString *> *)loadedTypeIdentifiers
{
    return [_fileURLs allKeys];
}

- (NSItemProvider *)itemProvider
{
    return _itemProvider.get();
}

- (NSString *)description
{
    __block NSMutableString *description = [NSMutableString string];
    [description appendFormat:@"<%@: %p typesToLoad: [ ", [self class], self];
    [_typesToLoad enumerateObjectsUsingBlock:^(NSString *type, NSUInteger index, BOOL *) {
        [description appendString:type];
        if (index + 1 < [_typesToLoad count])
            [description appendString:@", "];
    }];
    [description appendFormat:@" ] fileURLs: { "];
    __block NSUInteger index = 0;
    [_fileURLs enumerateKeysAndObjectsUsingBlock:^(NSString *type, NSURL *url, BOOL *) {
        [description appendFormat:@"%@ => \"%@\"", type, url.path];
        if (++index < [_fileURLs count])
            [description appendString:@", "];
    }];
    [description appendFormat:@" }>"];
    return description;
}

@end

@interface WebItemProviderPasteboard ()

@property (nonatomic) NSInteger numberOfItems;
@property (nonatomic) NSInteger changeCount;
@property (nonatomic) NSInteger pendingOperationCount;

@end

@implementation WebItemProviderPasteboard {
    // FIXME: These ivars should be refactored to be Vector<RetainPtr<Type>> instead of generic NSArrays.
    RetainPtr<NSArray> _itemProviders;
    RetainPtr<NSArray> _supportedTypeIdentifiers;
    RetainPtr<NSArray<WebItemProviderRegistrationInfoList *>> _stagedRegistrationInfoLists;

    Vector<RetainPtr<WebItemProviderLoadResult>> _loadResults;
}

+ (instancetype)sharedInstance
{
    static NeverDestroyed<RetainPtr<WebItemProviderPasteboard>> sharedPasteboard;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^() {
        sharedPasteboard.get() = adoptNS([[WebItemProviderPasteboard alloc] init]);
    });
    return sharedPasteboard.get().get();
}

- (instancetype)init
{
    if (self = [super init]) {
        _itemProviders = adoptNS([[NSArray alloc] init]);
        _changeCount = 0;
        _pendingOperationCount = 0;
        _supportedTypeIdentifiers = nil;
        _stagedRegistrationInfoLists = nil;
        _loadResults = { };
    }
    return self;
}

- (void)updateSupportedTypeIdentifiers:(NSArray<NSString *> *)types
{
    _supportedTypeIdentifiers = types;
}

- (NSArray<NSString *> *)pasteboardTypes
{
    NSMutableSet<NSString *> *allTypes = [NSMutableSet set];
    NSMutableArray<NSString *> *allTypesInOrder = [NSMutableArray array];
    for (NSItemProvider *provider in _itemProviders.get()) {
        for (NSString *typeIdentifier in provider.registeredTypeIdentifiers) {
            if ([allTypes containsObject:typeIdentifier])
                continue;

            [allTypes addObject:typeIdentifier];
            [allTypesInOrder addObject:typeIdentifier];
        }
    }
    return allTypesInOrder;
}

- (NSArray<__kindof NSItemProvider *> *)itemProviders
{
    return _itemProviders.get();
}

- (void)setItemProviders:(NSArray<__kindof NSItemProvider *> *)itemProviders
{
    itemProviders = itemProviders ?: @[ ];
    if (_itemProviders == itemProviders || [_itemProviders isEqualToArray:itemProviders])
        return;

    _itemProviders = itemProviders;
    _changeCount++;

    if (!itemProviders.count)
        _loadResults = { };
}

- (NSInteger)numberOfItems
{
    return [_itemProviders count];
}

- (NSData *)_preLoadedDataConformingToType:(NSString *)typeIdentifier forItemProviderAtIndex:(NSUInteger)index
{
    if (_loadResults.size() != [_itemProviders count]) {
        ASSERT_NOT_REACHED();
        return nil;
    }

    WebItemProviderLoadResult *loadResult = _loadResults[index].get();
    for (NSString *loadedType in loadResult.loadedTypeIdentifiers) {
ALLOW_DEPRECATED_DECLARATIONS_BEGIN
        if (!UTTypeConformsTo((CFStringRef)loadedType, (CFStringRef)typeIdentifier))
            continue;
ALLOW_DEPRECATED_DECLARATIONS_END

        // We've already loaded data relevant for this UTI type onto disk, so there's no need to ask the NSItemProvider for the same data again.
        if (NSData *result = [NSData dataWithContentsOfURL:[loadResult fileURLForType:loadedType] options:NSDataReadingMappedIfSafe error:nil])
            return result;
    }
    return nil;
}

- (NSData *)dataForPasteboardType:(NSString *)pasteboardType
{
    return [self dataForPasteboardType:pasteboardType inItemSet:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.numberOfItems)]].firstObject;
}

- (NSArray *)dataForPasteboardType:(NSString *)pasteboardType inItemSet:(NSIndexSet *)itemSet
{
    if (_loadResults.isEmpty())
        return @[ ];

    auto values = adoptNS([[NSMutableArray alloc] init]);
    RetainPtr<WebItemProviderPasteboard> retainedSelf = self;
    [itemSet enumerateIndexesUsingBlock:[retainedSelf, pasteboardType, values] (NSUInteger index, BOOL *) {
        NSItemProvider *provider = [retainedSelf itemProviderAtIndex:index];
        if (!provider)
            return;

        if (NSData *loadedData = [retainedSelf _preLoadedDataConformingToType:pasteboardType forItemProviderAtIndex:index])
            [values addObject:loadedData];
    }];
    return values.autorelease();
}

static NSArray<Class<NSItemProviderReading>> *allLoadableClasses()
{
    return @[ [PAL::getUIColorClass() class], [PAL::getUIImageClass() class], [NSURL class], [NSString class], [NSAttributedString class] ];
}

static Class classForTypeIdentifier(NSString *typeIdentifier, NSString *&outTypeIdentifierToLoad)
{
    outTypeIdentifierToLoad = typeIdentifier;

    // First, try to load a platform NSItemProviderReading-conformant object as-is.
    for (Class<NSItemProviderReading> loadableClass in allLoadableClasses()) {
        if ([[loadableClass readableTypeIdentifiersForItemProvider] containsObject:(NSString *)typeIdentifier])
            return loadableClass;
    }

    // If we were unable to load any object, check if the given type identifier is still something
    // WebKit knows how to handle.
ALLOW_DEPRECATED_DECLARATIONS_BEGIN
    if ([typeIdentifier isEqualToString:(NSString *)kUTTypeHTML]) {
        // Load kUTTypeHTML as a plain text HTML string.
        outTypeIdentifierToLoad = (NSString *)kUTTypePlainText;
        return [NSString class];
    }
ALLOW_DEPRECATED_DECLARATIONS_END

    return nil;
}

- (NSArray *)valuesForPasteboardType:(NSString *)pasteboardType inItemSet:(NSIndexSet *)itemSet
{
    if (_loadResults.isEmpty())
        return @[ ];

    auto values = adoptNS([[NSMutableArray alloc] init]);
    RetainPtr<WebItemProviderPasteboard> retainedSelf = self;
    [itemSet enumerateIndexesUsingBlock:[retainedSelf, pasteboardType, values] (NSUInteger index, BOOL *) {
        NSItemProvider *provider = [retainedSelf itemProviderAtIndex:index];
        if (!provider)
            return;

        NSString *typeIdentifierToLoad;
        Class readableClass = classForTypeIdentifier(pasteboardType, typeIdentifierToLoad);
        if (!readableClass)
            return;

        NSData *preloadedData = [retainedSelf _preLoadedDataConformingToType:pasteboardType forItemProviderAtIndex:index];
        if (!preloadedData)
            return;

        if (id <NSItemProviderReading> readObject = [readableClass objectWithItemProviderData:preloadedData typeIdentifier:(NSString *)typeIdentifierToLoad error:nil])
            [values addObject:readObject];
    }];

    return values.autorelease();
}

- (NSInteger)changeCount
{
    return _changeCount;
}

- (NSArray<NSURL *> *)fileUploadURLsAtIndex:(NSUInteger)index fileTypes:(NSArray<NSString *> **)outFileTypes
{
    auto fileTypes = adoptNS([NSMutableArray new]);
    auto fileURLs = adoptNS([NSMutableArray new]);

    if (index >= _loadResults.size())
        return @[ ];

    auto result = _loadResults[index];
    if (![result canBeRepresentedAsFileUpload])
        return @[ ];

    for (NSString *contentType in [result itemProvider].web_fileUploadContentTypes) {
        if (NSURL *url = [result fileURLForType:contentType]) {
            [fileTypes addObject:contentType];
            [fileURLs addObject:url];
        }
    }

    *outFileTypes = fileTypes.autorelease();
    return fileURLs.autorelease();
}

- (NSArray<NSURL *> *)allDroppedFileURLs
{
    NSMutableArray<NSURL *> *fileURLs = [NSMutableArray array];
    for (const auto& loadResult : _loadResults) {
        if ([loadResult canBeRepresentedAsFileUpload])
            [fileURLs addObjectsFromArray:[loadResult loadedFileURLs]];
    }
    return fileURLs;
}

- (NSInteger)numberOfFiles
{
    NSInteger numberOfFiles = 0;
    for (NSItemProvider *itemProvider in _itemProviders.get()) {
#if !PLATFORM(MACCATALYST)
        // First, check if the source has explicitly indicated that this item should or should not be treated as an attachment.
        if (itemProvider.preferredPresentationStyle == UIPreferredPresentationStyleInline)
            continue;

        if (itemProvider.preferredPresentationStyle == UIPreferredPresentationStyleAttachment) {
            ++numberOfFiles;
            continue;
        }
#endif
        // Otherwise, fall back to examining the item's registered type identifiers.
        if (itemProvider.web_fileUploadContentTypes.count)
            ++numberOfFiles;
    }
    return numberOfFiles;
}

static NSURL *linkTemporaryItemProviderFilesToDropStagingDirectory(NSURL *url, NSString *suggestedName, NSString *typeIdentifier)
{
    static NSString *defaultDropFolderName = @"folder";
    static NSString *defaultDropFileName = @"file";
    static NSString *droppedDataDirectoryPrefix = @"dropped-data";
    if (!url)
        return nil;

    NSString *temporaryDropDataDirectory = FileSystem::createTemporaryDirectory(droppedDataDirectoryPrefix);
    if (!temporaryDropDataDirectory)
        return nil;

    NSURL *destination = nil;
ALLOW_DEPRECATED_DECLARATIONS_BEGIN
    BOOL isFolder = UTTypeConformsTo((CFStringRef)typeIdentifier, kUTTypeFolder);
ALLOW_DEPRECATED_DECLARATIONS_END
    NSFileManager *fileManager = [NSFileManager defaultManager];

    if (!suggestedName)
        suggestedName = url.lastPathComponent ?: (isFolder ? defaultDropFolderName : defaultDropFileName);

    if ([suggestedName.pathExtension caseInsensitiveCompare:url.pathExtension] != NSOrderedSame && !isFolder)
        suggestedName = [suggestedName stringByAppendingPathExtension:url.pathExtension];

    destination = [NSURL fileURLWithPath:[temporaryDropDataDirectory stringByAppendingPathComponent:suggestedName]];
    return [fileManager linkItemAtURL:url toURL:destination error:nil] ? destination : nil;
}

- (NSArray<NSString *> *)typeIdentifiersToLoad:(NSItemProvider *)itemProvider
{
ALLOW_DEPRECATED_DECLARATIONS_BEGIN
    auto typesToLoad = adoptNS([[NSMutableOrderedSet alloc] init]);
    NSString *highestFidelitySupportedType = nil;
    NSString *highestFidelityContentType = nil;

    NSArray<NSString *> *registeredTypeIdentifiers = itemProvider.registeredTypeIdentifiers;
    BOOL containsFile = itemProvider.web_containsFileURLAndFileUploadContent;
    BOOL containsFlatRTFD = [registeredTypeIdentifiers containsObject:(__bridge NSString *)kUTTypeFlatRTFD];
    // First, search for the highest fidelity supported type or the highest fidelity generic content type.
    for (NSString *registeredTypeIdentifier in registeredTypeIdentifiers) {
        if (containsFlatRTFD && [registeredTypeIdentifier isEqualToString:(__bridge NSString *)kUTTypeRTFD]) {
            // In the case where attachments are enabled and we're accepting all types of content using attachment
            // elements as a fallback representation, if the source writes attributed strings to the pasteboard with
            // com.apple.rtfd at a higher fidelity than com.apple.flat-rtfd, we'll end up loading only com.apple.rtfd
            // and dropping the text as an attachment element because we cannot convert the dropped content to markup.
            // Instead, if flat RTFD is present in the item provider, always prefer that over RTFD so that dropping as
            // regular web content isn't overridden by enabling attachment elements.
            continue;
        }

        if (containsFile && UTTypeConformsTo((__bridge CFStringRef)registeredTypeIdentifier, kUTTypeURL))
            continue;

        if (!highestFidelitySupportedType && typeConformsToTypes(registeredTypeIdentifier, _supportedTypeIdentifiers.get()))
            highestFidelitySupportedType = registeredTypeIdentifier;

        if (!highestFidelityContentType && UTTypeConformsTo((CFStringRef)registeredTypeIdentifier, kUTTypeContent))
            highestFidelityContentType = registeredTypeIdentifier;
    }

    // For compatibility with DataTransfer APIs, additionally load web-exposed types. Since this is the only chance to
    // fault in any data at all, we need to load up front any information that the page may ask for later down the line.
    NSString *customPasteboardDataUTI = @(PasteboardCustomData::cocoaType());
    for (NSString *registeredTypeIdentifier in registeredTypeIdentifiers) {
        if ([registeredTypeIdentifier isEqualToString:highestFidelityContentType]
            || [registeredTypeIdentifier isEqualToString:highestFidelitySupportedType]
            || [registeredTypeIdentifier isEqualToString:customPasteboardDataUTI]
            || (!containsFile && UTTypeConformsTo((__bridge CFStringRef)registeredTypeIdentifier, kUTTypeURL))
            || UTTypeConformsTo((__bridge CFStringRef)registeredTypeIdentifier, kUTTypeHTML)
            || UTTypeConformsTo((__bridge CFStringRef)registeredTypeIdentifier, kUTTypePlainText))
            [typesToLoad addObject:registeredTypeIdentifier];
    }
ALLOW_DEPRECATED_DECLARATIONS_END

    return [typesToLoad array];
}

- (void)doAfterLoadingProvidedContentIntoFileURLs:(WebItemProviderFileLoadBlock)action
{
    [self doAfterLoadingProvidedContentIntoFileURLs:action synchronousTimeout:0];
}

- (void)doAfterLoadingProvidedContentIntoFileURLs:(WebItemProviderFileLoadBlock)action synchronousTimeout:(NSTimeInterval)synchronousTimeout
{
    _loadResults.clear();

    auto changeCountBeforeLoading = _changeCount;
    auto loadResults = adoptNS([[NSMutableArray alloc] initWithCapacity:[_itemProviders count]]);

    // First, figure out which item providers we want to try and load files from.
    BOOL foundAnyDataToLoad = NO;
    RetainPtr<WebItemProviderPasteboard> protectedSelf = self;
    for (NSItemProvider *itemProvider in _itemProviders.get()) {
        NSArray<NSString *> *typeIdentifiersToLoad = [protectedSelf typeIdentifiersToLoad:itemProvider];
        foundAnyDataToLoad |= typeIdentifiersToLoad.count;
        [loadResults addObject:[WebItemProviderLoadResult loadResultWithItemProvider:itemProvider typesToLoad:typeIdentifiersToLoad]];
    }

    if (!foundAnyDataToLoad) {
        action(@[ ]);
        return;
    }

    auto setFileURLsLock = adoptNS([[NSLock alloc] init]);
    auto synchronousFileLoadingGroup = adoptOSObject(dispatch_group_create());
    auto fileLoadingGroup = adoptOSObject(dispatch_group_create());
    for (WebItemProviderLoadResult *loadResult in loadResults.get()) {
        for (NSString *typeToLoad in loadResult.typesToLoad) {
            dispatch_group_enter(fileLoadingGroup.get());
            dispatch_group_enter(synchronousFileLoadingGroup.get());
            [loadResult.itemProvider loadFileRepresentationForTypeIdentifier:typeToLoad completionHandler:[protectedLoadResult = retainPtr(loadResult), synchronousFileLoadingGroup, setFileURLsLock, protectedTypeToLoad = retainPtr(typeToLoad), fileLoadingGroup] (NSURL *url, NSError *) {
                // 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.
                // 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
                // WKFileUploadPanel.mm. The temporary files are cleaned up by the system at a later time.
                if (NSURL *destination = linkTemporaryItemProviderFilesToDropStagingDirectory(url, [protectedLoadResult itemProvider].suggestedName, protectedTypeToLoad.get())) {
                    [setFileURLsLock lock];
                    [protectedLoadResult setFileURL:destination forType:protectedTypeToLoad.get()];
                    [setFileURLsLock unlock];
                }
                dispatch_group_leave(fileLoadingGroup.get());
                dispatch_group_leave(synchronousFileLoadingGroup.get());
            }];
        }
    }

    RetainPtr<WebItemProviderPasteboard> retainedSelf = self;
    auto itemLoadCompletion = [retainedSelf, synchronousFileLoadingGroup, fileLoadingGroup, loadResults, completionBlock = makeBlockPtr(action), changeCountBeforeLoading] {
        if (changeCountBeforeLoading == retainedSelf->_changeCount) {
            for (WebItemProviderLoadResult *loadResult in loadResults.get())
                retainedSelf->_loadResults.append(loadResult);
        }

        completionBlock([retainedSelf allDroppedFileURLs]);
    };

    if (synchronousTimeout > 0 && !dispatch_group_wait(synchronousFileLoadingGroup.get(), dispatch_time(DISPATCH_TIME_NOW, synchronousTimeout * NSEC_PER_SEC))) {
        itemLoadCompletion();
        return;
    }

    dispatch_group_notify(fileLoadingGroup.get(), dispatch_get_main_queue(), itemLoadCompletion);
}

- (NSItemProvider *)itemProviderAtIndex:(NSUInteger)index
{
    return index < [_itemProviders count] ? [_itemProviders objectAtIndex:index] : nil;
}

- (BOOL)hasPendingOperation
{
    return _pendingOperationCount;
}

- (void)incrementPendingOperationCount
{
    _pendingOperationCount++;
}

- (void)decrementPendingOperationCount
{
    _pendingOperationCount--;
}

- (void)enumerateItemProvidersWithBlock:(void (^)(__kindof NSItemProvider *itemProvider, NSUInteger index, BOOL *stop))block
{
    [_itemProviders enumerateObjectsUsingBlock:block];
}

- (void)stageRegistrationLists:(NSArray<WebItemProviderRegistrationInfoList *> *)lists
{
    ASSERT(lists.count);
    _stagedRegistrationInfoLists = lists;
}

- (void)clearRegistrationLists
{
    _stagedRegistrationInfoLists = nil;
}

- (NSArray<WebItemProviderRegistrationInfoList *> *)takeRegistrationLists
{
    return _stagedRegistrationInfoLists.autorelease();
}

@end

#endif // PLATFORM(IOS_FAMILY) && ENABLE(DRAG_SUPPORT)
