// Copyright 2016 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/log/file_net_log_observer.h"

#include <algorithm>
#include <memory>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/containers/queue.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/lock.h"
#include "base/task/post_task.h"
#include "base/values.h"
#include "net/log/net_log_capture_mode.h"
#include "net/log/net_log_entry.h"
#include "net/log/net_log_util.h"
#include "net/url_request/url_request_context.h"

namespace {

// Number of events that can build up in |write_queue_| before a task is posted
// to the file task runner to flush them to disk.
const int kNumWriteQueueEvents = 15;

// TODO(eroman): Should use something other than 10 for number of files?
const int kDefaultNumFiles = 10;

scoped_refptr<base::SequencedTaskRunner> CreateFileTaskRunner() {
  // The tasks posted to this sequenced task runner do synchronous File I/O for
  // the purposes of writing NetLog files.
  //
  // These intentionally block shutdown to ensure the log file has finished
  // being written.
  return base::CreateSequencedTaskRunnerWithTraits(
      {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
       base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
}

// Truncates a file, also reseting the seek position.
void TruncateFile(base::File* file) {
  if (!file->IsValid())
    return;
  file->Seek(base::File::FROM_BEGIN, 0);
  file->SetLength(0);
}

// Opens |path| in write mode.
base::File OpenFileForWrite(const base::FilePath& path) {
  base::File result(path,
                    base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
  LOG_IF(ERROR, !result.IsValid()) << "Failed opening: " << path.value();
  return result;
}

// Helper that writes data to a file. |file->IsValid()| may be false,
// in which case nothing will be written. Returns the number of bytes
// successfully written (may be less than input data in case of errors).
size_t WriteToFile(base::File* file,
                   base::StringPiece data1,
                   base::StringPiece data2 = base::StringPiece(),
                   base::StringPiece data3 = base::StringPiece()) {
  size_t bytes_written = 0;

  if (file->IsValid()) {
    // Append each of data1, data2 and data3.
    if (!data1.empty())
      bytes_written +=
          std::max(0, file->WriteAtCurrentPos(data1.data(), data1.size()));
    if (!data2.empty())
      bytes_written +=
          std::max(0, file->WriteAtCurrentPos(data2.data(), data2.size()));
    if (!data3.empty())
      bytes_written +=
          std::max(0, file->WriteAtCurrentPos(data3.data(), data3.size()));
  }

  return bytes_written;
}

// Copies all of the data at |source_path| and appends it to |destination_file|,
// then deletes |source_path|.
void AppendToFileThenDelete(const base::FilePath& source_path,
                            base::File* destination_file,
                            char* read_buffer,
                            size_t read_buffer_size) {
  base::ScopedFILE source_file(base::OpenFile(source_path, "rb"));
  if (!source_file)
    return;

  // Read |source_path|'s contents in chunks of read_buffer_size and append
  // to |destination_file|.
  size_t num_bytes_read;
  while ((num_bytes_read =
              fread(read_buffer, 1, read_buffer_size, source_file.get())) > 0) {
    WriteToFile(destination_file,
                base::StringPiece(read_buffer, num_bytes_read));
  }

  // Now that it has been copied, delete the source file.
  source_file.reset();
  base::DeleteFile(source_path, false);
}

base::FilePath SiblingInprogressDirectory(const base::FilePath& log_path) {
  return log_path.AddExtension(FILE_PATH_LITERAL(".inprogress"));
}

}  // namespace

namespace net {

// Used to store events to be written to file.
using EventQueue = base::queue<std::unique_ptr<std::string>>;

// WriteQueue receives events from FileNetLogObserver on the main thread and
// holds them in a queue until they are drained from the queue and written to
// file on the file task runner.
//
// WriteQueue contains the resources shared between the main thread and the
// file task runner. |lock_| must be acquired to read or write to |queue_| and
// |memory_|.
//
// WriteQueue is refcounted and should be destroyed once all events on the
// file task runner have finished executing.
class FileNetLogObserver::WriteQueue
    : public base::RefCountedThreadSafe<WriteQueue> {
 public:
  // |memory_max| indicates the maximum amount of memory that the virtual write
  // queue can use. If |memory_| exceeds |memory_max_|, the |queue_| of events
  // is overwritten.
  explicit WriteQueue(uint64_t memory_max);

  // Adds |event| to |queue_|. Also manages the size of |memory_|; if it
  // exceeds |memory_max_|, then old events are dropped from |queue_| without
  // being written to file.
  //
  // Returns the number of events in the |queue_|.
  size_t AddEntryToQueue(std::unique_ptr<std::string> event);

  // Swaps |queue_| with |local_queue|. |local_queue| should be empty, so that
  // |queue_| is emptied. Resets |memory_| to 0.
  void SwapQueue(EventQueue* local_queue);

 private:
  friend class base::RefCountedThreadSafe<WriteQueue>;

  ~WriteQueue();

  // Queue of events to be written, shared between main thread and file task
  // runner. Main thread adds events to the queue and the file task runner
  // drains them and writes the events to file.
  //
  // |lock_| must be acquired to read or write to this.
  EventQueue queue_;

  // Tracks how much memory is being used by the virtual write queue.
  // Incremented in AddEntryToQueue() when events are added to the
  // buffer, and decremented when SwapQueue() is called and the file task
  // runner's local queue is swapped with the shared write queue.
  //
  // |lock_| must be acquired to read or write to this.
  uint64_t memory_;

  // Indicates the maximum amount of memory that the |queue_| is allowed to
  // use.
  const uint64_t memory_max_;

  // Protects access to |queue_| and |memory_|.
  //
  // A lock is necessary because |queue_| and |memory_| are shared between the
  // file task runner and the main thread. NetLog's lock protects OnAddEntry(),
  // which calls AddEntryToQueue(), but it does not protect access to the
  // observer's member variables. Thus, a race condition exists if a thread is
  // calling OnAddEntry() at the same time that the file task runner is
  // accessing |memory_| and |queue_| to write events to file. The |queue_| and
  // |memory_| counter are necessary to bound the amount of memory that is used
  // for the queue in the event that the file task runner lags significantly
  // behind the main thread in writing events to file.
  base::Lock lock_;

  DISALLOW_COPY_AND_ASSIGN(WriteQueue);
};

// FileWriter is responsible for draining events from a WriteQueue and writing
// them to disk. FileWriter can be constructed on any thread, and
// afterwards is only accessed on the file task runner.
class FileNetLogObserver::FileWriter {
 public:
  // If max_event_file_size == kNoLimit, then no limit is enforced.
  FileWriter(const base::FilePath& log_path,
             const base::FilePath& inprogress_dir_path,
             base::Optional<base::File> pre_existing_log_file,
             uint64_t max_event_file_size,
             size_t total_num_event_files,
             scoped_refptr<base::SequencedTaskRunner> task_runner);

  ~FileWriter();

  // Writes |constants_value| to disk and opens the events array (closed in
  // Stop()).
  void Initialize(std::unique_ptr<base::Value> constants_value);

  // Closes the events array opened in Initialize() and writes |polled_data| to
  // disk. If |polled_data| cannot be converted to proper JSON, then it
  // is ignored.
  void Stop(std::unique_ptr<base::Value> polled_data);

  // Drains |queue_| from WriteQueue into a local file queue and writes the
  // events in the queue to disk.
  void Flush(scoped_refptr<WriteQueue> write_queue);

  // Deletes all netlog files. It is not valid to call any method of
  // FileNetLogObserver after DeleteAllFiles().
  void DeleteAllFiles();

  void FlushThenStop(scoped_refptr<WriteQueue> write_queue,
                     std::unique_ptr<base::Value> polled_data);

 private:
  // Returns true if there is no file size bound to enforce.
  //
  // When operating in unbounded mode, the implementation is optimized to stream
  // writes to a single file, rather than chunking them across temporary event
  // files.
  bool IsUnbounded() const;
  bool IsBounded() const;

  // Increments |current_event_file_number_|, and updates all state relating to
  // the current event file (open file handle, num bytes written, current file
  // number).
  void IncrementCurrentEventFile();

  // Returns the path to the event file having |index|. This looks like
  // "LOGDIR/event_file_<index>.json".
  base::FilePath GetEventFilePath(size_t index) const;

  // Gets the file path where constants are saved at the start of
  // logging. This looks like "LOGDIR/constants.json".
  base::FilePath GetConstantsFilePath() const;

  // Gets the file path where the final data is written at the end of logging.
  // This looks like "LOGDIR/end_netlog.json".
  base::FilePath GetClosingFilePath() const;

  // Returns the corresponding index for |file_number|. File "numbers" are a
  // monotonically increasing identifier that start at 1 (a value of zero means
  // it is uninitialized), whereas the file "index" is a bounded value that
  // wraps and identifies the file path to use.
  //
  // Keeping track of the current number rather than index makes it a bit easier
  // to assemble a file at the end, since it is unambiguous which paths have
  // been used/re-used.
  size_t FileNumberToIndex(size_t file_number) const;

  // Writes |constants_value| to a file.
  static void WriteConstantsToFile(std::unique_ptr<base::Value> constants_value,
                                   base::File* file);

  // Writes |polled_data| to a file.
  static void WritePolledDataToFile(std::unique_ptr<base::Value> polled_data,
                                    base::File* file);

  // If any events were written (wrote_event_bytes_), rewinds |file| by 2 bytes
  // in order to overwrite the trailing ",\n" that was written by the last event
  // line.
  void RewindIfWroteEventBytes(base::File* file) const;

  // Concatenates all the log files to assemble the final
  // |final_log_file_|. This single "stitched" file is what other
  // log ingesting tools expect.
  void StitchFinalLogFile();

  // Creates the .inprogress directory used by bounded mode.
  void CreateInprogressDirectory();

  // The file the final netlog is written to. In bounded mode this is mostly
  // written to once logging is stopped, whereas in unbounded mode events will
  // be directly written to it.
  base::File final_log_file_;

  // If non-empty, this is the path to |final_log_file_| created and owned
  // by FileWriter itself (rather than passed in to Create*PreExisting
  // methods of FileNetLogObserver).
  const base::FilePath final_log_path_;

  // Path to a (temporary) directory where files are written in bounded mode.
  // When logging is stopped these files are stitched together and written
  // to the final log path.
  const base::FilePath inprogress_dir_path_;

  // Holds the numbered events file where data is currently being written to.
  // The file path of this file is GetEventFilePath(current_event_file_number_).
  // The file may be !IsValid() if an error previously occurred opening the
  // file, or logging has been stopped.
  base::File current_event_file_;
  uint64_t current_event_file_size_;

  // Indicates the total number of netlog event files allowed.
  // (The files GetConstantsFilePath() and GetClosingFilePath() do
  // not count against the total.)
  const size_t total_num_event_files_;

  // Counter for the events file currently being written into. See
  // FileNumberToIndex() for an explanation of what "number" vs "index" mean.
  size_t current_event_file_number_;

  // Indicates the maximum size of each individual events file. May be kNoLimit
  // to indicate that it can grow arbitrarily large.
  const uint64_t max_event_file_size_;

  // Whether any bytes were written for events. This is used to properly format
  // JSON (events list shouldn't end with a comma).
  bool wrote_event_bytes_;

  // Task runner for doing file operations.
  const scoped_refptr<base::SequencedTaskRunner> task_runner_;

  DISALLOW_COPY_AND_ASSIGN(FileWriter);
};

std::unique_ptr<FileNetLogObserver> FileNetLogObserver::CreateBounded(
    const base::FilePath& log_path,
    uint64_t max_total_size,
    std::unique_ptr<base::Value> constants) {
  return CreateInternal(log_path, SiblingInprogressDirectory(log_path),
                        base::nullopt, max_total_size, kDefaultNumFiles,
                        std::move(constants));
}

std::unique_ptr<FileNetLogObserver> FileNetLogObserver::CreateUnbounded(
    const base::FilePath& log_path,
    std::unique_ptr<base::Value> constants) {
  return CreateInternal(log_path, base::FilePath(), base::nullopt, kNoLimit,
                        kDefaultNumFiles, std::move(constants));
}

std::unique_ptr<FileNetLogObserver>
FileNetLogObserver::CreateBoundedPreExisting(
    const base::FilePath& inprogress_dir_path,
    base::File output_file,
    uint64_t max_total_size,
    std::unique_ptr<base::Value> constants) {
  return CreateInternal(base::FilePath(), inprogress_dir_path,
                        base::make_optional<base::File>(std::move(output_file)),
                        max_total_size, kDefaultNumFiles, std::move(constants));
}

std::unique_ptr<FileNetLogObserver>
FileNetLogObserver::CreateUnboundedPreExisting(
    base::File output_file,
    std::unique_ptr<base::Value> constants) {
  return CreateInternal(base::FilePath(), base::FilePath(),
                        base::make_optional<base::File>(std::move(output_file)),
                        kNoLimit, kDefaultNumFiles, std::move(constants));
}

FileNetLogObserver::~FileNetLogObserver() {
  if (net_log()) {
    // StopObserving was not called.
    net_log()->RemoveObserver(this);
    file_task_runner_->PostTask(
        FROM_HERE, base::Bind(&FileNetLogObserver::FileWriter::DeleteAllFiles,
                              base::Unretained(file_writer_.get())));
  }
  file_task_runner_->DeleteSoon(FROM_HERE, file_writer_.release());
}

void FileNetLogObserver::StartObserving(NetLog* net_log,
                                        NetLogCaptureMode capture_mode) {
  net_log->AddObserver(this, capture_mode);
}

void FileNetLogObserver::StopObserving(std::unique_ptr<base::Value> polled_data,
                                       base::OnceClosure optional_callback) {
  net_log()->RemoveObserver(this);

  base::OnceClosure bound_flush_then_stop =
      base::Bind(&FileNetLogObserver::FileWriter::FlushThenStop,
                 base::Unretained(file_writer_.get()), write_queue_,
                 base::Passed(&polled_data));

  // Note that PostTaskAndReply() requires a non-null closure.
  if (!optional_callback.is_null()) {
    file_task_runner_->PostTaskAndReply(FROM_HERE,
                                        std::move(bound_flush_then_stop),
                                        std::move(optional_callback));
  } else {
    file_task_runner_->PostTask(FROM_HERE, std::move(bound_flush_then_stop));
  }
}

void FileNetLogObserver::OnAddEntry(const NetLogEntry& entry) {
  std::unique_ptr<std::string> json(new std::string);

  // If |entry| cannot be converted to proper JSON, ignore it.
  if (!base::JSONWriter::Write(*entry.ToValue(), json.get()))
    return;

  size_t queue_size = write_queue_->AddEntryToQueue(std::move(json));

  // If events build up in |write_queue_|, trigger the file task runner to drain
  // the queue. Because only 1 item is added to the queue at a time, if
  // queue_size > kNumWriteQueueEvents a task has already been posted, or will
  // be posted.
  if (queue_size == kNumWriteQueueEvents) {
    file_task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&FileNetLogObserver::FileWriter::Flush,
                   base::Unretained(file_writer_.get()), write_queue_));
  }
}

std::unique_ptr<FileNetLogObserver> FileNetLogObserver::CreateBoundedForTests(
    const base::FilePath& log_path,
    uint64_t max_total_size,
    size_t total_num_event_files,
    std::unique_ptr<base::Value> constants) {
  return CreateInternal(log_path, SiblingInprogressDirectory(log_path),
                        base::nullopt, max_total_size, total_num_event_files,
                        std::move(constants));
}

std::unique_ptr<FileNetLogObserver> FileNetLogObserver::CreateInternal(
    const base::FilePath& log_path,
    const base::FilePath& inprogress_dir_path,
    base::Optional<base::File> pre_existing_log_file,
    uint64_t max_total_size,
    size_t total_num_event_files,
    std::unique_ptr<base::Value> constants) {
  DCHECK_GT(total_num_event_files, 0u);

  scoped_refptr<base::SequencedTaskRunner> file_task_runner =
      CreateFileTaskRunner();

  const uint64_t max_event_file_size =
      max_total_size == kNoLimit ? kNoLimit
                                 : max_total_size / total_num_event_files;

  // The FileWriter uses a soft limit to write events to file that allows
  // the size of the file to exceed the limit, but the WriteQueue uses a hard
  // limit which the size of |WriteQueue::queue_| cannot exceed. Thus, the
  // FileWriter may write more events to file than can be contained by
  // the WriteQueue if they have the same size limit. The maximum size of the
  // WriteQueue is doubled to allow |WriteQueue::queue_| to hold enough events
  // for the FileWriter to fill all files. As long as all events have
  // sizes <= the size of an individual event file, the discrepancy between the
  // hard limit and the soft limit will not cause an issue.
  // TODO(dconnol): Handle the case when the WriteQueue  still doesn't
  // contain enough events to fill all files, because of very large events
  // relative to file size.
  std::unique_ptr<FileWriter> file_writer(new FileWriter(
      log_path, inprogress_dir_path, std::move(pre_existing_log_file),
      max_event_file_size, total_num_event_files, file_task_runner));

  scoped_refptr<WriteQueue> write_queue(new WriteQueue(max_total_size * 2));

  return std::unique_ptr<FileNetLogObserver>(
      new FileNetLogObserver(file_task_runner, std::move(file_writer),
                             std::move(write_queue), std::move(constants)));
}

FileNetLogObserver::FileNetLogObserver(
    scoped_refptr<base::SequencedTaskRunner> file_task_runner,
    std::unique_ptr<FileWriter> file_writer,
    scoped_refptr<WriteQueue> write_queue,
    std::unique_ptr<base::Value> constants)
    : file_task_runner_(std::move(file_task_runner)),
      write_queue_(std::move(write_queue)),
      file_writer_(std::move(file_writer)) {
  if (!constants)
    constants = GetNetConstants();
  file_task_runner_->PostTask(
      FROM_HERE, base::Bind(&FileNetLogObserver::FileWriter::Initialize,
                            base::Unretained(file_writer_.get()),
                            base::Passed(&constants)));
}

FileNetLogObserver::WriteQueue::WriteQueue(uint64_t memory_max)
    : memory_(0), memory_max_(memory_max) {}

size_t FileNetLogObserver::WriteQueue::AddEntryToQueue(
    std::unique_ptr<std::string> event) {
  base::AutoLock lock(lock_);

  memory_ += event->size();
  queue_.push(std::move(event));

  while (memory_ > memory_max_ && !queue_.empty()) {
    // Delete oldest events in the queue.
    DCHECK(queue_.front());
    memory_ -= queue_.front()->size();
    queue_.pop();
  }

  return queue_.size();
}

void FileNetLogObserver::WriteQueue::SwapQueue(EventQueue* local_queue) {
  DCHECK(local_queue->empty());
  base::AutoLock lock(lock_);
  queue_.swap(*local_queue);
  memory_ = 0;
}

FileNetLogObserver::WriteQueue::~WriteQueue() = default;

FileNetLogObserver::FileWriter::FileWriter(
    const base::FilePath& log_path,
    const base::FilePath& inprogress_dir_path,
    base::Optional<base::File> pre_existing_log_file,
    uint64_t max_event_file_size,
    size_t total_num_event_files,
    scoped_refptr<base::SequencedTaskRunner> task_runner)
    : final_log_path_(log_path),
      inprogress_dir_path_(inprogress_dir_path),
      total_num_event_files_(total_num_event_files),
      current_event_file_number_(0),
      max_event_file_size_(max_event_file_size),
      wrote_event_bytes_(false),
      task_runner_(std::move(task_runner)) {
  DCHECK_EQ(pre_existing_log_file.has_value(), log_path.empty());
  DCHECK_EQ(IsBounded(), !inprogress_dir_path.empty());

  if (pre_existing_log_file.has_value()) {
    // pre_existing_log_file.IsValid() being false is fine.
    final_log_file_ = std::move(pre_existing_log_file.value());
  }
}

FileNetLogObserver::FileWriter::~FileWriter() = default;

void FileNetLogObserver::FileWriter::Initialize(
    std::unique_ptr<base::Value> constants_value) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());

