From 4bb9168712d6e706465ded9e1b6764a039651ea0 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sat, 17 Aug 2024 14:44:26 -0400 Subject: [PATCH] LibWeb: Implement the DataTransfer files attribute --- .../Text/expected/HTML/drag-and-drop.txt | 6 +++ .../LibWeb/Text/input/HTML/drag-and-drop.html | 10 +++++ .../Libraries/LibWeb/HTML/DataTransfer.cpp | 43 +++++++++++++++++++ Userland/Libraries/LibWeb/HTML/DataTransfer.h | 2 + .../Libraries/LibWeb/HTML/DataTransfer.idl | 4 +- 5 files changed, 64 insertions(+), 1 deletion(-) diff --git a/Tests/LibWeb/Text/expected/HTML/drag-and-drop.txt b/Tests/LibWeb/Text/expected/HTML/drag-and-drop.txt index 10392e4d5a0..3af87db2d67 100644 --- a/Tests/LibWeb/Text/expected/HTML/drag-and-drop.txt +++ b/Tests/LibWeb/Text/expected/HTML/drag-and-drop.txt @@ -5,6 +5,8 @@ dragover types: Files drop types: Files + files: 1 + test1 Drag enter and leave: dragenter @@ -19,6 +21,8 @@ dragover types: Files drop types: Files + files: 1 + test2 Drag enter not accepted: dragenter @@ -41,3 +45,5 @@ dragover types: Files drop types: Files + files: 1 + test5 diff --git a/Tests/LibWeb/Text/input/HTML/drag-and-drop.html b/Tests/LibWeb/Text/input/HTML/drag-and-drop.html index a1d00a19ce4..5a40ec01005 100644 --- a/Tests/LibWeb/Text/input/HTML/drag-and-drop.html +++ b/Tests/LibWeb/Text/input/HTML/drag-and-drop.html @@ -8,6 +8,16 @@ const printEvent = (name, e) => { println(name); println(` types: ${e.dataTransfer.types}`); + + const files = e.dataTransfer.files; + + if (files.length !== 0) { + println(` files: ${files.length}`); + + for (const file of files) { + println(` ${file.name}`); + } + } }; target.addEventListener("dragenter", e => { diff --git a/Userland/Libraries/LibWeb/HTML/DataTransfer.cpp b/Userland/Libraries/LibWeb/HTML/DataTransfer.cpp index 94cd5c1ddba..6baa5b7f0a2 100644 --- a/Userland/Libraries/LibWeb/HTML/DataTransfer.cpp +++ b/Userland/Libraries/LibWeb/HTML/DataTransfer.cpp @@ -7,6 +7,9 @@ #include #include #include +#include +#include +#include #include namespace Web::HTML { @@ -84,6 +87,46 @@ ReadonlySpan DataTransfer::types() const return m_types; } +// https://html.spec.whatwg.org/multipage/dnd.html#dom-datatransfer-files +JS::NonnullGCPtr DataTransfer::files() const +{ + auto& realm = this->realm(); + + // 1. Start with an empty list L. + auto files = FileAPI::FileList::create(realm); + + // 2. If the DataTransfer object is no longer associated with a drag data store, the FileList is empty. Return + // the empty list L. + if (!m_associated_drag_data_store.has_value()) + return files; + + // 3. If the drag data store's mode is the protected mode, return the empty list L. + if (m_associated_drag_data_store->mode() == DragDataStore::Mode::Protected) + return files; + + // 4. For each item in the drag data store item list whose kind is File, add the item's data (the file, in + // particular its name and contents, as well as its type) to the list L. + for (auto const& item : m_associated_drag_data_store->item_list()) { + if (item.kind != DragDataStoreItem::Kind::File) + continue; + + 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; + + auto file = MUST(FileAPI::File::create(realm, { JS::make_handle(blob) }, file_name, move(options))); + files->add_file(file); + } + + // 5. The files found by these steps are those in the list L. + return files; +} + void DataTransfer::associate_with_drag_data_store(DragDataStore& drag_data_store) { m_associated_drag_data_store = drag_data_store; diff --git a/Userland/Libraries/LibWeb/HTML/DataTransfer.h b/Userland/Libraries/LibWeb/HTML/DataTransfer.h index 0a33f5b34f1..1ab610df538 100644 --- a/Userland/Libraries/LibWeb/HTML/DataTransfer.h +++ b/Userland/Libraries/LibWeb/HTML/DataTransfer.h @@ -51,6 +51,8 @@ public: ReadonlySpan types() const; + JS::NonnullGCPtr files() const; + void associate_with_drag_data_store(DragDataStore& drag_data_store); void disassociate_with_drag_data_store(); diff --git a/Userland/Libraries/LibWeb/HTML/DataTransfer.idl b/Userland/Libraries/LibWeb/HTML/DataTransfer.idl index 9a61a3a31dd..41921951f58 100644 --- a/Userland/Libraries/LibWeb/HTML/DataTransfer.idl +++ b/Userland/Libraries/LibWeb/HTML/DataTransfer.idl @@ -1,3 +1,5 @@ +#import + // https://html.spec.whatwg.org/multipage/dnd.html#datatransfer [Exposed=Window] interface DataTransfer { @@ -15,5 +17,5 @@ interface DataTransfer { [FIXME] DOMString getData(DOMString format); [FIXME] undefined setData(DOMString format, DOMString data); [FIXME] undefined clearData(optional DOMString format); - [FIXME, SameObject] readonly attribute FileList files; + [SameObject] readonly attribute FileList files; };