chromium/chrome/browser/ash/file_manager/trash_unittest_base.cc

// 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 "chrome/browser/ash/file_manager/trash_unittest_base.h"

#include "base/files/file_util.h"
#include "base/i18n/time_formatting.h"
#include "base/strings/escape.h"
#include "base/strings/strcat.h"
#include "base/test/bind.h"
#include "chrome/browser/ash/file_manager/path_util.h"
#include "chrome/browser/ash/file_manager/trash_common_util.h"
#include "chrome/browser/ash/file_manager/volume_manager.h"
#include "chrome/browser/ash/file_manager/volume_manager_factory.h"
#include "chromeos/ash/components/dbus/chunneld/chunneld_client.h"
#include "chromeos/ash/components/dbus/cros_disks/cros_disks_client.h"
#include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
#include "storage/browser/file_system/external_mount_points.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/test/test_file_system_context.h"

namespace file_manager::io_task {

TrashBaseTest::TrashBaseTest() = default;

TrashBaseTest::~TrashBaseTest() = default;

void TrashBaseTest::SetUp() {
  ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());

  // Pass in a mock factory method that sets up a fake
  // DriveIntegrationService. This ensures the enabled paths contain the drive
  // path.
  create_drive_integration_service_ = base::BindRepeating(
      &TrashBaseTest::CreateDriveIntegrationService, base::Unretained(this));
  service_factory_for_test_ = std::make_unique<
      drive::DriveIntegrationServiceFactory::ScopedFactoryForTest>(
      &create_drive_integration_service_);
  fake_user_manager_.Reset(std::make_unique<ash::FakeChromeUserManager>());
  // Create the profile and add it to the user manager for DriveFS.
  profile_ =
      std::make_unique<TestingProfile>(base::FilePath(temp_dir_.GetPath()));
  AccountId account_id =
      AccountId::FromUserEmailGaiaId(profile_->GetProfileUserName(), "12345");
  fake_user_manager_->AddUserWithAffiliationAndTypeAndProfile(
      account_id, /*is_affiliated=*/false, user_manager::UserType::kRegular,
      profile_.get());
  fake_user_manager_->LoginUser(account_id, true);

  file_system_context_ =
      storage::CreateFileSystemContextForTesting(nullptr, temp_dir_.GetPath());
  my_files_dir_ = temp_dir_.GetPath().Append("MyFiles");
  storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
      file_manager::util::GetDownloadsMountPointName(profile_.get()),
      storage::kFileSystemTypeLocal, storage::FileSystemMountOption(),
      my_files_dir_);

  // Create Downloads inside the `temp_dir_` which will implicitly create the
  // `my_files_dir_.
  downloads_dir_ = my_files_dir_.Append("Downloads");
  ASSERT_TRUE(base::CreateDirectory(downloads_dir_));

  ash::ChunneldClient::InitializeFake();
  ash::CiceroneClient::InitializeFake();
  ash::ConciergeClient::InitializeFake();
  ash::CrosDisksClient::InitializeFake();
  ash::SeneschalClient::InitializeFake();

  // Ensure Crostini is setup correctly.
  crostini_manager_ = crostini::CrostiniManager::GetForProfile(profile_.get());
  crostini_manager_->AddRunningVmForTesting(crostini::kCrostiniDefaultVmName);
  crostini_manager_->AddRunningContainerForTesting(
      crostini::kCrostiniDefaultVmName,
      crostini::ContainerInfo(crostini::kCrostiniDefaultContainerName,
                              "testuser", "/remote/mount", "PLACEHOLDER_IP"));

  crostini_dir_ = temp_dir_.GetPath().Append("crostini");
  ASSERT_TRUE(base::CreateDirectory(crostini_dir_));

  VolumeManagerFactory::GetInstance()->SetTestingFactory(
      profile_.get(),
      base::BindLambdaForTesting([this](content::BrowserContext* context) {
        return std::unique_ptr<KeyedService>(std::make_unique<VolumeManager>(
            Profile::FromBrowserContext(context), nullptr, nullptr,
            &disk_mount_manager_, nullptr,
            VolumeManager::GetMtpStorageInfoCallback()));
      }));
  crostini_remote_mount_ = base::FilePath("/remote/mount");
  auto* volume_manager = VolumeManager::Get(profile_.get());
  volume_manager->AddVolumeForTesting(
      Volume::CreateForSshfsCrostini(crostini_dir_, crostini_remote_mount_));
}