  // Open the final log file, and keep it open for the duration of logging (even
  // in bounded mode).
  if (!final_log_path_.empty())
    final_log_file_ = OpenFileForWrite(final_log_path_);
  else
    TruncateFile(&final_log_file_);

  if (IsBounded()) {
    CreateInprogressDirectory();
    base::File constants_file = OpenFileForWrite(GetConstantsFilePath());
    WriteConstantsToFile(std::move(constants_value), &constants_file);
  } else {
    WriteConstantsToFile(std::move(constants_value), &final_log_file_);
  }
}

void FileNetLogObserver::FileWriter::Stop(
    std::unique_ptr<base::Value> polled_data) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());

  // Write out the polled data.
  if (IsBounded()) {
    base::File closing_file = OpenFileForWrite(GetClosingFilePath());
    WritePolledDataToFile(std::move(polled_data), &closing_file);
  } else {
    RewindIfWroteEventBytes(&final_log_file_);
    WritePolledDataToFile(std::move(polled_data), &final_log_file_);
  }

  // If operating in bounded mode, the events were written to separate files
  // within |inprogress_dir_path_|. Assemble them into the final destination
  // file.
  if (IsBounded())
    StitchFinalLogFile();

  // Ensure the final log file has been flushed.
  final_log_file_.Close();
}

