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"
9 #include "net/base/io_buffer.h"
10 #include "net/base/net_errors.h"
11 #include "storage/browser/fileapi/file_system_backend.h"
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
),
24 preloading_buffer_(new net::IOBuffer(preloading_buffer_length
)),
25 preloading_buffer_offset_(0),
27 weak_ptr_factory_(this) {
30 BufferingFileStreamReader::~BufferingFileStreamReader() {
33 int BufferingFileStreamReader::Read(net::IOBuffer
* buffer
,
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
);
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(
49 base::Bind(&BufferingFileStreamReader::OnReadCompleted
,
50 weak_ptr_factory_
.GetWeakPtr(),
52 DCHECK_EQ(result
, net::ERR_IO_PENDING
);
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
),
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
);
76 int BufferingFileStreamReader::CopyFromPreloadingBuffer(
77 scoped_refptr
<net::IOBuffer
> buffer
,
79 const int read_bytes
= std::min(buffer_length
, preloaded_bytes_
);
81 memcpy(buffer
->data(),
82 preloading_buffer_
->data() + preloading_buffer_offset_
,
84 preloading_buffer_offset_
+= read_bytes
;
85 preloaded_bytes_
-= 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
,
104 const net::CompletionCallback
& callback
,
107 callback
.Run(result
);
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
,
121 callback
.Run(result
);
125 // If more bytes than declared in |max_bytes_to_read_| was read in total, then
128 if (result
> max_bytes_to_read_
- bytes_read_
) {
129 callback
.Run(net::ERR_FAILED
);
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