Jelajahi Sumber

LibWeb: Implement the DataTransfer files attribute

Timothy Flynn 11 bulan lalu
induk
melakukan
4bb9168712

+ 6 - 0
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

+ 10 - 0
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 => {

+ 43 - 0
Userland/Libraries/LibWeb/HTML/DataTransfer.cpp

@@ -7,6 +7,9 @@
 #include <LibJS/Runtime/Realm.h>
 #include <LibWeb/Bindings/DataTransferPrototype.h>
 #include <LibWeb/Bindings/Intrinsics.h>
+#include <LibWeb/FileAPI/Blob.h>
+#include <LibWeb/FileAPI/File.h>
+#include <LibWeb/FileAPI/FileList.h>
 #include <LibWeb/HTML/DataTransfer.h>
 
 namespace Web::HTML {
@@ -84,6 +87,46 @@ ReadonlySpan<String> DataTransfer::types() const
     return m_types;
 }
 
+// https://html.spec.whatwg.org/multipage/dnd.html#dom-datatransfer-files
+JS::NonnullGCPtr<FileAPI::FileList> 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;

+ 2 - 0
Userland/Libraries/LibWeb/HTML/DataTransfer.h

@@ -51,6 +51,8 @@ public:
 
     ReadonlySpan<String> types() const;
 
+    JS::NonnullGCPtr<FileAPI::FileList> files() const;
+
     void associate_with_drag_data_store(DragDataStore& drag_data_store);
     void disassociate_with_drag_data_store();
 

+ 3 - 1
Userland/Libraries/LibWeb/HTML/DataTransfer.idl

@@ -1,3 +1,5 @@
+#import <FileAPI/FileList.idl>
+
 // 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;
 };