void FileNetLogObserver::FileWriter::Flush(
    scoped_refptr<FileNetLogObserver::WriteQueue> write_queue) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());

  EventQueue local_file_queue;
  write_queue->SwapQueue(&local_file_queue);

  while (!local_file_queue.empty()) {
    base::File* output_file;

    // If in bounded mode, output events to the current event file. Otherwise
    // output events to the final log path.
    if (IsBounded()) {
      if (current_event_file_number_ == 0 ||
          current_event_file_size_ >= max_event_file_size_) {
        IncrementCurrentEventFile();
      }
      output_file = &current_event_file_;
    } else {
      output_file = &final_log_file_;
    }

    size_t bytes_written =
        WriteToFile(output_file, *local_file_queue.front(), ",\n");

    wrote_event_bytes_ |= bytes_written > 0;

    // Keep track of the filesize for current event file when in bounded mode.
    if (IsBounded())
      current_event_file_size_ += bytes_written;

    local_file_queue.pop();
  }
}

void FileNetLogObserver::FileWriter::DeleteAllFiles() {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());

  final_log_file_.Close();

  if (IsBounded()) {
    current_event_file_.Close();
    base::DeleteFile(inprogress_dir_path_, true);
  }

  // Only delete |final_log_file_| if it was created internally.
  // (If it was provided as a base::File by the caller, don't try to delete it).
  if (!final_log_path_.empty())
    base::DeleteFile(final_log_path_, false);
}