void TrashBaseTest::TearDown() {
  // Ensure any previously registered mount points for Downloads are revoked.
  storage::ExternalMountPoints::GetSystemInstance()->RevokeAllFileSystems();
  profile_.reset();
  fake_user_manager_.Reset();
  ash::SeneschalClient::Shutdown();
  ash::CrosDisksClient::Shutdown();
  ash::ConciergeClient::Shutdown();
  ash::CiceroneClient::Shutdown();
  ash::ChunneldClient::Shutdown();
}

drive::DriveIntegrationService* TrashBaseTest::CreateDriveIntegrationService(
    Profile* profile) {
  base::ScopedAllowBlockingForTesting allow_blocking;
  base::FilePath mount_point = temp_dir_.GetPath().Append("drivefs");
  fake_drivefs_helper_ =
      std::make_unique<drive::FakeDriveFsHelper>(profile, mount_point);
  integration_service_ = new drive::DriveIntegrationService(
      profile, "", mount_point,
      fake_drivefs_helper_->CreateFakeDriveFsListenerFactory());
  return integration_service_;
}

storage::FileSystemURL TrashBaseTest::CreateFileSystemURL(
    const base::FilePath& absolute_path) {
  std::string relative_path = absolute_path.value();

  // URLs in test are required to be relative to the `base_path_`. This ensures
  // all FileSystemURLs in test are made relative.
  EXPECT_TRUE(file_manager::util::ReplacePrefix(
      &relative_path, temp_dir_.GetPath().AsEndingWithSeparator().value(), ""));

  return file_system_context_->CreateCrackedFileSystemURL(
      kTestStorageKey, storage::kFileSystemTypeTest,
      base::FilePath::FromUTF8Unsafe(relative_path));
}

const base::FilePath TrashBaseTest::GenerateInfoPath(
    const std::string& file_name) {
  return trash::GenerateTrashPath(
      downloads_dir_.Append(trash::kTrashFolderName), trash::kInfoFolderName,
      file_name);
}

const base::FilePath TrashBaseTest::GenerateFilesPath(
    const std::string& file_name) {
  return trash::GenerateTrashPath(
      downloads_dir_.Append(trash::kTrashFolderName), trash::kFilesFolderName,
      file_name);
}

const std::string TrashBaseTest::CreateTrashInfoContentsFromPath(
    const base::FilePath& file_path,
    const base::FilePath& base_path,
    const base::FilePath& prefix_path) {
  std::string relative_restore_path = file_path.value();
  EXPECT_TRUE(file_manager::util::ReplacePrefix(
      &relative_restore_path, base_path.AsEndingWithSeparator().value(), ""));

  base::FilePath prefix = (prefix_path.IsAbsolute())
                              ? prefix_path
                              : base::FilePath("/").Append(prefix_path);

  return base::StrCat(
      {"[Trash Info]\nPath=",
       base::EscapePath(prefix.AsEndingWithSeparator().value()),
       base::EscapePath(relative_restore_path), "\nDeletionDate=",
       base::TimeFormatAsIso8601(base::Time::UnixEpoch()), "\n"});
}

const std::string TrashBaseTest::CreateTrashInfoContentsFromPath(
    const base::FilePath& file_path) {
  return CreateTrashInfoContentsFromPath(file_path, my_files_dir_,
                                         base::FilePath("/"));
}

bool TrashBaseTest::EnsureTrashDirectorySetup(
    const base::FilePath& parent_path) {
  base::FilePath trash_path = parent_path.Append(trash::kTrashFolderName);
  if (!base::CreateDirectory(trash_path.Append(trash::kInfoFolderName))) {
    return false;
  }
  if (!base::CreateDirectory(trash_path.Append(trash::kFilesFolderName))) {
    return false;
  }
  return true;
}

}  // namespace file_manager::io_task