// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "client/crash_report_database.h"

#include <windows.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <wchar.h>

#include <utility>

#include "base/logging.h"
#include "base/numerics/safe_math.h"
#include "base/strings/string16.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "client/settings.h"
#include "util/misc/implicit_cast.h"
#include "util/misc/initialization_state_dcheck.h"
#include "util/misc/metrics.h"

namespace crashpad {

namespace {

constexpr wchar_t kReportsDirectory[] = L"reports";
constexpr wchar_t kMetadataFileName[] = L"metadata";

constexpr wchar_t kSettings[] = L"settings.dat";

constexpr wchar_t kCrashReportFileExtension[] = L"dmp";

constexpr uint32_t kMetadataFileHeaderMagic = 'CPAD';
constexpr uint32_t kMetadataFileVersion = 1;

using OperationStatus = CrashReportDatabase::OperationStatus;

// Helpers ---------------------------------------------------------------------

// Adds a string to the string table and returns the byte index where it was
// added.
uint32_t AddStringToTable(std::string* string_table, const std::string& str) {
  uint32_t offset = base::checked_cast<uint32_t>(string_table->size());
  *string_table += str;
  *string_table += '\0';
  return offset;
}

// Converts |str| to UTF8, adds the result to the string table and returns the
// byte index where it was added.
uint32_t AddStringToTable(std::string* string_table,
                          const base::string16& str) {
  return AddStringToTable(string_table, base::UTF16ToUTF8(str));
}

// Reads from the current file position to EOF and returns as a string of bytes.
std::string ReadRestOfFileAsString(FileHandle file) {
  FileOffset read_from = LoggingSeekFile(file, 0, SEEK_CUR);
  FileOffset end = LoggingSeekFile(file, 0, SEEK_END);
  FileOffset original = LoggingSeekFile(file, read_from, SEEK_SET);
  if (read_from == -1 || end == -1 || original == -1 || read_from == end)
    return std::string();
  DCHECK_EQ(read_from, original);
  DCHECK_GT(end, read_from);
  size_t data_length = static_cast<size_t>(end - read_from);
  std::string buffer(data_length, '\0');
  return LoggingReadFileExactly(file, &buffer[0], data_length) ? buffer
                                                               : std::string();
}

// Helper structures, and conversions ------------------------------------------

// The format of the on disk metadata file is a MetadataFileHeader, followed by
// a number of fixed size records of MetadataFileReportRecord, followed by a
// string table in UTF8 format, where each string is \0 terminated.
struct MetadataFileHeader {
  uint32_t magic;
  uint32_t version;
  uint32_t num_records;
  uint32_t padding;
};

struct ReportDisk;

enum class ReportState {
  //! \brief Created and filled out by caller, owned by database.
  kPending,
  //! \brief In the process of uploading, owned by caller.
  kUploading,
  //! \brief Upload completed or skipped, owned by database.
  kCompleted,
};

enum {
  //! \brief Corresponds to uploaded bit of the report state.
  kAttributeUploaded = 1 << 0,

  //! \brief Corresponds to upload_explicity_requested bit of the report state.
  kAttributeUploadExplicitlyRequested = 1 << 1,
};

struct MetadataFileReportRecord {
  // Note that this default constructor does no initialization. It is used only
  // to create an array of records that are immediately initialized by reading
  // from disk in Metadata::Read().
  MetadataFileReportRecord() {}

  // Constructs from a ReportDisk, adding to |string_table| and storing indices
  // as strings into that table.
  MetadataFileReportRecord(const ReportDisk& report, std::string* string_table);

  UUID uuid;  // UUID is a 16 byte, standard layout structure.
  uint32_t file_path_index;  // Index into string table. File name is relative
                             // to the reports directory when on disk.
  uint32_t id_index;  // Index into string table.
  int64_t creation_time;  // Holds a time_t.
  int64_t last_upload_attempt_time;  // Holds a time_t.
  int32_t upload_attempts;
  int32_t state;  // A ReportState.
  uint8_t attributes;  // Bitfield of kAttribute*.
  uint8_t padding[7];
};

//! \brief A private extension of the Report class that includes additional data
//!     that's stored on disk in the metadata file.
struct ReportDisk : public CrashReportDatabase::Report {
  ReportDisk(const MetadataFileReportRecord& record,
             const base::FilePath& report_dir,
             const std::string& string_table);