void FileNetLogObserver::FileWriter::FlushThenStop(
    scoped_refptr<FileNetLogObserver::WriteQueue> write_queue,
    std::unique_ptr<base::Value> polled_data) {
  Flush(write_queue);
  Stop(std::move(polled_data));
}

bool FileNetLogObserver::FileWriter::IsUnbounded() const {
  return max_event_file_size_ == kNoLimit;
}

bool FileNetLogObserver::FileWriter::IsBounded() const {
  return !IsUnbounded();
}

void FileNetLogObserver::FileWriter::IncrementCurrentEventFile() {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  DCHECK(IsBounded());

  current_event_file_number_++;
  current_event_file_ = OpenFileForWrite(
      GetEventFilePath(FileNumberToIndex(current_event_file_number_)));
  current_event_file_size_ = 0;
}

base::FilePath FileNetLogObserver::FileWriter::GetEventFilePath(
    size_t index) const {
  DCHECK_LT(index, total_num_event_files_);
  DCHECK(IsBounded());
  return inprogress_dir_path_.AppendASCII(
      "event_file_" + base::NumberToString(index) + ".json");
}

base::FilePath FileNetLogObserver::FileWriter::GetConstantsFilePath() const {
  return inprogress_dir_path_.AppendASCII("constants.json");
}

