// Copyright 2013 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/volume_manager.h"

#include <optional>
#include <string_view>

#include "ash/constants/ash_features.h"
#include "base/auto_reset.h"
#include "base/base64url.h"
#include "base/check_deref.h"
#include "base/check_is_test.h"
#include "base/containers/span.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/pickle.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/system/sys_info.h"
#include "base/task/thread_pool.h"
#include "base/types/optional_util.h"
#include "chrome/browser/ash/arc/arc_util.h"
#include "chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map.h"
#include "chrome/browser/ash/arc/fileapi/arc_documents_provider_util.h"
#include "chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.h"
#include "chrome/browser/ash/arc/fileapi/arc_media_view_util.h"
#include "chrome/browser/ash/crostini/crostini_manager.h"
#include "chrome/browser/ash/drive/drive_integration_service.h"
#include "chrome/browser/ash/file_manager/fileapi_util.h"
#include "chrome/browser/ash/file_manager/path_util.h"
#include "chrome/browser/ash/file_manager/snapshot_manager.h"
#include "chrome/browser/ash/file_manager/volume_manager_factory.h"
#include "chrome/browser/ash/file_manager/volume_manager_observer.h"
#include "chrome/browser/ash/policy/skyvault/local_files_migration_manager.h"
#include "chrome/browser/ash/policy/skyvault/policy_utils.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h"
#include "chrome/common/chrome_features.h"
#include "chromeos/ash/components/policy/external_storage/device_id.h"
#include "chromeos/ash/components/policy/external_storage/external_storage_policy_controller.h"
#include "chromeos/ash/experiences/arc/arc_util.h"
#include "chromeos/components/disks/disks_prefs.h"
#include "components/prefs/pref_service.h"
#include "components/storage_monitor/storage_info_utils.h"
#include "components/storage_monitor/storage_monitor.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "crypto/sha2.h"
#include "services/device/public/mojom/mtp_storage_info.mojom.h"
#include "storage/browser/file_system/external_mount_points.h"
#include "ui/base/clipboard/clipboard_data.h"
#include "ui/base/clipboard/clipboard_format_type.h"
#include "ui/base/clipboard/clipboard_monitor.h"
#include "ui/base/clipboard/clipboard_non_backed.h"