  ReportDisk(const UUID& uuid,
             const base::FilePath& path,
             time_t creation_tim,
             ReportState state);

  //! \brief The current state of the report.
  ReportState state;
};

MetadataFileReportRecord::MetadataFileReportRecord(const ReportDisk& report,
                                                   std::string* string_table)
    : uuid(report.uuid),
      file_path_index(
          AddStringToTable(string_table, report.file_path.BaseName().value())),
      id_index(AddStringToTable(string_table, report.id)),
      creation_time(report.creation_time),
      last_upload_attempt_time(report.last_upload_attempt_time),
      upload_attempts(report.upload_attempts),
      state(static_cast<uint32_t>(report.state)),
      attributes((report.uploaded ? kAttributeUploaded : 0) |
                 (report.upload_explicitly_requested
                      ? kAttributeUploadExplicitlyRequested
                      : 0)) {
  memset(&padding, 0, sizeof(padding));
}

ReportDisk::ReportDisk(const MetadataFileReportRecord& record,
                       const base::FilePath& report_dir,
                       const std::string& string_table)
    : Report() {
  uuid = record.uuid;
  file_path = report_dir.Append(
      base::UTF8ToUTF16(&string_table[record.file_path_index]));
  id = &string_table[record.id_index];
  creation_time = record.creation_time;
  last_upload_attempt_time = record.last_upload_attempt_time;
  upload_attempts = record.upload_attempts;
  state = static_cast<ReportState>(record.state);
  uploaded = (record.attributes & kAttributeUploaded) != 0;
  upload_explicitly_requested =
      (record.attributes & kAttributeUploadExplicitlyRequested) != 0;
}

ReportDisk::ReportDisk(const UUID& uuid,
                       const base::FilePath& path,
                       time_t creation_time,
                       ReportState state)
    : Report() {
  this->uuid = uuid;
  this->file_path = path;
  this->creation_time = creation_time;
  this->state = state;
}

// Metadata --------------------------------------------------------------------

//! \brief Manages the metadata for the set of reports, handling serialization
//!     to disk, and queries.
class Metadata {
 public:
  //! \brief Writes any changes if necessary, unlocks and closes the file
  //!     handle.
  ~Metadata();

  static std::unique_ptr<Metadata> Create(const base::FilePath& metadata_file,
                                          const base::FilePath& report_dir);

  //! \brief Adds a new report to the set.
  //!
  //! \param[in] new_report_disk The record to add. The #state field must be set
  //!     to kPending.
  void AddNewRecord(const ReportDisk& new_report_disk);

  //! \brief Finds all reports in a given state. The \a reports vector is only
  //!     valid when CrashReportDatabase::kNoError is returned.
  //!
  //! \param[in] desired_state The state to match.
  //! \param[out] reports Matching reports, must be empty on entry.
  OperationStatus FindReports(
      ReportState desired_state,
      std::vector<CrashReportDatabase::Report>* reports) const;

  //! \brief Finds the report matching the given UUID.
  //!
  //! The returned report is only valid if CrashReportDatabase::kNoError is
  //! returned.
  //!
  //! \param[in] uuid The report identifier.
  //! \param[out] report_disk The found report, valid only if
  //!     CrashReportDatabase::kNoError is returned. Ownership is not
  //!     transferred to the caller, and the report may not be modified.
  OperationStatus FindSingleReport(const UUID& uuid,
                                   const ReportDisk** report_disk) const;

  //! \brief Finds a single report matching the given UUID and in the desired
  //!     state, and returns a mutable ReportDisk* if found.
  //!
  //! This marks the metadata as dirty, and on destruction, changes will be
  //! written to disk via Write().
  //!
  //! \return #kNoError on success. #kReportNotFound if there was no report with
  //!     the specified UUID, or if the report was not in the specified state
  //!     and was not uploading. #kBusyError if the report was not in the
  //!     specified state and was uploading.
  OperationStatus FindSingleReportAndMarkDirty(const UUID& uuid,
                                               ReportState desired_state,
                                               ReportDisk** report_disk);

