// 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/path_util.h"

#include <memory>
#include <string_view>
#include <utility>

#include "ash/constants/ash_switches.h"
#include "base/barrier_closure.h"
#include "base/base64.h"
#include "base/check_op.h"
#include "base/functional/bind.h"
#include "base/no_destructor.h"
#include "base/pickle.h"
#include "base/strings/escape.h"
#include "base/strings/strcat.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/system/sys_info.h"
#include "chrome/browser/ash/arc/fileapi/arc_documents_provider_root.h"
#include "chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map.h"
#include "chrome/browser/ash/arc/fileapi/arc_media_view_util.h"
#include "chrome/browser/ash/arc/fileapi/chrome_content_provider_url_util.h"
#include "chrome/browser/ash/crostini/crostini_manager.h"
#include "chrome/browser/ash/crostini/crostini_util.h"
#include "chrome/browser/ash/drive/drive_integration_service.h"
#include "chrome/browser/ash/drive/drive_integration_service_factory.h"
#include "chrome/browser/ash/drive/file_system_util.h"
#include "chrome/browser/ash/file_manager/fileapi_util.h"
#include "chrome/browser/ash/file_manager/volume_manager.h"
#include "chrome/browser/ash/fileapi/external_file_url_util.h"
#include "chrome/browser/ash/fileapi/file_system_backend.h"
#include "chrome/browser/ash/fusebox/fusebox_server.h"
#include "chrome/browser/ash/guest_os/guest_os_session_tracker.h"
#include "chrome/browser/ash/guest_os/guest_os_session_tracker_factory.h"
#include "chrome/browser/ash/guest_os/public/guest_os_mount_provider.h"
#include "chrome/browser/ash/guest_os/public/guest_os_service.h"
#include "chrome/browser/ash/guest_os/public/guest_os_service_factory.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/ash/smb_client/smb_service.h"
#include "chrome/browser/ash/smb_client/smb_service_factory.h"
#include "chrome/browser/ash/smb_client/smbfs_share.h"
#include "chrome/browser/download/download_dir_util.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h"
#include "chromeos/ash/components/disks/disk.h"
#include "chromeos/ash/components/disks/disk_mount_manager.h"
#include "chromeos/ash/experiences/arc/arc_features.h"
#include "chromeos/ash/experiences/arc/arc_util.h"
#include "components/drive/file_system_core_util.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/common/extension.h"
#include "net/base/filename_util.h"
#include "storage/browser/file_system/external_mount_points.h"
#include "storage/common/file_system/file_system_types.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/cros_system_api/dbus/fusebox/dbus-constants.h"
#include "ui/base/clipboard/custom_data_helper.h"
#include "ui/base/clipboard/file_info.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace file_manager::util {
namespace {

using base::FilePath;
using base::StrCat;
using drive::DriveIntegrationService;
using drive::DriveIntegrationServiceFactory;
using l10n_util::GetStringUTF8;

constexpr char kAndroidFilesMountPointName[] = "android_files";
constexpr char kCrostiniMapGoogleDrive[] = "GoogleDrive";
constexpr char kCrostiniMapLinuxFiles[] = "LinuxFiles";
constexpr char kCrostiniMapMyDrive[] = "MyDrive";
constexpr char kCrostiniMapPlayFiles[] = "PlayFiles";
constexpr char kCrostiniMapSmbFs[] = "SMB";
constexpr char kCrostiniMapFusebox[] = "Fusebox";
constexpr char kCrostiniMapTeamDrives[] = "SharedDrives";
constexpr char kCrostiniMapSharedWithMe[] = "SharedWithMe";
constexpr char kCrostiniMapShortcutsSharedWithMe[] = "ShortcutsSharedWithMe";
constexpr char kFolderNameDownloads[] = "Downloads";
constexpr char kFolderNameMyFiles[] = "MyFiles";
constexpr char kFolderNamePvmDefault[] = "PvmDefault";
constexpr char kFolderNameCamera[] = "Camera";
constexpr char kFolderNameShareCache[] = "ShareCache";
constexpr char kDisplayNameGoogleDrive[] = "Google Drive";
constexpr char kDisplayNameMicrosoftOneDrive[] = "Microsoft OneDrive";
constexpr char kDriveFsDirComputers[] = "Computers";
constexpr char kDriveFsDirSharedWithMe[] = ".files-by-id";
constexpr char kDriveFsDirShortcutsSharedWithMe[] = ".shortcut-targets-by-id";
constexpr char kDriveFsDirRoot[] = "root";
constexpr char kDriveFsDirTeamDrives[] = "team_drives";

constexpr char16_t kFilesAppMimeSources[] = u"fs/sources";
constexpr char16_t kFilesAppSeparator16[] = u"\n";

// Sync with the root name defined with the file provider in ARC++ side.
constexpr FilePath::CharType kArcDownloadRoot[] =
    FILE_PATH_LITERAL("/download");
constexpr FilePath::CharType kArcExternalFilesRoot[] =
    FILE_PATH_LITERAL("/external_files");
// Sync with the volume provider in ARC++ side.
constexpr char kArcStorageContentUrlPrefix[] =
    "content://org.chromium.arc.volumeprovider/";
// A predefined removable media UUID for testing. Defined in
// chromeos/ash/experiences/arc/volume_mounter/arc_volume_mounter_bridge.cc.
// TODO(crbug.com/1274481): Move ash-wide constants to a common place.
constexpr char kArcRemovableMediaUuidForTesting[] =
    "00000000000000000000000000000000DEADBEEF";
// The dummy UUID of the MyFiles volume is taken from
// chromeos/ash/experiences/arc/volume_mounter/arc_volume_mounter_bridge.cc.
// TODO(crbug.com/929031): Move MyFiles constants to a common place.
constexpr char kArcMyFilesContentUrlPrefix[] =
    "content://org.chromium.arc.volumeprovider/"
    "0000000000000000000000000000CAFEF00D2019/";

// Helper function for |ConvertToContentUrls|.
void OnSingleContentUrlResolved(const base::RepeatingClosure& barrier_closure,
                                std::vector<GURL>* out_urls,
                                size_t index,
                                const GURL& url) {
  (*out_urls)[index] = url;
  barrier_closure.Run();
}

// Helper function for |ConvertToContentUrls|.
void OnAllContentUrlsResolved(
    ConvertToContentUrlsCallback callback,
    std::unique_ptr<std::vector<GURL>> urls,
    std::unique_ptr<std::vector<FilePath>> paths_to_share) {
  std::move(callback).Run(*urls, *paths_to_share);
}

// By default, in ChromeOS it uses the $profile_dir/MyFiles however,
// for manual tests/development in linux-chromeos it uses $HOME/Downloads for
// chrome binary and a temp dir for browser tests. The flag
// `--use-myfiles-in-user-data-dir-for-testing` forces the ChromeOS pattern,
// even for non-ChromeOS environments.
bool ShouldMountPrimaryUserDownloads(Profile* profile) {
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          ash::switches::kUseMyFilesInUserDataDirForTesting)) {
    return false;
  }

  if (!base::SysInfo::IsRunningOnChromeOS() &&
      user_manager::UserManager::IsInitialized()) {
    const user_manager::User* const user =
        ash::ProfileHelper::Get()->GetUserByProfile(
            profile->GetOriginalProfile());
    const user_manager::User* const primary_user =
        user_manager::UserManager::Get()->GetPrimaryUser();
    return user == primary_user;
  }

  return false;
}

