/*
 * Copyright (C) 2013-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. ``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
 * 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 "PlatformPasteboard.h"

#if PLATFORM(IOS_FAMILY)

#import "Color.h"
#import "Image.h"
#import "Pasteboard.h"
#import "RuntimeApplicationChecks.h"
#import "SharedBuffer.h"
#import "UTIUtilities.h"
#import "WebItemProviderPasteboard.h"
#import <MobileCoreServices/MobileCoreServices.h>
#import <UIKit/UIColor.h>
#import <UIKit/UIImage.h>
#import <UIKit/UIPasteboard.h>
#import <pal/ios/UIKitSoftLink.h>
#import <pal/spi/cocoa/NSKeyedArchiverSPI.h>
#import <pal/spi/ios/UIKitSPI.h>
#import <wtf/ListHashSet.h>
#import <wtf/URL.h>
#import <wtf/cocoa/NSURLExtras.h>
#import <wtf/text/StringHash.h>

#define PASTEBOARD_SUPPORTS_ITEM_PROVIDERS (PLATFORM(IOS_FAMILY) && !(PLATFORM(WATCHOS) || PLATFORM(APPLETV)))
#define PASTEBOARD_SUPPORTS_PRESENTATION_STYLE_AND_TEAM_DATA (PASTEBOARD_SUPPORTS_ITEM_PROVIDERS && !PLATFORM(MACCATALYST))
#define NSURL_SUPPORTS_TITLE (!PLATFORM(MACCATALYST))

namespace WebCore {

PlatformPasteboard::PlatformPasteboard()
    : m_pasteboard([PAL::getUIPasteboardClass() generalPasteboard])
{
}

#if PASTEBOARD_SUPPORTS_ITEM_PROVIDERS
PlatformPasteboard::PlatformPasteboard(const String& name)
{
    if (name == "data interaction pasteboard")
        m_pasteboard = [WebItemProviderPasteboard sharedInstance];
    else
        m_pasteboard = [PAL::getUIPasteboardClass() generalPasteboard];
}
#else
PlatformPasteboard::PlatformPasteboard(const String&)
    : m_pasteboard([PAL::getUIPasteboardClass() generalPasteboard])
{
}
#endif

void PlatformPasteboard::getTypes(Vector<String>& types)
{
    for (NSString *pasteboardType in [m_pasteboard pasteboardTypes])
        types.append(pasteboardType);
}

RefPtr<SharedBuffer> PlatformPasteboard::bufferForType(const String& type)
{
    if (NSData *data = [m_pasteboard dataForPasteboardType:type])
        return SharedBuffer::create(data);
    return nullptr;
}

void PlatformPasteboard::getPathnamesForType(Vector<String>&, const String&) const
{
}

int PlatformPasteboard::numberOfFiles() const
{
    return [m_pasteboard respondsToSelector:@selector(numberOfFiles)] ? [m_pasteboard numberOfFiles] : 0;
}

#if PASTEBOARD_SUPPORTS_ITEM_PROVIDERS

#if PASTEBOARD_SUPPORTS_PRESENTATION_STYLE_AND_TEAM_DATA

static PasteboardItemPresentationStyle pasteboardItemPresentationStyle(UIPreferredPresentationStyle style)
{
    switch (style) {
    case UIPreferredPresentationStyleUnspecified:
        return PasteboardItemPresentationStyle::Unspecified;
    case UIPreferredPresentationStyleInline:
        return PasteboardItemPresentationStyle::Inline;
    case UIPreferredPresentationStyleAttachment:
        return PasteboardItemPresentationStyle::Attachment;
    default:
        ASSERT_NOT_REACHED();
        return PasteboardItemPresentationStyle::Unspecified;
    }
}

#endif // PASTEBOARD_SUPPORTS_PRESENTATION_STYLE_AND_TEAM_DATA

PasteboardItemInfo PlatformPasteboard::informationForItemAtIndex(size_t index)
{
    if (index >= static_cast<NSUInteger>([m_pasteboard numberOfItems]))
        return { };

    PasteboardItemInfo info;
    NSItemProvider *itemProvider = [[m_pasteboard itemProviders] objectAtIndex:index];
    if ([m_pasteboard respondsToSelector:@selector(fileUploadURLsAtIndex:fileTypes:)]) {
        NSArray<NSString *> *fileTypes = nil;
        NSArray *urls = [m_pasteboard fileUploadURLsAtIndex:index fileTypes:&fileTypes];
        ASSERT(fileTypes.count == urls.count);

        info.pathsForFileUpload.reserveInitialCapacity(urls.count);
        for (NSURL *url in urls)
            info.pathsForFileUpload.uncheckedAppend(url.path);

        info.platformTypesForFileUpload.reserveInitialCapacity(fileTypes.count);
        for (NSString *fileType in fileTypes)
            info.platformTypesForFileUpload.uncheckedAppend(fileType);
    } else {
        NSArray *fileTypes = itemProvider.web_fileUploadContentTypes;
        info.platformTypesForFileUpload.reserveInitialCapacity(fileTypes.count);
        info.pathsForFileUpload.reserveInitialCapacity(fileTypes.count);
        for (NSString *fileType in fileTypes) {
            info.platformTypesForFileUpload.uncheckedAppend(fileType);
            info.pathsForFileUpload.uncheckedAppend({ });
        }
    }

#if PASTEBOARD_SUPPORTS_PRESENTATION_STYLE_AND_TEAM_DATA
    info.preferredPresentationStyle = pasteboardItemPresentationStyle(itemProvider.preferredPresentationStyle);
#endif
    if (!CGSizeEqualToSize(itemProvider.preferredPresentationSize, CGSizeZero)) {
        auto adjustedPreferredPresentationHeight = [](auto height) -> Optional<double> {
            if (!IOSApplication::isMobileMail() && !IOSApplication::isMailCompositionService())
                return { height };
            // Mail's max-width: 100%; default style is in conflict with the preferred presentation size and can lead to unexpectedly stretched images. Not setting the height forces layout to preserve the aspect ratio.
            return { };
        };
        info.preferredPresentationSize = PresentationSize { itemProvider.preferredPresentationSize.width, adjustedPreferredPresentationHeight(itemProvider.preferredPresentationSize.height) };
    }
    info.containsFileURLAndFileUploadContent = itemProvider.web_containsFileURLAndFileUploadContent;
    info.suggestedFileName = itemProvider.suggestedName;
    NSArray<NSString *> *registeredTypeIdentifiers = itemProvider.registeredTypeIdentifiers;
    info.platformTypesByFidelity.reserveInitialCapacity(registeredTypeIdentifiers.count);
    for (NSString *typeIdentifier in registeredTypeIdentifiers) {
        info.platformTypesByFidelity.uncheckedAppend(typeIdentifier);
        CFStringRef cfTypeIdentifier = (CFStringRef)typeIdentifier;
        if (!UTTypeIsDeclared(cfTypeIdentifier))
            continue;

        if (UTTypeConformsTo(cfTypeIdentifier, kUTTypeText))
            continue;

        if (UTTypeConformsTo(cfTypeIdentifier, kUTTypeURL))
            continue;

        if (UTTypeConformsTo(cfTypeIdentifier, kUTTypeRTFD))
            continue;

        if (UTTypeConformsTo(cfTypeIdentifier, kUTTypeFlatRTFD))
            continue;

        info.isNonTextType = true;
    }

    info.changeCount = changeCount();

    return info;
}

#else

PasteboardItemInfo PlatformPasteboard::informationForItemAtIndex(size_t)
{
    return { };
}

#endif

static bool pasteboardMayContainFilePaths(id<AbstractPasteboard> pasteboard)
{
#if PASTEBOARD_SUPPORTS_ITEM_PROVIDERS
    if ([pasteboard isKindOfClass:[WebItemProviderPasteboard class]])
        return false;
#endif

    for (NSString *type in pasteboard.pasteboardTypes) {
        if (Pasteboard::shouldTreatCocoaTypeAsFile(type))
            return true;
    }
    return false;
}

String PlatformPasteboard::stringForType(const String& type) const
{
    auto result = readString(0, type);

    if (pasteboardMayContainFilePaths(m_pasteboard.get()) && type == String { kUTTypeURL }) {
        if (!Pasteboard::canExposeURLToDOMWhenPasteboardContainsFiles(result))
            result = { };
    }

    return result;
}

Color PlatformPasteboard::color()
{
    NSData *data = [m_pasteboard dataForPasteboardType:UIColorPboardType];
    UIColor *uiColor = [NSKeyedUnarchiver unarchivedObjectOfClass:PAL::getUIColorClass() fromData:data error:nil];
    return Color(uiColor.CGColor);
}

URL PlatformPasteboard::url()
{
    return URL();
}

long PlatformPasteboard::copy(const String&)
{
    return 0;
}

long PlatformPasteboard::addTypes(const Vector<String>&)
{
    return 0;
}

long PlatformPasteboard::setTypes(const Vector<String>&)
{
    return 0;
}

long PlatformPasteboard::setBufferForType(SharedBuffer*, const String&)
{
    return 0;
}

long PlatformPasteboard::setURL(const PasteboardURL&)
{
    return 0;
}

long PlatformPasteboard::setStringForType(const String&, const String&)
{
    return 0;
}

long PlatformPasteboard::changeCount() const
{
    return [(id<AbstractPasteboard>)m_pasteboard.get() changeCount];
}

String PlatformPasteboard::uniqueName()
{
    return String();
}

String PlatformPasteboard::platformPasteboardTypeForSafeTypeForDOMToReadAndWrite(const String& domType)
{
    if (domType == "text/plain")
        return kUTTypePlainText;

    if (domType == "text/html")
        return kUTTypeHTML;

    if (domType == "text/uri-list")
        return kUTTypeURL;

    return { };
}

#if PASTEBOARD_SUPPORTS_ITEM_PROVIDERS

static NSString *webIOSPastePboardType = @"iOS rich content paste pasteboard type";

static void registerItemToPasteboard(WebItemProviderRegistrationInfoList *representationsToRegister, id <AbstractPasteboard> pasteboard)
{
#if PLATFORM(MACCATALYST)
    // In macCatalyst, -[UIPasteboard setItemProviders:] is not yet supported, so we fall back to setting an item dictionary when
    // populating the pasteboard upon copy.
    if ([pasteboard isKindOfClass:PAL::getUIPasteboardClass()]) {
        auto itemDictionary = adoptNS([[NSMutableDictionary alloc] init]);
        [representationsToRegister enumerateItems:[itemDictionary] (id <WebItemProviderRegistrar> item, NSUInteger) {
            if ([item respondsToSelector:@selector(typeIdentifierForClient)] && [item respondsToSelector:@selector(dataForClient)])
                [itemDictionary setObject:item.dataForClient forKey:item.typeIdentifierForClient];
        }];
        [pasteboard setItems:@[ itemDictionary.get() ]];
        return;
    }
#endif // PLATFORM(MACCATALYST)

    if (NSItemProvider *itemProvider = representationsToRegister.itemProvider)
        [pasteboard setItemProviders:@[ itemProvider ]];
    else
        [pasteboard setItemProviders:@[ ]];

    if ([pasteboard respondsToSelector:@selector(stageRegistrationList:)])
        [pasteboard stageRegistrationList:representationsToRegister];
}

long PlatformPasteboard::setColor(const Color& color)
{
    auto representationsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);
    UIColor *uiColor = [PAL::getUIColorClass() colorWithCGColor:cachedCGColor(color)];
    [representationsToRegister addData:[NSKeyedArchiver archivedDataWithRootObject:uiColor requiringSecureCoding:NO error:nil] forType:UIColorPboardType];
    registerItemToPasteboard(representationsToRegister.get(), m_pasteboard.get());
    return 0;
}

static void addRepresentationsForPlainText(WebItemProviderRegistrationInfoList *itemsToRegister, const String& plainText)
{
    if (plainText.isEmpty())
        return;

    NSURL *platformURL = [NSURL URLWithString:plainText];
    if (URL(platformURL).isValid())
        [itemsToRegister addRepresentingObject:platformURL];

    [itemsToRegister addData:[(NSString *)plainText dataUsingEncoding:NSUTF8StringEncoding] forType:(NSString *)kUTTypeUTF8PlainText];
}

bool PlatformPasteboard::allowReadingURLAtIndex(const URL& url, int index) const
{
    NSItemProvider *itemProvider = (NSUInteger)index < [m_pasteboard itemProviders].count ? [[m_pasteboard itemProviders] objectAtIndex:index] : nil;
    for (NSString *type in itemProvider.registeredTypeIdentifiers) {
        if (UTTypeConformsTo((CFStringRef)type, kUTTypeURL))
            return true;
    }

    return url.isValid();
}

void PlatformPasteboard::write(const PasteboardWebContent& content)
{
    auto representationsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);

#if !PLATFORM(MACCATALYST)
    [representationsToRegister addData:[webIOSPastePboardType dataUsingEncoding:NSUTF8StringEncoding] forType:webIOSPastePboardType];
#endif

    ASSERT(content.clientTypes.size() == content.clientData.size());
    for (size_t i = 0, size = content.clientTypes.size(); i < size; ++i)
        [representationsToRegister addData:content.clientData[i]->createNSData().get() forType:content.clientTypes[i]];

    if (content.dataInWebArchiveFormat) {
        auto webArchiveData = content.dataInWebArchiveFormat->createNSData();
#if PLATFORM(MACCATALYST)
        NSString *webArchiveType = (__bridge NSString *)kUTTypeWebArchive;
#else
        // FIXME: We should additionally register "com.apple.webarchive" once <rdar://problem/46830277> is fixed.
        NSString *webArchiveType = WebArchivePboardType;
#endif
        [representationsToRegister addData:webArchiveData.get() forType:webArchiveType];
    }

    if (content.dataInAttributedStringFormat) {
        NSAttributedString *attributedString = unarchivedObjectOfClassesFromData([NSSet setWithObject:[NSAttributedString class]], content.dataInAttributedStringFormat->createNSData().get());
        if (attributedString)
            [representationsToRegister addRepresentingObject:attributedString];
    }

    if (content.dataInRTFDFormat)
        [representationsToRegister addData:content.dataInRTFDFormat->createNSData().get() forType:(NSString *)kUTTypeFlatRTFD];

    if (content.dataInRTFFormat)
        [representationsToRegister addData:content.dataInRTFFormat->createNSData().get() forType:(NSString *)kUTTypeRTF];

    if (!content.dataInHTMLFormat.isEmpty()) {
        NSData *htmlAsData = [(NSString *)content.dataInHTMLFormat dataUsingEncoding:NSUTF8StringEncoding];
        [representationsToRegister addData:htmlAsData forType:(NSString *)kUTTypeHTML];
    }

    if (!content.dataInStringFormat.isEmpty())
        addRepresentationsForPlainText(representationsToRegister.get(), content.dataInStringFormat);

    PasteboardCustomData customData;
    customData.origin = content.contentOrigin;
    [representationsToRegister addData:customData.createSharedBuffer()->createNSData().get() forType:@(PasteboardCustomData::cocoaType())];

    registerItemToPasteboard(representationsToRegister.get(), m_pasteboard.get());
}

void PlatformPasteboard::write(const PasteboardImage& pasteboardImage)
{
    auto representationsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);

    auto& types = pasteboardImage.clientTypes;
    auto& data = pasteboardImage.clientData;
    ASSERT(types.size() == data.size());
    for (size_t i = 0, size = types.size(); i < size; ++i)
        [representationsToRegister addData:data[i]->createNSData().get() forType:types[i]];

    if (pasteboardImage.resourceData && !pasteboardImage.resourceMIMEType.isEmpty()) {
        auto utiOrMIMEType = pasteboardImage.resourceMIMEType;
        if (!isDeclaredUTI(utiOrMIMEType))
            utiOrMIMEType = UTIFromMIMEType(utiOrMIMEType);

        auto imageData = pasteboardImage.resourceData->createNSData();
        [representationsToRegister addData:imageData.get() forType:(NSString *)utiOrMIMEType];
        [representationsToRegister setPreferredPresentationSize:pasteboardImage.imageSize];
        [representationsToRegister setSuggestedName:pasteboardImage.suggestedName];
    }

    // FIXME: When writing a PasteboardImage, we currently always place the image data at a higer fidelity than the
    // associated image URL. However, in the case of an image enclosed by an anchor, we might want to consider the
    // the URL (i.e. the anchor's href attribute) to be a higher fidelity representation.
    auto& pasteboardURL = pasteboardImage.url;
    if (NSURL *nsURL = pasteboardURL.url) {
#if NSURL_SUPPORTS_TITLE
        nsURL._title = pasteboardURL.title.isEmpty() ? WTF::userVisibleString(pasteboardURL.url) : (NSString *)pasteboardURL.title;
#endif
        [representationsToRegister addRepresentingObject:nsURL];
    }

    registerItemToPasteboard(representationsToRegister.get(), m_pasteboard.get());
}

void PlatformPasteboard::write(const String& pasteboardType, const String& text)
{
    auto representationsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);
    [representationsToRegister setPreferredPresentationStyle:WebPreferredPresentationStyleInline];

    NSString *pasteboardTypeAsNSString = pasteboardType;
    if (!text.isEmpty() && pasteboardTypeAsNSString.length) {
        auto pasteboardTypeAsCFString = (CFStringRef)pasteboardTypeAsNSString;
        if (UTTypeConformsTo(pasteboardTypeAsCFString, kUTTypeURL) || UTTypeConformsTo(pasteboardTypeAsCFString, kUTTypeText))
            addRepresentationsForPlainText(representationsToRegister.get(), text);
        else
            [representationsToRegister addData:[pasteboardTypeAsNSString dataUsingEncoding:NSUTF8StringEncoding] forType:pasteboardType];
    }

    registerItemToPasteboard(representationsToRegister.get(), m_pasteboard.get());
}

void PlatformPasteboard::write(const PasteboardURL& url)
{
    auto representationsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);
    [representationsToRegister setPreferredPresentationStyle:WebPreferredPresentationStyleInline];

    if (NSURL *nsURL = url.url) {
#if NSURL_SUPPORTS_TITLE
        if (!url.title.isEmpty())
            nsURL._title = url.title;
#endif
        [representationsToRegister addRepresentingObject:nsURL];
        [representationsToRegister addRepresentingObject:(NSString *)url.url.string()];
    }

    registerItemToPasteboard(representationsToRegister.get(), m_pasteboard.get());
}

static const char *safeTypeForDOMToReadAndWriteForPlatformType(const String& platformType)
{
    auto cfType = platformType.createCFString();
    if (UTTypeConformsTo(cfType.get(), kUTTypePlainText))
        return "text/plain"_s;

    if (UTTypeConformsTo(cfType.get(), kUTTypeHTML) || UTTypeConformsTo(cfType.get(), (CFStringRef)WebArchivePboardType)
        || UTTypeConformsTo(cfType.get(), kUTTypeRTF) || UTTypeConformsTo(cfType.get(), kUTTypeFlatRTFD))
        return "text/html"_s;

    if (UTTypeConformsTo(cfType.get(), kUTTypeURL))
        return "text/uri-list"_s;

    return nullptr;
}

static const char originKeyForTeamData[] = "com.apple.WebKit.drag-and-drop-team-data.origin";
static const char customTypesKeyForTeamData[] = "com.apple.WebKit.drag-and-drop-team-data.custom-types";

Vector<String> PlatformPasteboard::typesSafeForDOMToReadAndWrite(const String& origin) const
{
    ListHashSet<String> domPasteboardTypes;
#if PASTEBOARD_SUPPORTS_PRESENTATION_STYLE_AND_TEAM_DATA
    for (NSItemProvider *provider in [m_pasteboard itemProviders]) {
        if (!provider.teamData.length)
            continue;

        NSDictionary *teamDataObject = unarchivedObjectOfClassesFromData([NSSet setWithObjects:[NSDictionary class], [NSString class], [NSArray class], nil], provider.teamData);
        if (!teamDataObject)
            continue;

        id originInTeamData = [teamDataObject objectForKey:@(originKeyForTeamData)];
        if (![originInTeamData isKindOfClass:[NSString class]])
            continue;
        if (String((NSString *)originInTeamData) != origin)
            continue;

        id customTypes = [(NSDictionary *)teamDataObject objectForKey:@(customTypesKeyForTeamData)];
        if (![customTypes isKindOfClass:[NSArray class]])
            continue;

        for (NSString *type in customTypes)
            domPasteboardTypes.add(type);
    }
#endif // PASTEBOARD_SUPPORTS_PRESENTATION_STYLE_AND_TEAM_DATA

    if (NSData *serializedCustomData = [m_pasteboard dataForPasteboardType:@(PasteboardCustomData::cocoaType())]) {
        auto data = PasteboardCustomData::fromSharedBuffer(SharedBuffer::create(serializedCustomData).get());
        if (data.origin == origin) {
            for (auto& type : data.orderedTypes)
                domPasteboardTypes.add(type);
        }
    }

    for (NSString *type in [m_pasteboard pasteboardTypes]) {
        if ([type isEqualToString:@(PasteboardCustomData::cocoaType())])
            continue;

        if (Pasteboard::isSafeTypeForDOMToReadAndWrite(type)) {
            domPasteboardTypes.add(type);
            continue;
        }

        if (auto* coercedType = safeTypeForDOMToReadAndWriteForPlatformType(type)) {
            auto domTypeAsString = String::fromUTF8(coercedType);
            if (domTypeAsString == "text/uri-list") {
                BOOL ableToDetermineProtocolOfPasteboardURL = ![m_pasteboard isKindOfClass:[WebItemProviderPasteboard class]];
                if (ableToDetermineProtocolOfPasteboardURL && stringForType(kUTTypeURL).isEmpty())
                    continue;

                if ([[m_pasteboard pasteboardTypes] containsObject:(__bridge NSString *)kUTTypeFileURL])
                    continue;
            }
            domPasteboardTypes.add(WTFMove(domTypeAsString));
        }
    }

    return copyToVector(domPasteboardTypes);
}

long PlatformPasteboard::write(const PasteboardCustomData& data)
{
    auto representationsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);
    [representationsToRegister setPreferredPresentationStyle:WebPreferredPresentationStyleInline];

    if (data.sameOriginCustomData.size()) {
        if (auto serializedSharedBuffer = data.createSharedBuffer()->createNSData()) {
            // We stash the list of supplied pasteboard types in teamData here for compatibility with drag and drop.
            // Since the contents of item providers cannot be loaded prior to drop, but the pasteboard types are
            // contained within the custom data blob and we need to vend them to the page when firing `dragover`
            // events, we need an additional in-memory representation of the pasteboard types array that contains
            // all of the custom types. We use the teamData property, available on NSItemProvider on iOS, to store
            // this information, since the contents of teamData are immediately available prior to the drop.
            NSMutableArray<NSString *> *typesAsNSArray = [NSMutableArray array];
            for (auto& type : data.orderedTypes)
                [typesAsNSArray addObject:type];
            [representationsToRegister setTeamData:securelyArchivedDataWithRootObject(@{ @(originKeyForTeamData) : data.origin, @(customTypesKeyForTeamData) : typesAsNSArray })];
            [representationsToRegister addData:serializedSharedBuffer.get() forType:@(PasteboardCustomData::cocoaType())];
        }
    }

    for (auto& type : data.orderedTypes) {
        NSString *stringValue = data.platformData.get(type);
        if (!stringValue.length)
            continue;

        auto cocoaType = platformPasteboardTypeForSafeTypeForDOMToReadAndWrite(type).createCFString();
        if (UTTypeConformsTo(cocoaType.get(), kUTTypeURL))
            [representationsToRegister addRepresentingObject:[NSURL URLWithString:stringValue]];
        else if (UTTypeConformsTo(cocoaType.get(), kUTTypePlainText))
            [representationsToRegister addRepresentingObject:stringValue];
        else
            [representationsToRegister addData:[stringValue dataUsingEncoding:NSUTF8StringEncoding] forType:(NSString *)cocoaType.get()];
    }

    registerItemToPasteboard(representationsToRegister.get(), m_pasteboard.get());
    return [(id<AbstractPasteboard>)m_pasteboard.get() changeCount];
}

#else

long PlatformPasteboard::setColor(const Color&)
{
    return 0;
}

bool PlatformPasteboard::allowReadingURLAtIndex(const URL&, int) const
{
    return false;
}

void PlatformPasteboard::write(const PasteboardWebContent&)
{
}

void PlatformPasteboard::write(const PasteboardImage&)
{
}

void PlatformPasteboard::write(const String&, const String&)
{
}

void PlatformPasteboard::write(const PasteboardURL&)
{
}

Vector<String> PlatformPasteboard::typesSafeForDOMToReadAndWrite(const String&) const
{
    return { };
}

long PlatformPasteboard::write(const PasteboardCustomData&)
{
    return 0;
}

#endif

int PlatformPasteboard::count() const
{
    return [m_pasteboard numberOfItems];
}

Vector<String> PlatformPasteboard::allStringsForType(const String& type) const
{
    auto numberOfItems = count();
    Vector<String> strings;
    strings.reserveInitialCapacity(numberOfItems);
    for (int index = 0; index < numberOfItems; ++index) {
        String value = readString(index, type);
        if (!value.isEmpty())
            strings.uncheckedAppend(WTFMove(value));
    }
    return strings;
}

RefPtr<SharedBuffer> PlatformPasteboard::readBuffer(size_t index, const String& type) const
{
    NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:index];

    RetainPtr<NSArray> pasteboardItem = [m_pasteboard dataForPasteboardType:type inItemSet:indexSet];

    if (![pasteboardItem count])
        return nullptr;
    return SharedBuffer::create([pasteboardItem.get() objectAtIndex:0]);
}

String PlatformPasteboard::readString(size_t index, const String& type) const
{
    if (type == String(kUTTypeURL)) {
        String title;
        return [(NSURL *)readURL(index, title) absoluteString];
    }

    NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:index];
    auto value = retainPtr([m_pasteboard valuesForPasteboardType:type inItemSet:indexSet].firstObject ?: [m_pasteboard dataForPasteboardType:type inItemSet:indexSet].firstObject);
    if (!value)
        return { };

    if ([value isKindOfClass:[NSData class]])
        value = adoptNS([[NSString alloc] initWithData:(NSData *)value.get() encoding:NSUTF8StringEncoding]);
    
    if (type == String(kUTTypePlainText) || type == String(kUTTypeHTML)) {
        ASSERT([value isKindOfClass:[NSString class]]);
        return [value isKindOfClass:[NSString class]] ? value.get() : nil;
    }
    if (type == String(kUTTypeText)) {
        ASSERT([value isKindOfClass:[NSString class]] || [value isKindOfClass:[NSAttributedString class]]);
        if ([value isKindOfClass:[NSString class]])
            return value.get();
        if ([value isKindOfClass:[NSAttributedString class]])
            return [(NSAttributedString *)value string];
    }

    return String();
}

URL PlatformPasteboard::readURL(size_t index, String& title) const
{
    id value = [m_pasteboard valuesForPasteboardType:(__bridge NSString *)kUTTypeURL inItemSet:[NSIndexSet indexSetWithIndex:index]].firstObject;
    if (!value)
        return { };

    ASSERT([value isKindOfClass:[NSURL class]]);
    if (![value isKindOfClass:[NSURL class]])
        return { };

    NSURL *url = (NSURL *)value;
    if (!allowReadingURLAtIndex(url, index))
        return { };

#if PASTEBOARD_SUPPORTS_ITEM_PROVIDERS && NSURL_SUPPORTS_TITLE
    title = [url _title];
#else
    UNUSED_PARAM(title);
#endif

    return url;
}

void PlatformPasteboard::updateSupportedTypeIdentifiers(const Vector<String>& types)
{
    if (![m_pasteboard respondsToSelector:@selector(updateSupportedTypeIdentifiers:)])
        return;

    NSMutableArray *typesArray = [NSMutableArray arrayWithCapacity:types.size()];
    for (const auto& type : types)
        [typesArray addObject:(NSString *)type];

    [m_pasteboard updateSupportedTypeIdentifiers:typesArray];
}

}

#endif // PLATFORM(IOS_FAMILY)
