summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-02 18:08:25 +0000
committerrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-02 18:08:25 +0000
commit634739bf391585057f2f1a9f8f173d418958ae0f (patch)
treec68d3b382be4edaebf5aec10de6dba870563df7b /net
parent18699b72815f6f435c4e00f4f1eb900440898468 (diff)
downloadchromium_src-634739bf391585057f2f1a9f8f173d418958ae0f.zip
chromium_src-634739bf391585057f2f1a9f8f173d418958ae0f.tar.gz
chromium_src-634739bf391585057f2f1a9f8f173d418958ae0f.tar.bz2
Http cache: Fix handling of truncated entries.
- Always validate a truncated entry. Furthermore, given that a server can say not-modified (304), followed by 200 when actually asked for the final range, now we validate truncated entries by asking for the next byte that we need. - If a server refuses to serve a byte range and instead sends the whole resource, we just cache the response as if nothing was stored before. - If we receive a network error while reading from the net, we don't discard the cached entry right away. Now we wait until the transaction is closed, and attempt to mark the entry as truncated. BUG=48468 TEST=net_unittests Review URL: http://codereview.chromium.org/6588105 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76560 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/http/http_cache_transaction.cc28
-rw-r--r--net/http/http_cache_unittest.cc249
-rw-r--r--net/http/partial_data.cc31
-rw-r--r--net/http/partial_data.h6
4 files changed, 194 insertions, 120 deletions
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 32386f0..6665d5ff 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -731,6 +731,11 @@ int HttpCache::Transaction::DoNetworkReadComplete(int result) {
if (!cache_)
return ERR_UNEXPECTED;
+ // If there is an error and we are saving the data, just tell the user about
+ // it and wait until the destructor runs to see if we can keep the data.
+ if (mode_ != NONE && result < 0)
+ return result;
+
next_state_ = STATE_CACHE_WRITE_DATA;
return result;
}
@@ -982,6 +987,16 @@ int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) {
// We no longer need the network transaction, so destroy it.
final_upload_progress_ = network_trans_->GetUploadProgress();
network_trans_.reset();
+ } else if (entry_ && server_responded_206_ && truncated_ &&
+ partial_->initial_validation()) {
+ // We just finished the validation of a truncated entry, and the server
+ // is willing to resume the operation. Now we go back and start serving
+ // the first part to the user.
+ network_trans_.reset();
+ new_response_ = NULL;
+ next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
+ partial_->SetRangeToStartDownload();
+ return OK;
}
next_state_ = STATE_OVERWRITE_CACHED_RESPONSE;
return OK;
@@ -1442,6 +1457,9 @@ int HttpCache::Transaction::BeginCacheValidation() {
bool skip_validation = effective_load_flags_ & LOAD_PREFERRING_CACHE ||
!RequiresValidation();
+ if (truncated_)
+ skip_validation = !partial_->initial_validation();
+
if ((partial_.get() && !partial_->IsCurrentRangeCached()) || invalid_range_)
skip_validation = false;
@@ -1738,8 +1756,16 @@ bool HttpCache::Transaction::ValidatePartialResponse(bool* partial_content) {
// 304 is not expected here, but we'll spare the entry (unless it was
// truncated).
- if (truncated_)
+ if (truncated_) {
+ if (!reading_ && response_code == 200) {
+ // The server is sending the whole resource, and we can save it.
+ DCHECK(!partial_->IsLastRange());
+ partial_.reset();
+ truncated_ = false;
+ return true;
+ }
failure = true;
+ }
}
if (failure) {
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index 8d5fea4..52e48e6 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -885,9 +885,15 @@ void RangeTransactionServer::RangeHandler(const net::HttpRequestInfo* request,
std::string range_header;
if (!request->extra_headers.GetHeader(
net::HttpRequestHeaders::kRange, &range_header) ||
- !net::HttpUtil::ParseRangeHeader(range_header, &ranges) ||
- ranges.size() != 1)
+ !net::HttpUtil::ParseRangeHeader(range_header, &ranges) || bad_200_ ||
+ ranges.size() != 1) {
+ // This is not a byte range request. We return 200.
+ response_status->assign("HTTP/1.1 200 OK");
+ response_headers->assign("Date: Wed, 28 Nov 2007 09:40:09 GMT");
+ response_data->assign("Not a range");
return;
+ }
+
// We can handle this range request.
net::HttpByteRange byte_range = ranges[0];
if (byte_range.first_byte_position() > 79) {
@@ -907,27 +913,27 @@ void RangeTransactionServer::RangeHandler(const net::HttpRequestInfo* request,
response_headers->append(content_range);
if (!request->extra_headers.HasHeader("If-None-Match") || modified_) {
- EXPECT_EQ(9, (end - start) % 10);
std::string data;
- for (int block_start = start; block_start < end; block_start += 10) {
- base::StringAppendF(&data, "rg: %02d-%02d ",
- block_start, block_start + 9);
+ if (end == start) {
+ EXPECT_EQ(0, end % 10);
+ data = "r";
+ } else {
+ EXPECT_EQ(9, (end - start) % 10);
+ for (int block_start = start; block_start < end; block_start += 10) {
+ base::StringAppendF(&data, "rg: %02d-%02d ",
+ block_start, block_start + 9);
+ }
}
*response_data = data;
if (end - start != 9) {
// We also have to fix content-length.
int len = end - start + 1;
- EXPECT_EQ(0, len % 10);
std::string content_length = base::StringPrintf("Content-Length: %d\n",
len);
response_headers->replace(response_headers->find("Content-Length:"),
content_length.size(), content_length);
}
- if (bad_200_) {
- // We return a range, but with a response code of 200.
- response_status->assign("HTTP/1.1 200 Success");
- }
} else {
response_status->assign("HTTP/1.1 304 Not Modified");
response_data->clear();
@@ -974,6 +980,32 @@ void Verify206Response(std::string response, int start, int end) {
ASSERT_EQ(end, range_end);
}
+// Creates a truncated entry that can be resumed using byte ranges.
+void CreateTruncatedEntry(std::string raw_headers, MockHttpCache* cache) {
+ // Create a disk cache entry that stores an incomplete resource.
+ disk_cache::Entry* entry;
+ ASSERT_TRUE(cache->CreateBackendEntry(kRangeGET_TransactionOK.url, &entry,
+ NULL));
+
+ raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(),
+ raw_headers.size());
+
+ net::HttpResponseInfo response;
+ response.response_time = base::Time::Now();
+ response.request_time = base::Time::Now();
+ response.headers = new net::HttpResponseHeaders(raw_headers);
+ // Set the last argument for this to be an incomplete request.
+ EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
+
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(100));
+ int len = static_cast<int>(base::strlcpy(buf->data(),
+ "rg: 00-09 rg: 10-19 ", 100));
+ TestCompletionCallback cb;
+ int rv = entry->WriteData(1, 0, buf, len, &cb, true);
+ EXPECT_EQ(len, cb.GetResult(rv));
+ entry->Close();
+}
+
// Helper to represent a network HTTP response.
struct Response {
// Set this response into |trans|.
@@ -3291,12 +3323,12 @@ TEST(HttpCache, GET_Previous206_NewContent) {
MockTransaction transaction2(kRangeGET_TransactionOK);
transaction2.request_headers = EXTRA_HEADER;
transaction2.load_flags |= net::LOAD_VALIDATE_CACHE;
- transaction2.data = "rg: 40-49 ";
+ transaction2.data = "Not a range";
RangeTransactionServer handler;
handler.set_modified(true);
RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
- EXPECT_EQ(0U, headers.find("HTTP/1.1 206 Partial Content\n"));
+ EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
EXPECT_EQ(3, cache.network_layer()->transaction_count());
EXPECT_EQ(1, cache.disk_cache()->open_count());
EXPECT_EQ(1, cache.disk_cache()->create_count());
@@ -3865,6 +3897,7 @@ TEST(HttpCache, RangeGET_FastFlakyServer) {
// And now read from the cache and the network.
RangeTransactionServer handler;
handler.set_bad_200(true);
+ transaction.data = "Not a range";
RunTransactionTest(cache.http_cache(), transaction);
EXPECT_EQ(3, cache.network_layer()->transaction_count());
@@ -4180,30 +4213,12 @@ TEST(HttpCache, GET_IncompleteResource) {
MockHttpCache cache;
AddMockTransaction(&kRangeGET_TransactionOK);
- // Create a disk cache entry that stores an incomplete resource.
- disk_cache::Entry* entry;
- ASSERT_TRUE(cache.CreateBackendEntry(kRangeGET_TransactionOK.url, &entry,
- NULL));
-
std::string raw_headers("HTTP/1.1 200 OK\n"
"Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
"ETag: \"foo\"\n"
"Accept-Ranges: bytes\n"
"Content-Length: 80\n");
- raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(),
- raw_headers.size());
-
- net::HttpResponseInfo response;
- response.headers = new net::HttpResponseHeaders(raw_headers);
- // Set the last argument for this to be an incomplete request.
- EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
-
- scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(100));
- int len = static_cast<int>(base::strlcpy(buf->data(),
- "rg: 00-09 rg: 10-19 ", 100));
- TestCompletionCallback cb;
- int rv = entry->WriteData(1, 0, buf, len, &cb, true);
- EXPECT_EQ(len, cb.GetResult(rv));
+ CreateTruncatedEntry(raw_headers, &cache);
// Now make a regular request.
std::string headers;
@@ -4226,14 +4241,17 @@ TEST(HttpCache, GET_IncompleteResource) {
EXPECT_EQ(1, cache.disk_cache()->open_count());
EXPECT_EQ(1, cache.disk_cache()->create_count());
- RemoveMockTransaction(&kRangeGET_TransactionOK);
-
// Verify that the disk entry was updated.
+ disk_cache::Entry* entry;
+ ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
EXPECT_EQ(80, entry->GetDataSize(1));
bool truncated = true;
+ net::HttpResponseInfo response;
EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
EXPECT_FALSE(truncated);
entry->Close();
+
+ RemoveMockTransaction(&kRangeGET_TransactionOK);
}
// Tests that we delete truncated entries if the server changes its mind midway.
@@ -4241,91 +4259,124 @@ TEST(HttpCache, GET_IncompleteResource2) {
MockHttpCache cache;
AddMockTransaction(&kRangeGET_TransactionOK);
- // Create a disk cache entry that stores an incomplete resource.
- disk_cache::Entry* entry;
- ASSERT_TRUE(cache.CreateBackendEntry(kRangeGET_TransactionOK.url, &entry,
- NULL));
-
-
// Content-length will be intentionally bad.
std::string raw_headers("HTTP/1.1 200 OK\n"
"Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
"ETag: \"foo\"\n"
"Accept-Ranges: bytes\n"
"Content-Length: 50\n");
- raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(),
- raw_headers.size());
-
- net::HttpResponseInfo response;
- response.headers = new net::HttpResponseHeaders(raw_headers);
- // Set the last argument for this to be an incomplete request.
- EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
-
- scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(100));
- int len = static_cast<int>(base::strlcpy(buf->data(),
- "rg: 00-09 rg: 10-19 ", 100));
- TestCompletionCallback cb;
- int rv = entry->WriteData(1, 0, buf, len, &cb, true);
- EXPECT_EQ(len, cb.GetResult(rv));
- entry->Close();
+ CreateTruncatedEntry(raw_headers, &cache);
- // Now make a regular request.
+ // Now make a regular request. We expect the code to fail the validation and
+ // retry the request without using byte ranges.
std::string headers;
MockTransaction transaction(kRangeGET_TransactionOK);
transaction.request_headers = EXTRA_HEADER;
- transaction.data = "rg: 00-09 rg: 10-19 ";
+ transaction.data = "Not a range";
RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
- // We update the headers with the ones received while revalidating.
+ // The server will return 200 instead of a byte range.
std::string expected_headers(
"HTTP/1.1 200 OK\n"
- "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
- "Accept-Ranges: bytes\n"
- "ETag: \"foo\"\n"
- "Content-Length: 50\n");
+ "Date: Wed, 28 Nov 2007 09:40:09 GMT\n");
EXPECT_EQ(expected_headers, headers);
EXPECT_EQ(2, cache.network_layer()->transaction_count());
EXPECT_EQ(1, cache.disk_cache()->open_count());
EXPECT_EQ(1, cache.disk_cache()->create_count());
- RemoveMockTransaction(&kRangeGET_TransactionOK);
-
// Verify that the disk entry was deleted.
+ disk_cache::Entry* entry;
ASSERT_FALSE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
+ RemoveMockTransaction(&kRangeGET_TransactionOK);
}
-// Tests that when we cancel a request that was interrupted, we mark it again
-// as truncated.
-TEST(HttpCache, GET_CancelIncompleteResource) {
+// Tests that we always validate a truncated request.
+TEST(HttpCache, GET_IncompleteResource3) {
MockHttpCache cache;
AddMockTransaction(&kRangeGET_TransactionOK);
- // Create a disk cache entry that stores an incomplete resource.
- disk_cache::Entry* entry;
- ASSERT_TRUE(cache.CreateBackendEntry(kRangeGET_TransactionOK.url, &entry,
- NULL));
+ // This should not require validation for 10 hours.
+ std::string raw_headers("HTTP/1.1 200 OK\n"
+ "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
+ "ETag: \"foo\"\n"
+ "Cache-Control: max-age= 36000\n"
+ "Accept-Ranges: bytes\n"
+ "Content-Length: 80\n");
+ CreateTruncatedEntry(raw_headers, &cache);
+
+ // Now make a regular request.
+ std::string headers;
+ MockTransaction transaction(kRangeGET_TransactionOK);
+ transaction.request_headers = EXTRA_HEADER;
+ transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 "
+ "rg: 50-59 rg: 60-69 rg: 70-79 ";
+
+ scoped_ptr<Context> c(new Context);
+ EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(&c->trans));
+
+ MockHttpRequest request(transaction);
+ int rv = c->trans->Start(&request, &c->callback, net::BoundNetLog());
+ EXPECT_EQ(net::OK, c->callback.GetResult(rv));
+
+ // We should have checked with the server before finishing Start().
+ EXPECT_EQ(1, cache.network_layer()->transaction_count());
+ EXPECT_EQ(1, cache.disk_cache()->open_count());
+ EXPECT_EQ(1, cache.disk_cache()->create_count());
+
+ RemoveMockTransaction(&kRangeGET_TransactionOK);
+}
+
+// Tests that we cache a 200 response to the validation request.
+TEST(HttpCache, GET_IncompleteResource4) {
+ MockHttpCache cache;
+ AddMockTransaction(&kRangeGET_TransactionOK);
std::string raw_headers("HTTP/1.1 200 OK\n"
"Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
"ETag: \"foo\"\n"
"Accept-Ranges: bytes\n"
"Content-Length: 80\n");
- raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(),
- raw_headers.size());
+ CreateTruncatedEntry(raw_headers, &cache);
+
+ // Now make a regular request.
+ std::string headers;
+ MockTransaction transaction(kRangeGET_TransactionOK);
+ transaction.request_headers = EXTRA_HEADER;
+ transaction.data = "Not a range";
+ RangeTransactionServer handler;
+ handler.set_bad_200(true);
+ RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
+ EXPECT_EQ(1, cache.network_layer()->transaction_count());
+ EXPECT_EQ(1, cache.disk_cache()->open_count());
+ EXPECT_EQ(1, cache.disk_cache()->create_count());
+
+ // Verify that the disk entry was updated.
+ disk_cache::Entry* entry;
+ ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
+ EXPECT_EQ(11, entry->GetDataSize(1));
+ bool truncated = true;
net::HttpResponseInfo response;
- response.headers = new net::HttpResponseHeaders(raw_headers);
+ EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
+ EXPECT_FALSE(truncated);
+ entry->Close();
- // Set the last argument for this to be an incomplete request.
- EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
+ RemoveMockTransaction(&kRangeGET_TransactionOK);
+}
- scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(100));
- int len = static_cast<int>(base::strlcpy(buf->data(), "rg: 00-09 rg: 10-19 ",
- buf->size()));
- TestCompletionCallback cb;
- int rv = entry->WriteData(1, 0, buf, len, &cb, true);
- EXPECT_EQ(len, cb.GetResult(rv));
+// Tests that when we cancel a request that was interrupted, we mark it again
+// as truncated.
+TEST(HttpCache, GET_CancelIncompleteResource) {
+ MockHttpCache cache;
+ AddMockTransaction(&kRangeGET_TransactionOK);
+
+ std::string raw_headers("HTTP/1.1 200 OK\n"
+ "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
+ "ETag: \"foo\"\n"
+ "Accept-Ranges: bytes\n"
+ "Content-Length: 80\n");
+ CreateTruncatedEntry(raw_headers, &cache);
// Now make a regular request.
MockTransaction transaction(kRangeGET_TransactionOK);
@@ -4335,12 +4386,13 @@ TEST(HttpCache, GET_CancelIncompleteResource) {
Context* c = new Context();
EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(&c->trans));
- rv = c->trans->Start(&request, &c->callback, net::BoundNetLog());
+ int rv = c->trans->Start(&request, &c->callback, net::BoundNetLog());
EXPECT_EQ(net::OK, c->callback.GetResult(rv));
// Read 20 bytes from the cache, and 10 from the net.
- rv = c->trans->Read(buf, len, &c->callback);
- EXPECT_EQ(len, c->callback.GetResult(rv));
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(100));
+ rv = c->trans->Read(buf, 20, &c->callback);
+ EXPECT_EQ(20, c->callback.GetResult(rv));
rv = c->trans->Read(buf, 10, &c->callback);
EXPECT_EQ(10, c->callback.GetResult(rv));
@@ -4348,18 +4400,20 @@ TEST(HttpCache, GET_CancelIncompleteResource) {
// a truncated one.
delete c;
- RemoveMockTransaction(&kRangeGET_TransactionOK);
-
EXPECT_EQ(2, cache.network_layer()->transaction_count());
EXPECT_EQ(1, cache.disk_cache()->open_count());
EXPECT_EQ(1, cache.disk_cache()->create_count());
// Verify that the disk entry was updated: now we have 30 bytes.
+ disk_cache::Entry* entry;
+ ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
EXPECT_EQ(30, entry->GetDataSize(1));
bool truncated = false;
+ net::HttpResponseInfo response;
EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
EXPECT_TRUE(truncated);
entry->Close();
+ RemoveMockTransaction(&kRangeGET_TransactionOK);
}
// Tests that we can handle range requests when we have a truncated entry.
@@ -4367,32 +4421,13 @@ TEST(HttpCache, RangeGET_IncompleteResource) {
MockHttpCache cache;
AddMockTransaction(&kRangeGET_TransactionOK);
- // Create a disk cache entry that stores an incomplete resource.
- disk_cache::Entry* entry;
- ASSERT_TRUE(cache.CreateBackendEntry(kRangeGET_TransactionOK.url, &entry,
- NULL));
-
// Content-length will be intentionally bogus.
std::string raw_headers("HTTP/1.1 200 OK\n"
"Last-Modified: something\n"
"ETag: \"foo\"\n"
"Accept-Ranges: bytes\n"
"Content-Length: 10\n");
- raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(),
- raw_headers.size());
-
- net::HttpResponseInfo response;
- response.headers = new net::HttpResponseHeaders(raw_headers);
- // Set the last argument for this to be an incomplete request.
- EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
-
- scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(100));
- int len = static_cast<int>(base::strlcpy(buf->data(),
- "rg: 00-09 rg: 10-19 ", 100));
- TestCompletionCallback cb;
- int rv = entry->WriteData(1, 0, buf, len, &cb, true);
- EXPECT_EQ(len, cb.GetResult(rv));
- entry->Close();
+ CreateTruncatedEntry(raw_headers, &cache);
// Now make a range request.
std::string headers;
diff --git a/net/http/partial_data.cc b/net/http/partial_data.cc
index 68d8048..c1f448e 100644
--- a/net/http/partial_data.cc
+++ b/net/http/partial_data.cc
@@ -111,6 +111,7 @@ PartialData::PartialData()
final_range_(false),
sparse_entry_(true),
truncated_(false),
+ initial_validation_(false),
core_(NULL),
callback_(NULL) {
}
@@ -153,7 +154,7 @@ void PartialData::RestoreHeaders(HttpRequestHeaders* headers) const {
byte_range_.suffix_length() : byte_range_.last_byte_position();
headers->CopyFrom(extra_headers_);
- if (byte_range_.IsValid())
+ if (!truncated_ && byte_range_.IsValid())
AddRangeHeader(current_range_start_, end, headers);
}
@@ -178,13 +179,7 @@ int PartialData::ShouldValidateCache(disk_cache::Entry* entry,
callback_ = callback;
return ERR_IO_PENDING;
}
- } else if (truncated_) {
- if (!current_range_start_) {
- // Update the cached range only the first time.
- cached_min_len_ = static_cast<int32>(byte_range_.first_byte_position());
- cached_start_ = 0;
- }
- } else {
+ } else if (!truncated_) {
if (byte_range_.HasFirstBytePosition() &&
byte_range_.first_byte_position() >= resource_size_) {
// The caller should take care of this condition because we should have
@@ -259,10 +254,14 @@ bool PartialData::UpdateFromStoredHeaders(const HttpResponseHeaders* headers,
return false;
truncated_ = true;
+ initial_validation_ = true;
sparse_entry_ = false;
- byte_range_.set_first_byte_position(entry->GetDataSize(kDataStream));
+ int current_len = entry->GetDataSize(kDataStream);
+ byte_range_.set_first_byte_position(current_len);
resource_size_ = total_length;
- current_range_start_ = 0;
+ current_range_start_ = current_len;
+ cached_min_len_ = current_len;
+ cached_start_ = current_len + 1;
return true;
}
@@ -284,12 +283,20 @@ bool PartialData::UpdateFromStoredHeaders(const HttpResponseHeaders* headers,
return entry->CouldBeSparse();
}
+void PartialData::SetRangeToStartDownload() {
+ DCHECK(truncated_);
+ DCHECK(!sparse_entry_);
+ current_range_start_ = 0;
+ cached_start_ = 0;
+ initial_validation_ = false;
+}
+
bool PartialData::IsRequestedRangeOK() {
if (byte_range_.IsValid()) {
- if (truncated_)
- return true;
if (!byte_range_.ComputeBounds(resource_size_))
return false;
+ if (truncated_)
+ return true;
if (current_range_start_ < 0)
current_range_start_ = byte_range_.first_byte_position();
diff --git a/net/http/partial_data.h b/net/http/partial_data.h
index 4726d10..6224fdf 100644
--- a/net/http/partial_data.h
+++ b/net/http/partial_data.h
@@ -75,6 +75,9 @@ class PartialData {
bool UpdateFromStoredHeaders(const HttpResponseHeaders* headers,
disk_cache::Entry* entry, bool truncated);
+ // Sets the byte current range to start again at zero (for a truncated entry).
+ void SetRangeToStartDownload();
+
// Returns true if the requested range is valid given the stored data.
bool IsRequestedRangeOK();
@@ -110,6 +113,8 @@ class PartialData {
// update the internal state about the current range.
void OnNetworkReadCompleted(int result);
+ bool initial_validation() const { return initial_validation_; }
+
private:
class Core;
// Returns the length to use when scanning the cache.
@@ -129,6 +134,7 @@ class PartialData {
bool final_range_;
bool sparse_entry_;
bool truncated_; // We have an incomplete 200 stored.
+ bool initial_validation_; // Only used for truncated entries.
Core* core_;
CompletionCallback* callback_;