session_file_operations_handler.cc 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "remoting/host/file_transfer/session_file_operations_handler.h"
  5. #include <memory>
  6. #include "base/bind.h"
  7. #include "base/files/file_path.h"
  8. #include "base/memory/weak_ptr.h"
  9. #include "remoting/host/mojom/desktop_session.mojom.h"
  10. #include "remoting/protocol/file_transfer_helpers.h"
  11. #include "third_party/abseil-cpp/absl/types/optional.h"
  12. namespace remoting {
  13. namespace {
  14. using BeginFileReadCallback =
  15. SessionFileOperationsHandler::BeginFileReadCallback;
  16. using BeginFileWriteCallback =
  17. SessionFileOperationsHandler::BeginFileWriteCallback;
  18. using Reader = FileOperations::Reader;
  19. using Writer = FileOperations::Writer;
  20. class MojoFileReader : public mojom::FileReader {
  21. public:
  22. explicit MojoFileReader(std::unique_ptr<Reader> file_reader);
  23. MojoFileReader(const MojoFileReader&) = delete;
  24. MojoFileReader& operator=(const MojoFileReader&) = delete;
  25. ~MojoFileReader() override = default;
  26. base::WeakPtr<MojoFileReader> GetWeakPtr();
  27. // Requests |file_reader_| to open an existing file for reading.
  28. void Open(Reader::OpenCallback callback);
  29. // Receives the result from Open() and returns it over the mojo channel.
  30. void OnFileOpened(BeginFileReadCallback callback,
  31. mojo::PendingAssociatedRemote<mojom::FileReader> remote,
  32. Reader::OpenResult result);
  33. // mojom::FileReader implementation.
  34. void ReadChunk(uint64_t bytes_to_read, ReadChunkCallback callback) override;
  35. const base::FilePath& filename() const { return file_reader_->filename(); }
  36. uint64_t size() const { return file_reader_->size(); }
  37. private:
  38. const std::unique_ptr<Reader> file_reader_;
  39. base::WeakPtrFactory<MojoFileReader> weak_ptr_factory{this};
  40. };
  41. class MojoFileWriter : public mojom::FileWriter {
  42. public:
  43. explicit MojoFileWriter(std::unique_ptr<Writer> file_writer);
  44. MojoFileWriter(const MojoFileWriter&) = delete;
  45. MojoFileWriter& operator=(const MojoFileWriter&) = delete;
  46. ~MojoFileWriter() override = default;
  47. // Requests |file_writer_| to open a new file for writing.
  48. void Open(const base::FilePath& filename, Writer::Callback callback);
  49. // Receives the result from Open() and returns it over the mojo channel.
  50. void OnFileOpened(BeginFileWriteCallback callback,
  51. mojo::PendingAssociatedRemote<mojom::FileWriter> remote,
  52. Writer::Result result);
  53. // mojom::FileWriter implementation.
  54. void WriteChunk(const std::vector<std::uint8_t>& data,
  55. WriteChunkCallback callback) override;
  56. void CloseFile(CloseFileCallback callback) override;
  57. base::WeakPtr<MojoFileWriter> GetWeakPtr();
  58. private:
  59. const std::unique_ptr<Writer> file_writer_;
  60. base::WeakPtrFactory<MojoFileWriter> weak_ptr_factory{this};
  61. };
  62. MojoFileReader::MojoFileReader(std::unique_ptr<Reader> file_reader)
  63. : file_reader_(std::move(file_reader)) {}
  64. base::WeakPtr<MojoFileReader> MojoFileReader::GetWeakPtr() {
  65. return weak_ptr_factory.GetWeakPtr();
  66. }
  67. void MojoFileReader::Open(Reader::OpenCallback callback) {
  68. file_reader_->Open(std::move(callback));
  69. }
  70. void MojoFileReader::OnFileOpened(
  71. BeginFileReadCallback callback,
  72. mojo::PendingAssociatedRemote<mojom::FileReader> remote,
  73. Reader::OpenResult result) {
  74. if (result.is_error()) {
  75. std::move(callback).Run(
  76. mojom::BeginFileReadResult::NewError(result.error()));
  77. // This will asynchronously trigger the destruction of this object.
  78. remote.reset();
  79. return;
  80. }
  81. std::move(callback).Run(mojom::BeginFileReadResult::NewSuccess(
  82. mojom::BeginFileReadSuccess::New(std::move(remote), filename(), size())));
  83. }
  84. // The Mojo-generated ReadChunkCallback has a const& param whereas the
  85. // FileReader::ReadCallback does not so this function wraps the Mojo callback
  86. // so it is compatible with the FileReader interface.
  87. void ReadChunkCallbackWrapper(
  88. mojom::FileReader::ReadChunkCallback callback,
  89. protocol::FileTransferResult<std::vector<std::uint8_t>> result) {
  90. std::move(callback).Run(result);
  91. }
  92. void MojoFileReader::ReadChunk(uint64_t bytes_to_read,
  93. ReadChunkCallback callback) {
  94. file_reader_->ReadChunk(
  95. bytes_to_read,
  96. base::BindOnce(&ReadChunkCallbackWrapper, std::move(callback)));
  97. }
  98. MojoFileWriter::MojoFileWriter(std::unique_ptr<Writer> file_writer)
  99. : file_writer_(std::move(file_writer)) {}
  100. void MojoFileWriter::Open(const base::FilePath& filename,
  101. Writer::Callback callback) {
  102. file_writer_->Open(filename, std::move(callback));
  103. }
  104. void MojoFileWriter::OnFileOpened(
  105. BeginFileWriteCallback callback,
  106. mojo::PendingAssociatedRemote<mojom::FileWriter> remote,
  107. Writer::Result result) {
  108. if (result.is_error()) {
  109. std::move(callback).Run(
  110. mojom::BeginFileWriteResult::NewError(result.error()));
  111. // This will asynchronously trigger the destruction of this object.
  112. remote.reset();
  113. return;
  114. }
  115. std::move(callback).Run(mojom::BeginFileWriteResult::NewSuccess(
  116. mojom::BeginFileWriteSuccess::New(std::move(remote))));
  117. }
  118. base::WeakPtr<MojoFileWriter> MojoFileWriter::GetWeakPtr() {
  119. return weak_ptr_factory.GetWeakPtr();
  120. }
  121. // Wraps a Mojo-generated callback to provide compatibility with the FileWriter
  122. // methods which expect a Writer::Callback.
  123. template <class T>
  124. void FileWriterCallbackWrapper(T callback, remoting::Writer::Result result) {
  125. absl::optional<protocol::FileTransfer_Error> error;
  126. if (result.is_error()) {
  127. error = std::move(result.error());
  128. }
  129. std::move(callback).Run(std::move(error));
  130. }
  131. void MojoFileWriter::WriteChunk(const std::vector<std::uint8_t>& data,
  132. WriteChunkCallback callback) {
  133. file_writer_->WriteChunk(
  134. std::move(data),
  135. base::BindOnce(&FileWriterCallbackWrapper<WriteChunkCallback>,
  136. std::move(callback)));
  137. }
  138. void MojoFileWriter::CloseFile(CloseFileCallback callback) {
  139. file_writer_->Close(base::BindOnce(
  140. &FileWriterCallbackWrapper<CloseFileCallback>, std::move(callback)));
  141. }
  142. } // namespace
  143. SessionFileOperationsHandler::SessionFileOperationsHandler(
  144. std::unique_ptr<FileOperations> file_operations)
  145. : file_operations_(std::move(file_operations)) {}
  146. SessionFileOperationsHandler::~SessionFileOperationsHandler() = default;
  147. void SessionFileOperationsHandler::BeginFileRead(
  148. BeginFileReadCallback callback) {
  149. mojo::AssociatedRemote<mojom::FileReader> remote;
  150. auto mojo_file_reader =
  151. std::make_unique<MojoFileReader>(file_operations_->CreateReader());
  152. MojoFileReader* ptr = mojo_file_reader.get();
  153. // |file_readers_| now manages the lifetime of |mojo_file_reader| and will
  154. // destroy the instance when |remote| is reset.
  155. file_readers_.Add(std::move(mojo_file_reader),
  156. remote.BindNewEndpointAndPassReceiver());
  157. // We Unbind() |remote| so we can return it to the other end of the IPC
  158. // channel, this will not cause |mojo_file_reader| to be destroyed.
  159. ptr->Open(base::BindOnce(&MojoFileReader::OnFileOpened, ptr->GetWeakPtr(),
  160. std::move(callback), remote.Unbind()));
  161. }
  162. void SessionFileOperationsHandler::BeginFileWrite(
  163. const base::FilePath& file_path,
  164. BeginFileWriteCallback callback) {
  165. mojo::AssociatedRemote<mojom::FileWriter> remote;
  166. auto mojo_file_writer =
  167. std::make_unique<MojoFileWriter>(file_operations_->CreateWriter());
  168. MojoFileWriter* ptr = mojo_file_writer.get();
  169. // |file_writers_| now manages the lifetime of |mojo_file_writer| and will
  170. // destroy the instance when |remote| is reset.
  171. file_writers_.Add(std::move(mojo_file_writer),
  172. remote.BindNewEndpointAndPassReceiver());
  173. // We Unbind() |remote| so we can return it to the other end of the IPC
  174. // channel, this will not cause |mojo_file_writer| to be destroyed.
  175. ptr->Open(file_path,
  176. base::BindOnce(&MojoFileWriter::OnFileOpened, ptr->GetWeakPtr(),
  177. std::move(callback), remote.Unbind()));
  178. }
  179. } // namespace remoting