[go: nahoru, domu]

Handle range request on a truncated entry

This change will doom the truncated entry and creates a new sparse entry.

TEST=unit tests

Review URL: http://codereview.chromium.org/251067

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27859 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index c1c3478..b6a8bc33c 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -969,8 +969,10 @@
   if (!partial_->UpdateFromStoredHeaders(response_.headers, entry_->disk_entry,
                                          truncated_)) {
     // The stored data cannot be used. Get rid of it and restart this request.
+    // We need to also reset the |truncated_| flag as a new entry is created.
     DoomPartialEntry(!byte_range_requested);
     mode_ = WRITE;
+    truncated_ = false;
     return AddToEntry();
   }
 
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index 064f7c4..ea98c67 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -2541,6 +2541,50 @@
   entry->Close();
 }
 
+// Tests that we can handle range requests when we have a truncated entry.
+TEST(HttpCache, RangeGET_IncompleteResource) {
+  MockHttpCache cache;
+  cache.http_cache()->set_enable_range_support(true);
+  AddMockTransaction(&kRangeGET_TransactionOK);
+
+  // Create a disk cache entry that stores an incomplete resource.
+  disk_cache::Entry* entry;
+  ASSERT_TRUE(cache.disk_cache()->CreateEntry(kRangeGET_TransactionOK.url,
+                                              &entry));
+
+  // 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(net::HttpCache::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));
+  EXPECT_EQ(len, entry->WriteData(1, 0, buf, len, NULL, true));
+  entry->Close();
+
+  // Now make a range request.
+  std::string headers;
+  RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
+                                 &headers);
+
+  EXPECT_TRUE(Verify206Response(headers, 40, 49));
+  EXPECT_EQ(1, cache.network_layer()->transaction_count());
+  EXPECT_EQ(1, cache.disk_cache()->open_count());
+  EXPECT_EQ(2, cache.disk_cache()->create_count());
+
+  RemoveMockTransaction(&kRangeGET_TransactionOK);
+}
+
 TEST(HttpCache, SyncRead) {
   MockHttpCache cache;
 
diff --git a/net/http/partial_data.cc b/net/http/partial_data.cc
index 7257f00..b61d9be 100644
--- a/net/http/partial_data.cc
+++ b/net/http/partial_data.cc
@@ -120,14 +120,13 @@
   resource_size_ = 0;
   if (truncated) {
     DCHECK_EQ(headers->response_code(), 200);
-    truncated_ = true;
-    sparse_entry_ = false;
-
     // We don't have the real length and the user may be trying to create a
     // sparse entry so let's not write to this entry.
     if (byte_range_.IsValid())
       return false;
 
+    truncated_ = true;
+    sparse_entry_ = false;
     byte_range_.set_first_byte_position(entry->GetDataSize(kDataStream));
     current_range_start_ = 0;
     return true;