1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "content/browser/fileapi/upload_file_system_file_element_reader.h" 6 7#include <algorithm> 8#include <limits> 9 10#include "base/bind.h" 11#include "base/numerics/safe_conversions.h" 12#include "net/base/net_errors.h" 13#include "storage/browser/blob/file_stream_reader.h" 14#include "storage/browser/fileapi/file_system_context.h" 15#include "storage/browser/fileapi/file_system_url.h" 16 17namespace content { 18 19UploadFileSystemFileElementReader::UploadFileSystemFileElementReader( 20 storage::FileSystemContext* file_system_context, 21 const GURL& url, 22 uint64 range_offset, 23 uint64 range_length, 24 const base::Time& expected_modification_time) 25 : file_system_context_(file_system_context), 26 url_(url), 27 range_offset_(range_offset), 28 range_length_(range_length), 29 expected_modification_time_(expected_modification_time), 30 stream_length_(0), 31 position_(0), 32 weak_ptr_factory_(this) { 33} 34 35UploadFileSystemFileElementReader::~UploadFileSystemFileElementReader() { 36} 37 38int UploadFileSystemFileElementReader::Init( 39 const net::CompletionCallback& callback) { 40 // Reset states. 41 weak_ptr_factory_.InvalidateWeakPtrs(); 42 stream_length_ = 0; 43 position_ = 0; 44 45 // Initialize the stream reader and the length. 46 stream_reader_ = file_system_context_->CreateFileStreamReader( 47 file_system_context_->CrackURL(url_), 48 range_offset_, 49 range_length_ == std::numeric_limits<uint64>::max() 50 ? storage::kMaximumLength 51 : base::checked_cast<int64>(range_length_), 52 expected_modification_time_); 53 DCHECK(stream_reader_); 54 55 const int64 result = stream_reader_->GetLength( 56 base::Bind(&UploadFileSystemFileElementReader::OnGetLength, 57 weak_ptr_factory_.GetWeakPtr(), 58 callback)); 59 if (result >= 0) { 60 stream_length_ = result; 61 return net::OK; 62 } 63 64 // The error code can be casted to int. 65 return static_cast<int>(result); 66} 67 68uint64 UploadFileSystemFileElementReader::GetContentLength() const { 69 return std::min(stream_length_, range_length_); 70} 71 72uint64 UploadFileSystemFileElementReader::BytesRemaining() const { 73 return GetContentLength() - position_; 74} 75 76int UploadFileSystemFileElementReader::Read( 77 net::IOBuffer* buf, 78 int buf_length, 79 const net::CompletionCallback& callback) { 80 DCHECK_LT(0, buf_length); 81 DCHECK(stream_reader_); 82 83 const uint64 num_bytes_to_read = 84 std::min(BytesRemaining(), static_cast<uint64>(buf_length)); 85 86 if (num_bytes_to_read == 0) 87 return 0; 88 89 const int result = stream_reader_->Read( 90 buf, num_bytes_to_read, 91 base::Bind(&UploadFileSystemFileElementReader::OnRead, 92 weak_ptr_factory_.GetWeakPtr(), 93 callback)); 94 if (result >= 0) 95 OnRead(net::CompletionCallback(), result); 96 return result; 97} 98 99void UploadFileSystemFileElementReader::OnGetLength( 100 const net::CompletionCallback& callback, 101 int64 result) { 102 if (result >= 0) { 103 stream_length_ = result; 104 callback.Run(net::OK); 105 return; 106 } 107 callback.Run(result); 108} 109 110void UploadFileSystemFileElementReader::OnRead( 111 const net::CompletionCallback& callback, 112 int result) { 113 if (result > 0) { 114 position_ += result; 115 DCHECK_LE(position_, GetContentLength()); 116 } 117 if (!callback.is_null()) 118 callback.Run(result); 119} 120 121} // namespace content 122