mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 07:34:57 +00:00
LibWeb+LibWebView+WebContent: Implement more <input type=file> behavior
We had previous implemented some plumbing for file input elements in
commit 636602a54e
.
This implements the return path for chromes to inform WebContent of the
file(s) the user selected. This patch includes a dummy implementation
for headless-browser to enable testing.
This commit is contained in:
parent
435c2c24d1
commit
108521a566
23 changed files with 307 additions and 5 deletions
|
@ -28,6 +28,7 @@
|
|||
#include <LibWeb/HTML/Numbers.h>
|
||||
#include <LibWeb/HTML/Parser/HTMLParser.h>
|
||||
#include <LibWeb/HTML/Scripting/Environments.h>
|
||||
#include <LibWeb/HTML/SelectedFile.h>
|
||||
#include <LibWeb/HTML/SharedImageRequest.h>
|
||||
#include <LibWeb/HTML/Window.h>
|
||||
#include <LibWeb/Infra/CharacterTypes.h>
|
||||
|
@ -37,6 +38,7 @@
|
|||
#include <LibWeb/Layout/CheckBox.h>
|
||||
#include <LibWeb/Layout/ImageBox.h>
|
||||
#include <LibWeb/Layout/RadioButton.h>
|
||||
#include <LibWeb/MimeSniff/Resource.h>
|
||||
#include <LibWeb/Namespace.h>
|
||||
#include <LibWeb/Page/Page.h>
|
||||
#include <LibWeb/UIEvents/EventNames.h>
|
||||
|
@ -213,12 +215,12 @@ static void show_the_picker_if_applicable(HTMLInputElement& element)
|
|||
// with the bubbles attribute initialized to true.
|
||||
// 5. Otherwise, update the file selection for element.
|
||||
|
||||
bool const multiple = element.has_attribute(HTML::AttributeNames::multiple);
|
||||
auto weak_element = element.make_weak_ptr<DOM::EventTarget>();
|
||||
auto allow_multiple_files = element.has_attribute(HTML::AttributeNames::multiple) ? AllowMultipleFiles::Yes : AllowMultipleFiles::No;
|
||||
auto weak_element = element.make_weak_ptr<HTMLInputElement>();
|
||||
|
||||
// FIXME: Pass along accept attribute information https://html.spec.whatwg.org/multipage/input.html#attr-input-accept
|
||||
// The accept attribute may be specified to provide user agents with a hint of what file types will be accepted.
|
||||
element.document().browsing_context()->top_level_browsing_context()->page().client().page_did_request_file_picker(weak_element, multiple);
|
||||
element.document().browsing_context()->top_level_browsing_context()->page().did_request_file_picker(weak_element, allow_multiple_files);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -380,6 +382,51 @@ void HTMLInputElement::did_pick_color(Optional<Color> picked_color)
|
|||
}
|
||||
}
|
||||
|
||||
void HTMLInputElement::did_select_files(Span<SelectedFile> selected_files)
|
||||
{
|
||||
// https://html.spec.whatwg.org/multipage/input.html#show-the-picker,-if-applicable
|
||||
// 4. If the user dismissed the prompt without changing their selection, then queue an element task on the user
|
||||
// interaction task source given element to fire an event named cancel at element, with the bubbles attribute
|
||||
// initialized to true.
|
||||
if (selected_files.is_empty()) {
|
||||
queue_an_element_task(HTML::Task::Source::UserInteraction, [this]() {
|
||||
dispatch_event(DOM::Event::create(realm(), HTML::EventNames::cancel, { .bubbles = true }));
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<JS::NonnullGCPtr<FileAPI::File>> files;
|
||||
files.ensure_capacity(selected_files.size());
|
||||
|
||||
for (auto& selected_file : selected_files) {
|
||||
auto contents = selected_file.take_contents();
|
||||
|
||||
auto mime_type = MUST(MimeSniff::Resource::sniff(contents));
|
||||
auto blob = FileAPI::Blob::create(realm(), move(contents), mime_type.essence());
|
||||
|
||||
// FIXME: The FileAPI should use ByteString for file names.
|
||||
auto file_name = MUST(String::from_byte_string(selected_file.name()));
|
||||
|
||||
auto file = MUST(FileAPI::File::create(realm(), { JS::make_handle(blob) }, file_name));
|
||||
files.unchecked_append(file);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/input.html#update-the-file-selection
|
||||
// 1. Queue an element task on the user interaction task source given element and the following steps:
|
||||
queue_an_element_task(HTML::Task::Source::UserInteraction, [this, files = move(files)]() mutable {
|
||||
// 1. Update element's selected files so that it represents the user's selection.
|
||||
m_selected_files = FileAPI::FileList::create(realm(), move(files));
|
||||
update_file_input_shadow_tree();
|
||||
|
||||
// 2. Fire an event named input at the input element, with the bubbles and composed attributes initialized to true.
|
||||
dispatch_event(DOM::Event::create(realm(), HTML::EventNames::input, { .bubbles = true, .composed = true }));
|
||||
|
||||
// 3. Fire an event named change at the input element, with the bubbles attribute initialized to true.
|
||||
dispatch_event(DOM::Event::create(realm(), HTML::EventNames::change, { .bubbles = true }));
|
||||
});
|
||||
}
|
||||
|
||||
String HTMLInputElement::value() const
|
||||
{
|
||||
switch (value_attribute_mode()) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue