blob: b108c6330d2b23362d2b75b7b9570b086bc0dd4c [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_NETWORK_PUBLIC_CPP_TRANSFERABLE_DIRECTORY_H_
#define SERVICES_NETWORK_PUBLIC_CPP_TRANSFERABLE_DIRECTORY_H_
#include "base/component_export.h"
#include "base/files/file_path.h"
#include "base/functional/callback_helpers.h"
#include "mojo/public/cpp/bindings/union_traits.h"
#include "mojo/public/cpp/platform/platform_handle.h"
namespace network {
class TransferableDirectory;
}
namespace network::mojom {
class TransferableDirectoryDataView;
}
namespace mojo {
template <>
struct UnionTraits<network::mojom::TransferableDirectoryDataView,
network::TransferableDirectory>;
}
namespace network {
// Represents a directory that, on some platforms, can be sent as a handle
// across process boundaries to be later mounted to a process-local path.
//
// Platforms which use the same filesystem across process boundaries can simply
// use the path as-is, with no handle marshaling steps required.
//
// Example usage:
// SENDER:
// TransferableDirectory dir = base::FilePath("/dir/to/share");
// if (dir.IsOpenForTransferRequired())
// dir.OpenForTransfer();
// mojo_client->UseDirectory(std::move(dir));
//
// RECEIVER:
// AutoClosureRunner dismounter;
// if (dir.NeedsMount())
// dismounter = AutoClosureRunner(dir.Mount());
//
// base::File file(dir.path().Append("shared_file.txt"));
// ...use |file| normally...
class COMPONENT_EXPORT(NETWORK_CPP_BASE) TransferableDirectory {
public:
TransferableDirectory();
explicit TransferableDirectory(const base::FilePath& path);
TransferableDirectory(TransferableDirectory&& other);
~TransferableDirectory();
void operator=(TransferableDirectory&& other);
void operator=(const base::FilePath& path);
const base::FilePath& path() const;
void ClearPath();
static bool IsOpenForTransferRequired();
// Gets a directory handle for |path_| to be sent over Mojo.
// Call may block, so should be called on an IO thread.
// Should be prefaced with a check against IsOpenForTransferRequired().
void OpenForTransfer();
// Returns true if |this| contains a handle that needs to be mounted before
// the path can be accessed.
bool NeedsMount() const;
// Mounts |handle_| to a location on the filesystem.
// Should be prefaced with a check against NeedsMount().
// Returns a task that, when run, will dismount the directory.
// The task should not be run while I/O is occurring to the directory from
// any thread.
// Deleting the task should not unmount the directory, so that during
// shutdown the unmounting can be skipped with no adverse effects.
[[nodiscard]] base::OnceClosure Mount();
private:
friend struct mojo::UnionTraits<network::mojom::TransferableDirectoryDataView,
network::TransferableDirectory>;
// Handle manipulation calls, hidden from callers and only surfaced to
// UnionTraits.
explicit TransferableDirectory(mojo::PlatformHandle handle);
bool HasValidHandle() const { return handle_.is_valid(); }
mojo::PlatformHandle TakeHandle();
// The path to the source directory for the producer, or the mounted location
// for the consumer. Initially empty on the consumer unitil Mount() is
// called.
base::FilePath path_;
// Contains a handle to the directory, populated by calling OpenForTransfer()
// just prior to sending over Mojo. On the directory consumer, calling
// Mount() will mount |handle_| at |path_|, and |handle_| will be cleared.
mojo::PlatformHandle handle_;
};
} // namespace network
#endif // SERVICES_NETWORK_PUBLIC_CPP_TRANSFERABLE_DIRECTORY_H_