1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "media/blink/buffered_resource_loader.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bits.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_helpers.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/media_log.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "media/blink/cache_util.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "net/http/http_byte_range.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_request_headers.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebString.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLError.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLResponse.h"
197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebKit.h"
207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebURLLoaderOptions.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebFrame;
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebString;
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebURLError;
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebURLLoader;
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebURLLoaderOptions;
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebURLRequest;
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebURLResponse;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace media {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kHttpOK = 200;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kHttpPartialContent = 206;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Define the number of bytes in a megabyte.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMegabyte = 1024 * 1024;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Minimum capacity of the buffer in forward or backward direction.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2MB is an arbitrary limit; it just seems to be "good enough" in practice.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMinBufferCapacity = 2 * kMegabyte;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum capacity of the buffer in forward or backward direction. This is
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// effectively the largest single read the code path can handle.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 20MB is an arbitrary limit; it just seems to be "good enough" in practice.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMaxBufferCapacity = 20 * kMegabyte;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum number of bytes outside the buffer we will wait for in order to
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// fulfill a read. If a read starts more than 2MB away from the data we
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// currently have in the buffer, we will not wait for buffer to reach the read's
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// location and will instead reset the request.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kForwardWaitThreshold = 2 * kMegabyte;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Computes the suggested backward and forward capacity for the buffer
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if one wants to play at |playback_rate| * the natural playback speed.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use a value of 0 for |bitrate| if it is unknown.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ComputeTargetBufferWindow(float playback_rate, int bitrate,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      int* out_backward_capacity,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      int* out_forward_capacity) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kDefaultBitrate = 200 * 1024 * 8;  // 200 Kbps.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kMaxBitrate = 20 * kMegabyte * 8;  // 20 Mbps.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const float kMaxPlaybackRate = 25.0;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kTargetSecondsBufferedAhead = 10;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kTargetSecondsBufferedBehind = 2;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use a default bit rate if unknown and clamp to prevent overflow.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bitrate <= 0)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bitrate = kDefaultBitrate;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitrate = std::min(bitrate, kMaxBitrate);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only scale the buffer window for playback rates greater than 1.0 in
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // magnitude and clamp to prevent overflow.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool backward_playback = false;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (playback_rate < 0.0f) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backward_playback = true;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    playback_rate *= -1.0f;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  playback_rate = std::max(playback_rate, 1.0f);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  playback_rate = std::min(playback_rate, kMaxPlaybackRate);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bytes_per_second = (bitrate / 8.0) * playback_rate;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clamp between kMinBufferCapacity and kMaxBufferCapacity.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *out_forward_capacity = std::max(
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kTargetSecondsBufferedAhead * bytes_per_second, kMinBufferCapacity);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *out_backward_capacity = std::max(
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kTargetSecondsBufferedBehind * bytes_per_second, kMinBufferCapacity);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *out_forward_capacity = std::min(*out_forward_capacity, kMaxBufferCapacity);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *out_backward_capacity = std::min(*out_backward_capacity, kMaxBufferCapacity);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (backward_playback)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::swap(*out_forward_capacity, *out_backward_capacity);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BufferedResourceLoader::BufferedResourceLoader(
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CORSMode cors_mode,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 first_byte_position,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 last_byte_position,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeferStrategy strategy,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int bitrate,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float playback_rate,
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    MediaLog* media_log)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : buffer_(kMinBufferCapacity, kMinBufferCapacity),
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      loader_failed_(false),
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      defer_strategy_(strategy),
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      might_be_reused_from_cache_in_future_(true),
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      range_supported_(false),
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      saved_forward_capacity_(0),
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url_(url),
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cors_mode_(cors_mode),
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      first_byte_position_(first_byte_position),
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_byte_position_(last_byte_position),
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      single_origin_(true),
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      offset_(0),
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_length_(kPositionNotSpecified),
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_size_(kPositionNotSpecified),
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_position_(0),
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_size_(0),
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_buffer_(NULL),
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      first_offset_(0),
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_offset_(0),
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bitrate_(bitrate),
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      playback_rate_(playback_rate),
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      media_log_(media_log) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the initial capacity of |buffer_| based on |bitrate_| and
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |playback_rate_|.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateBufferWindow();
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BufferedResourceLoader::~BufferedResourceLoader() {}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::Start(
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const StartCB& start_cb,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const LoadingStateChangedCB& loading_cb,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProgressCB& progress_cb,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebFrame* frame) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure we have not started.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(start_cb_.is_null());
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(loading_cb_.is_null());
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(progress_cb_.is_null());
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!start_cb.is_null());
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!loading_cb.is_null());
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!progress_cb.is_null());
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(frame);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  start_cb_ = start_cb;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loading_cb_ = loading_cb;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  progress_cb_ = progress_cb;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (first_byte_position_ != kPositionNotSpecified) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(hclam): server may not support range request so |offset_| may not
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // equal to |first_byte_position_|.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offset_ = first_byte_position_;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prepare the request.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebURLRequest request(url_);
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // TODO(mkwst): Split this into video/audio.
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  request.setRequestContext(WebURLRequest::RequestContextVideo);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsRangeRequest()) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request.setHTTPHeaderField(
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WebString::fromUTF8(net::HttpRequestHeaders::kRange),
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        WebString::fromUTF8(net::HttpByteRange::Bounded(
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            first_byte_position_, last_byte_position_).GetHeaderValue()));
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  frame->setReferrerForRequest(request, blink::WebURL());
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Disable compression, compression for audio/video doesn't make sense...
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.setHTTPHeaderField(
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebString::fromUTF8(net::HttpRequestHeaders::kAcceptEncoding),
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebString::fromUTF8("identity;q=1, *;q=0"));
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check for our test WebURLLoader.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WebURLLoader> loader;
181b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (test_loader_) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loader = test_loader_.Pass();
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebURLLoaderOptions options;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cors_mode_ == kUnspecified) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      options.allowCredentials = true;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      options.crossOriginRequestPolicy =
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          WebURLLoaderOptions::CrossOriginRequestPolicyAllow;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      options.exposeAllResponseHeaders = true;
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // The author header set is empty, no preflight should go ahead.
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      options.preflightPolicy = WebURLLoaderOptions::PreventPreflight;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      options.crossOriginRequestPolicy =
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (cors_mode_ == kUseCredentials)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        options.allowCredentials = true;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loader.reset(frame->createAssociatedURLLoader(options));
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start the resource loading.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loader->loadAsynchronously(request, this);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  active_loader_.reset(new ActiveLoader(loader.Pass()));
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loading_cb_.Run(kLoading);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::Stop() {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset callbacks.
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  start_cb_.Reset();
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loading_cb_.Reset();
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  progress_cb_.Reset();
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_cb_.Reset();
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel and reset any active loaders.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  active_loader_.reset();
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::Read(
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 position,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int read_size,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8* buffer,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ReadCB& read_cb) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(start_cb_.is_null());
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(read_cb_.is_null());
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!read_cb.is_null());
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(buffer);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(read_size, 0);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Save the parameter of reading.
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_cb_ = read_cb;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_position_ = position;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_size_ = read_size;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buffer_ = buffer;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reads should immediately fail if the loader also failed.
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (loader_failed_) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneRead(kFailed, 0);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we're attempting to read past the end of the file, return a zero
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // indicating EOF.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This can happen with callees that read in fixed-sized amounts for parsing
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // or at the end of chunked 200 responses when we discover the actual length
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the file.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (instance_size_ != kPositionNotSpecified &&
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_size_ <= read_position_) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "Appear to have seeked beyond EOS; returning 0.";
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneRead(kOk, 0);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure |offset_| and |read_position_| does not differ by a large
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // amount.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (read_position_ > offset_ + kint32max ||
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_position_ < offset_ + kint32min) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneRead(kCacheMiss, 0);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure |read_size_| is not too large for the buffer to ever be able to
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fulfill the read request.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (read_size_ > kMaxBufferCapacity) {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneRead(kFailed, 0);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prepare the parameters.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  first_offset_ = read_position_ - offset_;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_offset_ = first_offset_ + read_size_;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we can serve the request now, do the actual read.
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CanFulfillRead()) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReadInternal();
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateDeferBehavior();
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we expect the read request to be fulfilled later, expand capacity as
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // necessary and disable deferring.
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (WillFulfillRead()) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Advance offset as much as possible to create additional capacity.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int advance = std::min(first_offset_, buffer_.forward_bytes());
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool ret = buffer_.Seek(advance);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(ret);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offset_ += advance;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    first_offset_ -= advance;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_offset_ -= advance;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Expand capacity to accomodate a read that extends past the normal
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // capacity.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This can happen when reading in a large seek index or when the
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // first byte of a read request falls within kForwardWaitThreshold.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (last_offset_ > buffer_.forward_capacity()) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      saved_forward_capacity_ = buffer_.forward_capacity();
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buffer_.set_forward_capacity(last_offset_);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure we stop deferring now that there's additional capacity.
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!ShouldDefer())
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Capacity was not adjusted properly to prevent deferring.";
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateDeferBehavior();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make a callback to report failure.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoneRead(kCacheMiss, 0);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 BufferedResourceLoader::content_length() {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return content_length_;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 BufferedResourceLoader::instance_size() {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return instance_size_;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceLoader::range_supported() {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return range_supported_;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// blink::WebURLLoaderClient implementation.
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::willSendRequest(
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebURLLoader* loader,
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebURLRequest& newRequest,
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WebURLResponse& redirectResponse) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The load may have been stopped and |start_cb| is destroyed.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In this case we shouldn't do anything.
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (start_cb_.is_null()) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set the url in the request to an invalid value (empty url).
337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    newRequest.setURL(blink::WebURL());
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only allow |single_origin_| if we haven't seen a different origin yet.
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (single_origin_)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    single_origin_ = url_.GetOrigin() == GURL(newRequest.url()).GetOrigin();
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_ = newRequest.url();
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::didSendData(
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebURLLoader* loader,
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned long long bytes_sent,
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned long long total_bytes_to_be_sent) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::didReceiveResponse(
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebURLLoader* loader,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WebURLResponse& response) {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "didReceiveResponse: HTTP/"
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << (response.httpVersion() == WebURLResponse::HTTP_0_9 ? "0.9" :
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               response.httpVersion() == WebURLResponse::HTTP_1_0 ? "1.0" :
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               response.httpVersion() == WebURLResponse::HTTP_1_1 ? "1.1" :
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "Unknown")
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << " " << response.httpStatusCode();
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(active_loader_.get());
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The loader may have been stopped and |start_cb| is destroyed.
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In this case we shouldn't do anything.
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (start_cb_.is_null())
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 reasons = GetReasonsForUncacheability(response);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  might_be_reused_from_cache_in_future_ = reasons == 0;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN("Media.CacheUseful", reasons == 0);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int shift = 0;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int max_enum = base::bits::Log2Ceiling(kMaxReason);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (reasons) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LT(shift, max_enum);  // Sanity check.
3781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (reasons & 0x1) {
3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      UMA_HISTOGRAM_ENUMERATION("Media.UncacheableReason",
3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                shift,
3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                max_enum); // PRESUBMIT_IGNORE_UMA_MAX
3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reasons >>= 1;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++shift;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Expected content length can be |kPositionNotSpecified|, in that case
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |content_length_| is not specified and this is a streaming response.
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content_length_ = response.expectedContentLength();
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We make a strong assumption that when we reach here we have either
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // received a response from HTTP/HTTPS protocol or the request was
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // successful (in particular range request). So we only verify the partial
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // response for HTTP and HTTPS protocol.
396f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (url_.SchemeIsHTTPOrHTTPS()) {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool partial_response = (response.httpStatusCode() == kHttpPartialContent);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool ok_response = (response.httpStatusCode() == kHttpOK);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsRangeRequest()) {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Check to see whether the server supports byte ranges.
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string accept_ranges =
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response.httpHeaderField("Accept-Ranges").utf8();
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      range_supported_ = (accept_ranges.find("bytes") != std::string::npos);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If we have verified the partial response and it is correct, we will
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // return kOk. It's also possible for a server to support range requests
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // without advertising "Accept-Ranges: bytes".
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (partial_response && VerifyPartialResponse(response)) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        range_supported_ = true;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (ok_response && first_byte_position_ == 0 &&
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 last_byte_position_ == kPositionNotSpecified) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We accept a 200 response for a Range:0- request, trusting the
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Accept-Ranges header, because Apache thinks that's a reasonable thing
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // to return.
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        instance_size_ = content_length_;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DoneStart(kFailed);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_size_ = content_length_;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (response.httpStatusCode() != kHttpOK) {
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We didn't request a range but server didn't reply with "200 OK".
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DoneStart(kFailed);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_EQ(instance_size_, kPositionNotSpecified);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (content_length_ != kPositionNotSpecified) {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (first_byte_position_ == kPositionNotSpecified)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        instance_size_ = content_length_;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (last_byte_position_ == kPositionNotSpecified)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        instance_size_ = content_length_ + first_byte_position_;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Calls with a successful response.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoneStart(kOk);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::didReceiveData(
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebURLLoader* loader,
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* data,
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int data_length,
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int encoded_data_length) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "didReceiveData: " << data_length << " bytes";
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(active_loader_.get());
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(data_length, 0);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_.Append(reinterpret_cast<const uint8*>(data), data_length);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there is an active read request, try to fulfill the request.
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasPendingRead() && CanFulfillRead())
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReadInternal();
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // At last see if the buffer is full and we need to defer the downloading.
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateDeferBehavior();
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consume excess bytes from our in-memory buffer if necessary.
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buffer_.forward_bytes() > buffer_.forward_capacity()) {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int excess = buffer_.forward_bytes() - buffer_.forward_capacity();
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success = buffer_.Seek(excess);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(success);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offset_ += first_offset_ + excess;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notify latest progress and buffered offset.
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  progress_cb_.Run(offset_ + buffer_.forward_bytes() - 1);
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Log();
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::didDownloadData(
476f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    blink::WebURLLoader* loader,
47758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    int dataLength,
47858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    int encoded_data_length) {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::didReceiveCachedMetadata(
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebURLLoader* loader,
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* data,
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int data_length) {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::didFinishLoading(
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebURLLoader* loader,
4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    double finishTime,
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int64_t total_encoded_data_length) {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "didFinishLoading";
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(active_loader_.get());
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We're done with the loader.
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  active_loader_.reset();
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loading_cb_.Run(kLoadingFinished);
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we didn't know the |instance_size_| we do now.
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (instance_size_ == kPositionNotSpecified) {
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    instance_size_ = offset_ + buffer_.forward_bytes();
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there is a start callback, run it.
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!start_cb_.is_null()) {
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(read_cb_.is_null())
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Shouldn't have a read callback during start";
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneStart(kOk);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't leave read callbacks hanging around.
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasPendingRead()) {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Try to fulfill with what is in the buffer.
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (CanFulfillRead())
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReadInternal();
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DoneRead(kCacheMiss, 0);
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::didFail(
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebURLLoader* loader,
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WebURLError& error) {
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "didFail: reason=" << error.reason
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << ", isCancellation=" << error.isCancellation
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << ", domain=" << error.domain.utf8().data()
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << ", localizedDescription="
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << error.localizedDescription.utf8().data();
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(active_loader_.get());
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't need to continue loading after failure.
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Keep it alive until we exit this method so that |error| remains valid.
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ActiveLoader> active_loader = active_loader_.Pass();
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loader_failed_ = true;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loading_cb_.Run(kLoadingFailed);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't leave start callbacks hanging around.
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!start_cb_.is_null()) {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(read_cb_.is_null())
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Shouldn't have a read callback during start";
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneStart(kFailed);
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't leave read callbacks hanging around.
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasPendingRead()) {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneRead(kFailed, 0);
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceLoader::HasSingleOrigin() const {
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(start_cb_.is_null())
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Start() must complete before calling HasSingleOrigin()";
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return single_origin_;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceLoader::DidPassCORSAccessCheck() const {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(start_cb_.is_null())
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Start() must complete before calling DidPassCORSAccessCheck()";
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !loader_failed_ && cors_mode_ != kUnspecified;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::UpdateDeferStrategy(DeferStrategy strategy) {
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!might_be_reused_from_cache_in_future_ && strategy == kNeverDefer)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strategy = kCapacityDefer;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  defer_strategy_ = strategy;
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateDeferBehavior();
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::SetPlaybackRate(float playback_rate) {
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  playback_rate_ = playback_rate;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is a pause so don't bother updating the buffer window as we'll likely
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // get unpaused in the future.
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (playback_rate_ == 0.0)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateBufferWindow();
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::SetBitrate(int bitrate) {
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(bitrate >= 0);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitrate_ = bitrate;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateBufferWindow();
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper methods.
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::UpdateBufferWindow() {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int backward_capacity;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int forward_capacity;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ComputeTargetBufferWindow(
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      playback_rate_, bitrate_, &backward_capacity, &forward_capacity);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This does not evict data from the buffer if the new capacities are less
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // than the current capacities; the new limits will be enforced after the
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // existing excess buffered data is consumed.
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_.set_backward_capacity(backward_capacity);
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_.set_forward_capacity(forward_capacity);
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::UpdateDeferBehavior() {
607b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!active_loader_)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetDeferred(ShouldDefer());
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::SetDeferred(bool deferred) {
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (active_loader_->deferred() == deferred)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  active_loader_->SetDeferred(deferred);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loading_cb_.Run(deferred ? kLoadingDeferred : kLoading);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceLoader::ShouldDefer() const {
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch(defer_strategy_) {
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kNeverDefer:
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kReadThenDefer:
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(read_cb_.is_null() || last_offset_ > buffer_.forward_bytes())
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "We shouldn't stop deferring if we can fulfill the read";
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return read_cb_.is_null();
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kCapacityDefer:
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return buffer_.forward_bytes() >= buffer_.forward_capacity();
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceLoader::CanFulfillRead() const {
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we are reading too far in the backward direction.
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (first_offset_ < 0 && (first_offset_ + buffer_.backward_bytes()) < 0)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the start offset is too far ahead.
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (first_offset_ >= buffer_.forward_bytes())
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // At the point, we verified that first byte requested is within the buffer.
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the request has completed, then just returns with what we have now.
649b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!active_loader_)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the resource request is still active, make sure the whole requested
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // range is covered.
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_offset_ > buffer_.forward_bytes())
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceLoader::WillFulfillRead() const {
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trying to read too far behind.
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (first_offset_ < 0 && (first_offset_ + buffer_.backward_bytes()) < 0)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trying to read too far ahead.
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((first_offset_ - buffer_.forward_bytes()) >= kForwardWaitThreshold)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The resource request has completed, there's no way we can fulfill the
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // read request.
671b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!active_loader_)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::ReadInternal() {
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Seek to the first byte requested.
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ret = buffer_.Seek(first_offset_);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ret);
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Then do the read.
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int read = buffer_.Read(read_buffer_, read_size_);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  offset_ += first_offset_ + read;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // And report with what we have read.
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoneRead(kOk, read);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 BufferedResourceLoader::first_byte_position() const {
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return first_byte_position_;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceLoader::ParseContentRange(
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& content_range_str, int64* first_byte_position,
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64* last_byte_position, int64* instance_size) {
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kUpThroughBytesUnit = "bytes ";
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (content_range_str.find(kUpThroughBytesUnit) != 0)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string range_spec =
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_range_str.substr(kUpThroughBytesUnit.length());
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t dash_offset = range_spec.find("-");
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t slash_offset = range_spec.find("/");
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dash_offset == std::string::npos || slash_offset == std::string::npos ||
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      slash_offset < dash_offset || slash_offset + 1 == range_spec.length()) {
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!base::StringToInt64(range_spec.substr(0, dash_offset),
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           first_byte_position) ||
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !base::StringToInt64(range_spec.substr(dash_offset + 1,
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             slash_offset - dash_offset - 1),
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           last_byte_position)) {
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (slash_offset == range_spec.length() - 2 &&
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      range_spec[slash_offset + 1] == '*') {
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *instance_size = kPositionNotSpecified;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!base::StringToInt64(range_spec.substr(slash_offset + 1),
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             instance_size)) {
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*last_byte_position < *first_byte_position ||
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (*instance_size != kPositionNotSpecified &&
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *last_byte_position >= *instance_size)) {
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceLoader::VerifyPartialResponse(
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WebURLResponse& response) {
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 first_byte_position, last_byte_position, instance_size;
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ParseContentRange(response.httpHeaderField("Content-Range").utf8(),
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         &first_byte_position, &last_byte_position,
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         &instance_size)) {
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (instance_size != kPositionNotSpecified) {
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    instance_size_ = instance_size;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (first_byte_position_ != kPositionNotSpecified &&
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      first_byte_position_ != first_byte_position) {
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(hclam): I should also check |last_byte_position|, but since
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we will never make such a request that it is ok to leave it unimplemented.
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::DoneRead(Status status, int bytes_read) {
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (saved_forward_capacity_) {
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_.set_forward_capacity(saved_forward_capacity_);
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    saved_forward_capacity_ = 0;
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_position_ = 0;
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_size_ = 0;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buffer_ = NULL;
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  first_offset_ = 0;
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_offset_ = 0;
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Log();
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ResetAndReturn(&read_cb_).Run(status, bytes_read);
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::DoneStart(Status status) {
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ResetAndReturn(&start_cb_).Run(status);
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceLoader::IsRangeRequest() const {
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return first_byte_position_ != kPositionNotSpecified;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceLoader::Log() {
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media_log_->AddEvent(
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      media_log_->CreateBufferedExtentsChangedEvent(
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          offset_ - buffer_.backward_bytes(),
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          offset_,
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          offset_ + buffer_.forward_bytes()));
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace media
791