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

#include <stddef.h>
#include <utility>

#include "ash/constants/ash_features.h"
#include "ash/webui/file_manager/url_constants.h"
#include "base/files/file.h"
#include "base/files/file_error_or.h"
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/strings/escape.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ash/file_manager/filesystem_api_util.h"
#include "chrome/browser/ash/fileapi/file_system_backend.h"
#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/url_utils.h"
#include "extensions/browser/extension_util.h"
#include "google_apis/common/task_util.h"
#include "storage/browser/file_system/file_system_context.h"
#include "storage/browser/file_system/isolated_context.h"
#include "storage/browser/file_system/open_file_system_mode.h"
#include "storage/common/file_system/file_system_util.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
#include "third_party/re2/src/re2/re2.h"
#include "ui/shell_dialogs/selected_file_info.h"
#include "url/gurl.h"
#include "url/origin.h"

using content::BrowserThread;

namespace file_manager {
namespace util {

using blink::mojom::FileChooserFileInfo;
using blink::mojom::FileSystemFileInfo;
using blink::mojom::NativeFileInfo;

namespace {

GURL ConvertRelativeFilePathToFileSystemUrl(const base::FilePath& relative_path,
                                            const GURL& source_url) {
  GURL base_url = storage::GetFileSystemRootURI(
      source_url, storage::kFileSystemTypeExternal);
  return GURL(base_url.spec() +
              base::EscapeUrlEncodedData(relative_path.AsUTF8Unsafe(),
                                         false));  // Space to %20 instead of +.
}

// Creates an ErrorDefinition with an error set to |error|.
EntryDefinition CreateEntryDefinitionWithError(base::File::Error error) {
  EntryDefinition result;
  result.error = error;
  return result;
}

// Helper class for performing conversions from file definitions to entry
// definitions. It is possible to do it without a class, but the code would be
// crazy and super tricky.
//
// This class copies the input |file_definition_list|,
// so there is no need to worry about validity of passed |file_definition_list|
// reference. Also, it automatically deletes itself after converting finished,
// or if shutdown is invoked during ResolveURL(). Must be called on UI thread.
class FileDefinitionListConverter {
 public:
  FileDefinitionListConverter(
      scoped_refptr<storage::FileSystemContext> file_system_context,
      const url::Origin& origin,
      const FileDefinitionList& file_definition_list,
      EntryDefinitionListCallback callback);
  ~FileDefinitionListConverter() = default;

 private:
  // Converts the element under the iterator to an entry. First, converts
  // the virtual path to an URL, and calls OnResolvedURL(). In case of error
  // calls OnIteratorConverted with an error entry definition.
  void ConvertNextIterator(
      std::unique_ptr<FileDefinitionListConverter> self_deleter,
      FileDefinitionList::const_iterator iterator);

  // Creates an entry definition from the URL as well as the file definition.
  // Then, calls OnIteratorConverted with the created entry definition.
  void OnResolvedURL(std::unique_ptr<FileDefinitionListConverter> self_deleter,
                     FileDefinitionList::const_iterator iterator,
                     base::File::Error error,
                     const storage::FileSystemInfo& info,
                     const base::FilePath& file_path,
                     storage::FileSystemContext::ResolvedEntryType type);

  // Called when the iterator is converted. Adds the |entry_definition| to
  // |results_| and calls ConvertNextIterator() for the next element.
  void OnIteratorConverted(
      std::unique_ptr<FileDefinitionListConverter> self_deleter,
      FileDefinitionList::const_iterator iterator,
      const EntryDefinition& entry_definition);

