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/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 : weak_factory_(this), 56 file_task_runner_(file_task_runner), 57 file_path_(file_path), 58 owns_file_(false) { 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(NULL)); 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::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC | 84 base::PLATFORM_FILE_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 int result = file_stream_->Close(base::Bind( 111 &URLFetcherFileWriter::CloseComplete, 112 weak_factory_.GetWeakPtr(), callback)); 113 if (result != ERR_IO_PENDING) 114 file_stream_.reset(); 115 return result; 116 } 117 118 URLFetcherFileWriter* URLFetcherFileWriter::AsFileWriter() { 119 return this; 120 } 121 122 void URLFetcherFileWriter::DisownFile() { 123 // Disowning is done by the delegate's OnURLFetchComplete method. 124 // The file should be closed by the time that method is called. 125 DCHECK(!file_stream_); 126 127 owns_file_ = false; 128 } 129 130 void URLFetcherFileWriter::DidWrite(const CompletionCallback& callback, 131 int result) { 132 if (result < 0) 133 CloseAndDeleteFile(); 134 135 callback.Run(result); 136 } 137 138 void URLFetcherFileWriter::CloseAndDeleteFile() { 139 if (!owns_file_) 140 return; 141 142 file_stream_.reset(); 143 DisownFile(); 144 file_task_runner_->PostTask(FROM_HERE, 145 base::Bind(base::IgnoreResult(&base::DeleteFile), 146 file_path_, 147 false /* recursive */)); 148 } 149 150 void URLFetcherFileWriter::DidCreateTempFile(const CompletionCallback& callback, 151 base::FilePath* temp_file_path, 152 bool success) { 153 if (!success) { 154 callback.Run(ERR_FILE_NOT_FOUND); 155 return; 156 } 157 file_path_ = *temp_file_path; 158 owns_file_ = true; 159 const int result = file_stream_->Open( 160 file_path_, 161 base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC | 162 base::PLATFORM_FILE_OPEN, 163 base::Bind(&URLFetcherFileWriter::DidOpenFile, 164 weak_factory_.GetWeakPtr(), 165 callback)); 166 if (result != ERR_IO_PENDING) 167 DidOpenFile(callback, result); 168 } 169 170 void URLFetcherFileWriter::DidOpenFile(const CompletionCallback& callback, 171 int result) { 172 if (result == OK) 173 owns_file_ = true; 174 else 175 CloseAndDeleteFile(); 176 177 callback.Run(result); 178 } 179 180 void URLFetcherFileWriter::CloseComplete(const CompletionCallback& callback, 181 int result) { 182 // Destroy |file_stream_| whether or not the close succeeded. 183 file_stream_.reset(); 184 callback.Run(result); 185 } 186 187 } // namespace net 188