// Copyright 2017 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. #ifndef MOJO_PUBLIC_CPP_SYSTEM_FILE_DATA_PIPE_PRODUCER_H_ #define MOJO_PUBLIC_CPP_SYSTEM_FILE_DATA_PIPE_PRODUCER_H_ #include <memory> #include "base/callback_forward.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "mojo/public/cpp/system/data_pipe.h" #include "mojo/public/cpp/system/system_export.h" namespace mojo { // Helper class which takes ownership of a ScopedDataPipeProducerHandle and // assumes responsibility for feeding it the contents of a given file. This // takes care of waiting for pipe capacity as needed, and can notify callers // asynchronously when the operation is complete. // // Note that the FileDataPipeProducer must be kept alive until notified of // completion to ensure that all of the intended contents are written to the // pipe. Premature destruction may result in partial or total truncation of data // made available to the consumer. class MOJO_CPP_SYSTEM_EXPORT FileDataPipeProducer { public: using CompletionCallback = base::OnceCallback<void(MojoResult result)>; // Interface definition of an optional object that may be supplied to the // FileDataPipeProducer so that the data being read from the consumer can be // observed. class Observer { public: virtual ~Observer() {} // Called once per read attempt. |data| contains the read data (if any). // |num_bytes_read| is the number of read bytes, 0 indicates EOF. Both // parameters may only be used when |read_result| is base::File::FILE_OK. // Can be called on any sequence. virtual void OnBytesRead(const void* data, size_t num_bytes_read, base::File::Error read_result) = 0; // Called when the FileDataPipeProducer has finished reading all data. Will // be called even if there was an error opening the file or reading the // data. Can be called on any sequence. virtual void OnDoneReading() = 0; }; // Constructs a new FileDataPipeProducer which will write data to |producer|. // Caller may supply an optional |observer| if observation of the read file // data is desired. FileDataPipeProducer(ScopedDataPipeProducerHandle producer, std::unique_ptr<Observer> observer); ~FileDataPipeProducer(); // Attempts to eventually write all of |file|'s contents to the pipe. Invokes // |callback| asynchronously when done. Note that |callback| IS allowed to // delete this FileDataPipeProducer. // // If the write is successful |result| will be |MOJO_RESULT_OK|. Otherwise // (e.g. if the producer detects the consumer is closed and the pipe has no // remaining capacity, or if file open/reads fail for any reason) |result| // will be one of the following: // // |MOJO_RESULT_ABORTED| // |MOJO_RESULT_NOT_FOUND| // |MOJO_RESULT_PERMISSION_DENIED| // |MOJO_RESULT_RESOURCE_EXHAUSTED| // |MOJO_RESULT_UNKNOWN| // // Note that if the FileDataPipeProducer is destroyed before |callback| can be // invoked, |callback| is *never* invoked, and the write will be permanently // interrupted (and the producer handle closed) after making potentially only // partial progress. // // Multiple writes may be performed in sequence (each one after the last // completes), but Write() must not be called before the |callback| for the // previous call to Write() (if any) has returned. void WriteFromFile(base::File file, CompletionCallback callback); // Like above, but writes at most |max_bytes| bytes from the file to the pipe. void WriteFromFile(base::File file, size_t max_bytes, CompletionCallback callback); // Same as above but takes a FilePath instead of an opened File. Opens the // file on an appropriate sequence and then proceeds as WriteFromFile() would. void WriteFromPath(const base::FilePath& path, CompletionCallback callback); private: class FileSequenceState; void InitializeNewRequest(CompletionCallback callback); void OnWriteComplete(CompletionCallback callback, ScopedDataPipeProducerHandle producer, MojoResult result); ScopedDataPipeProducerHandle producer_; scoped_refptr<FileSequenceState> file_sequence_state_; std::unique_ptr<Observer> observer_; base::WeakPtrFactory<FileDataPipeProducer> weak_factory_; DISALLOW_COPY_AND_ASSIGN(FileDataPipeProducer); }; } // namespace mojo #endif // MOJO_PUBLIC_CPP_SYSTEM_FILE_DATA_PIPE_PRODUCER_H_