  //! \brief Removes a report from the metadata database, without touching the
  //!     on-disk file.
  //!
  //! The returned report is only valid if CrashReportDatabase::kNoError is
  //! returned. This will mark the database as dirty. Future metadata
  //! operations for this report will not succeed.
  //!
  //! \param[in] uuid The report identifier to remove.
  //! \param[out] report_path The found report's file_path, valid only if
  //!     CrashReportDatabase::kNoError is returned.
  OperationStatus DeleteReport(const UUID& uuid,
                               base::FilePath* report_path);

 private:
  Metadata(FileHandle handle, const base::FilePath& report_dir);

  bool Rewind();

  void Read();
  void Write();

  //! \brief Confirms that the corresponding report actually exists on disk
  //!     (that is, the dump file has not been removed), and that the report is
  //!     in the given state.
  static OperationStatus VerifyReport(const ReportDisk& report_disk,
                                      ReportState desired_state);
  //! \brief Confirms that the corresponding report actually exists on disk
  //!     (that is, the dump file has not been removed).
  static OperationStatus VerifyReportAnyState(const ReportDisk& report_disk);

  ScopedFileHandle handle_;
  const base::FilePath report_dir_;
  bool dirty_;  //! \brief `true` when a Write() is required on destruction.
  std::vector<ReportDisk> reports_;

