Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / file_system_provider / fileapi / buffering_file_stream_reader.cc
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 "chrome/browser/chromeos/file_system_provider/fileapi/buffering_file_stream_reader.h"
6
7 #include <algorithm>
8
9 #include "net/base/io_buffer.h"
10 #include "net/base/net_errors.h"
11 #include "storage/browser/fileapi/file_system_backend.h"
12
13 namespace chromeos {
14 namespace file_system_provider {
15
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) {
28 }
29
30 BufferingFileStreamReader::~BufferingFileStreamReader() {
31 }
32
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;
42
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;
54   }
55
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)));
64
65   return net::ERR_IO_PENDING;
66 }
67
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);
72
73   return result;
74 }
75
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_);
80
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;
86
87   return read_bytes;
88 }
89
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_);
95
96   const int result = file_stream_reader_->Read(
97       preloading_buffer_.get(), preload_bytes, callback);
98   DCHECK_EQ(result, net::ERR_IO_PENDING);
99 }
100
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;
109   }
110
111   preloading_buffer_offset_ = 0;
112   preloaded_bytes_ = result;
113
114   callback.Run(CopyFromPreloadingBuffer(buffer, buffer_length));
115 }
116
117 void BufferingFileStreamReader::OnReadCompleted(
118     const net::CompletionCallback& callback,
119     int result) {
120   if (result < 0) {
121     callback.Run(result);
122     return;
123   }
124
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;
131   }
132
133   bytes_read_ += result;
134   DCHECK_LE(bytes_read_, max_bytes_to_read_);
135
136   callback.Run(result);
137 }
138
139 }  // namespace file_system_provider
140 }  // namespace chromeos