// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ASH_FILE_MANAGER_FILE_MANAGER_TEST_UTIL_H_
#define CHROME_BROWSER_ASH_FILE_MANAGER_FILE_MANAGER_TEST_UTIL_H_
#include <vector>
#include "base/files/file_path.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/apps/app_service/app_service_proxy_ash.h"
#include "chrome/browser/ash/drive/drivefs_test_support.h"
#include "chrome/browser/ash/file_manager/file_tasks.h"
#include "chrome/browser/ash/file_system_provider/fake_extension_provider.h"
#include "chrome/browser/ash/file_system_provider/fake_provided_file_system.h"
#include "chrome/browser/ash/file_system_provider/provider_interface.h"
#include "chrome/browser/platform_util.h"
#include "chromeos/ash/components/drivefs/fake_drivefs.h"
class Profile;
namespace file_manager {
class Volume;
namespace test {
static const char kODFSSampleUrl[] = "https://1drv.ms/123";
static const char kSampleUserEmail1[] = "[email protected]";
static const char kSampleUserUpperCaseEmail1[] = "[email protected]";
static const char kSampleUserEmail2[] = "[email protected]";
// A dummy folder in a temporary path that is automatically mounted as a
// Profile's Downloads folder.
class FolderInMyFiles {
public:
explicit FolderInMyFiles(Profile* profile);
~FolderInMyFiles();
// Copies additional files into `folder_`, appending to `files_`.
void Add(const std::vector<base::FilePath>& files);
// Copies the contents of `file` to `folder_` with the given `new_base_name`.
void AddWithName(const base::FilePath& file,
const base::FilePath& new_base_name);
// Use platform_util::OpenItem() on the file with basename matching `path` to
// simulate a user request to open that path, e.g., from the Files app or
// chrome://downloads.
platform_util::OpenOperationResult Open(const base::FilePath& path);
// Refreshes `files_` by re-reading directory contents, sorting by name.
void Refresh();
const std::vector<base::FilePath> files() { return files_; }
private:
FolderInMyFiles(const FolderInMyFiles&) = delete;
FolderInMyFiles& operator=(const FolderInMyFiles&) = delete;
const raw_ptr<Profile, DanglingUntriaged> profile_;
base::FilePath folder_;
std::vector<base::FilePath> files_;
};
// Take test files from the chromeos/file_manager/ test directory and copy them
// into a temp folder mounted within MyFiles.
std::vector<storage::FileSystemURL> CopyTestFilesIntoMyFiles(
Profile* profile,
std::vector<std::string> file_names);
// Load the default set of component extensions used on ChromeOS. This should be
// done in an override of InProcessBrowserTest::SetUpOnMainThread().
void AddDefaultComponentExtensionsOnMainThread(Profile* profile);
// Installs the chrome app at the provided `test_path_ascii` under DIR_TEST_DATA
// and waits for the background page to start up.
scoped_refptr<const extensions::Extension> InstallTestingChromeApp(
Profile* profile,
const char* test_path_ascii);
// Uses InstallTestingChromeApp to install a test File System Provider chrome
// app that provides a file system containing readwrite.gif and readonly.png
// files, and wait for the file system to be mounted. Returns a
// base::WeakPtr<file_manager::Volume> to the mounted file system.
base::WeakPtr<file_manager::Volume> InstallFileSystemProviderChromeApp(
Profile* profile);
// Like above but uses the provided chrome app installation function
// `install_fn` instead of InstallTestingChromeApp. `install_fn` receives the
// chrome app's path (relative to DIR_TEST_DATA) as argument.
base::WeakPtr<file_manager::Volume> InstallFileSystemProviderChromeApp(
Profile* profile,
base::OnceCallback<void(const char*)> install_fn);
// Gets the list of available tasks for the provided `file`. Note only the path
// string is used for this helper, so it must have a well-known MIME type
// according to net::GetMimeTypeFromFile().
std::vector<file_tasks::FullTaskDescriptor> GetTasksForFile(
Profile* profile,
const base::FilePath& file);
// Add a fake web app with to the `app_service_proxy` with
// `intent_filters`.
void AddFakeAppWithIntentFilters(
const std::string& app_id,
std::vector<apps::IntentFilterPtr> intent_filters,
apps::AppType app_type,
std::optional<bool> handles_intents,
apps::AppServiceProxy* app_service_proxy);
// Add a fake web app with to the `app_service_proxy`.
void AddFakeWebApp(const std::string& app_id,
const std::string& mime_type,
const std::string& file_extension,
const std::string& activity_label,
std::optional<bool> handles_intents,
apps::AppServiceProxy* app_service_proxy);
// Fake DriveFs specific to the `DriveTest`. The alternate URL is the only piece
// of metadata stored for a file which is identified by its relative path.
class FakeSimpleDriveFs : public drivefs::FakeDriveFs {
public:
explicit FakeSimpleDriveFs(const base::FilePath& mount_path);
~FakeSimpleDriveFs() override;
// Sets the `alternate_urls_` entry for the given path.
void SetMetadata(const drivefs::FakeMetadata& metadata);
private:
// This is a simplified version of `FakeDriveFs::GetMetadata()` that returns a
// `metadata` with `alternate_url ` field set as the `alternate_urls_` entry
// for `path`. The other metadata fields are constructed with default values.
// If there is no `alternate_urls_` entry for `path`, return with
// `FILE_ERROR_NOT_FOUND`.
void GetMetadata(const base::FilePath& path,
GetMetadataCallback callback) override;
// Each file in this DriveFs has an entry.
std::unordered_map<base::FilePath, std::string> alternate_urls_;
};
// Fake DriveFs helper specific to the `DriveTest`. Implements the
// functions to create a `FakeSimpleDriveFs`.
class FakeSimpleDriveFsHelper : public drive::FakeDriveFsHelper {
public:
FakeSimpleDriveFsHelper(Profile* profile, const base::FilePath& mount_path);
base::RepeatingCallback<std::unique_ptr<drivefs::DriveFsBootstrapListener>()>
CreateFakeDriveFsListenerFactory();
const base::FilePath& mount_path() { return mount_path_; }
FakeSimpleDriveFs& fake_drivefs() { return fake_drivefs_; }
private:
const base::FilePath mount_path_;
FakeSimpleDriveFs fake_drivefs_;
};
// Fake provided file system implementation specific to mimic ODFS. Override
// `CreateFile` method to fail with a specific error, if set. Override
// `GetActions` method to return fake actions and to fail with a specific error
// for a non-root entry, if set.
class FakeProvidedFileSystemOneDrive
: public ash::file_system_provider::FakeProvidedFileSystem {
public:
explicit FakeProvidedFileSystemOneDrive(
const ash::file_system_provider::ProvidedFileSystemInfo&
file_system_info);
~FakeProvidedFileSystemOneDrive() override;
// Fail the create file request with `create_file_error_` if it exists.
// Otherwise, create a file as normal. Tests can run a callback on
// `CreateFile` via `SetCreateFileCallback()`.
ash::file_system_provider::AbortCallback CreateFile(
const base::FilePath& file_path,
storage::AsyncFileUtil::StatusCallback callback) override;
// Parallel what ODFS does but fail to get non-root entry metadata if
// `get_actions_error_` is set:
// - If the number of entries requested is not 1, fail.
// - If the root is requested, return (test) ODFS metadata.
// - If `get_actions_error_` is set, fail request with it.
// - If the entry is found, return (test) entry metadata.
// - Otherwise, fail.
ash::file_system_provider::AbortCallback GetActions(
const std::vector<base::FilePath>& entry_paths,
GetActionsCallback callback) override;
// Set error for the `CreateFile` to fail with.
void SetCreateFileError(base::File::Error error);
// Set a callback to be called when `CreateFile` is called.
void SetCreateFileCallback(base::OnceClosure callback);
// Set error for the `GetActions` to fail with when non-root entry actions are
// requested.
void SetGetActionsError(base::File::Error error);
// Set value for the `kReauthenticationRequiredId` ODFS metadata action.
void SetReauthenticationRequired(bool reauthentication_required);
private:
base::File::Error create_file_error_ = base::File::Error::FILE_OK;
base::File::Error get_actions_error_ = base::File::Error::FILE_OK;
bool reauthentication_required_ = false;
base::OnceClosure create_file_callback_;
};
// Fake extension provider to create a `FakeProvidedFileSystemOneDrive`.
class FakeExtensionProviderOneDrive
: public ash::file_system_provider::FakeExtensionProvider {
public:
static std::unique_ptr<ProviderInterface> Create(
const extensions::ExtensionId& extension_id);
std::unique_ptr<ash::file_system_provider::ProvidedFileSystemInterface>
CreateProvidedFileSystem(
Profile* profile,
const ash::file_system_provider::ProvidedFileSystemInfo& file_system_info,
ash::file_system_provider::CacheManager* cache_manager) override;
// Calls `request_mount_callback` if set.
bool RequestMount(
Profile* profile,
ash::file_system_provider::RequestMountCallback callback) override;
// `RequestMount()` will call this callback as its implementation.
void SetRequestMountImpl(
base::OnceCallback<
void(ash::file_system_provider::RequestMountCallback)>);
private:
FakeExtensionProviderOneDrive(
const extensions::ExtensionId& extension_id,
const ash::file_system_provider::Capabilities& capabilities);
~FakeExtensionProviderOneDrive() override;
base::OnceCallback<void(ash::file_system_provider::RequestMountCallback)>
request_mount_impl_;
};
// Mount a provider and return a `ProvidedFileSystemInterface`.
ash::file_system_provider::ProvidedFileSystemInterface* MountProvidedFileSystem(
Profile* profile,
const extensions::ExtensionId& extension_id,
ash::file_system_provider::MountOptions options,
std::unique_ptr<ash::file_system_provider::ProviderInterface> provider);
// Only call this after `MountProvidedFileSystem()`.
ash::file_system_provider::ProviderInterface* GetProvider(
Profile* profile,
const extensions::ExtensionId& extension_id);
// Mount a `FakeProvidedFileSystemOneDrive`.
FakeProvidedFileSystemOneDrive* MountFakeProvidedFileSystemOneDrive(
Profile* profile);
// Only call this after `MountFakeProvidedFileSystemOneDrive()`.
FakeExtensionProviderOneDrive* GetFakeProviderOneDrive(Profile* profile);
} // namespace test
} // namespace file_manager
#endif // CHROME_BROWSER_ASH_FILE_MANAGER_FILE_MANAGER_TEST_UTIL_H_