// Extracts the Drive path from the given path located under the legacy Drive
// mount point. Returns an empty path if |path| is not under the legacy Drive
// mount point.
// Example: ExtractLegacyDrivePath("/special/drive-xxx/foo.txt") =>
//   "drive/foo.txt"
FilePath ExtractLegacyDrivePath(const FilePath& path) {
  std::vector<FilePath::StringType> components = path.GetComponents();
  if (components.size() < 3) {
    return FilePath();
  }
  if (components[0] != FILE_PATH_LITERAL("/")) {
    return FilePath();
  }
  if (components[1] != FILE_PATH_LITERAL("special")) {
    return FilePath();
  }
  static const FilePath::CharType kPrefix[] = FILE_PATH_LITERAL("drive");
  if (components[2].compare(0, std::size(kPrefix) - 1, kPrefix) != 0) {
    return FilePath();
  }

  FilePath drive_path = drive::util::GetDriveGrandRootPath();
  for (size_t i = 3; i < components.size(); ++i) {
    drive_path = drive_path.Append(components[i]);
  }
  return drive_path;
}

// Extracts the volume name of a removable device. |relative_path| is expected
// to be of the form <volume name>/..., which is relative to /media/removable.
std::string ExtractVolumeNameFromRelativePathForRemovableMedia(
    const FilePath& relative_path) {
  std::vector<FilePath::StringType> components = relative_path.GetComponents();
  if (components.empty()) {
    LOG(WARNING) << "Failed to extract volume name from relative path: "
                 << relative_path;
    return std::string();
  }
  return components[0];
}

// Returns the source path of a removable device using its volume name as a key.
// An empty string is returned when it fails to get a valid mount point from
// DiskMountManager.
std::string GetSourcePathForRemovableMedia(const std::string& volume_name) {
  const std::string mount_path(
      base::StringPrintf("%s/%s", kRemovableMediaPath, volume_name.c_str()));
  const auto& mount_points =
      ash::disks::DiskMountManager::GetInstance()->mount_points();
  const auto found = mount_points.find(mount_path);
  return found == mount_points.end() ? std::string() : found->source_path;
}

// Returns the UUID of a removable device using its volume name as a key.
// An empty string is returned when it fails to get valid source path and disk
// from DiskMountManager.
std::string GetFsUuidForRemovableMedia(const std::string& volume_name) {
  const std::string source_path = GetSourcePathForRemovableMedia(volume_name);
  if (source_path.empty()) {
    LOG(WARNING) << "No source path is found for volume name: " << volume_name;
    return std::string();
  }
  const ash::disks::Disk* disk =
      ash::disks::DiskMountManager::GetInstance()->FindDiskBySourcePath(
          source_path);
  std::string fs_uuid = disk == nullptr ? std::string() : disk->fs_uuid();
  if (fs_uuid.empty()) {
    LOG(WARNING) << "No UUID is found for volume name: " << volume_name;
  }
  return fs_uuid;
}

// Same as parent.AppendRelativePath(child, path) except that it allows
// parent == child, in which case path is unchanged.
bool AppendRelativePath(const FilePath& parent,
                        const FilePath& child,
                        FilePath* path) {
  return child == parent || parent.AppendRelativePath(child, path);
}

// Same as parent.AppendRelativePath(child, path) except that the relative path
// to the child is just set to `path` (instead of being appended).
// Note that `path` is always cleared at the beginning, so it becomes empty when
// parent.IsParent(child) does not hold.
bool SetRelativePath(const FilePath& parent,
                     const FilePath& child,
                     FilePath* path) {
  path->clear();
  return parent.AppendRelativePath(child, path);
}

// Translates known DriveFS folders into their localized message id.
std::optional<int> DriveFsFolderToMessageId(std::string folder) {
  if (folder == kDriveFsDirRoot) {
    return IDS_FILE_BROWSER_DRIVE_MY_DRIVE_LABEL;
  } else if (folder == kDriveFsDirTeamDrives) {
    return IDS_FILE_BROWSER_DRIVE_SHARED_DRIVES_LABEL;
  } else if (folder == kDriveFsDirComputers) {
    return IDS_FILE_BROWSER_DRIVE_COMPUTERS_LABEL;
  } else if (folder == kDriveFsDirSharedWithMe) {
    return IDS_FILE_BROWSER_DRIVE_SHARED_WITH_ME_COLLECTION_LABEL;
  } else if (folder == kDriveFsDirShortcutsSharedWithMe) {
    return IDS_FILE_BROWSER_DRIVE_SHARED_WITH_ME_COLLECTION_LABEL;
  }
  return std::nullopt;
}

// Translates special My Files folders into their localized message id.
std::optional<int> MyFilesFolderToMessageId(std::string folder) {
  if (folder == kFolderNameDownloads) {
    return IDS_FILE_BROWSER_DOWNLOADS_DIRECTORY_LABEL;
  } else if (folder == kFolderNamePvmDefault) {
    return IDS_FILE_BROWSER_PLUGIN_VM_DIRECTORY_LABEL;
  } else if (folder == kFolderNameCamera) {
    return IDS_FILE_BROWSER_CAMERA_DIRECTORY_LABEL;
  }
  return std::nullopt;
}

std::string GetMountPointNameForProfile(Profile* profile,
                                        const std::string& folder_name) {
  // To distinguish profiles in multi-profile session, we append user name hash
  // to folder_name. Note that some profiles (like login or test profiles)
  // are not associated with an user account. In that case, no suffix is added
  // because such a profile never belongs to a multi-profile session.
  const user_manager::User* const user =
      user_manager::UserManager::IsInitialized()
          ? ash::ProfileHelper::Get()->GetUserByProfile(
                profile->GetOriginalProfile())
          : nullptr;
  const std::string id = user ? "-" + user->username_hash() : "";
  return base::EscapeQueryParamValue(folder_name + id, false);
}

}  // namespace

const FilePath::CharType kFuseBoxMediaPath[] =
    FILE_PATH_LITERAL("/media/fuse/fusebox");

const FilePath::CharType kFuseBoxMediaSlashPath[] =
    FILE_PATH_LITERAL("/media/fuse/fusebox/");

const FilePath::CharType kRemovableMediaPath[] =
    FILE_PATH_LITERAL("/media/removable");

const FilePath::CharType kAndroidFilesPath[] =
    FILE_PATH_LITERAL("/run/arc/sdcard/write/emulated/0");

const FilePath::CharType kGuestOsAndroidFilesPath[] =
    FILE_PATH_LITERAL("/media/fuse/android_files");

const FilePath::CharType kSystemFontsPath[] =
    FILE_PATH_LITERAL("/usr/share/fonts");

