mirror of
https://github.com/fergalmoran/ladybird.git
synced 2026-01-06 00:25:12 +00:00
ProtocolServer: Stream the downloaded data if possible
This patchset makes ProtocolServer stream the downloads to its client
(LibProtocol), and as such changes the download API; a possible
download lifecycle could be as such:
notation = client->server:'>', server->client:'<', pipe activity:'*'
```
> StartDownload(GET, url, headers, {})
< Response(0, fd 8)
* {data, 1024b}
< HeadersBecameAvailable(0, response_headers, 200)
< DownloadProgress(0, 4K, 1024)
* {data, 1024b}
* {data, 1024b}
< DownloadProgress(0, 4K, 2048)
* {data, 1024b}
< DownloadProgress(0, 4K, 1024)
< DownloadFinished(0, true, 4K)
```
Since managing the received file descriptor is a pain, LibProtocol
implements `Download::stream_into(OutputStream)`, which can be used to
stream the download into any given output stream (be it a file, or
memory, or writing stuff with a delay, etc.).
Also, as some of the users of this API require all the downloaded data
upfront, LibProtocol also implements `set_should_buffer_all_input()`,
which causes the download instance to buffer all the data until the
download is complete, and to call the `on_buffered_download_finish`
hook.
This commit is contained in:
committed by
Andreas Kling
parent
36d642ee75
commit
4a2da10e38
@@ -62,16 +62,17 @@ OwnPtr<Messages::ProtocolServer::StartDownloadResponse> ClientConnection::handle
|
||||
{
|
||||
URL url(message.url());
|
||||
if (!url.is_valid())
|
||||
return make<Messages::ProtocolServer::StartDownloadResponse>(-1);
|
||||
return make<Messages::ProtocolServer::StartDownloadResponse>(-1, -1);
|
||||
auto* protocol = Protocol::find_by_name(url.protocol());
|
||||
if (!protocol)
|
||||
return make<Messages::ProtocolServer::StartDownloadResponse>(-1);
|
||||
auto download = protocol->start_download(*this, message.method(), url, message.request_headers().entries(), message.request_body().to_byte_buffer());
|
||||
return make<Messages::ProtocolServer::StartDownloadResponse>(-1, -1);
|
||||
auto download = protocol->start_download(*this, message.method(), url, message.request_headers().entries(), message.request_body());
|
||||
if (!download)
|
||||
return make<Messages::ProtocolServer::StartDownloadResponse>(-1);
|
||||
return make<Messages::ProtocolServer::StartDownloadResponse>(-1, -1);
|
||||
auto id = download->id();
|
||||
auto fd = download->download_fd();
|
||||
m_downloads.set(id, move(download));
|
||||
return make<Messages::ProtocolServer::StartDownloadResponse>(id);
|
||||
return make<Messages::ProtocolServer::StartDownloadResponse>(id, fd);
|
||||
}
|
||||
|
||||
OwnPtr<Messages::ProtocolServer::StopDownloadResponse> ClientConnection::handle(const Messages::ProtocolServer::StopDownload& message)
|
||||
@@ -86,22 +87,20 @@ OwnPtr<Messages::ProtocolServer::StopDownloadResponse> ClientConnection::handle(
|
||||
return make<Messages::ProtocolServer::StopDownloadResponse>(success);
|
||||
}
|
||||
|
||||
void ClientConnection::did_finish_download(Badge<Download>, Download& download, bool success)
|
||||
void ClientConnection::did_receive_headers(Badge<Download>, Download& download)
|
||||
{
|
||||
RefPtr<SharedBuffer> buffer;
|
||||
if (success && download.payload().size() > 0 && !download.payload().is_null()) {
|
||||
buffer = SharedBuffer::create_with_size(download.payload().size());
|
||||
memcpy(buffer->data<void>(), download.payload().data(), download.payload().size());
|
||||
buffer->seal();
|
||||
buffer->share_with(client_pid());
|
||||
m_shared_buffers.set(buffer->shbuf_id(), buffer);
|
||||
}
|
||||
ASSERT(download.total_size().has_value());
|
||||
|
||||
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.status_code(), download.total_size().value(), buffer ? buffer->shbuf_id() : -1, response_headers));
|
||||
|
||||
post_message(Messages::ProtocolClient::HeadersBecameAvailable(download.id(), move(response_headers), download.status_code()));
|
||||
}
|
||||
|
||||
void ClientConnection::did_finish_download(Badge<Download>, Download& download, bool success)
|
||||
{
|
||||
ASSERT(download.total_size().has_value());
|
||||
|
||||
post_message(Messages::ProtocolClient::DownloadFinished(download.id(), success, download.total_size().value()));
|
||||
|
||||
m_downloads.remove(download.id());
|
||||
}
|
||||
@@ -121,12 +120,6 @@ OwnPtr<Messages::ProtocolServer::GreetResponse> ClientConnection::handle(const M
|
||||
return make<Messages::ProtocolServer::GreetResponse>(client_id());
|
||||
}
|
||||
|
||||
OwnPtr<Messages::ProtocolServer::DisownSharedBufferResponse> ClientConnection::handle(const Messages::ProtocolServer::DisownSharedBuffer& message)
|
||||
{
|
||||
m_shared_buffers.remove(message.shbuf_id());
|
||||
return make<Messages::ProtocolServer::DisownSharedBufferResponse>();
|
||||
}
|
||||
|
||||
OwnPtr<Messages::ProtocolServer::SetCertificateResponse> ClientConnection::handle(const Messages::ProtocolServer::SetCertificate& message)
|
||||
{
|
||||
auto* download = const_cast<Download*>(m_downloads.get(message.download_id()).value_or(nullptr));
|
||||
|
||||
Reference in New Issue
Block a user