base::FilePath FileNetLogObserver::FileWriter::GetClosingFilePath() const {
  return inprogress_dir_path_.AppendASCII("end_netlog.json");
}

size_t FileNetLogObserver::FileWriter::FileNumberToIndex(
    size_t file_number) const {
  DCHECK_GT(file_number, 0u);
  // Note that "file numbers" start at 1 not 0.
  return (file_number - 1) % total_num_event_files_;
}

void FileNetLogObserver::FileWriter::WriteConstantsToFile(
    std::unique_ptr<base::Value> constants_value,
    base::File* file) {
  // Print constants to file and open events array.
  std::string json;

  // It should always be possible to convert constants to JSON.
  if (!base::JSONWriter::Write(*constants_value, &json))
    DCHECK(false);
  WriteToFile(file, "{\"constants\":", json, ",\n\"events\": [\n");
}

void FileNetLogObserver::FileWriter::WritePolledDataToFile(
    std::unique_ptr<base::Value> polled_data,
    base::File* file) {
  // Close the events array.
  WriteToFile(file, "]");

  // Write the polled data (if any).
  if (polled_data) {
    std::string polled_data_json;
    base::JSONWriter::Write(*polled_data, &polled_data_json);
    if (!polled_data_json.empty())
      WriteToFile(file, ",\n\"polledData\": ", polled_data_json, "\n");
  }

  // Close the log.
  WriteToFile(file, "}\n");
}