const FilePath::CharType kArchiveMountPath[] =
    FILE_PATH_LITERAL("/media/archive");

const char kFuseBox[] = "fusebox";

// The actual value of this string is arbitrary (other than, per the comments
// in external_mount_points.h, mount names should not contain '/'), but this
// nonsense-looking word (based on the first two letters of each of "fuse box
// mount name") is unique enough so that, when seeing "fubomona" in a log
// message (e.g. in a storage::FileSystemURL's debug string form), code-
// searching for that string should quickly find this definition here (and the
// kFuseBoxMountNamePrefix name that code-search can find references for).
//
// This is just a prefix. The complete mount name (for FuseBox mounts, not for
// storage::ExternalMountPoints generally) looks like "fubomona:volumetype.etc"
// where the volumetype (e.g. "adp", "fsp") acts like a namespace so that ADP's
// "etc" format won't accidentally conflict with FSP's "etc" format.
//
// This means that the "volumetype.etc" string value *can* be the same as a
// FuseBox subdir string value, as they're both prefixed with "volumetype.",
// but they don't *have* to be. Specifically, the "etc" may contain identifiers
// that other in-process Chromium code wants to parse but those identifiers
// might be longer than Linux's NAME_MAX.
const char kFuseBoxMountNamePrefix[] = "fubomona:";

const char kFuseBoxSubdirPrefixADP[] = "adp.";
const char kFuseBoxSubdirPrefixFSP[] = "fsp.";
const char kFuseBoxSubdirPrefixLOC[] = "loc.";
const char kFuseBoxSubdirPrefixMTP[] = "mtp.";
const char kFuseBoxSubdirPrefixTMP[] = "tmp.";

const char kShareCacheMountPointName[] = "ShareCache";

const url::Origin& GetFilesAppOrigin() {
  static const base::NoDestructor<url::Origin> origin(
      [] { return url::Origin::Create(GetFileManagerURL()); }());
  return *origin;
}

FilePath GetDownloadsFolderForProfile(Profile* profile) {
  // Check if FilesApp has a registered path already.  This happens for tests.
  const std::string mount_point_name =
      util::GetDownloadsMountPointName(profile);
  storage::ExternalMountPoints* const mount_points =
      storage::ExternalMountPoints::GetSystemInstance();
  FilePath path;
  if (mount_points->GetRegisteredPath(mount_point_name, &path)) {
    return path.AppendASCII(kFolderNameDownloads);
  }

  // Return $HOME/Downloads as Download folder.
  if (ShouldMountPrimaryUserDownloads(profile)) {
    return DownloadPrefs::GetDefaultDownloadDirectory();
  }

  // Return <cryptohome>/MyFiles/Downloads if it feature is enabled.
  return profile->GetPath()
      .AppendASCII(kFolderNameMyFiles)
      .AppendASCII(kFolderNameDownloads);
}

FilePath GetMyFilesFolderForProfile(Profile* profile) {
  // Check if FilesApp has a registered path already. This happens for tests.
  const std::string mount_point_name =
      util::GetDownloadsMountPointName(profile);
  storage::ExternalMountPoints* const mount_points =
      storage::ExternalMountPoints::GetSystemInstance();
  FilePath path;
  if (mount_points->GetRegisteredPath(mount_point_name, &path)) {
    return path;
  }

  // Return $HOME/Downloads as MyFiles folder.
  if (ShouldMountPrimaryUserDownloads(profile)) {
    return DownloadPrefs::GetDefaultDownloadDirectory();
  }

  // Return <cryptohome>/MyFiles.
  return profile->GetPath().AppendASCII(kFolderNameMyFiles);
}

FilePath GetShareCacheFilePath(Profile* profile) {
  return profile->GetPath().AppendASCII(kFolderNameShareCache);
}

FilePath GetAndroidFilesPath() {
  // Check if Android has a registered path already. This happens for tests.
  const std::string mount_point_name = util::GetAndroidFilesMountPointName();
  storage::ExternalMountPoints* const mount_points =
      storage::ExternalMountPoints::GetSystemInstance();
  FilePath path;
  if (mount_points->GetRegisteredPath(mount_point_name, &path)) {
    return path;
  }
  if (arc::IsArcVmEnabled()) {
    return FilePath(file_manager::util::kGuestOsAndroidFilesPath);
  }
  return FilePath(file_manager::util::kAndroidFilesPath);
}

bool MigratePathFromOldFormat(Profile* profile,
                              const FilePath& old_base,
                              const FilePath& old_path,
                              FilePath* new_path) {
  // Special case, migrating /home/chronos/user which is set early (before a
  // profile is attached to the browser process) to default to
  // /home/chronos/u-{hash}/MyFiles/Downloads.
  if (old_path == old_base && old_path == FilePath("/home/chronos/user")) {
    *new_path = GetDownloadsFolderForProfile(profile);
    return true;
  }

  // If the `new_base` is already parent of `old_path`, no need to migrate.
  const FilePath new_base = GetMyFilesFolderForProfile(profile);
  if (new_base.IsParent(old_path)) {
    return false;
  }

  FilePath relative;
  if (old_base.AppendRelativePath(old_path, &relative)) {
    *new_path = new_base.Append(relative);
    return old_path != *new_path;
  }

  return false;
}

bool MigrateToDriveFs(Profile* profile,
                      const FilePath& old_path,
                      FilePath* new_path) {
  const auto* user = ash::ProfileHelper::Get()->GetUserByProfile(profile);
  DriveIntegrationService* const service =
      DriveIntegrationServiceFactory::FindForProfile(profile);
  if (!service || !service->is_enabled() || !user ||
      !user->GetAccountId().HasAccountIdKey()) {
    return false;
  }
  *new_path = service->GetMountPointPath();
  return drive::util::GetDriveGrandRootPath().AppendRelativePath(
      ExtractLegacyDrivePath(old_path), new_path);
}

std::string GetDownloadsMountPointName(Profile* profile) {
  return GetMountPointNameForProfile(profile, kFolderNameDownloads);
}

std::string GetShareCacheMountPointName(Profile* profile) {
  return GetMountPointNameForProfile(profile, kFolderNameShareCache);
}

std::string GetAndroidFilesMountPointName() {
  return kAndroidFilesMountPointName;
}

// Returns true if |name| is a known Bruschetta mount point name (e.g. as
// produced by GetGuestOsMountPointName), and populates |guest_id|.
bool IsBruschettaMountPointName(const std::string& name,
                                Profile* profile,
                                guest_os::GuestId* guest_id) {
  auto* service = guest_os::GuestOsServiceFactory::GetForProfile(profile);
  if (!service) {
    return false;
  }
  auto* registry = service->MountProviderRegistry();
  for (const auto id : registry->List()) {
    auto* provider = registry->Get(id);
    if (provider->vm_type() != vm_tools::apps::VmType::BRUSCHETTA) {
      continue;
    }
    if (name == util::GetGuestOsMountPointName(profile, provider->GuestId())) {
      *guest_id = provider->GuestId();
      return true;
    }
  }
  return false;
}