  DISALLOW_COPY_AND_ASSIGN(Metadata);
};

Metadata::~Metadata() {
  if (dirty_)
    Write();
  // Not actually async, UnlockFileEx requires the Offset fields.
  OVERLAPPED overlapped = {0};
  if (!UnlockFileEx(handle_.get(), 0, MAXDWORD, MAXDWORD, &overlapped))
    PLOG(ERROR) << "UnlockFileEx";
}

// static
std::unique_ptr<Metadata> Metadata::Create(const base::FilePath& metadata_file,
                                           const base::FilePath& report_dir) {
  // It is important that dwShareMode be non-zero so that concurrent access to
  // this file results in a successful open. This allows us to get to LockFileEx
  // which then blocks to guard access.
  FileHandle handle = CreateFile(metadata_file.value().c_str(),
                                 GENERIC_READ | GENERIC_WRITE,
                                 FILE_SHARE_READ | FILE_SHARE_WRITE,
                                 nullptr,
                                 OPEN_ALWAYS,
                                 FILE_ATTRIBUTE_NORMAL,
                                 nullptr);
  if (handle == kInvalidFileHandle)
    return std::unique_ptr<Metadata>();
  // Not actually async, LockFileEx requires the Offset fields.
  OVERLAPPED overlapped = {0};
  if (!LockFileEx(handle,
                  LOCKFILE_EXCLUSIVE_LOCK,
                  0,
                  MAXDWORD,
                  MAXDWORD,
                  &overlapped)) {
    PLOG(ERROR) << "LockFileEx";
    return std::unique_ptr<Metadata>();
  }

  std::unique_ptr<Metadata> metadata(new Metadata(handle, report_dir));
  // If Read() fails, for whatever reason (corruption, etc.) metadata will not
  // have been modified and will be in a clean empty state. We continue on and
  // return an empty database to hopefully recover. This means that existing
  // crash reports have been orphaned.
  metadata->Read();
  return metadata;
}

void Metadata::AddNewRecord(const ReportDisk& new_report_disk) {
  DCHECK(new_report_disk.state == ReportState::kPending);
  reports_.push_back(new_report_disk);
  dirty_ = true;
}

OperationStatus Metadata::FindReports(
    ReportState desired_state,
    std::vector<CrashReportDatabase::Report>* reports) const {
  DCHECK(reports->empty());
  for (const auto& report : reports_) {
    if (report.state == desired_state &&
        VerifyReport(report, desired_state) == CrashReportDatabase::kNoError) {
      reports->push_back(report);
    }
  }
  return CrashReportDatabase::kNoError;
}

OperationStatus Metadata::FindSingleReport(
    const UUID& uuid,
    const ReportDisk** out_report) const {
  auto report_iter = std::find_if(
      reports_.begin(), reports_.end(), [uuid](const ReportDisk& report) {
        return report.uuid == uuid;
      });
  if (report_iter == reports_.end())
    return CrashReportDatabase::kReportNotFound;
  OperationStatus os = VerifyReportAnyState(*report_iter);
  if (os == CrashReportDatabase::kNoError)
    *out_report = &*report_iter;
  return os;
}

OperationStatus Metadata::FindSingleReportAndMarkDirty(
    const UUID& uuid,
    ReportState desired_state,
    ReportDisk** report_disk) {
  auto report_iter = std::find_if(
      reports_.begin(), reports_.end(), [uuid](const ReportDisk& report) {
        return report.uuid == uuid;
      });
  if (report_iter == reports_.end())
    return CrashReportDatabase::kReportNotFound;
  OperationStatus os = VerifyReport(*report_iter, desired_state);
  if (os == CrashReportDatabase::kNoError) {
    dirty_ = true;
    *report_disk = &*report_iter;
  }
  return os;
}

OperationStatus Metadata::DeleteReport(const UUID& uuid,
                                       base::FilePath* report_path) {
  auto report_iter = std::find_if(
      reports_.begin(), reports_.end(), [uuid](const ReportDisk& report) {
        return report.uuid == uuid;
      });
  if (report_iter == reports_.end())
    return CrashReportDatabase::kReportNotFound;
  *report_path = report_iter->file_path;
  reports_.erase(report_iter);
  dirty_ = true;
  return CrashReportDatabase::kNoError;
}

Metadata::Metadata(FileHandle handle, const base::FilePath& report_dir)
    : handle_(handle), report_dir_(report_dir), dirty_(false), reports_() {
}

bool Metadata::Rewind() {
  FileOffset result = LoggingSeekFile(handle_.get(), 0, SEEK_SET);
  DCHECK_EQ(result, 0);
  return result == 0;
}

void Metadata::Read() {
  FileOffset length = LoggingSeekFile(handle_.get(), 0, SEEK_END);
  if (length <= 0)  // Failed, or empty: Abort.
    return;
  if (!Rewind()) {
    LOG(ERROR) << "failed to rewind to read";
    return;
  }

  MetadataFileHeader header;
  if (!LoggingReadFileExactly(handle_.get(), &header, sizeof(header))) {
    LOG(ERROR) << "failed to read header";
    return;
  }
  if (header.magic != kMetadataFileHeaderMagic ||
      header.version != kMetadataFileVersion) {
    LOG(ERROR) << "unexpected header";
    return;
  }

  base::CheckedNumeric<uint32_t> records_size =
      base::CheckedNumeric<uint32_t>(header.num_records) *
      static_cast<uint32_t>(sizeof(MetadataFileReportRecord));
  if (!records_size.IsValid()) {
    LOG(ERROR) << "record size out of range";
    return;
  }

  std::vector<ReportDisk> reports;
  if (header.num_records > 0) {
    std::vector<MetadataFileReportRecord> records(header.num_records);
    if (!LoggingReadFileExactly(
            handle_.get(), &records[0], records_size.ValueOrDie())) {
      LOG(ERROR) << "failed to read records";
      return;
    }

    std::string string_table = ReadRestOfFileAsString(handle_.get());
    if (string_table.empty() || string_table.back() != '\0') {
      LOG(ERROR) << "bad string table";
      return;
    }

    for (const auto& record : records) {
      if (record.file_path_index >= string_table.size() ||
          record.id_index >= string_table.size()) {
        LOG(ERROR) << "invalid string table index";
        return;
      }
      ReportDisk report_disk(record, report_dir_, string_table);

      // There are no attachments on Windows so the total size is the main
      // report size.
      struct _stati64 statbuf;
      if (_wstat64(report_disk.file_path.value().c_str(), &statbuf) == 0) {
        report_disk.total_size = statbuf.st_size;
      } else {
        LOG(ERROR) << "failed to stat report";
      }

      reports.push_back(report_disk);
    }
  }
  reports_.swap(reports);
}

void Metadata::Write() {
  if (!Rewind()) {
    LOG(ERROR) << "failed to rewind to write";
    return;
  }

  // Truncate to ensure that a partial write doesn't cause a mix of old and new
  // data causing an incorrect interpretation on read.
  if (!SetEndOfFile(handle_.get())) {
    PLOG(ERROR) << "failed to truncate";
    return;
  }

  size_t num_records = reports_.size();

  // Fill and write out the header.
  MetadataFileHeader header = {0};
  header.magic = kMetadataFileHeaderMagic;
  header.version = kMetadataFileVersion;
  header.num_records = base::checked_cast<uint32_t>(num_records);
  if (!LoggingWriteFile(handle_.get(), &header, sizeof(header))) {
    LOG(ERROR) << "failed to write header";
    return;
  }

  if (num_records == 0)
    return;

  // Build the records and string table we're going to write.
  std::string string_table;
  std::vector<MetadataFileReportRecord> records;
  records.reserve(num_records);
  for (const auto& report : reports_) {
    const base::FilePath& path = report.file_path;
    if (path.DirName() != report_dir_) {
      LOG(ERROR) << path.value().c_str() << " expected to start with "
                 << base::UTF16ToUTF8(report_dir_.value());
      return;
    }
    records.push_back(MetadataFileReportRecord(report, &string_table));
  }

  if (!LoggingWriteFile(handle_.get(),
                        &records[0],
                        records.size() * sizeof(MetadataFileReportRecord))) {
    LOG(ERROR) << "failed to write records";
    return;
  }
  if (!LoggingWriteFile(
          handle_.get(), string_table.c_str(), string_table.size())) {
    LOG(ERROR) << "failed to write string table";
    return;
  }
}

// static
OperationStatus Metadata::VerifyReportAnyState(const ReportDisk& report_disk) {
  DWORD fileattr = GetFileAttributes(report_disk.file_path.value().c_str());
  if (fileattr == INVALID_FILE_ATTRIBUTES)
    return CrashReportDatabase::kReportNotFound;
  return (fileattr & FILE_ATTRIBUTE_DIRECTORY)
             ? CrashReportDatabase::kFileSystemError
             : CrashReportDatabase::kNoError;
}

// static
OperationStatus Metadata::VerifyReport(const ReportDisk& report_disk,
                                       ReportState desired_state) {
  if (report_disk.state == desired_state) {
    return VerifyReportAnyState(report_disk);
  }

  return report_disk.state == ReportState::kUploading
             ? CrashReportDatabase::kBusyError
             : CrashReportDatabase::kReportNotFound;
}

bool EnsureDirectory(const base::FilePath& path) {
  DWORD fileattr = GetFileAttributes(path.value().c_str());
  if (fileattr == INVALID_FILE_ATTRIBUTES) {
    PLOG(ERROR) << "GetFileAttributes " << base::UTF16ToUTF8(path.value());
    return false;
  }
  if ((fileattr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
    LOG(ERROR) << "GetFileAttributes "
               << base::UTF16ToUTF8(path.value())
               << ": not a directory";
    return false;
  }
  return true;
}

//! \brief Ensures that the node at path is a directory, and creates it if it
//!     does not exist.
//!
//! \return If the path points to a file, rather than a directory, or the
//!     directory could not be created, returns `false`. Otherwise, returns
//!     `true`, indicating that path already was or now is a directory.
bool CreateDirectoryIfNecessary(const base::FilePath& path) {
  if (CreateDirectory(path.value().c_str(), nullptr))
    return true;
  if (GetLastError() != ERROR_ALREADY_EXISTS) {
    PLOG(ERROR) << "CreateDirectory " << base::UTF16ToUTF8(path.value());
    return false;
  }
  return EnsureDirectory(path);
}

}  // namespace

// CrashReportDatabaseWin ------------------------------------------------------

class CrashReportDatabaseWin : public CrashReportDatabase {
 public:
  explicit CrashReportDatabaseWin(const base::FilePath& path);
  ~CrashReportDatabaseWin() override;

