[go: nahoru, domu]

Http Cache: Improve handling of unexpected responses with byte ranges.

The main change here is to keep track of the end of the requested range
so that when a server returns a different range, we can make sure we
detect the condition and update the response accordingly. Previously we
could detect the condition but fail to update the returned headers (or
more preciselly, overwrite the range header as if nothing happen).

The second change is to avoid reissuing the same network requests twice.
When we detect an unexpected response or an error, we often try to
remove headers changed by the cache an reissue the request; This could
cause the same request issued again (if we didn't add anything to start
with). Now we avoid reissuing requests if there was nothing cached to
start with (so we did not have to modify the requested range).

BUG=421787, 421266
TEST=net_unittests

Review URL: https://codereview.chromium.org/739803002

Cr-Commit-Position: refs/heads/master@{#310015}
diff --git a/net/http/partial_data.cc b/net/http/partial_data.cc
index 247d76b..565623b8 100644
--- a/net/http/partial_data.cc
+++ b/net/http/partial_data.cc
@@ -103,7 +103,12 @@
 // -----------------------------------------------------------------------------
 
 PartialData::PartialData()
-    : range_present_(false),
+    : current_range_start_(0),
+      current_range_end_(0),
+      cached_start_(0),
+      resource_size_(0),
+      cached_min_len_(0),
+      range_present_(false),
       final_range_(false),
       sparse_entry_(true),
       truncated_(false),
@@ -130,7 +135,6 @@
   if (!byte_range_.IsValid())
     return false;
 
-  resource_size_ = 0;
   current_range_start_ = byte_range_.first_byte_position();
 
   DVLOG(1) << "Range start: " << current_range_start_ << " end: " <<
@@ -222,19 +226,20 @@
   if (current_range_start_ == cached_start_) {
     // The data lives in the cache.
     range_present_ = true;
+    current_range_end_ = cached_start_ + cached_min_len_ - 1;
     if (len == cached_min_len_)
       final_range_ = true;
     headers->SetHeader(
         HttpRequestHeaders::kRange,
-        net::HttpByteRange::Bounded(
-            current_range_start_,
-            cached_start_ + cached_min_len_ - 1).GetHeaderValue());
+        HttpByteRange::Bounded(current_range_start_, current_range_end_)
+            .GetHeaderValue());
   } else {
     // This range is not in the cache.
+    current_range_end_ = cached_start_ - 1;
     headers->SetHeader(
         HttpRequestHeaders::kRange,
-        net::HttpByteRange::Bounded(
-            current_range_start_, cached_start_ - 1).GetHeaderValue());
+        HttpByteRange::Bounded(current_range_start_, current_range_end_)
+            .GetHeaderValue());
   }
 }
 
@@ -371,7 +376,21 @@
   if (start != current_range_start_)
     return false;
 
-  if (byte_range_.IsValid() && end > byte_range_.last_byte_position())
+  if (!current_range_end_) {
+    // There is nothing in the cache.
+    DCHECK(byte_range_.HasLastBytePosition());
+    current_range_end_ = byte_range_.last_byte_position();
+    if (current_range_end_ >= resource_size_) {
+      // We didn't know the real file size, and the server is saying that the
+      // requested range goes beyond the size. Fix it.
+      current_range_end_ = end;
+      byte_range_.set_last_byte_position(end);
+    }
+  }
+
+  // If we received a range, but it's not exactly the range we asked for, avoid
+  // trouble and signal an error.
+  if (end != current_range_end_)
     return false;
 
   return true;