std::string GetCrostiniMountPointName(Profile* profile) {
  // crostini_<hash>_termina_penguin
  return base::JoinString(
      {"crostini", crostini::CryptohomeIdForProfile(profile),
       crostini::kCrostiniDefaultVmName,
       crostini::kCrostiniDefaultContainerName},
      "_");
}

std::string GetGuestOsMountPointName(Profile* profile,
                                     const guest_os::GuestId& id) {
  if (id.vm_type == guest_os::VmType::ARCVM) {
    return kAndroidFilesMountPointName;
  }
  if (id == crostini::DefaultContainerId()) {
    return GetCrostiniMountPointName(profile);
  }
  return base::JoinString(
      {"guestos", ash::ProfileHelper::GetUserIdHashFromProfile(profile),
       base::EscapeAllExceptUnreserved(id.vm_name),
       base::EscapeAllExceptUnreserved(id.container_name)},
      "+");
}

FilePath GetCrostiniMountDirectory(Profile* profile) {
  return FilePath("/media/fuse/" + GetCrostiniMountPointName(profile));
}

FilePath GetGuestOsMountDirectory(std::string mountPointName) {
  return FilePath("/media/fuse/" + mountPointName);
}

bool ConvertFileSystemURLToPathInsideVM(
    Profile* profile,
    const storage::FileSystemURL& file_system_url,
    const FilePath& vm_mount,
    bool map_crostini_home,
    FilePath* inside) {
  const std::string& id(file_system_url.mount_filesystem_id());
  // File system root requires strip trailing separator.
  FilePath path =
      FilePath(file_system_url.virtual_path()).StripTrailingSeparators();
  // Include drive if using DriveFS.
  std::string mount_point_name_drive;
  if (DriveIntegrationService* const service =
          DriveIntegrationServiceFactory::FindForProfile(profile)) {
    mount_point_name_drive = service->GetMountPointPath().BaseName().value();
  }

  // Reformat virtual_path() from:
  //   <mount_label>/path/to/file
  // To:
  //   <vm_mount>/<mapping>/path/to/file
  // If |map_crostini_home| is set, paths in crostini mount map to:
  //   /<home-directory>/path/to/file
  FilePath base_to_exclude(id);
  guest_os::GuestId guest_id("", "");
  if (id == GetDownloadsMountPointName(profile)) {
    // MyFiles.
    *inside = vm_mount.Append(kFolderNameMyFiles);
  } else if (!mount_point_name_drive.empty() && id == mount_point_name_drive) {
    // DriveFS has some more complicated mappings.
    std::vector<FilePath::StringType> components = path.GetComponents();
    *inside = vm_mount.Append(kCrostiniMapGoogleDrive);
    if (components.size() >= 2 && components[1] == kDriveFsDirRoot) {
      // root -> MyDrive.
      base_to_exclude = base_to_exclude.Append(kDriveFsDirRoot);
      *inside = inside->Append(kCrostiniMapMyDrive);
    } else if (components.size() >= 2 &&
               components[1] == kDriveFsDirTeamDrives) {
      // team_drives -> SharedDrives.
      base_to_exclude = base_to_exclude.Append(kDriveFsDirTeamDrives);
      *inside = inside->Append(kCrostiniMapTeamDrives);
    } else if (components.size() >= 2 &&
               components[1] == kDriveFsDirSharedWithMe) {
      // .files-by-id -> SharedWithMe.
      base_to_exclude = base_to_exclude.Append(kDriveFsDirSharedWithMe);
      *inside = inside->Append(kCrostiniMapSharedWithMe);
    } else if (components.size() >= 2 &&
               components[1] == kDriveFsDirShortcutsSharedWithMe) {
      // .shortcut-targets-by-id -> ShortcutsSharedWithMe.
      base_to_exclude =
          base_to_exclude.Append(kDriveFsDirShortcutsSharedWithMe);
      *inside = inside->Append(kCrostiniMapShortcutsSharedWithMe);
    }
    // Computers -> Computers
  } else if (id == ash::kSystemMountNameRemovable) {
    // Removable.
    *inside = vm_mount.Append(ash::kSystemMountNameRemovable);
  } else if (id == GetAndroidFilesMountPointName()) {
    // PlayFiles.
    *inside = vm_mount.Append(kCrostiniMapPlayFiles);
  } else if (id == ash::kSystemMountNameArchive) {
    // Archive.
    *inside = vm_mount.Append(ash::kSystemMountNameArchive);
  } else if (id == GetCrostiniMountPointName(profile)) {
    // Crostini.
    if (map_crostini_home) {
      auto container_info =
          guest_os::GuestOsSessionTrackerFactory::GetForProfile(profile)
              ->GetInfo(crostini::DefaultContainerId());
      if (!container_info) {
        return false;
      }
      *inside = container_info->homedir;
    } else {
      *inside = vm_mount.Append(kCrostiniMapLinuxFiles);
    }
  } else if (IsBruschettaMountPointName(id, profile, &guest_id)) {
    // Bruschetta: use path to homedir, which is currently the empty string
    // because sftp-server inside the VM runs in the homedir.
    auto container_info =
        guest_os::GuestOsSessionTrackerFactory::GetForProfile(profile)->GetInfo(
            guest_id);
    if (!container_info) {
      return false;
    }
    *inside = container_info->homedir;
  } else if (file_system_url.type() == storage::kFileSystemTypeSmbFs) {
    // SMB. Do not assume the share is currently accessible via SmbService
    // as this function is called during unmount when SmbFsShare is
    // destroyed. The only information safely available is the stable
    // mount ID.
    *inside = vm_mount.Append(kCrostiniMapSmbFs);
    *inside = inside->Append(id);
  } else if (file_system_url.type() == storage::kFileSystemTypeFuseBox) {
    // `inside` should be of the form <vm_mount>/Fusebox/<subdir>/foo/bar.
    // Since <subdir> is not available in either `id` or `path`, we look up
    // `file_system_url.path()` (the raw VFS path), which is of the form
    // /media/fuse/fusebox/<subdir>/foo/bar.
    *inside = vm_mount.Append(kCrostiniMapFusebox);
    return base::FilePath(kFuseBoxMediaPath)
        .AppendRelativePath(file_system_url.path(), inside);
  } else {
    return false;
  }
  return AppendRelativePath(base_to_exclude, path, inside);
}

bool ConvertFileSystemURLToPathInsideCrostini(
    Profile* profile,
    const storage::FileSystemURL& file_system_url,
    FilePath* inside) {
  return ConvertFileSystemURLToPathInsideVM(
      profile, file_system_url, crostini::ContainerChromeOSBaseDirectory(),
      /*map_crostini_home=*/true, inside);
}

bool ConvertFuseboxMonikerPathToPathInsideVM(const base::FilePath& path,
                                             const base::FilePath& vm_mount,
                                             base::FilePath* inside) {
  base::FilePath relative_path;
  if (!base::FilePath(fusebox::kMonikerFilenamePrefixWithTrailingSlash)
           .AppendRelativePath(path, &relative_path)) {
    return false;
  }
  *inside = vm_mount.Append(kCrostiniMapFusebox)
                .Append(fusebox::kMonikerSubdir)
                .Append(relative_path);
  return true;
}

