chromium/chromeos/ash/components/nearby/common/connections_manager/nearby_file_handler.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromeos/ash/components/nearby/common/connections_manager/nearby_file_handler.h"

#include "base/files/file_util.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom.h"

namespace {

scoped_refptr<base::SequencedTaskRunner> CreateFileTaskRunner() {
  // The tasks posted to this sequenced task runner do synchronous File I/O for
  // the purposes of opening and closing files for Nearby Share file payloads.
  return base::ThreadPool::CreateSequencedTaskRunner(
      {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
}

// Called on the FileTaskRunner to actually open the files passed.
std::vector<NearbyFileHandler::FileInfo> DoOpenFiles(
    std::vector<base::FilePath> file_paths) {
  std::vector<NearbyFileHandler::FileInfo> files;
  for (const auto& path : file_paths) {
    base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
    if (!file.IsValid())
      return {};

    int64_t size = file.GetLength();
    if (size < 0)
      return {};

    files.push_back({size, std::move(file)});
  }
  return files;
}

NearbyFileHandler::CreateFileResult DoCreateFile(base::FilePath file_path) {
  NearbyFileHandler::CreateFileResult result;
  result.output_file.Initialize(
      file_path,
      base::File::Flags::FLAG_CREATE_ALWAYS | base::File::Flags::FLAG_WRITE);
  result.input_file.Initialize(
      file_path, base::File::Flags::FLAG_OPEN | base::File::Flags::FLAG_READ);
  return result;
}

}  // namespace

NearbyFileHandler::NearbyFileHandler() : task_runner_(CreateFileTaskRunner()) {}

NearbyFileHandler::~NearbyFileHandler() = default;

void NearbyFileHandler::OpenFiles(std::vector<base::FilePath> file_paths,
                                  OpenFilesCallback callback) {
  task_runner_->PostTaskAndReplyWithResult(
      FROM_HERE, base::BindOnce(&DoOpenFiles, std::move(file_paths)),
      std::move(callback));
}

void NearbyFileHandler::GetUniquePath(const base::FilePath& file_path,
                                      GetUniquePathCallback callback) {
  // TODO(crbug.com/40132032) - Confirm if this should be run on
  // DownloadManager's task runner.
  task_runner_->PostTaskAndReplyWithResult(
      FROM_HERE, base::BindOnce(&base::GetUniquePath, file_path),
      std::move(callback));
}

void NearbyFileHandler::ReleaseFilePayloads(std::vector<PayloadPtr> payloads) {
  auto files = std::make_unique<std::vector<base::File>>();
  for (auto& payload : payloads) {
    if (payload->content->is_file())
      files->push_back(std::move(payload->content->get_file()->file));
  }
  if (!files->empty())
    task_runner_->DeleteSoon(FROM_HERE, std::move(files));
}

void NearbyFileHandler::CreateFile(const base::FilePath& file_path,
                                   CreateFileCallback callback) {
  task_runner_->PostTaskAndReplyWithResult(
      FROM_HERE, base::BindOnce(&DoCreateFile, file_path), std::move(callback));
}

void NearbyFileHandler::DeleteFilesFromDisk(std::vector<base::FilePath> paths) {
  task_runner_->PostTask(FROM_HERE, base::BindOnce(
                                        [](std::vector<base::FilePath> paths) {
                                          for (const auto& path : paths)
                                            base::DeleteFile(path);
                                        },
                                        std::move(paths)));
}