OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "media/blink/resource_multibuffer_data_provider.h" | 5 #include "media/blink/resource_multibuffer_data_provider.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 | 280 |
281 reasons >>= 1; | 281 reasons >>= 1; |
282 ++shift; | 282 ++shift; |
283 } | 283 } |
284 | 284 |
285 // Expected content length can be |kPositionNotSpecified|, in that case | 285 // Expected content length can be |kPositionNotSpecified|, in that case |
286 // |content_length_| is not specified and this is a streaming response. | 286 // |content_length_| is not specified and this is a streaming response. |
287 int64_t content_length = response.ExpectedContentLength(); | 287 int64_t content_length = response.ExpectedContentLength(); |
288 bool end_of_file = false; | 288 bool end_of_file = false; |
289 bool do_fail = false; | 289 bool do_fail = false; |
| 290 bytes_to_discard_ = 0; |
290 | 291 |
291 // We make a strong assumption that when we reach here we have either | 292 // We make a strong assumption that when we reach here we have either |
292 // received a response from HTTP/HTTPS protocol or the request was | 293 // received a response from HTTP/HTTPS protocol or the request was |
293 // successful (in particular range request). So we only verify the partial | 294 // successful (in particular range request). So we only verify the partial |
294 // response for HTTP and HTTPS protocol. | 295 // response for HTTP and HTTPS protocol. |
295 if (destination_url_data->url().SchemeIsHTTPOrHTTPS()) { | 296 if (destination_url_data->url().SchemeIsHTTPOrHTTPS()) { |
296 bool partial_response = (response.HttpStatusCode() == kHttpPartialContent); | 297 bool partial_response = (response.HttpStatusCode() == kHttpPartialContent); |
297 bool ok_response = (response.HttpStatusCode() == kHttpOK); | 298 bool ok_response = (response.HttpStatusCode() == kHttpOK); |
298 | 299 |
299 // Check to see whether the server supports byte ranges. | 300 // Check to see whether the server supports byte ranges. |
300 std::string accept_ranges = | 301 std::string accept_ranges = |
301 response.HttpHeaderField("Accept-Ranges").Utf8(); | 302 response.HttpHeaderField("Accept-Ranges").Utf8(); |
302 if (accept_ranges.find("bytes") != std::string::npos) | 303 if (accept_ranges.find("bytes") != std::string::npos) |
303 destination_url_data->set_range_supported(); | 304 destination_url_data->set_range_supported(); |
304 | 305 |
305 // If we have verified the partial response and it is correct. | 306 // If we have verified the partial response and it is correct. |
306 // It's also possible for a server to support range requests | 307 // It's also possible for a server to support range requests |
307 // without advertising "Accept-Ranges: bytes". | 308 // without advertising "Accept-Ranges: bytes". |
308 if (partial_response && | 309 if (partial_response && |
309 VerifyPartialResponse(response, destination_url_data)) { | 310 VerifyPartialResponse(response, destination_url_data)) { |
310 destination_url_data->set_range_supported(); | 311 destination_url_data->set_range_supported(); |
311 } else if (ok_response && pos_ == 0) { | 312 } else if (ok_response) { |
312 // We accept a 200 response for a Range:0- request, trusting the | 313 // We accept a 200 response for a Range:0- request, trusting the |
313 // Accept-Ranges header, because Apache thinks that's a reasonable thing | 314 // Accept-Ranges header, because Apache thinks that's a reasonable thing |
314 // to return. | 315 // to return. |
315 destination_url_data->set_length(content_length); | 316 destination_url_data->set_length(content_length); |
| 317 bytes_to_discard_ = byte_pos(); |
316 } else if (response.HttpStatusCode() == kHttpRangeNotSatisfiable) { | 318 } else if (response.HttpStatusCode() == kHttpRangeNotSatisfiable) { |
317 // Unsatisfiable range | 319 // Unsatisfiable range |
318 // Really, we should never request a range that doesn't exist, but | 320 // Really, we should never request a range that doesn't exist, but |
319 // if we do, let's handle it in a sane way. | 321 // if we do, let's handle it in a sane way. |
320 // Note, we can't just call OnDataProviderEvent() here, because | 322 // Note, we can't just call OnDataProviderEvent() here, because |
321 // url_data_ hasn't been updated to the final destination yet. | 323 // url_data_ hasn't been updated to the final destination yet. |
322 end_of_file = true; | 324 end_of_file = true; |
323 } else { | 325 } else { |
324 active_loader_ = nullptr; | 326 active_loader_ = nullptr; |
325 // Can't call fail until readers have been migrated to the new | 327 // Can't call fail until readers have been migrated to the new |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 } | 381 } |
380 } | 382 } |
381 | 383 |
382 void ResourceMultiBufferDataProvider::DidReceiveData(const char* data, | 384 void ResourceMultiBufferDataProvider::DidReceiveData(const char* data, |
383 int data_length) { | 385 int data_length) { |
384 DVLOG(1) << "didReceiveData: " << data_length << " bytes"; | 386 DVLOG(1) << "didReceiveData: " << data_length << " bytes"; |
385 DCHECK(!Available()); | 387 DCHECK(!Available()); |
386 DCHECK(active_loader_); | 388 DCHECK(active_loader_); |
387 DCHECK_GT(data_length, 0); | 389 DCHECK_GT(data_length, 0); |
388 | 390 |
| 391 if (bytes_to_discard_) { |
| 392 uint64_t tmp = std::min<uint64_t>(bytes_to_discard_, data_length); |
| 393 data_length -= tmp; |
| 394 data += tmp; |
| 395 bytes_to_discard_ -= tmp; |
| 396 if (data_length == 0) |
| 397 return; |
| 398 } |
| 399 |
389 // When we receive data, we allow more retries. | 400 // When we receive data, we allow more retries. |
390 retries_ = 0; | 401 retries_ = 0; |
391 | 402 |
392 while (data_length) { | 403 while (data_length) { |
393 if (fifo_.empty() || fifo_.back()->data_size() == block_size()) { | 404 if (fifo_.empty() || fifo_.back()->data_size() == block_size()) { |
394 fifo_.push_back(new DataBuffer(block_size())); | 405 fifo_.push_back(new DataBuffer(block_size())); |
395 fifo_.back()->set_data_size(0); | 406 fifo_.back()->set_data_size(0); |
396 } | 407 } |
397 int last_block_size = fifo_.back()->data_size(); | 408 int last_block_size = fifo_.back()->data_size(); |
398 int to_append = std::min<int>(data_length, block_size() - last_block_size); | 409 int to_append = std::min<int>(data_length, block_size() - last_block_size); |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
554 if (!ParseContentRange(response.HttpHeaderField("Content-Range").Utf8(), | 565 if (!ParseContentRange(response.HttpHeaderField("Content-Range").Utf8(), |
555 &first_byte_position, &last_byte_position, | 566 &first_byte_position, &last_byte_position, |
556 &instance_size)) { | 567 &instance_size)) { |
557 return false; | 568 return false; |
558 } | 569 } |
559 | 570 |
560 if (url_data_->length() == kPositionNotSpecified) { | 571 if (url_data_->length() == kPositionNotSpecified) { |
561 url_data->set_length(instance_size); | 572 url_data->set_length(instance_size); |
562 } | 573 } |
563 | 574 |
564 if (byte_pos() != first_byte_position) { | 575 if (first_byte_position > byte_pos()) { |
565 return false; | 576 return false; |
566 } | 577 } |
| 578 if (last_byte_position + 1 < byte_pos()) { |
| 579 return false; |
| 580 } |
| 581 bytes_to_discard_ = byte_pos() - first_byte_position; |
567 | 582 |
568 return true; | 583 return true; |
569 } | 584 } |
570 | 585 |
571 } // namespace media | 586 } // namespace media |
OLD | NEW |