namespace file_manager {
namespace {

const uint32_t kAccessCapabilityReadWrite = 0;
const uint32_t kFilesystemTypeGenericHierarchical = 2;
const char kFileManagerMTPMountNamePrefix[] = "fileman-mtp-";
const char kMtpVolumeIdPrefix[] = "mtp:";
const char kRootPath[] = "/";

// Registers |path| as the "Downloads" folder to the FileSystem API backend.
// If another folder is already mounted. It revokes and overrides the old one.
bool RegisterDownloadsMountPoint(Profile* profile, const base::FilePath& path) {
  // Although we show only profile's own "Downloads" folder in the Files app,
  // in the backend we need to mount all profile's download directory globally.
  // Otherwise, the Files app cannot support cross-profile file copies, etc.
  // For this reason, we need to register to the global GetSystemInstance().
  const std::string mount_point_name =
      file_manager::util::GetDownloadsMountPointName(profile);
  storage::ExternalMountPoints* const mount_points =
      storage::ExternalMountPoints::GetSystemInstance();

  // In some tests we want to override existing Downloads mount point, so we
  // first revoke the existing mount point (if any).
  mount_points->RevokeFileSystem(mount_point_name);
  return mount_points->RegisterFileSystem(
      mount_point_name, storage::kFileSystemTypeLocal,
      storage::FileSystemMountOption(), path);
}

// Revokes |path| as the "Downloads" folder from the FileSystem API backend,
// if mounted.
void RevokeDownloadsMountPoint(Profile* profile, const base::FilePath& path) {
  const std::string mount_point_name =
      file_manager::util::GetDownloadsMountPointName(profile);
  storage::ExternalMountPoints* const mount_points =
      storage::ExternalMountPoints::GetSystemInstance();

  mount_points->RevokeFileSystem(mount_point_name);
}

// Registers a mount point for Android files to ExternalMountPoints.
bool RegisterAndroidFilesMountPoint() {
  if (arc::IsArcVmEnabled()) {
    return false;
  }
  storage::ExternalMountPoints* const mount_points =
      storage::ExternalMountPoints::GetSystemInstance();
  return mount_points->RegisterFileSystem(
      file_manager::util::GetAndroidFilesMountPointName(),
      storage::kFileSystemTypeLocal, storage::FileSystemMountOption(),
      base::FilePath(util::kAndroidFilesPath));
}

// Revokes Android files mount point, if mounted.
void RevokeAndroidFilesMountPoint() {
  if (arc::IsArcVmEnabled()) {
    return;
  }
  storage::ExternalMountPoints* const mount_points =
      storage::ExternalMountPoints::GetSystemInstance();
  mount_points->RevokeFileSystem(
      file_manager::util::GetAndroidFilesMountPointName());
}

bool RegisterShareCacheMountPoint(Profile* profile) {
  const std::string mount_point_name =
      file_manager::util::GetShareCacheMountPointName(profile);
  storage::ExternalMountPoints* const mount_points =
      storage::ExternalMountPoints::GetSystemInstance();
  mount_points->RevokeFileSystem(mount_point_name);
  return mount_points->RegisterFileSystem(
      mount_point_name, storage::kFileSystemTypeLocal,
      storage::FileSystemMountOption(), util::GetShareCacheFilePath(profile));
}

// Finds the path register as the "Downloads" folder to FileSystem API backend.
// Returns false if it is not registered.
bool FindDownloadsMountPointPath(Profile* profile, base::FilePath* path) {
  const std::string mount_point_name =
      util::GetDownloadsMountPointName(profile);
  storage::ExternalMountPoints* const mount_points =
      storage::ExternalMountPoints::GetSystemInstance();
  return mount_points->GetRegisteredPath(mount_point_name, path);
}

// Returns true if the mount point is registered with FileSystem API backend.
// Return false if it is not registered.
bool FindExternalMountPoint(const std::string& mount_point_name) {
  storage::ExternalMountPoints* const mount_points =
      storage::ExternalMountPoints::GetSystemInstance();
  base::FilePath path;
  return mount_points->GetRegisteredPath(mount_point_name, &path);
}

std::string FuseBoxSubdirADP(const std::string& authority,
                             const std::string& root_id) {
  // Hash the authority and document ID
  // - because the ID can be quite long (400+ bytes) and
  // - to avoid sharing the ID in the file system.
  std::string hash = crypto::SHA256HashString(
      arc::GetDocumentsProviderMountPathSuffix(authority, root_id)
          .AsUTF8Unsafe());
  std::string b64;
  base::Base64UrlEncode(hash, base::Base64UrlEncodePolicy::OMIT_PADDING, &b64);
  return base::StrCat({util::kFuseBoxSubdirPrefixADP, b64});
}

std::string FuseBoxSubdirFSP(
    const ash::file_system_provider::ProvidedFileSystemInfo& file_system_info) {
  std::string hash =
      crypto::SHA256HashString(file_system_info.mount_path().value());
  std::string b64;
  base::Base64UrlEncode(hash, base::Base64UrlEncodePolicy::OMIT_PADDING, &b64);
  return base::StrCat({util::kFuseBoxSubdirPrefixFSP, b64});
}

std::string FuseBoxSubdirLOC(const base::FilePath& path) {
  std::string hash = crypto::SHA256HashString(path.value());
  std::string b64;
  base::Base64UrlEncode(hash, base::Base64UrlEncodePolicy::OMIT_PADDING, &b64);
  return base::StrCat({util::kFuseBoxSubdirPrefixLOC, b64});
}

std::string FuseBoxSubdirMTP(const std::string& device_id) {
  // Derive the subdir name from the MTP device ID (which is stable even after
  // unplugging and replugging a phone). It's a hash of the ID, not the ID
  // itself, to avoid sharing the device's unique ID in the file system.
  std::string hash = crypto::SHA256HashString(device_id);
  std::string b64;
  base::Base64UrlEncode(hash, base::Base64UrlEncodePolicy::OMIT_PADDING, &b64);
  return base::StrCat({util::kFuseBoxSubdirPrefixMTP, b64});
}

std::string GetMountPointNameForMediaStorage(
    const storage_monitor::StorageInfo& info) {
  std::string name(kFileManagerMTPMountNamePrefix);
  name += info.device_id();
  return name;
}

ash::MountAccessMode GetExternalStorageAccessMode(
    const Profile* profile,
    std::optional<policy::DeviceId> device_id) {
  return policy::ExternalStoragePolicyController::IsDeviceReadOnly(
             CHECK_DEREF(profile->GetPrefs()), std::move(device_id))
             ? ash::MountAccessMode::kReadOnly
             : ash::MountAccessMode::kReadWrite;
}

void RecordDownloadsDiskUsageStats(base::FilePath downloads_path) {
  constexpr int64_t kOneMiB = 1024 * 1024;
  // For now assume a maximum bucket size of 512GB, which exceeds all current
  // chromeOS hard disk sizes.
  constexpr int64_t k512GiBInMiB = 512 * 1024;

  int64_t download_directory_size_in_bytes =
      base::ComputeDirectorySize(downloads_path);

  base::UmaHistogramCustomCounts(
      "FileBrowser.Downloads.DirectorySizeMiB",
      static_cast<int>(download_directory_size_in_bytes / kOneMiB), 1,
      k512GiBInMiB, 100);

  int64_t total_disk_space_in_bytes =
      base::SysInfo::AmountOfTotalDiskSpace(downloads_path);

  // total_disk_space_in_bytes can be -1 on error.
  if (total_disk_space_in_bytes > 0) {
    int percentage_space_used = std::lround(
        (download_directory_size_in_bytes * 100.0) / total_disk_space_in_bytes);

    base::UmaHistogramPercentageObsoleteDoNotUse(
        "FileBrowser.Downloads.DirectoryPercentageOfDiskUsage",
        percentage_space_used);
  }
}

std::unique_ptr<Volume> CreateForFuseBoxDownloads(
    Profile* profile,
    file_manager::FuseBoxDaemon* fusebox_daemon,
    const char* fusebox_volume_label) {
  if (!profile || !fusebox_daemon) {
    return nullptr;
  }

  // Get the FileSystemURL for the underlying Downloads folder.
  GURL gurl;
  base::FilePath downloads_path = util::GetDownloadsFolderForProfile(profile);
  if (!util::ConvertAbsoluteFilePathToFileSystemUrl(
          profile, downloads_path, util::GetFileManagerURL(), &gurl)) {
    LOG(ERROR) << "could not convert Downloads to FileSystemURL";
    return nullptr;
  }

  // Attach the Downloads directory to the fusebox daemon.
  std::string subdir = FuseBoxSubdirLOC(downloads_path);
  static constexpr bool read_only = false;
  fusebox_daemon->AttachStorage(subdir, gurl.spec(), read_only);

  // Create a Volume for the fusebox edition of Downloads.
  std::unique_ptr<Volume> fusebox_volume = Volume::CreateForDownloads(
      {}, base::FilePath(util::kFuseBoxMediaPath).Append(subdir),
      fusebox_volume_label);

  // Register the fusebox file system with chrome::storage.
  const std::string fusebox_fsid =
      base::StrCat({util::kFuseBoxMountNamePrefix, subdir});
  if (!FindExternalMountPoint(fusebox_fsid)) {
    auto* mount_points = storage::ExternalMountPoints::GetSystemInstance();
    bool result = mount_points->RegisterFileSystem(
        fusebox_fsid, storage::kFileSystemTypeFuseBox,
        storage::FileSystemMountOption(), fusebox_volume->mount_path());
    LOG_IF(ERROR, !result) << "invalid FuseBox Downloads mount path";
    DCHECK(result);
  }

  return fusebox_volume;
}

bool IsArcEnabled(Profile* profile) {
  return arc::IsArcAllowedForProfile(profile);
}

bool IsSkyVaultV2Enabled() {
  return base::FeatureList::IsEnabled(features::kSkyVaultV2);
}

}  // namespace

int VolumeManager::counter_ = 0;

VolumeManager::VolumeManager(
    Profile* profile,
    drive::DriveIntegrationService* drive_integration_service,
    chromeos::PowerManagerClient* power_manager_client,
    ash::disks::DiskMountManager* disk_mount_manager,
    ash::file_system_provider::Service* file_system_provider_service,
    GetMtpStorageInfoCallback get_mtp_storage_info_callback)
    : profile_(profile),
      drive_integration_service_(drive_integration_service),
      disk_mount_manager_(disk_mount_manager),
      file_system_provider_service_(file_system_provider_service),
      get_mtp_storage_info_callback_(get_mtp_storage_info_callback),
      snapshot_manager_(new SnapshotManager(profile_)),
      documents_provider_root_manager_(
          std::make_unique<DocumentsProviderRootManager>(
              profile_,
              arc::ArcFileSystemOperationRunner::GetForBrowserContext(
                  profile_))) {
  DCHECK(profile_);
  DCHECK(disk_mount_manager_);
  VLOG(1) << *this << "::Constructor with Profile: " << profile->GetDebugName();
}

VolumeManager::~VolumeManager() {
  VLOG(1) << *this << "::Destructor";
}

VolumeManager* VolumeManager::Get(content::BrowserContext* context) {
  return VolumeManagerFactory::Get(context);
}

void VolumeManager::Initialize() {
  VLOG(1) << *this << "::Initialize";

  // If in the Sign in profile or the lock screen app profile or lock screen
  // profile, skip mounting and listening for mount events.
  if (!ash::ProfileHelper::IsUserProfile(profile_)) {
    VLOG(1) << *this << ": Not a user profile: " << profile_->GetDebugName();
    return;
  }

  if (!fusebox_daemon_) {
    fusebox_daemon_ = file_manager::FuseBoxDaemon::GetInstance();
  }

  local_user_files_allowed_ = policy::local_user_files::LocalUserFilesAllowed();
  if (local_user_files_allowed_) {
    // Add local folders - MyFiles and ARC if enabled.
    OnLocalUserFilesEnabled();
  } else {
    OnLocalUserFilesDisabled();
  }
  // For GA, also subscribe to SkyVault LocalFilesMigrationManager.
  if (IsSkyVaultV2Enabled()) {
    if (policy::local_user_files::
            LocalFilesMigrationManager* migration_manager =
                policy::local_user_files::LocalFilesMigrationManagerFactory::
                    GetForBrowserContext(profile_)) {
      migration_manager->AddObserver(this);
    }
  }

  // Subscribe to DriveIntegrationService.
  Observe(drive_integration_service_);
  if (drive_integration_service_->IsMounted()) {
    DoMountEvent(Volume::CreateForDrive(GetDriveMountPointPath()));
  }

  // Subscribe to DiskMountManager.
  disk_mount_manager_->AddObserver(this);
  disk_mount_manager_->EnsureMountInfoRefreshed(
      base::BindOnce(&VolumeManager::OnDiskMountManagerRefreshed,
                     weak_ptr_factory_.GetWeakPtr()),
      false /* force */);

  // Subscribe to FileSystemProviderService and register currently mounted
  // volumes for the profile.
  if (file_system_provider_service_) {
    file_system_provider_service_->AddObserver(this);

    std::vector<ash::file_system_provider::ProvidedFileSystemInfo>
        file_system_info_list =
            file_system_provider_service_->GetProvidedFileSystemInfoList();
    for (const auto& file_system_info : file_system_info_list) {
      OnProvidedFileSystemMount(
          file_system_info, ash::file_system_provider::MOUNT_CONTEXT_RESTORE,
          base::File::FILE_OK);
    }
  }

  // Subscribe to Profile Preference change.
  pref_change_registrar_.Init(profile_->GetPrefs());
  pref_change_registrar_.Add(
      disks::prefs::kExternalStorageDisabled,
      base::BindRepeating(&VolumeManager::OnExternalStorageDisabledChanged,
                          weak_ptr_factory_.GetWeakPtr()));
  pref_change_registrar_.Add(
      disks::prefs::kExternalStorageReadOnly,
      base::BindRepeating(&VolumeManager::OnExternalStorageReadOnlyChanged,
                          weak_ptr_factory_.GetWeakPtr()));
  pref_change_registrar_.Add(
      disks::prefs::kExternalStorageAllowlist,
      base::BindRepeating(&VolumeManager::OnExternalStorageAllowlistChanged,
                          weak_ptr_factory_.GetWeakPtr()));

  // Subscribe to storage monitor for MTP notifications.
  if (storage_monitor::StorageMonitor::GetInstance()) {
    storage_monitor::StorageMonitor::GetInstance()->EnsureInitialized(
        base::BindOnce(&VolumeManager::OnStorageMonitorInitialized,
                       weak_ptr_factory_.GetWeakPtr()));
  }

  // Subscribe to clipboard events.
  ui::ClipboardMonitor::GetInstance()->AddObserver(this);

  RegisterShareCacheMountPoint(profile_);
  DoMountEvent(
      Volume::CreateForShareCache(util::GetShareCacheFilePath(profile_)));

  // Start Trash autocleanup.
  if (!base::FeatureList::IsEnabled(ash::features::kFilesTrashAutoCleanup)) {
    trash_auto_cleanup_ = trash::TrashAutoCleanup::Create(profile_);
  }
}

void VolumeManager::Shutdown() {
  VLOG(1) << *this << "::Shutdown";

  for (auto& observer : observers_) {
    observer.OnShutdownStart(this);
  }

  weak_ptr_factory_.InvalidateWeakPtrs();

  snapshot_manager_.reset();
  pref_change_registrar_.RemoveAll();
  disk_mount_manager_->RemoveObserver(this);
  documents_provider_root_manager_->RemoveObserver(this);
  documents_provider_root_manager_.reset();
  trash_auto_cleanup_.reset();

  if (storage_monitor::StorageMonitor* const p =
          storage_monitor::StorageMonitor::GetInstance()) {
    p->RemoveObserver(this);
  }

  drive::DriveIntegrationService::Observer::Reset();

  if (file_system_provider_service_) {
    file_system_provider_service_->RemoveObserver(this);
  }

  UnsubscribeFromArcEvents();
  ui::ClipboardMonitor::GetInstance()->RemoveObserver(this);

  // If GA, unsubscribe from SkyVault LocalFilesMigrationManager.
  if (IsSkyVaultV2Enabled()) {
    if (policy::local_user_files::
            LocalFilesMigrationManager* migration_manager =
                policy::local_user_files::LocalFilesMigrationManagerFactory::
                    GetForBrowserContext(profile_, /*create=*/false)) {
      migration_manager->RemoveObserver(this);
    }
  }
}

void VolumeManager::AddObserver(VolumeManagerObserver* observer) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(observer);
  observers_.AddObserver(observer);
}

