/*
 * Copyright (C) 2006-2020 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. 
 */

#include "config.h"
#include "DataTransfer.h"

#include "CachedImage.h"
#include "CachedImageClient.h"
#include "DataTransferItem.h"
#include "DataTransferItemList.h"
#include "DocumentFragment.h"
#include "DragData.h"
#include "Editor.h"
#include "FileList.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "HTMLImageElement.h"
#include "HTMLParserIdioms.h"
#include "Image.h"
#include "PagePasteboardContext.h"
#include "Pasteboard.h"
#include "RuntimeEnabledFeatures.h"
#include "Settings.h"
#include "StaticPasteboard.h"
#include "WebContentReader.h"
#include "WebCorePasteboardFileReader.h"
#include "markup.h"
#include <wtf/URLParser.h>
#include <wtf/unicode/CharacterNames.h>

namespace WebCore {

#if ENABLE(DRAG_SUPPORT)

class DragImageLoader final : private CachedImageClient {
    WTF_MAKE_NONCOPYABLE(DragImageLoader); WTF_MAKE_FAST_ALLOCATED;
public:
    explicit DragImageLoader(DataTransfer*);
    void startLoading(CachedResourceHandle<CachedImage>&);
    void stopLoading(CachedResourceHandle<CachedImage>&);
    void moveToDataTransfer(DataTransfer&);

private:
    void imageChanged(CachedImage*, const IntRect*) override;
    DataTransfer* m_dataTransfer;
};

#endif

DataTransfer::DataTransfer(StoreMode mode, std::unique_ptr<Pasteboard> pasteboard, Type type, String&& effectAllowed)
    : m_storeMode(mode)
    , m_pasteboard(WTFMove(pasteboard))
#if ENABLE(DRAG_SUPPORT)
    , m_type(type)
    , m_dropEffect("uninitialized"_s)
    , m_effectAllowed(WTFMove(effectAllowed))
    , m_shouldUpdateDragImage(false)
#endif
{
#if !ENABLE(DRAG_SUPPORT)
    UNUSED_PARAM(effectAllowed);
    ASSERT_UNUSED(type, type != Type::DragAndDropData && type != Type::DragAndDropFiles);
#endif
}

Ref<DataTransfer> DataTransfer::createForCopyAndPaste(const Document& document, StoreMode storeMode, std::unique_ptr<Pasteboard>&& pasteboard)
{
    auto dataTransfer = adoptRef(*new DataTransfer(storeMode, WTFMove(pasteboard)));
    dataTransfer->m_originIdentifier = document.originIdentifierForPasteboard();
    return dataTransfer;
}

Ref<DataTransfer> DataTransfer::create()
{
    return adoptRef(*new DataTransfer(StoreMode::ReadWrite, makeUnique<StaticPasteboard>(), Type::CopyAndPaste, "none"_s));
}

DataTransfer::~DataTransfer()
{
#if ENABLE(DRAG_SUPPORT)
    if (m_dragImageLoader && m_dragImage)
        m_dragImageLoader->stopLoading(m_dragImage);
#endif
}

bool DataTransfer::canReadTypes() const
{
    return m_storeMode == StoreMode::Readonly || m_storeMode == StoreMode::Protected || m_storeMode == StoreMode::ReadWrite;
}

bool DataTransfer::canReadData() const
{
    return m_storeMode == StoreMode::Readonly || m_storeMode == StoreMode::ReadWrite;
}

bool DataTransfer::canWriteData() const
{
    return m_storeMode == StoreMode::ReadWrite;
}

static String normalizeType(const String& type)
{
    if (type.isNull())
        return type;

    String lowercaseType = stripLeadingAndTrailingHTMLSpaces(type).convertToASCIILowercase();
    if (lowercaseType == "text" || lowercaseType.startsWith("text/plain;"))
        return "text/plain";
    if (lowercaseType == "url" || lowercaseType.startsWith("text/uri-list;"))
        return "text/uri-list";
    if (lowercaseType.startsWith("text/html;"))
        return "text/html";

    return lowercaseType;
}

void DataTransfer::clearData(const String& type)
{
    if (!canWriteData())
        return;

    String normalizedType = normalizeType(type);
    if (normalizedType.isNull())
        m_pasteboard->clear();
    else
        m_pasteboard->clear(normalizedType);
    if (m_itemList)
        m_itemList->didClearStringData(normalizedType);
}

static String readURLsFromPasteboardAsString(Pasteboard& pasteboard, Function<bool(const String&)>&& shouldIncludeURL)
{
    StringBuilder urlList;
    for (const auto& urlString : pasteboard.readAllStrings("text/uri-list"_s)) {
        if (!shouldIncludeURL(urlString))
            continue;
        if (!urlList.isEmpty())
            urlList.append(newlineCharacter);
        urlList.append(urlString);
    }
    return urlList.toString();
}

String DataTransfer::getDataForItem(Document& document, const String& type) const
{
    if (!canReadData())
        return { };

    auto lowercaseType = stripLeadingAndTrailingHTMLSpaces(type).convertToASCIILowercase();
    if (shouldSuppressGetAndSetDataToAvoidExposingFilePaths()) {
        if (lowercaseType == "text/uri-list") {
            return readURLsFromPasteboardAsString(*m_pasteboard, [] (auto& urlString) {
                return Pasteboard::canExposeURLToDOMWhenPasteboardContainsFiles(urlString);
            });
        }

        if (lowercaseType == "text/html" && RuntimeEnabledFeatures::sharedFeatures().customPasteboardDataEnabled()) {
            // If the pasteboard contains files and the page requests 'text/html', we only read from rich text types to prevent file
            // paths from leaking (e.g. from plain text data on the pasteboard) since we sanitize cross-origin markup. However, if
            // custom pasteboard data is disabled, then we can't ensure that the markup we deliver is sanitized, so we fall back to
            // current behavior and return an empty string.
            return readStringFromPasteboard(document, lowercaseType, WebContentReadingPolicy::OnlyRichTextTypes);
        }

        return { };
    }

    return readStringFromPasteboard(document, lowercaseType, WebContentReadingPolicy::AnyType);
}

String DataTransfer::readStringFromPasteboard(Document& document, const String& lowercaseType, WebContentReadingPolicy policy) const
{
    if (!RuntimeEnabledFeatures::sharedFeatures().customPasteboardDataEnabled())
        return m_pasteboard->readString(lowercaseType);

    // StaticPasteboard is only used to stage data written by websites before being committed to the system pasteboard.
    bool isSameOrigin = is<StaticPasteboard>(*m_pasteboard) || (!m_originIdentifier.isNull() && m_originIdentifier == m_pasteboard->readOrigin());
    if (isSameOrigin) {
        String value = m_pasteboard->readStringInCustomData(lowercaseType);
        if (!value.isNull())
            return value;
    }
    if (!Pasteboard::isSafeTypeForDOMToReadAndWrite(lowercaseType))
        return { };

    if (!is<StaticPasteboard>(*m_pasteboard) && lowercaseType == "text/html") {
        if (!document.frame())
            return { };
        WebContentMarkupReader reader { *document.frame() };
        m_pasteboard->read(reader, policy);
        return reader.markup;
    }

    if (!is<StaticPasteboard>(*m_pasteboard) && lowercaseType == "text/uri-list") {
        return readURLsFromPasteboardAsString(*m_pasteboard, [] (auto&) {
            return true;
        });
    }

    return m_pasteboard->readString(lowercaseType);
}

String DataTransfer::getData(Document& document, const String& type) const
{
    return getDataForItem(document, normalizeType(type));
}

bool DataTransfer::shouldSuppressGetAndSetDataToAvoidExposingFilePaths() const
{
    if (!forFileDrag() && !RuntimeEnabledFeatures::sharedFeatures().customPasteboardDataEnabled())
        return false;
    return m_pasteboard->fileContentState() == Pasteboard::FileContentState::MayContainFilePaths;
}

void DataTransfer::setData(const String& type, const String& data)
{
    if (!canWriteData())
        return;

    if (shouldSuppressGetAndSetDataToAvoidExposingFilePaths())
        return;

    auto normalizedType = normalizeType(type);
    setDataFromItemList(normalizedType, data);
    if (m_itemList)
        m_itemList->didSetStringData(normalizedType);
}

void DataTransfer::setDataFromItemList(const String& type, const String& data)
{
    ASSERT(canWriteData());
    RELEASE_ASSERT(is<StaticPasteboard>(*m_pasteboard));

    if (!RuntimeEnabledFeatures::sharedFeatures().customPasteboardDataEnabled()) {
        m_pasteboard->writeString(type, data);
        return;
    }

    String sanitizedData;
    if (type == "text/html")
        sanitizedData = sanitizeMarkup(data);
    else if (type == "text/uri-list") {
        auto url = URL({ }, data);
        if (url.isValid())
            sanitizedData = url.string();
    } else if (type == "text/plain")
        sanitizedData = data; // Nothing to sanitize.

    if (sanitizedData != data)
        downcast<StaticPasteboard>(*m_pasteboard).writeStringInCustomData(type, data);

    if (Pasteboard::isSafeTypeForDOMToReadAndWrite(type) && !sanitizedData.isNull())
        m_pasteboard->writeString(type, sanitizedData);
}

void DataTransfer::updateFileList(ScriptExecutionContext* context)
{
    ASSERT(canWriteData());

    m_fileList->m_files = filesFromPasteboardAndItemList(context);
}

void DataTransfer::didAddFileToItemList()
{
    ASSERT(canWriteData());
    if (!m_fileList)
        return;

    auto& newItem = m_itemList->items().last();
    ASSERT(newItem->isFile());
    m_fileList->append(*newItem->file());
}

DataTransferItemList& DataTransfer::items(Document& document)
{
    if (!m_itemList)
        m_itemList = makeUnique<DataTransferItemList>(document, *this);
    return *m_itemList;
}

Vector<String> DataTransfer::types() const
{
    return types(AddFilesType::Yes);
}

Vector<String> DataTransfer::typesForItemList() const
{
    return types(AddFilesType::No);
}

Vector<String> DataTransfer::types(AddFilesType addFilesType) const
{
    if (!canReadTypes())
        return { };
    
    if (!RuntimeEnabledFeatures::sharedFeatures().customPasteboardDataEnabled()) {
        auto types = m_pasteboard->typesForLegacyUnsafeBindings();
        ASSERT(!types.contains("Files"));
        if (m_pasteboard->fileContentState() != Pasteboard::FileContentState::NoFileOrImageData && addFilesType == AddFilesType::Yes)
            types.append("Files");
        return types;
    }

    auto safeTypes = m_pasteboard->typesSafeForBindings(m_originIdentifier);
    bool hasFileBackedItem = m_itemList && m_itemList->hasItems() && notFound != m_itemList->items().findMatching([] (const auto& item) {
        return item->isFile();
    });

    auto fileContentState = m_pasteboard->fileContentState();
    if (hasFileBackedItem || fileContentState != Pasteboard::FileContentState::NoFileOrImageData) {
        Vector<String> types;
        if (addFilesType == AddFilesType::Yes)
            types.append("Files"_s);

        if (fileContentState != Pasteboard::FileContentState::MayContainFilePaths) {
            types.appendVector(WTFMove(safeTypes));
            return types;
        }

        if (safeTypes.contains("text/uri-list"))
            types.append("text/uri-list"_s);
        if (safeTypes.contains("text/html") && RuntimeEnabledFeatures::sharedFeatures().customPasteboardDataEnabled())
            types.append("text/html"_s);
        return types;
    }

    ASSERT(!safeTypes.contains("Files"));
    return safeTypes;
}

Vector<Ref<File>> DataTransfer::filesFromPasteboardAndItemList(ScriptExecutionContext* context) const
{
    bool addedFilesFromPasteboard = false;
    Vector<Ref<File>> files;
    if ((!forDrag() || forFileDrag()) && m_pasteboard->fileContentState() != Pasteboard::FileContentState::NoFileOrImageData) {
        WebCorePasteboardFileReader reader(context);
        m_pasteboard->read(reader);
        files = WTFMove(reader.files);
        addedFilesFromPasteboard = !files.isEmpty();
    }

    bool itemListContainsItems = false;
    if (m_itemList && m_itemList->hasItems()) {
        for (auto& item : m_itemList->items()) {
            if (auto file = item->file())
                files.append(file.releaseNonNull());
        }
        itemListContainsItems = true;
    }

    bool containsItemsAndFiles = itemListContainsItems && addedFilesFromPasteboard;
    ASSERT_UNUSED(containsItemsAndFiles, !containsItemsAndFiles);
    return files;
}

FileList& DataTransfer::files(Document* document) const
{
    if (!canReadData()) {
        if (m_fileList)
            m_fileList->clear();
        else
            m_fileList = FileList::create();
        return *m_fileList;
    }

    if (!m_fileList)
        m_fileList = FileList::create(filesFromPasteboardAndItemList(document));

    return *m_fileList;
}

FileList& DataTransfer::files(Document& document) const
{
    return files(&document);
}

struct PasteboardFileTypeReader final : PasteboardFileReader {
    void readFilename(const String& filename)
    {
        types.add(File::contentTypeForFile(filename));
    }