  scoped_refptr<storage::FileSystemContext> file_system_context_;
  const url::Origin origin_;
  const FileDefinitionList file_definition_list_;
  EntryDefinitionListCallback callback_;
  std::unique_ptr<EntryDefinitionList> result_;
};

FileDefinitionListConverter::FileDefinitionListConverter(
    scoped_refptr<storage::FileSystemContext> file_system_context,
    const url::Origin& origin,
    const FileDefinitionList& file_definition_list,
    EntryDefinitionListCallback callback)
    : file_system_context_(file_system_context),
      origin_(origin),
      file_definition_list_(file_definition_list),
      callback_(std::move(callback)),
      result_(new EntryDefinitionList) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Deletes the converter, once the scoped pointer gets out of scope. It is
  // either, if the conversion is finished, or ResolveURL() is terminated, and
  // the callback not called because of shutdown.
  std::unique_ptr<FileDefinitionListConverter> self_deleter(this);
  ConvertNextIterator(std::move(self_deleter), file_definition_list_.begin());
}

void FileDefinitionListConverter::ConvertNextIterator(
    std::unique_ptr<FileDefinitionListConverter> self_deleter,
    FileDefinitionList::const_iterator iterator) {
  if (iterator == file_definition_list_.end()) {
    // The converter object will be destroyed since |self_deleter| gets out of
    // scope.
    std::move(callback_).Run(std::move(result_));
    return;
  }

  if (!file_system_context_.get()) {
    OnIteratorConverted(std::move(self_deleter), iterator,
                        CreateEntryDefinitionWithError(
                            base::File::FILE_ERROR_INVALID_OPERATION));
    return;
  }

  storage::FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
      blink::StorageKey::CreateFirstParty(origin_),
      storage::kFileSystemTypeExternal, iterator->virtual_path);

  if (!url.is_valid()) {
    OnIteratorConverted(
        std::move(self_deleter), iterator,
        CreateEntryDefinitionWithError(base::File::FILE_ERROR_NOT_FOUND));
    return;
  }

  // The converter object will be deleted if the callback is not called because
  // of shutdown during ResolveURL().
  file_system_context_->ResolveURL(
      url, base::BindOnce(&FileDefinitionListConverter::OnResolvedURL,
                          base::Unretained(this), std::move(self_deleter),
                          iterator));
}

void FileDefinitionListConverter::OnResolvedURL(
    std::unique_ptr<FileDefinitionListConverter> self_deleter,
    FileDefinitionList::const_iterator iterator,
    base::File::Error error,
    const storage::FileSystemInfo& info,
    const base::FilePath& file_path,
    storage::FileSystemContext::ResolvedEntryType type) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (error != base::File::FILE_OK) {
    OnIteratorConverted(std::move(self_deleter), iterator,
                        CreateEntryDefinitionWithError(error));
    return;
  }

  EntryDefinition entry_definition;
  entry_definition.file_system_root_url = info.root_url.spec();
  entry_definition.file_system_name = info.name;
  switch (type) {
    case storage::FileSystemContext::RESOLVED_ENTRY_FILE:
      entry_definition.is_directory = false;
      break;
    case storage::FileSystemContext::RESOLVED_ENTRY_DIRECTORY:
      entry_definition.is_directory = true;
      break;
    case storage::FileSystemContext::RESOLVED_ENTRY_NOT_FOUND:
      entry_definition.is_directory = iterator->is_directory;
      break;
  }
  entry_definition.error = base::File::FILE_OK;

  // Construct a target Entry.fullPath value from the virtual path and the
  // root URL. Eg. Downloads/A/b.txt -> A/b.txt.
  storage::FileSystemURL fs_url =
      file_system_context_->CrackURLInFirstPartyContext(info.root_url);
  if (!fs_url.is_valid()) {
    OnIteratorConverted(
        std::move(self_deleter), iterator,
        CreateEntryDefinitionWithError(base::File::FILE_ERROR_NOT_FOUND));
    return;
  }
  const base::FilePath root_virtual_path = fs_url.virtual_path();
  DCHECK(root_virtual_path == iterator->virtual_path ||
         root_virtual_path.IsParent(iterator->virtual_path));
  base::FilePath full_path;
  root_virtual_path.AppendRelativePath(iterator->virtual_path, &full_path);
  entry_definition.full_path = full_path;

  OnIteratorConverted(std::move(self_deleter), iterator, entry_definition);
}

