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 "webkit/fileapi/local_file_stream_writer.h"
7 #include "base/callback.h"
8 #include "base/message_loop.h"
9 #include "net/base/file_stream.h"
10 #include "net/base/io_buffer.h"
11 #include "net/base/net_errors.h"
17 const int kOpenFlagsForWrite
= base::PLATFORM_FILE_OPEN
|
18 base::PLATFORM_FILE_WRITE
|
19 base::PLATFORM_FILE_ASYNC
;
23 LocalFileStreamWriter::LocalFileStreamWriter(const FilePath
& file_path
,
25 : file_path_(file_path
),
26 initial_offset_(initial_offset
),
27 has_pending_operation_(false),
28 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
30 LocalFileStreamWriter::~LocalFileStreamWriter() {
31 // Invalidate weak pointers so that we won't receive any callbacks from
32 // in-flight stream operations, which might be triggered during the file close
33 // in the FileStream destructor.
34 weak_factory_
.InvalidateWeakPtrs();
36 // FileStream's destructor closes the file safely, since we opened the file
37 // by its Open() method.
40 int LocalFileStreamWriter::Write(net::IOBuffer
* buf
, int buf_len
,
41 const net::CompletionCallback
& callback
) {
42 DCHECK(!has_pending_operation_
);
43 DCHECK(cancel_callback_
.is_null());
45 has_pending_operation_
= true;
46 if (stream_impl_
.get()) {
47 int result
= InitiateWrite(buf
, buf_len
, callback
);
48 if (result
!= net::ERR_IO_PENDING
)
49 has_pending_operation_
= false;
52 return InitiateOpen(callback
,
53 base::Bind(&LocalFileStreamWriter::ReadyToWrite
,
54 weak_factory_
.GetWeakPtr(),
55 make_scoped_refptr(buf
), buf_len
, callback
));
58 int LocalFileStreamWriter::Cancel(const net::CompletionCallback
& callback
) {
59 if (!has_pending_operation_
)
60 return net::ERR_UNEXPECTED
;
62 DCHECK(!callback
.is_null());
63 cancel_callback_
= callback
;
64 return net::ERR_IO_PENDING
;
67 int LocalFileStreamWriter::InitiateOpen(
68 const net::CompletionCallback
& error_callback
,
69 const base::Closure
& main_operation
) {
70 DCHECK(has_pending_operation_
);
71 DCHECK(!stream_impl_
.get());
73 stream_impl_
.reset(new net::FileStream(NULL
));
74 return stream_impl_
->Open(file_path_
,
76 base::Bind(&LocalFileStreamWriter::DidOpen
,
77 weak_factory_
.GetWeakPtr(),
82 void LocalFileStreamWriter::DidOpen(
83 const net::CompletionCallback
& error_callback
,
84 const base::Closure
& main_operation
,
86 DCHECK(has_pending_operation_
);
87 DCHECK(stream_impl_
.get());
89 if (CancelIfRequested())
92 if (result
!= net::OK
) {
93 has_pending_operation_
= false;
94 stream_impl_
.reset(NULL
);
95 error_callback
.Run(result
);
99 InitiateSeek(error_callback
, main_operation
);
102 void LocalFileStreamWriter::InitiateSeek(
103 const net::CompletionCallback
& error_callback
,
104 const base::Closure
& main_operation
) {
105 DCHECK(has_pending_operation_
);
106 DCHECK(stream_impl_
.get());
108 if (initial_offset_
== 0) {
110 main_operation
.Run();
114 int result
= stream_impl_
->Seek(net::FROM_BEGIN
, initial_offset_
,
115 base::Bind(&LocalFileStreamWriter::DidSeek
,
116 weak_factory_
.GetWeakPtr(),
119 if (result
!= net::ERR_IO_PENDING
) {
120 has_pending_operation_
= false;
121 error_callback
.Run(result
);
125 void LocalFileStreamWriter::DidSeek(
126 const net::CompletionCallback
& error_callback
,
127 const base::Closure
& main_operation
,
129 DCHECK(has_pending_operation_
);
131 if (CancelIfRequested())
134 if (result
!= initial_offset_
) {
135 // TODO(kinaba) add a more specific error code.
136 result
= net::ERR_FAILED
;
140 has_pending_operation_
= false;
141 error_callback
.Run(static_cast<int>(result
));
145 main_operation
.Run();
148 void LocalFileStreamWriter::ReadyToWrite(
149 net::IOBuffer
* buf
, int buf_len
,
150 const net::CompletionCallback
& callback
) {
151 DCHECK(has_pending_operation_
);
153 int result
= InitiateWrite(buf
, buf_len
, callback
);
154 if (result
!= net::ERR_IO_PENDING
) {
155 has_pending_operation_
= false;
156 callback
.Run(result
);
160 int LocalFileStreamWriter::InitiateWrite(
161 net::IOBuffer
* buf
, int buf_len
,
162 const net::CompletionCallback
& callback
) {
163 DCHECK(has_pending_operation_
);
164 DCHECK(stream_impl_
.get());
166 return stream_impl_
->Write(buf
, buf_len
,
167 base::Bind(&LocalFileStreamWriter::DidWrite
,
168 weak_factory_
.GetWeakPtr(),
172 void LocalFileStreamWriter::DidWrite(const net::CompletionCallback
& callback
,
174 DCHECK(has_pending_operation_
);
176 if (CancelIfRequested())
178 has_pending_operation_
= false;
179 callback
.Run(result
);
182 bool LocalFileStreamWriter::CancelIfRequested() {
183 DCHECK(has_pending_operation_
);
185 if (cancel_callback_
.is_null())
188 net::CompletionCallback pending_cancel
= cancel_callback_
;
189 has_pending_operation_
= false;
190 cancel_callback_
.Reset();
191 pending_cancel
.Run(net::OK
);
195 } // namespace fileapi