// 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