void FileDefinitionListConverter::OnIteratorConverted(
    std::unique_ptr<FileDefinitionListConverter> self_deleter,
    FileDefinitionList::const_iterator iterator,
    const EntryDefinition& entry_definition) {
  result_->push_back(entry_definition);
  ConvertNextIterator(std::move(self_deleter), ++iterator);
}

// Helper function to return the converted definition entry directly, without
// the redundant container.
void OnConvertFileDefinitionDone(
    EntryDefinitionCallback callback,
    std::unique_ptr<EntryDefinitionList> entry_definition_list) {
  DCHECK_EQ(1u, entry_definition_list->size());
  std::move(callback).Run(entry_definition_list->at(0));
}

// Checks if the |file_path| points non-native location or not.
bool IsUnderNonNativeLocalPath(const storage::FileSystemContext& context,
                               const base::FilePath& file_path) {
  base::FilePath virtual_path;
  if (!ash::FileSystemBackend::Get(context)->GetVirtualPath(file_path,
                                                            &virtual_path)) {
    return false;
  }

  const storage::FileSystemURL url = context.CreateCrackedFileSystemURL(
      blink::StorageKey(), storage::kFileSystemTypeExternal, virtual_path);
  if (!url.is_valid()) {
    return false;
  }

  return !url.TypeImpliesPathIsReal();
}

// Helper class to convert SelectedFileInfoList into ChooserFileInfoList.
class ConvertSelectedFileInfoListToFileChooserFileInfoListImpl {
 public:
  // The scoped pointer to control lifetime of the instance itself. The pointer
  // is passed to callback functions and binds the lifetime of the instance to
  // the callback's lifetime.
  typedef std::unique_ptr<
      ConvertSelectedFileInfoListToFileChooserFileInfoListImpl>
      Lifetime;

