blob: f40a32dbeb1b0f560ff39ba6725714349f3b705b [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_SERVICES_STORAGE_PUBLIC_CPP_FILESYSTEM_FILESYSTEM_PROXY_H_
#define COMPONENTS_SERVICES_STORAGE_PUBLIC_CPP_FILESYSTEM_FILESYSTEM_PROXY_H_
#include <memory>
#include <optional>
#include <vector>
#include "base/component_export.h"
#include "base/files/file_error_or.h"
#include "base/files/file_path.h"
#include "base/memory/scoped_refptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/types/pass_key.h"
#include "components/services/storage/public/mojom/filesystem/directory.mojom.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/shared_remote.h"
namespace storage {
// A FilesystemProxy performs common filesystem operations on the caller's
// behalf, either directly (if the calling process environment permits) or via a
// remote storage.mojom.Directory implementation if one is provided.
//
// This class is thread-safe, but must only be called from threads that allow
// blocking operations.
class COMPONENT_EXPORT(STORAGE_SERVICE_FILESYSTEM_SUPPORT) FilesystemProxy {
public:
// Tags used to clarify the meaning of each constructor so that call sites can
// be more easily evaluated.
enum { UNRESTRICTED };
enum { RESTRICTED };
// Constructs a new FilesystemProxy which performs privileged, in-process
// file system operations. Not suitable for use within a restricted sandbox
// environment, as it may ultimately attempt to work that will be blocked by
// the sandbox boundary.
//
// If relative paths are given to methods on this object, they are interpreted
// relative to |root|. Objects constructed in this way can process paths
// outside of |root| and in general suffer no restrictions on what paths are
// allowed.
//
// If |root| is empty, relative paths are used as-is and effectively
// interpreted as relative to the current working directory.
explicit FilesystemProxy(decltype(UNRESTRICTED), const base::FilePath& root);
// Constructs a new FilesystemProxy for |root|, using |directory| to invoke
// privileged operations. Suitable for use within a sandboxed/ environment,
// assuming |directory| is connected to a remote implementation in a more
// privileged process.
//
// Objects constructed in this way can ONLY access contents within |root|;
// relative paths are interpreted as relative to |root|, and absolute paths
// must fall within |root|.
//
// |ipc_task_runner| is a task runner suitable for internally binding the
// Directory IPC endpoint; this is the task runner used to bind the internal
// SharedRemote, and so this is where all outgoing IPCs will hop before being
// transmitted. As such it must be a thread which is never blocked. Typically
// in a Content process environment, this should be the "IO thread".
FilesystemProxy(decltype(RESTRICTED),
const base::FilePath& root,
mojo::PendingRemote<mojom::Directory> directory,
scoped_refptr<base::SequencedTaskRunner> ipc_task_runner);
FilesystemProxy(const FilesystemProxy&) = delete;
FilesystemProxy& operator=(const FilesystemProxy&) = delete;
~FilesystemProxy();
// Returns true iff |path| refers to an existing file or directory.
bool PathExists(const base::FilePath& path);
// Enumerates all files and/or directories within |path|, a directory. Not
// recursive.
enum class DirectoryEntryType {
kFilesOnly,
kFilesAndDirectories,
};
base::FileErrorOr<std::vector<base::FilePath>> GetDirectoryEntries(
const base::FilePath& path,
DirectoryEntryType type);
// Opens a file at |path| with the given |flags|. If successful, the newly
// opened file is returned. |flags| may be any bitwise union of
// base::File::Flags values.
base::FileErrorOr<base::File> OpenFile(const base::FilePath& path, int flags);
// Creates a new directory at |path|. Any needed parent directories above
// |path| are also created if they don't already exist.
base::File::Error CreateDirectory(const base::FilePath& path);
// Deletes the file or directory at |path| if it exists and returns true iff
// successful. Not recursive. Will fail if there are subdirectories. This
// will return true if |path| does not exist.
bool DeleteFile(const base::FilePath& path);
// Retrieves information about a file or directory at |path|. Returns a valid
// base::File::Info value on success, or null on failure.
std::optional<base::File::Info> GetFileInfo(const base::FilePath& path);
// Retrieves information about access rights for a path in the filesystem.
// Returns a valid PathAccessInfo on success, or null on failure.
struct PathAccessInfo {
bool can_read = false;
bool can_write = false;
};
std::optional<PathAccessInfo> GetPathAccess(const base::FilePath& path);
// Renames a file from |old_path| to |new_path|. Must be atomic.
base::File::Error RenameFile(const base::FilePath& old_path,
const base::FilePath& new_path);
// Acquires an exclusive lock on the file at |path| if possible, returning a
// FileLock object to hold the lock if successful. The lock remains held as
// long as the returned FileLock object remains alive. Destroying the FileLock
// releases the lock.
class FileLock {
public:
virtual ~FileLock() = default;
// Explicitly releases the lock. This only has side effects the first time
// it's called, and once this is called, FileLock destruction also will be a
// no-op.
virtual base::File::Error Release() = 0;
};
// `same_process_failure`, if non-null, will be set to true iff acquiring the
// lock failed due to the lookup in `LockTable()`. TODO(crbug.com/340398745):
// remove this parameter.
base::FileErrorOr<std::unique_ptr<FileLock>> LockFile(
const base::FilePath& path,
bool* same_process_failure = nullptr);
private:
// For restricted FilesystemProxy instances, this returns a FilePath
// equivalent to |path| which is strictly relative to |root_|. It is an error
// to call with a |path| for which this is impossible.
//
// Not called by unrestricted FilesystemProxy instances.
base::FilePath MakeRelative(const base::FilePath& path) const;
// For unrestricted FilesystemProxy instances with a non-empty root, this
// returns a FilePath that is always absolute. If |path| is absolute, it is
// returned unmodified. If |path| is relative AND |root_| is non-empty, the
// path is resolved against |root_| and the resulting absolute path is
// returned. Finally, if |path| is relative and |root_| is empty, this returns
// |path| unmodified.
base::FilePath MaybeMakeAbsolute(const base::FilePath& path) const;
const base::FilePath root_;
// If |remote_directory_| is set this is a restricted proxy, otherwise
// it is unrestricted and will perform filesystem operations directly.
const mojo::SharedRemote<mojom::Directory> remote_directory_;
};
} // namespace storage
#endif // COMPONENTS_SERVICES_STORAGE_PUBLIC_CPP_FILESYSTEM_FILESYSTEM_PROXY_H_