void VolumeManager::RemoveObserver(VolumeManagerObserver* observer) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(observer);
  observers_.RemoveObserver(observer);
}

std::vector<base::WeakPtr<Volume>> VolumeManager::GetVolumeList() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  std::vector<base::WeakPtr<Volume>> result;
  result.reserve(mounted_volumes_.size());
  for (const auto& volume : mounted_volumes_) {
    DCHECK(volume);
    result.push_back(volume->AsWeakPtr());
  }
  return result;
}

base::WeakPtr<Volume> VolumeManager::FindVolumeById(
    const std::string& volume_id) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  if (const Volumes::const_iterator it = mounted_volumes_.find(volume_id);
      it != mounted_volumes_.end()) {
    DCHECK(*it);
    return (*it)->AsWeakPtr();
  }

  return nullptr;
}

base::WeakPtr<Volume> VolumeManager::FindVolumeFromPath(
    const base::FilePath& path) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  for (const auto& volume : mounted_volumes_) {
    DCHECK(volume);
    const base::FilePath& volume_mount_path = volume->mount_path();
    if (path == volume_mount_path || volume_mount_path.IsParent(path)) {
      return volume->AsWeakPtr();
    }
  }

  return nullptr;
}

void VolumeManager::AddSshfsCrostiniVolume(
    const base::FilePath& sshfs_mount_path,
    const base::FilePath& remote_mount_path) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  // Ignore if volume already exists.
  if (!DoMountEvent(Volume::CreateForSshfsCrostini(sshfs_mount_path,
                                                   remote_mount_path))) {
    return;
  }

  // Listen for crostini container shutdown and remove volume.
  crostini::CrostiniManager::GetForProfile(profile_)
      ->AddShutdownContainerCallback(
          crostini::DefaultContainerId(),
          base::BindOnce(&VolumeManager::RemoveSshfsCrostiniVolume,
                         weak_ptr_factory_.GetWeakPtr(), sshfs_mount_path,
                         base::BindOnce([](bool result) {
                           if (!result) {
                             LOG(ERROR) << "Failed to remove sshfs mount";
                           }
                         })));
}

void VolumeManager::AddSftpGuestOsVolume(
    std::string display_name,
    const base::FilePath& sftp_mount_path,
    const base::FilePath& remote_mount_path,
    const guest_os::VmType vm_type) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DoMountEvent(Volume::CreateForSftpGuestOs(
      std::move(display_name), sftp_mount_path, remote_mount_path, vm_type));
}

void VolumeManager::RemoveSshfsCrostiniVolume(
    const base::FilePath& sshfs_mount_path,
    RemoveSshfsCrostiniVolumeCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  disk_mount_manager_->UnmountPath(
      sshfs_mount_path.value(),
      base::BindOnce(&VolumeManager::OnSshfsCrostiniUnmountCallback,
                     weak_ptr_factory_.GetWeakPtr(), sshfs_mount_path,
                     std::move(callback)));
}

void VolumeManager::RemoveSftpGuestOsVolume(
    const base::FilePath& sftp_mount_path,
    const guest_os::VmType vm_type,
    RemoveSshfsCrostiniVolumeCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  disk_mount_manager_->UnmountPath(
      sftp_mount_path.value(),
      base::BindOnce(&VolumeManager::OnSftpGuestOsUnmountCallback,
                     weak_ptr_factory_.GetWeakPtr(), sftp_mount_path, vm_type,
                     std::move(callback)));
}

bool VolumeManager::RegisterAndroidFilesDirectoryForTesting(
    const base::FilePath& path) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  bool result =
      storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
          file_manager::util::GetAndroidFilesMountPointName(),
          storage::kFileSystemTypeLocal, storage::FileSystemMountOption(),
          path);
  DCHECK(result);
  return DoMountEvent(Volume::CreateForAndroidFiles(path));
}

bool VolumeManager::RegisterMediaViewForTesting(
    const std::string& root_document_id) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  return DoMountEvent(Volume::CreateForMediaView(root_document_id));
}

bool VolumeManager::RemoveAndroidFilesDirectoryForTesting(
    const base::FilePath& path) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DoUnmountEvent(*Volume::CreateForAndroidFiles(path));
  return true;
}

void VolumeManager::RemoveDownloadsDirectoryForTesting() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  base::FilePath path;
  if (FindDownloadsMountPointPath(profile_, &path)) {
    DoUnmountEvent(*Volume::CreateForDownloads(path));
  }
}

bool VolumeManager::RegisterDownloadsDirectoryForTesting(
    const base::FilePath& path) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  base::FilePath old_path;
  if (FindDownloadsMountPointPath(profile_, &old_path)) {
    DoUnmountEvent(*Volume::CreateForDownloads(old_path));
  }

  const bool ok = RegisterDownloadsMountPoint(profile_, path);
  // Determine if the local user files directory should be mounted as read-only:
  //  - SkyVault GA is enabled
  //  - Local storage of user files is disallowed by policy
  const bool read_only = IsSkyVaultV2Enabled() && !local_user_files_allowed_;

  // In production, once read_only_local_folders_ is false, the
  // MyFiles/Downloads are unmounted and not mounted again. However, in tests,
  // it's possible to call this function after the SkyVault migration has
  // completed.
  if (read_only && !read_only_local_folders_) {
    LOG(WARNING) << "Adding Downloads volume for testing, even though it "
                    "should've been removed because of SkyVault.";
  }
  return DoMountEvent(
      Volume::CreateForDownloads(path, {}, nullptr, read_only),
      ok ? ash::MountError::kSuccess : ash::MountError::kInvalidPath);
}

bool VolumeManager::RegisterCrostiniDirectoryForTesting(
    const base::FilePath& path) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  const bool ok =
      storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
          file_manager::util::GetCrostiniMountPointName(profile_),
          storage::kFileSystemTypeLocal, storage::FileSystemMountOption(),
          path);
  return DoMountEvent(
      Volume::CreateForSshfsCrostini(path, base::FilePath("/home/testuser")),
      ok ? ash::MountError::kSuccess : ash::MountError::kInvalidPath);
}

bool VolumeManager::AddVolumeForTesting(base::FilePath path,
                                        VolumeType volume_type,
                                        ash::DeviceType device_type,
                                        bool read_only,
                                        base::FilePath device_path,
                                        std::string drive_label,
                                        std::string file_system_type,
                                        bool hidden,
                                        bool watchable) {
  return AddVolumeForTesting(Volume::CreateForTesting(
      std::move(path), volume_type, device_type, read_only,
      std::move(device_path), std::move(drive_label),
      std::move(file_system_type), hidden, watchable));
}

bool VolumeManager::AddVolumeForTesting(std::unique_ptr<Volume> volume) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  return DoMountEvent(std::move(volume));
}

void VolumeManager::RemoveVolumeForTesting(
    const base::FilePath& path,
    VolumeType volume_type,
    ash::DeviceType device_type,
    bool read_only,
    const base::FilePath& device_path,
    const std::string& drive_label,
    const std::string& file_system_type) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DoUnmountEvent(*Volume::CreateForTesting(path, volume_type, device_type,
                                           read_only, device_path, drive_label,
                                           file_system_type));
}

void VolumeManager::RemoveVolumeForTesting(const std::string& volume_id) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DoUnmountEvent(volume_id);
}

void VolumeManager::OnFileSystemMounted() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  // Raise mount event.
  // We can pass ash::MountError::kNone even when authentication is failed
  // or network is unreachable. These two errors will be handled later.
  DoMountEvent(Volume::CreateForDrive(GetDriveMountPointPath()));
}

void VolumeManager::OnFileSystemBeingUnmounted() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DoUnmountEvent(*Volume::CreateForDrive(GetDriveMountPointPath()));
}

