123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- // 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 "remoting/host/file_transfer/session_file_operations_handler.h"
- #include <memory>
- #include "base/bind.h"
- #include "base/files/file_path.h"
- #include "base/memory/weak_ptr.h"
- #include "remoting/host/mojom/desktop_session.mojom.h"
- #include "remoting/protocol/file_transfer_helpers.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- namespace remoting {
- namespace {
- using BeginFileReadCallback =
- SessionFileOperationsHandler::BeginFileReadCallback;
- using BeginFileWriteCallback =
- SessionFileOperationsHandler::BeginFileWriteCallback;
- using Reader = FileOperations::Reader;
- using Writer = FileOperations::Writer;
- class MojoFileReader : public mojom::FileReader {
- public:
- explicit MojoFileReader(std::unique_ptr<Reader> file_reader);
- MojoFileReader(const MojoFileReader&) = delete;
- MojoFileReader& operator=(const MojoFileReader&) = delete;
- ~MojoFileReader() override = default;
- base::WeakPtr<MojoFileReader> GetWeakPtr();
- // Requests |file_reader_| to open an existing file for reading.
- void Open(Reader::OpenCallback callback);
- // Receives the result from Open() and returns it over the mojo channel.
- void OnFileOpened(BeginFileReadCallback callback,
- mojo::PendingAssociatedRemote<mojom::FileReader> remote,
- Reader::OpenResult result);
- // mojom::FileReader implementation.
- void ReadChunk(uint64_t bytes_to_read, ReadChunkCallback callback) override;
- const base::FilePath& filename() const { return file_reader_->filename(); }
- uint64_t size() const { return file_reader_->size(); }
- private:
- const std::unique_ptr<Reader> file_reader_;
- base::WeakPtrFactory<MojoFileReader> weak_ptr_factory{this};
- };
- class MojoFileWriter : public mojom::FileWriter {
- public:
- explicit MojoFileWriter(std::unique_ptr<Writer> file_writer);
- MojoFileWriter(const MojoFileWriter&) = delete;
- MojoFileWriter& operator=(const MojoFileWriter&) = delete;
- ~MojoFileWriter() override = default;
- // Requests |file_writer_| to open a new file for writing.
- void Open(const base::FilePath& filename, Writer::Callback callback);
- // Receives the result from Open() and returns it over the mojo channel.
- void OnFileOpened(BeginFileWriteCallback callback,
- mojo::PendingAssociatedRemote<mojom::FileWriter> remote,
- Writer::Result result);
- // mojom::FileWriter implementation.
- void WriteChunk(const std::vector<std::uint8_t>& data,
- WriteChunkCallback callback) override;
- void CloseFile(CloseFileCallback callback) override;
- base::WeakPtr<MojoFileWriter> GetWeakPtr();
- private:
- const std::unique_ptr<Writer> file_writer_;
- base::WeakPtrFactory<MojoFileWriter> weak_ptr_factory{this};
- };
- MojoFileReader::MojoFileReader(std::unique_ptr<Reader> file_reader)
- : file_reader_(std::move(file_reader)) {}
- base::WeakPtr<MojoFileReader> MojoFileReader::GetWeakPtr() {
- return weak_ptr_factory.GetWeakPtr();
- }
- void MojoFileReader::Open(Reader::OpenCallback callback) {
- file_reader_->Open(std::move(callback));
- }
- void MojoFileReader::OnFileOpened(
- BeginFileReadCallback callback,
- mojo::PendingAssociatedRemote<mojom::FileReader> remote,
- Reader::OpenResult result) {
- if (result.is_error()) {
- std::move(callback).Run(
- mojom::BeginFileReadResult::NewError(result.error()));
- // This will asynchronously trigger the destruction of this object.
- remote.reset();
- return;
- }
- std::move(callback).Run(mojom::BeginFileReadResult::NewSuccess(
- mojom::BeginFileReadSuccess::New(std::move(remote), filename(), size())));
- }
- // The Mojo-generated ReadChunkCallback has a const& param whereas the
- // FileReader::ReadCallback does not so this function wraps the Mojo callback
- // so it is compatible with the FileReader interface.
- void ReadChunkCallbackWrapper(
- mojom::FileReader::ReadChunkCallback callback,
- protocol::FileTransferResult<std::vector<std::uint8_t>> result) {
- std::move(callback).Run(result);
- }
- void MojoFileReader::ReadChunk(uint64_t bytes_to_read,
- ReadChunkCallback callback) {
- file_reader_->ReadChunk(
- bytes_to_read,
- base::BindOnce(&ReadChunkCallbackWrapper, std::move(callback)));
- }
- MojoFileWriter::MojoFileWriter(std::unique_ptr<Writer> file_writer)
- : file_writer_(std::move(file_writer)) {}
- void MojoFileWriter::Open(const base::FilePath& filename,
- Writer::Callback callback) {
- file_writer_->Open(filename, std::move(callback));
- }
- void MojoFileWriter::OnFileOpened(
- BeginFileWriteCallback callback,
- mojo::PendingAssociatedRemote<mojom::FileWriter> remote,
- Writer::Result result) {
- if (result.is_error()) {
- std::move(callback).Run(
- mojom::BeginFileWriteResult::NewError(result.error()));
- // This will asynchronously trigger the destruction of this object.
- remote.reset();
- return;
- }
- std::move(callback).Run(mojom::BeginFileWriteResult::NewSuccess(
- mojom::BeginFileWriteSuccess::New(std::move(remote))));
- }
- base::WeakPtr<MojoFileWriter> MojoFileWriter::GetWeakPtr() {
- return weak_ptr_factory.GetWeakPtr();
- }
- // Wraps a Mojo-generated callback to provide compatibility with the FileWriter
- // methods which expect a Writer::Callback.
- template <class T>
- void FileWriterCallbackWrapper(T callback, remoting::Writer::Result result) {
- absl::optional<protocol::FileTransfer_Error> error;
- if (result.is_error()) {
- error = std::move(result.error());
- }
- std::move(callback).Run(std::move(error));
- }
- void MojoFileWriter::WriteChunk(const std::vector<std::uint8_t>& data,
- WriteChunkCallback callback) {
- file_writer_->WriteChunk(
- std::move(data),
- base::BindOnce(&FileWriterCallbackWrapper<WriteChunkCallback>,
- std::move(callback)));
- }
- void MojoFileWriter::CloseFile(CloseFileCallback callback) {
- file_writer_->Close(base::BindOnce(
- &FileWriterCallbackWrapper<CloseFileCallback>, std::move(callback)));
- }
- } // namespace
- SessionFileOperationsHandler::SessionFileOperationsHandler(
- std::unique_ptr<FileOperations> file_operations)
- : file_operations_(std::move(file_operations)) {}
- SessionFileOperationsHandler::~SessionFileOperationsHandler() = default;
- void SessionFileOperationsHandler::BeginFileRead(
- BeginFileReadCallback callback) {
- mojo::AssociatedRemote<mojom::FileReader> remote;
- auto mojo_file_reader =
- std::make_unique<MojoFileReader>(file_operations_->CreateReader());
- MojoFileReader* ptr = mojo_file_reader.get();
- // |file_readers_| now manages the lifetime of |mojo_file_reader| and will
- // destroy the instance when |remote| is reset.
- file_readers_.Add(std::move(mojo_file_reader),
- remote.BindNewEndpointAndPassReceiver());
- // We Unbind() |remote| so we can return it to the other end of the IPC
- // channel, this will not cause |mojo_file_reader| to be destroyed.
- ptr->Open(base::BindOnce(&MojoFileReader::OnFileOpened, ptr->GetWeakPtr(),
- std::move(callback), remote.Unbind()));
- }
- void SessionFileOperationsHandler::BeginFileWrite(
- const base::FilePath& file_path,
- BeginFileWriteCallback callback) {
- mojo::AssociatedRemote<mojom::FileWriter> remote;
- auto mojo_file_writer =
- std::make_unique<MojoFileWriter>(file_operations_->CreateWriter());
- MojoFileWriter* ptr = mojo_file_writer.get();
- // |file_writers_| now manages the lifetime of |mojo_file_writer| and will
- // destroy the instance when |remote| is reset.
- file_writers_.Add(std::move(mojo_file_writer),
- remote.BindNewEndpointAndPassReceiver());
- // We Unbind() |remote| so we can return it to the other end of the IPC
- // channel, this will not cause |mojo_file_writer| to be destroyed.
- ptr->Open(file_path,
- base::BindOnce(&MojoFileWriter::OnFileOpened, ptr->GetWeakPtr(),
- std::move(callback), remote.Unbind()));
- }
- } // namespace remoting
|