Skip to content

Commit f88146c

Browse files
committed
LibWeb: Let Resource figure out its own encoding and MIME type
Also, if the request URL is a data: URL, use the MIME type from the URL itself if available. This makes it possible to load arbitrary MIME type data: URLs in the browser :^)
1 parent efe9d36 commit f88146c

File tree

3 files changed

+53
-46
lines changed

3 files changed

+53
-46
lines changed

Libraries/LibWeb/Loader/FrameLoader.cpp

Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -118,37 +118,6 @@ static RefPtr<Document> create_gemini_document(const ByteBuffer& data, const URL
118118
return parse_html_document(markdown_document->render_to_html(), url);
119119
}
120120

121-
String encoding_from_content_type(const String& content_type)
122-
{
123-
auto offset = content_type.index_of("charset=");
124-
if (offset.has_value())
125-
return content_type.substring(offset.value() + 8, content_type.length() - offset.value() - 8).to_lowercase();
126-
127-
return "utf-8";
128-
}
129-
130-
String mime_type_from_content_type(const String& content_type)
131-
{
132-
auto offset = content_type.index_of(";");
133-
if (offset.has_value())
134-
return content_type.substring(0, offset.value()).to_lowercase();
135-
136-
return content_type;
137-
}
138-
139-
static String guess_mime_type_based_on_filename(const URL& url)
140-
{
141-
if (url.path().ends_with(".png"))
142-
return "image/png";
143-
if (url.path().ends_with(".gif"))
144-
return "image/gif";
145-
if (url.path().ends_with(".md"))
146-
return "text/markdown";
147-
if (url.path().ends_with(".html") || url.path().ends_with(".htm"))
148-
return "text/html";
149-
return "text/plain";
150-
}
151-
152121
RefPtr<Document> FrameLoader::create_document_from_mime_type(const ByteBuffer& data, const URL& url, const String& mime_type, const String& encoding)
153122
{
154123
if (mime_type.starts_with("image/"))
@@ -250,21 +219,8 @@ void FrameLoader::resource_did_load()
250219
return;
251220
}
252221

253-
String encoding = "utf-8";
254-
String mime_type;
255-
256-
auto content_type = resource()->response_headers().get("Content-Type");
257-
if (content_type.has_value()) {
258-
dbg() << "Content-Type header: _" << content_type.value() << "_";
259-
encoding = encoding_from_content_type(content_type.value());
260-
mime_type = mime_type_from_content_type(content_type.value());
261-
} else {
262-
dbg() << "No Content-Type header to go on! Guessing based on filename...";
263-
mime_type = guess_mime_type_based_on_filename(url);
264-
}
265-
266-
dbg() << "I believe this content has MIME type '" << mime_type << "', encoding '" << encoding << "'";
267-
auto document = create_document_from_mime_type(resource()->encoded_data(), url, mime_type, encoding);
222+
dbg() << "I believe this content has MIME type '" << resource()->mime_type() << "', encoding '" << resource()->encoding() << "'";
223+
auto document = create_document_from_mime_type(resource()->encoded_data(), url, resource()->mime_type(), resource()->encoding());
268224
ASSERT(document);
269225
frame().set_document(document);
270226

Libraries/LibWeb/Loader/Resource.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,59 @@ void Resource::for_each_client(Function<void(ResourceClient&)> callback)
5959
}
6060
}
6161

62+
String encoding_from_content_type(const String& content_type)
63+
{
64+
auto offset = content_type.index_of("charset=");
65+
if (offset.has_value())
66+
return content_type.substring(offset.value() + 8, content_type.length() - offset.value() - 8).to_lowercase();
67+
68+
return "utf-8";
69+
}
70+
71+
String mime_type_from_content_type(const String& content_type)
72+
{
73+
auto offset = content_type.index_of(";");
74+
if (offset.has_value())
75+
return content_type.substring(0, offset.value()).to_lowercase();
76+
77+
return content_type;
78+
}
79+
80+
static String guess_mime_type_based_on_filename(const URL& url)
81+
{
82+
if (url.path().ends_with(".png"))
83+
return "image/png";
84+
if (url.path().ends_with(".gif"))
85+
return "image/gif";
86+
if (url.path().ends_with(".md"))
87+
return "text/markdown";
88+
if (url.path().ends_with(".html") || url.path().ends_with(".htm"))
89+
return "text/html";
90+
return "text/plain";
91+
}
92+
6293
void Resource::did_load(Badge<ResourceLoader>, const ByteBuffer& data, const HashMap<String, String, CaseInsensitiveStringTraits>& headers)
6394
{
6495
ASSERT(!m_loaded);
6596
m_encoded_data = data;
6697
m_response_headers = headers;
6798
m_loaded = true;
6899

100+
auto content_type = headers.get("Content-Type");
101+
if (content_type.has_value()) {
102+
dbg() << "Content-Type header: _" << content_type.value() << "_";
103+
m_encoding = encoding_from_content_type(content_type.value());
104+
m_mime_type = mime_type_from_content_type(content_type.value());
105+
} else if (url().protocol() == "data" && !url().data_mime_type().is_empty()) {
106+
dbg() << "This is a data URL with mime-type _" << url().data_mime_type() << "_";
107+
m_encoding = "utf-8"; // FIXME: This doesn't seem nice.
108+
m_mime_type = url().data_mime_type();
109+
} else {
110+
dbg() << "No Content-Type header to go on! Guessing based on filename...";
111+
m_encoding = "utf-8"; // FIXME: This doesn't seem nice.
112+
m_mime_type = guess_mime_type_based_on_filename(url());
113+
}
114+
69115
for_each_client([](auto& client) {
70116
client.resource_did_load();
71117
});

Libraries/LibWeb/Loader/Resource.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ class Resource : public RefCounted<Resource> {
7272
void register_client(Badge<ResourceClient>, ResourceClient&);
7373
void unregister_client(Badge<ResourceClient>, ResourceClient&);
7474

75+
const String& encoding() const { return m_encoding; }
76+
const String& mime_type() const { return m_mime_type; }
77+
7578
void for_each_client(Function<void(ResourceClient&)>);
7679

7780
void did_load(Badge<ResourceLoader>, const ByteBuffer& data, const HashMap<String, String, CaseInsensitiveStringTraits>& headers);
@@ -87,6 +90,8 @@ class Resource : public RefCounted<Resource> {
8790
bool m_loaded { false };
8891
bool m_failed { false };
8992
String m_error;
93+
String m_encoding;
94+
String m_mime_type;
9095
HashMap<String, String, CaseInsensitiveStringTraits> m_response_headers;
9196
HashTable<ResourceClient*> m_clients;
9297
};

0 commit comments

Comments
 (0)