  bool Initialize(bool may_create);

  // CrashReportDatabase:
  Settings* GetSettings() override;
  OperationStatus PrepareNewCrashReport(
      std::unique_ptr<NewReport>* report) override;
  OperationStatus FinishedWritingCrashReport(std::unique_ptr<NewReport> report,
                                             UUID* uuid) override;
  OperationStatus LookUpCrashReport(const UUID& uuid, Report* report) override;
  OperationStatus GetPendingReports(std::vector<Report>* reports) override;
  OperationStatus GetCompletedReports(std::vector<Report>* reports) override;
  OperationStatus GetReportForUploading(
      const UUID& uuid,
      std::unique_ptr<const UploadReport>* report,
      bool report_metrics) override;
  OperationStatus SkipReportUpload(const UUID& uuid,
                                   Metrics::CrashSkippedReason reason) override;
  OperationStatus DeleteReport(const UUID& uuid) override;
  OperationStatus RequestUpload(const UUID& uuid) override;

 private:
  // CrashReportDatabase:
  OperationStatus RecordUploadAttempt(UploadReport* report,
                                      bool successful,
                                      const std::string& id) override;

  std::unique_ptr<Metadata> AcquireMetadata();

  base::FilePath base_dir_;
  Settings settings_;
  InitializationStateDcheck initialized_;