void VolumeManager::OnAutoMountableDiskEvent(
    ash::disks::DiskMountManager::DiskEvent event,
    const ash::disks::Disk& disk) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  // Disregard hidden devices.
  if (disk.is_hidden()) {
    return;
  }

  switch (event) {
    case ash::disks::DiskMountManager::DISK_ADDED:
    case ash::disks::DiskMountManager::DISK_CHANGED: {
      if (disk.device_path().empty()) {
        DVLOG(1) << "Empty system path for disk " << disk.device_number();
        return;
      }

      bool mounting = false;
      if (disk.mount_path().empty() && disk.has_media()) {
        const auto device_id = policy::DeviceId::FromDisk(&disk);
        if (policy::ExternalStoragePolicyController::IsDeviceDisabled(
                CHECK_DEREF(profile_->GetPrefs()), device_id)) {
          observers_.Notify(&VolumeManagerObserver::OnDiskAddBlockedByPolicy,
                            disk.device_path());
          return;
        }
        // If disk is not mounted yet and it has media and there is no policy
        // forbidding external storage, give it a try.
        // Initiate disk mount operation. MountPath auto-detects the filesystem
        // format if the second argument is empty.
        disk_mount_manager_->MountPath(
            disk.device_path(), {}, disk.device_label(), {},
            ash::MountType::kDevice,
            GetExternalStorageAccessMode(profile_, device_id),
            base::DoNothing());
        mounting = true;
      }

      // Notify to observers.
      for (auto& observer : observers_) {
        observer.OnDiskAdded(disk, mounting);
      }

      return;
    }

    case ash::disks::DiskMountManager::DISK_REMOVED:
      // If the disk is already mounted, unmount it.
      if (!disk.mount_path().empty()) {
        disk_mount_manager_->UnmountPath(disk.mount_path(), base::DoNothing());
      }

      // Notify to observers.
      for (auto& observer : observers_) {
        observer.OnDiskRemoved(disk);
      }

      return;
  }
  NOTREACHED();
}

void VolumeManager::OnDeviceEvent(
    ash::disks::DiskMountManager::DeviceEvent event,
    const std::string& device_path) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  DVLOG(1) << "OnDeviceEvent: " << event << ", " << device_path;
  switch (event) {
    case ash::disks::DiskMountManager::DEVICE_ADDED:
      for (auto& observer : observers_) {
        observer.OnDeviceAdded(device_path);
      }
      return;
    case ash::disks::DiskMountManager::DEVICE_REMOVED: {
      for (auto& observer : observers_) {
        observer.OnDeviceRemoved(device_path);
      }
      return;
    }
    case ash::disks::DiskMountManager::DEVICE_SCANNED:
      DVLOG(1) << "Ignore SCANNED event: " << device_path;
      return;
  }
  NOTREACHED();
}

void VolumeManager::OnMountEvent(
    ash::disks::DiskMountManager::MountEvent event,
    ash::MountError error,
    const ash::disks::DiskMountManager::MountPoint& mount_info) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  // Network storage is responsible for doing its own mounting.
  if (mount_info.mount_type == ash::MountType::kNetworkStorage) {
    return;
  }

  // Notify a mounting/unmounting event to observers.
  const ash::disks::Disk* const disk =
      disk_mount_manager_->FindDiskBySourcePath(mount_info.source_path);
  std::unique_ptr<Volume> volume = Volume::CreateForRemovable(mount_info, disk);

  switch (event) {
    case ash::disks::DiskMountManager::MOUNTING: {
      DoMountEvent(std::move(volume), error);
      return;
    }

    case ash::disks::DiskMountManager::UNMOUNTING:
      DoUnmountEvent(*volume, error);
      return;
  }

  NOTREACHED() << "Unexpected event type " << event;
}

void VolumeManager::OnFormatEvent(
    ash::disks::DiskMountManager::FormatEvent event,
    ash::FormatError error,
    const std::string& device_path,
    const std::string& device_label) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DVLOG(1) << "OnFormatEvent: " << event << ", error = " << error
           << ", device_path = " << device_path;

  switch (event) {
    case ash::disks::DiskMountManager::FORMAT_STARTED:
      for (auto& observer : observers_) {
        observer.OnFormatStarted(device_path, device_label,
                                 error == ash::FormatError::kSuccess);
      }
      return;

    case ash::disks::DiskMountManager::FORMAT_COMPLETED:
      // Even if format did not complete successfully, try to mount the device
      // so the user can retry.
      // MountPath auto-detects filesystem format if second argument is
      // empty. The third argument (mount label) is not used in a disk mount
      // operation.
      disk_mount_manager_->MountPath(
          device_path, {}, {}, {}, ash::MountType::kDevice,
          GetExternalStorageAccessMode(profile_,
                                       GetDeviceIdFromDevicePath(device_path)),
          base::DoNothing());

      for (auto& observer : observers_) {
        observer.OnFormatCompleted(device_path, device_label,
                                   error == ash::FormatError::kSuccess);
      }

      return;
  }

  NOTREACHED() << "Unexpected FormatEvent " << event;
}

void VolumeManager::OnPartitionEvent(
    ash::disks::DiskMountManager::PartitionEvent event,
    ash::PartitionError error,
    const std::string& device_path,
    const std::string& device_label) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DVLOG(1) << "OnPartitionEvent: " << event << ", error = " << error
           << ", device_path = " << device_path;

  switch (event) {
    case ash::disks::DiskMountManager::PARTITION_STARTED:
      for (auto& observer : observers_) {
        observer.OnPartitionStarted(device_path, device_label,
                                    error == ash::PartitionError::kSuccess);
      }
      return;

    case ash::disks::DiskMountManager::PARTITION_COMPLETED:
      // If partitioning failed, try to mount the device so the user can retry.
      // MountPath auto-detects filesystem format if second argument is
      // empty. The third argument (mount label) is not used in a disk mount
      // operation.
      if (error != ash::PartitionError::kSuccess) {
        disk_mount_manager_->MountPath(
            device_path, {}, {}, {}, ash::MountType::kDevice,
            GetExternalStorageAccessMode(
                profile_, GetDeviceIdFromDevicePath(device_path)),
            base::DoNothing());
      }

      for (auto& observer : observers_) {
        observer.OnPartitionCompleted(device_path, device_label,
                                      error == ash::PartitionError::kSuccess);
      }
      return;
  }

  NOTREACHED() << "Unexpected PartitionEvent " << event;
}

void VolumeManager::OnRenameEvent(
    ash::disks::DiskMountManager::RenameEvent event,
    ash::RenameError error,
    const std::string& device_path,
    const std::string& device_label) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DVLOG(1) << "OnRenameEvent: " << event << ", error = " << error
           << ", device_path = " << device_path;

  switch (event) {
    case ash::disks::DiskMountManager::RENAME_STARTED:
      for (auto& observer : observers_) {
        observer.OnRenameStarted(device_path, device_label,
                                 error == ash::RenameError::kSuccess);
      }
      return;

    case ash::disks::DiskMountManager::RENAME_COMPLETED:
      // Find previous mount point label if it exists
      std::string mount_label;
      auto disk_map_iter = disk_mount_manager_->disks().find(device_path);
      if (disk_map_iter != disk_mount_manager_->disks().end() &&
          !disk_map_iter->get()->base_mount_path().empty()) {
        mount_label = base::FilePath(disk_map_iter->get()->base_mount_path())
                          .BaseName()
                          .AsUTF8Unsafe();
      }

      // Try to mount the device. MountPath auto-detects filesystem format if
      // second argument is empty. Third argument is a mount point name of the
      // disk when it was first time mounted (to preserve mount point regardless
      // of the volume name).
      disk_mount_manager_->MountPath(
          device_path, {}, mount_label, {}, ash::MountType::kDevice,
          GetExternalStorageAccessMode(profile_,
                                       GetDeviceIdFromDevicePath(device_path)),
          base::DoNothing());

      bool successfully_renamed = error == ash::RenameError::kSuccess;
      for (auto& observer : observers_) {
        observer.OnRenameCompleted(device_path, device_label,
                                   successfully_renamed);
      }

      return;
  }

  NOTREACHED() << "Unexpected RenameEvent " << event;
}

