910e62b5创建于 1月15日历史提交
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "services/network/disk_cache/mojo_backend_file_operations.h"

#include "base/task/sequenced_task_runner.h"

namespace network {

namespace {

class FileEnumeratorImpl final
    : public disk_cache::BackendFileOperations::FileEnumerator {
 public:
  using FileEnumerationEntry =
      disk_cache::BackendFileOperations::FileEnumerationEntry;

  explicit FileEnumeratorImpl(mojo::PendingRemote<mojom::FileEnumerator> remote)
      : remote_(std::move(remote)) {}
  ~FileEnumeratorImpl() override = default;

  std::optional<FileEnumerationEntry> Next() override {
    if (has_seen_end_) {
      return std::nullopt;
    }
    if (index_ >= entries_.size()) {
      index_ = 0;
      entries_.clear();
      remote_->GetNext(kNumEntries, &entries_, &has_seen_end_, &has_error_);
    }
    if (entries_.empty()) {
      if (has_seen_end_) {
        return std::nullopt;
      }
      has_error_ = true;
      has_seen_end_ = true;
      return std::nullopt;
    }
    DCHECK_LT(index_, entries_.size());
    return std::make_optional<FileEnumerationEntry>(
        std::move(entries_[index_++]));
  }

  bool HasError() const override { return has_error_; }

 private:
  mojo::Remote<mojom::FileEnumerator> remote_;
  std::vector<FileEnumerationEntry> entries_;
  bool has_seen_end_ = false;
  bool has_error_ = false;
  size_t index_ = 0;

  static constexpr uint32_t kNumEntries = 1000;
};

}  // namespace

MojoBackendFileOperations::MojoBackendFileOperations(
    mojo::PendingRemote<mojom::HttpCacheBackendFileOperations> pending_remote,
    scoped_refptr<base::SequencedTaskRunner> task_runner)
    : remote_(std::move(pending_remote), std::move(task_runner)) {}
MojoBackendFileOperations::~MojoBackendFileOperations() = default;

bool MojoBackendFileOperations::CreateDirectory(const base::FilePath& path) {
  bool result = false;
  remote_->CreateDirectory(path, &result);
  return result;
}

bool MojoBackendFileOperations::PathExists(const base::FilePath& path) {
  bool result = false;
  remote_->PathExists(path, &result);
  return result;
}

bool MojoBackendFileOperations::DirectoryExists(const base::FilePath& path) {
  bool result = false;
  remote_->DirectoryExists(path, &result);
  return result;
}

base::File MojoBackendFileOperations::OpenFile(const base::FilePath& path,
                                               uint32_t flags) {
  base::File file;
  base::File::Error error;
  // The value will be checked in the message receiver side.
  auto flags_to_pass = static_cast<mojom::HttpCacheBackendOpenFileFlags>(flags);
  remote_->OpenFile(path, flags_to_pass, &file, &error);
  if (error != base::File::FILE_OK) {
    return base::File(error);
  }
  return file;
}

bool MojoBackendFileOperations::DeleteFile(const base::FilePath& path,
                                           DeleteFileMode mode) {
  mojom::HttpCacheBackendDeleteFileMode mode_to_pass;
  switch (mode) {
    case DeleteFileMode::kDefault:
      mode_to_pass = mojom::HttpCacheBackendDeleteFileMode::kDefault;
      break;
    case DeleteFileMode::kEnsureImmediateAvailability:
      mode_to_pass =
          mojom::HttpCacheBackendDeleteFileMode::kEnsureImmediateAvailability;
      break;
  }
  bool result = false;
  remote_->DeleteFile(path, mode_to_pass, &result);
  return result;
}

bool MojoBackendFileOperations::ReplaceFile(const base::FilePath& from_path,
                                            const base::FilePath& to_path,
                                            base::File::Error* error_out) {
  base::File::Error error;
  remote_->RenameFile(from_path, to_path, &error);
  if (error_out) {
    *error_out = error;
  }
  return error == base::File::FILE_OK;
}

std::optional<base::File::Info> MojoBackendFileOperations::GetFileInfo(
    const base::FilePath& path) {
  std::optional<base::File::Info> info;
  remote_->GetFileInfo(path, &info);
  return info;
}

std::unique_ptr<disk_cache::BackendFileOperations::FileEnumerator>
MojoBackendFileOperations::EnumerateFiles(const base::FilePath& path) {
  mojo::PendingRemote<mojom::FileEnumerator> remote;
  remote_->EnumerateFiles(path, remote.InitWithNewPipeAndPassReceiver());
  return std::make_unique<FileEnumeratorImpl>(std::move(remote));
}

void MojoBackendFileOperations::CleanupDirectory(
    const base::FilePath& path,
    base::OnceCallback<void(bool)> callback) {
  remote_->CleanupDirectory(path, std::move(callback));
}

std::unique_ptr<disk_cache::UnboundBackendFileOperations>
MojoBackendFileOperations::Unbind() {
  return std::make_unique<UnboundMojoBackendFileOperations>(remote_.Unbind());
}

bool MojoBackendFileOperations::IsEncrypted() const {
  return false;
}

UnboundMojoBackendFileOperations::UnboundMojoBackendFileOperations(
    mojo::PendingRemote<mojom::HttpCacheBackendFileOperations> pending_remote)
    : pending_remote_(std::move(pending_remote)) {}

UnboundMojoBackendFileOperations::~UnboundMojoBackendFileOperations() = default;

std::unique_ptr<disk_cache::BackendFileOperations>
UnboundMojoBackendFileOperations::Bind(
    scoped_refptr<base::SequencedTaskRunner> task_runner) {
  return std::make_unique<MojoBackendFileOperations>(std::move(pending_remote_),
                                                     std::move(task_runner));
}

}  // namespace network