bool ConvertPathInsideVMToFileSystemURL(
    Profile* profile,
    const FilePath& inside,
    const FilePath& vm_mount,
    bool map_crostini_home,
    storage::FileSystemURL* file_system_url) {
  storage::ExternalMountPoints* mount_points =
      storage::ExternalMountPoints::GetSystemInstance();

  // Include drive if using DriveFS.
  std::string mount_point_name_drive;
  if (DriveIntegrationService* const service =
          DriveIntegrationServiceFactory::FindForProfile(profile)) {
    mount_point_name_drive = service->GetMountPointPath().BaseName().value();
  }

  std::string mount_name;
  FilePath path;
  FilePath relative_path;

  if (map_crostini_home) {
    auto container_info =
        guest_os::GuestOsSessionTrackerFactory::GetForProfile(profile)->GetInfo(
            crostini::DefaultContainerId());
    if (container_info &&
        AppendRelativePath(container_info->homedir, inside, &relative_path)) {
      *file_system_url = mount_points->CreateExternalFileSystemURL(
          blink::StorageKey::CreateFirstParty(GetFilesAppOrigin()),
          GetCrostiniMountPointName(profile), relative_path);
      return file_system_url->is_valid();
    }
  }

  if (!vm_mount.AppendRelativePath(inside, &path)) {
    return false;
  }

  if (AppendRelativePath(FilePath(kFolderNameMyFiles), path, &relative_path)) {
    // MyFiles.
    mount_name = GetDownloadsMountPointName(profile);
    path = relative_path;
  } else if (AppendRelativePath(FilePath(kCrostiniMapLinuxFiles), path,
                                &relative_path)) {
    // LinuxFiles.
    mount_name = GetCrostiniMountPointName(profile);
    path = relative_path;
  } else if (FilePath(kCrostiniMapGoogleDrive)
                 .AppendRelativePath(path, &relative_path)) {
    mount_name = mount_point_name_drive;
    path = relative_path;
    relative_path.clear();
    // GoogleDrive
    if (AppendRelativePath(FilePath(kCrostiniMapMyDrive), path,
                           &relative_path)) {
      // /GoogleDrive/MyDrive -> root
      path = FilePath(kDriveFsDirRoot).Append(relative_path);
    } else if (AppendRelativePath(FilePath(kCrostiniMapTeamDrives), path,
                                  &relative_path)) {
      // /GoogleDrive/SharedDrive -> team_drives
      path = FilePath(kDriveFsDirTeamDrives).Append(relative_path);
    } else if (AppendRelativePath(FilePath(kCrostiniMapSharedWithMe), path,
                                  &relative_path)) {
      // /GoogleDrive/SharedWithMe -> .files-by-id
      path = FilePath(kDriveFsDirSharedWithMe).Append(relative_path);
    } else if (AppendRelativePath(FilePath(kCrostiniMapShortcutsSharedWithMe),
                                  path, &relative_path)) {
      // /GoogleDrive/ShortcutsSharedWithMe -> .shortcut-targets-by-id
      path = FilePath(kDriveFsDirShortcutsSharedWithMe).Append(relative_path);
    }
    // Computers -> Computers
  } else if (FilePath(ash::kSystemMountNameRemovable)
                 .AppendRelativePath(path, &relative_path)) {
    // Removable subdirs only.
    mount_name = ash::kSystemMountNameRemovable;
    path = relative_path;
  } else if (AppendRelativePath(FilePath(kCrostiniMapPlayFiles), path,
                                &relative_path)) {
    // PlayFiles.
    mount_name = GetAndroidFilesMountPointName();
    path = relative_path;
  } else if (FilePath(ash::kSystemMountNameArchive)
                 .AppendRelativePath(path, &relative_path)) {
    // Archive subdirs only.
    mount_name = ash::kSystemMountNameArchive;
    path = relative_path;
  } else if (FilePath(kCrostiniMapSmbFs)
                 .AppendRelativePath(path, &relative_path)) {
    // SMB.
    std::vector<FilePath::StringType> components =
        relative_path.GetComponents();
    if (components.size() < 1) {
      return false;
    }
    mount_name = components[0];
    path.clear();
    FilePath(mount_name).AppendRelativePath(relative_path, &path);
  } else if (FilePath(kCrostiniMapFusebox)
                 .AppendRelativePath(path, &relative_path)) {
    // For Fusebox files, `mount_name` is the first component of the virtual
    // path, and `path` is the remaining part of the virtual path.
    const FilePath absolute_path =
        FilePath(kFuseBoxMediaPath).Append(relative_path);
    FilePath virtual_path;
    if (!mount_points->GetVirtualPath(absolute_path, &virtual_path)) {
      return false;
    }
    const std::vector<FilePath::StringType> components =
        virtual_path.GetComponents();
    if (components.size() < 1) {
      return false;
    }
    mount_name = components[0];
    SetRelativePath(FilePath(mount_name), virtual_path, &path);
  } else {
    return false;
  }

  *file_system_url = mount_points->CreateExternalFileSystemURL(
      blink::StorageKey::CreateFirstParty(GetFilesAppOrigin()), mount_name,
      path);
  return file_system_url->is_valid();
}