void VolumeManager::OnProvidedFileSystemMount(
    const ash::file_system_provider::ProvidedFileSystemInfo& file_system_info,
    ash::file_system_provider::MountContext context,
    base::File::Error error) {
  MountContext volume_context = MOUNT_CONTEXT_UNKNOWN;
  switch (context) {
    case ash::file_system_provider::MOUNT_CONTEXT_USER:
      volume_context = MOUNT_CONTEXT_USER;
      break;
    case ash::file_system_provider::MOUNT_CONTEXT_RESTORE:
      volume_context = MOUNT_CONTEXT_AUTO;
      break;
  }

  std::unique_ptr<Volume> volume =
      Volume::CreateForProvidedFileSystem(file_system_info, volume_context);

  ash::MountError mount_error;
  switch (error) {
    case base::File::FILE_OK:
      mount_error = ash::MountError::kSuccess;
      break;
    case base::File::FILE_ERROR_EXISTS:
      mount_error = ash::MountError::kPathAlreadyMounted;
      break;
    default:
      mount_error = ash::MountError::kUnknownError;
      break;
  }

  DoMountEvent(std::move(volume), mount_error);

  // The FSP is not added to chrome::storage if mounting failed.
  if (error != base::File::FILE_OK) {
    return;
  }

  // Get the FuseBoxDaemon instance.
  if (!fusebox_daemon_) {
    fusebox_daemon_ = file_manager::FuseBoxDaemon::GetInstance();
  }

  // Get the FileSystemURL of the FSP storage device.
  const std::string fsid =
      file_system_info.mount_path().BaseName().AsUTF8Unsafe();
  auto* mount_points = storage::ExternalMountPoints::GetSystemInstance();
  auto fsp_file_system_url = mount_points->CreateExternalFileSystemURL(
      blink::StorageKey::CreateFirstParty(util::GetFilesAppOrigin()), fsid, {});
  const std::string url = fsp_file_system_url.ToGURL().spec();
  DCHECK(fsp_file_system_url.is_valid());

  // Attach the FSP storage device to the fusebox daemon.
  const std::string subdir = FuseBoxSubdirFSP(file_system_info);
  fusebox_daemon_->AttachStorage(subdir, url, !file_system_info.writable());

  // Create a Volume for the fusebox FSP storage device.
  std::unique_ptr<Volume> fusebox_volume = Volume::CreateForProvidedFileSystem(
      file_system_info, volume_context,
      base::FilePath(util::kFuseBoxMediaPath).Append(subdir));

  // Register the fusebox FSP storage device with chrome::storage.
  const std::string fusebox_fsid = base::StrCat(
      {util::kFuseBoxMountNamePrefix, util::kFuseBoxSubdirPrefixFSP, fsid});
  if (!FindExternalMountPoint(fusebox_fsid)) {
    bool result = mount_points->RegisterFileSystem(
        fusebox_fsid, storage::kFileSystemTypeFuseBox,
        storage::FileSystemMountOption(), fusebox_volume->mount_path());
    LOG_IF(ERROR, !result) << "invalid FuseBox FSP mount path";
    DCHECK(result);
  }

  // Mount the fusebox FSP storage device in files app.
  DoMountEvent(std::move(fusebox_volume));
}

void VolumeManager::ConvertFuseBoxFSPVolumeIdToFSPIfNeeded(
    std::string* volume_id) const {
  DCHECK(volume_id);

  static const base::FilePath::CharType kFuseBoxFSPVolumeIdPrefix[] =
      FILE_PATH_LITERAL("fuseboxprovided:fsp:");
  if (!base::StartsWith(*volume_id, kFuseBoxFSPVolumeIdPrefix)) {
    return;
  }

  int prefix = strlen(kFuseBoxFSPVolumeIdPrefix);
  *volume_id = volume_id->substr(prefix).insert(0, "provided:");
}

// TODO(aidazolic): Figure out why it's called twice for every update.
void VolumeManager::OnLocalUserFilesPolicyChanged() {
  if (!base::FeatureList::IsEnabled(features::kSkyVault)) {
    return;
  }

  bool allowed = policy::local_user_files::LocalUserFilesAllowed();
  if (allowed == local_user_files_allowed_) {
    return;
  }
  local_user_files_allowed_ = allowed;

  if (allowed) {
    OnLocalUserFilesEnabled();
  } else {
    OnLocalUserFilesDisabled();
  }
}

void VolumeManager::OnProvidedFileSystemUnmount(
    const ash::file_system_provider::ProvidedFileSystemInfo& file_system_info,
    base::File::Error error) {
  // TODO(mtomasz): Introduce own type, and avoid using MountError internally,
  // since it is related to cros disks only.
  const ash::MountError mount_error = error == base::File::FILE_OK
                                          ? ash::MountError::kSuccess
                                          : ash::MountError::kUnknownError;
  std::unique_ptr<Volume> volume = Volume::CreateForProvidedFileSystem(
      file_system_info, MOUNT_CONTEXT_UNKNOWN);
  DoUnmountEvent(*volume, mount_error);

  // Get FSP chrome::storage |fsid| and fusebox daemon |subdir|.
  const std::string fsid =
      file_system_info.mount_path().BaseName().AsUTF8Unsafe();
  const std::string subdir = FuseBoxSubdirFSP(file_system_info);

  // Unmount the fusebox FSP storage device in files app.
  std::unique_ptr<Volume> fusebox_volume = Volume::CreateForProvidedFileSystem(
      file_system_info, MOUNT_CONTEXT_UNKNOWN,
      base::FilePath(util::kFuseBoxMediaPath).Append(subdir));
  DoUnmountEvent(*fusebox_volume, mount_error);

  // Remove the fusebox FSP storage device from chrome::storage.
  auto* mount_points = storage::ExternalMountPoints::GetSystemInstance();
  const std::string fusebox_fsid = base::StrCat(
      {util::kFuseBoxMountNamePrefix, util::kFuseBoxSubdirPrefixFSP, fsid});
  mount_points->RevokeFileSystem(fusebox_fsid);

  // Detach the fusebox FSP storage device from the fusebox daemon.
  if (fusebox_daemon_) {
    fusebox_daemon_->DetachStorage(subdir);
  }
}

void VolumeManager::OnExternalStorageDisabledChangedUnmountCallback(
    std::vector<std::string> remaining_mount_paths,
    ash::MountError error) {
  LOG_IF(ERROR, error != ash::MountError::kSuccess)
      << "Unmount on ExternalStorageDisabled policy change failed: " << error;

  while (!remaining_mount_paths.empty()) {
    std::string mount_path = remaining_mount_paths.back();
    remaining_mount_paths.pop_back();
    if (!base::Contains(disk_mount_manager_->mount_points(), mount_path)) {
      // The mount point could have already been removed for another reason
      // (i.e. the disk was removed by the user).
      continue;
    }

    disk_mount_manager_->UnmountPath(
        mount_path,
        base::BindOnce(
            &VolumeManager::OnExternalStorageDisabledChangedUnmountCallback,
            weak_ptr_factory_.GetWeakPtr(), std::move(remaining_mount_paths)));
    return;
  }
}

void VolumeManager::OnArcPlayStoreEnabledChanged(bool enabled) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(IsArcEnabled(profile_));
  const bool mounting =
      arc::ShouldAlwaysMountAndroidVolumesInFilesForTesting() || enabled;

  if (mounting == arc_volumes_mounted_) {
    return;
  }

  if (mounting) {
    MountArcRoots();
  } else {
    UnmountArcRoots();
  }

  documents_provider_root_manager_->SetEnabled(mounting);
  arc_volumes_mounted_ = mounting;
}

void VolumeManager::OnShutdown() {
  arc_session_manager_observation_.Reset();
}

void VolumeManager::OnExternalStorageDisabledChanged() {
  // If the policy just got set to disabled we have to unmount every device
  // currently mounted which is not allowlisted. The opposite is fine - we can
  // let the user re-plug their device to make it available.

  const PrefService& pref_service = CHECK_DEREF(profile_->GetPrefs());

  // We do not iterate on mount_points directly, because mount_points can be
  // changed by UnmountPath(). Also, a failing unmount shouldn't be retried
  // indefinitely. So make a set of all the mount points that should be
  // unmounted (all external media mounts which aren't allowlisted), and iterate
  // through them.
  std::vector<std::string> remaining_mount_paths;
  for (const auto& mount_point : disk_mount_manager_->mount_points()) {
    if (mount_point.mount_type == ash::MountType::kDevice &&
        policy::ExternalStoragePolicyController::IsDeviceDisabled(
            pref_service, GetDeviceIdFromDevicePath(mount_point.source_path))) {
      remaining_mount_paths.push_back(mount_point.mount_path);
    }
  }
  if (remaining_mount_paths.empty()) {
    return;
  }

  std::string mount_path = remaining_mount_paths.back();
  remaining_mount_paths.pop_back();
  disk_mount_manager_->UnmountPath(
      mount_path,
      base::BindOnce(
          &VolumeManager::OnExternalStorageDisabledChangedUnmountCallback,
          weak_ptr_factory_.GetWeakPtr(), std::move(remaining_mount_paths)));
}

void VolumeManager::OnExternalStorageReadOnlyChanged() {
  for (const auto& disk : disk_mount_manager_->disks()) {
    const ash::MountAccessMode access_mode = GetExternalStorageAccessMode(
        profile_, policy::DeviceId::FromDisk(disk.get()));
    disk_mount_manager_->RemountRemovableDrive(*disk, access_mode);
  }
}

void VolumeManager::OnExternalStorageAllowlistChanged() {
  // The Allowlist overrides both Disabled and ReadOnly policies, fire both of
  // their listener events.
  OnExternalStorageDisabledChanged();
  OnExternalStorageReadOnlyChanged();
}

