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

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: Created 5 years, 4 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 <limits>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
9 #include "base/format_macros.h" 11 #include "base/format_macros.h"
10 #include "base/logging.h" 12 #include "base/logging.h"
11 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
14 #include "net/base/net_errors.h" 16 #include "net/base/net_errors.h"
15 #include "net/disk_cache/disk_cache.h" 17 #include "net/disk_cache/disk_cache.h"
16 #include "net/http/http_response_headers.h" 18 #include "net/http/http_response_headers.h"
17 #include "net/http/http_util.h" 19 #include "net/http/http_util.h"
18 20
19 namespace net { 21 namespace net {
20 22
21 namespace { 23 namespace {
22 24
23 // The headers that we have to process. 25 // The headers that we have to process.
24 const char kLengthHeader[] = "Content-Length"; 26 const char kLengthHeader[] = "Content-Length";
25 const char kRangeHeader[] = "Content-Range"; 27 const char kRangeHeader[] = "Content-Range";
26 const int kDataStream = 1; 28 const int kDataStream = 1;
29 const int64 kUnbounded = std::numeric_limits<int64>::max();
rvargas (doing something else) 2015/08/19 23:46:39 A recent chr-dev thread suggest this may use an st
asanka 2015/09/04 19:09:04 Done. I used basictypes.h instead of sttdint becau
27 30
28 } // namespace 31 } // namespace
29 32
30 PartialData::PartialData() 33 PartialData::PartialData()
31 : current_range_start_(0), 34 : current_range_start_(0),
32 current_range_end_(0), 35 current_range_end_(0),
33 cached_start_(0), 36 cached_start_(0),
34 resource_size_(0), 37 resource_size_(0),
35 cached_min_len_(0), 38 cached_min_len_(0),
36 range_present_(false), 39 range_present_(false),
(...skipping 16 matching lines...) Expand all
53 if (!HttpUtil::ParseRangeHeader(range_header, &ranges) || ranges.size() != 1) 56 if (!HttpUtil::ParseRangeHeader(range_header, &ranges) || ranges.size() != 1)
54 return false; 57 return false;
55 58
56 // We can handle this range request. 59 // We can handle this range request.
57 byte_range_ = ranges[0]; 60 byte_range_ = ranges[0];
58 if (!byte_range_.IsValid()) 61 if (!byte_range_.IsValid())
59 return false; 62 return false;
60 63
61 current_range_start_ = byte_range_.first_byte_position(); 64 current_range_start_ = byte_range_.first_byte_position();
62 65
63 DVLOG(1) << "Range start: " << current_range_start_ << " end: " << 66 DVLOG(1) << "Range start: " << current_range_start_
64 byte_range_.last_byte_position(); 67 << " end: " << byte_range_.last_byte_position();
65 return true; 68 return true;
66 } 69 }
67 70
68 void PartialData::SetHeaders(const HttpRequestHeaders& headers) { 71 void PartialData::SetHeaders(const HttpRequestHeaders& headers) {
69 DCHECK(extra_headers_.IsEmpty()); 72 DCHECK(extra_headers_.IsEmpty());
70 extra_headers_.CopyFrom(headers); 73 extra_headers_.CopyFrom(headers);
71 } 74 }
72 75
73 void PartialData::RestoreHeaders(HttpRequestHeaders* headers) const { 76 void PartialData::RestoreHeaders(HttpRequestHeaders* headers) const {
74 DCHECK(current_range_start_ >= 0 || byte_range_.IsSuffixByteRange()); 77 DCHECK(current_range_start_ >= 0 || byte_range_.IsSuffixByteRange());
(...skipping 12 matching lines...) Expand all
87 HttpByteRange::Bounded( 90 HttpByteRange::Bounded(
88 current_range_start_, end).GetHeaderValue()); 91 current_range_start_, end).GetHeaderValue());
89 } 92 }
90 } 93 }
91 94
92 int PartialData::ShouldValidateCache(disk_cache::Entry* entry, 95 int PartialData::ShouldValidateCache(disk_cache::Entry* entry,
93 const CompletionCallback& callback) { 96 const CompletionCallback& callback) {
94 DCHECK_GE(current_range_start_, 0); 97 DCHECK_GE(current_range_start_, 0);
95 98
96 // Scan the disk cache for the first cached portion within this range. 99 // Scan the disk cache for the first cached portion within this range.
97 int len = GetNextRangeLen(); 100 int64 len = GetNextRangeLen();
98 if (!len) 101 if (!len)
99 return 0; 102 return 0;
100 103
101 DVLOG(3) << "ShouldValidateCache len: " << len; 104 DVLOG(3) << "ShouldValidateCache len: " << len;
102 105
103 if (sparse_entry_) { 106 if (sparse_entry_) {
104 DCHECK(callback_.is_null()); 107 DCHECK(callback_.is_null());
105 int64* start = new int64; 108 int64* start = new int64;
109 // TODO(asanka): Use the full |len| when int64_t is plumbed all the way
110 // through.
111 int cached_len = std::min<int64>(std::numeric_limits<int32>::max(), len);
112
106 // This callback now owns "start". We make sure to keep it 113 // This callback now owns "start". We make sure to keep it
107 // in a local variable since we want to use it later. 114 // in a local variable since we want to use it later.
108 CompletionCallback cb = 115 CompletionCallback cb =
109 base::Bind(&PartialData::GetAvailableRangeCompleted, 116 base::Bind(&PartialData::GetAvailableRangeCompleted,
110 weak_factory_.GetWeakPtr(), base::Owned(start)); 117 weak_factory_.GetWeakPtr(), base::Owned(start));
111 cached_min_len_ = 118 cached_min_len_ =
112 entry->GetAvailableRange(current_range_start_, len, start, cb); 119 entry->GetAvailableRange(current_range_start_, cached_len, start, cb);
113 120
114 if (cached_min_len_ == ERR_IO_PENDING) { 121 if (cached_min_len_ == ERR_IO_PENDING) {
115 callback_ = callback; 122 callback_ = callback;
116 return ERR_IO_PENDING; 123 return ERR_IO_PENDING;
117 } else { 124 } else {
118 cached_start_ = *start; 125 cached_start_ = *start;
119 } 126 }
120 } else if (!truncated_) { 127 } else if (!truncated_) {
rvargas (doing something else) 2015/08/19 23:46:39 Aren't we going through this else after SkipCacheF
asanka 2015/09/04 19:09:04 Changed SkipCacheForRemainder() to explicitly set
121 if (byte_range_.HasFirstBytePosition() && 128 if (byte_range_.HasFirstBytePosition() &&
122 byte_range_.first_byte_position() >= resource_size_) { 129 byte_range_.first_byte_position() >= resource_size_) {
123 // The caller should take care of this condition because we should have 130 // The caller should take care of this condition because we should have
124 // failed IsRequestedRangeOK(), but it's better to be consistent here. 131 // failed IsRequestedRangeOK(), but it's better to be consistent here.
125 len = 0; 132 len = 0;
126 } 133 }
127 cached_min_len_ = len; 134 cached_min_len_ = len;
128 cached_start_ = current_range_start_; 135 cached_start_ = current_range_start_;
129 } 136 }
130 137
131 if (cached_min_len_ < 0) 138 if (cached_min_len_ < 0)
132 return cached_min_len_; 139 return cached_min_len_;
133 140
134 // Return a positive number to indicate success (versus error or finished). 141 // Return a positive number to indicate success (versus error or finished).
135 return 1; 142 return 1;
136 } 143 }
137 144
138 void PartialData::PrepareCacheValidation(disk_cache::Entry* entry, 145 void PartialData::PrepareCacheValidation(disk_cache::Entry* entry,
139 HttpRequestHeaders* headers) { 146 HttpRequestHeaders* headers) {
140 DCHECK_GE(current_range_start_, 0); 147 DCHECK_GE(current_range_start_, 0);
141 DCHECK_GE(cached_min_len_, 0); 148 DCHECK_GE(cached_min_len_, 0);
142 149
143 int len = GetNextRangeLen(); 150 int64 len = GetNextRangeLen();
151 // PrepareCacheValidation shouldn't have been called if ShouldValidateCache()
152 // returned 0.
144 DCHECK_NE(0, len); 153 DCHECK_NE(0, len);
145 range_present_ = false; 154 range_present_ = false;
146 155
147 headers->CopyFrom(extra_headers_); 156 headers->CopyFrom(extra_headers_);
148 157
149 if (!cached_min_len_) { 158 if (!cached_min_len_) {
150 // We don't have anything else stored. 159 // We don't have anything else stored.
151 final_range_ = true; 160 final_range_ = true;
152 cached_start_ = 161 cached_start_ =
153 byte_range_.HasLastBytePosition() ? current_range_start_ + len : 0; 162 byte_range_.HasLastBytePosition() ? current_range_start_ + len : 0;
154 } 163 }
155 164
156 if (current_range_start_ == cached_start_) { 165 if (current_range_start_ == cached_start_) {
157 // The data lives in the cache. 166 // The data lives in the cache.
158 range_present_ = true; 167 range_present_ = true;
159 current_range_end_ = cached_start_ + cached_min_len_ - 1; 168 current_range_end_ = cached_start_ + cached_min_len_ - 1;
160 if (len == cached_min_len_) 169 if (len == cached_min_len_)
161 final_range_ = true; 170 final_range_ = true;
162 } else { 171 } else {
163 // This range is not in the cache. 172 // This range is not in the cache.
164 current_range_end_ = cached_start_ - 1; 173 current_range_end_ = cached_start_ - 1;
165 } 174 }
175
166 headers->SetHeader( 176 headers->SetHeader(
167 HttpRequestHeaders::kRange, 177 HttpRequestHeaders::kRange,
168 HttpByteRange::Bounded(current_range_start_, current_range_end_) 178 HttpByteRange::Bounded(current_range_start_, current_range_end_)
169 .GetHeaderValue()); 179 .GetHeaderValue());
170 } 180 }
171 181
172 bool PartialData::IsCurrentRangeCached() const { 182 bool PartialData::IsCurrentRangeCached() const {
173 return range_present_; 183 return range_present_;
174 } 184 }
175 185
176 bool PartialData::IsLastRange() const { 186 bool PartialData::IsLastRange() const {
177 return final_range_; 187 return final_range_;
178 } 188 }
179 189
180 bool PartialData::UpdateFromStoredHeaders(const HttpResponseHeaders* headers, 190 bool PartialData::UpdateFromStoredHeaders(const HttpResponseHeaders* headers,
181 disk_cache::Entry* entry, 191 disk_cache::Entry* entry,
182 bool truncated) { 192 bool truncated) {
183 resource_size_ = 0; 193 resource_size_ = 0;
184 if (truncated) { 194 if (truncated) {
185 DCHECK_EQ(headers->response_code(), 200); 195 DCHECK_EQ(headers->response_code(), 200);
186 // We don't have the real length and the user may be trying to create a 196 // 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. 197 // sparse entry so let's not write to this entry.
198 std::string header_string;
199 headers->GetNormalizedHeaders(&header_string);
188 if (byte_range_.IsValid()) 200 if (byte_range_.IsValid())
189 return false; 201 return false;
190 202
191 if (!headers->HasStrongValidators()) 203 if (!headers->HasStrongValidators())
192 return false; 204 return false;
193 205
194 // Now we avoid resume if there is no content length, but that was not 206 // Now we avoid resume if there is no content length, but that was not
195 // always the case so double check here. 207 // always the case so double check here.
196 int64 total_length = headers->GetContentLength(); 208 int64 total_length = headers->GetContentLength();
197 if (total_length <= 0) 209 if (total_length <= 0)
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 } 243 }
232 244
233 void PartialData::SetRangeToStartDownload() { 245 void PartialData::SetRangeToStartDownload() {
234 DCHECK(truncated_); 246 DCHECK(truncated_);
235 DCHECK(!sparse_entry_); 247 DCHECK(!sparse_entry_);
236 current_range_start_ = 0; 248 current_range_start_ = 0;
237 cached_start_ = 0; 249 cached_start_ = 0;
238 initial_validation_ = false; 250 initial_validation_ = false;
239 } 251 }
240 252
253 bool PartialData::SkipCacheForRemainder() {
254 if (GetNextRangeLen() == 0)
255 return false;
256
257 sparse_entry_ = false;
258 cached_start_ = 0;
259 cached_min_len_ = 0;
260 return true;
261 }
262
241 bool PartialData::IsRequestedRangeOK() { 263 bool PartialData::IsRequestedRangeOK() {
242 if (byte_range_.IsValid()) { 264 if (byte_range_.IsValid()) {
243 if (!byte_range_.ComputeBounds(resource_size_)) 265 if (!byte_range_.ComputeBounds(resource_size_))
244 return false; 266 return false;
245 if (truncated_) 267 if (truncated_)
246 return true; 268 return true;
247 269
248 if (current_range_start_ < 0) 270 if (current_range_start_ < 0)
249 current_range_start_ = byte_range_.first_byte_position(); 271 current_range_start_ = byte_range_.first_byte_position();
250 } else { 272 } else {
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 void PartialData::FixContentLength(HttpResponseHeaders* headers) { 380 void PartialData::FixContentLength(HttpResponseHeaders* headers) {
359 headers->RemoveHeader(kLengthHeader); 381 headers->RemoveHeader(kLengthHeader);
360 headers->AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader, 382 headers->AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader,
361 resource_size_)); 383 resource_size_));
362 } 384 }
363 385
364 int PartialData::CacheRead(disk_cache::Entry* entry, 386 int PartialData::CacheRead(disk_cache::Entry* entry,
365 IOBuffer* data, 387 IOBuffer* data,
366 int data_len, 388 int data_len,
367 const CompletionCallback& callback) { 389 const CompletionCallback& callback) {
368 int read_len = std::min(data_len, cached_min_len_); 390 int read_len = std::min<int64>(data_len, cached_min_len_);
369 if (!read_len) 391 if (!read_len)
370 return 0; 392 return 0;
371 393
372 int rv = 0; 394 int rv = 0;
373 if (sparse_entry_) { 395 if (sparse_entry_) {
374 rv = entry->ReadSparseData(current_range_start_, data, read_len, 396 rv = entry->ReadSparseData(current_range_start_, data, read_len,
375 callback); 397 callback);
376 } else { 398 } else {
377 if (current_range_start_ > kint32max) 399 if (current_range_start_ > kint32max)
378 return ERR_INVALID_ARGUMENT; 400 return ERR_INVALID_ARGUMENT;
(...skipping 28 matching lines...) Expand all
407 cached_min_len_ -= result; 429 cached_min_len_ -= result;
408 DCHECK_GE(cached_min_len_, 0); 430 DCHECK_GE(cached_min_len_, 0);
409 } 431 }
410 } 432 }
411 433
412 void PartialData::OnNetworkReadCompleted(int result) { 434 void PartialData::OnNetworkReadCompleted(int result) {
413 if (result > 0) 435 if (result > 0)
414 current_range_start_ += result; 436 current_range_start_ += result;
415 } 437 }
416 438
417 int PartialData::GetNextRangeLen() { 439 int64 PartialData::GetNextRangeLen() {
418 int64 range_len = 440 return byte_range_.HasLastBytePosition()
419 byte_range_.HasLastBytePosition() ? 441 ? byte_range_.last_byte_position() - current_range_start_ + 1
420 byte_range_.last_byte_position() - current_range_start_ + 1 : 442 : kUnbounded;
421 kint32max;
422 if (range_len > kint32max)
423 range_len = kint32max;
424 return static_cast<int32>(range_len);
425 } 443 }
426 444
427 void PartialData::GetAvailableRangeCompleted(int64* start, int result) { 445 void PartialData::GetAvailableRangeCompleted(int64* start, int result) {
428 DCHECK(!callback_.is_null()); 446 DCHECK(!callback_.is_null());
429 DCHECK_NE(ERR_IO_PENDING, result); 447 DCHECK_NE(ERR_IO_PENDING, result);
430 448
431 cached_start_ = *start; 449 cached_start_ = *start;
432 cached_min_len_ = result; 450 cached_min_len_ = result;
433 if (result >= 0) 451 if (result >= 0)
434 result = 1; // Return success, go ahead and validate the entry. 452 result = 1; // Return success, go ahead and validate the entry.
435 453
436 CompletionCallback cb = callback_; 454 CompletionCallback cb = callback_;
437 callback_.Reset(); 455 callback_.Reset();
438 cb.Run(result); 456 cb.Run(result);
439 } 457 }
440 458
441 } // namespace net 459 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698