diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index b89bc9bf789..c1c058a3d41 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -53,6 +53,7 @@ static bool is_platform_object(Type const& type) "DynamicsCompressorNode"sv, "ElementInternals"sv, "EventTarget"sv, + "File"sv, "FileList"sv, "FontFace"sv, "FormData"sv, diff --git a/Tests/LibWeb/Text/expected/HTML/data-transfer.txt b/Tests/LibWeb/Text/expected/HTML/data-transfer.txt index 59aa6d4f348..68fbee671ac 100644 --- a/Tests/LibWeb/Text/expected/HTML/data-transfer.txt +++ b/Tests/LibWeb/Text/expected/HTML/data-transfer.txt @@ -1,2 +1,4 @@ dropEffect: none effectAllowed: none +stringItem: [object DataTransferItem], types=custom-type +fileItem: [object DataTransferItem], types=custom-type,Files diff --git a/Tests/LibWeb/Text/input/HTML/data-transfer.html b/Tests/LibWeb/Text/input/HTML/data-transfer.html index af33a611f6d..b174681d1f9 100644 --- a/Tests/LibWeb/Text/input/HTML/data-transfer.html +++ b/Tests/LibWeb/Text/input/HTML/data-transfer.html @@ -4,5 +4,22 @@ let dataTransfer = new DataTransfer(); println(`dropEffect: ${dataTransfer.dropEffect}`); println(`effectAllowed: ${dataTransfer.effectAllowed}`); + + let dataTransferItemList = dataTransfer.items; + + let stringItem = dataTransferItemList.add("well hello friends", "custom-type"); + println(`stringItem: ${stringItem}, types=${dataTransfer.types}`); + + try { + dataTransferItemList.add("well hello friends", "custom-type"); + println("FAILED"); + } catch (e) {} + + let file = new File(["well hello friends"], "file.txt", { + type: "text/plain", + }); + + let fileItem = dataTransferItemList.add(file); + println(`fileItem: ${fileItem}, types=${dataTransfer.types}`); }); diff --git a/Userland/Libraries/LibWeb/HTML/DataTransfer.cpp b/Userland/Libraries/LibWeb/HTML/DataTransfer.cpp index 930ce99ccd0..019485fd43e 100644 --- a/Userland/Libraries/LibWeb/HTML/DataTransfer.cpp +++ b/Userland/Libraries/LibWeb/HTML/DataTransfer.cpp @@ -220,12 +220,46 @@ JS::NonnullGCPtr DataTransfer::files() const return files; } +Optional DataTransfer::mode() const +{ + if (m_associated_drag_data_store) + return m_associated_drag_data_store->mode(); + return {}; +} + void DataTransfer::disassociate_with_drag_data_store() { m_associated_drag_data_store.clear(); update_data_transfer_types_list(); } +JS::NonnullGCPtr DataTransfer::add_item(DragDataStoreItem item) +{ + auto& realm = this->realm(); + + VERIFY(m_associated_drag_data_store); + m_associated_drag_data_store->add_item(move(item)); + + auto data_transfer_item = DataTransferItem::create(realm, *this, m_associated_drag_data_store->size() - 1); + m_item_list.append(data_transfer_item); + + update_data_transfer_types_list(); + + return data_transfer_item; +} + +bool DataTransfer::contains_item_with_type(DragDataStoreItem::Kind kind, String const& type) const +{ + VERIFY(m_associated_drag_data_store); + + for (auto const& item : m_associated_drag_data_store->item_list()) { + if (item.kind == kind && item.type_string.equals_ignoring_ascii_case(type)) + return true; + } + + return false; +} + // https://html.spec.whatwg.org/multipage/dnd.html#concept-datatransfer-types void DataTransfer::update_data_transfer_types_list() { @@ -259,5 +293,4 @@ void DataTransfer::update_data_transfer_types_list() // 3. Set the DataTransfer object's types array to the result of creating a frozen array from L. m_types = move(types); } - } diff --git a/Userland/Libraries/LibWeb/HTML/DataTransfer.h b/Userland/Libraries/LibWeb/HTML/DataTransfer.h index b4ad54a2f70..049dc2a891e 100644 --- a/Userland/Libraries/LibWeb/HTML/DataTransfer.h +++ b/Userland/Libraries/LibWeb/HTML/DataTransfer.h @@ -56,8 +56,12 @@ public: String get_data(String const& format) const; JS::NonnullGCPtr files() const; + Optional mode() const; void disassociate_with_drag_data_store(); + JS::NonnullGCPtr add_item(DragDataStoreItem item); + bool contains_item_with_type(DragDataStoreItem::Kind, String const& type) const; + private: DataTransfer(JS::Realm&, NonnullRefPtr); diff --git a/Userland/Libraries/LibWeb/HTML/DataTransferItemList.cpp b/Userland/Libraries/LibWeb/HTML/DataTransferItemList.cpp index 1b10c6eecbd..b901194cd83 100644 --- a/Userland/Libraries/LibWeb/HTML/DataTransferItemList.cpp +++ b/Userland/Libraries/LibWeb/HTML/DataTransferItemList.cpp @@ -7,8 +7,10 @@ #include #include #include +#include #include #include +#include namespace Web::HTML { @@ -39,4 +41,63 @@ void DataTransferItemList::visit_edges(JS::Cell::Visitor& visitor) visitor.visit(m_data_transfer); } +// https://html.spec.whatwg.org/multipage/dnd.html#dom-datatransferitemlist-add +WebIDL::ExceptionOr> DataTransferItemList::add(String const& data, String const& type) +{ + auto& realm = this->realm(); + + // 1. If the DataTransferItemList object is not in the read/write mode, return null. + if (m_data_transfer->mode() != DragDataStore::Mode::ReadWrite) + return nullptr; + + // 2. Jump to the appropriate set of steps from the following list: + // -> If the first argument to the method is a string + + // If there is already an item in the drag data store item list whose kind is text and whose type string is equal + // to the value of the method's second argument, converted to ASCII lowercase, then throw a "NotSupportedError" + // DOMException. + if (m_data_transfer->contains_item_with_type(DragDataStoreItem::Kind::Text, type)) { + auto error = MUST(String::formatted("There is already a DataTransferItem with type {}", type)); + return WebIDL::NotSupportedError::create(realm, error); + } + + // Otherwise, add an item to the drag data store item list whose kind is text, whose type string is equal to the + // value of the method's second argument, converted to ASCII lowercase, and whose data is the string given by the + // method's first argument. + auto item = m_data_transfer->add_item({ + .kind = HTML::DragDataStoreItem::Kind::Text, + .type_string = MUST(Infra::to_ascii_lowercase(type)), + .data = MUST(ByteBuffer::copy(data.bytes())), + .file_name = {}, + }); + + // 3. Determine the value of the indexed property corresponding to the newly added item, and return that value (a + // newly created DataTransferItem object). + return item; +} + +// https://html.spec.whatwg.org/multipage/dnd.html#dom-datatransferitemlist-add +JS::GCPtr DataTransferItemList::add(JS::NonnullGCPtr file) +{ + // 1. If the DataTransferItemList object is not in the read/write mode, return null. + if (m_data_transfer->mode() != DragDataStore::Mode::ReadWrite) + return nullptr; + + // 2. Jump to the appropriate set of steps from the following list: + // -> If the first argument to the method is a File + + // Add an item to the drag data store item list whose kind is File, whose type string is the type of the File, + // converted to ASCII lowercase, and whose data is the same as the File's data. + auto item = m_data_transfer->add_item({ + .kind = HTML::DragDataStoreItem::Kind::File, + .type_string = MUST(Infra::to_ascii_lowercase(file->type())), + .data = MUST(ByteBuffer::copy(file->raw_bytes())), + .file_name = file->name().to_byte_string(), + }); + + // 3. Determine the value of the indexed property corresponding to the newly added item, and return that value (a + // newly created DataTransferItem object). + return item; +} + } diff --git a/Userland/Libraries/LibWeb/HTML/DataTransferItemList.h b/Userland/Libraries/LibWeb/HTML/DataTransferItemList.h index 5f773de66bc..1574a778b1e 100644 --- a/Userland/Libraries/LibWeb/HTML/DataTransferItemList.h +++ b/Userland/Libraries/LibWeb/HTML/DataTransferItemList.h @@ -8,6 +8,7 @@ #include #include +#include namespace Web::HTML { @@ -20,6 +21,9 @@ public: static JS::NonnullGCPtr create(JS::Realm&, JS::NonnullGCPtr); virtual ~DataTransferItemList() override; + WebIDL::ExceptionOr> add(String const& data, String const& type); + JS::GCPtr add(JS::NonnullGCPtr); + private: DataTransferItemList(JS::Realm&, JS::NonnullGCPtr); diff --git a/Userland/Libraries/LibWeb/HTML/DataTransferItemList.idl b/Userland/Libraries/LibWeb/HTML/DataTransferItemList.idl index 211c089cf31..ee41a834444 100644 --- a/Userland/Libraries/LibWeb/HTML/DataTransferItemList.idl +++ b/Userland/Libraries/LibWeb/HTML/DataTransferItemList.idl @@ -1,3 +1,4 @@ +#import #import // https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist @@ -5,8 +6,8 @@ interface DataTransferItemList { [FIXME] readonly attribute unsigned long length; [FIXME] getter DataTransferItem (unsigned long index); - [FIXME] DataTransferItem? add(DOMString data, DOMString type); - [FIXME] DataTransferItem? add(File data); + DataTransferItem? add(DOMString data, DOMString type); + DataTransferItem? add(File data); [FIXME] undefined remove(unsigned long index); [FIXME] undefined clear(); };