void VolumeManager::OnRemovableStorageAttached(
    const storage_monitor::StorageInfo& info) {
  if (!storage_monitor::StorageInfo::IsMTPDevice(info.device_id())) {
    return;
  }

  // Resolve mtp storage name and get MtpStorageInfo.
  std::string storage_name;
  base::RemoveChars(info.location(), kRootPath, &storage_name);
  DCHECK(!storage_name.empty());
  if (get_mtp_storage_info_callback_.is_null()) {
    storage_monitor::StorageMonitor::GetInstance()
        ->media_transfer_protocol_manager()
        ->GetStorageInfo(storage_name,
                         base::BindOnce(&VolumeManager::DoAttachMtpStorage,
                                        weak_ptr_factory_.GetWeakPtr(), info));
  } else {
    get_mtp_storage_info_callback_.Run(
        storage_name, base::BindOnce(&VolumeManager::DoAttachMtpStorage,
                                     weak_ptr_factory_.GetWeakPtr(), info));
  }
}

void VolumeManager::DoAttachMtpStorage(
    const storage_monitor::StorageInfo& info,
    device::mojom::MtpStorageInfoPtr mtp_storage_info) {
  if (!mtp_storage_info) {
    // |mtp_storage_info| can be null. e.g. As OnRemovableStorageAttached and
    // DoAttachMtpStorage are called asynchronously, there can be a race
    // condition where the storage has been already removed in
    // MediaTransferProtocolManager at the time when this method is called.
    return;
  }

  // `mtp_storage_info` is a protocol buffer and proto file syntax has a uint32
  // type, but not a uint16 type.
  const policy::DeviceId device_id =
      policy::DeviceId(static_cast<uint16_t>(mtp_storage_info->vendor_id),
                       static_cast<uint16_t>(mtp_storage_info->product_id));

  if (policy::ExternalStoragePolicyController::IsDeviceDisabled(
          CHECK_DEREF(profile_->GetPrefs()), device_id)) {
    const std::string device_location =
        storage_monitor::GetDeviceLocationFromStorageName(
            mtp_storage_info->storage_name);
    observers_.Notify(&VolumeManagerObserver::OnDiskAddBlockedByPolicy,
                      device_location);
    return;
  }

  // Mtp write is enabled only when the device is writable, supports generic
  // hierarchical file system, and writing to external storage devices is not
  // prohibited by the preference.
  const bool read_only =
      mtp_storage_info->access_capability != kAccessCapabilityReadWrite ||
      mtp_storage_info->filesystem_type != kFilesystemTypeGenericHierarchical ||
      policy::ExternalStoragePolicyController::IsDeviceReadOnly(
          CHECK_DEREF(profile_->GetPrefs()), device_id);

  const base::FilePath path = base::FilePath::FromUTF8Unsafe(info.location());
  const std::string fsid = GetMountPointNameForMediaStorage(info);
  const std::string base_name = base::UTF16ToUTF8(info.model_name());

  // Assign a fresh volume ID based on the volume name.
  std::string label = base_name;
  for (int i = 2; mounted_volumes_.count(kMtpVolumeIdPrefix + label) != 0;
       ++i) {
    label = base_name + base::StringPrintf(" (%d)", i);
  }

  // Register the MTP storage device with chrome::storage.
  auto* mount_points = storage::ExternalMountPoints::GetSystemInstance();
  if (!FindExternalMountPoint(fsid)) {
    bool result = mount_points->RegisterFileSystem(
        fsid, storage::kFileSystemTypeDeviceMediaAsFileStorage,
        storage::FileSystemMountOption(), path);
    LOG_IF(ERROR, !result) << "invalid MTP mount path";
    DCHECK(result);
  }

  // Register the MTP storage device with the MTPDeviceMapService.
  content::GetIOThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(&MTPDeviceMapService::RegisterMTPFileSystem,
                     base::Unretained(MTPDeviceMapService::GetInstance()),
                     info.location(), fsid, read_only));

  // Mount the MTP storage device in files app.
  std::unique_ptr<Volume> volume = Volume::CreateForMTP(path, label, read_only);
  DoMountEvent(std::move(volume));

  // Get the FuseBoxDaemon instance.
  if (!fusebox_daemon_) {
    fusebox_daemon_ = file_manager::FuseBoxDaemon::GetInstance();
  }

  // Get the FileSystemURL of the MTP storage device.
  auto mtp_file_system_url = mount_points->CreateExternalFileSystemURL(
      blink::StorageKey::CreateFirstParty(util::GetFilesAppOrigin()), fsid, {});
  const std::string url = mtp_file_system_url.ToGURL().spec();
  DCHECK(mtp_file_system_url.is_valid());

  // Attach the MTP storage device to the fusebox daemon.
  std::string subdir = FuseBoxSubdirMTP(info.device_id());
  fusebox_daemon_->AttachStorage(subdir, url, read_only);

  // Create a Volume for the fusebox MTP storage device.
  std::unique_ptr<Volume> fusebox_volume = Volume::CreateForMTP(
      base::FilePath(util::kFuseBoxMediaPath).Append(subdir), label, read_only,
      /*use_fusebox=*/true);

  // Register the fusebox MTP storage device with chrome::storage.
  const std::string fusebox_fsid =
      base::StrCat({util::kFuseBoxMountNamePrefix, subdir});
  if (!FindExternalMountPoint(fusebox_fsid)) {
    bool result = mount_points->RegisterFileSystem(
        fusebox_fsid, storage::kFileSystemTypeFuseBox,
        storage::FileSystemMountOption(), fusebox_volume->mount_path());
    LOG_IF(ERROR, !result) << "invalid FuseBox MTP mount path";
    DCHECK(result);
  }

  // Mount the fusebox MTP storage device in files app.
  DoMountEvent(std::move(fusebox_volume));
}

void VolumeManager::OnRemovableStorageDetached(
    const storage_monitor::StorageInfo& info) {
  if (!storage_monitor::StorageInfo::IsMTPDevice(info.device_id())) {
    return;
  }

  Volumes::const_iterator it = mounted_volumes_.begin();
  for (const Volumes::const_iterator end = mounted_volumes_.end();; ++it) {
    if (it == end) {
      return;
    }
    DCHECK(*it);
    if ((*it)->source_path().value() == info.location()) {
      break;
    }
  }

  // Unmount the MTP storage device in files app.
  const std::string volume_id = (*it)->volume_id();
  DoUnmountEvent(std::move(it));

  // Remove the MTP storage device from chrome::storage.
  const std::string fsid = GetMountPointNameForMediaStorage(info);
  storage::ExternalMountPoints* const mount_points =
      storage::ExternalMountPoints::GetSystemInstance();
  mount_points->RevokeFileSystem(fsid);

  // Remove the MTP storage device from the MTPDeviceMapService.
  content::GetIOThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(&MTPDeviceMapService::RevokeMTPFileSystem,
                     base::Unretained(MTPDeviceMapService::GetInstance()),
                     fsid));

  // Unmount the fusebox MTP storage device in files app.
  base::WeakPtr<Volume> fusebox_volume =
      FindVolumeById(util::kFuseBox + volume_id);
  if (fusebox_volume) {
    DoUnmountEvent(*fusebox_volume);
  }

  // Remove the fusebox MTP storage device from chrome::storage.
  std::string subdir = FuseBoxSubdirMTP(info.device_id());
  const std::string fusebox_fsid =
      base::StrCat({util::kFuseBoxMountNamePrefix, subdir});
  mount_points->RevokeFileSystem(fusebox_fsid);

  // Detach the fusebox MTP storage device from the fusebox daemon.
  if (fusebox_daemon_) {
    fusebox_daemon_->DetachStorage(subdir);
  }
}

void VolumeManager::OnDocumentsProviderRootAdded(
    const std::string& authority,
    const std::string& root_id,
    const std::string& document_id,
    const std::string& title,
    const std::string& summary,
    const GURL& icon_url,
    bool read_only,
    const std::vector<std::string>& mime_types) {
  arc::ArcDocumentsProviderRootMap::GetForArcBrowserContext()->RegisterRoot(
      authority, document_id, root_id, read_only, mime_types);
  DoMountEvent(Volume::CreateForDocumentsProvider(
      authority, root_id, title, summary, icon_url, read_only,
      /*optional_fusebox_subdir=*/std::string()));

  // Get the FuseBoxDaemon instance.
  if (!fusebox_daemon_) {
    fusebox_daemon_ = file_manager::FuseBoxDaemon::GetInstance();
  }

  // Get the FileSystemURL of the ADP storage device.
  auto* mount_points = storage::ExternalMountPoints::GetSystemInstance();
  auto adp_file_system_url = mount_points->CreateExternalFileSystemURL(
      blink::StorageKey::CreateFirstParty(util::GetFilesAppOrigin()),
      arc::kDocumentsProviderMountPointName,
      arc::GetDocumentsProviderMountPathSuffix(authority, root_id));
  const std::string url = adp_file_system_url.ToGURL().spec();
  DCHECK(adp_file_system_url.is_valid());

  // Attach the ADP storage device to the fusebox daemon.
  std::string subdir = FuseBoxSubdirADP(authority, root_id);
  fusebox_daemon_->AttachStorage(subdir, url, read_only);

  // Create a Volume for the fusebox ADP storage device.
  std::unique_ptr<Volume> fusebox_volume = Volume::CreateForDocumentsProvider(
      authority, root_id, title, summary, icon_url, read_only, subdir);

  // Register the fusebox ADP storage device with chrome::storage.
  const std::string fusebox_fsid =
      base::StrCat({util::kFuseBoxMountNamePrefix, subdir});
  if (!FindExternalMountPoint(fusebox_fsid)) {
    bool result = mount_points->RegisterFileSystem(
        fusebox_fsid, storage::kFileSystemTypeFuseBox,
        storage::FileSystemMountOption(), fusebox_volume->mount_path());
    LOG_IF(ERROR, !result) << "invalid FuseBox ADP mount path";
    DCHECK(result);
  }

  // Mount the fusebox ADP storage device in files app.
  DoMountEvent(std::move(fusebox_volume));
}