bool ConvertPathToArcUrl(const FilePath& path,
                         GURL* const arc_url_out,
                         bool* const requires_sharing_out) {
  DCHECK(arc_url_out);
  DCHECK(requires_sharing_out);
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  *requires_sharing_out = false;

  // Obtain the primary profile. This information is required because currently
  // only the file systems for the primary profile is exposed to ARC.
  Profile* primary_profile = ProfileManager::GetPrimaryUserProfile();
  if (!primary_profile) {
    return false;
  }

  // Convert paths under primary profile's Downloads directory.
  FilePath primary_downloads = GetDownloadsFolderForProfile(primary_profile);
  FilePath result_path(kArcDownloadRoot);
  if (primary_downloads.AppendRelativePath(path, &result_path)) {
    *arc_url_out = GURL(kArcStorageContentUrlPrefix)
                       .Resolve(base::EscapePath(result_path.AsUTF8Unsafe()));
    return true;
  }

  // Convert paths under Android files root (e.g.,
  // /run/arc/sdcard/write/emulated/0).
  result_path = FilePath(kArcExternalFilesRoot);
  if (GetAndroidFilesPath().AppendRelativePath(path, &result_path)) {
    *arc_url_out = GURL(kArcStorageContentUrlPrefix)
                       .Resolve(base::EscapePath(result_path.AsUTF8Unsafe()));
    return true;
  }

  // Convert paths under /media/removable.
  FilePath relative_path;
  if (SetRelativePath(FilePath(kRemovableMediaPath), path, &relative_path)) {
    const std::string volume_name =
        ExtractVolumeNameFromRelativePathForRemovableMedia(relative_path);
    if (volume_name.empty()) {
      return false;
    }
    const std::string fs_uuid = GetFsUuidForRemovableMedia(volume_name);
    // Replace the volume name in the relative path with the UUID.
    // When no UUID is found for the volume, use the predefined one for testing.
    FilePath relative_path_with_uuid =
        FilePath(fs_uuid.empty() ? kArcRemovableMediaUuidForTesting : fs_uuid);
    if (!FilePath(volume_name)
             .AppendRelativePath(relative_path, &relative_path_with_uuid)) {
      LOG(WARNING) << "Failed to replace volume name \"" << volume_name
                   << "\" in relative path \"" << relative_path
                   << "\" with UUID \"" << fs_uuid << "\"";
      return false;
    }
    *arc_url_out =
        GURL(kArcStorageContentUrlPrefix)
            .Resolve(base::EscapePath(relative_path_with_uuid.AsUTF8Unsafe()));
    return true;
  }

  // Convert paths under MyFiles.
  if (SetRelativePath(GetMyFilesFolderForProfile(primary_profile), path,
                      &relative_path)) {
    *arc_url_out = GURL(kArcMyFilesContentUrlPrefix)
                       .Resolve(base::EscapePath(relative_path.AsUTF8Unsafe()));
    return true;
  }

  bool force_external = false;
  // Convert paths under DriveFS.
  const DriveIntegrationService* integration_service =
      drive::util::GetIntegrationServiceByProfile(primary_profile);
  if (integration_service &&
      SetRelativePath(integration_service->GetMountPointPath(), path,
                      &relative_path)) {
    // TODO(b/157297349) Remove this condition.
    if (arc::IsArcVmEnabled()) {
      *arc_url_out =
          GURL("content://org.chromium.arc.volumeprovider/MyDrive/")
              .Resolve(base::EscapePath(relative_path.AsUTF8Unsafe()));
      *requires_sharing_out = true;
      return true;
    }

    // TODO(b/157297349): For backward compatibility with ARC++ P, force
    // external URL for DriveFS.
    force_external = true;
  }

  // Convert paths under /media/fuse/crostini_...
  if (SetRelativePath(GetCrostiniMountDirectory(primary_profile), path,
                      &relative_path)) {
    if (arc::IsArcVmEnabled()) {
      // For ARCVM, we can use ArcVolumeProvider URL and ask Seneschal to share
      // the path to ARCVM so ARCVM does not need to talk through Chrome.
      *arc_url_out =
          GURL("content://org.chromium.arc.volumeprovider/crostini/")
              .Resolve(base::EscapePath(relative_path.AsUTF8Unsafe()));
      *requires_sharing_out = true;
      return true;
    }

    // Use ChromeContentProvider for ARC++ Container to proxy through Chrome.
    force_external = true;
  }

  // Convert path under /media/archive.
  if (SetRelativePath(FilePath(kArchiveMountPath), path, &relative_path)) {
    // TODO(b/157297349) Remove this condition.
    if (arc::IsArcVmEnabled()) {
      *arc_url_out =
          GURL("content://org.chromium.arc.volumeprovider/archive/")
              .Resolve(base::EscapePath(relative_path.AsUTF8Unsafe()));
      *requires_sharing_out = true;
      return true;
    }

    force_external = true;
  }

  // Convert path under /media/fuse/smb-...
  if (ash::smb_client::SmbService* const service =
          ash::smb_client::SmbServiceFactory::Get(primary_profile)) {
    if (const ash::smb_client::SmbFsShare* const share =
            service->GetSmbFsShareForPath(path)) {
      if (SetRelativePath(share->mount_path(), path, &relative_path)) {
        // TODO(b/157297349) Remove this condition.
        if (arc::IsArcVmEnabled()) {
          *arc_url_out =
              GURL(StrCat({"content://org.chromium.arc.volumeprovider/smb/",
                           share->mount_id(), "/"}))
                  .Resolve(base::EscapePath(relative_path.AsUTF8Unsafe()));
          *requires_sharing_out = true;
          return true;
        }

        force_external = true;
      }
    }
  }

  // Convert path under /media/fuse/fusebox.
  if (SetRelativePath(FilePath(kFuseBoxMediaPath), path, &relative_path)) {
    if (arc::IsArcVmEnabled()) {
      *arc_url_out =
          GURL("content://org.chromium.arc.volumeprovider/fusebox/")
              .Resolve(base::EscapePath(relative_path.AsUTF8Unsafe()));
      *requires_sharing_out = true;
      return true;
    }
    // Use ChromeContentProvider for ARC++ container.
    force_external = true;
  }

  // ShareCache files are not available as mount-passthrough and must be shared
  // through ChromeContentProvider.
  if (GetShareCacheFilePath(primary_profile).IsParent(path)) {
    force_external = true;
  }

  // Convert paths under /special or other paths forced to use external URL.
  GURL external_file_url =
      ash::CreateExternalFileURLFromPath(primary_profile, path, force_external);

  if (!external_file_url.is_empty()) {
    *arc_url_out = arc::EncodeToChromeContentProviderUrl(external_file_url);
    return true;
  }

  // TODO(kinaba): Add conversion logic once other file systems are supported.
  return false;
}

base::FilePath ConvertFileSystemURLToPathForSharingWithArc(
    const storage::FileSystemURL& file_system_url) {
  switch (file_system_url.type()) {
    // Use Fusebox path for FSP and MTP.
    case storage::kFileSystemTypeProvided:
    case storage::kFileSystemTypeDeviceMediaAsFileStorage:
      return fusebox::Server::SubstituteFuseboxFilePath(file_system_url);
    default:
      return file_system_url.path();
  }
}

void ConvertToContentUrls(
    Profile* profile,
    const std::vector<storage::FileSystemURL>& file_system_urls,
    ConvertToContentUrlsCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  if (file_system_urls.empty()) {
    std::move(callback).Run(std::vector<GURL>(), std::vector<FilePath>());
    return;
  }

  auto* documents_provider_root_map =
      profile ? arc::ArcDocumentsProviderRootMap::GetForBrowserContext(profile)
              : nullptr;

  // To keep the original order, prefill |out_urls| with empty URLs and
  // specify index when updating it like (*out_urls)[index] = url.
  auto out_urls = std::make_unique<std::vector<GURL>>(file_system_urls.size());
  auto* out_urls_ptr = out_urls.get();
  auto paths_to_share = std::make_unique<std::vector<FilePath>>();
  auto* paths_to_share_ptr = paths_to_share.get();
  auto barrier = base::BarrierClosure(
      file_system_urls.size(),
      base::BindOnce(&OnAllContentUrlsResolved, std::move(callback),
                     std::move(out_urls), std::move(paths_to_share)));
  auto single_content_url_callback =
      base::BindRepeating(&OnSingleContentUrlResolved, barrier, out_urls_ptr);

  for (size_t index = 0; index < file_system_urls.size(); ++index) {
    const auto& file_system_url = file_system_urls[index];

    // Run DocumentsProvider check before running ConvertPathToArcUrl.
    // Otherwise, DocumentsProvider file path would be encoded to a
    // ChromeContentProvider URL (b/132314050).
    if (documents_provider_root_map) {
      FilePath file_path;
      auto* documents_provider_root =
          documents_provider_root_map->ParseAndLookup(file_system_url,
                                                      &file_path);
      if (documents_provider_root) {
        documents_provider_root->ResolveToContentUrl(
            file_path, base::BindOnce(single_content_url_callback, index));
        continue;
      }
    }

    if (file_system_url.mount_type() == storage::kFileSystemTypeExternal) {
      const base::FilePath path =
          ConvertFileSystemURLToPathForSharingWithArc(file_system_url);
      GURL arc_url;
      bool requires_sharing = false;
      if (ConvertPathToArcUrl(path, &arc_url, &requires_sharing)) {
        if (requires_sharing) {
          paths_to_share_ptr->push_back(path);
        }
        single_content_url_callback.Run(index, arc_url);
        continue;
      }
    }

    single_content_url_callback.Run(index, GURL());
  }
}

