| Index: net/url_request/url_fetcher_response_writer.cc
|
| diff --git a/net/url_request/url_fetcher_response_writer.cc b/net/url_request/url_fetcher_response_writer.cc
|
| index fcc8cbf38ffc4129245cd2cf2ceb63466e112a67..3286e675ca1819c3a13bd2bc84953b9c56360e74 100644
|
| --- a/net/url_request/url_fetcher_response_writer.cc
|
| +++ b/net/url_request/url_fetcher_response_writer.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "net/url_request/url_fetcher_response_writer.h"
|
|
|
| +#include "base/callback_helpers.h"
|
| #include "base/files/file_util.h"
|
| #include "base/location.h"
|
| #include "base/sequenced_task_runner.h"
|
| @@ -40,7 +41,8 @@ int URLFetcherStringWriter::Write(IOBuffer* buffer,
|
| return num_bytes;
|
| }
|
|
|
| -int URLFetcherStringWriter::Finish(const CompletionCallback& callback) {
|
| +int URLFetcherStringWriter::Finish(int net_error,
|
| + const CompletionCallback& callback) {
|
| // Do nothing.
|
| return OK;
|
| }
|
| @@ -64,9 +66,12 @@ URLFetcherFileWriter::~URLFetcherFileWriter() {
|
| }
|
|
|
| int URLFetcherFileWriter::Initialize(const CompletionCallback& callback) {
|
| + DCHECK(!callback_);
|
| +
|
| file_stream_.reset(new FileStream(file_task_runner_));
|
|
|
| int result = ERR_IO_PENDING;
|
| + owns_file_ = true;
|
| if (file_path_.empty()) {
|
| base::FilePath* temp_file_path = new base::FilePath;
|
| base::PostTaskAndReplyWithResult(
|
| @@ -75,18 +80,22 @@ int URLFetcherFileWriter::Initialize(const CompletionCallback& callback) {
|
| base::Bind(&base::CreateTemporaryFile, temp_file_path),
|
| base::Bind(&URLFetcherFileWriter::DidCreateTempFile,
|
| weak_factory_.GetWeakPtr(),
|
| - callback,
|
| base::Owned(temp_file_path)));
|
| } else {
|
| - result = file_stream_->Open(
|
| - file_path_,
|
| - base::File::FLAG_WRITE | base::File::FLAG_ASYNC |
|
| - base::File::FLAG_CREATE_ALWAYS,
|
| - base::Bind(&URLFetcherFileWriter::DidOpenFile,
|
| - weak_factory_.GetWeakPtr(),
|
| - callback));
|
| + result = file_stream_->Open(file_path_, base::File::FLAG_WRITE |
|
| + base::File::FLAG_ASYNC |
|
| + base::File::FLAG_CREATE_ALWAYS,
|
| + base::Bind(&URLFetcherFileWriter::OnIOCompleted,
|
| + weak_factory_.GetWeakPtr()));
|
| DCHECK_NE(OK, result);
|
| }
|
| +
|
| + if (result == ERR_IO_PENDING) {
|
| + callback_ = callback;
|
| + return result;
|
| + }
|
| + if (result < 0)
|
| + CloseAndDeleteFile();
|
| return result;
|
| }
|
|
|
| @@ -95,25 +104,44 @@ int URLFetcherFileWriter::Write(IOBuffer* buffer,
|
| const CompletionCallback& callback) {
|
| DCHECK(file_stream_);
|
| DCHECK(owns_file_);
|
| + DCHECK(!callback_);
|
|
|
| - int result = file_stream_->Write(buffer, num_bytes,
|
| - base::Bind(&URLFetcherFileWriter::DidWrite,
|
| - weak_factory_.GetWeakPtr(),
|
| - callback));
|
| - if (result < 0 && result != ERR_IO_PENDING)
|
| + int result = file_stream_->Write(
|
| + buffer, num_bytes, base::Bind(&URLFetcherFileWriter::OnIOCompleted,
|
| + weak_factory_.GetWeakPtr()));
|
| + if (result == ERR_IO_PENDING) {
|
| + callback_ = callback;
|
| + return result;
|
| + }
|
| + if (result < 0)
|
| CloseAndDeleteFile();
|
| -
|
| return result;
|
| }
|
|
|
| -int URLFetcherFileWriter::Finish(const CompletionCallback& callback) {
|
| +int URLFetcherFileWriter::Finish(int net_error,
|
| + const CompletionCallback& callback) {
|
| + DCHECK_NE(ERR_IO_PENDING, net_error);
|
| +
|
| + // If an error occurred, simply delete the file after any pending operation
|
| + // is done. Do not call file_stream_->Close() because there might be an
|
| + // operation pending. See crbug.com/487732.
|
| + if (net_error < 0) {
|
| + // Cancel callback and invalid weak ptrs so as to cancel any posted task.
|
| + callback_.Reset();
|
| + weak_factory_.InvalidateWeakPtrs();
|
| + CloseAndDeleteFile();
|
| + return OK;
|
| + }
|
| + DCHECK(!callback_);
|
| // If the file_stream_ still exists at this point, close it.
|
| if (file_stream_) {
|
| int result = file_stream_->Close(base::Bind(
|
| - &URLFetcherFileWriter::CloseComplete,
|
| - weak_factory_.GetWeakPtr(), callback));
|
| - if (result != ERR_IO_PENDING)
|
| - file_stream_.reset();
|
| + &URLFetcherFileWriter::CloseComplete, weak_factory_.GetWeakPtr()));
|
| + if (result == ERR_IO_PENDING) {
|
| + callback_ = callback;
|
| + return result;
|
| + }
|
| + file_stream_.reset();
|
| return result;
|
| }
|
| return OK;
|
| @@ -131,14 +159,6 @@ void URLFetcherFileWriter::DisownFile() {
|
| owns_file_ = false;
|
| }
|
|
|
| -void URLFetcherFileWriter::DidWrite(const CompletionCallback& callback,
|
| - int result) {
|
| - if (result < 0)
|
| - CloseAndDeleteFile();
|
| -
|
| - callback.Run(result);
|
| -}
|
| -
|
| void URLFetcherFileWriter::CloseAndDeleteFile() {
|
| if (!owns_file_)
|
| return;
|
| @@ -151,41 +171,35 @@ void URLFetcherFileWriter::CloseAndDeleteFile() {
|
| false /* recursive */));
|
| }
|
|
|
| -void URLFetcherFileWriter::DidCreateTempFile(const CompletionCallback& callback,
|
| - base::FilePath* temp_file_path,
|
| +void URLFetcherFileWriter::DidCreateTempFile(base::FilePath* temp_file_path,
|
| bool success) {
|
| if (!success) {
|
| - callback.Run(ERR_FILE_NOT_FOUND);
|
| + OnIOCompleted(ERR_FILE_NOT_FOUND);
|
| return;
|
| }
|
| file_path_ = *temp_file_path;
|
| - owns_file_ = true;
|
| const int result = file_stream_->Open(
|
| file_path_,
|
| - base::File::FLAG_WRITE | base::File::FLAG_ASYNC |
|
| - base::File::FLAG_OPEN,
|
| - base::Bind(&URLFetcherFileWriter::DidOpenFile,
|
| - weak_factory_.GetWeakPtr(),
|
| - callback));
|
| + base::File::FLAG_WRITE | base::File::FLAG_ASYNC | base::File::FLAG_OPEN,
|
| + base::Bind(&URLFetcherFileWriter::OnIOCompleted,
|
| + weak_factory_.GetWeakPtr()));
|
| if (result != ERR_IO_PENDING)
|
| - DidOpenFile(callback, result);
|
| + OnIOCompleted(result);
|
| }
|
|
|
| -void URLFetcherFileWriter::DidOpenFile(const CompletionCallback& callback,
|
| - int result) {
|
| - if (result == OK)
|
| - owns_file_ = true;
|
| - else
|
| +void URLFetcherFileWriter::OnIOCompleted(int result) {
|
| + if (result < OK)
|
| CloseAndDeleteFile();
|
|
|
| - callback.Run(result);
|
| + if (!callback_.is_null())
|
| + base::ResetAndReturn(&callback_).Run(result);
|
| }
|
|
|
| -void URLFetcherFileWriter::CloseComplete(const CompletionCallback& callback,
|
| - int result) {
|
| +void URLFetcherFileWriter::CloseComplete(int result) {
|
| // Destroy |file_stream_| whether or not the close succeeded.
|
| file_stream_.reset();
|
| - callback.Run(result);
|
| + if (!callback_.is_null())
|
| + base::ResetAndReturn(&callback_).Run(result);
|
| }
|
|
|
| } // namespace net
|
|
|