void VolumeManager::OnDocumentsProviderRootRemoved(const std::string& authority,
                                                   const std::string& root_id) {
  DoUnmountEvent(*Volume::CreateForDocumentsProvider(
      authority, root_id, std::string(), std::string(), GURL(), false,
      /*optional_fusebox_subdir=*/std::string()));
  arc::ArcDocumentsProviderRootMap::GetForArcBrowserContext()->UnregisterRoot(
      authority, root_id);

  // Unmount the fusebox ADP storage device in files app.
  std::string volume_id = arc::GetDocumentsProviderVolumeId(authority, root_id);
  base::WeakPtr<Volume> fusebox_volume =
      FindVolumeById(util::kFuseBox + volume_id);
  if (fusebox_volume) {
    DoUnmountEvent(*fusebox_volume);
  }

  // Remove the fusebox ADP storage device from chrome::storage.
  std::string subdir = FuseBoxSubdirADP(authority, root_id);
  auto* mount_points = storage::ExternalMountPoints::GetSystemInstance();
  const std::string fusebox_fsid =
      base::StrCat({util::kFuseBoxMountNamePrefix, subdir});
  mount_points->RevokeFileSystem(fusebox_fsid);

  // Detach the fusebox ADP storage device from the fusebox daemon.
  if (fusebox_daemon_) {
    fusebox_daemon_->DetachStorage(subdir);
  }
}

void VolumeManager::OnClipboardDataChanged() {
  // Ignore the event created when we change the clipboard.
  if (ignore_clipboard_changed_) {
    return;
  }

  auto* clipboard = ui::ClipboardNonBacked::GetForCurrentThread();
  if (!clipboard) {
    return;
  }

  ui::DataTransferEndpoint dte(ui::EndpointType::kClipboardHistory);
  std::string web_custom_data;
  const ui::ClipboardData* data = clipboard->GetClipboardData(&dte);
  if (data) {
    web_custom_data = data->GetDataTransferCustomData();
  }
  if (web_custom_data.empty()) {
    return;
  }

  base::Pickle pickle =
      base::Pickle::WithUnownedBuffer(base::as_byte_span(web_custom_data));
  std::vector<ui::FileInfo> file_info =
      file_manager::util::ParseFileSystemSources(
          base::OptionalToPtr(data->source()), pickle);
  if (!file_info.empty()) {
    auto with_files = std::make_unique<ui::ClipboardData>(*data);
    with_files->set_filenames(std::move(file_info));
    base::AutoReset<bool> reset(&ignore_clipboard_changed_, true);
    clipboard->WriteClipboardData(std::move(with_files));
  }
}

void VolumeManager::AddSmbFsVolume(const base::FilePath& mount_point,
                                   const std::string& display_name) {
  DoMountEvent(Volume::CreateForSmb(mount_point, display_name));
}

void VolumeManager::RemoveSmbFsVolume(const base::FilePath& mount_point) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  DoUnmountEvent(*Volume::CreateForSmb(mount_point, ""));
}

void VolumeManager::OnMigrationSucceededForTesting() {
  read_only_local_folders_ = false;
  // Don't call OnLocalUserFilesPolicyChanged() because it's no-op if there's no
  // change, and we want to force mount/unmount.
  if (local_user_files_allowed_) {
    OnLocalUserFilesEnabled();
  } else {
    OnLocalUserFilesDisabled();
  }
}

void VolumeManager::OnDiskMountManagerRefreshed(bool success) {
  if (!success) {
    LOG(ERROR) << "Cannot refresh disk mount manager";
    return;
  }

  std::vector<std::unique_ptr<Volume>> archives;

  const ash::disks::DiskMountManager::MountPoints& mount_points =
      disk_mount_manager_->mount_points();
  for (const auto& mount_point : mount_points) {
    switch (mount_point.mount_type) {
      case ash::MountType::kArchive: {
        // Archives are mounted after other types of volume. See below.
        archives.push_back(Volume::CreateForRemovable(mount_point, nullptr));
        break;
      }
      case ash::MountType::kDevice: {
        DoMountEvent(Volume::CreateForRemovable(
            mount_point, disk_mount_manager_->FindDiskBySourcePath(
                             mount_point.source_path)));
        break;
      }
      case ash::MountType::kNetworkStorage: {
        break;
      }
      case ash::MountType::kInvalid: {
        NOTREACHED();
      }
    }
  }

  // We mount archives only if they are opened from currently mounted volumes.
  // To check the condition correctly in DoMountEvent, we care about the order.
  std::vector<bool> done(archives.size(), false);
  for (size_t i = 0; i < archives.size(); ++i) {
    if (done[i]) {
      continue;
    }

    std::vector<std::unique_ptr<Volume>> chain;
    // done[x] = true means archives[x] is null and that volume is in |chain|.
    done[i] = true;
    chain.push_back(std::move(archives[i]));

    // If archives[i]'s source_path is in another archive, mount it first.
    for (size_t parent = i + 1; parent < archives.size(); ++parent) {
      if (!done[parent] && archives[parent]->mount_path().IsParent(
                               chain.back()->source_path())) {
        // done[parent] started false, so archives[parent] is non-null.
        done[parent] = true;
        chain.push_back(std::move(archives[parent]));
        parent = i + 1;  // Search archives[parent]'s parent from the beginning.
      }
    }

    // Mount from the tail of chain.
    while (!chain.empty()) {
      DoMountEvent(std::move(chain.back()));
      chain.pop_back();
    }
  }
}

void VolumeManager::OnStorageMonitorInitialized() {
  VLOG(1) << *this << "::OnStorageMonitorInitialized";

  const std::vector<storage_monitor::StorageInfo> storages =
      storage_monitor::StorageMonitor::GetInstance()->GetAllAvailableStorages();
  for (const storage_monitor::StorageInfo& storage : storages) {
    OnRemovableStorageAttached(storage);
  }

  storage_monitor::StorageMonitor::GetInstance()->AddObserver(this);
}

bool VolumeManager::DoMountEvent(std::unique_ptr<Volume> volume_ptr,
                                 ash::MountError error) {
  DCHECK(volume_ptr);
  const Volume& volume = *volume_ptr;

  // Archive files are mounted globally in system. We however don't want to show
  // archives from profile-specific folders (Drive/Downloads) of other users in
  // multi-profile session. To this end, we filter out archives not on the
  // volumes already mounted on this VolumeManager instance.
  if (volume.type() == VOLUME_TYPE_MOUNTED_ARCHIVE_FILE) {
    // Source may be in Drive cache folder under the current profile directory.
    bool from_current_profile =
        profile_->GetPath().IsParent(volume.source_path());
    for (const auto& mounted_volume : mounted_volumes_) {
      DCHECK(mounted_volume);
      if (mounted_volume->mount_path().IsParent(volume.source_path())) {
        from_current_profile = true;
        break;
      }
    }
    if (!from_current_profile) {
      return false;
    }
  }

  // Filter out removable disks if forbidden by policy for this profile.
  if (volume.type() == VOLUME_TYPE_REMOVABLE_DISK_PARTITION &&
      policy::ExternalStoragePolicyController::IsDeviceDisabled(
          CHECK_DEREF(profile_->GetPrefs()),
          GetDeviceIdFromDevicePath(volume.source_path().AsUTF8Unsafe()))) {
    observers_.Notify(&VolumeManagerObserver::OnDiskAddBlockedByPolicy,
                      volume.source_path().AsUTF8Unsafe());
    return false;
  }

  bool inserted = false;

  if (error == ash::MountError::kSuccess ||
      volume.mount_condition() != ash::MountError::kSuccess) {
    const auto [it, ok] = mounted_volumes_.insert(std::move(volume_ptr));
    if (ok) {
      inserted = true;
      VLOG(1) << "Added volume '" << volume.volume_id() << "'";
      UMA_HISTOGRAM_ENUMERATION("FileBrowser.VolumeType", volume.type(),
                                NUM_VOLUME_TYPE);
    } else {
      DCHECK(volume_ptr);
      DCHECK_EQ((*it)->volume_id(), volume.volume_id());

      // It is possible for a Volume object with different properties to be
      // inserted here. Replace the Volume in |mounted_volumes_|.
      const_cast<std::unique_ptr<Volume>&>(*it) = std::move(volume_ptr);
      VLOG(1) << "Replaced volume '" << volume.volume_id() << "'";
    }

    DCHECK_EQ(&volume, it->get());
  }

  for (auto& observer : observers_) {
    observer.OnVolumeMounted(error, volume);
  }

  return inserted;
}