    void readBuffer(const String&, const String& type, Ref<SharedBuffer>&&)
    {
        types.add(type);
    }

    HashSet<String, ASCIICaseInsensitiveHash> types;
};

bool DataTransfer::hasFileOfType(const String& type)
{
    ASSERT_WITH_SECURITY_IMPLICATION(canReadTypes());
    PasteboardFileTypeReader reader;
    m_pasteboard->read(reader);
    return reader.types.contains(type);
}

bool DataTransfer::hasStringOfType(const String& type)
{
    ASSERT_WITH_SECURITY_IMPLICATION(canReadTypes());

    return !type.isNull() && types().contains(type);
}

Ref<DataTransfer> DataTransfer::createForInputEvent(const String& plainText, const String& htmlText)
{
    auto pasteboard = makeUnique<StaticPasteboard>();
    pasteboard->writeString("text/plain"_s, plainText);
    pasteboard->writeString("text/html"_s, htmlText);
    return adoptRef(*new DataTransfer(StoreMode::Readonly, WTFMove(pasteboard), Type::InputEvent));
}

void DataTransfer::commitToPasteboard(Pasteboard& nativePasteboard)
{
    ASSERT(is<StaticPasteboard>(*m_pasteboard) && !is<StaticPasteboard>(nativePasteboard));
    auto& staticPasteboard = downcast<StaticPasteboard>(*m_pasteboard);
    if (!staticPasteboard.hasNonDefaultData()) {
        // We clear the platform pasteboard here to ensure that the pasteboard doesn't contain any data
        // that may have been written before starting the drag or copying, and after ending the last
        // drag session or paste. After pushing the static pasteboard's contents to the platform, the
        // pasteboard should only contain data that was in the static pasteboard.
        nativePasteboard.clear();
        return;
    }

    auto customData = staticPasteboard.takeCustomData();
    if (RuntimeEnabledFeatures::sharedFeatures().customPasteboardDataEnabled()) {
        customData.setOrigin(m_originIdentifier);
        nativePasteboard.writeCustomData({ customData });
        return;
    }

    nativePasteboard.clear();
    customData.forEachPlatformString([&] (auto& type, auto& string) {
        nativePasteboard.writeString(type, string);
    });

    customData.forEachCustomString([&] (auto& type, auto& string) {
        nativePasteboard.writeString(type, string);
    });
}

#if !ENABLE(DRAG_SUPPORT)

String DataTransfer::dropEffect() const
{
    return "none"_s;
}

void DataTransfer::setDropEffect(const String&)
{
}

String DataTransfer::effectAllowed() const
{
    return "uninitialized"_s;
}

void DataTransfer::setEffectAllowed(const String&)
{
}

void DataTransfer::setDragImage(Element&, int, int)
{
}

#else

Ref<DataTransfer> DataTransfer::createForDrag(const Document& document)
{
    return adoptRef(*new DataTransfer(StoreMode::ReadWrite, Pasteboard::createForDragAndDrop(PagePasteboardContext::create(document.pageID())), Type::DragAndDropData));
}

Ref<DataTransfer> DataTransfer::createForDragStartEvent(const Document& document)
{
    auto dataTransfer = adoptRef(*new DataTransfer(StoreMode::ReadWrite, makeUnique<StaticPasteboard>(), Type::DragAndDropData));
    dataTransfer->m_originIdentifier = document.originIdentifierForPasteboard();
    return dataTransfer;
}

Ref<DataTransfer> DataTransfer::createForDrop(const Document& document, std::unique_ptr<Pasteboard>&& pasteboard, OptionSet<DragOperation> sourceOperationMask, bool draggingFiles)
{
    auto dataTransfer = adoptRef(*new DataTransfer(DataTransfer::StoreMode::Readonly, WTFMove(pasteboard), draggingFiles ? Type::DragAndDropFiles : Type::DragAndDropData));
    dataTransfer->setSourceOperationMask(sourceOperationMask);
    dataTransfer->m_originIdentifier = document.originIdentifierForPasteboard();
    return dataTransfer;
}

Ref<DataTransfer> DataTransfer::createForUpdatingDropTarget(const Document& document, std::unique_ptr<Pasteboard>&& pasteboard, OptionSet<DragOperation> sourceOperationMask, bool draggingFiles)
{
    auto dataTransfer = adoptRef(*new DataTransfer(DataTransfer::StoreMode::Protected, WTFMove(pasteboard), draggingFiles ? Type::DragAndDropFiles : Type::DragAndDropData));
    dataTransfer->setSourceOperationMask(sourceOperationMask);
    dataTransfer->m_originIdentifier = document.originIdentifierForPasteboard();
    return dataTransfer;
}

void DataTransfer::setDragImage(Element& element, int x, int y)
{
    if (!forDrag() || !canWriteData())
        return;

    CachedImage* image = nullptr;
    if (is<HTMLImageElement>(element) && !element.isConnected())
        image = downcast<HTMLImageElement>(element).cachedImage();

    m_dragLocation = IntPoint(x, y);

    if (m_dragImageLoader && m_dragImage)
        m_dragImageLoader->stopLoading(m_dragImage);
    m_dragImage = image;
    if (m_dragImage) {
        if (!m_dragImageLoader)
            m_dragImageLoader = makeUnique<DragImageLoader>(this);
        m_dragImageLoader->startLoading(m_dragImage);
    }

    m_dragImageElement = image ? nullptr : &element;

    updateDragImage();
}

void DataTransfer::updateDragImage()
{
    // Don't allow setting the image if we haven't started dragging yet; we'll rely on the dragging code
    // to install this drag image as part of getting the drag kicked off.
    if (!m_shouldUpdateDragImage)
        return;

    IntPoint computedHotSpot;
    auto computedImage = DragImage { createDragImage(computedHotSpot) };
    if (!computedImage)
        return;

    m_pasteboard->setDragImage(WTFMove(computedImage), computedHotSpot);
}

RefPtr<Element> DataTransfer::dragImageElement() const
{
    return m_dragImageElement;
}

#if !PLATFORM(MAC)

DragImageRef DataTransfer::createDragImage(IntPoint& location) const
{
    location = m_dragLocation;

    if (m_dragImage)
        return createDragImageFromImage(m_dragImage->image(), ImageOrientation::None);

    if (m_dragImageElement) {
        if (Frame* frame = m_dragImageElement->document().frame())
            return createDragImageForNode(*frame, *m_dragImageElement);
    }

    // We do not have enough information to create a drag image, use the default icon.
    return nullptr;
}

#endif

DragImageLoader::DragImageLoader(DataTransfer* dataTransfer)
    : m_dataTransfer(dataTransfer)
{
}

void DragImageLoader::moveToDataTransfer(DataTransfer& newDataTransfer)
{
    m_dataTransfer = &newDataTransfer;
}

void DragImageLoader::startLoading(CachedResourceHandle<WebCore::CachedImage>& image)
{
    // FIXME: Does this really trigger a load? Does it need to?
    image->addClient(*this);
}

void DragImageLoader::stopLoading(CachedResourceHandle<WebCore::CachedImage>& image)
{
    image->removeClient(*this);
}

void DragImageLoader::imageChanged(CachedImage*, const IntRect*)
{
    m_dataTransfer->updateDragImage();
}

static OptionSet<DragOperation> dragOpFromIEOp(const String& operation)
{
    if (operation == "uninitialized")
        return anyDragOperation();
    if (operation == "none")
        return { };
    if (operation == "copy")
        return { DragOperation::Copy };
    if (operation == "link")
        return { DragOperation::Link };
    if (operation == "move")
        return { DragOperation::Generic, DragOperation::Move };
    if (operation == "copyLink")
        return { DragOperation::Copy, DragOperation::Link };
    if (operation == "copyMove")
        return { DragOperation::Copy, DragOperation::Generic, DragOperation::Move };
    if (operation == "linkMove")
        return { DragOperation::Link, DragOperation::Generic, DragOperation::Move };
    if (operation == "all")
        return anyDragOperation();
    return { DragOperation::Private }; // Really a marker for "no conversion".
}

static const char* IEOpFromDragOp(OptionSet<DragOperation> operationMask)
{
    bool isGenericMove = operationMask.containsAny({ DragOperation::Generic, DragOperation::Move });

    if ((isGenericMove && operationMask.containsAll({ DragOperation::Copy, DragOperation::Link })) || operationMask.containsAll({ DragOperation::Copy, DragOperation::Link, DragOperation::Generic, DragOperation::Private, DragOperation::Move, DragOperation::Delete }))
        return "all";
    if (isGenericMove && operationMask.contains(DragOperation::Copy))
        return "copyMove";
    if (isGenericMove && operationMask.contains(DragOperation::Link))
        return "linkMove";
    if (operationMask.containsAll({ DragOperation::Copy, DragOperation::Link }))
        return "copyLink";
    if (isGenericMove)
        return "move";
    if (operationMask.contains(DragOperation::Copy))
        return "copy";
    if (operationMask.contains(DragOperation::Link))
        return "link";
    return "none";
}

OptionSet<DragOperation> DataTransfer::sourceOperationMask() const
{
    auto operationMask = dragOpFromIEOp(m_effectAllowed);
    ASSERT(operationMask != DragOperation::Private);
    return operationMask;
}

OptionSet<DragOperation> DataTransfer::destinationOperationMask() const
{
    auto operationMask = dragOpFromIEOp(m_dropEffect);
    ASSERT(operationMask == DragOperation::Copy || operationMask.isEmpty() || operationMask == DragOperation::Link || operationMask == OptionSet<DragOperation>({ DragOperation::Generic, DragOperation::Move }) || operationMask.containsAll({ DragOperation::Copy, DragOperation::Link, DragOperation::Generic, DragOperation::Private, DragOperation::Move, DragOperation::Delete }));
    return operationMask;
}

void DataTransfer::setSourceOperationMask(OptionSet<DragOperation> operationMask)
{
    ASSERT_ARG(operationMask, operationMask != DragOperation::Private);
    m_effectAllowed = IEOpFromDragOp(operationMask);
}

void DataTransfer::setDestinationOperationMask(OptionSet<DragOperation> operationMask)
{
    ASSERT_ARG(operationMask, operationMask == DragOperation::Copy || operationMask.isEmpty() || operationMask == DragOperation::Link || operationMask == DragOperation::Generic || operationMask == DragOperation::Move || operationMask == OptionSet<DragOperation>({ DragOperation::Generic, DragOperation::Move }));
    m_dropEffect = IEOpFromDragOp(operationMask);
}

String DataTransfer::dropEffect() const
{
    return m_dropEffect == "uninitialized" ? "none"_s : m_dropEffect;
}

void DataTransfer::setDropEffect(const String& effect)
{
    if (!forDrag())
        return;

    if (effect != "none" && effect != "copy" && effect != "link" && effect != "move")
        return;

    // FIXME: The spec allows this in all circumstances. There is probably no value
    // in ignoring attempts to change it.
    if (!canReadTypes())
        return;

    m_dropEffect = effect;
}

String DataTransfer::effectAllowed() const
{
    return m_effectAllowed;
}

void DataTransfer::setEffectAllowed(const String& effect)
{
    if (!forDrag())
        return;

    // Ignore any attempts to set it to an unknown value.
    if (dragOpFromIEOp(effect) == DragOperation::Private)
        return;

    if (!canWriteData())
        return;

    m_effectAllowed = effect;
}

void DataTransfer::moveDragState(Ref<DataTransfer>&& other)
{
    RELEASE_ASSERT(is<StaticPasteboard>(other->pasteboard()));
    other->commitToPasteboard(*m_pasteboard);

    m_dropEffect = other->m_dropEffect;
    m_effectAllowed = other->m_effectAllowed;
    m_dragLocation = other->m_dragLocation;
    m_dragImage = other->m_dragImage;
    m_dragImageElement = WTFMove(other->m_dragImageElement);
    m_dragImageLoader = WTFMove(other->m_dragImageLoader);
    if (m_dragImageLoader)
        m_dragImageLoader->moveToDataTransfer(*this);
    m_fileList = WTFMove(other->m_fileList);
}

bool DataTransfer::hasDragImage() const
{
    return m_dragImage || m_dragImageElement;
}

#endif // ENABLE(DRAG_SUPPORT)

} // namespace WebCore
