15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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 "storage/browser/blob/blob_url_request_job.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <algorithm>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <limits>
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <string>
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <vector>
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_util_proxy.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/format_macros.h"
17ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/numerics/safe_conversions.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/stringprintf.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_request_headers.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_info.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_util.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_error_job.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_status.h"
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/blob/file_stream_reader.h"
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_context.h"
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_url.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace storage {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsFileType(BlobData::Item::Type type) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BlobData::Item::TYPE_FILE:
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BlobData::Item::TYPE_FILE_FILESYSTEM:
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BlobURLRequestJob::BlobURLRequestJob(
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::NetworkDelegate* network_delegate,
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<BlobData>& blob_data,
5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    storage::FileSystemContext* file_system_context,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::MessageLoopProxy* file_thread_proxy)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : net::URLRequestJob(request, network_delegate),
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blob_data_(blob_data),
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      file_system_context_(file_system_context),
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      file_thread_proxy_(file_thread_proxy),
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      total_size_(0),
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      remaining_bytes_(0),
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_get_file_info_count_(0),
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      current_item_index_(0),
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      current_item_offset_(0),
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_(false),
694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      byte_range_set_(false),
704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      weak_factory_(this) {
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(file_thread_proxy_.get());
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlobURLRequestJob::Start() {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Continue asynchronously.
76b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BlobURLRequestJob::DidStart, weak_factory_.GetWeakPtr()));
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlobURLRequestJob::Kill() {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeleteCurrentFileReader();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::URLRequestJob::Kill();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_factory_.InvalidateWeakPtrs();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BlobURLRequestJob::ReadRawData(net::IOBuffer* dest,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int dest_size,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int* bytes_read) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(dest_size, 0);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(bytes_read);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(remaining_bytes_, 0);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Bail out immediately if we encounter an error.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error_) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *bytes_read = 0;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (remaining_bytes_ < dest_size)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dest_size = static_cast<int>(remaining_bytes_);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we should copy zero bytes because |remaining_bytes_| is zero, short
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // circuit here.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dest_size) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *bytes_read = 0;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Keep track of the buffer.
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!read_buf_.get());
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buf_ = new net::DrainableIOBuffer(dest, dest_size);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ReadLoop(bytes_read);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BlobURLRequestJob::GetMimeType(std::string* mime_type) const {
119b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!response_info_)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return response_info_->headers->GetMimeType(mime_type);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlobURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
126b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (response_info_)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *info = *response_info_;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BlobURLRequestJob::GetResponseCode() const {
131b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!response_info_)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return response_info_->headers->response_code();
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlobURLRequestJob::SetExtraRequestHeaders(
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::HttpRequestHeaders& headers) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string range_header;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We only care about "Range" header here.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<net::HttpByteRange> ranges;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ranges.size() == 1) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        byte_range_set_ = true;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        byte_range_ = ranges[0];
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We don't support multiple range requests in one single URL request,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // because we need to do multipart encoding here.
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(jianli): Support multipart byte range requests.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BlobURLRequestJob::~BlobURLRequestJob() {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteValues(&index_to_reader_);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlobURLRequestJob::DidStart() {
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error_ = false;
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We only support GET request per the spec.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request()->method() != "GET") {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the blob data is not present, bail out.
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!blob_data_.get()) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyFailure(net::ERR_FILE_NOT_FOUND);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CountSize();
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BlobURLRequestJob::AddItemLength(size_t index, int64 item_length) {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (item_length > kint64max - total_size_) {
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotifyFailure(net::ERR_FAILED);
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Cache the size and add it to the total size.
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_LT(index, item_length_list_.size());
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  item_length_list_[index] = item_length;
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  total_size_ += item_length;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlobURLRequestJob::CountSize() {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_get_file_info_count_ = 0;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  total_size_ = 0;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  item_length_list_.resize(blob_data_->items().size());
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < blob_data_->items().size(); ++i) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BlobData::Item& item = blob_data_->items().at(i);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsFileType(item.type())) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++pending_get_file_info_count_;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetFileStreamReader(i)->GetLength(
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&BlobURLRequestJob::DidGetFileItemLength,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     weak_factory_.GetWeakPtr(), i));
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!AddItemLength(i, item.length()))
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_get_file_info_count_ == 0)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DidCountSize(net::OK);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlobURLRequestJob::DidCountSize(int error) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!error_);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If an error occured, bail out.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error != net::OK) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyFailure(error);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Apply the range requirement.
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!byte_range_.ComputeBounds(total_size_)) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  remaining_bytes_ = base::checked_cast<int64>(
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      byte_range_.last_byte_position() - byte_range_.first_byte_position() + 1);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(remaining_bytes_, 0);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do the seek at the beginning of the request.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (byte_range_.first_byte_position())
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Seek(byte_range_.first_byte_position());
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifySuccess();
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlobURLRequestJob::DidGetFileItemLength(size_t index, int64 result) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do nothing if we have encountered an error.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error_)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == net::ERR_UPLOAD_FILE_CHANGED) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyFailure(net::ERR_FILE_NOT_FOUND);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (result < 0) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyFailure(result);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LT(index, blob_data_->items().size());
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BlobData::Item& item = blob_data_->items().at(index);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsFileType(item.type()));
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint64 file_length = result;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint64 item_offset = item.offset();
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint64 item_length = item.length();
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (item_offset > file_length) {
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotifyFailure(net::ERR_FILE_NOT_FOUND);
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint64 max_length = file_length - item_offset;
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // If item length is undefined, then we need to use the file size being
2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // resolved in the real time.
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (item_length == std::numeric_limits<uint64>::max()) {
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    item_length = max_length;
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (item_length > max_length) {
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotifyFailure(net::ERR_FILE_NOT_FOUND);
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!AddItemLength(index, item_length))
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (--pending_get_file_info_count_ == 0)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DidCountSize(net::OK);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlobURLRequestJob::Seek(int64 offset) {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Skip the initial items that are not in the range.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (current_item_index_ = 0;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       current_item_index_ < blob_data_->items().size() &&
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           offset >= item_length_list_[current_item_index_];
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++current_item_index_) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offset -= item_length_list_[current_item_index_];
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the offset that need to jump to for the first item in the range.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_item_offset_ = offset;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (offset == 0)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adjust the offset of the first stream if it is of file type.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BlobData::Item& item = blob_data_->items().at(current_item_index_);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsFileType(item.type())) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeleteCurrentFileReader();
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateFileStreamReader(current_item_index_, offset);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BlobURLRequestJob::ReadItem() {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Are we done with reading all the blob data?
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (remaining_bytes_ == 0)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we get to the last item but still expect something to read, bail out
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // since something is wrong.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_item_index_ >= blob_data_->items().size()) {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyFailure(net::ERR_FAILED);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Compute the bytes to read for current item.
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bytes_to_read = ComputeBytesToRead();
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If nothing to read for current item, advance to next item.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bytes_to_read == 0) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AdvanceItem();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ReadItem();
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do the reading.
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BlobData::Item& item = blob_data_->items().at(current_item_index_);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (item.type() == BlobData::Item::TYPE_BYTES)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ReadBytesItem(item, bytes_to_read);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsFileType(item.type())) {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ReadFileItem(GetFileStreamReader(current_item_index_),
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        bytes_to_read);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlobURLRequestJob::AdvanceItem() {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close the file if the current item is a file.
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeleteCurrentFileReader();
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Advance to the next item.
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_item_index_++;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_item_offset_ = 0;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlobURLRequestJob::AdvanceBytesRead(int result) {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(result, 0);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do we finish reading the current item?
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_item_offset_ += result;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_item_offset_ == item_length_list_[current_item_index_])
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AdvanceItem();
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Subtract the remaining bytes.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remaining_bytes_ -= result;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(remaining_bytes_, 0);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adjust the read buffer.
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buf_->DidConsume(result);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(read_buf_->BytesRemaining(), 0);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BlobURLRequestJob::ReadBytesItem(const BlobData::Item& item,
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      int bytes_to_read) {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(read_buf_->data(),
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         item.bytes() + item.offset() + current_item_offset_,
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         bytes_to_read);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AdvanceBytesRead(bytes_to_read);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BlobURLRequestJob::ReadFileItem(FileStreamReader* reader,
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     int bytes_to_read) {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(reader);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int result = reader->Read(
384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      read_buf_.get(),
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      bytes_to_read,
386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Bind(&BlobURLRequestJob::DidReadFile, base::Unretained(this)));
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result >= 0) {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Data is immediately available.
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (GetStatus().is_io_pending())
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DidReadFile(result);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AdvanceBytesRead(result);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == net::ERR_IO_PENDING)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyFailure(result);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlobURLRequestJob::DidReadFile(int result) {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result <= 0) {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyFailure(net::ERR_FAILED);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStatus(net::URLRequestStatus());  // Clear the IO_PENDING status
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AdvanceBytesRead(result);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the read buffer is completely filled, we're done.
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!read_buf_->BytesRemaining()) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int bytes_read = BytesReadCompleted();
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyReadComplete(bytes_read);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise, continue the reading.
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bytes_read = 0;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ReadLoop(&bytes_read))
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyReadComplete(bytes_read);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlobURLRequestJob::DeleteCurrentFileReader() {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IndexToReaderMap::iterator found = index_to_reader_.find(current_item_index_);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found != index_to_reader_.end() && found->second) {
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete found->second;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    index_to_reader_.erase(found);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BlobURLRequestJob::BytesReadCompleted() {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bytes_read = read_buf_->BytesConsumed();
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buf_ = NULL;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bytes_read;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BlobURLRequestJob::ComputeBytesToRead() const {
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 current_item_length = item_length_list_[current_item_index_];
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 item_remaining = current_item_length - current_item_offset_;
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 buf_remaining = read_buf_->BytesRemaining();
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 max_remaining = std::numeric_limits<int>::max();
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 min = std::min(std::min(std::min(item_remaining,
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         buf_remaining),
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         remaining_bytes_),
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         max_remaining);
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return static_cast<int>(min);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BlobURLRequestJob::ReadLoop(int* bytes_read) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read until we encounter an error or could not get the data immediately.
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (remaining_bytes_ > 0 && read_buf_->BytesRemaining() > 0) {
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ReadItem())
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *bytes_read = BytesReadCompleted();
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlobURLRequestJob::NotifySuccess() {
465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  net::HttpStatusCode status_code = net::HTTP_OK;
466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (byte_range_set_ && byte_range_.IsValid())
467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    status_code = net::HTTP_PARTIAL_CONTENT;
468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  HeadersCompleted(status_code);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlobURLRequestJob::NotifyFailure(int error_code) {
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  error_ = true;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we already return the headers on success, we can't change the headers
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // now. Instead, we just error out.
476868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (response_info_) {
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     error_code));
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  net::HttpStatusCode status_code = net::HTTP_INTERNAL_SERVER_ERROR;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (error_code) {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case net::ERR_ACCESS_DENIED:
485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      status_code = net::HTTP_FORBIDDEN;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case net::ERR_FILE_NOT_FOUND:
488868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      status_code = net::HTTP_NOT_FOUND;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case net::ERR_METHOD_NOT_SUPPORTED:
491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      status_code = net::HTTP_METHOD_NOT_ALLOWED;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case net::ERR_REQUEST_RANGE_NOT_SATISFIABLE:
494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      status_code = net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case net::ERR_FAILED:
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(false);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
502868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  HeadersCompleted(status_code);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void BlobURLRequestJob::HeadersCompleted(net::HttpStatusCode status_code) {
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string status("HTTP/1.1 ");
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  status.append(base::IntToString(status_code));
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  status.append(" ");
509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  status.append(net::GetHttpReasonPhrase(status_code));
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  status.append("\0\0", 2);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (status_code == net::HTTP_OK || status_code == net::HTTP_PARTIAL_CONTENT) {
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string content_length_header(net::HttpRequestHeaders::kContentLength);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content_length_header.append(": ");
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content_length_header.append(base::Int64ToString(remaining_bytes_));
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headers->AddHeader(content_length_header);
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (status_code == net::HTTP_PARTIAL_CONTENT) {
5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK(byte_range_set_);
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK(byte_range_.IsValid());
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::string content_range_header(net::HttpResponseHeaders::kContentRange);
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      content_range_header.append(": bytes ");
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      content_range_header.append(base::StringPrintf(
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          "%" PRId64 "-%" PRId64,
5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          byte_range_.first_byte_position(), byte_range_.last_byte_position()));
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      content_range_header.append("/");
5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      content_range_header.append(base::StringPrintf("%" PRId64, total_size_));
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      headers->AddHeader(content_range_header);
5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!blob_data_->content_type().empty()) {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string content_type_header(net::HttpRequestHeaders::kContentType);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_type_header.append(": ");
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_type_header.append(blob_data_->content_type());
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers->AddHeader(content_type_header);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!blob_data_->content_disposition().empty()) {
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string content_disposition_header("Content-Disposition: ");
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_disposition_header.append(blob_data_->content_disposition());
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers->AddHeader(content_disposition_header);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_info_.reset(new net::HttpResponseInfo());
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_info_->headers = headers;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_expected_content_size(remaining_bytes_);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyHeadersComplete();
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FileStreamReader* BlobURLRequestJob::GetFileStreamReader(size_t index) {
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LT(index, blob_data_->items().size());
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BlobData::Item& item = blob_data_->items().at(index);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsFileType(item.type()))
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (index_to_reader_.find(index) == index_to_reader_.end())
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateFileStreamReader(index, 0);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(index_to_reader_[index]);
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return index_to_reader_[index];
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlobURLRequestJob::CreateFileStreamReader(size_t index,
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               int64 additional_offset) {
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LT(index, blob_data_->items().size());
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BlobData::Item& item = blob_data_->items().at(index);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsFileType(item.type()));
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(0U, index_to_reader_.count(index));
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileStreamReader* reader = NULL;
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (item.type()) {
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BlobData::Item::TYPE_FILE:
572d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      reader = FileStreamReader::CreateForLocalFile(
573d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          file_thread_proxy_.get(),
574d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          item.path(),
575d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          item.offset() + additional_offset,
576d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          item.expected_modification_time());
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BlobData::Item::TYPE_FILE_FILESYSTEM:
5791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      reader = file_system_context_
5801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   ->CreateFileStreamReader(
5811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         storage::FileSystemURL(file_system_context_->CrackURL(
5821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             item.filesystem_url())),
5831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         item.offset() + additional_offset,
5841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         item.length() == std::numeric_limits<uint64>::max()
5851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             ? storage::kMaximumLength
5861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             : item.length() - additional_offset,
5871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         item.expected_modification_time())
58803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                   .release();
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(reader);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  index_to_reader_[index] = reader;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}  // namespace storage
598