  ConvertSelectedFileInfoListToFileChooserFileInfoListImpl(
      storage::FileSystemContext* context,
      const url::Origin& origin,
      const SelectedFileInfoList& selected_info_list,
      FileChooserFileInfoListCallback callback)
      : context_(context), callback_(std::move(callback)) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);

    Lifetime lifetime(this);
    bool need_fill_metadata = false;

    for (size_t i = 0; i < selected_info_list.size(); ++i) {
      // Native file.
      if (!IsUnderNonNativeLocalPath(*context,
                                     selected_info_list[i].file_path)) {
        chooser_info_list_.push_back(
            FileChooserFileInfo::NewNativeFile(NativeFileInfo::New(
                selected_info_list[i].file_path,
                base::UTF8ToUTF16(selected_info_list[i].display_name),
                std::vector<std::u16string>())));
        continue;
      }

      // Non-native file, but it has a native snapshot file.
      if (!selected_info_list[i].local_path.empty()) {
        chooser_info_list_.push_back(
            FileChooserFileInfo::NewNativeFile(NativeFileInfo::New(
                selected_info_list[i].local_path,
                base::UTF8ToUTF16(selected_info_list[i].display_name),
                std::vector<std::u16string>())));
        continue;
      }

      // Non-native file without a snapshot file.
      base::FilePath virtual_path;
      if (!ash::FileSystemBackend::Get(*context)->GetVirtualPath(
              selected_info_list[i].file_path, &virtual_path)) {
        NotifyError(std::move(lifetime));
        return;
      }

      FileSystemURLAndHandle isolated_file_system_url_and_handle =
          CreateIsolatedURLFromVirtualPath(*context_, origin, virtual_path);
      const GURL url = isolated_file_system_url_and_handle.url.ToGURL();
      if (!url.is_valid()) {
        NotifyError(std::move(lifetime));
        return;
      }

      // Increase ref count of file system to keep it alive after |file_system|
      // goes out of scope. Our destructor will eventually revoke the file
      // system.
      storage::IsolatedContext::GetInstance()->AddReference(
          isolated_file_system_url_and_handle.handle.id());

      auto fs_info = FileSystemFileInfo::New();
      fs_info->url = url;
      chooser_info_list_.push_back(
          FileChooserFileInfo::NewFileSystem(std::move(fs_info)));
      need_fill_metadata = true;
    }

    // If the list includes at least one non-native file (wihtout a snapshot
    // file), move to IO thread to obtian metadata for the non-native file.
    if (need_fill_metadata) {
      content::GetIOThreadTaskRunner({})->PostTask(
          FROM_HERE,
          base::BindOnce(
              &ConvertSelectedFileInfoListToFileChooserFileInfoListImpl::
                  FillMetadataOnIOThread,
              base::Unretained(this), std::move(lifetime),
              chooser_info_list_.begin()));
      return;
    }

    NotifyComplete(std::move(lifetime));
  }

  ConvertSelectedFileInfoListToFileChooserFileInfoListImpl(
      const ConvertSelectedFileInfoListToFileChooserFileInfoListImpl&) = delete;
  ConvertSelectedFileInfoListToFileChooserFileInfoListImpl& operator=(
      const ConvertSelectedFileInfoListToFileChooserFileInfoListImpl&) = delete;

  ~ConvertSelectedFileInfoListToFileChooserFileInfoListImpl() {
    for (const auto& info : chooser_info_list_) {
      if (info && info->is_file_system()) {
        storage::IsolatedContext::GetInstance()->RevokeFileSystem(
            context_->CrackURLInFirstPartyContext(info->get_file_system()->url)
                .mount_filesystem_id());
      }
    }
  }

 private:
  // Obtains metadata for the non-native file |it|.
  void FillMetadataOnIOThread(Lifetime lifetime,
                              const FileChooserFileInfoList::iterator& it) {
    DCHECK_CURRENTLY_ON(BrowserThread::IO);

    if (it == chooser_info_list_.end()) {
      content::GetUIThreadTaskRunner({})->PostTask(
          FROM_HERE,
          base::BindOnce(
              &ConvertSelectedFileInfoListToFileChooserFileInfoListImpl::
                  NotifyComplete,
              base::Unretained(this), std::move(lifetime)));
      return;
    }

    if ((*it)->is_native_file()) {
      FillMetadataOnIOThread(std::move(lifetime), it + 1);
      return;
    }

    context_->operation_runner()->GetMetadata(
        context_->CrackURLInFirstPartyContext((*it)->get_file_system()->url),
        {storage::FileSystemOperation::GetMetadataField::kIsDirectory,
         storage::FileSystemOperation::GetMetadataField::kSize,
         storage::FileSystemOperation::GetMetadataField::kLastModified},
        base::BindOnce(
            &ConvertSelectedFileInfoListToFileChooserFileInfoListImpl::
                OnGotMetadataOnIOThread,
            base::Unretained(this), std::move(lifetime), it));
  }

  // Callback invoked after GetMetadata.
  void OnGotMetadataOnIOThread(Lifetime lifetime,
                               const FileChooserFileInfoList::iterator& it,
                               base::File::Error result,
                               const base::File::Info& file_info) {
    DCHECK_CURRENTLY_ON(BrowserThread::IO);

    if (result != base::File::FILE_OK) {
      content::GetUIThreadTaskRunner({})->PostTask(
          FROM_HERE,
          base::BindOnce(
              &ConvertSelectedFileInfoListToFileChooserFileInfoListImpl::
                  NotifyError,
              base::Unretained(this), std::move(lifetime)));
      return;
    }

    (*it)->get_file_system()->length = file_info.size;
    (*it)->get_file_system()->modification_time = file_info.last_modified;
    DCHECK(!file_info.is_directory);
    FillMetadataOnIOThread(std::move(lifetime), it + 1);
  }

  // Returns a result to the |callback_|.
  void NotifyComplete(Lifetime /* lifetime */) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    // Move the list content so that the file systems are not revoked at the
    // destructor.
    std::move(callback_).Run(std::move(chooser_info_list_));
  }

  // Returns an empty list to the |callback_|.
  void NotifyError(Lifetime /* lifetime */) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    std::move(callback_).Run(FileChooserFileInfoList());
  }

  scoped_refptr<storage::FileSystemContext> context_;
  FileChooserFileInfoList chooser_info_list_;
  FileChooserFileInfoListCallback callback_;
};

