// 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_