Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(29)

Side by Side Diff: net/http/partial_data.cc

Issue 1230113012: [net] Better StopCaching() handling for HttpCache::Transaction. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add missing MockTransaction initializers Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/partial_data.h" 5 #include "net/http/partial_data.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/format_macros.h" 9 #include "base/format_macros.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h" 12 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
14 #include "net/base/net_errors.h" 14 #include "net/base/net_errors.h"
15 #include "net/disk_cache/disk_cache.h" 15 #include "net/disk_cache/disk_cache.h"
16 #include "net/http/http_response_headers.h" 16 #include "net/http/http_response_headers.h"
17 #include "net/http/http_util.h" 17 #include "net/http/http_util.h"
18 18
19 namespace net { 19 namespace net {
20 20
21 namespace { 21 namespace {
22 22
23 // The headers that we have to process. 23 // The headers that we have to process.
24 const char kLengthHeader[] = "Content-Length"; 24 const char kLengthHeader[] = "Content-Length";
25 const char kRangeHeader[] = "Content-Range"; 25 const char kRangeHeader[] = "Content-Range";
26 const int kDataStream = 1; 26 const int kDataStream = 1;
27 const int64 kUnbounded = kint64max;
27 28
28 } // namespace 29 } // namespace
29 30
30 PartialData::PartialData() 31 PartialData::PartialData()
31 : current_range_start_(0), 32 : current_range_start_(0),
32 current_range_end_(0), 33 current_range_end_(0),
33 cached_start_(0), 34 cached_start_(0),
34 resource_size_(0), 35 resource_size_(0),
35 cached_min_len_(0), 36 cached_min_len_(0),
36 range_present_(false), 37 range_present_(false),
(...skipping 16 matching lines...) Expand all
53 if (!HttpUtil::ParseRangeHeader(range_header, &ranges) || ranges.size() != 1) 54 if (!HttpUtil::ParseRangeHeader(range_header, &ranges) || ranges.size() != 1)
54 return false; 55 return false;
55 56
56 // We can handle this range request. 57 // We can handle this range request.
57 byte_range_ = ranges[0]; 58 byte_range_ = ranges[0];
58 if (!byte_range_.IsValid()) 59 if (!byte_range_.IsValid())
59 return false; 60 return false;
60 61
61 current_range_start_ = byte_range_.first_byte_position(); 62 current_range_start_ = byte_range_.first_byte_position();
62 63
63 DVLOG(1) << "Range start: " << current_range_start_ << " end: " << 64 DVLOG(1) << "Range start: " << current_range_start_
64 byte_range_.last_byte_position(); 65 << " end: " << byte_range_.last_byte_position();
65 return true; 66 return true;
66 } 67 }
67 68
68 void PartialData::SetHeaders(const HttpRequestHeaders& headers) { 69 void PartialData::SetHeaders(const HttpRequestHeaders& headers) {
69 DCHECK(extra_headers_.IsEmpty()); 70 DCHECK(extra_headers_.IsEmpty());
70 extra_headers_.CopyFrom(headers); 71 extra_headers_.CopyFrom(headers);
71 } 72 }
72 73
73 void PartialData::RestoreHeaders(HttpRequestHeaders* headers) const { 74 void PartialData::RestoreHeaders(HttpRequestHeaders* headers) const {
74 DCHECK(current_range_start_ >= 0 || byte_range_.IsSuffixByteRange()); 75 DCHECK(current_range_start_ >= 0 || byte_range_.IsSuffixByteRange());
(...skipping 12 matching lines...) Expand all
87 HttpByteRange::Bounded( 88 HttpByteRange::Bounded(
88 current_range_start_, end).GetHeaderValue()); 89 current_range_start_, end).GetHeaderValue());
89 } 90 }
90 } 91 }
91 92
92 int PartialData::ShouldValidateCache(disk_cache::Entry* entry, 93 int PartialData::ShouldValidateCache(disk_cache::Entry* entry,
93 const CompletionCallback& callback) { 94 const CompletionCallback& callback) {
94 DCHECK_GE(current_range_start_, 0); 95 DCHECK_GE(current_range_start_, 0);
95 96
96 // Scan the disk cache for the first cached portion within this range. 97 // Scan the disk cache for the first cached portion within this range.
97 int len = GetNextRangeLen(); 98 int64 current_range_len =
98 if (!len) 99 byte_range_.HasLastBytePosition()
100 ? byte_range_.last_byte_position() - current_range_start_ + 1
101 : kUnbounded;
102 if (!current_range_len)
99 return 0; 103 return 0;
100 104
101 DVLOG(3) << "ShouldValidateCache len: " << len; 105 DVLOG(3) << "ShouldValidateCache current_range_len: " << current_range_len;
102 106
103 if (sparse_entry_) { 107 if (sparse_entry_) {
104 DCHECK(callback_.is_null()); 108 DCHECK(callback_.is_null());
105 int64* start = new int64; 109 int64* start = new int64;
110 // TODO(asanka): Use the full |current_range_len| when int64_t is plumbed
111 // all the way through.
112 int cached_len = std::min<int64>(kint32max, current_range_len);
113
106 // This callback now owns "start". We make sure to keep it 114 // This callback now owns "start". We make sure to keep it
107 // in a local variable since we want to use it later. 115 // in a local variable since we want to use it later.
108 CompletionCallback cb = 116 CompletionCallback cb =
109 base::Bind(&PartialData::GetAvailableRangeCompleted, 117 base::Bind(&PartialData::GetAvailableRangeCompleted,
110 weak_factory_.GetWeakPtr(), base::Owned(start)); 118 weak_factory_.GetWeakPtr(), base::Owned(start));
111 cached_min_len_ = 119 cached_min_len_ =
112 entry->GetAvailableRange(current_range_start_, len, start, cb); 120 entry->GetAvailableRange(current_range_start_, cached_len, start, cb);
113 121
114 if (cached_min_len_ == ERR_IO_PENDING) { 122 if (cached_min_len_ == ERR_IO_PENDING) {
115 callback_ = callback; 123 callback_ = callback;
116 return ERR_IO_PENDING; 124 return ERR_IO_PENDING;
117 } else { 125 } else {
118 cached_start_ = *start; 126 cached_start_ = *start;
119 } 127 }
120 } else if (!truncated_) { 128 } else if (!truncated_) {
121 if (byte_range_.HasFirstBytePosition() && 129 if (byte_range_.HasFirstBytePosition() &&
122 byte_range_.first_byte_position() >= resource_size_) { 130 byte_range_.first_byte_position() >= resource_size_) {
123 // The caller should take care of this condition because we should have 131 // The caller should take care of this condition because we should have
124 // failed IsRequestedRangeOK(), but it's better to be consistent here. 132 // failed IsRequestedRangeOK(), but it's better to be consistent here.
125 len = 0; 133 current_range_len = 0;
126 } 134 }
127 cached_min_len_ = len; 135 cached_min_len_ = current_range_len;
128 cached_start_ = current_range_start_; 136 cached_start_ = current_range_start_;
129 } 137 }
130 138
131 if (cached_min_len_ < 0) 139 if (cached_min_len_ < 0)
132 return cached_min_len_; 140 return cached_min_len_;
133 141
134 // Return a positive number to indicate success (versus error or finished). 142 // Return a positive number to indicate success (versus error or finished).
135 return 1; 143 return 1;
136 } 144 }
137 145
138 void PartialData::PrepareCacheValidation(disk_cache::Entry* entry, 146 void PartialData::PrepareCacheValidation(disk_cache::Entry* entry,
139 HttpRequestHeaders* headers) { 147 HttpRequestHeaders* headers) {
140 DCHECK_GE(current_range_start_, 0); 148 DCHECK_GE(current_range_start_, 0);
141 DCHECK_GE(cached_min_len_, 0); 149 DCHECK_GE(cached_min_len_, 0);
142 150
143 int len = GetNextRangeLen(); 151 int64 current_range_len =
144 DCHECK_NE(0, len); 152 byte_range_.HasLastBytePosition()
153 ? byte_range_.last_byte_position() - current_range_start_ + 1
154 : kUnbounded;
155 // PrepareCacheValidation shouldn't have been called if ShouldValidateCache()
156 // returned 0.
157 DCHECK_NE(0, current_range_len);
145 range_present_ = false; 158 range_present_ = false;
146 159
147 headers->CopyFrom(extra_headers_); 160 headers->CopyFrom(extra_headers_);
148 161
149 if (!cached_min_len_) { 162 if (!cached_min_len_) {
150 // We don't have anything else stored. 163 // We don't have anything else stored.
151 final_range_ = true; 164 final_range_ = true;
152 cached_start_ = 165 cached_start_ = byte_range_.HasLastBytePosition()
153 byte_range_.HasLastBytePosition() ? current_range_start_ + len : 0; 166 ? current_range_start_ + current_range_len
167 : 0;
154 } 168 }
155 169
156 if (current_range_start_ == cached_start_) { 170 if (current_range_start_ == cached_start_ && cached_min_len_) {
157 // The data lives in the cache. 171 // The data lives in the cache.
158 range_present_ = true; 172 range_present_ = true;
159 current_range_end_ = cached_start_ + cached_min_len_ - 1; 173 current_range_end_ = cached_start_ + cached_min_len_ - 1;
160 if (len == cached_min_len_) 174 if (current_range_len == cached_min_len_)
161 final_range_ = true; 175 final_range_ = true;
162 } else { 176 } else {
163 // This range is not in the cache. 177 // This range is not in the cache.
164 current_range_end_ = cached_start_ - 1; 178 current_range_end_ = cached_start_ - 1;
165 } 179 }
180
166 headers->SetHeader( 181 headers->SetHeader(
167 HttpRequestHeaders::kRange, 182 HttpRequestHeaders::kRange,
168 HttpByteRange::Bounded(current_range_start_, current_range_end_) 183 HttpByteRange::Bounded(current_range_start_, current_range_end_)
169 .GetHeaderValue()); 184 .GetHeaderValue());
170 } 185 }
171 186
172 bool PartialData::IsCurrentRangeCached() const { 187 bool PartialData::IsCurrentRangeCached() const {
173 return range_present_; 188 return range_present_;
174 } 189 }
175 190
176 bool PartialData::IsLastRange() const { 191 bool PartialData::IsLastRange() const {
177 return final_range_; 192 return final_range_;
178 } 193 }
179 194
180 bool PartialData::UpdateFromStoredHeaders(const HttpResponseHeaders* headers, 195 bool PartialData::UpdateFromStoredHeaders(const HttpResponseHeaders* headers,
181 disk_cache::Entry* entry, 196 disk_cache::Entry* entry,
182 bool truncated) { 197 bool truncated) {
183 resource_size_ = 0; 198 resource_size_ = 0;
184 if (truncated) { 199 if (truncated) {
185 DCHECK_EQ(headers->response_code(), 200); 200 DCHECK_EQ(headers->response_code(), 200);
186 // We don't have the real length and the user may be trying to create a 201 // We don't have the real length and the user may be trying to create a
187 // sparse entry so let's not write to this entry. 202 // sparse entry so let's not write to this entry.
203 std::string header_string;
204 headers->GetNormalizedHeaders(&header_string);
188 if (byte_range_.IsValid()) 205 if (byte_range_.IsValid())
189 return false; 206 return false;
190 207
191 if (!headers->HasStrongValidators()) 208 if (!headers->HasStrongValidators())
192 return false; 209 return false;
193 210
194 // Now we avoid resume if there is no content length, but that was not 211 // Now we avoid resume if there is no content length, but that was not
195 // always the case so double check here. 212 // always the case so double check here.
196 int64 total_length = headers->GetContentLength(); 213 int64 total_length = headers->GetContentLength();
197 if (total_length <= 0) 214 if (total_length <= 0)
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 } 248 }
232 249
233 void PartialData::SetRangeToStartDownload() { 250 void PartialData::SetRangeToStartDownload() {
234 DCHECK(truncated_); 251 DCHECK(truncated_);
235 DCHECK(!sparse_entry_); 252 DCHECK(!sparse_entry_);
236 current_range_start_ = 0; 253 current_range_start_ = 0;
237 cached_start_ = 0; 254 cached_start_ = 0;
238 initial_validation_ = false; 255 initial_validation_ = false;
239 } 256 }
240 257
258 bool PartialData::SkipCacheForRemainder() {
259 if (byte_range_.HasLastBytePosition() &&
260 current_range_start_ > byte_range_.last_byte_position()) {
261 return false;
262 }
263
264 // Don't look for any more cached sparse ranges.
265 sparse_entry_ = false;
266
267 // Ignoring the remainder of the cached entry is equivalent to the cache entry
268 // having been truncated.
269 truncated_ = true;
270
271 // Current range is not cached.
272 cached_start_ = 0;
273 cached_min_len_ = 0;
274 return true;
275 }
276
241 bool PartialData::IsRequestedRangeOK() { 277 bool PartialData::IsRequestedRangeOK() {
242 if (byte_range_.IsValid()) { 278 if (byte_range_.IsValid()) {
243 if (!byte_range_.ComputeBounds(resource_size_)) 279 if (!byte_range_.ComputeBounds(resource_size_))
244 return false; 280 return false;
245 if (truncated_) 281 if (truncated_)
246 return true; 282 return true;
247 283
248 if (current_range_start_ < 0) 284 if (current_range_start_ < 0)
249 current_range_start_ = byte_range_.first_byte_position(); 285 current_range_start_ = byte_range_.first_byte_position();
250 } else { 286 } else {
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 void PartialData::FixContentLength(HttpResponseHeaders* headers) { 394 void PartialData::FixContentLength(HttpResponseHeaders* headers) {
359 headers->RemoveHeader(kLengthHeader); 395 headers->RemoveHeader(kLengthHeader);
360 headers->AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader, 396 headers->AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader,
361 resource_size_)); 397 resource_size_));
362 } 398 }
363 399
364 int PartialData::CacheRead(disk_cache::Entry* entry, 400 int PartialData::CacheRead(disk_cache::Entry* entry,
365 IOBuffer* data, 401 IOBuffer* data,
366 int data_len, 402 int data_len,
367 const CompletionCallback& callback) { 403 const CompletionCallback& callback) {
368 int read_len = std::min(data_len, cached_min_len_); 404 int read_len = std::min<int64>(data_len, cached_min_len_);
369 if (!read_len) 405 if (!read_len)
370 return 0; 406 return 0;
371 407
372 int rv = 0; 408 int rv = 0;
373 if (sparse_entry_) { 409 if (sparse_entry_) {
374 rv = entry->ReadSparseData(current_range_start_, data, read_len, 410 rv = entry->ReadSparseData(current_range_start_, data, read_len,
375 callback); 411 callback);
376 } else { 412 } else {
377 if (current_range_start_ > kint32max) 413 if (current_range_start_ > kint32max)
378 return ERR_INVALID_ARGUMENT; 414 return ERR_INVALID_ARGUMENT;
(...skipping 28 matching lines...) Expand all
407 cached_min_len_ -= result; 443 cached_min_len_ -= result;
408 DCHECK_GE(cached_min_len_, 0); 444 DCHECK_GE(cached_min_len_, 0);
409 } 445 }
410 } 446 }
411 447
412 void PartialData::OnNetworkReadCompleted(int result) { 448 void PartialData::OnNetworkReadCompleted(int result) {
413 if (result > 0) 449 if (result > 0)
414 current_range_start_ += result; 450 current_range_start_ += result;
415 } 451 }
416 452
417 int PartialData::GetNextRangeLen() {
418 int64 range_len =
419 byte_range_.HasLastBytePosition() ?
420 byte_range_.last_byte_position() - current_range_start_ + 1 :
421 kint32max;
422 if (range_len > kint32max)
423 range_len = kint32max;
424 return static_cast<int32>(range_len);
425 }
426
427 void PartialData::GetAvailableRangeCompleted(int64* start, int result) { 453 void PartialData::GetAvailableRangeCompleted(int64* start, int result) {
428 DCHECK(!callback_.is_null()); 454 DCHECK(!callback_.is_null());
429 DCHECK_NE(ERR_IO_PENDING, result); 455 DCHECK_NE(ERR_IO_PENDING, result);
430 456
431 cached_start_ = *start; 457 cached_start_ = *start;
432 cached_min_len_ = result; 458 cached_min_len_ = result;
433 if (result >= 0) 459 if (result >= 0)
434 result = 1; // Return success, go ahead and validate the entry. 460 result = 1; // Return success, go ahead and validate the entry.
435 461
436 CompletionCallback cb = callback_; 462 CompletionCallback cb = callback_;
437 callback_.Reset(); 463 callback_.Reset();
438 cb.Run(result); 464 cb.Run(result);
439 } 465 }
440 466
441 } // namespace net 467 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698