void CheckIfDirectoryExistsOnIoThread(
    scoped_refptr<storage::FileSystemContext> file_system_context,
    const storage::FileSystemURL& internal_url,
    storage::FileSystemOperationRunner::StatusCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  file_system_context->operation_runner()->DirectoryExists(internal_url,
                                                           std::move(callback));
}

void GetMetadataForPathOnIoThread(
    scoped_refptr<storage::FileSystemContext> file_system_context,
    const storage::FileSystemURL& internal_url,
    storage::FileSystemOperationRunner::GetMetadataFieldSet fields,
    storage::FileSystemOperationRunner::GetMetadataCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  file_system_context->operation_runner()->GetMetadata(internal_url, fields,
                                                       std::move(callback));
}

// Helper struct used to store the current file url being checked when trying to
// find an unused filename.
struct GenerateUnusedFilenameState {
  scoped_refptr<storage::FileSystemContext> file_system_context;
  storage::FileSystemURL destination_folder;

  // The filename without the counter and extension.
  std::string prefix;

  // The number to check.
  int counter = 0;

  // The extension of the given filename, including the "." at the start.
  std::string extension;
};

// Helper callback function for GetUnusedFilename().
void GenerateUnusedFilenameOnGotMetadata(
    storage::FileSystemURL trial_url,
    GenerateUnusedFilenameState state,
    base::OnceCallback<void(base::FileErrorOr<storage::FileSystemURL>)>
        callback,
    base::File::Error error) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  if (error == base::File::FILE_ERROR_NOT_FOUND) {
    std::move(callback).Run(std::move(trial_url));
    return;
  } else if (error != base::File::FILE_OK &&
             error != base::File::FILE_ERROR_NOT_A_DIRECTORY) {
    std::move(callback).Run(base::unexpected(error));
    return;
  }

  // File at |trial_url| exists, so try the next number up.
  auto file_system_context = state.file_system_context;
  state.counter++;
  std::string filename =
      base::StringPrintf("%s (%d)%s", state.prefix.c_str(), state.counter,
                         state.extension.c_str());
  auto filesystem_url = file_system_context->CreateCrackedFileSystemURL(
      state.destination_folder.storage_key(),
      state.destination_folder.mount_type(),
      state.destination_folder.virtual_path().Append(
          base::FilePath::FromUTF8Unsafe(filename)));
  CheckIfDirectoryExistsOnIoThread(
      file_system_context, filesystem_url,
      base::BindOnce(&GenerateUnusedFilenameOnGotMetadata, filesystem_url,
                     std::move(state), std::move(callback)));
}

// If the file is on ODFS (OneDrive), trim leading and trailing spaces from the
// destination name because OneDrive will not allow this, even though Files app
// is fine with it.
base::FilePath TrimFilenameIfOnODFS(storage::FileSystemURL destination_folder,
                                    base::FilePath filename) {
  if (ash::cloud_upload::UrlIsOnODFS(destination_folder)) {
    std::string name = filename.AsUTF8Unsafe();
    base::TrimString(name, " ", &name);
    return base::FilePath(name);
  }

  return filename;
}

}  // namespace

EntryDefinition::EntryDefinition() = default;

EntryDefinition::EntryDefinition(const EntryDefinition& other) = default;

EntryDefinition::~EntryDefinition() = default;

const GURL GetFileManagerURL() {
  return GURL(ash::file_manager::kChromeUIFileManagerURL);
}

bool IsFileManagerURL(const GURL& source_url) {
  return GetFileManagerURL() == source_url.DeprecatedGetOriginAsURL();
}

storage::FileSystemContext* GetFileManagerFileSystemContext(
    content::BrowserContext* browser_context) {
  return GetFileSystemContextForSourceURL(browser_context, GetFileManagerURL());
}

