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/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::URLFetcherStringWriter(std::string* string) 18 : string_(string) { 19 } 20 21 URLFetcherStringWriter::~URLFetcherStringWriter() { 22 } 23 24 int URLFetcherStringWriter::Initialize(const CompletionCallback& callback) { 25 // Do nothing. 26 return OK; 27 } 28 29 int URLFetcherStringWriter::Write(IOBuffer* buffer, 30 int num_bytes, 31 const CompletionCallback& callback) { 32 string_->append(buffer->data(), num_bytes); 33 return num_bytes; 34 } 35 36 int URLFetcherStringWriter::Finish(const CompletionCallback& callback) { 37 // Do nothing. 38 return OK; 39 } 40 41 URLFetcherFileWriter::URLFetcherFileWriter( 42 scoped_refptr<base::TaskRunner> file_task_runner) 43 : error_code_(OK), 44 weak_factory_(this), 45 file_task_runner_(file_task_runner), 46 owns_file_(false), 47 total_bytes_written_(0) { 48 DCHECK(file_task_runner_.get()); 49 } 50 51 URLFetcherFileWriter::~URLFetcherFileWriter() { 52 CloseAndDeleteFile(); 53 } 54 55 int URLFetcherFileWriter::Initialize(const CompletionCallback& callback) { 56 DCHECK(!file_stream_); 57 DCHECK(!owns_file_); 58 59 file_stream_.reset(new FileStream(NULL)); 60 61 int result = ERR_IO_PENDING; 62 if (file_path_.empty()) { 63 base::FilePath* temp_file_path = new base::FilePath; 64 base::PostTaskAndReplyWithResult( 65 file_task_runner_.get(), 66 FROM_HERE, 67 base::Bind(&file_util::CreateTemporaryFile, temp_file_path), 68 base::Bind(&URLFetcherFileWriter::DidCreateTempFile, 69 weak_factory_.GetWeakPtr(), 70 callback, 71 base::Owned(temp_file_path))); 72 } else { 73 result = file_stream_->Open( 74 file_path_, 75 base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC | 76 base::PLATFORM_FILE_CREATE_ALWAYS, 77 base::Bind(&URLFetcherFileWriter::DidOpenFile, 78 weak_factory_.GetWeakPtr(), 79 callback)); 80 DCHECK_NE(OK, result); 81 if (result != ERR_IO_PENDING) 82 error_code_ = result; 83 } 84 return result; 85 } 86 87 int URLFetcherFileWriter::Write(IOBuffer* buffer, 88 int num_bytes, 89 const CompletionCallback& callback) { 90 DCHECK(file_stream_); 91 DCHECK(owns_file_); 92 93 int result = file_stream_->Write(buffer, num_bytes, 94 base::Bind(&URLFetcherFileWriter::DidWrite, 95 weak_factory_.GetWeakPtr(), 96 callback)); 97 if (result < 0 && result != ERR_IO_PENDING) { 98 error_code_ = result; 99 CloseAndDeleteFile(); 100 } 101 return result; 102 } 103 104 int URLFetcherFileWriter::Finish(const CompletionCallback& callback) { 105 file_stream_.reset(); 106 return OK; 107 } 108 109 void URLFetcherFileWriter::DidWrite(const CompletionCallback& callback, 110 int result) { 111 if (result < 0) { 112 error_code_ = result; 113 CloseAndDeleteFile(); 114 } 115 callback.Run(result); 116 } 117 118 void URLFetcherFileWriter::DisownFile() { 119 // Disowning is done by the delegate's OnURLFetchComplete method. 120 // The file should be closed by the time that method is called. 121 DCHECK(!file_stream_); 122 123 owns_file_ = false; 124 } 125 126 void URLFetcherFileWriter::CloseAndDeleteFile() { 127 if (!owns_file_) 128 return; 129 130 file_stream_.reset(); 131 DisownFile(); 132 file_task_runner_->PostTask(FROM_HERE, 133 base::Bind(base::IgnoreResult(&base::DeleteFile), 134 file_path_, 135 false /* recursive */)); 136 } 137 138 void URLFetcherFileWriter::DidCreateTempFile(const CompletionCallback& callback, 139 base::FilePath* temp_file_path, 140 bool success) { 141 if (!success) { 142 error_code_ = ERR_FILE_NOT_FOUND; 143 callback.Run(error_code_); 144 return; 145 } 146 file_path_ = *temp_file_path; 147 owns_file_ = true; 148 const int result = file_stream_->Open( 149 file_path_, 150 base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC | 151 base::PLATFORM_FILE_OPEN, 152 base::Bind(&URLFetcherFileWriter::DidOpenFile, 153 weak_factory_.GetWeakPtr(), 154 callback)); 155 if (result != ERR_IO_PENDING) 156 DidOpenFile(callback, result); 157 } 158 159 void URLFetcherFileWriter::DidOpenFile(const CompletionCallback& callback, 160 int result) { 161 if (result == OK) { 162 total_bytes_written_ = 0; 163 owns_file_ = true; 164 } else { 165 error_code_ = result; 166 CloseAndDeleteFile(); 167 } 168 callback.Run(result); 169 } 170 171 } // namespace net 172