#include "components/cronet/cronet_upload_data_stream.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
namespace cronet {
CronetUploadDataStream::CronetUploadDataStream(Delegate* delegate, int64_t size)
: UploadDataStream(size < 0, 0),
size_(size),
waiting_on_read_(false),
read_in_progress_(false),
waiting_on_rewind_(false),
rewind_in_progress_(false),
at_front_of_stream_(true),
delegate_(delegate) {}
CronetUploadDataStream::~CronetUploadDataStream() {
delegate_->OnUploadDataStreamDestroyed();
}
int CronetUploadDataStream::InitInternal(const net::NetLogWithSource& net_log) {
DCHECK(!waiting_on_read_);
DCHECK(!waiting_on_rewind_);
if (!weak_factory_.HasWeakPtrs())
delegate_->InitializeOnNetworkThread(weak_factory_.GetWeakPtr());
if (size_ >= 0)
SetSize(static_cast<uint64_t>(size_));
if (at_front_of_stream_) {
DCHECK(!read_in_progress_);
DCHECK(!rewind_in_progress_);
return net::OK;
}
waiting_on_rewind_ = true;
if (!read_in_progress_ && !rewind_in_progress_)
StartRewind();
return net::ERR_IO_PENDING;
}
int CronetUploadDataStream::ReadInternal(net::IOBuffer* buf, int buf_len) {
DCHECK(!waiting_on_read_);
DCHECK(!read_in_progress_);
DCHECK(!waiting_on_rewind_);
DCHECK(!rewind_in_progress_);
DCHECK(buf);
DCHECK_GT(buf_len, 0);
read_in_progress_ = true;
waiting_on_read_ = true;
at_front_of_stream_ = false;
scoped_refptr<net::IOBuffer> buffer(base::WrapRefCounted(buf));
delegate_->Read(std::move(buffer), buf_len);
return net::ERR_IO_PENDING;
}
void CronetUploadDataStream::ResetInternal() {
waiting_on_read_ = false;
waiting_on_rewind_ = false;
}
void CronetUploadDataStream::OnReadSuccess(int bytes_read, bool final_chunk) {
DCHECK(read_in_progress_);
DCHECK(!rewind_in_progress_);
DCHECK(bytes_read > 0 || (final_chunk && bytes_read == 0));
if (!is_chunked()) {
DCHECK(!final_chunk);
}
read_in_progress_ = false;
if (waiting_on_rewind_) {
DCHECK(!waiting_on_read_);
StartRewind();
return;
}
if (!waiting_on_read_)
return;
waiting_on_read_ = false;
if (final_chunk)
SetIsFinalChunk();
OnReadCompleted(bytes_read);
}
void CronetUploadDataStream::OnRewindSuccess() {
DCHECK(!waiting_on_read_);
DCHECK(!read_in_progress_);
DCHECK(rewind_in_progress_);
DCHECK(!at_front_of_stream_);
rewind_in_progress_ = false;
at_front_of_stream_ = true;
if (!waiting_on_rewind_)
return;
waiting_on_rewind_ = false;
OnInitCompleted(net::OK);
}
void CronetUploadDataStream::StartRewind() {
DCHECK(!waiting_on_read_);
DCHECK(!read_in_progress_);
DCHECK(waiting_on_rewind_);
DCHECK(!rewind_in_progress_);
DCHECK(!at_front_of_stream_);
rewind_in_progress_ = true;
delegate_->Rewind();
}
}