blob: 44f998fbf13ca43c99344f609ac87015d4dae1de [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cstdint>
#include <string>
#include <tuple>
#include "base/containers/flat_map.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "remoting/host/file_transfer/file_operations.h"
#include "remoting/protocol/file_transfer_helpers.h"
namespace remoting {
// Implementation of FileOperations that translates the interface into easy-to-
// serialize requests that can be forwarded over an IPC channel.
// IpcFileOperationsRequestHandlerImpl can be used on the remote end to
// perform the requested operations.
class IpcFileOperations : public FileOperations {
// Handles requests generated by IpcFileOperations instances by either
// performing the requested operations directly or forwarding them to another
// process.
class RequestHandler {
virtual ~RequestHandler() = default;
virtual void ReadFile(std::uint64_t file_id) = 0;
virtual void ReadChunk(std::uint64_t file_id, std::uint64_t size) = 0;
virtual void WriteFile(std::uint64_t file_id,
const base::FilePath& filename) = 0;
virtual void WriteChunk(std::uint64_t file_id, std::string data) = 0;
virtual void Close(std::uint64_t file_id) = 0;
virtual void Cancel(std::uint64_t file_id) = 0;
// Handles responses to file operations requests.
class ResultHandler {
using Result = protocol::FileTransferResult<Monostate>;
using InfoResult =
protocol::FileTransferResult<std::tuple<base::FilePath, uint64_t>>;
using DataResult = remoting::protocol::FileTransferResult<std::string>;
virtual ~ResultHandler() = default;
virtual void OnResult(std::uint64_t file_id, Result result) = 0;
virtual void OnInfoResult(std::uint64_t file_id, InfoResult result) = 0;
virtual void OnDataResult(std::uint64_t file_id, DataResult result) = 0;
~IpcFileOperations() override;
// FileOperations implementation.
std::unique_ptr<Reader> CreateReader() override;
std::unique_ptr<Writer> CreateWriter() override;
using ResultCallback = base::OnceCallback<void(ResultHandler::Result)>;
using InfoResultCallback =
using DataResultCallback =
class IpcReader;
class IpcWriter;
struct SharedState {
explicit SharedState(RequestHandler* request_handler);
// Send a Cancel request for |file_id| and provide an error response to any
// pending response callbacks for it. Called in the event of an unexpected
// message from the Desktop process.
void Abort(std::uint64_t file_id);
// File ID to use for the next file opened.
std::uint64_t next_file_id = 0;
// Pending callbacks awaiting responses from the desktop process, keyed by
// the file_id of the waiting Reader or Writer.
base::flat_map<std::uint64_t, ResultCallback> result_callbacks;
base::flat_map<std::uint64_t, InfoResultCallback> info_result_callbacks;
base::flat_map<std::uint64_t, DataResultCallback> data_result_callbacks;
// The associated RequestHandler.
RequestHandler* request_handler;
base::WeakPtrFactory<SharedState> weak_ptr_factory;
explicit IpcFileOperations(base::WeakPtr<SharedState> shared_state);
std::uint64_t GetNextFileId();
// Contains shared state used by all instances tied to a given
// RequestHandler.
base::WeakPtr<SharedState> shared_state_;
friend class IpcFileOperationsFactory;
// Creates IpcFileOperations instances for a given RequestHandler. All
// IpcFileOperations instances for the RequestHandler must be created through
// the same IpcFileOperationsFactory.
class IpcFileOperationsFactory : public IpcFileOperations::ResultHandler {
// |request_handler| must be valid for the entire lifetime of
// IpcFileOperationsFactory, and must only be used to construct a single
// IpcFileOperationsFactory to avoid file ID conflicts.
IpcFileOperationsFactory(IpcFileOperations::RequestHandler* request_handler);
~IpcFileOperationsFactory() override;
std::unique_ptr<FileOperations> CreateFileOperations();
// ResultHandler implementation.
void OnResult(std::uint64_t file_id, Result result) override;
void OnInfoResult(std::uint64_t file_id, InfoResult result) override;
void OnDataResult(std::uint64_t file_id, DataResult result) override;
IpcFileOperations::SharedState shared_state_;
} // namespace remoting