void FileNetLogObserver::FileWriter::RewindIfWroteEventBytes(
    base::File* file) const {
  if (file->IsValid() && wrote_event_bytes_) {
    // To be valid JSON the events array should not end with a comma. If events
    // were written though, they will have been terminated with "\n," so strip
    // it before closing the events array.
    file->Seek(base::File::FROM_END, -2);
  }
}

void FileNetLogObserver::FileWriter::StitchFinalLogFile() {
  // Make sure all the events files are flushed (as will read them next).
  current_event_file_.Close();

  // Allocate a 64K buffer used for reading the files. At most kReadBufferSize
  // bytes will be in memory at a time.
  const size_t kReadBufferSize = 1 << 16;  // 64KiB
  std::unique_ptr<char[]> read_buffer(new char[kReadBufferSize]);

  if (final_log_file_.IsValid()) {
    // Truncate the final log file.
    TruncateFile(&final_log_file_);

    // Append the constants file.
    AppendToFileThenDelete(GetConstantsFilePath(), &final_log_file_,
                           read_buffer.get(), kReadBufferSize);

    // Iterate over the events files, from oldest to most recent, and append
    // them to the final destination. Note that "file numbers" start at 1 not 0.
    size_t end_filenumber = current_event_file_number_ + 1;
    size_t begin_filenumber =
        current_event_file_number_ <= total_num_event_files_
            ? 1
            : end_filenumber - total_num_event_files_;
    for (size_t filenumber = begin_filenumber; filenumber < end_filenumber;
         ++filenumber) {
      AppendToFileThenDelete(GetEventFilePath(FileNumberToIndex(filenumber)),
                             &final_log_file_, read_buffer.get(),
                             kReadBufferSize);
    }

    // Account for the final event line ending in a ",\n". Strip it to form
    // valid JSON.
    RewindIfWroteEventBytes(&final_log_file_);

    // Append the polled data.
    AppendToFileThenDelete(GetClosingFilePath(), &final_log_file_,
                           read_buffer.get(), kReadBufferSize);
  }

  // Delete the inprogress directory (and anything that may still be left inside
  // it).
  base::DeleteFile(inprogress_dir_path_, true);
}

