// Copyright (c) 2012 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_request_file_dir_job.h"

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "net/base/directory_listing.h"
#include "net/base/io_buffer.h"
#include "net/url_request/url_request_status.h"
#include "url/gurl.h"

#if defined(OS_POSIX) || defined(OS_FUCHSIA)
#include <sys/stat.h>
#endif

namespace net {

URLRequestFileDirJob::URLRequestFileDirJob(URLRequest* request,
                                           NetworkDelegate* network_delegate,
                                           const base::FilePath& dir_path)
    : URLRequestJob(request, network_delegate),
      lister_(dir_path, this),
      dir_path_(dir_path),
      canceled_(false),
      list_complete_(false),
      wrote_header_(false),
      read_pending_(false),
      read_buffer_length_(0),
      weak_factory_(this) {}

void URLRequestFileDirJob::StartAsync() {
  base::PostTaskWithTraitsAndReplyWithResult(
      FROM_HERE,
      {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
      base::Bind(&base::MakeAbsoluteFilePath, dir_path_),
      base::Bind(&URLRequestFileDirJob::DidMakeAbsolutePath,
                 weak_factory_.GetWeakPtr()));
}

void URLRequestFileDirJob::Start() {
  // Start reading asynchronously so that all error reporting and data
  // callbacks happen as they would for network requests.
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::Bind(&URLRequestFileDirJob::StartAsync,
                            weak_factory_.GetWeakPtr()));
}

void URLRequestFileDirJob::Kill() {
  if (canceled_)
    return;

  canceled_ = true;

  if (!list_complete_)
    lister_.Cancel();

  URLRequestJob::Kill();

  weak_factory_.InvalidateWeakPtrs();
}

int URLRequestFileDirJob::ReadRawData(IOBuffer* buf, int buf_size) {
  int result = ReadBuffer(buf->data(), buf_size);
  if (result == ERR_IO_PENDING) {
    // We are waiting for more data
    read_pending_ = true;
    read_buffer_ = buf;
    read_buffer_length_ = buf_size;
    return ERR_IO_PENDING;
  }

  return result;
}

bool URLRequestFileDirJob::GetMimeType(std::string* mime_type) const {
  *mime_type = "text/html";
  return true;
}

bool URLRequestFileDirJob::GetCharset(std::string* charset) {
  // All the filenames are converted to UTF-8 before being added.
  *charset = "utf-8";
  return true;
}

void URLRequestFileDirJob::OnListFile(
    const DirectoryLister::DirectoryListerData& data) {
  // We wait to write out the header until we get the first file, so that we
  // can catch errors from DirectoryLister and show an error page.
  if (!wrote_header_) {
    wrote_header_ = true;

#if defined(OS_WIN)
    const base::string16& title = dir_path_.value();
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
    // TODO(jungshik): Add SysNativeMBToUTF16 to sys_string_conversions.
    // On Mac, need to add NFKC->NFC conversion either here or in file_path.
    // On Linux, the file system encoding is not defined, but we assume that
    // SysNativeMBToWide takes care of it at least for now. We can try something
    // more sophisticated if necessary later.
    const base::string16& title = base::WideToUTF16(
        base::SysNativeMBToWide(dir_path_.value()));
#endif
    data_.append(GetDirectoryListingHeader(title));

    // If this isn't top level directory, add a link to the parent directory.
    // To figure this out, first normalize |dir_path_| by stripping it of
    // trailing separators. Then compare the resulting |stripped_dir_path| to
    // its DirName(). For the top level directory, e.g. "/" or "c:\\", the
    // normalized path is equal to its DirName().
    base::FilePath stripped_dir_path = dir_path_.StripTrailingSeparators();
    if (stripped_dir_path != stripped_dir_path.DirName()) {
      data_.append(GetParentDirectoryLink());
    }
  }

  // Skip the current and parent directory entries in the listing.
  // GetParentDirectoryLink() takes care of them.
  base::FilePath filename = data.info.GetName();
  if (filename.value() != base::FilePath::kCurrentDirectory &&
      filename.value() != base::FilePath::kParentDirectory) {
#if defined(OS_WIN)
    std::string raw_bytes;  // Empty on Windows means UTF-8 encoded name.
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
    // TODO(jungshik): The same issue as for the directory name.
    const std::string& raw_bytes = filename.value();
#endif
    data_.append(GetDirectoryListingEntry(
        filename.LossyDisplayName(), raw_bytes, data.info.IsDirectory(),
        data.info.GetSize(), data.info.GetLastModifiedTime()));
  }

  // TODO(darin): coalesce more?
  CompleteRead(OK);
}

void URLRequestFileDirJob::OnListDone(int error) {
  DCHECK(!canceled_);
  DCHECK_LE(error, OK);

  list_complete_ = true;
  list_complete_result_ = static_cast<Error>(error);
  CompleteRead(list_complete_result_);
}

URLRequestFileDirJob::~URLRequestFileDirJob() = default;

void URLRequestFileDirJob::DidMakeAbsolutePath(
    const base::FilePath& absolute_path) {
  if (network_delegate() && !network_delegate()->CanAccessFile(
                                *request(), dir_path_, absolute_path)) {
    NotifyStartError(URLRequestStatus::FromError(ERR_ACCESS_DENIED));
    return;
  }

  lister_.Start();
  NotifyHeadersComplete();
}

void URLRequestFileDirJob::CompleteRead(Error error) {
  DCHECK_LE(error, OK);
  DCHECK_NE(error, ERR_IO_PENDING);

  // Do nothing if there is no read pending.
  if (!read_pending_)
    return;

  int result = error;
  if (error == OK) {
    result = ReadBuffer(read_buffer_->data(), read_buffer_length_);
    if (result >= 0) {
      // We completed the read, so reset the read buffer.
      read_buffer_ = nullptr;
      read_buffer_length_ = 0;
    } else {
      NOTREACHED();
      // TODO: Better error code.
      result = ERR_FAILED;
    }
  }

  read_pending_ = false;
  ReadRawDataComplete(result);
}

int URLRequestFileDirJob::ReadBuffer(char* buf, int buf_size) {
  int count = std::min(buf_size, static_cast<int>(data_.size()));
  if (count) {
    memcpy(buf, &data_[0], count);
    data_.erase(0, count);
    return count;
  }
  if (list_complete_) {
    // EOF
    return list_complete_result_;
  }
  return ERR_IO_PENDING;
}

}  // namespace net
