summaryrefslogtreecommitdiffstats
path: root/src/core/net
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-03-03 17:49:58 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-03-05 08:51:29 +0100
commit9b5a18179e4d7f3483948fd24b1c4dcb28608a80 (patch)
treebd90b690dbac72a872fd5067e367b616fb4ffefc /src/core/net
parent795d5e2666cababe4fbf8533d8a49fdc40d8d4c1 (diff)
Improve custom scheme http content-range support
Also parse length, and report back part expected HTTP headers. Change-Id: I414ef6fb6ade601f59a23c01bb547d58f0f7ffd1 Reviewed-by: Szabolcs David <davidsz@inf.u-szeged.hu> Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu>
Diffstat (limited to 'src/core/net')
-rw-r--r--src/core/net/custom_url_loader_factory.cpp59
-rw-r--r--src/core/net/url_request_custom_job_proxy.cpp5
2 files changed, 49 insertions, 15 deletions
diff --git a/src/core/net/custom_url_loader_factory.cpp b/src/core/net/custom_url_loader_factory.cpp
index e0ae22bb1..a96b35696 100644
--- a/src/core/net/custom_url_loader_factory.cpp
+++ b/src/core/net/custom_url_loader_factory.cpp
@@ -153,14 +153,8 @@ private:
headers.emplace("Referer", m_request.referrer.spec());
std::string rangeHeader;
- if (m_request.headers.GetHeader(net::HttpRequestHeaders::kRange, &rangeHeader)) {
- std::vector<net::HttpByteRange> ranges;
- if (net::HttpUtil::ParseRangeHeader(rangeHeader, &ranges)) {
- // Chromium doesn't support multiple range requests in one single URL request.
- if (ranges.size() == 1)
- m_firstBytePosition = ranges[0].first_byte_position();
- }
- }
+ if (ParseRange(m_request.headers))
+ m_firstBytePosition = m_byteRange.first_byte_position();
// m_taskRunner->PostTask(FROM_HERE,
base::PostTask(FROM_HERE, { content::BrowserThread::UI },
@@ -219,7 +213,17 @@ private:
void notifyExpectedContentSize(qint64 size) override
{
DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
- m_head.content_length = size;
+ m_totalSize = size;
+ if (m_byteRange.IsValid()) {
+ if (!m_byteRange.ComputeBounds(size)) {
+ CompleteWithFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
+ } else {
+ m_maxBytesToRead = m_byteRange.last_byte_position() - m_byteRange.first_byte_position() + 1;
+ m_head.content_length = m_maxBytesToRead;
+ }
+ } else {
+ m_head.content_length = size;
+ }
}
void notifyHeadersComplete() override
{
@@ -232,9 +236,20 @@ private:
headers += "HTTP/1.1 303 See Other\n";
headers += base::StringPrintf("Location: %s\n", m_redirect.spec().c_str());
} else {
- headers += "HTTP/1.1 200 OK\n";
+ if (m_byteRange.IsValid() && m_totalSize > 0) {
+ headers += "HTTP/1.1 206 Partial Content\n";
+ headers += net::HttpResponseHeaders::kContentRange;
+ headers += base::StringPrintf(": bytes %lld-%lld/%lld",
+ qlonglong{m_byteRange.first_byte_position()},
+ qlonglong{m_byteRange.last_byte_position()},
+ qlonglong{m_totalSize});
+ headers += "\n";
+ } else {
+ headers += "HTTP/1.1 200 OK\n";
+ }
if (m_mimeType.size() > 0) {
- headers += base::StringPrintf("Content-Type: %s", m_mimeType.c_str());
+ headers += net::HttpRequestHeaders::kContentType;
+ headers += base::StringPrintf(": %s", m_mimeType.c_str());
if (m_charset.size() > 0)
headers += base::StringPrintf("; charset=%s", m_charset.c_str());
headers += "\n";
@@ -351,6 +366,8 @@ private:
return false; // Wait for pipe watcher
if (beginResult != MOJO_RESULT_OK)
break;
+ if (m_maxBytesToRead > 0 && m_maxBytesToRead <= int64_t{std::numeric_limits<uint32_t>::max()})
+ bufferSize = std::min(bufferSize, uint32_t(m_maxBytesToRead));
int readResult = m_device->read(static_cast<char *>(buffer), bufferSize);
uint32_t bytesRead = std::max(readResult, 0);
@@ -358,7 +375,7 @@ private:
m_totalBytesRead += bytesRead;
m_client->OnTransferSizeUpdated(m_totalBytesRead);
- if (m_device->atEnd()) {
+ if (m_device->atEnd() || (m_maxBytesToRead > 0 && m_totalBytesRead >= m_maxBytesToRead)) {
OnTransferComplete(MOJO_RESULT_OK);
return true; // Done with reading
}
@@ -372,6 +389,21 @@ private:
CompleteWithFailure(m_error ? net::Error(m_error) : net::ERR_FAILED);
return true; // Done with reading
}
+ bool ParseRange(const net::HttpRequestHeaders &headers)
+ {
+ std::string range_header;
+ if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) {
+ std::vector<net::HttpByteRange> ranges;
+ if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
+ // Chromium doesn't support multirange requests.
+ if (ranges.size() == 1) {
+ m_byteRange = ranges[0];
+ return true;
+ }
+ }
+ }
+ return false;
+ }
base::TaskRunner *taskRunner() override
{
DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
@@ -386,6 +418,9 @@ private:
mojo::DataPipe m_pipe;
std::unique_ptr<mojo::SimpleWatcher> m_watcher;
+ net::HttpByteRange m_byteRange;
+ int64_t m_totalSize = 0;
+ int64_t m_maxBytesToRead = -1;
network::ResourceRequest m_request;
network::ResourceResponseHead m_head;
qint64 m_totalBytesRead = 0;
diff --git a/src/core/net/url_request_custom_job_proxy.cpp b/src/core/net/url_request_custom_job_proxy.cpp
index d2df64f2f..f734db645 100644
--- a/src/core/net/url_request_custom_job_proxy.cpp
+++ b/src/core/net/url_request_custom_job_proxy.cpp
@@ -100,9 +100,8 @@ void URLRequestCustomJobProxy::reply(std::string mimeType, QIODevice *device)
m_client->m_device->seek(m_client->m_firstBytePosition);
qint64 deviceSize = m_client->m_device ? m_client->m_device->size() : -1;
- qint64 remainingBytes = deviceSize - m_client->m_firstBytePosition;
- if (remainingBytes > 0)
- m_client->notifyExpectedContentSize(remainingBytes);
+ if (deviceSize > 0)
+ m_client->notifyExpectedContentSize(deviceSize);
if (m_client->m_device && m_client->m_device->isReadable()) {
m_started = true;