bool ReplacePrefix(std::string* const s,
                   std::string_view prefix,
                   std::string_view replacement) {
  DCHECK(s);
  if (s->starts_with(prefix) &&
      (prefix.ends_with('/') || s->size() <= prefix.size() ||
       (*s)[prefix.size()] == '/')) {
    s->replace(0, prefix.size(), replacement);
    return true;
  }

  return false;
}

std::string GetPathDisplayTextForSettings(Profile* const profile,
                                          std::string_view path) {
  std::string result(path);
  DriveIntegrationService* service =
      DriveIntegrationServiceFactory::FindForProfile(profile);
  if (service && !service->is_enabled()) {
    service = nullptr;
  }

  bool is_odfs_mounted = ash::cloud_upload::IsODFSMounted(profile);

  const std::string_view sep = " › ";
  const std::string downloads_label =
      StrCat({GetStringUTF8(IDS_FILE_BROWSER_MY_FILES_ROOT_LABEL), sep,
              GetStringUTF8(IDS_FILE_BROWSER_DOWNLOADS_DIRECTORY_LABEL)});
  if (ReplacePrefix(&result, "/home/chronos/user/MyFiles/Downloads",
                    downloads_label)) {
  } else if (ReplacePrefix(
                 &result,
                 profile->GetPath().Append("MyFiles/Downloads").value(),
                 downloads_label)) {
  } else if (ReplacePrefix(
                 &result, "/home/chronos/user/MyFiles",
                 GetStringUTF8(IDS_FILE_BROWSER_MY_FILES_ROOT_LABEL))) {
  } else if (ReplacePrefix(
                 &result, profile->GetPath().Append(kFolderNameMyFiles).value(),
                 GetStringUTF8(IDS_FILE_BROWSER_MY_FILES_ROOT_LABEL))) {
  } else if (service &&
             ReplacePrefix(
                 &result,
                 service->GetMountPointPath().Append(kDriveFsDirRoot).value(),
                 base::FilePath(kDisplayNameGoogleDrive)
                     .Append(l10n_util::GetStringUTF8(
                         IDS_FILE_BROWSER_DRIVE_MY_DRIVE_LABEL))
                     .value())) {
  } else if (ReplacePrefix(&result,
                           download_dir_util::kDriveNamePolicyVariableName,
                           base::FilePath(kDisplayNameGoogleDrive)
                               .Append(l10n_util::GetStringUTF8(
                                   IDS_FILE_BROWSER_DRIVE_MY_DRIVE_LABEL))
                               .value())) {
  } else if (service &&
             ReplacePrefix(&result,
                           service->GetMountPointPath()
                               .Append(kDriveFsDirTeamDrives)
                               .value(),
                           base::FilePath(kDisplayNameGoogleDrive)
                               .Append(l10n_util::GetStringUTF8(
                                   IDS_FILE_BROWSER_DRIVE_SHARED_DRIVES_LABEL))
                               .value())) {
  } else if (service &&
             ReplacePrefix(&result,
                           service->GetMountPointPath()
                               .Append(kDriveFsDirComputers)
                               .value(),
                           base::FilePath(kDisplayNameGoogleDrive)
                               .Append(l10n_util::GetStringUTF8(
                                   IDS_FILE_BROWSER_DRIVE_COMPUTERS_LABEL))
                               .value())) {
  } else if (
      service &&
      ReplacePrefix(
          &result,
          service->GetMountPointPath().Append(kDriveFsDirSharedWithMe).value(),
          base::FilePath(kDisplayNameGoogleDrive)
              .Append(l10n_util::GetStringUTF8(
                  IDS_FILE_BROWSER_DRIVE_SHARED_WITH_ME_COLLECTION_LABEL))
              .value())) {
  } else if (
      service &&
      ReplacePrefix(
          &result,
          service->GetMountPointPath()
              .Append(kDriveFsDirShortcutsSharedWithMe)
              .value(),
          base::FilePath(kDisplayNameGoogleDrive)
              .Append(l10n_util::GetStringUTF8(
                  IDS_FILE_BROWSER_DRIVE_SHARED_WITH_ME_COLLECTION_LABEL))
              .value())) {
  } else if (ReplacePrefix(
                 &result, download_dir_util::kOneDriveNamePolicyVariableName,
                 base::FilePath(kDisplayNameMicrosoftOneDrive).value())) {
  } else if (is_odfs_mounted &&
             ReplacePrefix(
                 &result,
                 ash::cloud_upload::GetODFSFuseboxMount(profile).value(),
                 base::FilePath(kDisplayNameMicrosoftOneDrive).value())) {
  } else if (ReplacePrefix(&result, GetAndroidFilesPath().value(),
                           l10n_util::GetStringUTF8(
                               IDS_FILE_BROWSER_ANDROID_FILES_ROOT_LABEL))) {
  } else if (ReplacePrefix(&result, GetCrostiniMountDirectory(profile).value(),
                           l10n_util::GetStringUTF8(
                               IDS_FILE_BROWSER_LINUX_FILES_ROOT_LABEL))) {
  } else if (ReplacePrefix(&result,
                           base::FilePath(kRemovableMediaPath)
                               .AsEndingWithSeparator()
                               .value(),
                           "")) {
    // Strip prefix of "/media/removable/" including trailing slash.
  } else if (ReplacePrefix(&result,
                           base::FilePath(kArchiveMountPath)
                               .AsEndingWithSeparator()
                               .value(),
                           "")) {
    // Strip prefix of "/media/archive/" including trailing slash.
  }

  base::ReplaceChars(result, "/", sep, &result);
  return result;
}