void VolumeManager::DoUnmountEvent(Volumes::const_iterator it,
                                   const ash::MountError error) {
  DCHECK(it != mounted_volumes_.end());

  // Hold a reference to the removed Volume from |mounted_volumes_|, because
  // OnVolumeMounted() will access it.
  const Volume& volume = **it;
  Volumes::node_type node_to_delete;
  if (error == ash::MountError::kSuccess) {
    node_to_delete = mounted_volumes_.extract(std::move(it));
  }

  VLOG_IF(1, node_to_delete) << "Removed volume '" << volume.volume_id() << "'";

  for (auto& observer : observers_) {
    observer.OnVolumeUnmounted(error, volume);
  }
}

base::FilePath VolumeManager::GetDriveMountPointPath() const {
  return drive_integration_service_->GetMountPointPath();
}

void VolumeManager::DoUnmountEvent(std::string_view volume_id,
                                   ash::MountError error) {
  Volumes::const_iterator it = mounted_volumes_.find(volume_id);
  if (it == mounted_volumes_.end()) {
    LOG(WARNING) << "Cannot find volume '" << volume_id << "' to unmount it";
    return;
  }
  DoUnmountEvent(std::move(it), error);
}

void VolumeManager::OnSshfsCrostiniUnmountCallback(
    const base::FilePath& sshfs_mount_path,
    RemoveSshfsCrostiniVolumeCallback callback,
    ash::MountError error) {
  if ((error == ash::MountError::kSuccess) ||
      (error == ash::MountError::kPathNotMounted)) {
    // Remove metadata associated with the mount. It will be a no-op if it
    // wasn't mounted or unmounted out of band.
    DoUnmountEvent(
        *Volume::CreateForSshfsCrostini(sshfs_mount_path, base::FilePath()));
    if (callback) {
      std::move(callback).Run(true);
    }
    return;
  }

  LOG(ERROR) << "Cannot unmount '" << sshfs_mount_path << "'";
  if (callback) {
    std::move(callback).Run(false);
  }
}

void VolumeManager::OnSftpGuestOsUnmountCallback(
    const base::FilePath& sftp_mount_path,
    const guest_os::VmType vm_type,
    RemoveSftpGuestOsVolumeCallback callback,
    ash::MountError error) {
  if ((error == ash::MountError::kSuccess) ||
      (error == ash::MountError::kPathNotMounted)) {
    // Remove metadata associated with the mount. It will be a no-op if it
    // wasn't mounted or unmounted out of band. We need the VolumeId to be
    // consistent, which means the mount path needs to be the same.
    // display_name, remote_mount_path and vm_type aren't needed and we don't
    // know them at unmount so leave them blank.
    DoUnmountEvent(*Volume::CreateForSftpGuestOs("", sftp_mount_path,
                                                 base::FilePath(), vm_type));
    if (callback) {
      std::move(callback).Run(true);
    }
    return;
  }

  LOG(ERROR) << "Cannot unmount SFTP path '" << sftp_mount_path
             << "': " << error;
  if (callback) {
    std::move(callback).Run(false);
  }
}

void VolumeManager::MountDownloadsVolume(bool read_only) {
  const base::FilePath localVolume =
      file_manager::util::GetMyFilesFolderForProfile(profile_);
  const bool success = RegisterDownloadsMountPoint(profile_, localVolume);
  DCHECK(success);
  DoMountEvent(Volume::CreateForDownloads(localVolume, {}, nullptr, read_only));
  if (ash::features::IsFileManagerFuseBoxDebugEnabled()) {
    if (auto volume = CreateForFuseBoxDownloads(profile_, fusebox_daemon_.get(),
                                                "fusebox Downloads")) {
      DoMountEvent(std::move(volume));
    }
  }

  // Asynchronously record the disk usage for the downloads path.
  base::ThreadPool::PostTask(
      FROM_HERE,
      {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
       base::TaskPriority::BEST_EFFORT},
      base::BindOnce(&RecordDownloadsDiskUsageStats, std::move(localVolume)));
}

void VolumeManager::UnmountDownloadsVolume() {
  const base::FilePath localVolume =
      file_manager::util::GetMyFilesFolderForProfile(profile_);
  RevokeDownloadsMountPoint(profile_, localVolume);
  DoUnmountEvent(*Volume::CreateForDownloads(localVolume));
  if (ash::features::IsFileManagerFuseBoxDebugEnabled()) {
    if (auto volume = CreateForFuseBoxDownloads(profile_, fusebox_daemon_.get(),
                                                "fusebox Downloads")) {
      DoUnmountEvent(*volume);
    }
  }
}

void VolumeManager::MountArcRoots() {
  DCHECK(IsArcEnabled(profile_));
  if (arc_volumes_mounted_) {
    return;
  }
  DoMountEvent(Volume::CreateForMediaView(arc::kImagesRootId));
  DoMountEvent(Volume::CreateForMediaView(arc::kVideosRootId));
  DoMountEvent(Volume::CreateForMediaView(arc::kAudioRootId));
  DoMountEvent(Volume::CreateForMediaView(arc::kDocumentsRootId));
  if (!arc::IsArcVmEnabled()) {
    DoMountEvent(
        Volume::CreateForAndroidFiles(base::FilePath(util::kAndroidFilesPath)));
  }
  arc_volumes_mounted_ = true;
}

void VolumeManager::UnmountArcRoots() {
  DCHECK(IsArcEnabled(profile_));
  if (!arc_volumes_mounted_) {
    return;
  }
  DoUnmountEvent(*Volume::CreateForMediaView(arc::kImagesRootId));
  DoUnmountEvent(*Volume::CreateForMediaView(arc::kVideosRootId));
  DoUnmountEvent(*Volume::CreateForMediaView(arc::kAudioRootId));
  DoUnmountEvent(*Volume::CreateForMediaView(arc::kDocumentsRootId));
  if (!arc::IsArcVmEnabled()) {
    DoUnmountEvent(*Volume::CreateForAndroidFiles(
        base::FilePath(util::kAndroidFilesPath)));
  }
  arc_volumes_mounted_ = false;
}

void VolumeManager::UnsubscribeFromArcEvents() {
  if (!IsArcEnabled(profile_)) {
    return;
  }
  // TODO(crbug.com/40497410): We need nullptr check here because
  // ArcSessionManager may or may not be alive at this point.
  if (arc::ArcSessionManager::Get()) {
    arc_session_manager_observation_.Reset();
  }
}

void VolumeManager::SubscribeAndMountArc() {
  if (!IsArcEnabled(profile_)) {
    return;
  }
  documents_provider_root_manager_->AddObserver(this);
  // Registers a mount point for Android files only when the flag is enabled.
  RegisterAndroidFilesMountPoint();
  if (arc::ArcSessionManager::Get()) {
    arc_session_manager_observation_.Observe(arc::ArcSessionManager::Get());
  } else {
    // Can be NULL only in tests.
    CHECK_IS_TEST();
  }
  // Trigger mounting if enabled by policy.
  OnArcPlayStoreEnabledChanged(arc::IsArcPlayStoreEnabledForProfile(profile_));
}

void VolumeManager::UnsubscribeAndUnmountArc() {
  if (!IsArcEnabled(profile_)) {
    return;
  }
  documents_provider_root_manager_->RemoveObserver(this);
  UnsubscribeFromArcEvents();
  UnmountArcRoots();
  RevokeAndroidFilesMountPoint();
}

void VolumeManager::OnLocalUserFilesEnabled() {
  CHECK(policy::local_user_files::LocalUserFilesAllowed());
  MountDownloadsVolume();
  SubscribeAndMountArc();
}

void VolumeManager::OnLocalUserFilesDisabled() {
  CHECK(!policy::local_user_files::LocalUserFilesAllowed());
  UnsubscribeAndUnmountArc();
  UnmountDownloadsVolume();
  if (IsSkyVaultV2Enabled() && read_only_local_folders_) {
    // Keep the volume in GA version. It will be removed after migration.
    MountDownloadsVolume(/*read_only=*/true);
  }
}

void VolumeManager::OnMigrationSucceeded() {
  if (policy::local_user_files::LocalUserFilesAllowed()) {
    LOG(ERROR)
        << "OnMigrationSucceeded() called but local files allowed, ignoring.";
    return;
  }

  read_only_local_folders_ = false;
  OnLocalUserFilesDisabled();
}

void VolumeManager::OnMigrationReset() {
  if (!read_only_local_folders_) {
    read_only_local_folders_ = true;
    OnLocalUserFilesPolicyChanged();
  }
}

std::optional<policy::DeviceId> VolumeManager::GetDeviceIdFromDevicePath(
    std::string_view device_path) {
  const ash::disks::Disk* disk =
      disk_mount_manager_->FindDiskBySourcePath(device_path);
  return policy::DeviceId::FromDisk(disk);
}

}  // namespace file_manager
