Don't preload rarely seen large images
[chromium-blink-merge.git] / storage / browser / fileapi / local_file_stream_writer.cc
blob72eb6cd1de46d04a9f5dee155c0d58e412136db3
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/message_loop/message_loop.h"
8 #include "net/base/file_stream.h"
9 #include "net/base/io_buffer.h"
10 #include "net/base/net_errors.h"
12 namespace storage {
14 namespace {
16 const int kOpenFlagsForWrite = base::File::FLAG_OPEN |
17 base::File::FLAG_WRITE |
18 base::File::FLAG_ASYNC;
19 const int kCreateFlagsForWrite = base::File::FLAG_CREATE |
20 base::File::FLAG_WRITE |
21 base::File::FLAG_ASYNC;
23 } // namespace
25 FileStreamWriter* FileStreamWriter::CreateForLocalFile(
26 base::TaskRunner* task_runner,
27 const base::FilePath& file_path,
28 int64 initial_offset,
29 OpenOrCreate open_or_create) {
30 return new LocalFileStreamWriter(
31 task_runner, file_path, initial_offset, open_or_create);
34 LocalFileStreamWriter::~LocalFileStreamWriter() {
35 // Invalidate weak pointers so that we won't receive any callbacks from
36 // in-flight stream operations, which might be triggered during the file close
37 // in the FileStream destructor.
38 weak_factory_.InvalidateWeakPtrs();
40 // FileStream's destructor closes the file safely, since we opened the file
41 // by its Open() method.
44 int LocalFileStreamWriter::Write(net::IOBuffer* buf, int buf_len,
45 const net::CompletionCallback& callback) {
46 DCHECK(!has_pending_operation_);
47 DCHECK(cancel_callback_.is_null());
49 has_pending_operation_ = true;
50 if (stream_impl_) {
51 int result = InitiateWrite(buf, buf_len, callback);
52 if (result != net::ERR_IO_PENDING)
53 has_pending_operation_ = false;
54 return result;
56 return InitiateOpen(callback,
57 base::Bind(&LocalFileStreamWriter::ReadyToWrite,
58 weak_factory_.GetWeakPtr(),
59 make_scoped_refptr(buf), buf_len, callback));
62 int LocalFileStreamWriter::Cancel(const net::CompletionCallback& callback) {
63 if (!has_pending_operation_)
64 return net::ERR_UNEXPECTED;
66 DCHECK(!callback.is_null());
67 cancel_callback_ = callback;
68 return net::ERR_IO_PENDING;
71 int LocalFileStreamWriter::Flush(const net::CompletionCallback& callback) {
72 DCHECK(!has_pending_operation_);
73 DCHECK(cancel_callback_.is_null());
75 // Write() is not called yet, so there's nothing to flush.
76 if (!stream_impl_)
77 return net::OK;
79 has_pending_operation_ = true;
80 int result = InitiateFlush(callback);
81 if (result != net::ERR_IO_PENDING)
82 has_pending_operation_ = false;
83 return result;
86 LocalFileStreamWriter::LocalFileStreamWriter(base::TaskRunner* task_runner,
87 const base::FilePath& file_path,
88 int64 initial_offset,
89 OpenOrCreate open_or_create)
90 : file_path_(file_path),
91 open_or_create_(open_or_create),
92 initial_offset_(initial_offset),
93 task_runner_(task_runner),
94 has_pending_operation_(false),
95 weak_factory_(this) {}
97 int LocalFileStreamWriter::InitiateOpen(
98 const net::CompletionCallback& error_callback,
99 const base::Closure& main_operation) {
100 DCHECK(has_pending_operation_);
101 DCHECK(!stream_impl_.get());
103 stream_impl_.reset(new net::FileStream(task_runner_));
105 int open_flags = 0;
106 switch (open_or_create_) {
107 case OPEN_EXISTING_FILE:
108 open_flags = kOpenFlagsForWrite;
109 break;
110 case CREATE_NEW_FILE:
111 open_flags = kCreateFlagsForWrite;
112 break;
115 return stream_impl_->Open(file_path_,
116 open_flags,
117 base::Bind(&LocalFileStreamWriter::DidOpen,
118 weak_factory_.GetWeakPtr(),
119 error_callback,
120 main_operation));
123 void LocalFileStreamWriter::DidOpen(
124 const net::CompletionCallback& error_callback,
125 const base::Closure& main_operation,
126 int result) {
127 DCHECK(has_pending_operation_);
128 DCHECK(stream_impl_.get());
130 if (CancelIfRequested())
131 return;
133 if (result != net::OK) {
134 has_pending_operation_ = false;
135 stream_impl_.reset(NULL);
136 error_callback.Run(result);
137 return;
140 InitiateSeek(error_callback, main_operation);
143 void LocalFileStreamWriter::InitiateSeek(
144 const net::CompletionCallback& error_callback,
145 const base::Closure& main_operation) {
146 DCHECK(has_pending_operation_);
147 DCHECK(stream_impl_.get());
149 if (initial_offset_ == 0) {
150 // No need to seek.
151 main_operation.Run();
152 return;
155 int result = stream_impl_->Seek(
156 initial_offset_,
157 base::Bind(&LocalFileStreamWriter::DidSeek, weak_factory_.GetWeakPtr(),
158 error_callback, main_operation));
159 if (result != net::ERR_IO_PENDING) {
160 has_pending_operation_ = false;
161 error_callback.Run(result);
165 void LocalFileStreamWriter::DidSeek(
166 const net::CompletionCallback& error_callback,
167 const base::Closure& main_operation,
168 int64 result) {
169 DCHECK(has_pending_operation_);
171 if (CancelIfRequested())
172 return;
174 if (result != initial_offset_) {
175 // TODO(kinaba) add a more specific error code.
176 result = net::ERR_FAILED;
179 if (result < 0) {
180 has_pending_operation_ = false;
181 error_callback.Run(static_cast<int>(result));
182 return;
185 main_operation.Run();
188 void LocalFileStreamWriter::ReadyToWrite(
189 net::IOBuffer* buf, int buf_len,
190 const net::CompletionCallback& callback) {
191 DCHECK(has_pending_operation_);
193 int result = InitiateWrite(buf, buf_len, callback);
194 if (result != net::ERR_IO_PENDING) {
195 has_pending_operation_ = false;
196 callback.Run(result);
200 int LocalFileStreamWriter::InitiateWrite(
201 net::IOBuffer* buf, int buf_len,
202 const net::CompletionCallback& callback) {
203 DCHECK(has_pending_operation_);
204 DCHECK(stream_impl_.get());
206 return stream_impl_->Write(buf, buf_len,
207 base::Bind(&LocalFileStreamWriter::DidWrite,
208 weak_factory_.GetWeakPtr(),
209 callback));
212 void LocalFileStreamWriter::DidWrite(const net::CompletionCallback& callback,
213 int result) {
214 DCHECK(has_pending_operation_);
216 if (CancelIfRequested())
217 return;
218 has_pending_operation_ = false;
219 callback.Run(result);
222 int LocalFileStreamWriter::InitiateFlush(
223 const net::CompletionCallback& callback) {
224 DCHECK(has_pending_operation_);
225 DCHECK(stream_impl_.get());
227 return stream_impl_->Flush(base::Bind(&LocalFileStreamWriter::DidFlush,
228 weak_factory_.GetWeakPtr(),
229 callback));
232 void LocalFileStreamWriter::DidFlush(const net::CompletionCallback& callback,
233 int result) {
234 DCHECK(has_pending_operation_);
236 if (CancelIfRequested())
237 return;
238 has_pending_operation_ = false;
239 callback.Run(result);
242 bool LocalFileStreamWriter::CancelIfRequested() {
243 DCHECK(has_pending_operation_);
245 if (cancel_callback_.is_null())
246 return false;
248 net::CompletionCallback pending_cancel = cancel_callback_;
249 has_pending_operation_ = false;
250 cancel_callback_.Reset();
251 pending_cancel.Run(net::OK);
252 return true;
255 } // namespace storage