DataTransferItemList.cpp [plain text]
#include "config.h"
#include "DataTransferItemList.h"
#include "DataTransferItem.h"
#include "FileList.h"
#include "Pasteboard.h"
#include "RuntimeEnabledFeatures.h"
#include "Settings.h"
namespace WebCore {
DataTransferItemList::DataTransferItemList(DataTransfer& dataTransfer)
: m_dataTransfer(dataTransfer)
{
}
DataTransferItemList::~DataTransferItemList() = default;
unsigned DataTransferItemList::length() const
{
return ensureItems().size();
}
RefPtr<DataTransferItem> DataTransferItemList::item(unsigned index)
{
auto& items = ensureItems();
if (items.size() <= index)
return nullptr;
return items[index].copyRef();
}
static bool shouldExposeTypeInItemList(const String& type)
{
return RuntimeEnabledFeatures::sharedFeatures().customPasteboardDataEnabled() || Pasteboard::isSafeTypeForDOMToReadAndWrite(type);
}
ExceptionOr<RefPtr<DataTransferItem>> DataTransferItemList::add(const String& data, const String& type)
{
if (!m_dataTransfer.canWriteData())
return nullptr;
for (auto& item : ensureItems()) {
if (!item->isFile() && equalIgnoringASCIICase(item->type(), type))
return Exception { NotSupportedError };
}
String lowercasedType = type.convertToASCIILowercase();
if (!shouldExposeTypeInItemList(lowercasedType))
return nullptr;
m_dataTransfer.setDataFromItemList(lowercasedType, data);
ASSERT(m_items);
m_items->append(DataTransferItem::create(m_weakPtrFactory.createWeakPtr(*this), lowercasedType));
return m_items->last().ptr();
}
RefPtr<DataTransferItem> DataTransferItemList::add(Ref<File>&& file)
{
if (!m_dataTransfer.canWriteData())
return nullptr;
ensureItems().append(DataTransferItem::create(m_weakPtrFactory.createWeakPtr(*this), file->type(), file.copyRef()));
m_dataTransfer.didAddFileToItemList();
return m_items->last().ptr();
}
ExceptionOr<void> DataTransferItemList::remove(unsigned index)
{
if (!m_dataTransfer.canWriteData())
return Exception { InvalidStateError };
auto& items = ensureItems();
if (items.size() <= index)
return Exception { IndexSizeError };
Ref<DataTransferItem> removedItem = items[index].copyRef();
if (!removedItem->isFile())
m_dataTransfer.pasteboard().clear(removedItem->type());
removedItem->clearListAndPutIntoDisabledMode();
items.remove(index);
if (removedItem->isFile())
m_dataTransfer.updateFileList();
return { };
}
void DataTransferItemList::clear()
{
m_dataTransfer.pasteboard().clear();
bool removedItemContainingFile = false;
if (m_items) {
for (auto& item : *m_items) {
removedItemContainingFile |= item->isFile();
item->clearListAndPutIntoDisabledMode();
}
m_items->clear();
}
if (removedItemContainingFile)
m_dataTransfer.updateFileList();
}
Vector<Ref<DataTransferItem>>& DataTransferItemList::ensureItems() const
{
if (m_items)
return *m_items;
Vector<Ref<DataTransferItem>> items;
for (auto& type : m_dataTransfer.typesForItemList()) {
auto lowercasedType = type.convertToASCIILowercase();
if (shouldExposeTypeInItemList(lowercasedType))
items.append(DataTransferItem::create(m_weakPtrFactory.createWeakPtr(*const_cast<DataTransferItemList*>(this)), lowercasedType));
}
for (auto& file : m_dataTransfer.files().files())
items.append(DataTransferItem::create(m_weakPtrFactory.createWeakPtr(*const_cast<DataTransferItemList*>(this)), file->type(), file.copyRef()));
m_items = WTFMove(items);
return *m_items;
}
static void removeStringItemOfLowercasedType(Vector<Ref<DataTransferItem>>& items, const String& lowercasedType)
{
auto index = items.findMatching([lowercasedType](auto& item) {
return !item->isFile() && item->type() == lowercasedType;
});
if (index == notFound)
return;
items[index]->clearListAndPutIntoDisabledMode();
items.remove(index);
}
void DataTransferItemList::didClearStringData(const String& type)
{
if (!m_items)
return;
auto& items = *m_items;
if (!type.isNull())
return removeStringItemOfLowercasedType(items, type.convertToASCIILowercase());
for (auto& item : items) {
if (!item->isFile())
item->clearListAndPutIntoDisabledMode();
}
items.removeAllMatching([](auto& item) {
return !item->isFile();
});
}
void DataTransferItemList::didSetStringData(const String& type)
{
if (!m_items)
return;
String lowercasedType = type.convertToASCIILowercase();
removeStringItemOfLowercasedType(*m_items, type.convertToASCIILowercase());
m_items->append(DataTransferItem::create(m_weakPtrFactory.createWeakPtr(*this), lowercasedType));
}
}