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

#if defined(STARBOARD)
URLFetcherLargeStringWriter* URLFetcherResponseWriter::AsLargeStringWriter() {
  return NULL;
}
#endif

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;
}

#if defined(STARBOARD)
URLFetcherLargeStringWriter::URLFetcherLargeStringWriter() = default;

URLFetcherLargeStringWriter::~URLFetcherLargeStringWriter() = default;

int URLFetcherLargeStringWriter::Initialize(CompletionOnceCallback callback) {
  data_.clear();
  return OK;
}

void URLFetcherLargeStringWriter::OnResponseStarted(int64_t content_length) {
  data_.reserve(content_length);
}

void URLFetcherLargeStringWriter::GetAndResetData(std::string* data) {
  CHECK(data != nullptr);

  // This implementation is copied from
  // cobalt::loader::URLFetcherStringWriter::GetAndResetData().
  std::string empty;
  data->swap(empty);
  data_.swap(*data);
}

int URLFetcherLargeStringWriter::Write(IOBuffer* buffer,
                                       int num_bytes,
                                       CompletionOnceCallback callback) {
  data_.append(buffer->data(), num_bytes);
  return num_bytes;
}

int URLFetcherLargeStringWriter::Finish(int net_error,
                                        CompletionOnceCallback callback) {
  // Do nothing.
  return OK;
}

URLFetcherLargeStringWriter*
    URLFetcherLargeStringWriter::AsLargeStringWriter() {
  return this;
}
#endif

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
