mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:12:45 +00:00 
			
		
		
		
	Ladybird+LibWeb+WebContent: Parse the <input type=file> accept attribute
This parses the accept attribute value for file input types and passes it along to the browser chromes.
This commit is contained in:
		
							parent
							
								
									e4213f5767
								
							
						
					
					
						commit
						6760d236e4
					
				
					 20 changed files with 267 additions and 24 deletions
				
			
		|  | @ -626,7 +626,7 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_ | |||
|         [panel makeKeyAndOrderFront:nil]; | ||||
|     }; | ||||
| 
 | ||||
|     m_web_view_bridge->on_request_file_picker = [self](auto allow_multiple_files) { | ||||
|     m_web_view_bridge->on_request_file_picker = [self](auto const&, auto allow_multiple_files) { | ||||
|         auto* panel = [NSOpenPanel openPanel]; | ||||
|         [panel setCanChooseFiles:YES]; | ||||
|         [panel setCanChooseDirectories:NO]; | ||||
|  |  | |||
|  | @ -232,7 +232,7 @@ Tab::Tab(BrowserWindow* window, WebContentOptions const& web_content_options, St | |||
|         m_dialog = nullptr; | ||||
|     }; | ||||
| 
 | ||||
|     view().on_request_file_picker = [this](auto allow_multiple_files) { | ||||
|     view().on_request_file_picker = [this](auto const&, auto allow_multiple_files) { | ||||
|         Vector<Web::HTML::SelectedFile> selected_files; | ||||
| 
 | ||||
|         auto create_selected_file = [&](auto const& qfile_path) { | ||||
|  |  | |||
|  | @ -31,6 +31,7 @@ source_set("HTML") { | |||
|     "ErrorEvent.cpp", | ||||
|     "EventHandler.cpp", | ||||
|     "EventNames.cpp", | ||||
|     "FileFilter.cpp", | ||||
|     "Focus.cpp", | ||||
|     "FormAssociatedElement.cpp", | ||||
|     "FormControlInfrastructure.cpp", | ||||
|  |  | |||
							
								
								
									
										12
									
								
								Tests/LibWeb/Text/expected/input-file-accept.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								Tests/LibWeb/Text/expected/input-file-accept.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| Select file...file1 Select files...4 files selected. Select file...file1.cpp Select files...2 files selected.   input1: | ||||
| file1: text/plain: Contents for file1 | ||||
| input2: | ||||
| file1: text/plain: Contents for file1 | ||||
| file2: text/plain: Contents for file2 | ||||
| file3: text/plain: Contents for file3 | ||||
| file4: text/plain: Contents for file4 | ||||
| input3: | ||||
| file1.cpp: text/plain: int main() {{ return 1; }} | ||||
| input4: | ||||
| file1.cpp: text/plain: int main() {{ return 1; }} | ||||
| file2.cpp: text/plain: int main() {{ return 2; }} | ||||
							
								
								
									
										34
									
								
								Tests/LibWeb/Text/input/input-file-accept.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								Tests/LibWeb/Text/input/input-file-accept.html
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | |||
| <input id="input1" type="file" accept="text/plain" /> | ||||
| <input id="input2" type="file" accept="text/plain" multiple /> | ||||
| <input id="input3" type="file" accept=".cpp" /> | ||||
| <input id="input4" type="file" accept=".cpp" multiple /> | ||||
| <script src="./include.js"></script> | ||||
| <script type="text/javascript"> | ||||
|     const runTest = async id => { | ||||
|         let input = document.getElementById(id); | ||||
| 
 | ||||
|         return new Promise(resolve => { | ||||
|             input.addEventListener("input", async () => { | ||||
|                 println(`${id}:`); | ||||
| 
 | ||||
|                 for (let file of input.files) { | ||||
|                     const text = await file.text(); | ||||
|                     println(`${file.name}: ${file.type}: ${text}`); | ||||
|                 } | ||||
| 
 | ||||
|                 resolve(); | ||||
|             }); | ||||
| 
 | ||||
|             internals.dispatchUserActivatedEvent(input, new Event("mousedown")); | ||||
|             input.showPicker(); | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     asyncTest(async done => { | ||||
|         await runTest("input1"); | ||||
|         await runTest("input2"); | ||||
|         await runTest("input3"); | ||||
|         await runTest("input4"); | ||||
|         done(); | ||||
|     }); | ||||
| </script> | ||||
|  | @ -556,7 +556,7 @@ Tab::Tab(BrowserWindow& window) | |||
|         m_dialog = nullptr; | ||||
|     }; | ||||
| 
 | ||||
|     view().on_request_file_picker = [this](auto allow_multiple_files) { | ||||
|     view().on_request_file_picker = [this](auto const&, auto allow_multiple_files) { | ||||
|         // FIXME: GUI::FilePicker does not allow selecting multiple files at once.
 | ||||
|         (void)allow_multiple_files; | ||||
| 
 | ||||
|  |  | |||
|  | @ -268,6 +268,7 @@ set(SOURCES | |||
|     HTML/EventLoop/Task.cpp | ||||
|     HTML/EventLoop/TaskQueue.cpp | ||||
|     HTML/EventNames.cpp | ||||
|     HTML/FileFilter.cpp | ||||
|     HTML/Focus.cpp | ||||
|     HTML/FormAssociatedElement.cpp | ||||
|     HTML/FormControlInfrastructure.cpp | ||||
|  |  | |||
							
								
								
									
										61
									
								
								Userland/Libraries/LibWeb/HTML/FileFilter.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								Userland/Libraries/LibWeb/HTML/FileFilter.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org> | ||||
|  * | ||||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
| 
 | ||||
| #include <LibIPC/Decoder.h> | ||||
| #include <LibIPC/Encoder.h> | ||||
| #include <LibWeb/HTML/FileFilter.h> | ||||
| 
 | ||||
| namespace Web::HTML { | ||||
| 
 | ||||
| void FileFilter::add_filter(FilterType filter) | ||||
| { | ||||
|     if (!filters.contains_slow(filter)) | ||||
|         filters.append(move(filter)); | ||||
| } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| template<> | ||||
| ErrorOr<void> IPC::encode(Encoder& encoder, Web::HTML::FileFilter::MimeType const& mime_type) | ||||
| { | ||||
|     TRY(encoder.encode(mime_type.value)); | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| template<> | ||||
| ErrorOr<Web::HTML::FileFilter::MimeType> IPC::decode(Decoder& decoder) | ||||
| { | ||||
|     auto value = TRY(decoder.decode<String>()); | ||||
|     return Web::HTML::FileFilter::MimeType { move(value) }; | ||||
| } | ||||
| 
 | ||||
| template<> | ||||
| ErrorOr<void> IPC::encode(Encoder& encoder, Web::HTML::FileFilter::Extension const& extension) | ||||
| { | ||||
|     TRY(encoder.encode(extension.value)); | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| template<> | ||||
| ErrorOr<Web::HTML::FileFilter::Extension> IPC::decode(Decoder& decoder) | ||||
| { | ||||
|     auto value = TRY(decoder.decode<String>()); | ||||
|     return Web::HTML::FileFilter::Extension { move(value) }; | ||||
| } | ||||
| 
 | ||||
| template<> | ||||
| ErrorOr<void> IPC::encode(Encoder& encoder, Web::HTML::FileFilter const& filter) | ||||
| { | ||||
|     TRY(encoder.encode(filter.filters)); | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| template<> | ||||
| ErrorOr<Web::HTML::FileFilter> IPC::decode(Decoder& decoder) | ||||
| { | ||||
|     auto filters = TRY(decoder.decode<Vector<Web::HTML::FileFilter::FilterType>>()); | ||||
|     return Web::HTML::FileFilter { move(filters) }; | ||||
| } | ||||
							
								
								
									
										62
									
								
								Userland/Libraries/LibWeb/HTML/FileFilter.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								Userland/Libraries/LibWeb/HTML/FileFilter.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,62 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org> | ||||
|  * | ||||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <AK/String.h> | ||||
| #include <AK/Variant.h> | ||||
| #include <AK/Vector.h> | ||||
| #include <LibIPC/Forward.h> | ||||
| 
 | ||||
| namespace Web::HTML { | ||||
| 
 | ||||
| struct FileFilter { | ||||
|     enum class FileType { | ||||
|         Audio, | ||||
|         Image, | ||||
|         Video, | ||||
|     }; | ||||
| 
 | ||||
|     struct MimeType { | ||||
|         bool operator==(MimeType const&) const = default; | ||||
|         String value; | ||||
|     }; | ||||
| 
 | ||||
|     struct Extension { | ||||
|         bool operator==(Extension const&) const = default; | ||||
|         String value; | ||||
|     }; | ||||
| 
 | ||||
|     using FilterType = Variant<FileType, MimeType, Extension>; | ||||
| 
 | ||||
|     void add_filter(FilterType); | ||||
| 
 | ||||
|     Vector<FilterType> filters; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| namespace IPC { | ||||
| 
 | ||||
| template<> | ||||
| ErrorOr<void> encode(Encoder&, Web::HTML::FileFilter::MimeType const&); | ||||
| 
 | ||||
| template<> | ||||
| ErrorOr<Web::HTML::FileFilter::MimeType> decode(Decoder&); | ||||
| 
 | ||||
| template<> | ||||
| ErrorOr<void> encode(Encoder&, Web::HTML::FileFilter::Extension const&); | ||||
| 
 | ||||
| template<> | ||||
| ErrorOr<Web::HTML::FileFilter::Extension> decode(Decoder&); | ||||
| 
 | ||||
| template<> | ||||
| ErrorOr<void> encode(Encoder&, Web::HTML::FileFilter const&); | ||||
| 
 | ||||
| template<> | ||||
| ErrorOr<Web::HTML::FileFilter> decode(Decoder&); | ||||
| 
 | ||||
| } | ||||
|  | @ -39,6 +39,7 @@ | |||
| #include <LibWeb/Layout/CheckBox.h> | ||||
| #include <LibWeb/Layout/ImageBox.h> | ||||
| #include <LibWeb/Layout/RadioButton.h> | ||||
| #include <LibWeb/MimeSniff/MimeType.h> | ||||
| #include <LibWeb/MimeSniff/Resource.h> | ||||
| #include <LibWeb/Namespace.h> | ||||
| #include <LibWeb/Page/Page.h> | ||||
|  | @ -181,6 +182,43 @@ void HTMLInputElement::set_files(JS::GCPtr<FileAPI::FileList> files) | |||
|     m_selected_files = files; | ||||
| } | ||||
| 
 | ||||
| // https://html.spec.whatwg.org/multipage/input.html#attr-input-accept
 | ||||
| FileFilter HTMLInputElement::parse_accept_attribute() const | ||||
| { | ||||
|     FileFilter filter; | ||||
| 
 | ||||
|     // If specified, the attribute must consist of a set of comma-separated tokens, each of which must be an ASCII
 | ||||
|     // case-insensitive match for one of the following:
 | ||||
|     get_attribute_value(HTML::AttributeNames::accept).bytes_as_string_view().for_each_split_view(',', SplitBehavior::Nothing, [&](StringView value) { | ||||
|         // The string "audio/*"
 | ||||
|         //     Indicates that sound files are accepted.
 | ||||
|         if (value.equals_ignoring_ascii_case("audio/*"sv)) | ||||
|             filter.add_filter(FileFilter::FileType::Audio); | ||||
| 
 | ||||
|         // The string "video/*"
 | ||||
|         //     Indicates that video files are accepted.
 | ||||
|         if (value.equals_ignoring_ascii_case("video/*"sv)) | ||||
|             filter.add_filter(FileFilter::FileType::Video); | ||||
| 
 | ||||
|         // The string "image/*"
 | ||||
|         //     Indicates that image files are accepted.
 | ||||
|         if (value.equals_ignoring_ascii_case("image/*"sv)) | ||||
|             filter.add_filter(FileFilter::FileType::Image); | ||||
| 
 | ||||
|         // A valid MIME type string with no parameters
 | ||||
|         //     Indicates that files of the specified type are accepted.
 | ||||
|         else if (auto mime_type = MUST(MimeSniff::MimeType::parse(value)); mime_type.has_value() && mime_type->parameters().is_empty()) | ||||
|             filter.add_filter(FileFilter::MimeType { mime_type->essence() }); | ||||
| 
 | ||||
|         // A string whose first character is a U+002E FULL STOP character (.)
 | ||||
|         //     Indicates that files with the specified file extension are accepted.
 | ||||
|         else if (value.starts_with('.')) | ||||
|             filter.add_filter(FileFilter::Extension { MUST(String::from_utf8(value.substring_view(1))) }); | ||||
|     }); | ||||
| 
 | ||||
|     return filter; | ||||
| } | ||||
| 
 | ||||
| // https://html.spec.whatwg.org/multipage/input.html#update-the-file-selection
 | ||||
| void HTMLInputElement::update_the_file_selection(JS::NonnullGCPtr<FileAPI::FileList> files) | ||||
| { | ||||
|  | @ -227,12 +265,11 @@ static void show_the_picker_if_applicable(HTMLInputElement& element) | |||
|         //    with the bubbles attribute initialized to true.
 | ||||
|         // 5. Otherwise, update the file selection for element.
 | ||||
| 
 | ||||
|         auto accepted_file_types = element.parse_accept_attribute(); | ||||
|         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().did_request_file_picker(weak_element, allow_multiple_files); | ||||
|         element.document().browsing_context()->top_level_browsing_context()->page().did_request_file_picker(weak_element, move(accepted_file_types), allow_multiple_files); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ | |||
| #include <LibWeb/DOM/Text.h> | ||||
| #include <LibWeb/FileAPI/FileList.h> | ||||
| #include <LibWeb/HTML/ColorPickerUpdateState.h> | ||||
| #include <LibWeb/HTML/FileFilter.h> | ||||
| #include <LibWeb/HTML/FormAssociatedElement.h> | ||||
| #include <LibWeb/HTML/HTMLElement.h> | ||||
| #include <LibWeb/Layout/ImageProvider.h> | ||||
|  | @ -102,6 +103,8 @@ public: | |||
|     JS::GCPtr<FileAPI::FileList> files(); | ||||
|     void set_files(JS::GCPtr<FileAPI::FileList>); | ||||
| 
 | ||||
|     FileFilter parse_accept_attribute() const; | ||||
| 
 | ||||
|     // NOTE: User interaction
 | ||||
|     // https://html.spec.whatwg.org/multipage/input.html#update-the-file-selection
 | ||||
|     void update_the_file_selection(JS::NonnullGCPtr<FileAPI::FileList>); | ||||
|  |  | |||
|  | @ -344,13 +344,13 @@ void Page::color_picker_update(Optional<Color> picked_color, HTML::ColorPickerUp | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void Page::did_request_file_picker(WeakPtr<HTML::HTMLInputElement> target, HTML::AllowMultipleFiles allow_multiple_files) | ||||
| void Page::did_request_file_picker(WeakPtr<HTML::HTMLInputElement> target, HTML::FileFilter accepted_file_types, HTML::AllowMultipleFiles allow_multiple_files) | ||||
| { | ||||
|     if (m_pending_non_blocking_dialog == PendingNonBlockingDialog::None) { | ||||
|         m_pending_non_blocking_dialog = PendingNonBlockingDialog::FilePicker; | ||||
|         m_pending_non_blocking_dialog_target = move(target); | ||||
| 
 | ||||
|         m_client->page_did_request_file_picker(allow_multiple_files); | ||||
|         m_client->page_did_request_file_picker(move(accepted_file_types), allow_multiple_files); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -31,6 +31,7 @@ | |||
| #include <LibWeb/Forward.h> | ||||
| #include <LibWeb/HTML/ActivateTab.h> | ||||
| #include <LibWeb/HTML/ColorPickerUpdateState.h> | ||||
| #include <LibWeb/HTML/FileFilter.h> | ||||
| #include <LibWeb/HTML/SelectItem.h> | ||||
| #include <LibWeb/HTML/TokenizedFeatures.h> | ||||
| #include <LibWeb/HTML/WebViewHints.h> | ||||
|  | @ -134,7 +135,7 @@ public: | |||
|     void did_request_color_picker(WeakPtr<HTML::HTMLInputElement> target, Color current_color); | ||||
|     void color_picker_update(Optional<Color> picked_color, HTML::ColorPickerUpdateState state); | ||||
| 
 | ||||
|     void did_request_file_picker(WeakPtr<HTML::HTMLInputElement> target, HTML::AllowMultipleFiles); | ||||
|     void did_request_file_picker(WeakPtr<HTML::HTMLInputElement> target, HTML::FileFilter accepted_file_types, HTML::AllowMultipleFiles); | ||||
|     void file_picker_closed(Span<HTML::SelectedFile> selected_files); | ||||
| 
 | ||||
|     void did_request_select_dropdown(WeakPtr<HTML::HTMLSelectElement> target, Web::CSSPixelPoint content_position, Web::CSSPixels minimum_width, Vector<Web::HTML::SelectItem> items); | ||||
|  | @ -285,7 +286,7 @@ public: | |||
| 
 | ||||
|     // https://html.spec.whatwg.org/multipage/input.html#show-the-picker,-if-applicable
 | ||||
|     virtual void page_did_request_color_picker([[maybe_unused]] Color current_color) {}; | ||||
|     virtual void page_did_request_file_picker(Web::HTML::AllowMultipleFiles) {}; | ||||
|     virtual void page_did_request_file_picker([[maybe_unused]] HTML::FileFilter accepted_file_types, Web::HTML::AllowMultipleFiles) {}; | ||||
|     virtual void page_did_request_select_dropdown([[maybe_unused]] Web::CSSPixelPoint content_position, [[maybe_unused]] Web::CSSPixels minimum_width, [[maybe_unused]] Vector<Web::HTML::SelectItem> items) {}; | ||||
| 
 | ||||
|     virtual void page_did_finish_text_test() {}; | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ | |||
| #include <LibWeb/Forward.h> | ||||
| #include <LibWeb/HTML/ActivateTab.h> | ||||
| #include <LibWeb/HTML/ColorPickerUpdateState.h> | ||||
| #include <LibWeb/HTML/FileFilter.h> | ||||
| #include <LibWeb/HTML/SelectItem.h> | ||||
| #include <LibWeb/Page/InputEvent.h> | ||||
| #include <LibWebView/Forward.h> | ||||
|  | @ -170,7 +171,7 @@ public: | |||
|     Function<Gfx::IntRect()> on_minimize_window; | ||||
|     Function<Gfx::IntRect()> on_fullscreen_window; | ||||
|     Function<void(Color current_color)> on_request_color_picker; | ||||
|     Function<void(Web::HTML::AllowMultipleFiles)> on_request_file_picker; | ||||
|     Function<void(Web::HTML::FileFilter const& accepted_file_types, Web::HTML::AllowMultipleFiles)> on_request_file_picker; | ||||
|     Function<void(Gfx::IntPoint content_position, i32 minimum_width, Vector<Web::HTML::SelectItem> items)> on_request_select_dropdown; | ||||
|     Function<void(Web::KeyEvent const&)> on_finish_handling_key_event; | ||||
|     Function<void()> on_text_test_finish; | ||||
|  |  | |||
|  | @ -806,7 +806,7 @@ void WebContentClient::did_request_color_picker(u64 page_id, Color const& curren | |||
|         view.on_request_color_picker(current_color); | ||||
| } | ||||
| 
 | ||||
| void WebContentClient::did_request_file_picker(u64 page_id, Web::HTML::AllowMultipleFiles allow_multiple_files) | ||||
| void WebContentClient::did_request_file_picker(u64 page_id, Web::HTML::FileFilter const& accepted_file_types, Web::HTML::AllowMultipleFiles allow_multiple_files) | ||||
| { | ||||
|     auto maybe_view = m_views.get(page_id); | ||||
|     if (!maybe_view.has_value()) { | ||||
|  | @ -816,7 +816,7 @@ void WebContentClient::did_request_file_picker(u64 page_id, Web::HTML::AllowMult | |||
|     auto& view = *maybe_view.value(); | ||||
| 
 | ||||
|     if (view.on_request_file_picker) | ||||
|         view.on_request_file_picker(allow_multiple_files); | ||||
|         view.on_request_file_picker(accepted_file_types, allow_multiple_files); | ||||
| } | ||||
| 
 | ||||
| void WebContentClient::did_request_select_dropdown(u64 page_id, Gfx::IntPoint content_position, i32 minimum_width, Vector<Web::HTML::SelectItem> const& items) | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ | |||
| #include <AK/HashMap.h> | ||||
| #include <LibIPC/ConnectionToServer.h> | ||||
| #include <LibWeb/HTML/ActivateTab.h> | ||||
| #include <LibWeb/HTML/FileFilter.h> | ||||
| #include <LibWeb/HTML/SelectItem.h> | ||||
| #include <LibWeb/HTML/WebViewHints.h> | ||||
| #include <WebContent/WebContentClientEndpoint.h> | ||||
|  | @ -89,7 +90,7 @@ private: | |||
|     virtual Messages::WebContentClient::DidRequestFullscreenWindowResponse did_request_fullscreen_window(u64 page_id) override; | ||||
|     virtual void did_request_file(u64 page_id, ByteString const& path, i32) override; | ||||
|     virtual void did_request_color_picker(u64 page_id, Color const& current_color) override; | ||||
|     virtual void did_request_file_picker(u64 page_id, Web::HTML::AllowMultipleFiles) override; | ||||
|     virtual void did_request_file_picker(u64 page_id, Web::HTML::FileFilter const& accepted_file_types, Web::HTML::AllowMultipleFiles) override; | ||||
|     virtual void did_request_select_dropdown(u64 page_id, Gfx::IntPoint content_position, i32 minimum_width, Vector<Web::HTML::SelectItem> const& items) override; | ||||
|     virtual void did_finish_handling_input_event(u64 page_id, bool event_was_accepted) override; | ||||
|     virtual void did_finish_text_test(u64 page_id) override; | ||||
|  |  | |||
|  | @ -549,9 +549,9 @@ void PageClient::page_did_request_color_picker(Color current_color) | |||
|     client().async_did_request_color_picker(m_id, current_color); | ||||
| } | ||||
| 
 | ||||
| void PageClient::page_did_request_file_picker(Web::HTML::AllowMultipleFiles allow_multiple_files) | ||||
| void PageClient::page_did_request_file_picker(Web::HTML::FileFilter accepted_file_types, Web::HTML::AllowMultipleFiles allow_multiple_files) | ||||
| { | ||||
|     client().async_did_request_file_picker(m_id, allow_multiple_files); | ||||
|     client().async_did_request_file_picker(m_id, move(accepted_file_types), allow_multiple_files); | ||||
| } | ||||
| 
 | ||||
| void PageClient::page_did_request_select_dropdown(Web::CSSPixelPoint content_position, Web::CSSPixels minimum_width, Vector<Web::HTML::SelectItem> items) | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ | |||
| 
 | ||||
| #include <LibAccelGfx/Forward.h> | ||||
| #include <LibGfx/Rect.h> | ||||
| #include <LibWeb/HTML/FileFilter.h> | ||||
| #include <LibWeb/Page/Page.h> | ||||
| #include <LibWeb/PixelUnits.h> | ||||
| #include <WebContent/Forward.h> | ||||
|  | @ -133,7 +134,7 @@ private: | |||
|     virtual void page_did_close_top_level_traversable() override; | ||||
|     virtual void request_file(Web::FileRequest) override; | ||||
|     virtual void page_did_request_color_picker(Color current_color) override; | ||||
|     virtual void page_did_request_file_picker(Web::HTML::AllowMultipleFiles) override; | ||||
|     virtual void page_did_request_file_picker(Web::HTML::FileFilter accepted_file_types, Web::HTML::AllowMultipleFiles) override; | ||||
|     virtual void page_did_request_select_dropdown(Web::CSSPixelPoint content_position, Web::CSSPixels minimum_width, Vector<Web::HTML::SelectItem> items) override; | ||||
|     virtual void page_did_finish_text_test() override; | ||||
|     virtual void page_did_change_theme_color(Gfx::Color color) override; | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| #include <LibWeb/Cookie/ParsedCookie.h> | ||||
| #include <LibWeb/CSS/Selector.h> | ||||
| #include <LibWeb/HTML/ActivateTab.h> | ||||
| #include <LibWeb/HTML/FileFilter.h> | ||||
| #include <LibWeb/HTML/SelectedFile.h> | ||||
| #include <LibWeb/HTML/SelectItem.h> | ||||
| #include <LibWeb/HTML/WebViewHints.h> | ||||
|  | @ -71,7 +72,7 @@ endpoint WebContentClient | |||
|     did_request_fullscreen_window(u64 page_id) => (Gfx::IntRect window_rect) | ||||
|     did_request_file(u64 page_id, ByteString path, i32 request_id) =| | ||||
|     did_request_color_picker(u64 page_id, Color current_color) =| | ||||
|     did_request_file_picker(u64 page_id, Web::HTML::AllowMultipleFiles allow_multiple_files) =| | ||||
|     did_request_file_picker(u64 page_id, Web::HTML::FileFilter accepted_file_types, Web::HTML::AllowMultipleFiles allow_multiple_files) =| | ||||
|     did_request_select_dropdown(u64 page_id, Gfx::IntPoint content_position, i32 minimum_width, Vector<Web::HTML::SelectItem> items) =| | ||||
|     did_finish_handling_input_event(u64 page_id, bool event_was_accepted) =| | ||||
|     did_change_theme_color(u64 page_id, Gfx::Color color) =| | ||||
|  |  | |||
|  | @ -436,9 +436,27 @@ static ErrorOr<TestResult> run_test(HeadlessWebContentView& view, StringView inp | |||
|     }; | ||||
|     view.on_text_test_finish = {}; | ||||
| 
 | ||||
|     view.on_request_file_picker = [&](auto allow_multiple_files) { | ||||
|     view.on_request_file_picker = [&](auto const& accepted_file_types, auto allow_multiple_files) { | ||||
|         // Create some dummy files for tests.
 | ||||
|         Vector<Web::HTML::SelectedFile> selected_files; | ||||
| 
 | ||||
|         bool add_txt_files = accepted_file_types.filters.is_empty(); | ||||
|         bool add_cpp_files = false; | ||||
| 
 | ||||
|         for (auto const& filter : accepted_file_types.filters) { | ||||
|             filter.visit( | ||||
|                 [](Web::HTML::FileFilter::FileType) {}, | ||||
|                 [&](Web::HTML::FileFilter::MimeType const& mime_type) { | ||||
|                     if (mime_type.value == "text/plain"sv) | ||||
|                         add_txt_files = true; | ||||
|                 }, | ||||
|                 [&](Web::HTML::FileFilter::Extension const& extension) { | ||||
|                     if (extension.value == "cpp"sv) | ||||
|                         add_cpp_files = true; | ||||
|                 }); | ||||
|         } | ||||
| 
 | ||||
|         if (add_txt_files) { | ||||
|             selected_files.empend("file1"sv, MUST(ByteBuffer::copy("Contents for file1"sv.bytes()))); | ||||
| 
 | ||||
|             if (allow_multiple_files == Web::HTML::AllowMultipleFiles::Yes) { | ||||
|  | @ -446,6 +464,15 @@ static ErrorOr<TestResult> run_test(HeadlessWebContentView& view, StringView inp | |||
|                 selected_files.empend("file3"sv, MUST(ByteBuffer::copy("Contents for file3"sv.bytes()))); | ||||
|                 selected_files.empend("file4"sv, MUST(ByteBuffer::copy("Contents for file4"sv.bytes()))); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (add_cpp_files) { | ||||
|             selected_files.empend("file1.cpp"sv, MUST(ByteBuffer::copy("int main() {{ return 1; }}"sv.bytes()))); | ||||
| 
 | ||||
|             if (allow_multiple_files == Web::HTML::AllowMultipleFiles::Yes) { | ||||
|                 selected_files.empend("file2.cpp"sv, MUST(ByteBuffer::copy("int main() {{ return 2; }}"sv.bytes()))); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         view.file_picker_closed(move(selected_files)); | ||||
|     }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Timothy Flynn
						Timothy Flynn