void FileNetLogObserver::FileWriter::CreateInprogressDirectory() {
  DCHECK(IsBounded());

  // If an output file couldn't be created, either creation of intermediate
  // files will also fail (if they're in a sibling directory), or are they are
  // hidden somewhere the user would be unlikely to find them, so there is
  // little reason to progress.
  if (!final_log_file_.IsValid())
    return;

  if (!base::CreateDirectory(inprogress_dir_path_)) {
    LOG(WARNING) << "Failed creating directory: "
                 << inprogress_dir_path_.value();
    return;
  }

  // It is OK if the path is wrong due to encoding - this is really just a
  // convenience display for the user in understanding what the file means.
  std::string in_progress_path = inprogress_dir_path_.AsUTF8Unsafe();

  // Since |final_log_file_| will not be written to until the very end, leave
  // some data in it explaining that the real data is currently in the
  // .inprogress directory. This ordinarily won't be visible (overwritten when
  // stopping) however if logging does not end gracefully the comments are
  // useful for recovery.
  WriteToFile(
      &final_log_file_, "Logging is in progress writing data to:\n    ",
      in_progress_path,
      "\n\n"
      "That data will be stitched into a single file (this one) once logging\n"
      "has stopped.\n"
      "\n"
      "If logging was interrupted, you can stitch a NetLog file out of the\n"
      ".inprogress directory manually using:\n"
      "\n"
      "https://chromium.googlesource.com/chromium/src/+/master/net/tools/"
      "stitch_net_log_files.py\n");
}

}  // namespace net
