Experimental push messaging api reference docs.
[chromium-blink-merge.git] / webkit / fileapi / local_file_stream_writer.cc
blob95a2a7e691d3fd729e733ed96370f0c884ced7c6
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"
13 namespace fileapi {
15 namespace {
17 const int kOpenFlagsForWrite = base::PLATFORM_FILE_OPEN |
18 base::PLATFORM_FILE_WRITE |
19 base::PLATFORM_FILE_ASYNC;
21 } // namespace
23 LocalFileStreamWriter::LocalFileStreamWriter(const FilePath& file_path,
24 int64 initial_offset)
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;
50 return result;
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_,
75 kOpenFlagsForWrite,
76 base::Bind(&LocalFileStreamWriter::DidOpen,
77 weak_factory_.GetWeakPtr(),
78 error_callback,
79 main_operation));
82 void LocalFileStreamWriter::DidOpen(
83 const net::CompletionCallback& error_callback,
84 const base::Closure& main_operation,
85 int result) {
86 DCHECK(has_pending_operation_);
87 DCHECK(stream_impl_.get());
89 if (CancelIfRequested())
90 return;
92 if (result != net::OK) {
93 has_pending_operation_ = false;
94 stream_impl_.reset(NULL);
95 error_callback.Run(result);
96 return;
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) {
109 // No need to seek.
110 main_operation.Run();
111 return;
114 int result = stream_impl_->Seek(net::FROM_BEGIN, initial_offset_,
115 base::Bind(&LocalFileStreamWriter::DidSeek,
116 weak_factory_.GetWeakPtr(),
117 error_callback,
118 main_operation));
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,
128 int64 result) {
129 DCHECK(has_pending_operation_);
131 if (CancelIfRequested())
132 return;
134 if (result != initial_offset_) {
135 // TODO(kinaba) add a more specific error code.
136 result = net::ERR_FAILED;
139 if (result < 0) {
140 has_pending_operation_ = false;
141 error_callback.Run(static_cast<int>(result));
142 return;
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(),
169 callback));
172 void LocalFileStreamWriter::DidWrite(const net::CompletionCallback& callback,
173 int result) {
174 DCHECK(has_pending_operation_);
176 if (CancelIfRequested())
177 return;
178 has_pending_operation_ = false;
179 callback.Run(result);
182 bool LocalFileStreamWriter::CancelIfRequested() {
183 DCHECK(has_pending_operation_);
185 if (cancel_callback_.is_null())
186 return false;
188 net::CompletionCallback pending_cancel = cancel_callback_;
189 has_pending_operation_ = false;
190 cancel_callback_.Reset();
191 pending_cancel.Run(net::OK);
192 return true;
195 } // namespace fileapi