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