mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-28 08:16:09 +03:00
206 lines
6.0 KiB
C++
206 lines
6.0 KiB
C++
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "net/url_request/url_fetcher_response_writer.h"
|
|
|
|
#include <utility>
|
|
|
|
#include "base/callback_helpers.h"
|
|
#include "base/files/file_util.h"
|
|
#include "base/location.h"
|
|
#include "base/sequenced_task_runner.h"
|
|
#include "base/task_runner_util.h"
|
|
#include "net/base/file_stream.h"
|
|
#include "net/base/io_buffer.h"
|
|
#include "net/base/net_errors.h"
|
|
|
|
namespace net {
|
|
|
|
URLFetcherStringWriter* URLFetcherResponseWriter::AsStringWriter() {
|
|
return NULL;
|
|
}
|
|
|
|
URLFetcherFileWriter* URLFetcherResponseWriter::AsFileWriter() {
|
|
return NULL;
|
|
}
|
|
|
|
URLFetcherStringWriter::URLFetcherStringWriter() = default;
|
|
|
|
URLFetcherStringWriter::~URLFetcherStringWriter() = default;
|
|
|
|
int URLFetcherStringWriter::Initialize(CompletionOnceCallback callback) {
|
|
data_.clear();
|
|
return OK;
|
|
}
|
|
|
|
int URLFetcherStringWriter::Write(IOBuffer* buffer,
|
|
int num_bytes,
|
|
CompletionOnceCallback callback) {
|
|
data_.append(buffer->data(), num_bytes);
|
|
return num_bytes;
|
|
}
|
|
|
|
int URLFetcherStringWriter::Finish(int net_error,
|
|
CompletionOnceCallback callback) {
|
|
// Do nothing.
|
|
return OK;
|
|
}
|
|
|
|
URLFetcherStringWriter* URLFetcherStringWriter::AsStringWriter() {
|
|
return this;
|
|
}
|
|
|
|
URLFetcherFileWriter::URLFetcherFileWriter(
|
|
scoped_refptr<base::SequencedTaskRunner> file_task_runner,
|
|
const base::FilePath& file_path)
|
|
: file_task_runner_(file_task_runner),
|
|
file_path_(file_path),
|
|
owns_file_(false),
|
|
weak_factory_(this) {
|
|
DCHECK(file_task_runner_.get());
|
|
}
|
|
|
|
URLFetcherFileWriter::~URLFetcherFileWriter() {
|
|
CloseAndDeleteFile();
|
|
}
|
|
|
|
int URLFetcherFileWriter::Initialize(CompletionOnceCallback 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(
|
|
file_task_runner_.get(),
|
|
FROM_HERE,
|
|
base::Bind(&base::CreateTemporaryFile, temp_file_path),
|
|
base::Bind(&URLFetcherFileWriter::DidCreateTempFile,
|
|
weak_factory_.GetWeakPtr(),
|
|
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::OnIOCompleted,
|
|
weak_factory_.GetWeakPtr()));
|
|
DCHECK_NE(OK, result);
|
|
}
|
|
|
|
if (result == ERR_IO_PENDING) {
|
|
callback_ = std::move(callback);
|
|
return result;
|
|
}
|
|
if (result < 0)
|
|
CloseAndDeleteFile();
|
|
return result;
|
|
}
|
|
|
|
int URLFetcherFileWriter::Write(IOBuffer* buffer,
|
|
int num_bytes,
|
|
CompletionOnceCallback callback) {
|
|
DCHECK(file_stream_);
|
|
DCHECK(owns_file_);
|
|
DCHECK(!callback_);
|
|
|
|
int result = file_stream_->Write(
|
|
buffer, num_bytes, base::Bind(&URLFetcherFileWriter::OnIOCompleted,
|
|
weak_factory_.GetWeakPtr()));
|
|
if (result == ERR_IO_PENDING) {
|
|
callback_ = std::move(callback);
|
|
return result;
|
|
}
|
|
if (result < 0)
|
|
CloseAndDeleteFile();
|
|
return result;
|
|
}
|
|
|
|
int URLFetcherFileWriter::Finish(int net_error,
|
|
CompletionOnceCallback 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()));
|
|
if (result == ERR_IO_PENDING) {
|
|
callback_ = std::move(callback);
|
|
return result;
|
|
}
|
|
file_stream_.reset();
|
|
return result;
|
|
}
|
|
return OK;
|
|
}
|
|
|
|
URLFetcherFileWriter* URLFetcherFileWriter::AsFileWriter() {
|
|
return this;
|
|
}
|
|
|
|
void URLFetcherFileWriter::DisownFile() {
|
|
// Disowning is done by the delegate's OnURLFetchComplete method.
|
|
// The file should be closed by the time that method is called.
|
|
DCHECK(!file_stream_);
|
|
|
|
owns_file_ = false;
|
|
}
|
|
|
|
void URLFetcherFileWriter::CloseAndDeleteFile() {
|
|
if (!owns_file_)
|
|
return;
|
|
|
|
file_stream_.reset();
|
|
DisownFile();
|
|
file_task_runner_->PostTask(FROM_HERE,
|
|
base::Bind(base::IgnoreResult(&base::DeleteFile),
|
|
file_path_,
|
|
false /* recursive */));
|
|
}
|
|
|
|
void URLFetcherFileWriter::DidCreateTempFile(base::FilePath* temp_file_path,
|
|
bool success) {
|
|
if (!success) {
|
|
OnIOCompleted(ERR_FILE_NOT_FOUND);
|
|
return;
|
|
}
|
|
file_path_ = *temp_file_path;
|
|
const int result = file_stream_->Open(
|
|
file_path_,
|
|
base::File::FLAG_WRITE | base::File::FLAG_ASYNC | base::File::FLAG_OPEN,
|
|
base::Bind(&URLFetcherFileWriter::OnIOCompleted,
|
|
weak_factory_.GetWeakPtr()));
|
|
if (result != ERR_IO_PENDING)
|
|
OnIOCompleted(result);
|
|
}
|
|
|
|
void URLFetcherFileWriter::OnIOCompleted(int result) {
|
|
if (result < OK)
|
|
CloseAndDeleteFile();
|
|
|
|
if (!callback_.is_null())
|
|
base::ResetAndReturn(&callback_).Run(result);
|
|
}
|
|
|
|
void URLFetcherFileWriter::CloseComplete(int result) {
|
|
// Destroy |file_stream_| whether or not the close succeeded.
|
|
file_stream_.reset();
|
|
if (!callback_.is_null())
|
|
base::ResetAndReturn(&callback_).Run(result);
|
|
}
|
|
|
|
} // namespace net
|