1 // Copyright (c) 2013 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 "net/url_request/url_fetcher_response_writer.h"
7 #include "base/files/file_util.h"
8 #include "base/location.h"
9 #include "base/profiler/scoped_tracker.h"
10 #include "base/sequenced_task_runner.h"
11 #include "base/task_runner_util.h"
12 #include "net/base/file_stream.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/net_errors.h"
18 URLFetcherStringWriter
* URLFetcherResponseWriter::AsStringWriter() {
22 URLFetcherFileWriter
* URLFetcherResponseWriter::AsFileWriter() {
26 URLFetcherStringWriter::URLFetcherStringWriter() {
29 URLFetcherStringWriter::~URLFetcherStringWriter() {
32 int URLFetcherStringWriter::Initialize(const CompletionCallback
& callback
) {
37 int URLFetcherStringWriter::Write(IOBuffer
* buffer
,
39 const CompletionCallback
& callback
) {
40 data_
.append(buffer
->data(), num_bytes
);
44 int URLFetcherStringWriter::Finish(const CompletionCallback
& callback
) {
49 URLFetcherStringWriter
* URLFetcherStringWriter::AsStringWriter() {
53 URLFetcherFileWriter::URLFetcherFileWriter(
54 scoped_refptr
<base::SequencedTaskRunner
> file_task_runner
,
55 const base::FilePath
& file_path
)
56 : file_task_runner_(file_task_runner
),
57 file_path_(file_path
),
60 DCHECK(file_task_runner_
.get());
63 URLFetcherFileWriter::~URLFetcherFileWriter() {
67 int URLFetcherFileWriter::Initialize(const CompletionCallback
& callback
) {
68 file_stream_
.reset(new FileStream(file_task_runner_
));
70 int result
= ERR_IO_PENDING
;
71 if (file_path_
.empty()) {
72 base::FilePath
* temp_file_path
= new base::FilePath
;
73 base::PostTaskAndReplyWithResult(
74 file_task_runner_
.get(),
76 base::Bind(&base::CreateTemporaryFile
, temp_file_path
),
77 base::Bind(&URLFetcherFileWriter::DidCreateTempFile
,
78 weak_factory_
.GetWeakPtr(),
80 base::Owned(temp_file_path
)));
82 result
= file_stream_
->Open(
84 base::File::FLAG_WRITE
| base::File::FLAG_ASYNC
|
85 base::File::FLAG_CREATE_ALWAYS
,
86 base::Bind(&URLFetcherFileWriter::DidOpenFile
,
87 weak_factory_
.GetWeakPtr(),
89 DCHECK_NE(OK
, result
);
94 int URLFetcherFileWriter::Write(IOBuffer
* buffer
,
96 const CompletionCallback
& callback
) {
100 int result
= file_stream_
->Write(buffer
, num_bytes
,
101 base::Bind(&URLFetcherFileWriter::DidWrite
,
102 weak_factory_
.GetWeakPtr(),
104 if (result
< 0 && result
!= ERR_IO_PENDING
)
105 CloseAndDeleteFile();
110 int URLFetcherFileWriter::Finish(const CompletionCallback
& callback
) {
111 // If the file_stream_ still exists at this point, close it.
113 int result
= file_stream_
->Close(base::Bind(
114 &URLFetcherFileWriter::CloseComplete
,
115 weak_factory_
.GetWeakPtr(), callback
));
116 if (result
!= ERR_IO_PENDING
)
117 file_stream_
.reset();
123 URLFetcherFileWriter
* URLFetcherFileWriter::AsFileWriter() {
127 void URLFetcherFileWriter::DisownFile() {
128 // Disowning is done by the delegate's OnURLFetchComplete method.
129 // The file should be closed by the time that method is called.
130 DCHECK(!file_stream_
);
135 void URLFetcherFileWriter::DidWrite(const CompletionCallback
& callback
,
138 CloseAndDeleteFile();
140 callback
.Run(result
);
143 void URLFetcherFileWriter::CloseAndDeleteFile() {
147 file_stream_
.reset();
149 file_task_runner_
->PostTask(FROM_HERE
,
150 base::Bind(base::IgnoreResult(&base::DeleteFile
),
152 false /* recursive */));
155 void URLFetcherFileWriter::DidCreateTempFile(const CompletionCallback
& callback
,
156 base::FilePath
* temp_file_path
,
159 callback
.Run(ERR_FILE_NOT_FOUND
);
162 file_path_
= *temp_file_path
;
164 const int result
= file_stream_
->Open(
166 base::File::FLAG_WRITE
| base::File::FLAG_ASYNC
|
167 base::File::FLAG_OPEN
,
168 base::Bind(&URLFetcherFileWriter::DidOpenFile
,
169 weak_factory_
.GetWeakPtr(),
171 if (result
!= ERR_IO_PENDING
)
172 DidOpenFile(callback
, result
);
175 void URLFetcherFileWriter::DidOpenFile(const CompletionCallback
& callback
,
177 // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed.
178 tracked_objects::ScopedTracker
tracking_profile(
179 FROM_HERE_WITH_EXPLICIT_FUNCTION(
180 "423948 URLFetcherFileWriter::DidOpenFile"));
185 CloseAndDeleteFile();
187 callback
.Run(result
);
190 void URLFetcherFileWriter::CloseComplete(const CompletionCallback
& callback
,
192 // Destroy |file_stream_| whether or not the close succeeded.
193 file_stream_
.reset();
194 callback
.Run(result
);