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/profiler/scoped_tracker.h"
12 #include "base/task_runner.h"
13 #include "net/base/file_stream.h"
14 #include "net/base/io_buffer.h"
15 #include "net/base/net_errors.h"
21 const int kOpenFlagsForRead
= base::File::FLAG_OPEN
|
22 base::File::FLAG_READ
|
23 base::File::FLAG_ASYNC
;
27 FileStreamReader
* FileStreamReader::CreateForLocalFile(
28 base::TaskRunner
* task_runner
,
29 const base::FilePath
& file_path
,
31 const base::Time
& expected_modification_time
) {
32 return new LocalFileStreamReader(task_runner
, file_path
, initial_offset
,
33 expected_modification_time
);
36 LocalFileStreamReader::~LocalFileStreamReader() {
39 int LocalFileStreamReader::Read(net::IOBuffer
* buf
, int buf_len
,
40 const net::CompletionCallback
& callback
) {
41 DCHECK(!has_pending_open_
);
43 return stream_impl_
->Read(buf
, buf_len
, callback
);
44 return Open(base::Bind(&LocalFileStreamReader::DidOpenForRead
,
45 weak_factory_
.GetWeakPtr(),
46 make_scoped_refptr(buf
), buf_len
, callback
));
49 int64
LocalFileStreamReader::GetLength(
50 const net::Int64CompletionCallback
& callback
) {
51 const bool posted
= base::FileUtilProxy::GetFileInfo(
54 base::Bind(&LocalFileStreamReader::DidGetFileInfoForGetLength
,
55 weak_factory_
.GetWeakPtr(),
58 return net::ERR_IO_PENDING
;
61 LocalFileStreamReader::LocalFileStreamReader(
62 base::TaskRunner
* task_runner
,
63 const base::FilePath
& file_path
,
65 const base::Time
& expected_modification_time
)
66 : task_runner_(task_runner
),
67 file_path_(file_path
),
68 initial_offset_(initial_offset
),
69 expected_modification_time_(expected_modification_time
),
70 has_pending_open_(false),
71 weak_factory_(this) {}
73 int LocalFileStreamReader::Open(const net::CompletionCallback
& callback
) {
74 DCHECK(!has_pending_open_
);
75 DCHECK(!stream_impl_
.get());
76 has_pending_open_
= true;
78 // Call GetLength first to make it perform last-modified-time verification,
79 // and then call DidVerifyForOpen for do the rest.
80 return GetLength(base::Bind(&LocalFileStreamReader::DidVerifyForOpen
,
81 weak_factory_
.GetWeakPtr(), callback
));
84 void LocalFileStreamReader::DidVerifyForOpen(
85 const net::CompletionCallback
& callback
,
86 int64 get_length_result
) {
87 if (get_length_result
< 0) {
88 callback
.Run(static_cast<int>(get_length_result
));
92 stream_impl_
.reset(new net::FileStream(task_runner_
));
93 const int result
= stream_impl_
->Open(
94 file_path_
, kOpenFlagsForRead
,
95 base::Bind(&LocalFileStreamReader::DidOpenFileStream
,
96 weak_factory_
.GetWeakPtr(),
98 if (result
!= net::ERR_IO_PENDING
)
102 void LocalFileStreamReader::DidOpenFileStream(
103 const net::CompletionCallback
& callback
,
105 // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed.
106 tracked_objects::ScopedTracker
tracking_profile(
107 FROM_HERE_WITH_EXPLICIT_FUNCTION(
108 "423948 LocalFileStreamReader::DidOpenFileStream"));
110 if (result
!= net::OK
) {
111 callback
.Run(result
);
114 result
= stream_impl_
->Seek(
115 base::File::FROM_BEGIN
, initial_offset_
,
116 base::Bind(&LocalFileStreamReader::DidSeekFileStream
,
117 weak_factory_
.GetWeakPtr(),
119 if (result
!= net::ERR_IO_PENDING
) {
120 callback
.Run(result
);
124 void LocalFileStreamReader::DidSeekFileStream(
125 const net::CompletionCallback
& callback
,
127 if (seek_result
< 0) {
128 callback
.Run(static_cast<int>(seek_result
));
131 if (seek_result
!= initial_offset_
) {
132 callback
.Run(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE
);
135 callback
.Run(net::OK
);
138 void LocalFileStreamReader::DidOpenForRead(
141 const net::CompletionCallback
& callback
,
143 DCHECK(has_pending_open_
);
144 has_pending_open_
= false;
145 if (open_result
!= net::OK
) {
146 stream_impl_
.reset();
147 callback
.Run(open_result
);
150 DCHECK(stream_impl_
.get());
151 const int read_result
= stream_impl_
->Read(buf
, buf_len
, callback
);
152 if (read_result
!= net::ERR_IO_PENDING
)
153 callback
.Run(read_result
);
156 void LocalFileStreamReader::DidGetFileInfoForGetLength(
157 const net::Int64CompletionCallback
& callback
,
158 base::File::Error error
,
159 const base::File::Info
& file_info
) {
160 if (file_info
.is_directory
) {
161 callback
.Run(net::ERR_FILE_NOT_FOUND
);
164 if (error
!= base::File::FILE_OK
) {
165 callback
.Run(net::FileErrorToNetError(error
));
168 if (!VerifySnapshotTime(expected_modification_time_
, file_info
)) {
169 callback
.Run(net::ERR_UPLOAD_FILE_CHANGED
);
172 callback
.Run(file_info
.size
);
175 } // namespace storage