storage::FileSystemContext* GetFileSystemContextForSourceURL(
    content::BrowserContext* browser_context,
    const GURL& source_url) {
  content::StoragePartition* const partition =
      content::HasWebUIScheme(source_url)
          ? browser_context->GetDefaultStoragePartition()
          : extensions::util::GetStoragePartitionForExtensionId(
                source_url.host(), browser_context);
  return partition->GetFileSystemContext();
}

storage::FileSystemContext* GetFileSystemContextForRenderFrameHost(
    content::BrowserContext* browser_context,
    content::RenderFrameHost* render_frame_host) {
  return render_frame_host->GetStoragePartition()->GetFileSystemContext();
}

bool ConvertAbsoluteFilePathToFileSystemUrl(
    content::BrowserContext* browser_context,
    const base::FilePath& absolute_path,
    const GURL& source_url,
    GURL* url) {
  base::FilePath relative_path;
  if (!ConvertAbsoluteFilePathToRelativeFileSystemPath(
          browser_context, source_url, absolute_path, &relative_path)) {
    return false;
  }
  *url = ConvertRelativeFilePathToFileSystemUrl(relative_path, source_url);
  return true;
}

bool ConvertAbsoluteFilePathToRelativeFileSystemPath(
    content::BrowserContext* browser_context,
    const GURL& source_url,
    const base::FilePath& absolute_path,
    base::FilePath* virtual_path) {
  auto* backend = ash::FileSystemBackend::Get(
      *GetFileSystemContextForSourceURL(browser_context, source_url));
  if (!backend) {
    return false;
  }

  // Find if this file path is managed by the external backend.
  if (!backend->GetVirtualPath(absolute_path, virtual_path)) {
    return false;
  }

  return true;
}

void ConvertFileDefinitionListToEntryDefinitionList(
    scoped_refptr<storage::FileSystemContext> file_system_context,
    const url::Origin& origin,
    const FileDefinitionList& file_definition_list,
    EntryDefinitionListCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // The converter object destroys itself.
  new FileDefinitionListConverter(file_system_context, origin,
                                  file_definition_list, std::move(callback));
}

void ConvertFileDefinitionToEntryDefinition(
    scoped_refptr<storage::FileSystemContext> file_system_context,
    const url::Origin& origin,
    const FileDefinition& file_definition,
    EntryDefinitionCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  FileDefinitionList file_definition_list;
  file_definition_list.push_back(file_definition);
  ConvertFileDefinitionListToEntryDefinitionList(
      file_system_context, origin, file_definition_list,
      base::BindOnce(&OnConvertFileDefinitionDone, std::move(callback)));
}

void ConvertSelectedFileInfoListToFileChooserFileInfoList(
    storage::FileSystemContext* context,
    const url::Origin& origin,
    const SelectedFileInfoList& selected_info_list,
    FileChooserFileInfoListCallback callback) {
  // The object deletes itself.
  new ConvertSelectedFileInfoListToFileChooserFileInfoListImpl(
      context, origin, selected_info_list, std::move(callback));
}

base::Value::Dict ConvertEntryDefinitionToValue(
    const EntryDefinition& entry_definition) {
  base::Value::Dict entry;
  entry.Set("fileSystemName", entry_definition.file_system_name);
  entry.Set("fileSystemRoot", entry_definition.file_system_root_url);
  entry.Set(
      "fileFullPath",
      base::FilePath("/").Append(entry_definition.full_path).AsUTF8Unsafe());
  entry.Set("fileIsDirectory", entry_definition.is_directory);
  return entry;
}

base::Value::List ConvertEntryDefinitionListToListValue(
    const EntryDefinitionList& entry_definition_list) {
  base::Value::List entries;
  for (const auto& entry : entry_definition_list) {
    entries.Append(ConvertEntryDefinitionToValue(entry));
  }
  return entries;
}

