1 // Copyright (c) 2012 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 "storage/browser/fileapi/local_file_stream_reader.h"
7 #include "base/files/file_util.h"
8 #include "base/files/file_util_proxy.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/task_runner.h"
12 #include "net/base/file_stream.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/net_errors.h"
20 const int kOpenFlagsForRead
= base::File::FLAG_OPEN
|
21 base::File::FLAG_READ
|
22 base::File::FLAG_ASYNC
;
26 FileStreamReader
* FileStreamReader::CreateForLocalFile(
27 base::TaskRunner
* task_runner
,
28 const base::FilePath
& file_path
,
30 const base::Time
& expected_modification_time
) {
31 return new LocalFileStreamReader(task_runner
, file_path
, initial_offset
,
32 expected_modification_time
);
35 LocalFileStreamReader::~LocalFileStreamReader() {
38 int LocalFileStreamReader::Read(net::IOBuffer
* buf
, int buf_len
,
39 const net::CompletionCallback
& callback
) {
40 DCHECK(!has_pending_open_
);
42 return stream_impl_
->Read(buf
, buf_len
, callback
);
43 return Open(base::Bind(&LocalFileStreamReader::DidOpenForRead
,
44 weak_factory_
.GetWeakPtr(),
45 make_scoped_refptr(buf
), buf_len
, callback
));
48 int64
LocalFileStreamReader::GetLength(
49 const net::Int64CompletionCallback
& callback
) {
50 const bool posted
= base::FileUtilProxy::GetFileInfo(
53 base::Bind(&LocalFileStreamReader::DidGetFileInfoForGetLength
,
54 weak_factory_
.GetWeakPtr(),
57 return net::ERR_IO_PENDING
;
60 LocalFileStreamReader::LocalFileStreamReader(
61 base::TaskRunner
* task_runner
,
62 const base::FilePath
& file_path
,
64 const base::Time
& expected_modification_time
)
65 : task_runner_(task_runner
),
66 file_path_(file_path
),
67 initial_offset_(initial_offset
),
68 expected_modification_time_(expected_modification_time
),
69 has_pending_open_(false),
70 weak_factory_(this) {}
72 int LocalFileStreamReader::Open(const net::CompletionCallback
& callback
) {
73 DCHECK(!has_pending_open_
);
74 DCHECK(!stream_impl_
.get());
75 has_pending_open_
= true;
77 // Call GetLength first to make it perform last-modified-time verification,
78 // and then call DidVerifyForOpen for do the rest.
79 return GetLength(base::Bind(&LocalFileStreamReader::DidVerifyForOpen
,
80 weak_factory_
.GetWeakPtr(), callback
));
83 void LocalFileStreamReader::DidVerifyForOpen(
84 const net::CompletionCallback
& callback
,
85 int64 get_length_result
) {
86 if (get_length_result
< 0) {
87 callback
.Run(static_cast<int>(get_length_result
));
91 stream_impl_
.reset(new net::FileStream(task_runner_
));
92 const int result
= stream_impl_
->Open(
93 file_path_
, kOpenFlagsForRead
,
94 base::Bind(&LocalFileStreamReader::DidOpenFileStream
,
95 weak_factory_
.GetWeakPtr(),
97 if (result
!= net::ERR_IO_PENDING
)
101 void LocalFileStreamReader::DidOpenFileStream(
102 const net::CompletionCallback
& callback
,
104 if (result
!= net::OK
) {
105 callback
.Run(result
);
108 result
= stream_impl_
->Seek(
109 base::File::FROM_BEGIN
, initial_offset_
,
110 base::Bind(&LocalFileStreamReader::DidSeekFileStream
,
111 weak_factory_
.GetWeakPtr(),
113 if (result
!= net::ERR_IO_PENDING
) {
114 callback
.Run(result
);
118 void LocalFileStreamReader::DidSeekFileStream(
119 const net::CompletionCallback
& callback
,
121 if (seek_result
< 0) {
122 callback
.Run(static_cast<int>(seek_result
));
125 if (seek_result
!= initial_offset_
) {
126 callback
.Run(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE
);
129 callback
.Run(net::OK
);
132 void LocalFileStreamReader::DidOpenForRead(
135 const net::CompletionCallback
& callback
,
137 DCHECK(has_pending_open_
);
138 has_pending_open_
= false;
139 if (open_result
!= net::OK
) {
140 stream_impl_
.reset();
141 callback
.Run(open_result
);
144 DCHECK(stream_impl_
.get());
145 const int read_result
= stream_impl_
->Read(buf
, buf_len
, callback
);
146 if (read_result
!= net::ERR_IO_PENDING
)
147 callback
.Run(read_result
);
150 void LocalFileStreamReader::DidGetFileInfoForGetLength(
151 const net::Int64CompletionCallback
& callback
,
152 base::File::Error error
,
153 const base::File::Info
& file_info
) {
154 if (file_info
.is_directory
) {
155 callback
.Run(net::ERR_FILE_NOT_FOUND
);
158 if (error
!= base::File::FILE_OK
) {
159 callback
.Run(net::FileErrorToNetError(error
));
162 if (!VerifySnapshotTime(expected_modification_time_
, file_info
)) {
163 callback
.Run(net::ERR_UPLOAD_FILE_CHANGED
);
166 callback
.Run(file_info
.size
);
169 } // namespace storage