[go: nahoru, domu]

blob: 1c7a8c47c30b8dcc3ac61e5531070bc44a1d8f5c [file] [log] [blame]
tbreisacher@chromium.org9987dd72012-01-25 23:40:041// Copyright (c) 2012 The Chromium Authors. All rights reserved.
rvargas@google.com8bf26f49a2009-06-12 17:35:502// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/http/partial_data.h"
6
avid0181f32015-12-10 19:41:477#include <limits>
Bence Béky74838e52018-08-03 19:25:238#include <utility>
avid0181f32015-12-10 19:41:479
jhawkins@chromium.org2a65aceb82011-12-19 20:59:2710#include "base/bind.h"
danakjdb9ae7942020-11-11 16:01:3511#include "base/callback_helpers.h"
evan@chromium.org34b2b002009-11-20 06:53:2812#include "base/format_macros.h"
rvargas@google.com8bf26f49a2009-06-12 17:35:5013#include "base/logging.h"
avi@chromium.org125ef482013-06-11 18:32:4714#include "base/strings/string_number_conversions.h"
15#include "base/strings/string_util.h"
16#include "base/strings/stringprintf.h"
rvargas@google.com8bf26f49a2009-06-12 17:35:5017#include "net/base/net_errors.h"
18#include "net/disk_cache/disk_cache.h"
rvargas@google.com95792eb12009-06-22 21:30:4019#include "net/http/http_response_headers.h"
Feifei Wanged3689f2022-05-29 23:35:3820#include "net/http/http_status_code.h"
rvargas@google.com8bf26f49a2009-06-12 17:35:5021#include "net/http/http_util.h"
22
willchan@chromium.org8c76ae22010-04-20 22:15:4323namespace net {
24
rvargas@google.com95792eb12009-06-22 21:30:4025namespace {
26
27// The headers that we have to process.
28const char kLengthHeader[] = "Content-Length";
29const char kRangeHeader[] = "Content-Range";
rvargas@google.come5dad132009-08-18 00:53:4130const int kDataStream = 1;
rvargas@google.com95792eb12009-06-22 21:30:4031
willchan@chromium.org8c76ae22010-04-20 22:15:4332} // namespace
rvargas@google.com8bf26f49a2009-06-12 17:35:5033
erg@google.comb104b502010-10-18 20:21:3134PartialData::PartialData()
rvargas3b57e37a2015-01-06 00:56:3435 : current_range_start_(0),
36 current_range_end_(0),
37 cached_start_(0),
rvargas3b57e37a2015-01-06 00:56:3438 cached_min_len_(0),
Maks Orlovich332bb11a2018-03-17 01:43:3239 resource_size_(0),
Maks Orlovich70039f12018-11-07 18:52:5740 range_requested_(false),
rvargas3b57e37a2015-01-06 00:56:3441 range_present_(false),
erg@google.comb104b502010-10-18 20:21:3142 final_range_(false),
43 sparse_entry_(true),
44 truncated_(false),
Jeremy Romand54000b22019-07-08 18:40:1645 initial_validation_(false) {}
erg@google.comb104b502010-10-18 20:21:3146
Chris Watkins7a41d3552017-12-01 02:13:2747PartialData::~PartialData() = default;
rvargas@google.com034740a2010-06-11 17:16:4848
willchan@chromium.org8c76ae22010-04-20 22:15:4349bool PartialData::Init(const HttpRequestHeaders& headers) {
50 std::string range_header;
Maks Orlovich70039f12018-11-07 18:52:5751 if (!headers.GetHeader(HttpRequestHeaders::kRange, &range_header)) {
52 range_requested_ = false;
willchan@chromium.org8c76ae22010-04-20 22:15:4353 return false;
Maks Orlovich70039f12018-11-07 18:52:5754 }
55 range_requested_ = true;
willchan@chromium.org8c76ae22010-04-20 22:15:4356
rvargas@google.com8bf26f49a2009-06-12 17:35:5057 std::vector<HttpByteRange> ranges;
willchan@chromium.org8c76ae22010-04-20 22:15:4358 if (!HttpUtil::ParseRangeHeader(range_header, &ranges) || ranges.size() != 1)
rvargas@google.com8bf26f49a2009-06-12 17:35:5059 return false;
60
61 // We can handle this range request.
62 byte_range_ = ranges[0];
63 if (!byte_range_.IsValid())
64 return false;
65
rvargas@google.com8bf26f49a2009-06-12 17:35:5066 current_range_start_ = byte_range_.first_byte_position();
rvargas@google.coma5c9d982010-10-12 20:48:0267
68 DVLOG(1) << "Range start: " << current_range_start_ << " end: " <<
69 byte_range_.last_byte_position();
rvargas@google.com8bf26f49a2009-06-12 17:35:5070 return true;
71}
72
willchan@chromium.org8c76ae22010-04-20 22:15:4373void PartialData::SetHeaders(const HttpRequestHeaders& headers) {
74 DCHECK(extra_headers_.IsEmpty());
75 extra_headers_.CopyFrom(headers);
rvargas@google.come75e8af2009-11-03 00:04:2076}
77
willchan@chromium.org8c76ae22010-04-20 22:15:4378void PartialData::RestoreHeaders(HttpRequestHeaders* headers) const {
rvargas@google.com67fe45c2009-06-24 17:44:5779 DCHECK(current_range_start_ >= 0 || byte_range_.IsSuffixByteRange());
avid0181f32015-12-10 19:41:4780 int64_t end = byte_range_.IsSuffixByteRange()
81 ? byte_range_.suffix_length()
82 : byte_range_.last_byte_position();
rvargas@google.com8bf26f49a2009-06-12 17:35:5083
willchan@chromium.org8c76ae22010-04-20 22:15:4384 headers->CopyFrom(extra_headers_);
tommycli@chromium.orgb7572ea2013-11-26 20:16:3885 if (truncated_ || !byte_range_.IsValid())
86 return;
87
88 if (current_range_start_ < 0) {
89 headers->SetHeader(HttpRequestHeaders::kRange,
90 HttpByteRange::Suffix(end).GetHeaderValue());
91 } else {
92 headers->SetHeader(HttpRequestHeaders::kRange,
93 HttpByteRange::Bounded(
94 current_range_start_, end).GetHeaderValue());
95 }
rvargas@google.com8bf26f49a2009-06-12 17:35:5096}
97
rvargas@google.com034740a2010-06-11 17:16:4898int PartialData::ShouldValidateCache(disk_cache::Entry* entry,
Bence Békya4a50932018-08-10 13:39:4199 CompletionOnceCallback callback) {
rvargas@google.com034740a2010-06-11 17:16:48100 DCHECK_GE(current_range_start_, 0);
rvargas@google.com8bf26f49a2009-06-12 17:35:50101
102 // Scan the disk cache for the first cached portion within this range.
rvargas@google.com034740a2010-06-11 17:16:48103 int len = GetNextRangeLen();
rvargas@google.com8bf26f49a2009-06-12 17:35:50104 if (!len)
105 return 0;
rvargas@google.com8bf26f49a2009-06-12 17:35:50106
rvargas@google.coma5c9d982010-10-12 20:48:02107 DVLOG(3) << "ShouldValidateCache len: " << len;
108
rvargas@google.come5dad132009-08-18 00:53:41109 if (sparse_entry_) {
jhawkins@chromium.org49639fa2011-12-20 23:22:41110 DCHECK(callback_.is_null());
Maks Orlovich04cd1ad2021-07-02 17:32:24111 disk_cache::RangeResultCallback cb = base::BindOnce(
112 &PartialData::GetAvailableRangeCompleted, weak_factory_.GetWeakPtr());
113 disk_cache::RangeResult range =
114 entry->GetAvailableRange(current_range_start_, len, std::move(cb));
rvargas@google.com034740a2010-06-11 17:16:48115
Maks Orlovich04cd1ad2021-07-02 17:32:24116 cached_min_len_ =
117 range.net_error == OK ? range.available_len : range.net_error;
rvargas@google.com034740a2010-06-11 17:16:48118 if (cached_min_len_ == ERR_IO_PENDING) {
Bence Békya4a50932018-08-10 13:39:41119 callback_ = std::move(callback);
rvargas@google.com034740a2010-06-11 17:16:48120 return ERR_IO_PENDING;
hubbe6cad67c2015-07-09 19:01:02121 } else {
Maks Orlovich04cd1ad2021-07-02 17:32:24122 cached_start_ = range.start;
rvargas@google.com034740a2010-06-11 17:16:48123 }
rvargas@google.com634739b2011-03-02 18:08:25124 } else if (!truncated_) {
rvargas@google.coma5c9d982010-10-12 20:48:02125 if (byte_range_.HasFirstBytePosition() &&
126 byte_range_.first_byte_position() >= resource_size_) {
127 // The caller should take care of this condition because we should have
128 // failed IsRequestedRangeOK(), but it's better to be consistent here.
129 len = 0;
130 }
rvargas@google.come5dad132009-08-18 00:53:41131 cached_min_len_ = len;
132 cached_start_ = current_range_start_;
133 }
134
rvargas@google.com034740a2010-06-11 17:16:48135 if (cached_min_len_ < 0)
rvargas@google.com8bf26f49a2009-06-12 17:35:50136 return cached_min_len_;
rvargas@google.com034740a2010-06-11 17:16:48137
138 // Return a positive number to indicate success (versus error or finished).
139 return 1;
140}
141
142void PartialData::PrepareCacheValidation(disk_cache::Entry* entry,
143 HttpRequestHeaders* headers) {
144 DCHECK_GE(current_range_start_, 0);
145 DCHECK_GE(cached_min_len_, 0);
146
147 int len = GetNextRangeLen();
148 DCHECK_NE(0, len);
149 range_present_ = false;
rvargas@google.com8bf26f49a2009-06-12 17:35:50150
willchan@chromium.org8c76ae22010-04-20 22:15:43151 headers->CopyFrom(extra_headers_);
rvargas@google.com8bf26f49a2009-06-12 17:35:50152
153 if (!cached_min_len_) {
154 // We don't have anything else stored.
155 final_range_ = true;
rvargas@google.com28accfe2009-09-04 23:36:33156 cached_start_ =
157 byte_range_.HasLastBytePosition() ? current_range_start_ + len : 0;
rvargas@google.com8bf26f49a2009-06-12 17:35:50158 }
159
160 if (current_range_start_ == cached_start_) {
161 // The data lives in the cache.
162 range_present_ = true;
rvargas3b57e37a2015-01-06 00:56:34163 current_range_end_ = cached_start_ + cached_min_len_ - 1;
rvargas@google.com8bf26f49a2009-06-12 17:35:50164 if (len == cached_min_len_)
165 final_range_ = true;
rvargas@google.com8bf26f49a2009-06-12 17:35:50166 } else {
167 // This range is not in the cache.
rvargas3b57e37a2015-01-06 00:56:34168 current_range_end_ = cached_start_ - 1;
rvargas@google.com8bf26f49a2009-06-12 17:35:50169 }
hubbe70fbde6a2015-07-08 19:24:14170 headers->SetHeader(
171 HttpRequestHeaders::kRange,
172 HttpByteRange::Bounded(current_range_start_, current_range_end_)
173 .GetHeaderValue());
rvargas@google.com8bf26f49a2009-06-12 17:35:50174}
175
176bool PartialData::IsCurrentRangeCached() const {
177 return range_present_;
178}
179
180bool PartialData::IsLastRange() const {
181 return final_range_;
182}
183
rvargas@google.com44f873a62009-08-12 00:14:48184bool PartialData::UpdateFromStoredHeaders(const HttpResponseHeaders* headers,
rvargas@google.com28accfe2009-09-04 23:36:33185 disk_cache::Entry* entry,
Maks Orlovichd19c8272018-03-23 15:27:05186 bool truncated,
187 bool writing_in_progress) {
rvargas@google.com67fe45c2009-06-24 17:44:57188 resource_size_ = 0;
rvargas@google.com28accfe2009-09-04 23:36:33189 if (truncated) {
190 DCHECK_EQ(headers->response_code(), 200);
rvargas@google.com28accfe2009-09-04 23:36:33191 // We don't have the real length and the user may be trying to create a
192 // sparse entry so let's not write to this entry.
193 if (byte_range_.IsValid())
194 return false;
195
rvargas@google.com9f03cb7a2012-07-30 23:15:20196 if (!headers->HasStrongValidators())
197 return false;
198
rvargas@google.comdbd39fb2010-01-08 01:13:36199 // Now we avoid resume if there is no content length, but that was not
200 // always the case so double check here.
avid0181f32015-12-10 19:41:47201 int64_t total_length = headers->GetContentLength();
rvargas@google.combd069d72011-05-19 01:11:11202 if (total_length <= 0)
rvargas@google.comdbd39fb2010-01-08 01:13:36203 return false;
204
Maks Orlovich332bb11a2018-03-17 01:43:32205 // In case we see a truncated entry, we first send a network request for
206 // 1 byte range with If-Range: to probe server support for resumption.
207 // The setting of |current_range_start_| and |cached_start_| below (with any
208 // positive value of |cached_min_len_|) results in that.
209 //
210 // Setting |initial_validation_| to true is how this communicates to
211 // HttpCache::Transaction that we're doing that (and that it's not the user
212 // asking for one byte), so if it sees a 206 with that flag set it will call
213 // SetRangeToStartDownload(), and then restart the process looking for the
214 // entire file (which is what the user wanted), with the cache handling
215 // the previous portion, and then a second network request for the entire
216 // rest of the range. A 200 in response to the probe request can be simply
217 // returned directly to the user.
hclam@chromium.orgecd8becb2009-10-02 17:57:45218 truncated_ = true;
rvargas@google.com634739b2011-03-02 18:08:25219 initial_validation_ = true;
hclam@chromium.orgecd8becb2009-10-02 17:57:45220 sparse_entry_ = false;
rvargas@google.com634739b2011-03-02 18:08:25221 int current_len = entry->GetDataSize(kDataStream);
222 byte_range_.set_first_byte_position(current_len);
rvargas@google.comdbd39fb2010-01-08 01:13:36223 resource_size_ = total_length;
rvargas@google.com634739b2011-03-02 18:08:25224 current_range_start_ = current_len;
225 cached_min_len_ = current_len;
226 cached_start_ = current_len + 1;
rvargas@google.com28accfe2009-09-04 23:36:33227 return true;
228 }
229
Feifei Wanged3689f2022-05-29 23:35:38230 sparse_entry_ = (headers->response_code() == net::HTTP_PARTIAL_CONTENT);
Maks Orlovichd19c8272018-03-23 15:27:05231
232 if (writing_in_progress || sparse_entry_) {
233 // |writing_in_progress| means another Transaction is still fetching the
234 // body, so the only way we can see the length is if the server sent it
235 // in Content-Length -- GetDataSize would just return what got written
236 // thus far.
237 //
238 // |sparse_entry_| means a 206, and for those FixContentLength arranges it
239 // so that Content-Length written to the cache has the full length (on wire
240 // it's for a particular range only); while GetDataSize would be unusable
241 // since the data is stored using WriteSparseData, and not in the usual data
242 // stream.
243 resource_size_ = headers->GetContentLength();
244 if (resource_size_ <= 0)
245 return false;
246 } else {
247 // If we can safely use GetDataSize, it's preferrable since it's usable for
248 // things w/o Content-Length, such as chunked content.
rvargas@google.come5dad132009-08-18 00:53:41249 resource_size_ = entry->GetDataSize(kDataStream);
rvargas@google.come5dad132009-08-18 00:53:41250 }
251
Maks Orlovichd19c8272018-03-23 15:27:05252 DVLOG(2) << "UpdateFromStoredHeaders size: " << resource_size_;
rvargas43dc8fd2015-01-07 23:03:25253
Maks Orlovichd19c8272018-03-23 15:27:05254 if (sparse_entry_) {
255 // If our previous is a 206, we need strong validators as we may be
256 // stiching the cached data and network data together.
257 if (!headers->HasStrongValidators())
258 return false;
259 // Make sure that this is really a sparse entry.
260 return entry->CouldBeSparse();
261 }
262 return true;
rvargas@google.come5dad132009-08-18 00:53:41263}
264
rvargas@google.com634739b2011-03-02 18:08:25265void PartialData::SetRangeToStartDownload() {
266 DCHECK(truncated_);
267 DCHECK(!sparse_entry_);
268 current_range_start_ = 0;
269 cached_start_ = 0;
270 initial_validation_ = false;
271}
272
rvargas@google.come5dad132009-08-18 00:53:41273bool PartialData::IsRequestedRangeOK() {
rvargas@google.com44f873a62009-08-12 00:14:48274 if (byte_range_.IsValid()) {
275 if (!byte_range_.ComputeBounds(resource_size_))
276 return false;
rvargas@google.com634739b2011-03-02 18:08:25277 if (truncated_)
278 return true;
rvargas@google.com67fe45c2009-06-24 17:44:57279
rvargas@google.com44f873a62009-08-12 00:14:48280 if (current_range_start_ < 0)
281 current_range_start_ = byte_range_.first_byte_position();
282 } else {
283 // This is not a range request but we have partial data stored.
284 current_range_start_ = 0;
285 byte_range_.set_last_byte_position(resource_size_ - 1);
286 }
287
rvargas@google.come5dad132009-08-18 00:53:41288 bool rv = current_range_start_ >= 0;
289 if (!rv)
290 current_range_start_ = 0;
rvargas@google.com67fe45c2009-06-24 17:44:57291
rvargas@google.come5dad132009-08-18 00:53:41292 return rv;
rvargas@google.com95792eb12009-06-22 21:30:40293}
294
295bool PartialData::ResponseHeadersOK(const HttpResponseHeaders* headers) {
Feifei Wanged3689f2022-05-29 23:35:38296 if (headers->response_code() == net::HTTP_NOT_MODIFIED) {
hclam@chromium.orgd9adff2c2009-09-05 01:15:45297 if (!byte_range_.IsValid() || truncated_)
rvargas@google.com28accfe2009-09-04 23:36:33298 return true;
299
rvargas@google.come5dad132009-08-18 00:53:41300 // We must have a complete range here.
301 return byte_range_.HasFirstBytePosition() &&
cbentzel@chromium.org2227c692010-05-04 15:36:11302 byte_range_.HasLastBytePosition();
rvargas@google.come5dad132009-08-18 00:53:41303 }
304
avid0181f32015-12-10 19:41:47305 int64_t start, end, total_length;
sclittled43b2fb2016-12-17 03:20:47306 if (!headers->GetContentRangeFor206(&start, &end, &total_length))
rvargas@google.com95792eb12009-06-22 21:30:40307 return false;
308 if (total_length <= 0)
309 return false;
310
rvargas@chromium.org9f10ec32013-11-01 00:51:53311 DCHECK_EQ(headers->response_code(), 206);
312
313 // A server should return a valid content length with a 206 (per the standard)
314 // but relax the requirement because some servers don't do that.
avid0181f32015-12-10 19:41:47315 int64_t content_length = headers->GetContentLength();
rvargas@chromium.org9f10ec32013-11-01 00:51:53316 if (content_length > 0 && content_length != end - start + 1)
rvargas@google.com7eab0d2262009-10-14 22:05:54317 return false;
318
rvargas@google.com95792eb12009-06-22 21:30:40319 if (!resource_size_) {
320 // First response. Update our values with the ones provided by the server.
321 resource_size_ = total_length;
rvargas@google.com67fe45c2009-06-24 17:44:57322 if (!byte_range_.HasFirstBytePosition()) {
rvargas@google.com95792eb12009-06-22 21:30:40323 byte_range_.set_first_byte_position(start);
rvargas@google.com67fe45c2009-06-24 17:44:57324 current_range_start_ = start;
325 }
rvargas@google.com95792eb12009-06-22 21:30:40326 if (!byte_range_.HasLastBytePosition())
327 byte_range_.set_last_byte_position(end);
328 } else if (resource_size_ != total_length) {
329 return false;
330 }
331
rvargas@google.comdbd39fb2010-01-08 01:13:36332 if (truncated_) {
333 if (!byte_range_.HasLastBytePosition())
334 byte_range_.set_last_byte_position(end);
335 }
336
rvargas@google.com95792eb12009-06-22 21:30:40337 if (start != current_range_start_)
338 return false;
339
rvargas3b57e37a2015-01-06 00:56:34340 if (!current_range_end_) {
341 // There is nothing in the cache.
342 DCHECK(byte_range_.HasLastBytePosition());
343 current_range_end_ = byte_range_.last_byte_position();
344 if (current_range_end_ >= resource_size_) {
345 // We didn't know the real file size, and the server is saying that the
346 // requested range goes beyond the size. Fix it.
347 current_range_end_ = end;
348 byte_range_.set_last_byte_position(end);
349 }
350 }
351
352 // If we received a range, but it's not exactly the range we asked for, avoid
353 // trouble and signal an error.
354 if (end != current_range_end_)
rvargas@google.com95792eb12009-06-22 21:30:40355 return false;
356
357 return true;
358}
359
360// We are making multiple requests to complete the range requested by the user.
361// Just assume that everything is fine and say that we are returning what was
362// requested.
rvargas@google.coma5c9d982010-10-12 20:48:02363void PartialData::FixResponseHeaders(HttpResponseHeaders* headers,
364 bool success) {
rvargas@google.com28accfe2009-09-04 23:36:33365 if (truncated_)
366 return;
367
kinuko@chromium.org3d47dac9622014-03-10 07:28:58368 if (byte_range_.IsValid() && success) {
369 headers->UpdateWithNewRange(byte_range_, resource_size_, !sparse_entry_);
370 return;
371 }
372
rvargas@google.com44f873a62009-08-12 00:14:48373 if (byte_range_.IsValid()) {
kinuko@chromium.org3d47dac9622014-03-10 07:28:58374 headers->ReplaceStatusLine("HTTP/1.1 416 Requested Range Not Satisfiable");
Matt Menke73ed38f2020-04-10 21:29:11375 headers->SetHeader(
376 kRangeHeader, base::StringPrintf("bytes 0-0/%" PRId64, resource_size_));
377 headers->SetHeader(kLengthHeader, "0");
rvargas@google.com44f873a62009-08-12 00:14:48378 } else {
379 // TODO(rvargas): Is it safe to change the protocol version?
380 headers->ReplaceStatusLine("HTTP/1.1 200 OK");
381 DCHECK_NE(resource_size_, 0);
Matt Menke73ed38f2020-04-10 21:29:11382 headers->RemoveHeader(kRangeHeader);
383 headers->SetHeader(kLengthHeader,
384 base::StringPrintf("%" PRId64, resource_size_));
rvargas@google.com44f873a62009-08-12 00:14:48385 }
rvargas@google.com95792eb12009-06-22 21:30:40386}
387
388void PartialData::FixContentLength(HttpResponseHeaders* headers) {
Matt Menke73ed38f2020-04-10 21:29:11389 headers->SetHeader(kLengthHeader,
390 base::StringPrintf("%" PRId64, resource_size_));
rvargas@google.com95792eb12009-06-22 21:30:40391}
392
ttuttle859dc7a2015-04-23 19:42:29393int PartialData::CacheRead(disk_cache::Entry* entry,
394 IOBuffer* data,
395 int data_len,
Bence Békya4a50932018-08-10 13:39:41396 CompletionOnceCallback callback) {
rvargas@google.com8bf26f49a2009-06-12 17:35:50397 int read_len = std::min(data_len, cached_min_len_);
hclam@chromium.org8f28d632009-10-01 22:09:21398 if (!read_len)
399 return 0;
400
rvargas@google.come5dad132009-08-18 00:53:41401 int rv = 0;
402 if (sparse_entry_) {
403 rv = entry->ReadSparseData(current_range_start_, data, read_len,
Bence Békya4a50932018-08-10 13:39:41404 std::move(callback));
rvargas@google.come5dad132009-08-18 00:53:41405 } else {
avid0181f32015-12-10 19:41:47406 if (current_range_start_ > std::numeric_limits<int32_t>::max())
rvargas@google.come5dad132009-08-18 00:53:41407 return ERR_INVALID_ARGUMENT;
408
409 rv = entry->ReadData(kDataStream, static_cast<int>(current_range_start_),
Bence Békya4a50932018-08-10 13:39:41410 data, read_len, std::move(callback));
rvargas@google.come5dad132009-08-18 00:53:41411 }
rvargas@google.com8bf26f49a2009-06-12 17:35:50412 return rv;
413}
414
ttuttle859dc7a2015-04-23 19:42:29415int PartialData::CacheWrite(disk_cache::Entry* entry,
416 IOBuffer* data,
417 int data_len,
Bence Békya4a50932018-08-10 13:39:41418 CompletionOnceCallback callback) {
rvargas@google.coma5c9d982010-10-12 20:48:02419 DVLOG(3) << "To write: " << data_len;
rvargas@google.come5dad132009-08-18 00:53:41420 if (sparse_entry_) {
Bence Békya4a50932018-08-10 13:39:41421 return entry->WriteSparseData(current_range_start_, data, data_len,
422 std::move(callback));
rvargas@google.come5dad132009-08-18 00:53:41423 } else {
avid0181f32015-12-10 19:41:47424 if (current_range_start_ > std::numeric_limits<int32_t>::max())
rvargas@google.come5dad132009-08-18 00:53:41425 return ERR_INVALID_ARGUMENT;
426
427 return entry->WriteData(kDataStream, static_cast<int>(current_range_start_),
Bence Békya4a50932018-08-10 13:39:41428 data, data_len, std::move(callback), true);
rvargas@google.come5dad132009-08-18 00:53:41429 }
rvargas@google.com8bf26f49a2009-06-12 17:35:50430}
431
432void PartialData::OnCacheReadCompleted(int result) {
rvargas@google.coma5c9d982010-10-12 20:48:02433 DVLOG(3) << "Read: " << result;
rvargas@google.com8bf26f49a2009-06-12 17:35:50434 if (result > 0) {
435 current_range_start_ += result;
436 cached_min_len_ -= result;
rvargas@google.com034740a2010-06-11 17:16:48437 DCHECK_GE(cached_min_len_, 0);
rvargas@google.com8bf26f49a2009-06-12 17:35:50438 }
439}
440
441void PartialData::OnNetworkReadCompleted(int result) {
442 if (result > 0)
443 current_range_start_ += result;
444}
445
rvargas@google.com034740a2010-06-11 17:16:48446int PartialData::GetNextRangeLen() {
avid0181f32015-12-10 19:41:47447 int64_t range_len =
448 byte_range_.HasLastBytePosition()
449 ? byte_range_.last_byte_position() - current_range_start_ + 1
450 : std::numeric_limits<int32_t>::max();
451 if (range_len > std::numeric_limits<int32_t>::max())
452 range_len = std::numeric_limits<int32_t>::max();
453 return static_cast<int32_t>(range_len);
rvargas@google.com034740a2010-06-11 17:16:48454}
455
Maks Orlovich04cd1ad2021-07-02 17:32:24456void PartialData::GetAvailableRangeCompleted(
457 const disk_cache::RangeResult& result) {
jhawkins@chromium.org49639fa2011-12-20 23:22:41458 DCHECK(!callback_.is_null());
Maks Orlovich04cd1ad2021-07-02 17:32:24459 DCHECK_NE(ERR_IO_PENDING, result.net_error);
rvargas@google.com034740a2010-06-11 17:16:48460
Maks Orlovich04cd1ad2021-07-02 17:32:24461 int len_or_error =
462 result.net_error == OK ? result.available_len : result.net_error;
463 cached_start_ = result.start;
464 cached_min_len_ = len_or_error;
rvargas@google.com034740a2010-06-11 17:16:48465
Maks Orlovich04cd1ad2021-07-02 17:32:24466 // ShouldValidateCache has an unusual convention where 0 denotes EOF,
467 // so convert end of range to success (since there may be things that need
468 // fetching from network or other ranges).
469 std::move(callback_).Run(len_or_error >= 0 ? 1 : len_or_error);
rvargas@google.com034740a2010-06-11 17:16:48470}
471
rvargas@google.com8bf26f49a2009-06-12 17:35:50472} // namespace net