diff --git a/Tests/LibWeb/Text/expected/HTML/data-transfer.txt b/Tests/LibWeb/Text/expected/HTML/data-transfer.txt index 96592024645..a41e32bd4b6 100644 --- a/Tests/LibWeb/Text/expected/HTML/data-transfer.txt +++ b/Tests/LibWeb/Text/expected/HTML/data-transfer.txt @@ -5,3 +5,4 @@ stringItem: kind=string, type=custom-type length=1, types=custom-type fileItem: kind=file, type=text/plain length=2, types=custom-type,Files +fileItemAsFile: name=file.txt, type=text/plain diff --git a/Tests/LibWeb/Text/input/HTML/data-transfer.html b/Tests/LibWeb/Text/input/HTML/data-transfer.html index 0d092360fa6..76038e2e862 100644 --- a/Tests/LibWeb/Text/input/HTML/data-transfer.html +++ b/Tests/LibWeb/Text/input/HTML/data-transfer.html @@ -29,6 +29,9 @@ println(`fileItem: kind=${fileItem.kind}, type=${fileItem.type}`); println(`length=${dataTransferItemList.length}, types=${dataTransfer.types}`); + let fileItemAsFile = fileItem.getAsFile(); + println(`fileItemAsFile: name=${fileItemAsFile.name}, type=${fileItemAsFile.type}`); + if (dataTransferItemList[1] !== fileItem) { println("FAILED"); } diff --git a/Userland/Libraries/LibWeb/HTML/DataTransferItem.cpp b/Userland/Libraries/LibWeb/HTML/DataTransferItem.cpp index fdf2ea8b004..27c8d2f7ec8 100644 --- a/Userland/Libraries/LibWeb/HTML/DataTransferItem.cpp +++ b/Userland/Libraries/LibWeb/HTML/DataTransferItem.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -85,4 +86,32 @@ Optional DataTransferItem::mode() const return m_data_transfer->mode(); } +// https://html.spec.whatwg.org/multipage/dnd.html#dom-datatransferitem-getasfile +JS::GCPtr DataTransferItem::get_as_file() const +{ + auto& realm = this->realm(); + + // 1. If the DataTransferItem object is not in the read/write mode or the read-only mode, then return null + if (mode() != DragDataStore::Mode::ReadWrite && mode() != DragDataStore::Mode::ReadOnly) + return nullptr; + + auto const& item = m_data_transfer->drag_data(*m_item_index); + + // 2. If the drag data item kind is not File, then return null. + if (item.kind != DragDataStoreItem::Kind::File) + return nullptr; + + // 3. Return a new File object representing the actual data of the item represented by the DataTransferItem object. + auto blob = FileAPI::Blob::create(realm, item.data, item.type_string); + + // FIXME: The FileAPI should use ByteString for file names. + auto file_name = MUST(String::from_byte_string(item.file_name)); + + // FIXME: Fill in other fields (e.g. last_modified). + FileAPI::FilePropertyBag options {}; + options.type = item.type_string; + + return MUST(FileAPI::File::create(realm, { JS::make_handle(blob) }, file_name, move(options))); +} + } diff --git a/Userland/Libraries/LibWeb/HTML/DataTransferItem.h b/Userland/Libraries/LibWeb/HTML/DataTransferItem.h index 5659286497f..adbce270a1d 100644 --- a/Userland/Libraries/LibWeb/HTML/DataTransferItem.h +++ b/Userland/Libraries/LibWeb/HTML/DataTransferItem.h @@ -25,6 +25,8 @@ public: String kind() const; String type() const; + JS::GCPtr get_as_file() const; + private: DataTransferItem(JS::Realm&, JS::NonnullGCPtr, size_t item_index); diff --git a/Userland/Libraries/LibWeb/HTML/DataTransferItem.idl b/Userland/Libraries/LibWeb/HTML/DataTransferItem.idl index 157e87b2894..4eb4a760ffc 100644 --- a/Userland/Libraries/LibWeb/HTML/DataTransferItem.idl +++ b/Userland/Libraries/LibWeb/HTML/DataTransferItem.idl @@ -8,5 +8,5 @@ interface DataTransferItem { readonly attribute DOMString kind; readonly attribute DOMString type; [FIXME] undefined getAsString(FunctionStringCallback? _callback); - [FIXME] File? getAsFile(); + File? getAsFile(); };