OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "net/url_request/url_fetcher_response_writer.h" | |
6 | |
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" | |
15 | |
16 namespace net { | |
17 | |
18 URLFetcherStringWriter* URLFetcherResponseWriter::AsStringWriter() { | |
19 return NULL; | |
20 } | |
21 | |
22 URLFetcherFileWriter* URLFetcherResponseWriter::AsFileWriter() { | |
23 return NULL; | |
24 } | |
25 | |
26 URLFetcherStringWriter::URLFetcherStringWriter() { | |
27 } | |
28 | |
29 URLFetcherStringWriter::~URLFetcherStringWriter() { | |
30 } | |
31 | |
32 int URLFetcherStringWriter::Initialize(const CompletionCallback& callback) { | |
33 data_.clear(); | |
34 return OK; | |
35 } | |
36 | |
37 int URLFetcherStringWriter::Write(IOBuffer* buffer, | |
38 int num_bytes, | |
39 const CompletionCallback& callback) { | |
40 data_.append(buffer->data(), num_bytes); | |
41 return num_bytes; | |
42 } | |
43 | |
44 int URLFetcherStringWriter::Finish(const CompletionCallback& callback) { | |
45 // Do nothing. | |
46 return OK; | |
47 } | |
48 | |
49 URLFetcherStringWriter* URLFetcherStringWriter::AsStringWriter() { | |
50 return this; | |
51 } | |
52 | |
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), | |
58 owns_file_(false), | |
59 weak_factory_(this) { | |
60 DCHECK(file_task_runner_.get()); | |
61 } | |
62 | |
63 URLFetcherFileWriter::~URLFetcherFileWriter() { | |
64 CloseAndDeleteFile(); | |
65 } | |
66 | |
67 int URLFetcherFileWriter::Initialize(const CompletionCallback& callback) { | |
68 file_stream_.reset(new FileStream(file_task_runner_)); | |
69 | |
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(), | |
75 FROM_HERE, | |
76 base::Bind(&base::CreateTemporaryFile, temp_file_path), | |
77 base::Bind(&URLFetcherFileWriter::DidCreateTempFile, | |
78 weak_factory_.GetWeakPtr(), | |
79 callback, | |
80 base::Owned(temp_file_path))); | |
81 } else { | |
82 result = file_stream_->Open( | |
83 file_path_, | |
84 base::File::FLAG_WRITE | base::File::FLAG_ASYNC | | |
85 base::File::FLAG_CREATE_ALWAYS, | |
86 base::Bind(&URLFetcherFileWriter::DidOpenFile, | |
87 weak_factory_.GetWeakPtr(), | |
88 callback)); | |
89 DCHECK_NE(OK, result); | |
90 } | |
91 return result; | |
92 } | |
93 | |
94 int URLFetcherFileWriter::Write(IOBuffer* buffer, | |
95 int num_bytes, | |
96 const CompletionCallback& callback) { | |
97 DCHECK(file_stream_); | |
98 DCHECK(owns_file_); | |
99 | |
100 int result = file_stream_->Write(buffer, num_bytes, | |
101 base::Bind(&URLFetcherFileWriter::DidWrite, | |
102 weak_factory_.GetWeakPtr(), | |
103 callback)); | |
104 if (result < 0 && result != ERR_IO_PENDING) | |
105 CloseAndDeleteFile(); | |
106 | |
107 return result; | |
108 } | |
109 | |
110 int URLFetcherFileWriter::Finish(const CompletionCallback& callback) { | |
111 // If the file_stream_ still exists at this point, close it. | |
112 if (file_stream_) { | |
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(); | |
118 return result; | |
119 } | |
120 return OK; | |
121 } | |
122 | |
123 URLFetcherFileWriter* URLFetcherFileWriter::AsFileWriter() { | |
124 return this; | |
125 } | |
126 | |
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_); | |
131 | |
132 owns_file_ = false; | |
133 } | |
134 | |
135 void URLFetcherFileWriter::DidWrite(const CompletionCallback& callback, | |
136 int result) { | |
137 if (result < 0) | |
138 CloseAndDeleteFile(); | |
139 | |
140 callback.Run(result); | |
141 } | |
142 | |
143 void URLFetcherFileWriter::CloseAndDeleteFile() { | |
144 if (!owns_file_) | |
145 return; | |
146 | |
147 file_stream_.reset(); | |
148 DisownFile(); | |
149 file_task_runner_->PostTask(FROM_HERE, | |
150 base::Bind(base::IgnoreResult(&base::DeleteFile), | |
151 file_path_, | |
152 false /* recursive */)); | |
153 } | |
154 | |
155 void URLFetcherFileWriter::DidCreateTempFile(const CompletionCallback& callback, | |
156 base::FilePath* temp_file_path, | |
157 bool success) { | |
158 if (!success) { | |
159 callback.Run(ERR_FILE_NOT_FOUND); | |
160 return; | |
161 } | |
162 file_path_ = *temp_file_path; | |
163 owns_file_ = true; | |
164 const int result = file_stream_->Open( | |
165 file_path_, | |
166 base::File::FLAG_WRITE | base::File::FLAG_ASYNC | | |
167 base::File::FLAG_OPEN, | |
168 base::Bind(&URLFetcherFileWriter::DidOpenFile, | |
169 weak_factory_.GetWeakPtr(), | |
170 callback)); | |
171 if (result != ERR_IO_PENDING) | |
172 DidOpenFile(callback, result); | |
173 } | |
174 | |
175 void URLFetcherFileWriter::DidOpenFile(const CompletionCallback& callback, | |
176 int result) { | |
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")); | |
181 | |
182 if (result == OK) | |
183 owns_file_ = true; | |
184 else | |
185 CloseAndDeleteFile(); | |
186 | |
187 callback.Run(result); | |
188 } | |
189 | |
190 void URLFetcherFileWriter::CloseComplete(const CompletionCallback& callback, | |
191 int result) { | |
192 // Destroy |file_stream_| whether or not the close succeeded. | |
193 file_stream_.reset(); | |
194 callback.Run(result); | |
195 } | |
196 | |
197 } // namespace net | |
OLD | NEW |