Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / chromeos / file_system_provider / fileapi / buffering_file_stream_reader.cc
blobcfb1946f22aa2dccfc7d33384b1b22f31756c627
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.
5 #include "chrome/browser/chromeos/file_system_provider/fileapi/buffering_file_stream_reader.h"
7 #include <algorithm>
9 #include "net/base/io_buffer.h"
10 #include "net/base/net_errors.h"
11 #include "storage/browser/fileapi/file_system_backend.h"
13 namespace chromeos {
14 namespace file_system_provider {
16 BufferingFileStreamReader::BufferingFileStreamReader(
17 scoped_ptr<storage::FileStreamReader> file_stream_reader,
18 int preloading_buffer_length,
19 int64 max_bytes_to_read)
20 : file_stream_reader_(file_stream_reader.Pass()),
21 preloading_buffer_length_(preloading_buffer_length),
22 max_bytes_to_read_(max_bytes_to_read),
23 bytes_read_(0),
24 preloading_buffer_(new net::IOBuffer(preloading_buffer_length)),
25 preloading_buffer_offset_(0),
26 preloaded_bytes_(0),
27 weak_ptr_factory_(this) {
30 BufferingFileStreamReader::~BufferingFileStreamReader() {
33 int BufferingFileStreamReader::Read(net::IOBuffer* buffer,
34 int buffer_length,
35 const net::CompletionCallback& callback) {
36 // Return as much as available in the internal buffer. It may be less than
37 // |buffer_length|, what is valid.
38 const int bytes_read =
39 CopyFromPreloadingBuffer(make_scoped_refptr(buffer), buffer_length);
40 if (bytes_read)
41 return bytes_read;
43 // If the internal buffer is empty, and more bytes than the internal buffer
44 // size is requested, then call the internal file stream reader directly.
45 if (buffer_length >= preloading_buffer_length_) {
46 const int result = file_stream_reader_->Read(
47 buffer,
48 buffer_length,
49 base::Bind(&BufferingFileStreamReader::OnReadCompleted,
50 weak_ptr_factory_.GetWeakPtr(),
51 callback));
52 DCHECK_EQ(result, net::ERR_IO_PENDING);
53 return result;
56 // Nothing copied, so contents have to be preloaded.
57 Preload(base::Bind(&BufferingFileStreamReader::OnReadCompleted,
58 weak_ptr_factory_.GetWeakPtr(),
59 base::Bind(&BufferingFileStreamReader::OnPreloadCompleted,
60 weak_ptr_factory_.GetWeakPtr(),
61 make_scoped_refptr(buffer),
62 buffer_length,
63 callback)));
65 return net::ERR_IO_PENDING;
68 int64 BufferingFileStreamReader::GetLength(
69 const net::Int64CompletionCallback& callback) {
70 const int64 result = file_stream_reader_->GetLength(callback);
71 DCHECK_EQ(net::ERR_IO_PENDING, result);
73 return result;
76 int BufferingFileStreamReader::CopyFromPreloadingBuffer(
77 scoped_refptr<net::IOBuffer> buffer,
78 int buffer_length) {
79 const int read_bytes = std::min(buffer_length, preloaded_bytes_);
81 memcpy(buffer->data(),
82 preloading_buffer_->data() + preloading_buffer_offset_,
83 read_bytes);
84 preloading_buffer_offset_ += read_bytes;
85 preloaded_bytes_ -= read_bytes;
87 return read_bytes;
90 void BufferingFileStreamReader::Preload(
91 const net::CompletionCallback& callback) {
92 const int preload_bytes =
93 std::min(static_cast<int64>(preloading_buffer_length_),
94 max_bytes_to_read_ - bytes_read_);
96 const int result = file_stream_reader_->Read(
97 preloading_buffer_.get(), preload_bytes, callback);
98 DCHECK_EQ(result, net::ERR_IO_PENDING);
101 void BufferingFileStreamReader::OnPreloadCompleted(
102 scoped_refptr<net::IOBuffer> buffer,
103 int buffer_length,
104 const net::CompletionCallback& callback,
105 int result) {
106 if (result < 0) {
107 callback.Run(result);
108 return;
111 preloading_buffer_offset_ = 0;
112 preloaded_bytes_ = result;
114 callback.Run(CopyFromPreloadingBuffer(buffer, buffer_length));
117 void BufferingFileStreamReader::OnReadCompleted(
118 const net::CompletionCallback& callback,
119 int result) {
120 if (result < 0) {
121 callback.Run(result);
122 return;
125 // If more bytes than declared in |max_bytes_to_read_| was read in total, then
126 // emit an
127 // error.
128 if (result > max_bytes_to_read_ - bytes_read_) {
129 callback.Run(net::ERR_FAILED);
130 return;
133 bytes_read_ += result;
134 DCHECK_LE(bytes_read_, max_bytes_to_read_);
136 callback.Run(result);
139 } // namespace file_system_provider
140 } // namespace chromeos