diff options
author | Andreas Kling <kling@serenityos.org> | 2020-05-03 22:20:49 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-05-03 23:01:58 +0200 |
commit | eb6e35a1be61115ab4618db695b668cb0b3d4d32 (patch) | |
tree | 6a955f81b36f66cc6ac30adc10cb9856d4bdf4ad | |
parent | a83d74b38cf10cc2999e1519dc62bc30fef1ed65 (diff) | |
download | serenity-eb6e35a1be61115ab4618db695b668cb0b3d4d32.zip |
ProtocolServer: Pass HTTP response headers to the client
We now store the response headers in a download object on the protocol
server side and pass it to the client when finishing up a download.
Response headers are passed as an IPC::Dictionary. :^)
-rw-r--r-- | Libraries/LibProtocol/Client.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibProtocol/Download.cpp | 5 | ||||
-rw-r--r-- | Libraries/LibProtocol/Download.h | 5 | ||||
-rw-r--r-- | Libraries/LibWeb/CSS/StyleValue.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/HTMLImageElement.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/HTMLLinkElement.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/HTMLScriptElement.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/XMLHttpRequest.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/HtmlView.cpp | 6 | ||||
-rw-r--r-- | Libraries/LibWeb/ResourceLoader.cpp | 16 | ||||
-rw-r--r-- | Libraries/LibWeb/ResourceLoader.h | 4 | ||||
-rw-r--r-- | Servers/ProtocolServer/Download.cpp | 5 | ||||
-rw-r--r-- | Servers/ProtocolServer/Download.h | 4 | ||||
-rw-r--r-- | Servers/ProtocolServer/HttpDownload.cpp | 6 | ||||
-rw-r--r-- | Servers/ProtocolServer/HttpsDownload.cpp | 6 | ||||
-rw-r--r-- | Servers/ProtocolServer/PSClientConnection.cpp | 6 | ||||
-rw-r--r-- | Servers/ProtocolServer/ProtocolClient.ipc | 2 | ||||
-rw-r--r-- | Userland/pro.cpp | 2 |
18 files changed, 49 insertions, 30 deletions
diff --git a/Libraries/LibProtocol/Client.cpp b/Libraries/LibProtocol/Client.cpp index 0b80102a8d..e13cbb2db7 100644 --- a/Libraries/LibProtocol/Client.cpp +++ b/Libraries/LibProtocol/Client.cpp @@ -68,7 +68,7 @@ void Client::handle(const Messages::ProtocolClient::DownloadFinished& message) { RefPtr<Download> download; if ((download = m_downloads.get(message.download_id()).value_or(nullptr))) { - download->did_finish({}, message.success(), message.total_size(), message.shbuf_id()); + download->did_finish({}, message.success(), message.total_size(), message.shbuf_id(), message.response_headers()); } send_sync<Messages::ProtocolServer::DisownSharedBuffer>(message.shbuf_id()); m_downloads.remove(message.download_id()); diff --git a/Libraries/LibProtocol/Download.cpp b/Libraries/LibProtocol/Download.cpp index 37ba4a6d95..103964a93f 100644 --- a/Libraries/LibProtocol/Download.cpp +++ b/Libraries/LibProtocol/Download.cpp @@ -41,7 +41,7 @@ bool Download::stop() return m_client->stop_download({}, *this); } -void Download::did_finish(Badge<Client>, bool success, u32 total_size, i32 shbuf_id) +void Download::did_finish(Badge<Client>, bool success, u32 total_size, i32 shbuf_id, const IPC::Dictionary& response_headers) { if (!on_finish) return; @@ -52,7 +52,8 @@ void Download::did_finish(Badge<Client>, bool success, u32 total_size, i32 shbuf shared_buffer = SharedBuffer::create_from_shbuf_id(shbuf_id); payload = ByteBuffer::wrap(shared_buffer->data(), total_size); } - on_finish(success, payload, move(shared_buffer)); + + on_finish(success, payload, move(shared_buffer), response_headers.entries()); } void Download::did_progress(Badge<Client>, Optional<u32> total_size, u32 downloaded_size) diff --git a/Libraries/LibProtocol/Download.h b/Libraries/LibProtocol/Download.h index 7296d1df06..883406e8b3 100644 --- a/Libraries/LibProtocol/Download.h +++ b/Libraries/LibProtocol/Download.h @@ -31,6 +31,7 @@ #include <AK/Function.h> #include <AK/RefCounted.h> #include <AK/WeakPtr.h> +#include <LibIPC/Forward.h> namespace Protocol { @@ -46,10 +47,10 @@ public: int id() const { return m_download_id; } bool stop(); - Function<void(bool success, const ByteBuffer& payload, RefPtr<SharedBuffer> payload_storage)> on_finish; + Function<void(bool success, const ByteBuffer& payload, RefPtr<SharedBuffer> payload_storage, const HashMap<String, String>& response_headers)> on_finish; Function<void(Optional<u32> total_size, u32 downloaded_size)> on_progress; - void did_finish(Badge<Client>, bool success, u32 total_size, i32 shbuf_id); + void did_finish(Badge<Client>, bool success, u32 total_size, i32 shbuf_id, const IPC::Dictionary& response_headers); void did_progress(Badge<Client>, Optional<u32> total_size, u32 downloaded_size); private: diff --git a/Libraries/LibWeb/CSS/StyleValue.cpp b/Libraries/LibWeb/CSS/StyleValue.cpp index 19472a1cfe..be960319af 100644 --- a/Libraries/LibWeb/CSS/StyleValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValue.cpp @@ -68,7 +68,7 @@ ImageStyleValue::ImageStyleValue(const URL& url, Document& document) , m_document(document.make_weak_ptr()) { NonnullRefPtr<ImageStyleValue> protector(*this); - ResourceLoader::the().load(url, [this, protector](auto& data) { + ResourceLoader::the().load(url, [this, protector](auto& data, auto&) { if (!m_document) return; m_bitmap = Gfx::load_png_from_memory(data.data(), data.size()); diff --git a/Libraries/LibWeb/DOM/HTMLImageElement.cpp b/Libraries/LibWeb/DOM/HTMLImageElement.cpp index 3b9334cd2e..27b9c484e8 100644 --- a/Libraries/LibWeb/DOM/HTMLImageElement.cpp +++ b/Libraries/LibWeb/DOM/HTMLImageElement.cpp @@ -53,7 +53,7 @@ void HTMLImageElement::parse_attribute(const FlyString& name, const String& valu void HTMLImageElement::load_image(const String& src) { URL src_url = document().complete_url(src); - ResourceLoader::the().load(src_url, [this, weak_element = make_weak_ptr()](auto data) { + ResourceLoader::the().load(src_url, [this, weak_element = make_weak_ptr()](auto data, auto&) { if (!weak_element) { dbg() << "HTMLImageElement: Load completed after element destroyed."; return; diff --git a/Libraries/LibWeb/DOM/HTMLLinkElement.cpp b/Libraries/LibWeb/DOM/HTMLLinkElement.cpp index 88ef395a52..c79ab9db1c 100644 --- a/Libraries/LibWeb/DOM/HTMLLinkElement.cpp +++ b/Libraries/LibWeb/DOM/HTMLLinkElement.cpp @@ -47,7 +47,7 @@ void HTMLLinkElement::inserted_into(Node&) { if (rel() == "stylesheet") { URL url = document().complete_url(href()); - ResourceLoader::the().load(url, [&](auto data) { + ResourceLoader::the().load(url, [&](auto data, auto&) { if (data.is_null()) { dbg() << "HTMLLinkElement: Failed to load stylesheet: " << href(); return; diff --git a/Libraries/LibWeb/DOM/HTMLScriptElement.cpp b/Libraries/LibWeb/DOM/HTMLScriptElement.cpp index 45b3930554..a6634da538 100644 --- a/Libraries/LibWeb/DOM/HTMLScriptElement.cpp +++ b/Libraries/LibWeb/DOM/HTMLScriptElement.cpp @@ -82,7 +82,7 @@ void HTMLScriptElement::inserted_into(Node& new_parent) } String source; - ResourceLoader::the().load_sync(src_url, [&](auto& data) { + ResourceLoader::the().load_sync(src_url, [&](auto& data, auto&) { if (data.is_null()) { dbg() << "HTMLScriptElement: Failed to load " << src; return; diff --git a/Libraries/LibWeb/DOM/XMLHttpRequest.cpp b/Libraries/LibWeb/DOM/XMLHttpRequest.cpp index 885c56fa26..5c96115fae 100644 --- a/Libraries/LibWeb/DOM/XMLHttpRequest.cpp +++ b/Libraries/LibWeb/DOM/XMLHttpRequest.cpp @@ -72,7 +72,7 @@ void XMLHttpRequest::send() // we need to make ResourceLoader give us more detailed updates than just "done" and "error". ResourceLoader::the().load( m_window->document().complete_url(m_url), - [weak_this = make_weak_ptr()](auto& data) { + [weak_this = make_weak_ptr()](auto& data, auto&) { if (!weak_this) return; const_cast<XMLHttpRequest&>(*weak_this).m_response = data; diff --git a/Libraries/LibWeb/HtmlView.cpp b/Libraries/LibWeb/HtmlView.cpp index 5092d61b6a..b74b5c8553 100644 --- a/Libraries/LibWeb/HtmlView.cpp +++ b/Libraries/LibWeb/HtmlView.cpp @@ -360,7 +360,7 @@ void HtmlView::load(const URL& url) ResourceLoader::the().load( url, - [this, url](auto data) { + [this, url](auto data, auto& response_headers) { if (data.is_null()) { load_error_page(url, "No data"); return; @@ -390,7 +390,7 @@ void HtmlView::load(const URL& url) ResourceLoader::the().load( favicon_url, - [this, favicon_url](auto data) { + [this, favicon_url](auto data, auto&) { dbg() << "Favicon downloaded, " << data.size() << " bytes from " << favicon_url.to_string(); auto decoder = Gfx::ImageDecoder::create(data.data(), data.size()); auto bitmap = decoder->bitmap(); @@ -412,7 +412,7 @@ void HtmlView::load_error_page(const URL& failed_url, const String& error) auto error_page_url = "file:///res/html/error.html"; ResourceLoader::the().load( error_page_url, - [this, failed_url, error](auto data) { + [this, failed_url, error](auto data, auto&) { ASSERT(!data.is_null()); auto html = String::format( String::copy(data).characters(), diff --git a/Libraries/LibWeb/ResourceLoader.cpp b/Libraries/LibWeb/ResourceLoader.cpp index 558359019b..664fbdb050 100644 --- a/Libraries/LibWeb/ResourceLoader.cpp +++ b/Libraries/LibWeb/ResourceLoader.cpp @@ -47,14 +47,14 @@ ResourceLoader::ResourceLoader() { } -void ResourceLoader::load_sync(const URL& url, Function<void(const ByteBuffer&)> success_callback, Function<void(const String&)> error_callback) +void ResourceLoader::load_sync(const URL& url, Function<void(const ByteBuffer&, const HashMap<String, String>& response_headers)> success_callback, Function<void(const String&)> error_callback) { Core::EventLoop loop; load( url, - [&](auto& data) { - success_callback(data); + [&](auto& data, auto& response_headers) { + success_callback(data, response_headers); loop.quit(0); }, [&](auto& string) { @@ -66,7 +66,7 @@ void ResourceLoader::load_sync(const URL& url, Function<void(const ByteBuffer&)> loop.exec(); } -void ResourceLoader::load(const URL& url, Function<void(const ByteBuffer&)> success_callback, Function<void(const String&)> error_callback) +void ResourceLoader::load(const URL& url, Function<void(const ByteBuffer&, const HashMap<String, String>& response_headers)> success_callback, Function<void(const String&)> error_callback) { if (is_port_blocked(url.port())) { dbg() << "ResourceLoader::load: Error: blocked port " << url.port() << " for URL: " << url; @@ -83,7 +83,7 @@ void ResourceLoader::load(const URL& url, Function<void(const ByteBuffer&)> succ data = url.data_payload().to_byte_buffer(); deferred_invoke([data = move(data), success_callback = move(success_callback)](auto&) { - success_callback(data); + success_callback(data, {}); }); return; } @@ -100,7 +100,7 @@ void ResourceLoader::load(const URL& url, Function<void(const ByteBuffer&)> succ auto data = f->read_all(); deferred_invoke([data = move(data), success_callback = move(success_callback)](auto&) { - success_callback(data); + success_callback(data, {}); }); return; } @@ -112,7 +112,7 @@ void ResourceLoader::load(const URL& url, Function<void(const ByteBuffer&)> succ error_callback("Failed to initiate load"); return; } - download->on_finish = [this, success_callback = move(success_callback), error_callback = move(error_callback)](bool success, const ByteBuffer& payload, auto) { + download->on_finish = [this, success_callback = move(success_callback), error_callback = move(error_callback)](bool success, const ByteBuffer& payload, auto, auto& response_headers) { --m_pending_loads; if (on_load_counter_change) on_load_counter_change(); @@ -121,7 +121,7 @@ void ResourceLoader::load(const URL& url, Function<void(const ByteBuffer&)> succ error_callback("HTTP load failed"); return; } - success_callback(ByteBuffer::copy(payload.data(), payload.size())); + success_callback(ByteBuffer::copy(payload.data(), payload.size()), response_headers); }; ++m_pending_loads; if (on_load_counter_change) diff --git a/Libraries/LibWeb/ResourceLoader.h b/Libraries/LibWeb/ResourceLoader.h index 9adfc169ee..44c849ab9a 100644 --- a/Libraries/LibWeb/ResourceLoader.h +++ b/Libraries/LibWeb/ResourceLoader.h @@ -41,8 +41,8 @@ class ResourceLoader : public Core::Object { public: static ResourceLoader& the(); - void load(const URL&, Function<void(const ByteBuffer&)> success_callback, Function<void(const String&)> error_callback = nullptr); - void load_sync(const URL&, Function<void(const ByteBuffer&)> success_callback, Function<void(const String&)> error_callback = nullptr); + void load(const URL&, Function<void(const ByteBuffer&, const HashMap<String, String>& response_headers)> success_callback, Function<void(const String&)> error_callback = nullptr); + void load_sync(const URL&, Function<void(const ByteBuffer&, const HashMap<String, String>& response_headers)> success_callback, Function<void(const String&)> error_callback = nullptr); Function<void()> on_load_counter_change; diff --git a/Servers/ProtocolServer/Download.cpp b/Servers/ProtocolServer/Download.cpp index 7ddfe419db..e4bbce082b 100644 --- a/Servers/ProtocolServer/Download.cpp +++ b/Servers/ProtocolServer/Download.cpp @@ -64,6 +64,11 @@ void Download::set_payload(const ByteBuffer& payload) m_total_size = payload.size(); } +void Download::set_response_headers(const HashMap<String, String>& response_headers) +{ + m_response_headers = response_headers; +} + void Download::did_finish(bool success) { if (!m_client) { diff --git a/Servers/ProtocolServer/Download.h b/Servers/ProtocolServer/Download.h index aff9912257..5609cd15b4 100644 --- a/Servers/ProtocolServer/Download.h +++ b/Servers/ProtocolServer/Download.h @@ -27,6 +27,7 @@ #pragma once #include <AK/ByteBuffer.h> +#include <AK/HashMap.h> #include <AK/Optional.h> #include <AK/RefCounted.h> #include <AK/URL.h> @@ -46,6 +47,7 @@ public: Optional<u32> total_size() const { return m_total_size; } size_t downloaded_size() const { return m_downloaded_size; } const ByteBuffer& payload() const { return m_payload; } + const HashMap<String, String>& response_headers() const { return m_response_headers; } void stop(); @@ -55,6 +57,7 @@ protected: void did_finish(bool success); void did_progress(Optional<u32> total_size, u32 downloaded_size); void set_payload(const ByteBuffer&); + void set_response_headers(const HashMap<String, String>&); private: i32 m_id; @@ -62,5 +65,6 @@ private: Optional<u32> m_total_size {}; size_t m_downloaded_size { 0 }; ByteBuffer m_payload; + HashMap<String, String> m_response_headers; WeakPtr<PSClientConnection> m_client; }; diff --git a/Servers/ProtocolServer/HttpDownload.cpp b/Servers/ProtocolServer/HttpDownload.cpp index ad400dfb61..5ffa30362b 100644 --- a/Servers/ProtocolServer/HttpDownload.cpp +++ b/Servers/ProtocolServer/HttpDownload.cpp @@ -33,8 +33,10 @@ HttpDownload::HttpDownload(PSClientConnection& client, NonnullRefPtr<HTTP::HttpJ , m_job(job) { m_job->on_finish = [this](bool success) { - if (m_job->response()) - set_payload(m_job->response()->payload()); + if (auto* response = m_job->response()) { + set_payload(response->payload()); + set_response_headers(response->headers()); + } // if we didn't know the total size, pretend that the download finished successfully // and set the total size to the downloaded size diff --git a/Servers/ProtocolServer/HttpsDownload.cpp b/Servers/ProtocolServer/HttpsDownload.cpp index c883a178d9..8e068c2b04 100644 --- a/Servers/ProtocolServer/HttpsDownload.cpp +++ b/Servers/ProtocolServer/HttpsDownload.cpp @@ -33,8 +33,10 @@ HttpsDownload::HttpsDownload(PSClientConnection& client, NonnullRefPtr<HTTP::Htt , m_job(job) { m_job->on_finish = [this](bool success) { - if (m_job->response()) - set_payload(m_job->response()->payload()); + if (auto* response = m_job->response()) { + set_payload(response->payload()); + set_response_headers(response->headers()); + } // if we didn't know the total size, pretend that the download finished successfully // and set the total size to the downloaded size diff --git a/Servers/ProtocolServer/PSClientConnection.cpp b/Servers/ProtocolServer/PSClientConnection.cpp index 848da08505..2be83a2c12 100644 --- a/Servers/ProtocolServer/PSClientConnection.cpp +++ b/Servers/ProtocolServer/PSClientConnection.cpp @@ -87,7 +87,11 @@ void PSClientConnection::did_finish_download(Badge<Download>, Download& download m_shared_buffers.set(buffer->shbuf_id(), buffer); } ASSERT(download.total_size().has_value()); - post_message(Messages::ProtocolClient::DownloadFinished(download.id(), success, download.total_size().value(), buffer ? buffer->shbuf_id() : -1)); + + IPC::Dictionary response_headers; + for (auto& it : download.response_headers()) + response_headers.add(it.key, it.value); + post_message(Messages::ProtocolClient::DownloadFinished(download.id(), success, download.total_size().value(), buffer ? buffer->shbuf_id() : -1, response_headers)); } void PSClientConnection::did_progress_download(Badge<Download>, Download& download) diff --git a/Servers/ProtocolServer/ProtocolClient.ipc b/Servers/ProtocolServer/ProtocolClient.ipc index d54cbac9fb..575b3ddd2b 100644 --- a/Servers/ProtocolServer/ProtocolClient.ipc +++ b/Servers/ProtocolServer/ProtocolClient.ipc @@ -2,5 +2,5 @@ endpoint ProtocolClient = 13 { // Download notifications DownloadProgress(i32 download_id, Optional<u32> total_size, u32 downloaded_size) =| - DownloadFinished(i32 download_id, bool success, u32 total_size, i32 shbuf_id) =| + DownloadFinished(i32 download_id, bool success, u32 total_size, i32 shbuf_id, IPC::Dictionary response_headers) =| } diff --git a/Userland/pro.cpp b/Userland/pro.cpp index 8edc0b2fd5..2307dfc36f 100644 --- a/Userland/pro.cpp +++ b/Userland/pro.cpp @@ -76,7 +76,7 @@ int main(int argc, char** argv) previous_downloaded_size = downloaded_size; prev_time = current_time; }; - download->on_finish = [&](bool success, auto& payload, auto) { + download->on_finish = [&](bool success, auto& payload, auto, auto&) { fprintf(stderr, "\n"); if (success) write(STDOUT_FILENO, payload.data(), payload.size()); |