  DISALLOW_COPY_AND_ASSIGN(CrashReportDatabaseWin);
};

FileWriter* CrashReportDatabase::NewReport::AddAttachment(
    const std::string& name) {
  // Attachments aren't implemented in the Windows database yet.
  return nullptr;
}

void CrashReportDatabase::UploadReport::InitializeAttachments() {
  // Attachments aren't implemented in the Windows database yet.
}

CrashReportDatabaseWin::CrashReportDatabaseWin(const base::FilePath& path)
    : CrashReportDatabase(), base_dir_(path), settings_(), initialized_() {}

CrashReportDatabaseWin::~CrashReportDatabaseWin() {
}

bool CrashReportDatabaseWin::Initialize(bool may_create) {
  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);

  // Ensure the database directory exists.
  if (may_create) {
    if (!CreateDirectoryIfNecessary(base_dir_))
      return false;
  } else if (!EnsureDirectory(base_dir_)) {
    return false;
  }

  // Ensure that the report subdirectory exists.
  if (!CreateDirectoryIfNecessary(base_dir_.Append(kReportsDirectory)))
    return false;

  if (!settings_.Initialize(base_dir_.Append(kSettings)))
    return false;

  INITIALIZATION_STATE_SET_VALID(initialized_);
  return true;
}

Settings* CrashReportDatabaseWin::GetSettings() {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return &settings_;
}

OperationStatus CrashReportDatabaseWin::PrepareNewCrashReport(
    std::unique_ptr<NewReport>* report) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::unique_ptr<NewReport> new_report(new NewReport());
  if (!new_report->Initialize(this,
                              base_dir_.Append(kReportsDirectory),
                              std::wstring(L".") + kCrashReportFileExtension)) {
    return kFileSystemError;
  }

  report->reset(new_report.release());
  return kNoError;
}

OperationStatus CrashReportDatabaseWin::FinishedWritingCrashReport(
    std::unique_ptr<NewReport> report,
    UUID* uuid) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  if (!metadata)
    return kDatabaseError;
  metadata->AddNewRecord(ReportDisk(report->ReportID(),
                                    report->file_remover_.get(),
                                    time(nullptr),
                                    ReportState::kPending));

  ignore_result(report->file_remover_.release());

  *uuid = report->ReportID();

  Metrics::CrashReportPending(Metrics::PendingReportReason::kNewlyCreated);
  Metrics::CrashReportSize(report->Writer()->Seek(0, SEEK_END));

  return kNoError;
}

OperationStatus CrashReportDatabaseWin::LookUpCrashReport(const UUID& uuid,
                                                          Report* report) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  if (!metadata)
    return kDatabaseError;
  // Find and return a copy of the matching report.
  const ReportDisk* report_disk;
  OperationStatus os = metadata->FindSingleReport(uuid, &report_disk);
  if (os == kNoError)
    *report = *report_disk;
  return os;
}

OperationStatus CrashReportDatabaseWin::GetPendingReports(
    std::vector<Report>* reports) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  return metadata ? metadata->FindReports(ReportState::kPending, reports)
                  : kDatabaseError;
}

OperationStatus CrashReportDatabaseWin::GetCompletedReports(
    std::vector<Report>* reports) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  return metadata ? metadata->FindReports(ReportState::kCompleted, reports)
                  : kDatabaseError;
}

OperationStatus CrashReportDatabaseWin::GetReportForUploading(
    const UUID& uuid,
    std::unique_ptr<const UploadReport>* report,
    bool report_metrics) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  if (!metadata)
    return kDatabaseError;

  ReportDisk* report_disk;
  OperationStatus os = metadata->FindSingleReportAndMarkDirty(
      uuid, ReportState::kPending, &report_disk);
  if (os == kNoError) {
    report_disk->state = ReportState::kUploading;
    auto upload_report = std::make_unique<UploadReport>();
    *implicit_cast<Report*>(upload_report.get()) = *report_disk;

    if (!upload_report->Initialize(upload_report->file_path, this)) {
      return kFileSystemError;
    }
    upload_report->report_metrics_ = report_metrics;

    report->reset(upload_report.release());
  }
  return os;
}

