From d612ca1fcc624b83cc7f72ea060153cb73ceb53c Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 10 May 2020 21:28:54 +0200 Subject: [PATCH] LibWeb: Render content based on MIME type provided by server (or guess) We now look at the Content-Type HTTP header when deciding how to render some loaded content. If there is no Content-Type header (which will always be the case when loading local files, for example), we make a guess based on the URL filename. --- Libraries/LibWeb/HtmlView.cpp | 64 ++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/Libraries/LibWeb/HtmlView.cpp b/Libraries/LibWeb/HtmlView.cpp index 84c379f224..f731580315 100644 --- a/Libraries/LibWeb/HtmlView.cpp +++ b/Libraries/LibWeb/HtmlView.cpp @@ -396,6 +396,41 @@ String encoding_from_content_type(const String& content_type) return "utf-8"; } +String mime_type_from_content_type(const String& content_type) +{ + auto offset = content_type.index_of(";"); + if (offset.has_value()) + return content_type.substring(0, offset.value()).to_lowercase(); + + return content_type; +} + +static String guess_mime_type_based_on_filename(const URL& url) +{ + if (url.path().ends_with(".png")) + return "image/png"; + if (url.path().ends_with(".gif")) + return "image/gif"; + if (url.path().ends_with(".md")) + return "text/markdown"; + if (url.path().ends_with(".html") || url.path().ends_with(".htm")) + return "text/html"; + return "text/plain"; +} + +static RefPtr create_document_from_mime_type(const ByteBuffer& data, const URL& url, const String& mime_type, const String& encoding) +{ + if (mime_type.starts_with("image/")) + return create_image_document(data, url); + if (mime_type == "text/plain") + return create_text_document(data, url); + if (mime_type == "text/markdown") + return create_markdown_document(data, url); + if (mime_type == "text/html") + return parse_html_document(data, url, encoding); + return nullptr; +} + void HtmlView::load(const URL& url) { dbg() << "HtmlView::load: " << url.to_string(); @@ -426,24 +461,21 @@ void HtmlView::load(const URL& url) return; } - RefPtr document; - if (url.path().ends_with(".png") || url.path().ends_with(".gif")) { - document = create_image_document(data, url); - } else if (url.path().ends_with(".txt")) { - document = create_text_document(data, url); - } else if (url.path().ends_with(".md")) { - document = create_markdown_document(data, url); + String encoding = "utf-8"; + String mime_type; + + auto content_type = response_headers.get("Content-Type"); + if (content_type.has_value()) { + dbg() << "Content-Type header: _" << content_type.value() << "_"; + encoding = encoding_from_content_type(content_type.value()); + mime_type = mime_type_from_content_type(content_type.value()); } else { - String encoding = "utf-8"; - - auto content_type = response_headers.get("Content-Type"); - if (content_type.has_value()) { - encoding = encoding_from_content_type(content_type.value()); - dbg() << "I think this content has encoding '" << encoding << "'"; - } - - document = parse_html_document(data, url, encoding); + dbg() << "No Content-Type header to go on! Guessing based on filename..."; + mime_type = guess_mime_type_based_on_filename(url); } + + dbg() << "I believe this content has MIME type '" << mime_type << "', encoding '" << encoding << "'"; + auto document = create_document_from_mime_type(data, url, mime_type, encoding); ASSERT(document); set_document(document); if (on_title_change)