Просмотр исходного кода

LibWeb: Implement DataTransferItem.prototype.getAsFile()

This is used on imgur after drag-and-dropping an image onto its page.
Timothy Flynn 10 месяцев назад
Родитель
Сommit
b978dba8bd

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

+ 3 - 0
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");
         }

+ 29 - 0
Userland/Libraries/LibWeb/HTML/DataTransferItem.cpp

@@ -7,6 +7,7 @@
 #include <LibJS/Runtime/Realm.h>
 #include <LibWeb/Bindings/DataTransferItemPrototype.h>
 #include <LibWeb/Bindings/Intrinsics.h>
+#include <LibWeb/FileAPI/File.h>
 #include <LibWeb/HTML/DataTransfer.h>
 #include <LibWeb/HTML/DataTransferItem.h>
 
@@ -85,4 +86,32 @@ Optional<DragDataStore::Mode> DataTransferItem::mode() const
     return m_data_transfer->mode();
 }
 
+// https://html.spec.whatwg.org/multipage/dnd.html#dom-datatransferitem-getasfile
+JS::GCPtr<FileAPI::File> 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)));
+}
+
 }

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

@@ -25,6 +25,8 @@ public:
     String kind() const;
     String type() const;
 
+    JS::GCPtr<FileAPI::File> get_as_file() const;
+
 private:
     DataTransferItem(JS::Realm&, JS::NonnullGCPtr<DataTransfer>, size_t item_index);
 

+ 1 - 1
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();
 };