diff --git a/Tests/LibWeb/TestMimeSniff.cpp b/Tests/LibWeb/TestMimeSniff.cpp index 7c6d01e30d9..a0c959d7778 100644 --- a/Tests/LibWeb/TestMimeSniff.cpp +++ b/Tests/LibWeb/TestMimeSniff.cpp @@ -38,7 +38,7 @@ TEST_CASE(determine_computed_mime_type_given_no_sniff_is_unset) TEST_CASE(determine_computed_mime_type_given_xml_mime_type_as_supplied_type) { auto xml_mime_type = "application/rss+xml"sv; - auto supplied_type = MUST(Web::MimeSniff::MimeType::parse(xml_mime_type)).release_value(); + auto supplied_type = Web::MimeSniff::MimeType::parse(xml_mime_type).release_value(); auto computed_mime_type = MUST(Web::MimeSniff::Resource::sniff("\x00"sv.bytes(), Web::MimeSniff::SniffingConfiguration { .supplied_type = supplied_type })); EXPECT_EQ(xml_mime_type, computed_mime_type.serialized()); @@ -85,7 +85,7 @@ TEST_CASE(determine_computed_mime_type_given_supplied_type_that_is_an_apache_bug // Cover all Apache bug MIME types. for (auto const& apache_bug_mime_type : apache_bug_mime_types) { - auto supplied_type = MUST(Web::MimeSniff::MimeType::parse(apache_bug_mime_type)).release_value(); + auto supplied_type = Web::MimeSniff::MimeType::parse(apache_bug_mime_type).release_value(); auto computed_mime_type = MUST(Web::MimeSniff::Resource::sniff("Hello world!"sv.bytes(), Web::MimeSniff::SniffingConfiguration { .scheme = "http"sv, .supplied_type = supplied_type })); @@ -195,7 +195,7 @@ TEST_CASE(determine_computed_mime_type_in_image_sniffing_context) { // Cover case where supplied type is an XML MIME type. auto mime_type = "application/rss+xml"sv; - auto supplied_type = MUST(Web::MimeSniff::MimeType::parse(mime_type)).release_value(); + auto supplied_type = Web::MimeSniff::MimeType::parse(mime_type).release_value(); auto computed_mime_type = MUST(Web::MimeSniff::Resource::sniff(""sv.bytes(), Web::MimeSniff::SniffingConfiguration { .sniffing_context = Web::MimeSniff::SniffingContext::Image, .supplied_type = supplied_type })); EXPECT_EQ(mime_type, computed_mime_type.serialized()); @@ -218,7 +218,7 @@ TEST_CASE(determine_computed_mime_type_in_image_sniffing_context) // Cover case where we aren't dealing with an image MIME type. mime_type = "text/html"sv; - supplied_type = MUST(Web::MimeSniff::MimeType::parse("text/html"sv)).release_value(); + supplied_type = Web::MimeSniff::MimeType::parse("text/html"sv).release_value(); computed_mime_type = MUST(Web::MimeSniff::Resource::sniff(""sv.bytes(), Web::MimeSniff::SniffingConfiguration { .sniffing_context = Web::MimeSniff::SniffingContext::Image, .supplied_type = supplied_type })); EXPECT_EQ(mime_type, computed_mime_type.essence()); @@ -228,7 +228,7 @@ TEST_CASE(determine_computed_mime_type_in_audio_or_video_sniffing_context) { // Cover case where supplied type is an XML MIME type. auto mime_type = "application/rss+xml"sv; - auto supplied_type = MUST(Web::MimeSniff::MimeType::parse(mime_type)).release_value(); + auto supplied_type = Web::MimeSniff::MimeType::parse(mime_type).release_value(); auto computed_mime_type = MUST(Web::MimeSniff::Resource::sniff(""sv.bytes(), Web::MimeSniff::SniffingConfiguration { .sniffing_context = Web::MimeSniff::SniffingContext::AudioOrVideo, .supplied_type = supplied_type, @@ -253,7 +253,7 @@ TEST_CASE(determine_computed_mime_type_in_audio_or_video_sniffing_context) // Cover case where we aren't dealing with an audio or video MIME type. mime_type = "text/html"sv; - supplied_type = MUST(Web::MimeSniff::MimeType::parse("text/html"sv)).release_value(); + supplied_type = Web::MimeSniff::MimeType::parse("text/html"sv).release_value(); computed_mime_type = MUST(Web::MimeSniff::Resource::sniff(""sv.bytes(), Web::MimeSniff::SniffingConfiguration { .sniffing_context = Web::MimeSniff::SniffingContext::AudioOrVideo, .supplied_type = supplied_type, @@ -299,7 +299,7 @@ TEST_CASE(determine_computed_mime_type_in_a_font_context) { // Cover case where supplied type is an XML MIME type. auto mime_type = "application/rss+xml"sv; - auto supplied_type = MUST(Web::MimeSniff::MimeType::parse(mime_type)).release_value(); + auto supplied_type = Web::MimeSniff::MimeType::parse(mime_type).release_value(); auto computed_mime_type = MUST(Web::MimeSniff::Resource::sniff(""sv.bytes(), Web::MimeSniff::SniffingConfiguration { .sniffing_context = Web::MimeSniff::SniffingContext::Font, .supplied_type = supplied_type, @@ -327,7 +327,7 @@ TEST_CASE(determine_computed_mime_type_in_a_font_context) // Cover case where we aren't dealing with a font MIME type. mime_type = "text/html"sv; - supplied_type = MUST(Web::MimeSniff::MimeType::parse("text/html"sv)).release_value(); + supplied_type = Web::MimeSniff::MimeType::parse("text/html"sv).release_value(); computed_mime_type = MUST(Web::MimeSniff::Resource::sniff(""sv.bytes(), Web::MimeSniff::SniffingConfiguration { .sniffing_context = Web::MimeSniff::SniffingContext::Font, .supplied_type = supplied_type, @@ -374,7 +374,7 @@ TEST_CASE(determine_minimised_mime_type) mime_type_to_minimised_mime_type_map.set("application/zip"sv, ""sv); for (auto const& mime_type_to_minimised_mime_type : mime_type_to_minimised_mime_type_map) { - auto mime_type = MUST(Web::MimeSniff::MimeType::parse(mime_type_to_minimised_mime_type.key)).release_value(); + auto mime_type = Web::MimeSniff::MimeType::parse(mime_type_to_minimised_mime_type.key).release_value(); EXPECT_EQ(mime_type_to_minimised_mime_type.value, Web::MimeSniff::minimise_a_supported_mime_type(mime_type)); } } diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index 37824efe17b..277d1f30698 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -181,7 +181,7 @@ void FontLoader::start_loading_next_url() ErrorOr> FontLoader::try_load_font() { // FIXME: This could maybe use the format() provided in @font-face as well, since often the mime type is just application/octet-stream and we have to try every format - auto mime_type = MUST(MimeSniff::MimeType::parse(resource()->mime_type())); + auto mime_type = MimeSniff::MimeType::parse(resource()->mime_type()); if (!mime_type.has_value() || !mime_type->is_font()) { mime_type = MUST(MimeSniff::Resource::sniff(resource()->encoded_data(), Web::MimeSniff::SniffingConfiguration { .sniffing_context = Web::MimeSniff::SniffingContext::Font })); } diff --git a/Userland/Libraries/LibWeb/Clipboard/Clipboard.cpp b/Userland/Libraries/LibWeb/Clipboard/Clipboard.cpp index f4a2d44d30a..8aa4191e373 100644 --- a/Userland/Libraries/LibWeb/Clipboard/Clipboard.cpp +++ b/Userland/Libraries/LibWeb/Clipboard/Clipboard.cpp @@ -44,7 +44,7 @@ void Clipboard::initialize(JS::Realm& realm) static String os_specific_well_known_format(StringView mime_type_string) { // NOTE: Here we always takes the Linux case, and defer to the chrome layer to handle OS specific implementations. - auto mime_type = MUST(MimeSniff::MimeType::parse(mime_type_string)); + auto mime_type = MimeSniff::MimeType::parse(mime_type_string); // 1. Let wellKnownFormat be an empty string. String well_known_format {}; diff --git a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp index 5c53011752d..ed07b9977ee 100644 --- a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp +++ b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp @@ -365,7 +365,7 @@ Optional HeaderList::extract_mime_type() const // 6. For each value of values: for (auto const& value : *values) { // 1. Let temporaryMimeType be the result of parsing value. - auto temporary_mime_type = MUST(MimeSniff::MimeType::parse(value)); + auto temporary_mime_type = MimeSniff::MimeType::parse(value); // 2. If temporaryMimeType is failure or its essence is "*/*", then continue. if (!temporary_mime_type.has_value() || temporary_mime_type->essence() == "*/*"sv) @@ -523,7 +523,7 @@ bool is_cors_safelisted_request_header(Header const& header) return false; // 2. Let mimeType be the result of parsing the result of isomorphic decoding value. - auto mime_type = MimeSniff::MimeType::parse(StringView { value }).release_value_but_fixme_should_propagate_errors(); + auto mime_type = MimeSniff::MimeType::parse(StringView { value }); // 3. If mimeType is failure, then return false. if (!mime_type.has_value()) diff --git a/Userland/Libraries/LibWeb/Fetch/Infrastructure/URL.cpp b/Userland/Libraries/LibWeb/Fetch/Infrastructure/URL.cpp index 3c332aa7829..509489b3190 100644 --- a/Userland/Libraries/LibWeb/Fetch/Infrastructure/URL.cpp +++ b/Userland/Libraries/LibWeb/Fetch/Infrastructure/URL.cpp @@ -97,7 +97,7 @@ ErrorOr process_data_url(URL::URL const& data_url) } // 13. Let mimeTypeRecord be the result of parsing mimeType. - auto mime_type_record = TRY(MimeSniff::MimeType::parse(mime_type)); + auto mime_type_record = MimeSniff::MimeType::parse(mime_type); // 14. If mimeTypeRecord is failure, then set mimeTypeRecord to text/plain;charset=US-ASCII. if (!mime_type_record.has_value()) { diff --git a/Userland/Libraries/LibWeb/FileAPI/Blob.cpp b/Userland/Libraries/LibWeb/FileAPI/Blob.cpp index 4c852ceecd4..0c6aad5c1d3 100644 --- a/Userland/Libraries/LibWeb/FileAPI/Blob.cpp +++ b/Userland/Libraries/LibWeb/FileAPI/Blob.cpp @@ -204,7 +204,7 @@ JS::NonnullGCPtr Blob::create(JS::Realm& realm, Optional> // NOTE: The spec is out of date, and we are supposed to call into the MimeType parser here. if (!options->type.is_empty()) { - auto maybe_parsed_type = MUST(Web::MimeSniff::MimeType::parse(options->type)); + auto maybe_parsed_type = Web::MimeSniff::MimeType::parse(options->type); if (maybe_parsed_type.has_value()) type = maybe_parsed_type->serialized(); diff --git a/Userland/Libraries/LibWeb/FileAPI/File.cpp b/Userland/Libraries/LibWeb/FileAPI/File.cpp index facaaa9b76d..14a6e4652f1 100644 --- a/Userland/Libraries/LibWeb/FileAPI/File.cpp +++ b/Userland/Libraries/LibWeb/FileAPI/File.cpp @@ -62,7 +62,7 @@ WebIDL::ExceptionOr> File::create(JS::Realm& realm, Vecto // FIXME: 2. Convert every character in t to ASCII lowercase. // NOTE: The spec is out of date, and we are supposed to call into the MimeType parser here. - auto maybe_parsed_type = MUST(Web::MimeSniff::MimeType::parse(options->type)); + auto maybe_parsed_type = Web::MimeSniff::MimeType::parse(options->type); if (maybe_parsed_type.has_value()) type = maybe_parsed_type->serialized(); diff --git a/Userland/Libraries/LibWeb/FileAPI/FileReader.cpp b/Userland/Libraries/LibWeb/FileAPI/FileReader.cpp index 39a09bfb8f2..fd46132f7a8 100644 --- a/Userland/Libraries/LibWeb/FileAPI/FileReader.cpp +++ b/Userland/Libraries/LibWeb/FileAPI/FileReader.cpp @@ -86,8 +86,8 @@ WebIDL::ExceptionOr FileReader::blob_package_data(JS::Realm& auto maybe_type = MimeSniff::MimeType::parse(mime_type.value()); // 2. If type is not failure, set encoding to the result of getting an encoding from type’s parameters["charset"]. - if (!maybe_type.is_error() && maybe_type.value().has_value()) { - auto type = maybe_type.release_value().value(); + if (maybe_type.has_value()) { + auto const& type = maybe_type.value(); auto it = type.parameters().find("charset"sv); if (it != type.parameters().end()) encoding = TextCodec::get_standardized_encoding(it->value); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 177f9639a03..d76385297e3 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -235,7 +235,7 @@ FileFilter HTMLInputElement::parse_accept_attribute() const // 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()) + else if (auto mime_type = 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 (.) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp index 3e6ca577170..230a4df06e2 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp @@ -186,7 +186,7 @@ Bindings::CanPlayTypeResult HTMLMediaElement::can_play_type(StringView type) con if (type == "application/octet-stream"sv) return Bindings::CanPlayTypeResult::Empty; - auto mime_type = MUST(MimeSniff::MimeType::parse(type)); + auto mime_type = MimeSniff::MimeType::parse(type); if (mime_type.has_value() && mime_type->type() == "video"sv) { if (mime_type->subtype() == "webm"sv) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp index 8e356903fca..b49330be5f6 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp @@ -246,7 +246,7 @@ void HTMLObjectElement::resource_did_load() // 2. If the type specified in the resource's Content-Type metadata is "text/plain", and the result of applying the rules for distinguishing if a resource is text or binary to the resource is that the resource is not text/plain, then set binary to true. if (content_type == "text/plain"sv) { - auto supplied_type = MimeSniff::MimeType::parse(content_type).release_value_but_fixme_should_propagate_errors(); + auto supplied_type = MimeSniff::MimeType::parse(content_type); auto computed_type = MimeSniff::Resource::sniff(resource()->encoded_data(), MimeSniff::SniffingConfiguration { .sniffing_context = MimeSniff::SniffingContext::TextOrBinary, .supplied_type = move(supplied_type), @@ -311,7 +311,7 @@ void HTMLObjectElement::run_object_representation_handler_steps(Optionalis_xml() || !mime_type->is_image())) { diff --git a/Userland/Libraries/LibWeb/MimeSniff/MimeType.cpp b/Userland/Libraries/LibWeb/MimeSniff/MimeType.cpp index 77341cabca2..5bda652a713 100644 --- a/Userland/Libraries/LibWeb/MimeSniff/MimeType.cpp +++ b/Userland/Libraries/LibWeb/MimeSniff/MimeType.cpp @@ -23,7 +23,7 @@ bool is_javascript_mime_type_essence_match(StringView string) { // A string is a JavaScript MIME type essence match if it is an ASCII case-insensitive match for one of the JavaScript MIME type essence strings. // NOTE: The mime type parser automatically lowercases the essence. - auto type = MimeType::parse(string).release_value_but_fixme_should_propagate_errors(); + auto type = MimeType::parse(string); if (!type.has_value()) return false; return type->is_javascript(); @@ -81,8 +81,12 @@ MimeType MimeType::create(String type, String subtype) } // https://mimesniff.spec.whatwg.org/#parse-a-mime-type -ErrorOr> MimeType::parse(StringView string) +Optional MimeType::parse(StringView string) { + // Verify that the input string is valid UTF-8 first, so we don't have to think about it anymore. + if (!Utf8View(string).validate()) + return OptionalNone {}; + // 1. Remove any leading and trailing HTTP whitespace from input. auto trimmed_string = string.trim(Fetch::Infrastructure::HTTP_WHITESPACE, TrimMode::Both); @@ -114,7 +118,7 @@ ErrorOr> MimeType::parse(StringView string) return OptionalNone {}; // 10. Let mimeType be a new MIME type record whose type is type, in ASCII lowercase, and subtype is subtype, in ASCII lowercase. - auto mime_type = MimeType::create(TRY(Infra::to_ascii_lowercase(type)), TRY(Infra::to_ascii_lowercase(subtype))); + auto mime_type = MimeType::create(MUST(Infra::to_ascii_lowercase(type)), MUST(Infra::to_ascii_lowercase(subtype))); // 11. While position is not past the end of input: while (!lexer.is_eof()) { @@ -130,7 +134,7 @@ ErrorOr> MimeType::parse(StringView string) }); // 4. Set parameterName to parameterName, in ASCII lowercase. - auto parameter_name = TRY(Infra::to_ascii_lowercase(parameter_name_view)); + auto parameter_name = MUST(Infra::to_ascii_lowercase(parameter_name_view)); // 5. If position is not past the end of input, then: if (!lexer.is_eof()) { @@ -162,10 +166,10 @@ ErrorOr> MimeType::parse(StringView string) // 9. Otherwise: else { // 1. Set parameterValue to the result of collecting a sequence of code points that are not U+003B (;) from input, given position. - parameter_value = TRY(String::from_utf8(lexer.consume_until(';'))); + parameter_value = String::from_utf8_without_validation(lexer.consume_until(';').bytes()); // 2. Remove any trailing HTTP whitespace from parameterValue. - parameter_value = TRY(parameter_value.trim(Fetch::Infrastructure::HTTP_WHITESPACE, TrimMode::Right)); + parameter_value = MUST(parameter_value.trim(Fetch::Infrastructure::HTTP_WHITESPACE, TrimMode::Right)); // 3. If parameterValue is the empty string, then continue. if (parameter_value.is_empty()) @@ -183,7 +187,7 @@ ErrorOr> MimeType::parse(StringView string) // - mimeType’s parameters[parameterName] does not exist && !mime_type.m_parameters.contains(parameter_name)) { // then set mimeType’s parameters[parameterName] to parameterValue. - TRY(mime_type.m_parameters.try_set(move(parameter_name), move(parameter_value))); + mime_type.m_parameters.set(move(parameter_name), move(parameter_value)); } } diff --git a/Userland/Libraries/LibWeb/MimeSniff/MimeType.h b/Userland/Libraries/LibWeb/MimeSniff/MimeType.h index 0ad37e022d1..d6b9f9d0d8e 100644 --- a/Userland/Libraries/LibWeb/MimeSniff/MimeType.h +++ b/Userland/Libraries/LibWeb/MimeSniff/MimeType.h @@ -17,8 +17,8 @@ bool is_javascript_mime_type_essence_match(StringView); // https://mimesniff.spec.whatwg.org/#mime-type class MimeType { public: - static MimeType create(String type, String subtype); - static ErrorOr> parse(StringView); + [[nodiscard]] static MimeType create(String type, String subtype); + [[nodiscard]] static Optional parse(StringView); MimeType(MimeType const&); MimeType& operator=(MimeType const&); diff --git a/Userland/Libraries/LibWeb/MimeSniff/Resource.cpp b/Userland/Libraries/LibWeb/MimeSniff/Resource.cpp index 08d8963ad8a..020035f8567 100644 --- a/Userland/Libraries/LibWeb/MimeSniff/Resource.cpp +++ b/Userland/Libraries/LibWeb/MimeSniff/Resource.cpp @@ -388,7 +388,7 @@ ErrorOr rules_for_identifying_an_unknown_mime_type(Resource const& res // 2. If patternMatched is true, return the value in the fourth column of row. if (pattern_matched) { - if (auto maybe_type = TRY(MimeType::parse(row.mime_type)); maybe_type.has_value()) + if (auto maybe_type = MimeType::parse(row.mime_type); maybe_type.has_value()) return maybe_type.release_value(); } } @@ -419,7 +419,7 @@ ErrorOr rules_for_identifying_an_unknown_mime_type(Resource const& res // 2. If patternMatched is true, return the value in the fourth column of row. if (pattern_matched) { - if (auto maybe_type = TRY(MimeType::parse(row.mime_type)); maybe_type.has_value()) + if (auto maybe_type = MimeType::parse(row.mime_type); maybe_type.has_value()) return maybe_type.release_value(); } } diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp index ccb08dbead8..646426735d4 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp @@ -594,7 +594,7 @@ WebIDL::ExceptionOr XMLHttpRequest::send(Optionalhas>() || body->has()) { // 1. Let contentTypeRecord be the result of parsing originalAuthorContentType. - auto content_type_record = TRY_OR_THROW_OOM(vm, MimeSniff::MimeType::parse(original_author_content_type.value())); + auto content_type_record = MimeSniff::MimeType::parse(original_author_content_type.value()); // 2. If contentTypeRecord is not failure, contentTypeRecord’s parameters["charset"] exists, and parameters["charset"] is not an ASCII case-insensitive match for "UTF-8", then: if (content_type_record.has_value()) { @@ -1028,14 +1028,12 @@ WebIDL::ExceptionOr XMLHttpRequest::get_all_response_headers() const // https://xhr.spec.whatwg.org/#dom-xmlhttprequest-overridemimetype WebIDL::ExceptionOr XMLHttpRequest::override_mime_type(String const& mime) { - auto& vm = this->vm(); - // 1. If this’s state is loading or done, then throw an "InvalidStateError" DOMException. if (m_state == State::Loading || m_state == State::Done) return WebIDL::InvalidStateError::create(realm(), "Cannot override MIME type when state is Loading or Done."_string); // 2. Set this’s override MIME type to the result of parsing mime. - m_override_mime_type = TRY_OR_THROW_OOM(vm, MimeSniff::MimeType::parse(mime)); + m_override_mime_type = MimeSniff::MimeType::parse(mime); // 3. If this’s override MIME type is failure, then set this’s override MIME type to application/octet-stream. if (!m_override_mime_type.has_value())