blob: 6e3b61314acf4cc257f238d40e579b4af40ffeb5 [file] [log] [blame]
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001// 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.
4
5#include "net/url_request/url_fetcher_response_writer.h"
6
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01007#include "base/file_util.h"
8#include "base/location.h"
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +00009#include "base/sequenced_task_runner.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010010#include "base/task_runner_util.h"
11#include "net/base/file_stream.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000012#include "net/base/io_buffer.h"
13#include "net/base/net_errors.h"
14
15namespace net {
16
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010017URLFetcherStringWriter* URLFetcherResponseWriter::AsStringWriter() {
18 return NULL;
19}
20
21URLFetcherFileWriter* URLFetcherResponseWriter::AsFileWriter() {
22 return NULL;
23}
24
25URLFetcherStringWriter::URLFetcherStringWriter() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000026}
27
28URLFetcherStringWriter::~URLFetcherStringWriter() {
29}
30
31int URLFetcherStringWriter::Initialize(const CompletionCallback& callback) {
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010032 data_.clear();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000033 return OK;
34}
35
36int URLFetcherStringWriter::Write(IOBuffer* buffer,
37 int num_bytes,
38 const CompletionCallback& callback) {
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010039 data_.append(buffer->data(), num_bytes);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000040 return num_bytes;
41}
42
43int URLFetcherStringWriter::Finish(const CompletionCallback& callback) {
44 // Do nothing.
45 return OK;
46}
47
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010048URLFetcherStringWriter* URLFetcherStringWriter::AsStringWriter() {
49 return this;
50}
51
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000052URLFetcherFileWriter::URLFetcherFileWriter(
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +000053 scoped_refptr<base::SequencedTaskRunner> file_task_runner,
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010054 const base::FilePath& file_path)
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010055 : file_task_runner_(file_task_runner),
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010056 file_path_(file_path),
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010057 owns_file_(false),
58 weak_factory_(this) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000059 DCHECK(file_task_runner_.get());
60}
61
62URLFetcherFileWriter::~URLFetcherFileWriter() {
63 CloseAndDeleteFile();
64}
65
66int URLFetcherFileWriter::Initialize(const CompletionCallback& callback) {
Bo Liu5c02ac12014-05-01 10:37:37 -070067 file_stream_.reset(new FileStream(file_task_runner_));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010068
69 int result = ERR_IO_PENDING;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000070 if (file_path_.empty()) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010071 base::FilePath* temp_file_path = new base::FilePath;
72 base::PostTaskAndReplyWithResult(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010073 file_task_runner_.get(),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010074 FROM_HERE,
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +000075 base::Bind(&base::CreateTemporaryFile, temp_file_path),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000076 base::Bind(&URLFetcherFileWriter::DidCreateTempFile,
77 weak_factory_.GetWeakPtr(),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000078 callback,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010079 base::Owned(temp_file_path)));
80 } else {
81 result = file_stream_->Open(
82 file_path_,
Torne (Richard Coles)23730a62014-03-21 14:25:57 +000083 base::File::FLAG_WRITE | base::File::FLAG_ASYNC |
84 base::File::FLAG_CREATE_ALWAYS,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010085 base::Bind(&URLFetcherFileWriter::DidOpenFile,
86 weak_factory_.GetWeakPtr(),
87 callback));
88 DCHECK_NE(OK, result);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000089 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010090 return result;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000091}
92
93int URLFetcherFileWriter::Write(IOBuffer* buffer,
94 int num_bytes,
95 const CompletionCallback& callback) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010096 DCHECK(file_stream_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000097 DCHECK(owns_file_);
98
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010099 int result = file_stream_->Write(buffer, num_bytes,
100 base::Bind(&URLFetcherFileWriter::DidWrite,
101 weak_factory_.GetWeakPtr(),
102 callback));
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100103 if (result < 0 && result != ERR_IO_PENDING)
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100104 CloseAndDeleteFile();
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100105
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100106 return result;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000107}
108
109int URLFetcherFileWriter::Finish(const CompletionCallback& callback) {
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000110 // If the file_stream_ still exists at this point, close it.
111 if (file_stream_) {
112 int result = file_stream_->Close(base::Bind(
113 &URLFetcherFileWriter::CloseComplete,
114 weak_factory_.GetWeakPtr(), callback));
115 if (result != ERR_IO_PENDING)
116 file_stream_.reset();
117 return result;
118 }
119 return OK;
Torne (Richard Coles)58537e22013-09-12 12:10:22 +0100120}
121
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100122URLFetcherFileWriter* URLFetcherFileWriter::AsFileWriter() {
123 return this;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000124}
125
126void URLFetcherFileWriter::DisownFile() {
127 // Disowning is done by the delegate's OnURLFetchComplete method.
128 // The file should be closed by the time that method is called.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100129 DCHECK(!file_stream_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000130
131 owns_file_ = false;
132}
133
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100134void URLFetcherFileWriter::DidWrite(const CompletionCallback& callback,
135 int result) {
136 if (result < 0)
137 CloseAndDeleteFile();
138
139 callback.Run(result);
140}
141
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000142void URLFetcherFileWriter::CloseAndDeleteFile() {
143 if (!owns_file_)
144 return;
145
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100146 file_stream_.reset();
147 DisownFile();
148 file_task_runner_->PostTask(FROM_HERE,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100149 base::Bind(base::IgnoreResult(&base::DeleteFile),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100150 file_path_,
151 false /* recursive */));
152}
153
154void URLFetcherFileWriter::DidCreateTempFile(const CompletionCallback& callback,
155 base::FilePath* temp_file_path,
156 bool success) {
157 if (!success) {
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100158 callback.Run(ERR_FILE_NOT_FOUND);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000159 return;
160 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100161 file_path_ = *temp_file_path;
162 owns_file_ = true;
163 const int result = file_stream_->Open(
164 file_path_,
Torne (Richard Coles)23730a62014-03-21 14:25:57 +0000165 base::File::FLAG_WRITE | base::File::FLAG_ASYNC |
166 base::File::FLAG_OPEN,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100167 base::Bind(&URLFetcherFileWriter::DidOpenFile,
168 weak_factory_.GetWeakPtr(),
169 callback));
170 if (result != ERR_IO_PENDING)
171 DidOpenFile(callback, result);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000172}
173
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100174void URLFetcherFileWriter::DidOpenFile(const CompletionCallback& callback,
175 int result) {
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100176 if (result == OK)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000177 owns_file_ = true;
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100178 else
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000179 CloseAndDeleteFile();
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100180
181 callback.Run(result);
182}
183
184void URLFetcherFileWriter::CloseComplete(const CompletionCallback& callback,
185 int result) {
186 // Destroy |file_stream_| whether or not the close succeeded.
187 file_stream_.reset();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100188 callback.Run(result);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000189}
190
191} // namespace net