bool ExtractMountNameFileSystemNameFullPath(const FilePath& absolute_path,
                                            std::string* mount_name,
                                            std::string* file_system_name,
                                            std::string* full_path) {
  DCHECK(absolute_path.IsAbsolute());
  DCHECK(mount_name);
  DCHECK(full_path);
  storage::ExternalMountPoints* mount_points =
      storage::ExternalMountPoints::GetSystemInstance();
  FilePath virtual_path;
  if (!mount_points->GetVirtualPath(absolute_path, &virtual_path)) {
    return false;
  }
  // |virtual_path| format is: <mount_name>/<full_path>, and
  // |file_system_name| == |mount_name|, except for 'removable' and 'archive',
  // |mount_name| is the first two segments, |file_system_name| is the second.
  const std::string& value = virtual_path.value();
  size_t fs_start = 0;
  size_t slash_pos = value.find(FilePath::kSeparators[0]);
  *mount_name = *file_system_name = value.substr(0, slash_pos);
  if (*mount_name == ash::kSystemMountNameRemovable ||
      *mount_name == ash::kSystemMountNameArchive) {
    if (slash_pos == std::string::npos) {
      return false;
    }
    fs_start = slash_pos + 1;
    slash_pos = value.find(FilePath::kSeparators[0], fs_start);
    *mount_name = value.substr(0, slash_pos);
  }

  // Set full_path to '/' if |absolute_path| is a root.
  if (slash_pos == std::string::npos) {
    *file_system_name = value.substr(fs_start);
    *full_path = "/";
  } else {
    *file_system_name = value.substr(fs_start, slash_pos - fs_start);
    *full_path = value.substr(slash_pos);
  }
  return true;
}

std::string GetDisplayableFileName(GURL file_url) {
  // Try to convert %20 to spaces, if this produces any invalid char, use the
  // file name URL encoded.
  std::string file_name;
  if (!base::UnescapeBinaryURLComponentSafe(file_url.ExtractFileName(),
                                            /*fail_on_path_separators=*/true,
                                            &file_name)) {
    file_name = file_url.ExtractFileName();
  }

  return file_name;
}

std::string GetDisplayableFileName(storage::FileSystemURL file_url) {
  return GetDisplayableFileName(file_url.ToGURL());
}

std::u16string GetDisplayableFileName16(GURL file_url) {
  return base::UTF8ToUTF16(GetDisplayableFileName(file_url));
}

std::u16string GetDisplayableFileName16(storage::FileSystemURL file_url) {
  return base::UTF8ToUTF16(GetDisplayableFileName(file_url.ToGURL()));
}

std::optional<FilePath> GetDisplayablePath(Profile* profile, FilePath path) {
  base::WeakPtr<Volume> volume =
      file_manager::VolumeManager::Get(profile)->FindVolumeFromPath(path);
  if (!volume) {
    return std::nullopt;
  }

  FilePath mount_relative_path;
  // AppendRelativePath fails if |mount_path| is the same as |path|, but in that
  // case |mount_relative_path| will be empty, which is what we want.
  volume->mount_path().AppendRelativePath(path, &mount_relative_path);
  auto path_components = mount_relative_path.GetComponents();

  auto cur_component = path_components.begin();
  FilePath result;
  switch (volume->type()) {
    case VOLUME_TYPE_GOOGLE_DRIVE: {
      // Start with the Google Drive root.
      result = FilePath(volume->volume_label());

      // The first directory indicates which Drive the path is in, so check it
      // against the expected directories. e.g. My Drive, Shared with me, etc.
      if (cur_component == path_components.end()) {
        return std::nullopt;
      }
      auto maybe_id = DriveFsFolderToMessageId(*cur_component);
      if (!maybe_id.has_value()) {
        return std::nullopt;
      }
      result = result.Append(GetStringUTF8(*maybe_id));
      cur_component++;

      // Skip the first directory in the Shared With Me folders as those are
      // just an opaque id.
      if (cur_component != path_components.end() &&
          (path_components[0] == kDriveFsDirSharedWithMe ||
           path_components[0] == kDriveFsDirShortcutsSharedWithMe)) {
        ++cur_component;
      }
      break;
    }
    case VOLUME_TYPE_DOWNLOADS_DIRECTORY:
      // Start with My Files root.
      result = FilePath(volume->volume_label());

      // Handle special folders under My Files.
      if (cur_component != path_components.end()) {
        auto maybe_id = MyFilesFolderToMessageId(*cur_component);
        if (maybe_id.has_value()) {
          result = result.Append(GetStringUTF8(*maybe_id));
          ++cur_component;
        }
      }
      break;
    case VOLUME_TYPE_ANDROID_FILES:
    case VOLUME_TYPE_CROSTINI:
    case VOLUME_TYPE_GUEST_OS:
      result = FilePath(GetStringUTF8(IDS_FILE_BROWSER_MY_FILES_ROOT_LABEL))
                   .Append(volume->volume_label());
      break;
    case VOLUME_TYPE_MEDIA_VIEW:
    case VOLUME_TYPE_REMOVABLE_DISK_PARTITION:
    case VOLUME_TYPE_MOUNTED_ARCHIVE_FILE:
    case VOLUME_TYPE_PROVIDED:
    case VOLUME_TYPE_DOCUMENTS_PROVIDER:
    case VOLUME_TYPE_MTP:
    case VOLUME_TYPE_SMB:
      result = FilePath(volume->volume_label());
      break;
    case VOLUME_TYPE_TESTING:
    case VOLUME_TYPE_SYSTEM_INTERNAL:
      return std::nullopt;
    case NUM_VOLUME_TYPE:
      NOTREACHED();
  }
  while (cur_component != path_components.end()) {
    result = result.Append(*cur_component);
    cur_component++;
  }
  return result;
}

std::optional<FilePath> GetDisplayablePath(Profile* profile,
                                           storage::FileSystemURL file_url) {
  return GetDisplayablePath(profile, file_url.path());
}

std::vector<ui::FileInfo> ParseFileSystemSources(
    const ui::DataTransferEndpoint* source,
    const base::Pickle& pickle) {
  std::vector<ui::FileInfo> file_info;
  // We only promote 'fs/sources' custom data pickle to be filenames if it came
  // from the trusted FilesApp.
  if (!source || !source->GetURL() || !IsFileManagerURL(*source->GetURL())) {
    return file_info;
  }

  std::optional<std::u16string> maybe_file_system_url_list =
      ui::ReadCustomDataForType(pickle, kFilesAppMimeSources);
  if (!maybe_file_system_url_list || maybe_file_system_url_list->empty()) {
    return file_info;
  }

  storage::ExternalMountPoints* mount_points =
      storage::ExternalMountPoints::GetSystemInstance();

  for (std::u16string_view line : base::SplitStringPiece(
           *maybe_file_system_url_list, kFilesAppSeparator16,
           base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
    if (line.empty() || line[0] == '#') {
      continue;
    }
    const GURL gurl(line);
    storage::FileSystemURL url = mount_points->CrackURL(
        gurl, blink::StorageKey::CreateFirstParty(url::Origin::Create(gurl)));
    if (!url.is_valid()) {
      LOG(WARNING) << "Invalid clipboard FileSystemURL: " << line;
      continue;
    } else if (url.TypeImpliesPathIsReal()) {
      file_info.emplace_back(std::move(url.path()), FilePath());
    } else if (FilePath path = fusebox::Server::SubstituteFuseboxFilePath(url);
               !path.empty()) {
      file_info.emplace_back(std::move(path), FilePath());
    }
  }
  return file_info;
}

}  // namespace file_manager::util