void CheckIfDirectoryExists(
    scoped_refptr<storage::FileSystemContext> file_system_context,
    const base::FilePath& directory_path,
    storage::FileSystemOperationRunner::StatusCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  auto* const backend = ash::FileSystemBackend::Get(*file_system_context);
  DCHECK(backend);
  const storage::FileSystemURL internal_url =
      backend->CreateInternalURL(file_system_context.get(), directory_path);

  content::GetIOThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(&CheckIfDirectoryExistsOnIoThread, file_system_context,
                     internal_url,
                     google_apis::CreateRelayCallback(std::move(callback))));
}

void GetMetadataForPath(
    scoped_refptr<storage::FileSystemContext> file_system_context,
    const base::FilePath& entry_path,
    storage::FileSystemOperationRunner::GetMetadataFieldSet fields,
    storage::FileSystemOperationRunner::GetMetadataCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  auto* const backend = ash::FileSystemBackend::Get(*file_system_context);
  DCHECK(backend);
  const storage::FileSystemURL internal_url =
      backend->CreateInternalURL(file_system_context.get(), entry_path);

  content::GetIOThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(&GetMetadataForPathOnIoThread, file_system_context,
                     internal_url, fields,
                     google_apis::CreateRelayCallback(std::move(callback))));
}

FileSystemURLAndHandle CreateIsolatedURLFromVirtualPath(
    const storage::FileSystemContext& context,
    const url::Origin& origin,
    const base::FilePath& virtual_path) {
  const storage::FileSystemURL original_url =
      context.CreateCrackedFileSystemURL(
          blink::StorageKey::CreateFirstParty(origin),
          storage::kFileSystemTypeExternal, virtual_path);

  std::string register_name;
  storage::IsolatedContext::ScopedFSHandle file_system =
      storage::IsolatedContext::GetInstance()->RegisterFileSystemForPath(
          original_url.type(), original_url.filesystem_id(),
          original_url.path(), &register_name);
  storage::FileSystemURL isolated_url = context.CreateCrackedFileSystemURL(
      blink::StorageKey::CreateFirstParty(origin),
      storage::kFileSystemTypeIsolated,
      base::FilePath(file_system.id()).Append(register_name));
  return {isolated_url, file_system};
}

void GenerateUnusedFilename(
    storage::FileSystemURL destination_folder,
    base::FilePath filename,
    scoped_refptr<storage::FileSystemContext> file_system_context,
    base::OnceCallback<void(base::FileErrorOr<storage::FileSystemURL>)>
        callback) {
  if (filename.empty() || filename != filename.BaseName()) {
    std::move(callback).Run(
        base::unexpected(base::File::FILE_ERROR_INVALID_OPERATION));
    return;
  }

  base::FilePath trimmed_filename =
      TrimFilenameIfOnODFS(destination_folder, filename);

  auto trial_url = file_system_context->CreateCrackedFileSystemURL(
      destination_folder.storage_key(), destination_folder.mount_type(),
      destination_folder.virtual_path().Append(trimmed_filename));

  GenerateUnusedFilenameState state;
  state.destination_folder = std::move(destination_folder);
  state.file_system_context = file_system_context;
  state.extension = trimmed_filename.Extension();
  // Extracts the filename without extension or existing counter.
  // E.g. "foo (3).txt" -> "foo".
  RE2::Options options;
  options.set_dot_nl(true);  // Dot matches a new line.
  const RE2 re(R"((.*?)(?: \(\d+\))?)", options);
  const bool res = RE2::FullMatch(trimmed_filename.RemoveExtension().value(),
                                  re, &state.prefix);
  DCHECK(res) << " for '" << trimmed_filename << "'";

  auto get_metadata_callback = base::BindOnce(
      &GenerateUnusedFilenameOnGotMetadata, trial_url, std::move(state),
      google_apis::CreateRelayCallback(std::move(callback)));
  content::GetIOThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(&CheckIfDirectoryExistsOnIoThread, file_system_context,
                     std::move(trial_url), std::move(get_metadata_callback)));
}

}  // namespace util
}  // namespace file_manager