OperationStatus CrashReportDatabaseWin::RecordUploadAttempt(
    UploadReport* report,
    bool successful,
    const std::string& id) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  if (report->report_metrics_) {
    Metrics::CrashUploadAttempted(successful);
  }

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  if (!metadata)
    return kDatabaseError;
  ReportDisk* report_disk;
  OperationStatus os = metadata->FindSingleReportAndMarkDirty(
      report->uuid, ReportState::kUploading, &report_disk);
  if (os != kNoError)
    return os;

  time_t now = time(nullptr);

  report_disk->uploaded = successful;
  report_disk->id = id;
  report_disk->last_upload_attempt_time = now;
  report_disk->upload_attempts++;
  if (successful) {
    report_disk->state = ReportState::kCompleted;
    report_disk->upload_explicitly_requested = false;
  } else {
    report_disk->state = ReportState::kPending;
    report_disk->upload_explicitly_requested =
        report->upload_explicitly_requested;
  }

  if (!settings_.SetLastUploadAttemptTime(now))
    return kDatabaseError;

  return kNoError;
}

OperationStatus CrashReportDatabaseWin::DeleteReport(const UUID& uuid) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  if (!metadata)
    return kDatabaseError;

  base::FilePath report_path;
  OperationStatus os = metadata->DeleteReport(uuid, &report_path);
  if (os != kNoError)
    return os;

  if (!DeleteFile(report_path.value().c_str())) {
    PLOG(ERROR) << "DeleteFile "
                << base::UTF16ToUTF8(report_path.value());
    return kFileSystemError;
  }
  return kNoError;
}

OperationStatus CrashReportDatabaseWin::SkipReportUpload(
    const UUID& uuid,
    Metrics::CrashSkippedReason reason) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  Metrics::CrashUploadSkipped(reason);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  if (!metadata)
    return kDatabaseError;
  ReportDisk* report_disk;
  OperationStatus os = metadata->FindSingleReportAndMarkDirty(
      uuid, ReportState::kPending, &report_disk);
  if (os == kNoError) {
    report_disk->state = ReportState::kCompleted;
    report_disk->upload_explicitly_requested = false;
  }
  return os;
}

std::unique_ptr<Metadata> CrashReportDatabaseWin::AcquireMetadata() {
  base::FilePath metadata_file = base_dir_.Append(kMetadataFileName);
  return Metadata::Create(metadata_file, base_dir_.Append(kReportsDirectory));
}

std::unique_ptr<CrashReportDatabase> InitializeInternal(
    const base::FilePath& path,
    bool may_create) {
  std::unique_ptr<CrashReportDatabaseWin> database_win(
      new CrashReportDatabaseWin(path));
  return database_win->Initialize(may_create)
             ? std::move(database_win)
             : std::unique_ptr<CrashReportDatabaseWin>();
}

OperationStatus CrashReportDatabaseWin::RequestUpload(const UUID& uuid) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  if (!metadata)
    return kDatabaseError;

  ReportDisk* report_disk;
  // TODO(gayane): Search for the report only once regardless of its state.
  OperationStatus os = metadata->FindSingleReportAndMarkDirty(
      uuid, ReportState::kCompleted, &report_disk);
  if (os == kReportNotFound) {
    os = metadata->FindSingleReportAndMarkDirty(
        uuid, ReportState::kPending, &report_disk);
  }

  if (os != kNoError)
    return os;

  // If the crash report has already been uploaded, don't request new upload.
  if (report_disk->uploaded)
    return kCannotRequestUpload;

  // Mark the crash report as having upload explicitly requested by the user,
  // and move it to the pending state.
  report_disk->upload_explicitly_requested = true;
  report_disk->state = ReportState::kPending;

  Metrics::CrashReportPending(Metrics::PendingReportReason::kUserInitiated);

  return kNoError;
}

// static
std::unique_ptr<CrashReportDatabase> CrashReportDatabase::Initialize(
    const base::FilePath& path) {
  return InitializeInternal(path, true);
}

// static
std::unique_ptr<CrashReportDatabase>
CrashReportDatabase::InitializeWithoutCreating(const base::FilePath& path) {
  return InitializeInternal(path, false);
}

}  // namespace crashpad
