Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / storage / browser / fileapi / local_file_stream_writer.cc
blobc6a1d5122fcc6445d93a850e24f8ae34e4487e4e
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_writer.h"
7 #include "base/callback.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/profiler/scoped_tracker.h"
10 #include "net/base/file_stream.h"
11 #include "net/base/io_buffer.h"
12 #include "net/base/net_errors.h"
14 namespace storage {
16 namespace {
18 const int kOpenFlagsForWrite = base::File::FLAG_OPEN |
19 base::File::FLAG_WRITE |
20 base::File::FLAG_ASYNC;
21 const int kCreateFlagsForWrite = base::File::FLAG_CREATE |
22 base::File::FLAG_WRITE |
23 base::File::FLAG_ASYNC;
25 } // namespace
27 FileStreamWriter* FileStreamWriter::CreateForLocalFile(
28 base::TaskRunner* task_runner,
29 const base::FilePath& file_path,
30 int64 initial_offset,
31 OpenOrCreate open_or_create) {
32 return new LocalFileStreamWriter(
33 task_runner, file_path, initial_offset, open_or_create);
36 LocalFileStreamWriter::~LocalFileStreamWriter() {
37 // Invalidate weak pointers so that we won't receive any callbacks from
38 // in-flight stream operations, which might be triggered during the file close
39 // in the FileStream destructor.
40 weak_factory_.InvalidateWeakPtrs();
42 // FileStream's destructor closes the file safely, since we opened the file
43 // by its Open() method.
46 int LocalFileStreamWriter::Write(net::IOBuffer* buf, int buf_len,
47 const net::CompletionCallback& callback) {
48 DCHECK(!has_pending_operation_);
49 DCHECK(cancel_callback_.is_null());
51 has_pending_operation_ = true;
52 if (stream_impl_) {
53 int result = InitiateWrite(buf, buf_len, callback);
54 if (result != net::ERR_IO_PENDING)
55 has_pending_operation_ = false;
56 return result;
58 return InitiateOpen(callback,
59 base::Bind(&LocalFileStreamWriter::ReadyToWrite,
60 weak_factory_.GetWeakPtr(),
61 make_scoped_refptr(buf), buf_len, callback));
64 int LocalFileStreamWriter::Cancel(const net::CompletionCallback& callback) {
65 if (!has_pending_operation_)
66 return net::ERR_UNEXPECTED;
68 DCHECK(!callback.is_null());
69 cancel_callback_ = callback;
70 return net::ERR_IO_PENDING;
73 int LocalFileStreamWriter::Flush(const net::CompletionCallback& callback) {
74 DCHECK(!has_pending_operation_);
75 DCHECK(cancel_callback_.is_null());
77 // Write() is not called yet, so there's nothing to flush.
78 if (!stream_impl_)
79 return net::OK;
81 has_pending_operation_ = true;
82 int result = InitiateFlush(callback);
83 if (result != net::ERR_IO_PENDING)
84 has_pending_operation_ = false;
85 return result;
88 LocalFileStreamWriter::LocalFileStreamWriter(base::TaskRunner* task_runner,
89 const base::FilePath& file_path,
90 int64 initial_offset,
91 OpenOrCreate open_or_create)
92 : file_path_(file_path),
93 open_or_create_(open_or_create),
94 initial_offset_(initial_offset),
95 task_runner_(task_runner),
96 has_pending_operation_(false),
97 weak_factory_(this) {}
99 int LocalFileStreamWriter::InitiateOpen(
100 const net::CompletionCallback& error_callback,
101 const base::Closure& main_operation) {
102 DCHECK(has_pending_operation_);
103 DCHECK(!stream_impl_.get());
105 stream_impl_.reset(new net::FileStream(task_runner_));
107 int open_flags = 0;
108 switch (open_or_create_) {
109 case OPEN_EXISTING_FILE:
110 open_flags = kOpenFlagsForWrite;
111 break;
112 case CREATE_NEW_FILE:
113 open_flags = kCreateFlagsForWrite;
114 break;
117 return stream_impl_->Open(file_path_,
118 open_flags,
119 base::Bind(&LocalFileStreamWriter::DidOpen,
120 weak_factory_.GetWeakPtr(),
121 error_callback,
122 main_operation));
125 void LocalFileStreamWriter::DidOpen(
126 const net::CompletionCallback& error_callback,
127 const base::Closure& main_operation,
128 int result) {
129 // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed.
130 tracked_objects::ScopedTracker tracking_profile(
131 FROM_HERE_WITH_EXPLICIT_FUNCTION(
132 "423948 LocalFileStreamWriter::DidOpen"));
134 DCHECK(has_pending_operation_);
135 DCHECK(stream_impl_.get());
137 if (CancelIfRequested())
138 return;
140 if (result != net::OK) {
141 has_pending_operation_ = false;
142 stream_impl_.reset(NULL);
143 error_callback.Run(result);
144 return;
147 InitiateSeek(error_callback, main_operation);
150 void LocalFileStreamWriter::InitiateSeek(
151 const net::CompletionCallback& error_callback,
152 const base::Closure& main_operation) {
153 DCHECK(has_pending_operation_);
154 DCHECK(stream_impl_.get());
156 if (initial_offset_ == 0) {
157 // No need to seek.
158 main_operation.Run();
159 return;
162 int result = stream_impl_->Seek(base::File::FROM_BEGIN, initial_offset_,
163 base::Bind(&LocalFileStreamWriter::DidSeek,
164 weak_factory_.GetWeakPtr(),
165 error_callback,
166 main_operation));
167 if (result != net::ERR_IO_PENDING) {
168 has_pending_operation_ = false;
169 error_callback.Run(result);
173 void LocalFileStreamWriter::DidSeek(
174 const net::CompletionCallback& error_callback,
175 const base::Closure& main_operation,
176 int64 result) {
177 DCHECK(has_pending_operation_);
179 if (CancelIfRequested())
180 return;
182 if (result != initial_offset_) {
183 // TODO(kinaba) add a more specific error code.
184 result = net::ERR_FAILED;
187 if (result < 0) {
188 has_pending_operation_ = false;
189 error_callback.Run(static_cast<int>(result));
190 return;
193 main_operation.Run();
196 void LocalFileStreamWriter::ReadyToWrite(
197 net::IOBuffer* buf, int buf_len,
198 const net::CompletionCallback& callback) {
199 DCHECK(has_pending_operation_);
201 int result = InitiateWrite(buf, buf_len, callback);
202 if (result != net::ERR_IO_PENDING) {
203 has_pending_operation_ = false;
204 callback.Run(result);
208 int LocalFileStreamWriter::InitiateWrite(
209 net::IOBuffer* buf, int buf_len,
210 const net::CompletionCallback& callback) {
211 DCHECK(has_pending_operation_);
212 DCHECK(stream_impl_.get());
214 return stream_impl_->Write(buf, buf_len,
215 base::Bind(&LocalFileStreamWriter::DidWrite,
216 weak_factory_.GetWeakPtr(),
217 callback));
220 void LocalFileStreamWriter::DidWrite(const net::CompletionCallback& callback,
221 int result) {
222 DCHECK(has_pending_operation_);
224 if (CancelIfRequested())
225 return;
226 has_pending_operation_ = false;
227 callback.Run(result);
230 int LocalFileStreamWriter::InitiateFlush(
231 const net::CompletionCallback& callback) {
232 DCHECK(has_pending_operation_);
233 DCHECK(stream_impl_.get());
235 return stream_impl_->Flush(base::Bind(&LocalFileStreamWriter::DidFlush,
236 weak_factory_.GetWeakPtr(),
237 callback));
240 void LocalFileStreamWriter::DidFlush(const net::CompletionCallback& callback,
241 int result) {
242 DCHECK(has_pending_operation_);
244 if (CancelIfRequested())
245 return;
246 has_pending_operation_ = false;
247 callback.Run(result);
250 bool LocalFileStreamWriter::CancelIfRequested() {
251 DCHECK(has_pending_operation_);
253 if (cancel_callback_.is_null())
254 return false;
256 net::CompletionCallback pending_cancel = cancel_callback_;
257 has_pending_operation_ = false;
258 cancel_callback_.Reset();
259 pending_cancel.Run(net::OK);
260 return true;
263 } // namespace storage